From fc4fcbab58d00651f7c3f21bb68c3a550bd2dba8 Mon Sep 17 00:00:00 2001 From: wehub-resource-sync Date: Mon, 13 Jul 2026 12:22:33 +0800 Subject: [PATCH] chore: import upstream snapshot with attribution --- .agents/skills/codexbar/SKILL.md | 38 + .agents/skills/codexbar/scripts/codexbar | 321 + .../skills/codexbar/scripts/test_codexbar.py | 231 + .agents/skills/qa-test/SKILL.md | 118 + .agents/skills/qa-test/agents/openai.yaml | 4 + .../skills/qa-test/references/api-specs.md | 10 + .../qa-test/scripts/live_provider_matrix.sh | 183 + .agents/skills/release-codexbar/SKILL.md | 141 + .github/workflows/ci.yml | 320 + .github/workflows/release-cli.yml | 497 ++ .github/workflows/upstream-monitor.yml | 188 + .gitignore | 47 + .swiftformat | 51 + .swiftlint.yml | 160 + .../contents.xcworkspacedata | 7 + AGENTS.md | 48 + CHANGELOG.md | 1622 +++++ Icon.icns | Bin 0 -> 1315598 bytes Icon.icon/Assets/codexbar.png | Bin 0 -> 674979 bytes Icon.icon/icon.json | 36 + LICENSE | 21 + Makefile | 43 + Package.resolved | 77 + Package.swift | 201 + README.md | 254 + README.wehub.md | 7 + Scripts/analyze_quotio.sh | 166 + Scripts/build-site-css.sh | 11 + Scripts/build_icon.sh | 49 + Scripts/changelog-to-html.sh | 4 + Scripts/check-app-locales.mjs | 199 + Scripts/check-documentation-links.mjs | 241 + Scripts/check-release-assets.sh | 4 + Scripts/check-site-locales.mjs | 129 + Scripts/check_repository_size.sh | 58 + Scripts/check_upstreams.sh | 118 + Scripts/ci_macos_test_gate.sh | 105 + Scripts/ci_swift_test_by_suite.py | 341 + Scripts/ci_verify_test_jobs.sh | 32 + Scripts/compile_and_run.sh | 326 + Scripts/cost_jsonl_shape_survey.swift | 289 + Scripts/docs-list.mjs | 119 + Scripts/generate-llms.mjs | 99 + Scripts/install_lint_tools.sh | 189 + Scripts/launch.sh | 32 + Scripts/lint.sh | 133 + Scripts/mac-release | 24 + Scripts/make_appcast.sh | 4 + Scripts/mimo-usage.py | 241 + Scripts/package_app.sh | 541 ++ Scripts/package_product_paths.sh | 72 + Scripts/prepare_upstream_pr.sh | 77 + Scripts/regenerate-codex-parser-hash.sh | 83 + Scripts/release.sh | 4 + Scripts/release_artifacts.sh | 44 + Scripts/release_dsym_paths.sh | 75 + Scripts/review_upstream.sh | 137 + Scripts/setup_dev_signing.sh | 80 + Scripts/sign-and-notarize.sh | 137 + Scripts/site-tailwind.input.css | 3 + Scripts/sparkle_signing_paths.sh | 137 + Scripts/tailwind.site.config.cjs | 14 + Scripts/test.sh | 39 + Scripts/test_ci_path_gate.sh | 119 + Scripts/test_live_update.sh | 54 + Scripts/test_package_product_paths.sh | 91 + Scripts/test_package_signing.sh | 39 + Scripts/test_package_strip.sh | 45 + Scripts/test_release_dsym_paths.sh | 108 + Scripts/test_repository_size.sh | 82 + Scripts/test_sparkle_signing_paths.sh | 129 + Scripts/test_swift_test_sharding.sh | 238 + Scripts/validate_changelog.sh | 23 + Scripts/verify_1844_live.sh | 262 + Scripts/verify_appcast.sh | 4 + .../AdaptiveRefreshPolicyCore.swift | 87 + Sources/AdaptiveReplayCLI/CLIArguments.swift | 98 + Sources/AdaptiveReplayCLI/main.swift | 217 + .../ActivityCoverageStats.swift | 50 + .../AdaptiveRefreshTrace.swift | 201 + .../AdaptiveRefreshTraceParser.swift | 85 + .../AdaptiveReplayKit/BaselinePolicies.swift | 57 + .../AdaptiveReplayKit/CandidatePolicies.swift | 27 + Sources/AdaptiveReplayKit/README.md | 39 + .../RecordedScheduleAudit.swift | 153 + Sources/AdaptiveReplayKit/ReplayEngine.swift | 303 + Sources/AdaptiveReplayKit/ReplayMetrics.swift | 108 + Sources/AdaptiveReplayKit/ReplayPolicy.swift | 90 + .../ReplayTraceSegmentation.swift | 123 + Sources/CSQLite3/module.modulemap | 5 + Sources/CSQLite3/shim.h | 1 + Sources/CodexBar/About.swift | 84 + Sources/CodexBar/AdaptiveRefreshPolicy.swift | 35 + Sources/CodexBar/AgentSessionsStore.swift | 154 + Sources/CodexBar/AppNotifications.swift | 115 + Sources/CodexBar/ChartBarHoverSelection.swift | 11 + Sources/CodexBar/ClaudeLoginRunner.swift | 123 + Sources/CodexBar/ClickToCopyOverlay.swift | 77 + .../CodexAccountMenuPresentation.swift | 180 + .../CodexAccountPromotionCoordinator.swift | 114 + .../CodexAccountPromotionExecution.swift | 277 + .../CodexAccountPromotionPlanning.swift | 190 + .../CodexAccountPromotionPreparation.swift | 346 + .../CodexAccountPromotionService.swift | 311 + .../CodexBar/CodexAccountReconciliation.swift | 4 + .../CodexAccountUsageSnapshotStore.swift | 133 + Sources/CodexBar/CodexHistoryOwnership.swift | 139 + .../CodexLoginAlertPresentation.swift | 44 + Sources/CodexBar/CodexLoginRunner.swift | 193 + Sources/CodexBar/CodexOwnershipContext.swift | 188 + .../CodexResetCreditExpiryNotifier.swift | 63 + Sources/CodexBar/CodexbarApp.swift | 596 ++ .../Config/CodexBarConfigMigrator.swift | 373 ++ Sources/CodexBar/CookieHeaderStore.swift | 190 + Sources/CodexBar/CopilotTokenStore.swift | 128 + .../CodexBar/CostHistoryChartMenuView.swift | 909 +++ .../CreditsHistoryChartMenuView.swift | 334 + Sources/CodexBar/CursorLoginRunner.swift | 117 + .../CodexBar/Date+RelativeDescription.swift | 23 + Sources/CodexBar/DisplayLink.swift | 96 + Sources/CodexBar/GeminiLoginRunner.swift | 95 + Sources/CodexBar/HiddenWindowView.swift | 38 + Sources/CodexBar/HistoricalUsagePace.swift | 975 +++ Sources/CodexBar/IconRemainingResolver.swift | 152 + Sources/CodexBar/IconRenderer.swift | 1069 +++ .../InlineUsageDashboardContent.swift | 914 +++ Sources/CodexBar/InstallOrigin.swift | 9 + .../CodexBar/KeyboardShortcuts+Names.swift | 6 + Sources/CodexBar/KeychainMigration.swift | 154 + .../CodexBar/KeychainPromptCoordinator.swift | 222 + Sources/CodexBar/KimiK2TokenStore.swift | 128 + Sources/CodexBar/KimiTokenStore.swift | 128 + Sources/CodexBar/LaunchAtLoginManager.swift | 56 + Sources/CodexBar/LoadingPattern.swift | 62 + Sources/CodexBar/Localization.swift | 264 + Sources/CodexBar/MainThreadHangWatchdog.swift | 311 + .../ManagedCodexAccountCoordinator.swift | 61 + .../CodexBar/ManagedCodexAccountService.swift | 497 ++ Sources/CodexBar/MemoryPressureMonitor.swift | 149 + Sources/CodexBar/MemoryPressureRelief.swift | 7 + Sources/CodexBar/MenuBarDisplayMode.swift | 31 + Sources/CodexBar/MenuBarDisplayText.swift | 182 + .../MenuBarMetricWindowResolver.swift | 283 + .../MenuBarStatusItemDefaultsRepair.swift | 54 + .../MenuBarStatusItemPlacementPreflight.swift | 61 + .../MenuBarStatusItemWindowProbe.swift | 110 + .../CodexBar/MenuBarVisibilityWatcher.swift | 464 ++ .../CodexBar/MenuCardGPUSelectionView.swift | 310 + .../CodexBar/MenuCardHeightFingerprint.swift | 177 + .../MenuCardQuotaWarningMarkers.swift | 30 + Sources/CodexBar/MenuCardRefreshMonitor.swift | 111 + .../MenuCardView+CodexResetCredits.swift | 132 + Sources/CodexBar/MenuCardView+Costs.swift | 393 ++ Sources/CodexBar/MenuCardView+Kiro.swift | 43 + Sources/CodexBar/MenuCardView+MiniMax.swift | 142 + .../CodexBar/MenuCardView+ModelHelpers.swift | 933 +++ .../CodexBar/MenuCardView+ModelInput.swift | 110 + Sources/CodexBar/MenuCardView.swift | 1570 +++++ Sources/CodexBar/MenuContent.swift | 267 + .../MenuDescriptor+ProviderUsage.swift | 169 + .../CodexBar/MenuDescriptor+Wayfinder.swift | 12 + Sources/CodexBar/MenuDescriptor.swift | 752 +++ Sources/CodexBar/MenuHighlightStyle.swift | 39 + Sources/CodexBar/MenuOpenRefreshPlan.swift | 41 + Sources/CodexBar/MenuSessionCoordinator.swift | 211 + Sources/CodexBar/MiniMaxAPITokenStore.swift | 128 + Sources/CodexBar/MiniMaxCookieStore.swift | 133 + Sources/CodexBar/MouseLocationReader.swift | 69 + Sources/CodexBar/Notifications+CodexBar.swift | 60 + ...penAICreditsPurchaseWindowController.swift | 548 ++ Sources/CodexBar/PersonalInfoRedactor.swift | 33 + .../PlanUtilizationHistoryChartMenuView.swift | 853 +++ .../PlanUtilizationHistoryStore.swift | 361 + Sources/CodexBar/PredictivePaceWarnings.swift | 284 + Sources/CodexBar/PreferencesAboutPane.swift | 181 + .../CodexBar/PreferencesAdvancedPane.swift | 129 + .../PreferencesCodexAccountsSection.swift | 333 + Sources/CodexBar/PreferencesComponents.swift | 167 + Sources/CodexBar/PreferencesDebugPane.swift | 563 ++ Sources/CodexBar/PreferencesGeneralPane.swift | 157 + Sources/CodexBar/PreferencesMenuBarPane.swift | 207 + Sources/CodexBar/PreferencesMenuPane.swift | 203 + Sources/CodexBar/PreferencesMenuPicker.swift | 92 + .../PreferencesNotificationsPane.swift | 61 + .../PreferencesProviderDetailView.swift | 604 ++ .../PreferencesProviderErrorView.swift | 53 + .../PreferencesProviderSettingsMetrics.swift | 8 + .../PreferencesProviderSettingsRows.swift | 621 ++ .../PreferencesProvidersPane+Testing.swift | 289 + .../CodexBar/PreferencesProvidersPane.swift | 820 +++ Sources/CodexBar/PreferencesSelection.swift | 61 + Sources/CodexBar/PreferencesSidebar.swift | 305 + Sources/CodexBar/PreferencesView.swift | 328 + Sources/CodexBar/ProviderBrandIcon.swift | 48 + .../CodexBar/ProviderRefreshCoordinator.swift | 199 + Sources/CodexBar/ProviderRegistry.swift | 167 + .../CodexBar/ProviderSwitcherButtons.swift | 285 + Sources/CodexBar/ProviderToggleStore.swift | 30 + .../Abacus/AbacusProviderImplementation.swift | 96 + .../Abacus/AbacusSettingsStore.swift | 35 + ...babaCodingPlanProviderImplementation.swift | 128 + .../AlibabaCodingPlanSettingsStore.swift | 86 + ...ibabaTokenPlanProviderImplementation.swift | 112 + .../AlibabaTokenPlanSettingsStore.swift | 43 + .../Amp/AmpProviderImplementation.swift | 136 + .../Providers/Amp/AmpSettingsStore.swift | 58 + .../Antigravity/AntigravityLoginFlow.swift | 33 + .../Antigravity/AntigravityLoginRunner.swift | 484 ++ .../AntigravityProviderImplementation.swift | 102 + .../AntigravitySettingsStore.swift | 65 + .../AugmentProviderImplementation.swift | 94 + .../Augment/AugmentProviderRuntime.swift | 121 + .../Augment/AugmentSettingsStore.swift | 37 + .../AzureOpenAIProviderImplementation.swift | 67 + .../AzureOpenAISettingsStore.swift | 32 + .../BedrockProviderImplementation.swift | 98 + .../Bedrock/BedrockSettingsStore.swift | 58 + .../Chutes/ChutesProviderImplementation.swift | 40 + .../Chutes/ChutesSettingsStore.swift | 16 + .../Providers/Claude/ClaudeLoginFlow.swift | 41 + .../Claude/ClaudeProviderImplementation.swift | 325 + .../Claude/ClaudeProviderRuntime.swift | 42 + .../Claude/ClaudeSettingsStore.swift | 162 + .../Claude/UsageStore+ClaudeSwapRefresh.swift | 153 + .../ClawRouterProviderImplementation.swift | 48 + .../ClawRouter/ClawRouterSettingsStore.swift | 23 + .../CodebuffProviderImplementation.swift | 40 + .../Codebuff/CodebuffSettingsStore.swift | 14 + .../Codex/CodexConsumerProjection.swift | 598 ++ .../Codex/CodexLimitResetOwnerKey.swift | 84 + .../Providers/Codex/CodexLoginFlow.swift | 33 + .../Codex/CodexProviderImplementation.swift | 280 + .../Codex/CodexProviderRuntime.swift | 17 + .../Providers/Codex/CodexSettingsStore.swift | 741 +++ .../Codex/CodexWeeklyResetConfirmation.swift | 184 + .../Codex/UsageStore+CodexAccountState.swift | 756 +++ .../Codex/UsageStore+CodexRefresh.swift | 269 + ...geStore+CodexWeeklyResetConfirmation.swift | 90 + .../CommandCodeProviderImplementation.swift | 79 + .../CommandCodeSettingsStore.swift | 37 + .../Providers/Copilot/CopilotLoginFlow.swift | 291 + .../CopilotProviderImplementation.swift | 219 + .../Copilot/CopilotSettingsStore.swift | 90 + .../Copilot/UsageStore+CopilotBudgets.swift | 19 + .../Crof/CrofProviderImplementation.swift | 52 + .../Providers/Crof/CrofSettingsStore.swift | 14 + .../CrossModelProviderImplementation.swift | 79 + .../CrossModel/CrossModelSettingsStore.swift | 14 + .../Providers/Cursor/CursorLoginFlow.swift | 25 + .../Cursor/CursorProviderImplementation.swift | 98 + .../Cursor/CursorSettingsStore.swift | 37 + .../DeepSeekProviderImplementation.swift | 27 + .../DeepgramProviderImplementation.swift | 51 + .../Deepgram/DeepgramSettingsStore.swift | 27 + .../Devin/DevinProviderImplementation.swift | 132 + .../Providers/Devin/DevinSettingsStore.swift | 43 + .../Doubao/DoubaoProviderImplementation.swift | 62 + .../Doubao/DoubaoSettingsStore.swift | 34 + .../ElevenLabsProviderImplementation.swift | 43 + .../ElevenLabs/ElevenLabsSettingsStore.swift | 14 + .../Providers/Factory/FactoryLoginFlow.swift | 12 + .../FactoryProviderImplementation.swift | 163 + .../Factory/FactorySettingsStore.swift | 69 + .../Providers/Gemini/GeminiLoginFlow.swift | 19 + .../Gemini/GeminiProviderImplementation.swift | 45 + .../Grok/GrokProviderImplementation.swift | 6 + .../Groq/GroqProviderImplementation.swift | 38 + .../Providers/Groq/GroqSettingsStore.swift | 16 + .../JetBrains/JetBrainsLoginFlow.swift | 28 + .../JetBrainsProviderImplementation.swift | 70 + .../JetBrains/JetBrainsSettingsStore.swift | 9 + .../Kilo/KiloProviderImplementation.swift | 167 + .../Providers/Kilo/KiloSettingsStore.swift | 142 + .../Kilo/UsageStore+KiloOrgRefresh.swift | 121 + .../Kimi/KimiProviderImplementation.swift | 148 + .../Providers/Kimi/KimiSettingsStore.swift | 63 + .../KimiK2/KimiK2ProviderImplementation.swift | 39 + .../KimiK2/KimiK2SettingsStore.swift | 16 + .../Kiro/KiroProviderImplementation.swift | 28 + .../LLMProxyProviderImplementation.swift | 49 + .../LLMProxy/LLMProxySettingsStore.swift | 27 + .../LiteLLMProviderImplementation.swift | 49 + .../LiteLLM/LiteLLMSettingsStore.swift | 27 + .../Manus/ManusProviderImplementation.swift | 107 + .../Providers/Manus/ManusSettingsStore.swift | 34 + .../MiMo/MiMoProviderImplementation.swift | 98 + .../Providers/MiMo/MiMoSettingsStore.swift | 36 + .../MiniMaxProviderImplementation.swift | 153 + .../MiniMax/MiniMaxSettingsStore.swift | 73 + .../MistralProviderImplementation.swift | 102 + .../Mistral/MistralSettingsStore.swift | 38 + .../MoonshotProviderImplementation.swift | 86 + .../Moonshot/MoonshotSettingsStore.swift | 44 + .../Ollama/OllamaProviderImplementation.swift | 151 + .../Ollama/OllamaSettingsStore.swift | 62 + .../OpenAIAPIProviderImplementation.swift | 78 + .../OpenAI/OpenAIAPISettingsStore.swift | 24 + .../OpenCodeProviderImplementation.swift | 93 + .../OpenCode/OpenCodeProviderUI.swift | 10 + .../OpenCode/OpenCodeSettingsStore.swift | 52 + .../OpenCodeGoProviderImplementation.swift | 93 + .../OpenCodeGo/OpenCodeGoSettingsStore.swift | 65 + .../OpenRouterProviderImplementation.swift | 55 + .../OpenRouter/OpenRouterSettingsStore.swift | 14 + .../PerplexityProviderImplementation.swift | 93 + .../Perplexity/PerplexitySettingsStore.swift | 35 + .../Poe/PoeProviderImplementation.swift | 38 + .../Providers/Poe/PoeSettingsStore.swift | 16 + .../Qoder/QoderProviderImplementation.swift | 103 + .../Providers/Qoder/QoderSettingsStore.swift | 38 + .../Sakana/SakanaProviderImplementation.swift | 51 + .../Sakana/SakanaSettingsStore.swift | 14 + .../Providers/Shared/ProviderCatalog.swift | 15 + .../Providers/Shared/ProviderContext.swift | 48 + .../ProviderCookieSettingsResolution.swift | 22 + .../Shared/ProviderCookieSourceUI.swift | 128 + .../Shared/ProviderImplementation.swift | 190 + .../ProviderImplementationRegistry.swift | 111 + .../Providers/Shared/ProviderLoginFlow.swift | 12 + .../Shared/ProviderMenuContext.swift | 28 + .../Shared/ProviderPresentation.swift | 12 + .../Providers/Shared/ProviderRuntime.swift | 34 + .../Shared/ProviderSettingsDescriptors.swift | 299 + .../ProviderTokenAccountSelection.swift | 19 + .../Shared/SystemSettingsLinks.swift | 18 + .../StepFunProviderImplementation.swift | 157 + .../StepFun/StepFunSettingsStore.swift | 65 + .../Sub2APIProviderImplementation.swift | 72 + .../Sub2API/Sub2APISettingsStore.swift | 23 + .../SyntheticProviderImplementation.swift | 42 + .../Synthetic/SyntheticSettingsStore.swift | 16 + .../T3Chat/T3ChatProviderImplementation.swift | 79 + .../T3Chat/T3ChatSettingsStore.swift | 36 + .../Venice/VeniceProviderImplementation.swift | 27 + .../VertexAI/VertexAILoginFlow.swift | 30 + .../VertexAIProviderImplementation.swift | 13 + .../Warp/WarpProviderImplementation.swift | 40 + .../Providers/Warp/WarpSettingsStore.swift | 14 + .../WayfinderProviderImplementation.swift | 51 + .../Wayfinder/WayfinderSettingsStore.swift | 13 + .../WindsurfProviderImplementation.swift | 104 + .../Windsurf/WindsurfSettingsStore.swift | 70 + .../Zai/ZaiProviderImplementation.swift | 60 + .../Providers/Zai/ZaiSettingsStore.swift | 64 + .../Zed/ZedProviderImplementation.swift | 5 + .../QuotaWarningAlertOverlayController.swift | 178 + .../CodexBar/QuotaWarningSettingsViews.swift | 612 ++ Sources/CodexBar/Resources/Icon-classic.icns | Bin 0 -> 1315598 bytes .../Resources/ProviderIcon-abacus.svg | 18 + .../Resources/ProviderIcon-alibaba.svg | 3 + .../CodexBar/Resources/ProviderIcon-amp.svg | 6 + .../Resources/ProviderIcon-antigravity.svg | 3 + .../Resources/ProviderIcon-augment.svg | 16 + .../Resources/ProviderIcon-bedrock.svg | 8 + .../Resources/ProviderIcon-chutes.svg | 6 + .../Resources/ProviderIcon-claude.svg | 3 + .../Resources/ProviderIcon-clawrouter.svg | 7 + .../Resources/ProviderIcon-codebuff.svg | 4 + .../CodexBar/Resources/ProviderIcon-codex.svg | 3 + .../Resources/ProviderIcon-commandcode.svg | 3 + .../Resources/ProviderIcon-copilot.svg | 3 + .../CodexBar/Resources/ProviderIcon-crof.svg | 3 + .../Resources/ProviderIcon-crossmodel.svg | 5 + .../Resources/ProviderIcon-cursor.svg | 3 + .../Resources/ProviderIcon-deepgram.svg | 4 + .../Resources/ProviderIcon-deepseek.svg | 3 + .../CodexBar/Resources/ProviderIcon-devin.svg | 3 + .../Resources/ProviderIcon-doubao.svg | 1 + .../Resources/ProviderIcon-elevenlabs.svg | 4 + .../Resources/ProviderIcon-factory.svg | 3 + .../Resources/ProviderIcon-gemini.svg | 3 + .../CodexBar/Resources/ProviderIcon-grok.svg | 4 + .../CodexBar/Resources/ProviderIcon-groq.svg | 4 + .../Resources/ProviderIcon-jetbrains.svg | 1 + .../CodexBar/Resources/ProviderIcon-kilo.svg | 6 + .../CodexBar/Resources/ProviderIcon-kimi.svg | 1 + .../CodexBar/Resources/ProviderIcon-kiro.svg | 19 + .../Resources/ProviderIcon-litellm.svg | 16 + .../Resources/ProviderIcon-llmproxy.svg | 7 + .../CodexBar/Resources/ProviderIcon-manus.svg | 6 + .../CodexBar/Resources/ProviderIcon-mimo.svg | 4 + .../Resources/ProviderIcon-minimax.svg | 1 + .../Resources/ProviderIcon-mistral.svg | 1 + .../Resources/ProviderIcon-ollama.svg | 7 + .../Resources/ProviderIcon-opencode.svg | 3 + .../Resources/ProviderIcon-opencodego.svg | 3 + .../Resources/ProviderIcon-openrouter.svg | 13 + .../Resources/ProviderIcon-perplexity.svg | 1 + .../CodexBar/Resources/ProviderIcon-poe.svg | 1 + .../CodexBar/Resources/ProviderIcon-qoder.svg | 3 + .../Resources/ProviderIcon-sakana.svg | 5 + .../Resources/ProviderIcon-stepfun.svg | 33 + .../Resources/ProviderIcon-sub2api.svg | 4 + .../Resources/ProviderIcon-synthetic.svg | 14 + .../Resources/ProviderIcon-t3chat.svg | 5 + .../Resources/ProviderIcon-venice.svg | 4 + .../Resources/ProviderIcon-vertexai.svg | 6 + .../CodexBar/Resources/ProviderIcon-warp.svg | 4 + .../Resources/ProviderIcon-wayfinder.svg | 5 + .../Resources/ProviderIcon-windsurf.svg | 3 + .../CodexBar/Resources/ProviderIcon-zai.svg | 5 + .../CodexBar/Resources/ProviderIcon-zed.svg | 3 + .../Resources/ar.lproj/Localizable.strings | 1189 ++++ .../Resources/ca.lproj/Localizable.strings | 1188 ++++ .../Resources/de.lproj/Localizable.strings | 1182 ++++ .../Resources/en.lproj/Localizable.strings | 1189 ++++ .../Resources/es.lproj/Localizable.strings | 1043 +++ .../Resources/fa.lproj/Localizable.strings | 1189 ++++ .../Resources/fr.lproj/Localizable.strings | 1182 ++++ .../Resources/gl.lproj/Localizable.strings | 1184 ++++ .../Resources/id.lproj/Localizable.strings | 1188 ++++ .../Resources/it.lproj/Localizable.strings | 1188 ++++ .../Resources/ja.lproj/Localizable.strings | 1183 ++++ .../Resources/ko.lproj/Localizable.strings | 1151 ++++ .../Resources/nl.lproj/Localizable.strings | 1182 ++++ .../Resources/pl.lproj/Localizable.strings | 1188 ++++ .../Resources/pt-BR.lproj/Localizable.strings | 1183 ++++ .../Resources/ru.lproj/Localizable.strings | 1189 ++++ .../Resources/sv.lproj/Localizable.strings | 1181 ++++ .../Resources/th.lproj/Localizable.strings | 1189 ++++ .../Resources/tr.lproj/Localizable.strings | 1186 ++++ .../Resources/uk.lproj/Localizable.strings | 1182 ++++ .../Resources/vi.lproj/Localizable.strings | 1183 ++++ .../zh-Hans.lproj/Localizable.strings | 1159 ++++ .../zh-Hant.lproj/Localizable.strings | 1218 ++++ .../ScreenConfettiOverlayController.swift | 290 + .../CodexBar/SessionQuotaNotifications.swift | 611 ++ Sources/CodexBar/SettingsStore+Config.swift | 170 + .../SettingsStore+ConfigPersistence.swift | 222 + Sources/CodexBar/SettingsStore+Defaults.swift | 862 +++ .../SettingsStore+MenuObservation.swift | 105 + .../SettingsStore+MenuPreferences.swift | 311 + .../SettingsStore+ProviderDetection.swift | 96 + .../SettingsStore+TokenAccounts.swift | 353 + .../CodexBar/SettingsStore+TokenCost.swift | 93 + Sources/CodexBar/SettingsStore.swift | 868 +++ Sources/CodexBar/SettingsStoreState.swift | 68 + .../CodexBar/StatusComponentsMenuView.swift | 115 + ...tusItemController+AccountMenuDisplay.swift | 152 + .../StatusItemController+Actions.swift | 881 +++ .../StatusItemController+AgentSessions.swift | 19 + .../StatusItemController+Animation.swift | 1449 ++++ .../StatusItemController+ClaudeSwapMenu.swift | 65 + ...tatusItemController+CodexStackedMenu.swift | 75 + .../StatusItemController+CostMenuCard.swift | 137 + ...tatusItemController+CountdownRefresh.swift | 150 + .../StatusItemController+HostedSubmenus.swift | 663 ++ ...StatusItemController+IconObservation.swift | 61 + .../StatusItemController+IconPerf.swift | 69 + .../StatusItemController+MemoryPressure.swift | 49 + .../CodexBar/StatusItemController+Menu.swift | 1647 +++++ ...atusItemController+MenuActionMapping.swift | 35 + .../StatusItemController+MenuAppearance.swift | 13 + ...usItemController+MenuCardHeightCache.swift | 54 + .../StatusItemController+MenuCardItems.swift | 178 + .../StatusItemController+MenuCardModel.swift | 160 + ...atusItemController+MenuCardRecycling.swift | 69 + .../StatusItemController+MenuContexts.swift | 34 + ...temController+MenuInteractionRefresh.swift | 175 + ...tatusItemController+MenuLocalization.swift | 38 + ...tatusItemController+MenuPresentation.swift | 685 ++ .../StatusItemController+MenuReconcile.swift | 221 + ...ItemController+MenuRefreshScheduling.swift | 361 + ...atusItemController+MenuRowReordering.swift | 47 + ...StatusItemController+MenuSmartUpdate.swift | 141 + .../StatusItemController+MenuTracking.swift | 591 ++ .../StatusItemController+MenuTypes.swift | 182 + ...usItemController+MenuViewportRestore.swift | 730 +++ .../StatusItemController+MenuWidthCache.swift | 148 + ...ontroller+MergedSwitcherContentCache.swift | 142 + .../StatusItemController+OverviewScroll.swift | 126 + ...tatusItemController+OverviewSubmenus.swift | 66 + ...ItemController+PersistentMenuActions.swift | 60 + ...Controller+PersistentRefreshMenuItem.swift | 58 + ...tusItemController+ProviderNavigation.swift | 102 + ...tatusItemController+ProviderSwitcher.swift | 387 ++ .../StatusItemController+Shutdown.swift | 117 + ...StatusItemController+StorageMenuCard.swift | 26 + ...StatusItemController+SwitcherMetrics.swift | 24 + .../StatusItemController+SwitcherViews.swift | 1669 +++++ ...tatusItemController+UsageHistoryMenu.swift | 70 + .../StatusItemController+WidgetSnapshot.swift | 16 + ...tusItemController+ZaiHourlyChartMenu.swift | 35 + Sources/CodexBar/StatusItemController.swift | 1030 +++ Sources/CodexBar/StatusItemMenu.swift | 107 + .../CodexBar/StorageBreakdownMenuView.swift | 367 ++ Sources/CodexBar/SyntheticTokenStore.swift | 128 + Sources/CodexBar/TerminalApp.swift | 123 + Sources/CodexBar/UpdateChannel.swift | 73 + .../UsageBreakdownChartMenuView.swift | 469 ++ ...ageMenuCardHeaderAndUsageSectionView.swift | 23 + Sources/CodexBar/UsageMenuCardLayout.swift | 17 + Sources/CodexBar/UsagePaceText.swift | 137 + Sources/CodexBar/UsageProgressBar.swift | 326 + Sources/CodexBar/UsageStore+APIKeyDebug.swift | 116 + Sources/CodexBar/UsageStore+Accessors.swift | 135 + .../CodexBar/UsageStore+AdaptiveRefresh.swift | 125 + .../UsageStore+BackgroundRefresh.swift | 101 + Sources/CodexBar/UsageStore+ClaudeDebug.swift | 174 + .../UsageStore+CodexResetCredits.swift | 133 + .../CodexBar/UsageStore+GeminiMigration.swift | 16 + .../CodexBar/UsageStore+HighestUsage.swift | 142 + .../CodexBar/UsageStore+HistoricalPace.swift | 153 + .../UsageStore+LimitResetBoundary.swift | 13 + .../UsageStore+LimitResetIdentity.swift | 32 + Sources/CodexBar/UsageStore+Logging.swift | 36 + .../CodexBar/UsageStore+MemoryPressure.swift | 39 + Sources/CodexBar/UsageStore+OpenAIWeb.swift | 1567 +++++ .../CodexBar/UsageStore+PlanUtilization.swift | 1712 +++++ .../UsageStore+PlanUtilizationLoading.swift | 37 + .../CodexBar/UsageStore+ProviderRuntime.swift | 21 + .../CodexBar/UsageStore+ProviderStatus.swift | 54 + .../CodexBar/UsageStore+ProviderStorage.swift | 300 + .../CodexBar/UsageStore+QuotaWarnings.swift | 160 + Sources/CodexBar/UsageStore+Refresh.swift | 1137 ++++ .../UsageStore+RefreshEnrichment.swift | 325 + .../UsageStore+ResetBoundaryRefresh.swift | 133 + .../UsageStore+StartupConnectivityRetry.swift | 85 + Sources/CodexBar/UsageStore+Status.swift | 491 ++ Sources/CodexBar/UsageStore+Timeout.swift | 97 + .../CodexBar/UsageStore+TokenAccounts.swift | 1536 +++++ Sources/CodexBar/UsageStore+TokenCost.swift | 190 + .../UsageStore+TokenRefreshSequence.swift | 153 + .../CodexBar/UsageStore+WidgetSnapshot.swift | 236 + Sources/CodexBar/UsageStore.swift | 1666 +++++ Sources/CodexBar/UsageStoreSupport.swift | 151 + .../ZaiHourlyUsageChartMenuView.swift | 251 + Sources/CodexBar/ZaiTokenStore.swift | 176 + Sources/CodexBarCLI/CLICacheCommand.swift | 152 + .../CodexBarCLI/CLICardsBriefRenderer.swift | 590 ++ Sources/CodexBarCLI/CLICardsCommand.swift | 212 + Sources/CodexBarCLI/CLICardsRenderer.swift | 529 ++ Sources/CodexBarCLI/CLIConfigCommand.swift | 444 ++ Sources/CodexBarCLI/CLICostCommand.swift | 510 ++ Sources/CodexBarCLI/CLIDiagnoseCommand.swift | 341 + Sources/CodexBarCLI/CLIEntry.swift | 226 + Sources/CodexBarCLI/CLIErrorReporting.swift | 131 + Sources/CodexBarCLI/CLIExitCode.swift | 11 + Sources/CodexBarCLI/CLIHelp.swift | 325 + Sources/CodexBarCLI/CLIHelpers.swift | 415 ++ Sources/CodexBarCLI/CLIIO.swift | 127 + Sources/CodexBarCLI/CLILocalHTTPServer.swift | 433 ++ Sources/CodexBarCLI/CLIOptions.swift | 145 + .../CodexBarCLI/CLIOutputPreferences.swift | 50 + Sources/CodexBarCLI/CLIPayloads.swift | 187 + Sources/CodexBarCLI/CLIRenderer.swift | 1355 ++++ Sources/CodexBarCLI/CLIServeCommand.swift | 1121 ++++ .../CLIServeOperationCoordinator.swift | 551 ++ Sources/CodexBarCLI/CLISessionsCommand.swift | 94 + .../CodexBarCLI/CLITerminalCapabilities.swift | 47 + .../CLITerminationSignalMonitor.swift | 79 + Sources/CodexBarCLI/CLIUsageCommand.swift | 744 +++ Sources/CodexBarCLI/DiagnoseOptions.swift | 29 + Sources/CodexBarCLI/TokenAccountCLI.swift | 648 ++ Sources/CodexBarClaudeWatchdog/main.swift | 122 + .../ClaudeWebProbeEntry.swift | 63 + Sources/CodexBarCore/AgentSession.swift | 445 ++ Sources/CodexBarCore/AppGroupSupport.swift | 247 + .../CodexBarCore/AutoreleasePoolCompat.swift | 8 + Sources/CodexBarCore/BoundedTaskJoin.swift | 81 + .../BrowserCookieAccessGate.swift | 355 + .../BrowserCookieImportOrder.swift | 62 + Sources/CodexBarCore/BrowserDetection.swift | 378 ++ Sources/CodexBarCore/CodexHomeScope.swift | 42 + .../CodexBarCore/CodexManagedAccounts.swift | 169 + .../Config/CodexActiveSource.swift | 59 + .../CodexBarCore/Config/CodexBarConfig.swift | 332 + .../Config/CodexBarConfigStore.swift | 125 + .../Config/CodexBarConfigValidation.swift | 359 + .../Config/ProviderConfigEnvironment.swift | 416 ++ Sources/CodexBarCore/CookieHeaderCache.swift | 982 +++ .../CodexBarCore/CookieHeaderNormalizer.swift | 92 + Sources/CodexBarCore/CopilotUsageModels.swift | 343 + Sources/CodexBarCore/CostUsageFetcher.swift | 738 +++ Sources/CodexBarCore/CostUsageModels.swift | 1000 +++ .../CodexBarCore/CostUsageScanExecutor.swift | 130 + Sources/CodexBarCore/CreditsModels.swift | 320 + Sources/CodexBarCore/Double+Clamped.swift | 5 + .../Generated/CodexParserHash.generated.swift | 5 + .../Host/PTY/TTYCommandRunner.swift | 1197 ++++ .../PosixSpawnFileActionsCloseFrom.swift | 61 + .../Host/Process/ProcessPipeCapture.swift | 150 + .../Host/Process/SpawnedProcessGroup.swift | 809 +++ .../Host/Process/SubprocessRunner.swift | 321 + Sources/CodexBarCore/KeychainAccessGate.swift | 100 + .../KeychainAccessPreflight.swift | 196 + Sources/CodexBarCore/KeychainCacheStore.swift | 665 ++ Sources/CodexBarCore/KeychainNoUIQuery.swift | 41 + Sources/CodexBarCore/KeychainSecurity.swift | 74 + .../LocalAgentSessionScanner.swift | 229 + .../CodexBarCore/Logging/CodexBarLog.swift | 229 + .../Logging/CompositeLogHandler.swift | 40 + .../CodexBarCore/Logging/FileLogHandler.swift | 150 + .../Logging/JSONStderrLogHandler.swift | 72 + .../CodexBarCore/Logging/LogCategories.swift | 96 + .../CodexBarCore/Logging/LogMetadata.swift | 10 + .../CodexBarCore/Logging/LogRedactor.swift | 61 + .../Logging/OSLogLogHandler.swift | 77 + .../Logging/ProviderLogging.swift | 27 + .../ManagedCodexAccountStore.swift | 115 + .../CodexBarCore/OpenAIDashboardModels.swift | 367 ++ ...hboardBrowserCookieImporter+Deadline.swift | 190 + ...OpenAIDashboardBrowserCookieImporter.swift | 1053 +++ ...penAIDashboardFetcher+ReturnableData.swift | 30 + .../OpenAIWeb/OpenAIDashboardFetcher.swift | 1092 ++++ .../OpenAIDashboardNavigationDelegate.swift | 101 + .../OpenAIWeb/OpenAIDashboardParser.swift | 551 ++ .../OpenAIDashboardScrapeScript.swift | 907 +++ .../OpenAIDashboardWebViewCache.swift | 782 +++ .../OpenAIDashboardWebsiteDataStore.swift | 118 + Sources/CodexBarCore/PathEnvironment.swift | 1228 ++++ Sources/CodexBarCore/PiSessionCostCache.swift | 97 + .../CodexBarCore/PiSessionCostScanner.swift | 943 +++ .../ProviderAccountSnapshot.swift | 55 + .../CodexBarCore/ProviderCostSnapshot.swift | 38 + .../ProviderEndpointOverrideValidator.swift | 170 + Sources/CodexBarCore/ProviderHTTPClient.swift | 253 + .../ProviderStorageFootprint.swift | 543 ++ .../Providers/APITokenFetchStrategy.swift | 72 + .../Abacus/AbacusCookieImporter.swift | 134 + .../Abacus/AbacusProviderDescriptor.swift | 91 + .../Providers/Abacus/AbacusUsageError.swift | 67 + .../Providers/Abacus/AbacusUsageFetcher.swift | 336 + .../Abacus/AbacusUsageSnapshot.swift | 77 + .../Alibaba/AlibabaCodingPlanAPIRegion.swift | 133 + .../AlibabaCodingPlanCookieImporter.swift | 510 ++ .../AlibabaCodingPlanProviderDescriptor.swift | 266 + .../AlibabaCodingPlanSettingsReader.swift | 118 + .../AlibabaCodingPlanUsageFetcher.swift | 1121 ++++ .../AlibabaCodingPlanUsageSnapshot.swift | 126 + .../Alibaba/AlibabaTokenPlanAPIRegion.swift | 60 + .../AlibabaTokenPlanCookieHeader.swift | 163 + .../AlibabaTokenPlanProviderDescriptor.swift | 289 + .../AlibabaTokenPlanSettingsReader.swift | 67 + .../AlibabaTokenPlanUsageFetcher.swift | 997 +++ .../AlibabaTokenPlanUsageSnapshot.swift | 96 + .../Providers/Amp/AmpCLIProbe.swift | 46 + .../Providers/Amp/AmpProviderDescriptor.swift | 169 + .../Providers/Amp/AmpSettingsReader.swift | 22 + .../Providers/Amp/AmpUsageFetcher.swift | 491 ++ .../Providers/Amp/AmpUsageParser.swift | 221 + .../Providers/Amp/AmpUsageSnapshot.swift | 109 + .../Antigravity/AntigravityCLISession.swift | 1297 ++++ .../AntigravityLocalSnapshotSelection.swift | 37 + .../AntigravityLocalhostSession.swift | 109 + .../AntigravityOAuthCredentialsStore.swift | 516 ++ .../AntigravityProviderDescriptor.swift | 673 ++ .../AntigravityQuotaSummaryParser.swift | 173 + .../AntigravityRemoteUsageFetcher.swift | 777 +++ .../AntigravityStatusProbe+Deadline.swift | 128 + ...ntigravityStatusProbe+LocalEndpoints.swift | 23 + ...AntigravityStatusProbe+PortDetection.swift | 137 + ...ntigravityStatusProbe+ResponseModels.swift | 111 + .../Antigravity/AntigravityStatusProbe.swift | 1642 +++++ .../AntigravityUsageDataSource.swift | 30 + .../Providers/Augment/AuggieCLIProbe.swift | 191 + .../Augment/AugmentProviderDescriptor.swift | 133 + .../Augment/AugmentSessionKeepalive.swift | 491 ++ .../Augment/AugmentStatusProbe.swift | 698 ++ .../AzureOpenAIProviderDescriptor.swift | 92 + .../AzureOpenAISettingsReader.swift | 82 + .../AzureOpenAI/AzureOpenAIUsageFetcher.swift | 244 + .../Providers/Bedrock/BedrockAWSSigner.swift | 179 + .../Bedrock/BedrockCloudWatchUsage.swift | 231 + .../Bedrock/BedrockCredentialResolver.swift | 78 + .../BedrockProfileCredentialProvider.swift | 87 + .../Bedrock/BedrockProviderDescriptor.swift | 74 + .../Bedrock/BedrockSettingsReader.swift | 107 + .../Providers/Bedrock/BedrockUsageStats.swift | 503 ++ .../Providers/CLIProbeSessionResetter.swift | 9 + .../Chutes/ChutesProviderDescriptor.swift | 68 + .../Chutes/ChutesSettingsReader.swift | 63 + .../Providers/Chutes/ChutesUsageStats.swift | 1045 +++ .../Claude/ClaudeAdminAPISettingsReader.swift | 43 + .../Claude/ClaudeAdminAPIUsageFetcher.swift | 432 ++ .../Claude/ClaudeAdminAPIUsageSnapshot.swift | 242 + .../Claude/ClaudeCLIAuthStatusProbe.swift | 35 + .../Claude/ClaudeCLIRateLimitGate.swift | 64 + .../Providers/Claude/ClaudeCLISession.swift | 499 ++ .../Claude/ClaudeCredentialRouting.swift | 102 + .../Claude/ClaudeDesktopProjectsLocator.swift | 89 + .../ClaudeOAuthCredentialModels.swift | 301 + .../ClaudeOAuthCredentials+Hashing.swift | 18 + ...deOAuthCredentials+SecurityCLIReader.swift | 375 ++ ...udeOAuthCredentials+TestingOverrides.swift | 430 ++ .../ClaudeOAuth/ClaudeOAuthCredentials.swift | 2563 ++++++++ ...audeOAuthDelegatedRefreshCoordinator.swift | 580 ++ .../ClaudeOAuthKeychainAccessGate.swift | 184 + .../ClaudeOAuthKeychainPreAlertGate.swift | 169 + .../ClaudeOAuthKeychainPromptMode.swift | 177 + .../ClaudeOAuthKeychainQueryTiming.swift | 31 + .../ClaudeOAuthKeychainReadStrategy.swift | 49 + .../ClaudeOAuthMutableKeychainOverrides.swift | 35 + .../ClaudeOAuthPendingCacheClearStore.swift | 142 + .../ClaudeOAuthRefreshFailureGate.swift | 371 ++ .../ClaudeOAuth/ClaudeOAuthUsageFetcher.swift | 324 + .../ClaudeOAuthUsageRateLimitGate.swift | 46 + .../Providers/Claude/ClaudePlan.swift | 179 + .../ClaudeProbeSessionArtifactCleaner.swift | 105 + .../Claude/ClaudeProviderDescriptor.swift | 679 ++ .../ClaudeScopedWeeklyLimitMapper.swift | 62 + .../Claude/ClaudeSourcePlanner.swift | 224 + .../Providers/Claude/ClaudeStatusProbe.swift | 1353 ++++ .../ClaudeSwap/ClaudeSwapAccountList.swift | 216 + .../ClaudeSwapAccountProjection.swift | 102 + .../ClaudeSwap/ClaudeSwapAccountReader.swift | 141 + .../ClaudeSwap/ClaudeSwapAccountSwitch.swift | 117 + .../Claude/ClaudeUsageDataSource.swift | 38 + .../Providers/Claude/ClaudeUsageFetcher.swift | 1533 +++++ .../ClaudeWeb/ClaudeWebAPIFetcher.swift | 1270 ++++ .../ClaudeWebExtraRateWindowParser.swift | 123 + .../ClawRouterProviderDescriptor.swift | 62 + .../ClawRouter/ClawRouterSettingsReader.swift | 55 + .../ClawRouter/ClawRouterUsageFetcher.swift | 255 + .../Codebuff/CodebuffProviderDescriptor.swift | 95 + .../Codebuff/CodebuffSettingsReader.swift | 86 + .../Codebuff/CodebuffUsageError.swift | 40 + .../Codebuff/CodebuffUsageFetcher.swift | 365 ++ .../Codebuff/CodebuffUsageSnapshot.swift | 147 + .../Codex/CodexAccountReconciliation.swift | 474 ++ .../CodexAdditionalRateLimitMapper.swift | 153 + .../CodexAuthenticatedHTTPTransport.swift | 33 + .../CodexCLIDashboardAuthorityContext.swift | 62 + .../Providers/Codex/CodexCLILaunchGate.swift | 70 + .../Providers/Codex/CodexCLISession.swift | 427 ++ .../Codex/CodexDashboardAuthority.swift | 332 + .../Providers/Codex/CodexIdentity.swift | 47 + .../CodexOAuth/CodexOAuthCredentials.swift | 285 + .../CodexOAuth/CodexOAuthUsageFetcher.swift | 655 ++ .../CodexOAuth/CodexTokenRefresher.swift | 123 + .../CodexOpenAIWorkspaceIdentityCache.swift | 115 + .../Codex/CodexOpenAIWorkspaceResolver.swift | 123 + .../Providers/Codex/CodexPlanFormatting.swift | 59 + .../Codex/CodexProviderDescriptor.swift | 454 ++ .../Codex/CodexProviderSettingsBuilder.swift | 93 + .../Codex/CodexRateWindowNormalizer.swift | 66 + .../Codex/CodexReconciledState.swift | 149 + .../Codex/CodexSpendControlLimitMapping.swift | 25 + .../Providers/Codex/CodexStatusProbe.swift | 294 + .../Codex/CodexStatusProbeIsolation.swift | 46 + .../Codex/CodexSystemAccountObserver.swift | 69 + .../Codex/CodexUsageDataSource.swift | 30 + .../Codex/CodexVisibleAccountProjection.swift | 287 + .../Codex/CodexWebDashboardStrategy.swift | 343 + .../CommandCode/CommandCodeCookieHeader.swift | 85 + .../CommandCodeCookieImporter.swift | 230 + .../CommandCode/CommandCodePlanCatalog.swift | 34 + .../CommandCodeProviderDescriptor.swift | 98 + .../CommandCode/CommandCodeUsageError.swift | 34 + .../CommandCode/CommandCodeUsageFetcher.swift | 263 + .../CommandCodeUsageSnapshot.swift | 124 + .../Copilot/CopilotBudgetWebFetcher.swift | 801 +++ .../Providers/Copilot/CopilotDeviceFlow.swift | 173 + .../Copilot/CopilotProviderDescriptor.swift | 135 + .../Copilot/CopilotUsageFetcher.swift | 186 + .../Crof/CrofProviderDescriptor.swift | 46 + .../Providers/Crof/CrofSettingsReader.swift | 27 + .../Providers/Crof/CrofUsageFetcher.swift | 89 + .../Providers/Crof/CrofUsageSnapshot.swift | 83 + .../CrossModelProviderDescriptor.swift | 63 + .../CrossModel/CrossModelSettingsReader.swift | 52 + .../CrossModel/CrossModelUsageStats.swift | 417 ++ .../Cursor/CursorProviderDescriptor.swift | 70 + .../Providers/Cursor/CursorRequestUsage.swift | 23 + .../Providers/Cursor/CursorStatusProbe.swift | 1475 +++++ .../DeepSeek/DeepSeekProviderDescriptor.swift | 48 + .../DeepSeek/DeepSeekSettingsReader.swift | 33 + .../DeepSeek/DeepSeekUsageCostParser.swift | 709 ++ .../DeepSeek/DeepSeekUsageFetcher.swift | 432 ++ .../Deepgram/DeepgramProviderDescriptor.swift | 102 + .../Deepgram/DeepgramSettingsReader.swift | 33 + .../Deepgram/DeepgramUsageFetcher.swift | 561 ++ .../Devin/DevinProviderDescriptor.swift | 92 + .../Devin/DevinSessionImporter.swift | 459 ++ .../Providers/Devin/DevinUsageFetcher.swift | 271 + .../Providers/Devin/DevinUsageSnapshot.swift | 345 + .../Doubao/DoubaoProviderDescriptor.swift | 110 + .../Doubao/DoubaoSettingsReader.swift | 86 + .../Providers/Doubao/DoubaoUsageFetcher.swift | 548 ++ .../Doubao/DoubaoVolcengineSigner.swift | 153 + .../ElevenLabsProviderDescriptor.swift | 49 + .../ElevenLabs/ElevenLabsSettingsReader.swift | 62 + .../ElevenLabs/ElevenLabsUsageFetcher.swift | 252 + .../Factory/FactoryLocalStorageImporter.swift | 383 ++ .../Factory/FactoryManualCredentials.swift | 58 + .../Factory/FactoryProviderDescriptor.swift | 145 + .../Factory/FactorySessionStore.swift | 179 + .../Factory/FactorySettingsReader.swift | 71 + .../Factory/FactoryStatusProbe+APIKey.swift | 62 + .../Factory/FactoryStatusProbe.swift | 1485 +++++ .../Factory/FactoryStatusProbeError.swift | 47 + .../Gemini/GeminiConsumerTierMigration.swift | 16 + .../Providers/Gemini/GeminiOAuthConfig.swift | 77 + .../Gemini/GeminiProviderDescriptor.swift | 65 + .../Gemini/GeminiStatusProbe+DataLoader.swift | 131 + .../Providers/Gemini/GeminiStatusProbe.swift | 1397 ++++ .../Providers/Grok/GrokAuth.swift | 188 + .../Providers/Grok/GrokCookieImporter.swift | 213 + .../Grok/GrokLocalSessionScanner.swift | 100 + .../Grok/GrokProviderDescriptor.swift | 223 + .../Providers/Grok/GrokRPCClient.swift | 371 ++ .../Providers/Grok/GrokStatusProbe.swift | 147 + .../Grok/GrokWebBillingFetcher.swift | 433 ++ .../Groq/GroqProviderDescriptor.swift | 49 + .../Providers/Groq/GroqSettingsReader.swift | 58 + .../Providers/Groq/GroqUsageFetcher.swift | 235 + .../JetBrains/JetBrainsIDEDetector.swift | 150 + .../JetBrainsProviderDescriptor.swift | 61 + .../JetBrains/JetBrainsStatusProbe.swift | 355 + .../Kilo/KiloBearerTokenResolver.swift | 78 + .../Providers/Kilo/KiloOrganization.swift | 13 + .../Kilo/KiloProviderDescriptor.swift | 141 + .../Providers/Kilo/KiloSettingsReader.swift | 61 + .../Providers/Kilo/KiloUsageDataSource.swift | 30 + .../Providers/Kilo/KiloUsageFetcher.swift | 1199 ++++ .../Providers/Kilo/KiloUsageScope.swift | 33 + .../Providers/Kimi/KimiAPIError.swift | 41 + .../Providers/Kimi/KimiCookieHeader.swift | 98 + .../Providers/Kimi/KimiCookieImporter.swift | 184 + .../Providers/Kimi/KimiModels.swift | 118 + .../Kimi/KimiProviderDescriptor.swift | 235 + .../Providers/Kimi/KimiSettingsReader.swift | 203 + .../Providers/Kimi/KimiUsageFetcher.swift | 303 + .../Providers/Kimi/KimiUsageSnapshot.swift | 135 + .../KimiK2/KimiK2ProviderDescriptor.swift | 46 + .../KimiK2/KimiK2SettingsReader.swift | 36 + .../Providers/KimiK2/KimiK2UsageFetcher.swift | 319 + .../Kiro/KiroProviderDescriptor.swift | 62 + .../Providers/Kiro/KiroStatusProbe.swift | 1363 ++++ .../LLMProxy/LLMProxyProviderDescriptor.swift | 68 + .../LLMProxy/LLMProxySettingsReader.swift | 32 + .../LLMProxy/LLMProxyUsageFetcher.swift | 313 + .../LiteLLM/LiteLLMProviderDescriptor.swift | 69 + .../LiteLLM/LiteLLMSettingsReader.swift | 32 + .../LiteLLM/LiteLLMUsageFetcher.swift | 587 ++ .../Providers/Manus/ManusCookieHeader.swift | 42 + .../Providers/Manus/ManusCookieImporter.swift | 188 + .../Manus/ManusProviderDescriptor.swift | 181 + .../Providers/Manus/ManusSettingsReader.swift | 31 + .../Providers/Manus/ManusUsageFetcher.swift | 295 + .../Providers/MiMo/MiMoCookieImporter.swift | 265 + .../MiMo/MiMoLocalUsageFallback.swift | 150 + .../MiMo/MiMoProviderDescriptor.swift | 212 + .../Providers/MiMo/MiMoUsageFetcher.swift | 354 + .../Providers/MiMo/MiMoUsageSnapshot.swift | 98 + .../Providers/MiniMax/MiniMaxAPIRegion.swift | 82 + .../MiniMax/MiniMaxAPISettingsReader.swift | 65 + .../Providers/MiniMax/MiniMaxAuthMode.swift | 48 + .../MiniMax/MiniMaxBillingHistory.swift | 360 + .../MiniMax/MiniMaxCookieHeader.swift | 118 + .../MiniMax/MiniMaxCookieImporter.swift | 190 + .../Providers/MiniMax/MiniMaxDecoding.swift | 46 + .../MiniMax/MiniMaxLocalStorageImporter.swift | 878 +++ .../MiniMax/MiniMaxModelRemains.swift | 68 + .../MiniMax/MiniMaxProviderDescriptor.swift | 365 ++ .../MiniMax/MiniMaxServiceUsage.swift | 225 + .../MiniMax/MiniMaxSettingsReader.swift | 116 + .../MiniMax/MiniMaxSubscriptionMetadata.swift | 274 + .../Providers/MiniMax/MiniMaxUsageError.swift | 21 + .../MiniMaxUsageFetcher+ModelMapping.swift | 62 + .../MiniMax/MiniMaxUsageFetcher.swift | 1667 +++++ .../MiniMaxUsageSnapshot+Metadata.swift | 47 + .../MiniMax/MiniMaxUsageSnapshot.swift | 245 + .../Mistral/MistralCookieImporter.swift | 101 + .../Providers/Mistral/MistralErrors.swift | 35 + .../Providers/Mistral/MistralModels.swift | 297 + .../Mistral/MistralProviderDescriptor.swift | 212 + .../Mistral/MistralUsageFetcher.swift | 570 ++ .../Moonshot/MoonshotProviderDescriptor.swift | 49 + .../Providers/Moonshot/MoonshotRegion.swift | 30 + .../Moonshot/MoonshotSettingsReader.swift | 47 + .../Moonshot/MoonshotUsageFetcher.swift | 161 + .../Ollama/OllamaProviderDescriptor.swift | 123 + .../Providers/Ollama/OllamaUsageFetcher.swift | 844 +++ .../Providers/Ollama/OllamaUsageParser.swift | 187 + .../Ollama/OllamaUsageSnapshot.swift | 79 + .../OpenAIAPICreditBalanceFetcher.swift | 193 + .../OpenAI/OpenAIAPIProviderDescriptor.swift | 133 + .../OpenAI/OpenAIAPISettingsReader.swift | 52 + .../OpenAI/OpenAIAPIUsageFetcher.swift | 462 ++ .../OpenAI/OpenAIAPIUsageResponses.swift | 136 + .../OpenAI/OpenAIAPIUsageSnapshot.swift | 300 + .../OpenCode/OpenCodeCookieImporter.swift | 94 + .../OpenCode/OpenCodeProviderDescriptor.swift | 109 + .../OpenCode/OpenCodeUsageFetcher.swift | 883 +++ .../OpenCode/OpenCodeUsageSnapshot.swift | 59 + .../OpenCode/OpenCodeWebCookieSupport.swift | 57 + .../OpenCodeGoLocalUsageReader.swift | 324 + .../OpenCodeGoProviderDescriptor.swift | 192 + .../OpenCodeGo/OpenCodeGoUsageFetcher.swift | 1027 +++ .../OpenCodeGo/OpenCodeGoUsageSnapshot.swift | 145 + .../OpenCodeGoZenBalanceFetcher.swift | 166 + .../OpenCodeGoZenBalanceParser.swift | 155 + .../OpenRouterProviderDescriptor.swift | 62 + .../OpenRouter/OpenRouterSettingsReader.swift | 48 + .../OpenRouter/OpenRouterUsageStats.swift | 465 ++ .../Perplexity/PerplexityAPIError.swift | 27 + .../Perplexity/PerplexityCookieHeader.swift | 129 + .../Perplexity/PerplexityCookieImporter.swift | 245 + .../Perplexity/PerplexityModels.swift | 29 + .../PerplexityProviderDescriptor.swift | 237 + .../Perplexity/PerplexitySettingsReader.swift | 38 + .../Perplexity/PerplexityUsageFetcher.swift | 71 + .../Perplexity/PerplexityUsageSnapshot.swift | 134 + .../Providers/Poe/PoeProviderDescriptor.swift | 69 + .../Providers/Poe/PoeSettingsReader.swift | 26 + .../Providers/Poe/PoeUsageFetcher.swift | 287 + .../Poe/PoeUsageHistorySnapshot.swift | 161 + .../Providers/Poe/PoeUsageSnapshot.swift | 47 + .../Providers/ProviderBranding.swift | 25 + .../Providers/ProviderCLIConfig.swift | 17 + .../ProviderCandidateRetryRunner.swift | 31 + .../ProviderCookieSettingsResolver.swift | 25 + .../Providers/ProviderCookieSource.swift | 26 + .../Providers/ProviderDescriptor.swift | 169 + .../Providers/ProviderDiagnosticExport.swift | 585 ++ .../ProviderEnvironmentResolver.swift | 64 + .../Providers/ProviderFetchPlan.swift | 291 + .../ProviderInteractionContext.swift | 19 + .../Providers/ProviderSettingsSnapshot.swift | 701 ++ .../Providers/ProviderTokenResolver.swift | 458 ++ .../Providers/ProviderVersionDetector.swift | 119 + .../CodexBarCore/Providers/Providers.swift | 295 + .../Providers/Qoder/QoderCookieImporter.swift | 109 + .../Qoder/QoderProviderDescriptor.swift | 871 +++ .../Providers/Qoder/QoderUsageError.swift | 31 + .../Providers/Qoder/QoderUsageFetcher.swift | 315 + .../Providers/Qoder/QoderUsageSnapshot.swift | 60 + .../Sakana/SakanaProviderDescriptor.swift | 67 + .../Sakana/SakanaSettingsReader.swift | 22 + .../Providers/Sakana/SakanaUsageFetcher.swift | 466 ++ .../StepFun/StepFunProviderDescriptor.swift | 315 + .../StepFun/StepFunSettingsReader.swift | 38 + .../StepFun/StepFunUsageFetcher.swift | 554 ++ .../Sub2API/Sub2APIProviderDescriptor.swift | 63 + .../Sub2API/Sub2APISettingsReader.swift | 53 + .../Sub2API/Sub2APIUsageFetcher.swift | 457 ++ .../SyntheticProviderDescriptor.swift | 44 + .../Synthetic/SyntheticSettingsReader.swift | 38 + .../Synthetic/SyntheticUsageStats.swift | 728 +++ .../T3Chat/T3ChatProviderDescriptor.swift | 84 + .../Providers/T3Chat/T3ChatUsageFetcher.swift | 366 ++ .../T3Chat/T3ChatUsageSnapshot.swift | 180 + .../Venice/VeniceProviderDescriptor.swift | 46 + .../Venice/VeniceSettingsReader.swift | 33 + .../Providers/Venice/VeniceUsageFetcher.swift | 236 + .../VertexAIOAuthCredentials.swift | 327 + .../VertexAITokenRefresher.swift | 128 + .../VertexAIOAuth/VertexAIUsageFetcher.swift | 292 + .../VertexAI/VertexAIProviderDescriptor.swift | 110 + .../Warp/WarpProviderDescriptor.swift | 45 + .../Providers/Warp/WarpSettingsReader.swift | 35 + .../Providers/Warp/WarpUsageFetcher.swift | 465 ++ .../WayfinderProviderDescriptor.swift | 60 + .../Wayfinder/WayfinderSettingsReader.swift | 66 + .../Wayfinder/WayfinderUsageFetcher.swift | 465 ++ .../WindsurfDevinSessionImporter.swift | 308 + .../Windsurf/WindsurfProviderDescriptor.swift | 100 + .../Windsurf/WindsurfStatusProbe.swift | 281 + .../Windsurf/WindsurfUsageDataSource.swift | 27 + .../Windsurf/WindsurfWebFetcher.swift | 679 ++ .../Providers/Zai/ZaiAPIRegion.swift | 53 + .../Providers/Zai/ZaiProviderDescriptor.swift | 51 + .../Providers/Zai/ZaiSettingsReader.swift | 89 + .../Providers/Zai/ZaiUsageStats.swift | 844 +++ .../Providers/Zed/ZedProviderDescriptor.swift | 60 + .../Providers/Zed/ZedStatusProbe.swift | 554 ++ .../CodexBarCore/RemoteSessionFetcher.swift | 191 + .../CodexBarCore/SessionWindowFocuser.swift | 107 + Sources/CodexBarCore/TextParsing.swift | 88 + .../CodexBarCore/TokenAccountSupport.swift | 104 + .../TokenAccountSupportCatalog+Data.swift | 175 + Sources/CodexBarCore/TokenAccounts.swift | 164 + Sources/CodexBarCore/UsageChartScale.swift | 16 + Sources/CodexBarCore/UsageFetcher.swift | 1669 +++++ Sources/CodexBarCore/UsageFormatter.swift | 440 ++ Sources/CodexBarCore/UsagePace.swift | 263 + .../Vendored/CostUsage/CostUsageCache.swift | 162 + .../Vendored/CostUsage/CostUsageJsonl.swift | 109 + .../Vendored/CostUsage/CostUsagePricing.swift | 811 +++ .../CostUsage/CostUsagePricingKey.swift | 76 + .../CostUsageScanner+CacheHelpers.swift | 1524 +++++ .../CostUsage/CostUsageScanner+Claude.swift | 864 +++ .../CostUsageScanner+CodexFastJSON.swift | 271 + .../CostUsageScanner+CodexPriority.swift | 653 ++ ...ostUsageScanner+CodexTruncatedPrefix.swift | 187 + .../CostUsage/CostUsageScanner+Projects.swift | 176 + .../CostUsageScanner+Timestamp.swift | 136 + .../Vendored/CostUsage/CostUsageScanner.swift | 2648 ++++++++ .../Vendored/CostUsage/ModelsDevPricing.swift | 717 ++ .../CodexBarCore/WebKit/WebKitTeardown.swift | 108 + Sources/CodexBarCore/WidgetSnapshot.swift | 243 + .../BurnDownWidgetProvider.swift | 228 + .../CodexBarWidget/BurnDownWidgetViews.swift | 682 ++ .../CodexBarWidget/CodexBarWidgetBundle.swift | 115 + .../CodexBarWidgetProvider.swift | 366 ++ .../CodexBarWidget/CodexBarWidgetViews.swift | 1173 ++++ .../CombinedBurnDownWidgetViews.swift | 480 ++ .../CLIArgumentsTests.swift | 47 + .../ActivityCoverageStatsTests.swift | 96 + .../AdaptiveRefreshPolicyCoreTests.swift | 100 + .../AdaptiveReplayEngineTests.swift | 282 + .../AdaptiveReplayPolicyTests.swift | 77 + .../AdaptiveReplayTraceParserTests.swift | 322 + .../CodingActivityReplayPolicyTests.swift | 141 + .../RecordedScheduleAuditTests.swift | 246 + .../ReplayTraceSegmentationTests.swift | 117 + .../APITokenFetchStrategyTests.swift | 97 + Tests/CodexBarTests/AbacusProviderTests.swift | 289 + .../AdaptiveRefreshHeuristicsTests.swift | 201 + .../AdaptiveRefreshPolicyTests.swift | 61 + .../AdaptiveRefreshTimerTests.swift | 403 ++ .../AdminAPIUsageLocalDaySelectionTests.swift | 196 + .../CodexBarTests/AgentSessionJSONTests.swift | 33 + .../AgentSessionMenuDescriptorTests.swift | 219 + .../AgentSessionParserTests.swift | 74 + ...AlibabaCodingPlanCookieImporterTests.swift | 147 + .../AlibabaCodingPlanMenuCardModelTests.swift | 128 + .../AlibabaCodingPlanProviderTests.swift | 1143 ++++ ...AlibabaTokenPlanDashboardActionTests.swift | 27 + .../AlibabaTokenPlanMenuCardModelTests.swift | 49 + .../AlibabaTokenPlanProviderTests.swift | 926 +++ .../CodexBarTests/AmpUsageFetcherTests.swift | 162 + Tests/CodexBarTests/AmpUsageParserTests.swift | 311 + ...ntigravityCLIHTTPSFetchStrategyTests.swift | 903 +++ .../AntigravityCLISessionTests.swift | 1548 +++++ .../AntigravityCompactFallbackTests.swift | 94 + .../AntigravityDeadlineTests.swift | 199 + ...tigravityLocalSnapshotSelectionTests.swift | 46 + .../AntigravityLoginAlertTests.swift | 52 + .../AntigravityModelLabelTests.swift | 25 + ...ntigravityOAuthCredentialsStoreTests.swift | 159 + .../AntigravityQuotaSummaryTests.swift | 381 ++ .../AntigravityRemoteUsageFetcherTests.swift | 1247 ++++ .../AntigravityStatusProbeTests.swift | 1683 +++++ .../AntigravityWarmAgyReuseTests.swift | 468 ++ Tests/CodexBarTests/AppDelegateTests.swift | 74 + .../CodexBarTests/AppGroupSupportTests.swift | 121 + .../AuggieCLIProbeParseTests.swift | 50 + ...AugmentCLIFetchStrategyFallbackTests.swift | 97 + .../AugmentProviderRuntimeTests.swift | 42 + .../AugmentStatusProbeTests.swift | 323 + .../AzureOpenAIUsageFetcherTests.swift | 282 + .../BatteryDrainDiagnosticTests.swift | 190 + .../BedrockCredentialResolverTests.swift | 139 + .../CodexBarTests/BedrockMenuCardTests.swift | 121 + ...edrockProfileCredentialProviderTests.swift | 93 + .../BedrockSettingsFlowTests.swift | 103 + .../BedrockSettingsReaderTests.swift | 50 + .../BedrockUsageStatsTests.swift | 712 ++ .../BrowserCookieOrderLabelTests.swift | 90 + .../CodexBarTests/BrowserDetectionTests.swift | 658 ++ .../CLIArgumentParsingTests.swift | 129 + Tests/CodexBarTests/CLICacheTests.swift | 32 + .../CodexBarTests/CLICardsRendererTests.swift | 615 ++ .../CodexBarTests/CLIConfigCommandTests.swift | 184 + Tests/CodexBarTests/CLICostTests.swift | 299 + .../CLIDiagnoseCommandTests.swift | 167 + Tests/CodexBarTests/CLIEntryTests.swift | 500 ++ .../CLIOpenAIDashboardCacheTests.swift | 433 ++ Tests/CodexBarTests/CLIOutputTests.swift | 248 + .../CLIProviderSelectionTests.swift | 112 + Tests/CodexBarTests/CLIServeRouterTests.swift | 1520 +++++ .../CodexBarTests/CLIServeTimeoutTests.swift | 826 +++ Tests/CodexBarTests/CLISnapshotTests.swift | 1191 ++++ Tests/CodexBarTests/CLIWebFallbackTests.swift | 231 + .../ChartBarHoverSelectionTests.swift | 49 + Tests/CodexBarTests/ChutesProviderTests.swift | 355 + ...udeAdminAPIInlineDashboardModelTests.swift | 71 + .../ClaudeAdminAPIUsageTests.swift | 227 + .../ClaudeBaselineCharacterizationTests.swift | 410 ++ .../ClaudeCLIAuthStatusProbeTests.swift | 16 + .../ClaudeCLIScopedWeeklyUsageTests.swift | 342 + .../ClaudeCLITimeoutRetryTests.swift | 367 ++ .../ClaudeCredentialRoutingTests.swift | 58 + .../ClaudeDebugDiagnosticsTests.swift | 461 ++ .../ClaudeDirectUsageFallbackTests.swift | 173 + .../ClaudeEducationAvailabilityTests.swift | 200 + .../ClaudeExtraWindowQuotaWarningTests.swift | 277 + .../ClaudeLoginFlowPolicyTests.swift | 48 + .../ClaudeLoginRunnerTests.swift | 107 + ...entialsStoreCLIStorageOwnershipTests.swift | 682 ++ ...entialsStoreIsolatedSecurityCLITests.swift | 124 + ...uthCredentialsStoreMCPOnlyGuardTests.swift | 105 + ...redentialsStoreNeverPromptCacheTests.swift | 693 ++ ...uthCredentialsStorePromptPolicyTests.swift | 742 +++ ...sStoreSecurityCLIFallbackPolicyTests.swift | 109 + ...AuthCredentialsStoreSecurityCLITests.swift | 882 +++ ...ialsStoreTemporaryKeychainCacheTests.swift | 237 + .../ClaudeOAuthCredentialsStoreTests.swift | 917 +++ ...AuthDelegatedRefreshCoordinatorTests.swift | 773 +++ ...deOAuthDelegatedRefreshRecoveryTests.swift | 387 ++ ...eOAuthFetchStrategyAvailabilityTests.swift | 471 ++ ...deOAuthHistoryCredentialRoutingTests.swift | 169 + .../ClaudeOAuthKeychainAccessGateTests.swift | 91 + ...ClaudeOAuthKeychainPreAlertGateTests.swift | 96 + .../ClaudeOAuthRefreshDispositionTests.swift | 33 + .../ClaudeOAuthRefreshFailureGateTests.swift | 307 + Tests/CodexBarTests/ClaudeOAuthTests.swift | 623 ++ .../ClaudePlanResolverTests.swift | 82 + .../ClaudeProbeWorkingDirectoryTests.swift | 156 + .../ClaudeProviderRuntimeTests.swift | 259 + .../ClaudeResetJSONParserTests.swift | 55 + .../ClaudeResetOccurrenceTests.swift | 122 + .../CodexBarTests/ClaudeResilienceTests.swift | 1390 ++++ .../ClaudeScopedWeeklyLimitMapperTests.swift | 65 + .../ClaudeSessionMappingTests.swift | 36 + .../ClaudeSourcePlannerTests.swift | 118 + .../ClaudeSwapAccountProjectionTests.swift | 144 + .../ClaudeSwapAccountReaderTests.swift | 201 + .../ClaudeSwapListParserTests.swift | 254 + .../ClaudeSwapMenuPrecedenceTests.swift | 17 + .../ClaudeSwapSwitchParserTests.swift | 92 + ...yntheticPlaceholderNotificationTests.swift | 257 + ...heticPlaceholderPlanUtilizationTests.swift | 38 + ...sageDelegatedRefreshEnvironmentTests.swift | 53 + Tests/CodexBarTests/ClaudeUsageTests.swift | 1510 +++++ .../ClaudeWebCookieRenewalTests.swift | 491 ++ .../ClaudeWebEnterpriseUsageTests.swift | 43 + .../ClaudeWebFetchDeadlineTests.swift | 459 ++ .../ClaudeWebRecoveryMenuTests.swift | 176 + .../ClaudeWebRefreshResilienceTests.swift | 175 + .../ClaudeWebUsageExtraWindowTests.swift | 83 + .../ClawRouterUsageFetcherTests.swift | 274 + .../ClickToCopyOverlayTests.swift | 50 + .../CodebuffSettingsReaderTests.swift | 110 + .../CodebuffUsageFetcherTests.swift | 492 ++ ...odexAccountAuthFingerprintApplyTests.swift | 1499 +++++ .../CodexAccountCompositeGuardTests.swift | 145 + ...AccountEmailOnlyHistoryBackfillTests.swift | 119 + ...ccountFingerprintReconciliationTests.swift | 102 + ...CodexAccountMenuDisplaySnapshotTests.swift | 424 ++ .../CodexAccountPromotionExecutionTests.swift | 310 + .../CodexAccountPromotionPlanningTests.swift | 227 + ...odexAccountPromotionPreparationTests.swift | 118 + .../CodexAccountPromotionServiceTests.swift | 734 +++ .../CodexAccountPromotionTestSupport.swift | 492 ++ ...tProviderIdentityReconciliationTests.swift | 48 + .../CodexAccountReconciliationTests.swift | 946 +++ .../CodexAccountRefreshProjectionTests.swift | 282 + ...odexAccountScopedRefreshCreditsTests.swift | 93 + ...ntScopedRefreshDashboardCleanupTests.swift | 273 + ...CodexAccountScopedRefreshTestSupport.swift | 728 +++ .../CodexAccountScopedRefreshTests.swift | 934 +++ ...exAccountVisibleHistoryBackfillTests.swift | 1560 +++++ .../CodexAccountsSectionStateTests.swift | 195 + .../CodexAccountsSettingsSectionTests.swift | 457 ++ .../CodexActiveSourceConfigTests.swift | 242 + .../CodexAdditionalRateLimitsTests.swift | 311 + ...odexBackgroundRefreshCoalescingTests.swift | 1579 +++++ .../CodexBarConfigMigratorTests.swift | 189 + .../CodexBarWidgetProviderTests.swift | 973 +++ .../CodexBaselineCharacterizationTests.swift | 395 ++ .../CodexCLILaunchGateTests.swift | 40 + .../CodexCLIWindowNormalizationTests.swift | 226 + ...CodexCombinedMetricHighestUsageTests.swift | 317 + ...sumerProjectionCharacterizationTests.swift | 302 + .../CodexConsumerProjectionTests.swift | 502 ++ .../CodexDashboardAuthorityTests.swift | 475 ++ ...CodexDashboardWeeklyPublicationTests.swift | 84 + ...dexDashboardWorkedExampleParityTests.swift | 598 ++ .../CodexHistoryOwnershipTests.swift | 110 + .../CodexIdentityResolverTests.swift | 43 + .../CodexLegacyWidgetSnapshotTests.swift | 54 + .../CodexLimitResetOwnerKeyTests.swift | 215 + .../CodexBarTests/CodexLoginRunnerTests.swift | 88 + .../CodexManagedOpenAIWebRefreshTests.swift | 972 +++ .../CodexManagedOpenAIWebTestSupport.swift | 207 + .../CodexManagedOpenAIWebTests.swift | 881 +++ .../CodexManagedRoutingTests.swift | 851 +++ ...AuthCredentialsStorePermissionsTests.swift | 67 + .../CodexOAuthCreditLimitTests.swift | 357 + .../CodexOAuthRequestTests.swift | 242 + .../CodexOAuthResetCreditFetchTests.swift | 161 + Tests/CodexBarTests/CodexOAuthTests.swift | 811 +++ .../CodexOpenAIWorkspaceResolverTests.swift | 171 + .../CodexPlanFormattingTests.swift | 40 + ...dexPresentationCharacterizationTests.swift | 530 ++ .../CodexProfileHomeAccountTests.swift | 398 ++ .../CodexProviderSettingsBuilderTests.swift | 200 + .../CodexRateLimitResetCreditsTests.swift | 253 + .../CodexResetBackfillSemanticsTests.swift | 213 + .../CodexResetCreditExpiryNotifierTests.swift | 107 + .../CodexResetCreditOutcomeTests.swift | 271 + .../CodexResetCreditsMenuCardTests.swift | 178 + .../CodexSessionQuotaFalseRestoreTests.swift | 1004 +++ .../CodexSessionRolloutTests.swift | 65 + .../CodexSystemAccountObserverTests.swift | 132 + .../CodexSystemPromotionUITests.swift | 153 + .../CodexUsageFetcherFallbackTests.swift | 508 ++ .../CodexUsageOwnerRaceTests.swift | 465 ++ .../CodexUserFacingErrorTests.swift | 294 + ...ccountProjectionRuntimeIdentityTests.swift | 31 + .../CodexVisibleAccountTests.swift | 39 + ...exWebDashboardStrategyAuthorityTests.swift | 436 ++ .../CodexWeeklyCapSurfaceTests.swift | 219 + .../CodexWeeklyResetConfirmationTests.swift | 405 ++ ...CodexWeeklyResetFailureBaselineTests.swift | 90 + ...CodexWeeklyResetOwnerTransitionTests.swift | 130 + .../CodexWeeklyResetPublicationTests.swift | 933 +++ Tests/CodexBarTests/CodexbarTests.swift | 892 +++ .../CommandCodeProviderTests.swift | 44 + .../CommandCodeQuotaTransitionTests.swift | 175 + .../CommandCodeUsageFetcherTests.swift | 416 ++ .../CodexBarTests/ConfigValidationTests.swift | 427 ++ .../ConfigurationDocsProviderIDTests.swift | 38 + ...eHeaderCacheConditionalMutationTests.swift | 101 + .../CookieHeaderCacheTests.swift | 931 +++ .../CookieHeaderNormalizerTests.swift | 14 + .../CopilotBudgetCookieRoutingTests.swift | 44 + .../CopilotBudgetWebFetcherTests.swift | 721 ++ .../CopilotDeviceFlowTests.swift | 91 + .../CopilotMenuCardModelTests.swift | 44 + .../CopilotMultiAccountTests.swift | 409 ++ .../CopilotUsageFetcherTests.swift | 200 + .../CopilotUsageModelsTests.swift | 577 ++ .../CostHistoryChartMenuViewTests.swift | 853 +++ Tests/CodexBarTests/CostUsageCacheTests.swift | 163 + .../CostUsageCancellationTests.swift | 147 + .../CostUsageDailyReportMergeTests.swift | 166 + .../CostUsageDecodingTests.swift | 503 ++ .../CostUsageFetcherCacheSnapshotTests.swift | 498 ++ .../CodexBarTests/CostUsageFetcherTests.swift | 870 +++ ...UsageFetcherUnknownModelPricingTests.swift | 291 + .../CostUsageJsonlPerformanceTests.swift | 207 + .../CostUsageJsonlScannerTests.swift | 68 + .../CostUsageJsonlShapeBenchmarkTests.swift | 407 ++ .../CostUsagePerformanceGateTests.swift | 343 + .../CodexBarTests/CostUsagePricingTests.swift | 1115 ++++ .../CostUsageScanExecutorTests.swift | 156 + .../CostUsageScannerBreakdownTests.swift | 5800 +++++++++++++++++ .../CostUsageScannerClaudeDesktopTests.swift | 161 + .../CostUsageScannerClaudeFableTests.swift | 457 ++ ...ostUsageScannerClaudeRegressionTests.swift | 778 +++ .../CostUsageScannerCodexPriorityTests.swift | 692 ++ .../CostUsageScannerPriorityTests.swift | 763 +++ .../CodexBarTests/CostUsageScannerTests.swift | 1078 +++ ...tUsageTokenSnapshotDaySelectionTests.swift | 121 + .../CostUsageWindowSummaryTests.swift | 80 + Tests/CodexBarTests/CrofMenuCardTests.swift | 44 + .../CrofProviderImplementationTests.swift | 52 + .../CodexBarTests/CrofUsageFetcherTests.swift | 236 + .../CrossModelUsageStatsTests.swift | 641 ++ .../CursorEnterpriseUsageTests.swift | 258 + .../CursorLegacyRequestProjectionTests.swift | 59 + .../CursorLoginRunnerTests.swift | 115 + .../CursorMenuCardModelTests.swift | 191 + .../CursorStatusProbeTests.swift | 1499 +++++ .../DeepSeekSettingsReaderTests.swift | 73 + .../DeepSeekUsageCostParserTests.swift | 855 +++ .../DeepSeekUsageFetcherTests.swift | 614 ++ .../CodexBarTests/DeepgramProviderTests.swift | 252 + ...erredMenuInteractionRefreshTailTests.swift | 177 + .../DevinUsageFetcherTests.swift | 507 ++ .../DocumentationLinkTests.swift | 379 ++ .../DoubaoMenuCardModelTests.swift | 97 + Tests/CodexBarTests/DoubaoProviderTests.swift | 151 + .../DoubaoUsageFetcherTests.swift | 434 ++ .../ElevenLabsUsageFetcherTests.swift | 178 + .../FactoryAPIKeyUsageTests.swift | 461 ++ .../FactoryManualCredentialTests.swift | 135 + .../FactoryProviderImplementationTests.swift | 82 + .../FactoryStatusProbeFetchTests.swift | 803 +++ .../FactoryStatusProbeTests.swift | 232 + .../archived-fork-33ce-3869/ORACLE.md | 46 + .../codex-home/archived_sessions/child.jsonl | 160 + .../codex-home/archived_sessions/parent.jsonl | 137 + .../archived-fork-33ce-3869/manifest.json | 41 + .../codex-home/archived_sessions/child.jsonl | 4 + .../sessions/2026/07/11/parent.jsonl | 3 + .../Issue2037/harness-smoke/manifest.json | 28 + .../Issue2037/live-fork-4d90-52bf/ORACLE.md | 37 + .../codex-home/archived_sessions/child.jsonl | 198 + .../codex-home/archived_sessions/parent.jsonl | 182 + .../live-fork-4d90-52bf/manifest.json | 51 + .../missing-parent-siblings/ORACLE.md | 30 + .../archived_sessions/sibling-a.jsonl | 160 + .../archived_sessions/sibling-b.jsonl | 140 + .../missing-parent-siblings/manifest.json | 51 + .../Providers/Claude/weekly-limit.json | 8 + .../MiniMax/token-plan-missing-reset.json | 17 + .../Providers/MiniMax/token-plan-normal.json | 22 + .../Fixtures/Providers/OpenAI/pro-normal.html | 16 + .../Fixtures/agent-session-rollout.jsonl | 2 + .../Fixtures/agent-sessions-lsof.txt | 4 + .../Fixtures/agent-sessions-ps.txt | 9 + .../Fixtures/agent-sessions-tailscale.json | 10 + .../codex-historical-usage-real-legacy.jsonl | 6 + ...codex-plan-utilization-real-migration.json | 211 + .../Fixtures/models-dev-subset.json | 89 + .../CodexBarTests/GeminiAPITestHelpers.swift | 141 + .../GeminiConsumerTierMigrationTests.swift | 163 + .../CodexBarTests/GeminiLoginAlertTests.swift | 27 + Tests/CodexBarTests/GeminiMenuCardTests.swift | 95 + .../GeminiOAuthConfigTests.swift | 26 + .../GeminiOAuthRecoveryAPITests.swift | 249 + .../GeminiPrimaryWindowTests.swift | 41 + ...GeminiProviderMigrationSettingsTests.swift | 134 + .../GeminiSourceLabelTests.swift | 9 + .../GeminiStatusProbeAPITests.swift | 848 +++ .../GeminiStatusProbePlanTests.swift | 557 ++ .../GeminiStatusProbeTests.swift | 270 + .../CodexBarTests/GeminiTestEnvironment.swift | 371 ++ .../GoogleWorkspaceStatusNetworkTests.swift | 70 + .../GoogleWorkspaceStatusTests.swift | 72 + Tests/CodexBarTests/GrokAuthTests.swift | 188 + .../GrokBillingResponseTests.swift | 69 + .../GrokWebBillingFetcherTests.swift | 883 +++ .../CodexBarTests/GroqUsageFetcherTests.swift | 41 + ...ricalUsagePaceBackfillAuthorityTests.swift | 511 ++ .../HistoricalUsagePaceOwnershipTests.swift | 444 ++ .../HistoricalUsagePaceTestSupport.swift | 318 + .../HistoricalUsagePaceTests.swift | 823 +++ .../IconRendererHideCrittersTests.swift | 79 + ...InlineCostHistoryDashboardLabelTests.swift | 271 + .../InlineUsageDashboardBarColorTests.swift | 88 + Tests/CodexBarTests/InstallOriginTests.swift | 17 + .../Issue2037FixtureHarnessTests.swift | 30 + .../Issue2037FixtureSupport.swift | 359 + .../Issue2037ProvenanceFixtureTests.swift | 163 + .../Issue2037ScannerIntegrationTests.swift | 181 + .../JetBrainsIDEDetectorTests.swift | 15 + .../JetBrainsStatusProbeTests.swift | 359 + .../KeyboardShortcutsBundleTests.swift | 19 + .../KeychainCacheStoreTests.swift | 217 + .../KeychainMigrationTests.swift | 24 + .../KeychainNoUIQueryTests.swift | 97 + .../KeychainPromptCoordinatorTests.swift | 68 + .../KeychainPromptSafetyAuditTests.swift | 248 + .../KiloBearerTokenResolverTests.swift | 124 + .../CodexBarTests/KiloOrganizationTests.swift | 72 + .../KiloSettingsReaderTests.swift | 40 + .../KiloSettingsStoreTests.swift | 57 + .../CodexBarTests/KiloUsageFetcherTests.swift | 789 +++ .../KimiK2SettingsReaderTests.swift | 26 + .../KimiK2TokenStoreTestSupport.swift | 9 + .../KimiK2UsageFetcherTests.swift | 286 + Tests/CodexBarTests/KimiProviderTests.swift | 1198 ++++ .../KiroMenuCardModelTests.swift | 108 + .../KiroStatusProbeTestSupport.swift | 83 + .../CodexBarTests/KiroStatusProbeTests.swift | 1683 +++++ .../KiroTransportRaceTests.swift | 119 + .../LLMProxyUsageFetcherTests.swift | 120 + .../LaunchAtLoginManagerTests.swift | 126 + .../LiteLLMMenuCardModelTests.swift | 235 + .../LiteLLMUsageFetcherTests.swift | 364 ++ Tests/CodexBarTests/LiveAccountTests.swift | 23 + Tests/CodexBarTests/LoadingPatternTests.swift | 34 + .../LocalizationBundleCacheTests.swift | 71 + .../LocalizationBundleTests.swift | 125 + .../LocalizationLanguageCatalogTests.swift | 617 ++ .../LoginNotificationLogicTests.swift | 19 + .../MainThreadHangWatchdogTests.swift | 196 + .../ManagedCodexAccountCoordinatorTests.swift | 157 + .../ManagedCodexAccountServiceTests.swift | 958 +++ .../ManagedCodexAccountStoreTests.swift | 542 ++ .../ManusCookieHeaderTests.swift | 48 + Tests/CodexBarTests/ManusProviderTests.swift | 310 + .../MemoryPressureCacheTrimTests.swift | 251 + .../MenuBarCountdownRefreshTests.swift | 505 ++ .../MenuBarMetricWindowResolverTests.swift | 539 ++ .../CodexBarTests/MenuBarPaceTextTests.swift | 32 + .../MenuBarResetTimeDisplayTests.swift | 365 ++ .../MenuBarSmartResetIntegrationTests.swift | 63 + .../MenuBarVisibilityWatcherTests.swift | 630 ++ .../MenuCardAntigravityTests.swift | 524 ++ .../MenuCardClaudeSwapAccountTests.swift | 76 + .../MenuCardCostComparisonTests.swift | 113 + .../CodexBarTests/MenuCardCostHintTests.swift | 96 + .../CodexBarTests/MenuCardDeepSeekTests.swift | 146 + .../MenuCardHeightFingerprintTests.swift | 92 + .../CodexBarTests/MenuCardKiloPassTests.swift | 56 + ...MenuCardModelCodexDegradedQuotaTests.swift | 247 + .../MenuCardModelCodexProjectionTests.swift | 881 +++ Tests/CodexBarTests/MenuCardModelTests.swift | 1571 +++++ .../MenuCardOptionalUsageModelTests.swift | 97 + .../MenuCardOverrideIsolationTests.swift | 179 + .../MenuCardProviderRegressionTests.swift | 157 + .../MenuCardQuotaWarningMarkerTests.swift | 203 + .../CodexBarTests/MenuCardRefreshTests.swift | 74 + .../CodexBarTests/MenuCardSubtitleTests.swift | 94 + .../MenuCardTestDateFormatting.swift | 9 + .../MenuCardViewRecyclingTests.swift | 755 +++ .../MenuCardWorkdayPaceTests.swift | 79 + .../MenuDescriptorAntigravityTests.swift | 158 + ...uDescriptorCodexManagedFallbackTests.swift | 181 + .../MenuDescriptorCrossModelTests.swift | 193 + .../MenuDescriptorKiloTests.swift | 167 + .../MenuDescriptorKimiK2Tests.swift | 36 + .../MenuDescriptorOpenAIAPITests.swift | 98 + .../MenuDescriptorPoeTests.swift | 139 + .../MenuDescriptorSakanaTests.swift | 128 + .../MenuDescriptorSub2APITests.swift | 69 + .../MenuOpenRefreshPlanTests.swift | 62 + .../MenuSessionCoordinatorTests.swift | 159 + .../MiMoLocalUsageFallbackTests.swift | 192 + Tests/CodexBarTests/MiMoProviderTests.swift | 1230 ++++ .../CodexBarTests/MiMoUsageScriptTests.swift | 195 + .../MiniMaxAPITokenFetchTests.swift | 233 + ...MiniMaxCurrentTokenPlanResponseTests.swift | 218 + .../MiniMaxLocalStorageImporterTests.swift | 70 + .../MiniMaxLogRedactorTests.swift | 105 + .../MiniMaxMenuCardBillingTests.swift | 103 + .../MiniMaxMenuCardModelPlanTests.swift | 288 + .../CodexBarTests/MiniMaxProviderTests.swift | 1242 ++++ .../MiniMaxTokenPlanChangeTests.swift | 791 +++ .../MistralMenuCardModelTests.swift | 168 + .../MistralUsageParserTests.swift | 614 ++ .../CodexBarTests/MistralVibeUsageTests.swift | 285 + .../CodexBarTests/ModelsDevPricingTests.swift | 1367 ++++ .../MoonshotSettingsReaderTests.swift | 68 + .../MoonshotUsageFetcherTests.swift | 220 + .../OllamaUsageFetcherRetryMappingTests.swift | 471 ++ .../OllamaUsageFetcherTests.swift | 290 + .../OllamaUsageParserTests.swift | 208 + .../OpenAIAPICreditBalanceTests.swift | 243 + .../OpenAIAPIMenuCardModelTests.swift | 173 + .../OpenAIAPIProjectScopeTests.swift | 334 + .../OpenAIAPIStatusMenuTests.swift | 225 + .../OpenAIAPIUsageFetcherTests.swift | 727 +++ ...IDashboardBrowserCookieImporterTests.swift | 375 ++ ...enAIDashboardFetcherCreditsWaitTests.swift | 350 + .../OpenAIDashboardModelsTests.swift | 217 + ...enAIDashboardNavigationDelegateTests.swift | 192 + .../OpenAIDashboardOffscreenHostTests.swift | 26 + .../OpenAIDashboardParserTests.swift | 250 + .../OpenAIDashboardScrapeScriptTests.swift | 236 + .../OpenAIDashboardSparkTests.swift | 232 + .../OpenAIDashboardWebViewCacheTests.swift | 628 ++ .../OpenAIWebAccountSwitchTests.swift | 96 + .../OpenAIWebRefreshGateTests.swift | 188 + .../OpenCodeGoLocalUsageReaderTests.swift | 299 + .../OpenCodeGoMenuCardModelTests.swift | 184 + .../OpenCodeGoProviderStrategyTests.swift | 64 + .../OpenCodeGoUsageFetcherErrorTests.swift | 873 +++ .../OpenCodeGoUsageParserTests.swift | 566 ++ .../OpenCodeUsageFetcherErrorTests.swift | 308 + .../OpenCodeUsageParserTests.swift | 278 + .../OpenCodeWebCookieSupportTests.swift | 19 + .../OpenRouterUsageStatsTests.swift | 294 + Tests/CodexBarTests/PathBuilderTests.swift | 955 +++ .../PerplexityCookieCacheTests.swift | 203 + .../PerplexityCookieHeaderTests.swift | 89 + .../PerplexityProviderTests.swift | 397 ++ .../PerplexitySettingsReaderTests.swift | 38 + .../PerplexityUsageFetcherTests.swift | 362 + .../PersistentRefreshAccessibilityTests.swift | 31 + .../PiSessionCostScannerTests.swift | 1212 ++++ ...UtilizationHistoryChartMenuViewTests.swift | 88 + .../PoeCurrentDayPresentationTests.swift | 36 + .../PoeProviderDescriptorTests.swift | 12 + .../PoeSettingsReaderTests.swift | 11 + .../CodexBarTests/PoeUsageFetcherTests.swift | 251 + .../PoeUsageHistorySnapshotTests.swift | 486 ++ .../PopupLocalizationTests.swift | 193 + .../PredictivePaceWarningTests.swift | 721 ++ .../PreferencesPaneSmokeTests.swift | 575 ++ .../PreferencesSelectionTests.swift | 45 + .../ProviderCandidateRetryRunnerTests.swift | 119 + .../ProviderChangelogLinkTests.swift | 79 + .../ProviderConfigEnvironmentTests.swift | 743 +++ .../ProviderCookieSettingsResolverTests.swift | 91 + .../ProviderDetectionPolicyTests.swift | 44 + .../ProviderDiagnosticExportTests.swift | 612 ++ ...roviderEndpointOverrideSecurityTests.swift | 232 + .../ProviderEnvironmentResolverTests.swift | 91 + .../ProviderHTTPClientTests.swift | 273 + .../ProviderHTTPTransportStub.swift | 20 + .../ProviderIconResourcesTests.swift | 143 + ...erLabelMetadataCharacterizationTests.swift | 63 + .../ProviderMetadataStatusLinkTests.swift | 26 + .../ProviderPlanLineParsingTests.swift | 72 + .../ProviderQuotaFixtureContractTests.swift | 79 + .../ProviderRefreshCoordinatorTests.swift | 160 + .../CodexBarTests/ProviderRegistryTests.swift | 48 + .../ProviderSettingsDescriptorTests.swift | 409 ++ .../ProviderStorageFootprintTests.swift | 552 ++ .../ProviderSwitcherEventPeekGateTests.swift | 149 + .../ProviderToggleStoreTests.swift | 50 + .../ProviderTokenResolverTests.swift | 154 + .../ProviderVersionDetectorTests.swift | 70 + .../ProvidersPaneCoverageTests.swift | 699 ++ .../QoderDashboardActionTests.swift | 94 + .../QoderProviderBehaviorTests.swift | 1055 +++ Tests/CodexBarTests/QoderProviderTests.swift | 62 + .../QoderUsageFetcherTests.swift | 299 + ...taWarningAlertPresentationStateTests.swift | 26 + .../QuotaWarningNotificationLogicTests.swift | 188 + .../RateWindowSyntheticPlaceholderTests.swift | 141 + .../RequiredRefreshCoalescingTests.swift | 555 ++ .../ResetTimeBackfillTests.swift | 175 + .../SakanaUsageFetcherTests.swift | 533 ++ .../SessionQuotaNotificationLogicTests.swift | 65 + .../SettingsStoreAdditionalTests.swift | 237 + .../SettingsStoreCoverageTests.swift | 875 +++ Tests/CodexBarTests/SettingsStoreTests.swift | 1762 +++++ .../SettingsWindowAppearanceTests.swift | 180 + .../ShellCommandForegroundTests.swift | 14 + .../SpawnedProcessGroupTests.swift | 611 ++ ...StatusItemAnimationCodexCreditsTests.swift | 51 + .../StatusItemAnimationSignatureTests.swift | 751 +++ .../StatusItemAnimationTests.swift | 1754 +++++ .../StatusItemBalanceDisplayTests.swift | 759 +++ ...usItemCombinedMetricPlaceholderTests.swift | 184 + .../StatusItemControllerMenuTests.swift | 206 + .../StatusItemControllerShutdownTests.swift | 302 + ...tusItemControllerSplitLifecycleTests.swift | 565 ++ .../StatusItemExtraUsageMetricTests.swift | 269 + ...tusItemIconObservationSignatureTests.swift | 364 ++ .../StatusItemPurchaseURLTests.swift | 63 + .../StatusItemQuotaWarningFlashTests.swift | 98 + .../StatusMenuAppearanceTests.swift | 60 + .../StatusMenuClosedPreparationTests.swift | 307 + ...atusMenuCodexCostHistoryRefreshTests.swift | 274 + ...usMenuCodexSwitcherPresentationTests.swift | 486 ++ .../StatusMenuCodexSwitcherTests.swift | 1414 ++++ .../StatusMenuCostMenuCardTests.swift | 183 + ...atusMenuCostSummaryDisplayStyleTests.swift | 76 + .../StatusMenuHeightCacheTests.swift | 302 + .../StatusMenuHighlightTests.swift | 554 ++ .../StatusMenuHostedSubmenuRefreshTests.swift | 700 ++ .../StatusMenuInstantOpenTests.swift | 1702 +++++ .../StatusMenuLocalizationRefreshTests.swift | 134 + ...StatusMenuMergedOverviewRefreshTests.swift | 91 + .../StatusMenuNativeSectionSpacingTests.swift | 178 + .../StatusMenuOpenRefreshTests.swift | 1743 +++++ .../StatusMenuOverviewClickTests.swift | 300 + .../StatusMenuOverviewScrollTests.swift | 203 + .../StatusMenuOverviewSubmenuTests.swift | 273 + .../StatusMenuPersistentRefreshTests.swift | 1575 +++++ .../StatusMenuReadinessBaselineTests.swift | 645 ++ .../StatusMenuScopedCodexRefreshTests.swift | 79 + .../StatusMenuSwitcherClickTests.swift | 917 +++ .../StatusMenuSwitcherLayoutTests.swift | 129 + .../StatusMenuSwitcherRefreshTests.swift | 818 +++ .../StatusMenuSwitcherTrackingTests.swift | 209 + Tests/CodexBarTests/StatusMenuTests.swift | 1707 +++++ .../StatusMenuTokenAccountSwitcherTests.swift | 1064 +++ .../StatusMenuUsageDisplayTests.swift | 87 + .../StatusMenuViewportRestoreTests.swift | 1535 +++++ Tests/CodexBarTests/StatusProbeTests.swift | 842 +++ .../StatuspageSummaryTests.swift | 208 + .../StepFunUsageFetcherTests.swift | 799 +++ .../StorageBreakdownSegmentTests.swift | 112 + .../CodexBarTests/Sub2APICLIOutputTests.swift | 52 + .../Sub2APIMenuCardModelTests.swift | 154 + .../Sub2APIUsageFetcherTests.swift | 345 + .../CodexBarTests/SubprocessRunnerTests.swift | 333 + .../SubscriptionDetectionTests.swift | 70 + .../SyntheticMenuCardTests.swift | 107 + .../SyntheticProviderTests.swift | 227 + .../T3ChatUsageFetcherTests.swift | 295 + .../CodexBarTests/TTYCommandRunnerTests.swift | 484 ++ Tests/CodexBarTests/TTYIntegrationTests.swift | 152 + .../CodexBarTests/TailscaleSessionTests.swift | 29 + Tests/CodexBarTests/TerminalAppTests.swift | 130 + Tests/CodexBarTests/TestProcessCleanup.swift | 76 + .../TestProcessCleanupTests.swift | 37 + Tests/CodexBarTests/TestStores.swift | 236 + Tests/CodexBarTests/TextParsingTests.swift | 30 + ...kenAccountEnvironmentPrecedenceTests.swift | 1237 ++++ .../TokenAccountStoreTests.swift | 56 + Tests/CodexBarTests/UpdateChannelTests.swift | 22 + .../UsageBreakdownChartMenuViewTests.swift | 30 + .../CodexBarTests/UsageChartScaleTests.swift | 23 + Tests/CodexBarTests/UsageFormatterTests.swift | 513 ++ .../UsageMenuCardLayoutTests.swift | 116 + Tests/CodexBarTests/UsagePaceTests.swift | 592 ++ Tests/CodexBarTests/UsagePaceTextTests.swift | 414 ++ .../UsageStoreCachedTokenHydrationTests.swift | 259 + .../UsageStoreCoverageTests.swift | 1022 +++ ...ageStoreDisabledProviderCleanupTests.swift | 762 +++ .../UsageStoreHighestUsageTests.swift | 992 +++ .../UsageStoreManualTokenRefreshTests.swift | 374 ++ .../UsageStorePathDebugTests.swift | 78 + ...geStorePlanUtilizationAsyncLoadTests.swift | 417 ++ ...StorePlanUtilizationCelebrationTests.swift | 1647 +++++ ...ilizationClaudeIdentityBoundaryTests.swift | 305 + ...rePlanUtilizationClaudeIdentityTests.swift | 905 +++ ...rePlanUtilizationCodexOwnershipTests.swift | 582 ++ ...nUtilizationCodexResetOwnershipTests.swift | 153 + ...torePlanUtilizationDerivedChartTests.swift | 55 + ...orePlanUtilizationExactFitResetTests.swift | 227 + ...ePlanUtilizationResetCoalescingTests.swift | 279 + .../UsageStorePlanUtilizationTests.swift | 1203 ++++ .../UsageStoreResetBoundaryRefreshTests.swift | 316 + ...sageStoreSessionQuotaTransitionTests.swift | 875 +++ .../UsageStoreTimeoutTests.swift | 61 + .../UsageStoreTokenRetryPolicyTests.swift | 12 + .../UsageStoreWidgetSnapshotTests.swift | 546 ++ .../UserFacingLocalizationCoverageTests.swift | 113 + .../VeniceSettingsReaderTests.swift | 73 + .../VeniceUsageFetcherTests.swift | 297 + .../VertexAIOAuthCredentialsTests.swift | 82 + .../CodexBarTests/WarpUsageFetcherTests.swift | 230 + .../WayfinderProviderTests.swift | 38 + Tests/CodexBarTests/WebKitTeardownTests.swift | 24 + Tests/CodexBarTests/WidgetSnapshotTests.swift | 255 + .../WindsurfDevinSessionImporterTests.swift | 169 + .../CodexBarTests/WindsurfProviderTests.swift | 55 + .../WindsurfStatusProbeTests.swift | 330 + .../WindsurfWebFetcherTests.swift | 565 ++ .../CodexBarTests/ZaiAvailabilityTests.swift | 65 + Tests/CodexBarTests/ZaiMenuCardTests.swift | 70 + Tests/CodexBarTests/ZaiProviderTests.swift | 1021 +++ .../ZaiTokenAccountEnvironmentTests.swift | 166 + .../ZaiTokenStoreTestSupport.swift | 17 + Tests/CodexBarTests/ZedStatusProbeTests.swift | 314 + .../AntigravityCLIStrategyLinuxTests.swift | 86 + ...AntigravityProcessLauncherLinuxTests.swift | 72 + .../AzureEndpointOverrideSecurityTests.swift | 71 + TestsLinux/CLICardsRendererTests.swift | 615 ++ TestsLinux/CLITerminalCapabilitiesTests.swift | 49 + ...audeOAuthCredentialHistoryLinuxTests.swift | 27 + ...laudeOAuthDelegatedRefreshLinuxTests.swift | 167 + .../CodexBarLoggingPerformanceTests.swift | 82 + ...CodexOAuthCredentialsStoreLinuxTests.swift | 31 + .../CostUsageScanExecutorLinuxTests.swift | 29 + TestsLinux/CursorLinuxTests.swift | 66 + TestsLinux/JetBrainsParserLinuxTests.swift | 190 + .../OpenAIDashboardParserLinuxTests.swift | 60 + TestsLinux/OpenCodeGoLinuxTests.swift | 74 + TestsLinux/PlatformGatingTests.swift | 257 + ...cNetTCPListeningPortParserLinuxTests.swift | 111 + ...erEndpointOverrideSecurityLinuxTests.swift | 137 + .../SettingsReaderQuoteUnwrapTrapTests.swift | 75 + .../ShellCommandSessionLinuxTests.swift | 22 + TestsLinux/UsageFormatterLinuxTests.swift | 15 + TestsLinux/WayfinderProviderLinuxTests.swift | 447 ++ VISION.md | 20 + .../project.pbxproj | 362 + .../contents.xcworkspacedata | 7 + .../xcshareddata/swiftpm/Package.resolved | 77 + WidgetExtension/Info.plist | 33 + WidgetExtension/project.yml | 42 + appcast.xml | 185 + bin/docs-list | 5 + bin/install-codexbar-cli.sh | 29 + docs/.nojekyll | 1 + docs/CNAME | 1 + docs/DEVELOPMENT.md | 218 + docs/DEVELOPMENT_SETUP.md | 179 + docs/FORK_QUICK_START.md | 257 + docs/FORK_ROADMAP.md | 232 + docs/FORK_SETUP.md | 334 + docs/ISSUE_LABELING.md | 199 + docs/KEYCHAIN_FIX.md | 134 + docs/QUOTIO_ANALYSIS.md | 352 + docs/RELEASING.md | 119 + docs/TODO.md | 10 + docs/UPSTREAM_STRATEGY.md | 638 ++ docs/abacus.md | 67 + docs/agent-sessions-design.md | 98 + docs/alibaba-coding-plan.md | 75 + docs/alibaba-token-plan.md | 61 + docs/amp.md | 60 + docs/antigravity.md | 231 + docs/architecture.md | 30 + docs/augment.md | 183 + docs/azure-openai.md | 106 + docs/bedrock.md | 121 + docs/chutes.md | 52 + docs/claude-comparison-since-0.18.0beta2.md | 216 + docs/claude-multi-account-and-status-items.md | 183 + docs/claude.md | 203 + docs/clawrouter.md | 51 + docs/cli-configuration.md | 115 + docs/cli.md | 263 + docs/codebuff.md | 72 + docs/codex-oauth.md | 635 ++ docs/codex.md | 171 + docs/codexbar.png | Bin 0 -> 306204 bytes docs/command-code.md | 51 + docs/configuration.md | 208 + docs/copilot.md | 69 + docs/cost-window-comparisons.md | 35 + docs/crof.md | 42 + docs/crossmodel.md | 69 + docs/cursor.md | 86 + docs/custom-provider-design.md | 257 + docs/deepgram.md | 111 + docs/deepseek.md | 39 + docs/devin.md | 43 + docs/doubao.md | 22 + docs/elevenlabs.md | 63 + docs/factory.md | 147 + docs/features/feature-credits.webp | Bin 0 -> 246520 bytes docs/features/feature-resets.webp | Bin 0 -> 494596 bytes docs/features/feature-status.webp | Bin 0 -> 71798 bytes docs/gemini.md | 101 + docs/grok.md | 151 + docs/groqcloud.md | 31 + docs/hero-mockup.svg | 41 + docs/icon.md | 37 + docs/icon.png | Bin 0 -> 303343 bytes docs/images/apple.svg | 1 + docs/images/menubar/github-circle-fill.png | Bin 0 -> 6742 bytes docs/images/menubar/openclaw-menubar.svg | 11 + docs/images/menubar/person-circle.png | Bin 0 -> 650 bytes docs/images/menubar/personalhotspot.png | Bin 0 -> 654 bytes docs/images/menubar/wifi.png | Bin 0 -> 516 bytes docs/index.html | 775 +++ .../issue-2037-fork-family-provenance-spec.md | 609 ++ docs/issue-2037-p0-local-corpus-findings.md | 212 + docs/issue-2037-ultra-fork-overcount-spec.md | 246 + docs/jetbrains.md | 70 + docs/keychain-allow.png | Bin 0 -> 164096 bytes docs/keychain-prompts.md | 100 + docs/kilo.md | 54 + docs/kimi-k2.md | 45 + docs/kimi.md | 192 + docs/kiro.md | 58 + docs/litellm.md | 54 + docs/llm-proxy.md | 41 + docs/llms.txt | 12 + docs/logos/abacus-ai-dark.svg | 18 + docs/logos/abacus-ai.png | Bin 0 -> 4166 bytes docs/logos/alibaba.svg | 1 + docs/logos/amp.svg | 1 + docs/logos/antigravity.svg | 1 + docs/logos/augment.svg | 4 + docs/logos/chutes.svg | 7 + docs/logos/claude.svg | 1 + docs/logos/codebuff-dark.svg | 4 + docs/logos/codebuff.png | Bin 0 -> 770 bytes docs/logos/codebuff.svg | 4 + docs/logos/codex-dark.svg | 3 + docs/logos/codex.svg | 1 + docs/logos/copilot.svg | 1 + docs/logos/cursor.svg | 1 + docs/logos/deepseek.svg | 1 + docs/logos/devin.svg | 3 + docs/logos/droid-dark.svg | 3 + docs/logos/droid.svg | 8 + docs/logos/elevenlabs.svg | 4 + docs/logos/gemini.svg | 1 + docs/logos/jetbrains-ai.svg | 1 + docs/logos/kilo.svg | 1 + docs/logos/kimi-k2.svg | 1 + docs/logos/kimi.svg | 1 + docs/logos/kiro-dark.svg | 19 + docs/logos/kiro.svg | 11 + docs/logos/litellm.svg | 16 + docs/logos/minimax.svg | 1 + docs/logos/mistral.svg | 1 + docs/logos/ollama.svg | 1 + docs/logos/opencode-dark.svg | 6 + docs/logos/opencode.svg | 6 + docs/logos/openrouter.svg | 1 + docs/logos/perplexity.svg | 1 + docs/logos/poe.svg | 1 + docs/logos/synthetic-dark.svg | 14 + docs/logos/synthetic.svg | 12 + docs/logos/t3chat.svg | 5 + docs/logos/vertex-ai.svg | 51 + docs/logos/warp.svg | 1 + docs/logos/zai-dark.svg | 5 + docs/logos/zai.svg | 219 + docs/logos/zed.svg | 4 + docs/manus.md | 73 + docs/mimo.md | 99 + docs/minimax.md | 95 + docs/mistral.md | 76 + docs/model-pricing.md | 42 + docs/moonshot.md | 50 + docs/ollama.md | 66 + docs/openai.md | 66 + docs/opencode.md | 32 + docs/openrouter.md | 72 + docs/overview-scroll-stutter-investigation.md | 531 ++ docs/packaging.md | 25 + ...ssue-139-main-fix-validation-2026-02-19.md | 77 + ...-issue-139-simulation-report-2026-02-19.md | 109 + docs/perplexity.md | 85 + docs/poe.md | 45 + docs/pr-1848-body.md | 51 + docs/pr-1848-verification-comment.md | 48 + docs/predictive-refresh-policy.md | 278 + docs/provider.md | 201 + docs/providers.md | 509 ++ docs/qoder.md | 73 + docs/quotio-comparison.md | 186 + docs/refactor/claude-current-baseline.md | 155 + docs/refactor/claude-provider-vnext-locked.md | 356 + docs/refactor/cli.md | 78 + docs/refresh-loop.md | 55 + docs/releasing-homebrew.md | 52 + docs/repository-size.md | 69 + docs/sakana.md | 130 + docs/screenshots/claude-extra-usage-bug.png | Bin 0 -> 81474 bytes ...de-multi-account-status-items-proposal.svg | 103 + .../claude-sign-in-synthetic-proof.png | Bin 0 -> 31238 bytes .../claude-swap-accounts-synthetic-proof.png | Bin 0 -> 161047 bytes docs/screenshots/clawrouter-settings.png | Bin 0 -> 107227 bytes docs/screenshots/clawrouter-usage.png | Bin 0 -> 17470 bytes ...am-weekly-exhausted-session-misleading.png | Bin 0 -> 31910 bytes .../codexbar-weekly-caps-session-fix.png | Bin 0 -> 157215 bytes docs/screenshots/cost-chart-yaxis-labels.png | Bin 0 -> 247405 bytes .../current-merged-menu-redacted.png | Bin 0 -> 17629 bytes .../factory-api-key-details-source-api.png | Bin 0 -> 59952 bytes .../factory-api-key-menu-usage.png | Bin 0 -> 165905 bytes .../factory-api-key-settings-connection.png | Bin 0 -> 112918 bytes .../settings-sidebar-card-before.png | Bin 0 -> 434102 bytes .../settings-sidebar-goldengate-after.png | Bin 0 -> 253660 bytes docs/session-keepalive-design.md | 239 + docs/sessions.md | 17 + docs/site-locales.mjs | 3342 ++++++++++ docs/site-utilities.css | 1 + docs/site.css | 2607 ++++++++ docs/site.js | 737 +++ docs/social.html | 242 + docs/social.png | Bin 0 -> 580936 bytes ...eb-extras-default-off-codexbar-20260307.md | 72 + docs/sparkle.md | 29 + docs/status.md | 28 + docs/stepfun.md | 57 + docs/sub2api.md | 50 + .../2026-05-11-kilo-organization-selection.md | 1490 +++++ ...5-11-kilo-organization-selection-design.md | 156 + .../specs/2026-07-01-mimo-reserve-decision.md | 100 + ...01-opencode-go-multi-workspace-decision.md | 106 + ...ctive-pace-warning-notifications-design.md | 117 + ...-provider-presentation-and-focus-design.md | 240 + docs/synthetic.md | 72 + docs/t3chat.md | 113 + docs/ui.md | 66 + docs/venice.md | 48 + docs/verify-1844-proof.md | 46 + docs/vertexai.md | 57 + docs/warp.md | 49 + docs/wayfinder.md | 68 + docs/web-integration.md | 9 + docs/webkit.md | 32 + docs/widgets.md | 107 + docs/widgets/01-codexbar-history-small.png | Bin 0 -> 39356 bytes docs/widgets/02-codexbar-history-large.png | Bin 0 -> 48932 bytes docs/widgets/03-codexbar-metric-compact.png | Bin 0 -> 20887 bytes docs/widgets/04-codexbar-burndown.png | Bin 0 -> 94309 bytes .../widgets/05-codexbar-burndown-combined.png | Bin 0 -> 96350 bytes docs/widgets/06-codexbar-usage-compact.png | Bin 0 -> 23285 bytes docs/widgets/07-codexbar-usage-wide.png | Bin 0 -> 35275 bytes docs/widgets/08-codexbar-usage-large.png | Bin 0 -> 56104 bytes docs/widgets/09-codexbar-switcher-compact.png | Bin 0 -> 25647 bytes docs/widgets/10-codexbar-switcher-wide.png | Bin 0 -> 39738 bytes docs/widgets/11-codexbar-switcher-large.png | Bin 0 -> 58478 bytes docs/windsurf.md | 172 + docs/zai.md | 143 + docs/zed.md | 76 + 1848 files changed, 472303 insertions(+) create mode 100644 .agents/skills/codexbar/SKILL.md create mode 100755 .agents/skills/codexbar/scripts/codexbar create mode 100644 .agents/skills/codexbar/scripts/test_codexbar.py create mode 100644 .agents/skills/qa-test/SKILL.md create mode 100644 .agents/skills/qa-test/agents/openai.yaml create mode 100644 .agents/skills/qa-test/references/api-specs.md create mode 100755 .agents/skills/qa-test/scripts/live_provider_matrix.sh create mode 100644 .agents/skills/release-codexbar/SKILL.md create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/release-cli.yml create mode 100644 .github/workflows/upstream-monitor.yml create mode 100644 .gitignore create mode 100644 .swiftformat create mode 100644 .swiftlint.yml create mode 100644 .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata create mode 100644 AGENTS.md create mode 100644 CHANGELOG.md create mode 100644 Icon.icns create mode 100644 Icon.icon/Assets/codexbar.png create mode 100644 Icon.icon/icon.json create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 Package.resolved create mode 100644 Package.swift create mode 100644 README.md create mode 100644 README.wehub.md create mode 100755 Scripts/analyze_quotio.sh create mode 100755 Scripts/build-site-css.sh create mode 100755 Scripts/build_icon.sh create mode 100755 Scripts/changelog-to-html.sh create mode 100644 Scripts/check-app-locales.mjs create mode 100644 Scripts/check-documentation-links.mjs create mode 100755 Scripts/check-release-assets.sh create mode 100644 Scripts/check-site-locales.mjs create mode 100755 Scripts/check_repository_size.sh create mode 100755 Scripts/check_upstreams.sh create mode 100755 Scripts/ci_macos_test_gate.sh create mode 100755 Scripts/ci_swift_test_by_suite.py create mode 100755 Scripts/ci_verify_test_jobs.sh create mode 100755 Scripts/compile_and_run.sh create mode 100755 Scripts/cost_jsonl_shape_survey.swift create mode 100755 Scripts/docs-list.mjs create mode 100755 Scripts/generate-llms.mjs create mode 100755 Scripts/install_lint_tools.sh create mode 100755 Scripts/launch.sh create mode 100755 Scripts/lint.sh create mode 100755 Scripts/mac-release create mode 100755 Scripts/make_appcast.sh create mode 100755 Scripts/mimo-usage.py create mode 100755 Scripts/package_app.sh create mode 100755 Scripts/package_product_paths.sh create mode 100755 Scripts/prepare_upstream_pr.sh create mode 100755 Scripts/regenerate-codex-parser-hash.sh create mode 100755 Scripts/release.sh create mode 100755 Scripts/release_artifacts.sh create mode 100755 Scripts/release_dsym_paths.sh create mode 100755 Scripts/review_upstream.sh create mode 100755 Scripts/setup_dev_signing.sh create mode 100755 Scripts/sign-and-notarize.sh create mode 100644 Scripts/site-tailwind.input.css create mode 100755 Scripts/sparkle_signing_paths.sh create mode 100644 Scripts/tailwind.site.config.cjs create mode 100755 Scripts/test.sh create mode 100755 Scripts/test_ci_path_gate.sh create mode 100755 Scripts/test_live_update.sh create mode 100755 Scripts/test_package_product_paths.sh create mode 100755 Scripts/test_package_signing.sh create mode 100755 Scripts/test_package_strip.sh create mode 100755 Scripts/test_release_dsym_paths.sh create mode 100755 Scripts/test_repository_size.sh create mode 100755 Scripts/test_sparkle_signing_paths.sh create mode 100755 Scripts/test_swift_test_sharding.sh create mode 100755 Scripts/validate_changelog.sh create mode 100755 Scripts/verify_1844_live.sh create mode 100755 Scripts/verify_appcast.sh create mode 100644 Sources/AdaptiveRefreshCore/AdaptiveRefreshPolicyCore.swift create mode 100644 Sources/AdaptiveReplayCLI/CLIArguments.swift create mode 100644 Sources/AdaptiveReplayCLI/main.swift create mode 100644 Sources/AdaptiveReplayKit/ActivityCoverageStats.swift create mode 100644 Sources/AdaptiveReplayKit/AdaptiveRefreshTrace.swift create mode 100644 Sources/AdaptiveReplayKit/AdaptiveRefreshTraceParser.swift create mode 100644 Sources/AdaptiveReplayKit/BaselinePolicies.swift create mode 100644 Sources/AdaptiveReplayKit/CandidatePolicies.swift create mode 100644 Sources/AdaptiveReplayKit/README.md create mode 100644 Sources/AdaptiveReplayKit/RecordedScheduleAudit.swift create mode 100644 Sources/AdaptiveReplayKit/ReplayEngine.swift create mode 100644 Sources/AdaptiveReplayKit/ReplayMetrics.swift create mode 100644 Sources/AdaptiveReplayKit/ReplayPolicy.swift create mode 100644 Sources/AdaptiveReplayKit/ReplayTraceSegmentation.swift create mode 100644 Sources/CSQLite3/module.modulemap create mode 100644 Sources/CSQLite3/shim.h create mode 100644 Sources/CodexBar/About.swift create mode 100644 Sources/CodexBar/AdaptiveRefreshPolicy.swift create mode 100644 Sources/CodexBar/AgentSessionsStore.swift create mode 100644 Sources/CodexBar/AppNotifications.swift create mode 100644 Sources/CodexBar/ChartBarHoverSelection.swift create mode 100644 Sources/CodexBar/ClaudeLoginRunner.swift create mode 100644 Sources/CodexBar/ClickToCopyOverlay.swift create mode 100644 Sources/CodexBar/CodexAccountMenuPresentation.swift create mode 100644 Sources/CodexBar/CodexAccountPromotionCoordinator.swift create mode 100644 Sources/CodexBar/CodexAccountPromotionExecution.swift create mode 100644 Sources/CodexBar/CodexAccountPromotionPlanning.swift create mode 100644 Sources/CodexBar/CodexAccountPromotionPreparation.swift create mode 100644 Sources/CodexBar/CodexAccountPromotionService.swift create mode 100644 Sources/CodexBar/CodexAccountReconciliation.swift create mode 100644 Sources/CodexBar/CodexAccountUsageSnapshotStore.swift create mode 100644 Sources/CodexBar/CodexHistoryOwnership.swift create mode 100644 Sources/CodexBar/CodexLoginAlertPresentation.swift create mode 100644 Sources/CodexBar/CodexLoginRunner.swift create mode 100644 Sources/CodexBar/CodexOwnershipContext.swift create mode 100644 Sources/CodexBar/CodexResetCreditExpiryNotifier.swift create mode 100644 Sources/CodexBar/CodexbarApp.swift create mode 100644 Sources/CodexBar/Config/CodexBarConfigMigrator.swift create mode 100644 Sources/CodexBar/CookieHeaderStore.swift create mode 100644 Sources/CodexBar/CopilotTokenStore.swift create mode 100644 Sources/CodexBar/CostHistoryChartMenuView.swift create mode 100644 Sources/CodexBar/CreditsHistoryChartMenuView.swift create mode 100644 Sources/CodexBar/CursorLoginRunner.swift create mode 100644 Sources/CodexBar/Date+RelativeDescription.swift create mode 100644 Sources/CodexBar/DisplayLink.swift create mode 100644 Sources/CodexBar/GeminiLoginRunner.swift create mode 100644 Sources/CodexBar/HiddenWindowView.swift create mode 100644 Sources/CodexBar/HistoricalUsagePace.swift create mode 100644 Sources/CodexBar/IconRemainingResolver.swift create mode 100644 Sources/CodexBar/IconRenderer.swift create mode 100644 Sources/CodexBar/InlineUsageDashboardContent.swift create mode 100644 Sources/CodexBar/InstallOrigin.swift create mode 100644 Sources/CodexBar/KeyboardShortcuts+Names.swift create mode 100644 Sources/CodexBar/KeychainMigration.swift create mode 100644 Sources/CodexBar/KeychainPromptCoordinator.swift create mode 100644 Sources/CodexBar/KimiK2TokenStore.swift create mode 100644 Sources/CodexBar/KimiTokenStore.swift create mode 100644 Sources/CodexBar/LaunchAtLoginManager.swift create mode 100644 Sources/CodexBar/LoadingPattern.swift create mode 100644 Sources/CodexBar/Localization.swift create mode 100644 Sources/CodexBar/MainThreadHangWatchdog.swift create mode 100644 Sources/CodexBar/ManagedCodexAccountCoordinator.swift create mode 100644 Sources/CodexBar/ManagedCodexAccountService.swift create mode 100644 Sources/CodexBar/MemoryPressureMonitor.swift create mode 100644 Sources/CodexBar/MemoryPressureRelief.swift create mode 100644 Sources/CodexBar/MenuBarDisplayMode.swift create mode 100644 Sources/CodexBar/MenuBarDisplayText.swift create mode 100644 Sources/CodexBar/MenuBarMetricWindowResolver.swift create mode 100644 Sources/CodexBar/MenuBarStatusItemDefaultsRepair.swift create mode 100644 Sources/CodexBar/MenuBarStatusItemPlacementPreflight.swift create mode 100644 Sources/CodexBar/MenuBarStatusItemWindowProbe.swift create mode 100644 Sources/CodexBar/MenuBarVisibilityWatcher.swift create mode 100644 Sources/CodexBar/MenuCardGPUSelectionView.swift create mode 100644 Sources/CodexBar/MenuCardHeightFingerprint.swift create mode 100644 Sources/CodexBar/MenuCardQuotaWarningMarkers.swift create mode 100644 Sources/CodexBar/MenuCardRefreshMonitor.swift create mode 100644 Sources/CodexBar/MenuCardView+CodexResetCredits.swift create mode 100644 Sources/CodexBar/MenuCardView+Costs.swift create mode 100644 Sources/CodexBar/MenuCardView+Kiro.swift create mode 100644 Sources/CodexBar/MenuCardView+MiniMax.swift create mode 100644 Sources/CodexBar/MenuCardView+ModelHelpers.swift create mode 100644 Sources/CodexBar/MenuCardView+ModelInput.swift create mode 100644 Sources/CodexBar/MenuCardView.swift create mode 100644 Sources/CodexBar/MenuContent.swift create mode 100644 Sources/CodexBar/MenuDescriptor+ProviderUsage.swift create mode 100644 Sources/CodexBar/MenuDescriptor+Wayfinder.swift create mode 100644 Sources/CodexBar/MenuDescriptor.swift create mode 100644 Sources/CodexBar/MenuHighlightStyle.swift create mode 100644 Sources/CodexBar/MenuOpenRefreshPlan.swift create mode 100644 Sources/CodexBar/MenuSessionCoordinator.swift create mode 100644 Sources/CodexBar/MiniMaxAPITokenStore.swift create mode 100644 Sources/CodexBar/MiniMaxCookieStore.swift create mode 100644 Sources/CodexBar/MouseLocationReader.swift create mode 100644 Sources/CodexBar/Notifications+CodexBar.swift create mode 100644 Sources/CodexBar/OpenAICreditsPurchaseWindowController.swift create mode 100644 Sources/CodexBar/PersonalInfoRedactor.swift create mode 100644 Sources/CodexBar/PlanUtilizationHistoryChartMenuView.swift create mode 100644 Sources/CodexBar/PlanUtilizationHistoryStore.swift create mode 100644 Sources/CodexBar/PredictivePaceWarnings.swift create mode 100644 Sources/CodexBar/PreferencesAboutPane.swift create mode 100644 Sources/CodexBar/PreferencesAdvancedPane.swift create mode 100644 Sources/CodexBar/PreferencesCodexAccountsSection.swift create mode 100644 Sources/CodexBar/PreferencesComponents.swift create mode 100644 Sources/CodexBar/PreferencesDebugPane.swift create mode 100644 Sources/CodexBar/PreferencesGeneralPane.swift create mode 100644 Sources/CodexBar/PreferencesMenuBarPane.swift create mode 100644 Sources/CodexBar/PreferencesMenuPane.swift create mode 100644 Sources/CodexBar/PreferencesMenuPicker.swift create mode 100644 Sources/CodexBar/PreferencesNotificationsPane.swift create mode 100644 Sources/CodexBar/PreferencesProviderDetailView.swift create mode 100644 Sources/CodexBar/PreferencesProviderErrorView.swift create mode 100644 Sources/CodexBar/PreferencesProviderSettingsMetrics.swift create mode 100644 Sources/CodexBar/PreferencesProviderSettingsRows.swift create mode 100644 Sources/CodexBar/PreferencesProvidersPane+Testing.swift create mode 100644 Sources/CodexBar/PreferencesProvidersPane.swift create mode 100644 Sources/CodexBar/PreferencesSelection.swift create mode 100644 Sources/CodexBar/PreferencesSidebar.swift create mode 100644 Sources/CodexBar/PreferencesView.swift create mode 100644 Sources/CodexBar/ProviderBrandIcon.swift create mode 100644 Sources/CodexBar/ProviderRefreshCoordinator.swift create mode 100644 Sources/CodexBar/ProviderRegistry.swift create mode 100644 Sources/CodexBar/ProviderSwitcherButtons.swift create mode 100644 Sources/CodexBar/ProviderToggleStore.swift create mode 100644 Sources/CodexBar/Providers/Abacus/AbacusProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Abacus/AbacusSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/Alibaba/AlibabaCodingPlanProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Alibaba/AlibabaCodingPlanSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/Alibaba/AlibabaTokenPlanProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Alibaba/AlibabaTokenPlanSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/Amp/AmpProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Amp/AmpSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/Antigravity/AntigravityLoginFlow.swift create mode 100644 Sources/CodexBar/Providers/Antigravity/AntigravityLoginRunner.swift create mode 100644 Sources/CodexBar/Providers/Antigravity/AntigravityProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Antigravity/AntigravitySettingsStore.swift create mode 100644 Sources/CodexBar/Providers/Augment/AugmentProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Augment/AugmentProviderRuntime.swift create mode 100644 Sources/CodexBar/Providers/Augment/AugmentSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/AzureOpenAI/AzureOpenAIProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/AzureOpenAI/AzureOpenAISettingsStore.swift create mode 100644 Sources/CodexBar/Providers/Bedrock/BedrockProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Bedrock/BedrockSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/Chutes/ChutesProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Chutes/ChutesSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/Claude/ClaudeLoginFlow.swift create mode 100644 Sources/CodexBar/Providers/Claude/ClaudeProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Claude/ClaudeProviderRuntime.swift create mode 100644 Sources/CodexBar/Providers/Claude/ClaudeSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/Claude/UsageStore+ClaudeSwapRefresh.swift create mode 100644 Sources/CodexBar/Providers/ClawRouter/ClawRouterProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/ClawRouter/ClawRouterSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/Codebuff/CodebuffProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Codebuff/CodebuffSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/Codex/CodexConsumerProjection.swift create mode 100644 Sources/CodexBar/Providers/Codex/CodexLimitResetOwnerKey.swift create mode 100644 Sources/CodexBar/Providers/Codex/CodexLoginFlow.swift create mode 100644 Sources/CodexBar/Providers/Codex/CodexProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Codex/CodexProviderRuntime.swift create mode 100644 Sources/CodexBar/Providers/Codex/CodexSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/Codex/CodexWeeklyResetConfirmation.swift create mode 100644 Sources/CodexBar/Providers/Codex/UsageStore+CodexAccountState.swift create mode 100644 Sources/CodexBar/Providers/Codex/UsageStore+CodexRefresh.swift create mode 100644 Sources/CodexBar/Providers/Codex/UsageStore+CodexWeeklyResetConfirmation.swift create mode 100644 Sources/CodexBar/Providers/CommandCode/CommandCodeProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/CommandCode/CommandCodeSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/Copilot/CopilotLoginFlow.swift create mode 100644 Sources/CodexBar/Providers/Copilot/CopilotProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Copilot/CopilotSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/Copilot/UsageStore+CopilotBudgets.swift create mode 100644 Sources/CodexBar/Providers/Crof/CrofProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Crof/CrofSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/CrossModel/CrossModelProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/CrossModel/CrossModelSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/Cursor/CursorLoginFlow.swift create mode 100644 Sources/CodexBar/Providers/Cursor/CursorProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Cursor/CursorSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/DeepSeek/DeepSeekProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Deepgram/DeepgramProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Deepgram/DeepgramSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/Devin/DevinProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Devin/DevinSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/Doubao/DoubaoProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Doubao/DoubaoSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/ElevenLabs/ElevenLabsProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/ElevenLabs/ElevenLabsSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/Factory/FactoryLoginFlow.swift create mode 100644 Sources/CodexBar/Providers/Factory/FactoryProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Factory/FactorySettingsStore.swift create mode 100644 Sources/CodexBar/Providers/Gemini/GeminiLoginFlow.swift create mode 100644 Sources/CodexBar/Providers/Gemini/GeminiProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Grok/GrokProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Groq/GroqProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Groq/GroqSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/JetBrains/JetBrainsLoginFlow.swift create mode 100644 Sources/CodexBar/Providers/JetBrains/JetBrainsProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/JetBrains/JetBrainsSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/Kilo/KiloProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Kilo/KiloSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/Kilo/UsageStore+KiloOrgRefresh.swift create mode 100644 Sources/CodexBar/Providers/Kimi/KimiProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Kimi/KimiSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/KimiK2/KimiK2ProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/KimiK2/KimiK2SettingsStore.swift create mode 100644 Sources/CodexBar/Providers/Kiro/KiroProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/LLMProxy/LLMProxyProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/LLMProxy/LLMProxySettingsStore.swift create mode 100644 Sources/CodexBar/Providers/LiteLLM/LiteLLMProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/LiteLLM/LiteLLMSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/Manus/ManusProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Manus/ManusSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/MiMo/MiMoProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/MiMo/MiMoSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/MiniMax/MiniMaxProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/MiniMax/MiniMaxSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/Mistral/MistralProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Mistral/MistralSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/Moonshot/MoonshotProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Moonshot/MoonshotSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/Ollama/OllamaProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Ollama/OllamaSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/OpenAI/OpenAIAPIProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/OpenAI/OpenAIAPISettingsStore.swift create mode 100644 Sources/CodexBar/Providers/OpenCode/OpenCodeProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/OpenCode/OpenCodeProviderUI.swift create mode 100644 Sources/CodexBar/Providers/OpenCode/OpenCodeSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/OpenCodeGo/OpenCodeGoProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/OpenCodeGo/OpenCodeGoSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/OpenRouter/OpenRouterProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/OpenRouter/OpenRouterSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/Perplexity/PerplexityProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Perplexity/PerplexitySettingsStore.swift create mode 100644 Sources/CodexBar/Providers/Poe/PoeProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Poe/PoeSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/Qoder/QoderProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Qoder/QoderSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/Sakana/SakanaProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Sakana/SakanaSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/Shared/ProviderCatalog.swift create mode 100644 Sources/CodexBar/Providers/Shared/ProviderContext.swift create mode 100644 Sources/CodexBar/Providers/Shared/ProviderCookieSettingsResolution.swift create mode 100644 Sources/CodexBar/Providers/Shared/ProviderCookieSourceUI.swift create mode 100644 Sources/CodexBar/Providers/Shared/ProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Shared/ProviderImplementationRegistry.swift create mode 100644 Sources/CodexBar/Providers/Shared/ProviderLoginFlow.swift create mode 100644 Sources/CodexBar/Providers/Shared/ProviderMenuContext.swift create mode 100644 Sources/CodexBar/Providers/Shared/ProviderPresentation.swift create mode 100644 Sources/CodexBar/Providers/Shared/ProviderRuntime.swift create mode 100644 Sources/CodexBar/Providers/Shared/ProviderSettingsDescriptors.swift create mode 100644 Sources/CodexBar/Providers/Shared/ProviderTokenAccountSelection.swift create mode 100644 Sources/CodexBar/Providers/Shared/SystemSettingsLinks.swift create mode 100644 Sources/CodexBar/Providers/StepFun/StepFunProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/StepFun/StepFunSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/Sub2API/Sub2APIProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Sub2API/Sub2APISettingsStore.swift create mode 100644 Sources/CodexBar/Providers/Synthetic/SyntheticProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Synthetic/SyntheticSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/T3Chat/T3ChatProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/T3Chat/T3ChatSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/Venice/VeniceProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/VertexAI/VertexAILoginFlow.swift create mode 100644 Sources/CodexBar/Providers/VertexAI/VertexAIProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Warp/WarpProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Warp/WarpSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/Wayfinder/WayfinderProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Wayfinder/WayfinderSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/Windsurf/WindsurfProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Windsurf/WindsurfSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/Zai/ZaiProviderImplementation.swift create mode 100644 Sources/CodexBar/Providers/Zai/ZaiSettingsStore.swift create mode 100644 Sources/CodexBar/Providers/Zed/ZedProviderImplementation.swift create mode 100644 Sources/CodexBar/QuotaWarningAlertOverlayController.swift create mode 100644 Sources/CodexBar/QuotaWarningSettingsViews.swift create mode 100644 Sources/CodexBar/Resources/Icon-classic.icns create mode 100644 Sources/CodexBar/Resources/ProviderIcon-abacus.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-alibaba.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-amp.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-antigravity.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-augment.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-bedrock.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-chutes.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-claude.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-clawrouter.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-codebuff.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-codex.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-commandcode.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-copilot.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-crof.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-crossmodel.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-cursor.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-deepgram.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-deepseek.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-devin.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-doubao.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-elevenlabs.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-factory.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-gemini.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-grok.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-groq.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-jetbrains.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-kilo.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-kimi.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-kiro.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-litellm.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-llmproxy.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-manus.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-mimo.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-minimax.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-mistral.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-ollama.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-opencode.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-opencodego.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-openrouter.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-perplexity.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-poe.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-qoder.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-sakana.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-stepfun.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-sub2api.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-synthetic.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-t3chat.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-venice.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-vertexai.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-warp.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-wayfinder.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-windsurf.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-zai.svg create mode 100644 Sources/CodexBar/Resources/ProviderIcon-zed.svg create mode 100644 Sources/CodexBar/Resources/ar.lproj/Localizable.strings create mode 100644 Sources/CodexBar/Resources/ca.lproj/Localizable.strings create mode 100644 Sources/CodexBar/Resources/de.lproj/Localizable.strings create mode 100644 Sources/CodexBar/Resources/en.lproj/Localizable.strings create mode 100644 Sources/CodexBar/Resources/es.lproj/Localizable.strings create mode 100644 Sources/CodexBar/Resources/fa.lproj/Localizable.strings create mode 100644 Sources/CodexBar/Resources/fr.lproj/Localizable.strings create mode 100644 Sources/CodexBar/Resources/gl.lproj/Localizable.strings create mode 100644 Sources/CodexBar/Resources/id.lproj/Localizable.strings create mode 100644 Sources/CodexBar/Resources/it.lproj/Localizable.strings create mode 100644 Sources/CodexBar/Resources/ja.lproj/Localizable.strings create mode 100644 Sources/CodexBar/Resources/ko.lproj/Localizable.strings create mode 100644 Sources/CodexBar/Resources/nl.lproj/Localizable.strings create mode 100644 Sources/CodexBar/Resources/pl.lproj/Localizable.strings create mode 100644 Sources/CodexBar/Resources/pt-BR.lproj/Localizable.strings create mode 100644 Sources/CodexBar/Resources/ru.lproj/Localizable.strings create mode 100644 Sources/CodexBar/Resources/sv.lproj/Localizable.strings create mode 100644 Sources/CodexBar/Resources/th.lproj/Localizable.strings create mode 100644 Sources/CodexBar/Resources/tr.lproj/Localizable.strings create mode 100644 Sources/CodexBar/Resources/uk.lproj/Localizable.strings create mode 100644 Sources/CodexBar/Resources/vi.lproj/Localizable.strings create mode 100644 Sources/CodexBar/Resources/zh-Hans.lproj/Localizable.strings create mode 100644 Sources/CodexBar/Resources/zh-Hant.lproj/Localizable.strings create mode 100644 Sources/CodexBar/ScreenConfettiOverlayController.swift create mode 100644 Sources/CodexBar/SessionQuotaNotifications.swift create mode 100644 Sources/CodexBar/SettingsStore+Config.swift create mode 100644 Sources/CodexBar/SettingsStore+ConfigPersistence.swift create mode 100644 Sources/CodexBar/SettingsStore+Defaults.swift create mode 100644 Sources/CodexBar/SettingsStore+MenuObservation.swift create mode 100644 Sources/CodexBar/SettingsStore+MenuPreferences.swift create mode 100644 Sources/CodexBar/SettingsStore+ProviderDetection.swift create mode 100644 Sources/CodexBar/SettingsStore+TokenAccounts.swift create mode 100644 Sources/CodexBar/SettingsStore+TokenCost.swift create mode 100644 Sources/CodexBar/SettingsStore.swift create mode 100644 Sources/CodexBar/SettingsStoreState.swift create mode 100644 Sources/CodexBar/StatusComponentsMenuView.swift create mode 100644 Sources/CodexBar/StatusItemController+AccountMenuDisplay.swift create mode 100644 Sources/CodexBar/StatusItemController+Actions.swift create mode 100644 Sources/CodexBar/StatusItemController+AgentSessions.swift create mode 100644 Sources/CodexBar/StatusItemController+Animation.swift create mode 100644 Sources/CodexBar/StatusItemController+ClaudeSwapMenu.swift create mode 100644 Sources/CodexBar/StatusItemController+CodexStackedMenu.swift create mode 100644 Sources/CodexBar/StatusItemController+CostMenuCard.swift create mode 100644 Sources/CodexBar/StatusItemController+CountdownRefresh.swift create mode 100644 Sources/CodexBar/StatusItemController+HostedSubmenus.swift create mode 100644 Sources/CodexBar/StatusItemController+IconObservation.swift create mode 100644 Sources/CodexBar/StatusItemController+IconPerf.swift create mode 100644 Sources/CodexBar/StatusItemController+MemoryPressure.swift create mode 100644 Sources/CodexBar/StatusItemController+Menu.swift create mode 100644 Sources/CodexBar/StatusItemController+MenuActionMapping.swift create mode 100644 Sources/CodexBar/StatusItemController+MenuAppearance.swift create mode 100644 Sources/CodexBar/StatusItemController+MenuCardHeightCache.swift create mode 100644 Sources/CodexBar/StatusItemController+MenuCardItems.swift create mode 100644 Sources/CodexBar/StatusItemController+MenuCardModel.swift create mode 100644 Sources/CodexBar/StatusItemController+MenuCardRecycling.swift create mode 100644 Sources/CodexBar/StatusItemController+MenuContexts.swift create mode 100644 Sources/CodexBar/StatusItemController+MenuInteractionRefresh.swift create mode 100644 Sources/CodexBar/StatusItemController+MenuLocalization.swift create mode 100644 Sources/CodexBar/StatusItemController+MenuPresentation.swift create mode 100644 Sources/CodexBar/StatusItemController+MenuReconcile.swift create mode 100644 Sources/CodexBar/StatusItemController+MenuRefreshScheduling.swift create mode 100644 Sources/CodexBar/StatusItemController+MenuRowReordering.swift create mode 100644 Sources/CodexBar/StatusItemController+MenuSmartUpdate.swift create mode 100644 Sources/CodexBar/StatusItemController+MenuTracking.swift create mode 100644 Sources/CodexBar/StatusItemController+MenuTypes.swift create mode 100644 Sources/CodexBar/StatusItemController+MenuViewportRestore.swift create mode 100644 Sources/CodexBar/StatusItemController+MenuWidthCache.swift create mode 100644 Sources/CodexBar/StatusItemController+MergedSwitcherContentCache.swift create mode 100644 Sources/CodexBar/StatusItemController+OverviewScroll.swift create mode 100644 Sources/CodexBar/StatusItemController+OverviewSubmenus.swift create mode 100644 Sources/CodexBar/StatusItemController+PersistentMenuActions.swift create mode 100644 Sources/CodexBar/StatusItemController+PersistentRefreshMenuItem.swift create mode 100644 Sources/CodexBar/StatusItemController+ProviderNavigation.swift create mode 100644 Sources/CodexBar/StatusItemController+ProviderSwitcher.swift create mode 100644 Sources/CodexBar/StatusItemController+Shutdown.swift create mode 100644 Sources/CodexBar/StatusItemController+StorageMenuCard.swift create mode 100644 Sources/CodexBar/StatusItemController+SwitcherMetrics.swift create mode 100644 Sources/CodexBar/StatusItemController+SwitcherViews.swift create mode 100644 Sources/CodexBar/StatusItemController+UsageHistoryMenu.swift create mode 100644 Sources/CodexBar/StatusItemController+WidgetSnapshot.swift create mode 100644 Sources/CodexBar/StatusItemController+ZaiHourlyChartMenu.swift create mode 100644 Sources/CodexBar/StatusItemController.swift create mode 100644 Sources/CodexBar/StatusItemMenu.swift create mode 100644 Sources/CodexBar/StorageBreakdownMenuView.swift create mode 100644 Sources/CodexBar/SyntheticTokenStore.swift create mode 100644 Sources/CodexBar/TerminalApp.swift create mode 100644 Sources/CodexBar/UpdateChannel.swift create mode 100644 Sources/CodexBar/UsageBreakdownChartMenuView.swift create mode 100644 Sources/CodexBar/UsageMenuCardHeaderAndUsageSectionView.swift create mode 100644 Sources/CodexBar/UsageMenuCardLayout.swift create mode 100644 Sources/CodexBar/UsagePaceText.swift create mode 100644 Sources/CodexBar/UsageProgressBar.swift create mode 100644 Sources/CodexBar/UsageStore+APIKeyDebug.swift create mode 100644 Sources/CodexBar/UsageStore+Accessors.swift create mode 100644 Sources/CodexBar/UsageStore+AdaptiveRefresh.swift create mode 100644 Sources/CodexBar/UsageStore+BackgroundRefresh.swift create mode 100644 Sources/CodexBar/UsageStore+ClaudeDebug.swift create mode 100644 Sources/CodexBar/UsageStore+CodexResetCredits.swift create mode 100644 Sources/CodexBar/UsageStore+GeminiMigration.swift create mode 100644 Sources/CodexBar/UsageStore+HighestUsage.swift create mode 100644 Sources/CodexBar/UsageStore+HistoricalPace.swift create mode 100644 Sources/CodexBar/UsageStore+LimitResetBoundary.swift create mode 100644 Sources/CodexBar/UsageStore+LimitResetIdentity.swift create mode 100644 Sources/CodexBar/UsageStore+Logging.swift create mode 100644 Sources/CodexBar/UsageStore+MemoryPressure.swift create mode 100644 Sources/CodexBar/UsageStore+OpenAIWeb.swift create mode 100644 Sources/CodexBar/UsageStore+PlanUtilization.swift create mode 100644 Sources/CodexBar/UsageStore+PlanUtilizationLoading.swift create mode 100644 Sources/CodexBar/UsageStore+ProviderRuntime.swift create mode 100644 Sources/CodexBar/UsageStore+ProviderStatus.swift create mode 100644 Sources/CodexBar/UsageStore+ProviderStorage.swift create mode 100644 Sources/CodexBar/UsageStore+QuotaWarnings.swift create mode 100644 Sources/CodexBar/UsageStore+Refresh.swift create mode 100644 Sources/CodexBar/UsageStore+RefreshEnrichment.swift create mode 100644 Sources/CodexBar/UsageStore+ResetBoundaryRefresh.swift create mode 100644 Sources/CodexBar/UsageStore+StartupConnectivityRetry.swift create mode 100644 Sources/CodexBar/UsageStore+Status.swift create mode 100644 Sources/CodexBar/UsageStore+Timeout.swift create mode 100644 Sources/CodexBar/UsageStore+TokenAccounts.swift create mode 100644 Sources/CodexBar/UsageStore+TokenCost.swift create mode 100644 Sources/CodexBar/UsageStore+TokenRefreshSequence.swift create mode 100644 Sources/CodexBar/UsageStore+WidgetSnapshot.swift create mode 100644 Sources/CodexBar/UsageStore.swift create mode 100644 Sources/CodexBar/UsageStoreSupport.swift create mode 100644 Sources/CodexBar/ZaiHourlyUsageChartMenuView.swift create mode 100644 Sources/CodexBar/ZaiTokenStore.swift create mode 100644 Sources/CodexBarCLI/CLICacheCommand.swift create mode 100644 Sources/CodexBarCLI/CLICardsBriefRenderer.swift create mode 100644 Sources/CodexBarCLI/CLICardsCommand.swift create mode 100644 Sources/CodexBarCLI/CLICardsRenderer.swift create mode 100644 Sources/CodexBarCLI/CLIConfigCommand.swift create mode 100644 Sources/CodexBarCLI/CLICostCommand.swift create mode 100644 Sources/CodexBarCLI/CLIDiagnoseCommand.swift create mode 100644 Sources/CodexBarCLI/CLIEntry.swift create mode 100644 Sources/CodexBarCLI/CLIErrorReporting.swift create mode 100644 Sources/CodexBarCLI/CLIExitCode.swift create mode 100644 Sources/CodexBarCLI/CLIHelp.swift create mode 100644 Sources/CodexBarCLI/CLIHelpers.swift create mode 100644 Sources/CodexBarCLI/CLIIO.swift create mode 100644 Sources/CodexBarCLI/CLILocalHTTPServer.swift create mode 100644 Sources/CodexBarCLI/CLIOptions.swift create mode 100644 Sources/CodexBarCLI/CLIOutputPreferences.swift create mode 100644 Sources/CodexBarCLI/CLIPayloads.swift create mode 100644 Sources/CodexBarCLI/CLIRenderer.swift create mode 100644 Sources/CodexBarCLI/CLIServeCommand.swift create mode 100644 Sources/CodexBarCLI/CLIServeOperationCoordinator.swift create mode 100644 Sources/CodexBarCLI/CLISessionsCommand.swift create mode 100644 Sources/CodexBarCLI/CLITerminalCapabilities.swift create mode 100644 Sources/CodexBarCLI/CLITerminationSignalMonitor.swift create mode 100644 Sources/CodexBarCLI/CLIUsageCommand.swift create mode 100644 Sources/CodexBarCLI/DiagnoseOptions.swift create mode 100644 Sources/CodexBarCLI/TokenAccountCLI.swift create mode 100644 Sources/CodexBarClaudeWatchdog/main.swift create mode 100644 Sources/CodexBarClaudeWebProbe/ClaudeWebProbeEntry.swift create mode 100644 Sources/CodexBarCore/AgentSession.swift create mode 100644 Sources/CodexBarCore/AppGroupSupport.swift create mode 100644 Sources/CodexBarCore/AutoreleasePoolCompat.swift create mode 100644 Sources/CodexBarCore/BoundedTaskJoin.swift create mode 100644 Sources/CodexBarCore/BrowserCookieAccessGate.swift create mode 100644 Sources/CodexBarCore/BrowserCookieImportOrder.swift create mode 100644 Sources/CodexBarCore/BrowserDetection.swift create mode 100644 Sources/CodexBarCore/CodexHomeScope.swift create mode 100644 Sources/CodexBarCore/CodexManagedAccounts.swift create mode 100644 Sources/CodexBarCore/Config/CodexActiveSource.swift create mode 100644 Sources/CodexBarCore/Config/CodexBarConfig.swift create mode 100644 Sources/CodexBarCore/Config/CodexBarConfigStore.swift create mode 100644 Sources/CodexBarCore/Config/CodexBarConfigValidation.swift create mode 100644 Sources/CodexBarCore/Config/ProviderConfigEnvironment.swift create mode 100644 Sources/CodexBarCore/CookieHeaderCache.swift create mode 100644 Sources/CodexBarCore/CookieHeaderNormalizer.swift create mode 100644 Sources/CodexBarCore/CopilotUsageModels.swift create mode 100644 Sources/CodexBarCore/CostUsageFetcher.swift create mode 100644 Sources/CodexBarCore/CostUsageModels.swift create mode 100644 Sources/CodexBarCore/CostUsageScanExecutor.swift create mode 100644 Sources/CodexBarCore/CreditsModels.swift create mode 100644 Sources/CodexBarCore/Double+Clamped.swift create mode 100644 Sources/CodexBarCore/Generated/CodexParserHash.generated.swift create mode 100644 Sources/CodexBarCore/Host/PTY/TTYCommandRunner.swift create mode 100644 Sources/CodexBarCore/Host/Process/PosixSpawnFileActionsCloseFrom.swift create mode 100644 Sources/CodexBarCore/Host/Process/ProcessPipeCapture.swift create mode 100644 Sources/CodexBarCore/Host/Process/SpawnedProcessGroup.swift create mode 100644 Sources/CodexBarCore/Host/Process/SubprocessRunner.swift create mode 100644 Sources/CodexBarCore/KeychainAccessGate.swift create mode 100644 Sources/CodexBarCore/KeychainAccessPreflight.swift create mode 100644 Sources/CodexBarCore/KeychainCacheStore.swift create mode 100644 Sources/CodexBarCore/KeychainNoUIQuery.swift create mode 100644 Sources/CodexBarCore/KeychainSecurity.swift create mode 100644 Sources/CodexBarCore/LocalAgentSessionScanner.swift create mode 100644 Sources/CodexBarCore/Logging/CodexBarLog.swift create mode 100644 Sources/CodexBarCore/Logging/CompositeLogHandler.swift create mode 100644 Sources/CodexBarCore/Logging/FileLogHandler.swift create mode 100644 Sources/CodexBarCore/Logging/JSONStderrLogHandler.swift create mode 100644 Sources/CodexBarCore/Logging/LogCategories.swift create mode 100644 Sources/CodexBarCore/Logging/LogMetadata.swift create mode 100644 Sources/CodexBarCore/Logging/LogRedactor.swift create mode 100644 Sources/CodexBarCore/Logging/OSLogLogHandler.swift create mode 100644 Sources/CodexBarCore/Logging/ProviderLogging.swift create mode 100644 Sources/CodexBarCore/ManagedCodexAccountStore.swift create mode 100644 Sources/CodexBarCore/OpenAIDashboardModels.swift create mode 100644 Sources/CodexBarCore/OpenAIWeb/OpenAIDashboardBrowserCookieImporter+Deadline.swift create mode 100644 Sources/CodexBarCore/OpenAIWeb/OpenAIDashboardBrowserCookieImporter.swift create mode 100644 Sources/CodexBarCore/OpenAIWeb/OpenAIDashboardFetcher+ReturnableData.swift create mode 100644 Sources/CodexBarCore/OpenAIWeb/OpenAIDashboardFetcher.swift create mode 100644 Sources/CodexBarCore/OpenAIWeb/OpenAIDashboardNavigationDelegate.swift create mode 100644 Sources/CodexBarCore/OpenAIWeb/OpenAIDashboardParser.swift create mode 100644 Sources/CodexBarCore/OpenAIWeb/OpenAIDashboardScrapeScript.swift create mode 100644 Sources/CodexBarCore/OpenAIWeb/OpenAIDashboardWebViewCache.swift create mode 100644 Sources/CodexBarCore/OpenAIWeb/OpenAIDashboardWebsiteDataStore.swift create mode 100644 Sources/CodexBarCore/PathEnvironment.swift create mode 100644 Sources/CodexBarCore/PiSessionCostCache.swift create mode 100644 Sources/CodexBarCore/PiSessionCostScanner.swift create mode 100644 Sources/CodexBarCore/ProviderAccountSnapshot.swift create mode 100644 Sources/CodexBarCore/ProviderCostSnapshot.swift create mode 100644 Sources/CodexBarCore/ProviderEndpointOverrideValidator.swift create mode 100644 Sources/CodexBarCore/ProviderHTTPClient.swift create mode 100644 Sources/CodexBarCore/ProviderStorageFootprint.swift create mode 100644 Sources/CodexBarCore/Providers/APITokenFetchStrategy.swift create mode 100644 Sources/CodexBarCore/Providers/Abacus/AbacusCookieImporter.swift create mode 100644 Sources/CodexBarCore/Providers/Abacus/AbacusProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Abacus/AbacusUsageError.swift create mode 100644 Sources/CodexBarCore/Providers/Abacus/AbacusUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/Abacus/AbacusUsageSnapshot.swift create mode 100644 Sources/CodexBarCore/Providers/Alibaba/AlibabaCodingPlanAPIRegion.swift create mode 100644 Sources/CodexBarCore/Providers/Alibaba/AlibabaCodingPlanCookieImporter.swift create mode 100644 Sources/CodexBarCore/Providers/Alibaba/AlibabaCodingPlanProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Alibaba/AlibabaCodingPlanSettingsReader.swift create mode 100644 Sources/CodexBarCore/Providers/Alibaba/AlibabaCodingPlanUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/Alibaba/AlibabaCodingPlanUsageSnapshot.swift create mode 100644 Sources/CodexBarCore/Providers/Alibaba/AlibabaTokenPlanAPIRegion.swift create mode 100644 Sources/CodexBarCore/Providers/Alibaba/AlibabaTokenPlanCookieHeader.swift create mode 100644 Sources/CodexBarCore/Providers/Alibaba/AlibabaTokenPlanProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Alibaba/AlibabaTokenPlanSettingsReader.swift create mode 100644 Sources/CodexBarCore/Providers/Alibaba/AlibabaTokenPlanUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/Alibaba/AlibabaTokenPlanUsageSnapshot.swift create mode 100644 Sources/CodexBarCore/Providers/Amp/AmpCLIProbe.swift create mode 100644 Sources/CodexBarCore/Providers/Amp/AmpProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Amp/AmpSettingsReader.swift create mode 100644 Sources/CodexBarCore/Providers/Amp/AmpUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/Amp/AmpUsageParser.swift create mode 100644 Sources/CodexBarCore/Providers/Amp/AmpUsageSnapshot.swift create mode 100644 Sources/CodexBarCore/Providers/Antigravity/AntigravityCLISession.swift create mode 100644 Sources/CodexBarCore/Providers/Antigravity/AntigravityLocalSnapshotSelection.swift create mode 100644 Sources/CodexBarCore/Providers/Antigravity/AntigravityLocalhostSession.swift create mode 100644 Sources/CodexBarCore/Providers/Antigravity/AntigravityOAuthCredentialsStore.swift create mode 100644 Sources/CodexBarCore/Providers/Antigravity/AntigravityProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Antigravity/AntigravityQuotaSummaryParser.swift create mode 100644 Sources/CodexBarCore/Providers/Antigravity/AntigravityRemoteUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/Antigravity/AntigravityStatusProbe+Deadline.swift create mode 100644 Sources/CodexBarCore/Providers/Antigravity/AntigravityStatusProbe+LocalEndpoints.swift create mode 100644 Sources/CodexBarCore/Providers/Antigravity/AntigravityStatusProbe+PortDetection.swift create mode 100644 Sources/CodexBarCore/Providers/Antigravity/AntigravityStatusProbe+ResponseModels.swift create mode 100644 Sources/CodexBarCore/Providers/Antigravity/AntigravityStatusProbe.swift create mode 100644 Sources/CodexBarCore/Providers/Antigravity/AntigravityUsageDataSource.swift create mode 100644 Sources/CodexBarCore/Providers/Augment/AuggieCLIProbe.swift create mode 100644 Sources/CodexBarCore/Providers/Augment/AugmentProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Augment/AugmentSessionKeepalive.swift create mode 100644 Sources/CodexBarCore/Providers/Augment/AugmentStatusProbe.swift create mode 100644 Sources/CodexBarCore/Providers/AzureOpenAI/AzureOpenAIProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/AzureOpenAI/AzureOpenAISettingsReader.swift create mode 100644 Sources/CodexBarCore/Providers/AzureOpenAI/AzureOpenAIUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/Bedrock/BedrockAWSSigner.swift create mode 100644 Sources/CodexBarCore/Providers/Bedrock/BedrockCloudWatchUsage.swift create mode 100644 Sources/CodexBarCore/Providers/Bedrock/BedrockCredentialResolver.swift create mode 100644 Sources/CodexBarCore/Providers/Bedrock/BedrockProfileCredentialProvider.swift create mode 100644 Sources/CodexBarCore/Providers/Bedrock/BedrockProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Bedrock/BedrockSettingsReader.swift create mode 100644 Sources/CodexBarCore/Providers/Bedrock/BedrockUsageStats.swift create mode 100644 Sources/CodexBarCore/Providers/CLIProbeSessionResetter.swift create mode 100644 Sources/CodexBarCore/Providers/Chutes/ChutesProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Chutes/ChutesSettingsReader.swift create mode 100644 Sources/CodexBarCore/Providers/Chutes/ChutesUsageStats.swift create mode 100644 Sources/CodexBarCore/Providers/Claude/ClaudeAdminAPISettingsReader.swift create mode 100644 Sources/CodexBarCore/Providers/Claude/ClaudeAdminAPIUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/Claude/ClaudeAdminAPIUsageSnapshot.swift create mode 100644 Sources/CodexBarCore/Providers/Claude/ClaudeCLIAuthStatusProbe.swift create mode 100644 Sources/CodexBarCore/Providers/Claude/ClaudeCLIRateLimitGate.swift create mode 100644 Sources/CodexBarCore/Providers/Claude/ClaudeCLISession.swift create mode 100644 Sources/CodexBarCore/Providers/Claude/ClaudeCredentialRouting.swift create mode 100644 Sources/CodexBarCore/Providers/Claude/ClaudeDesktopProjectsLocator.swift create mode 100644 Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthCredentialModels.swift create mode 100644 Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthCredentials+Hashing.swift create mode 100644 Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthCredentials+SecurityCLIReader.swift create mode 100644 Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthCredentials+TestingOverrides.swift create mode 100644 Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthCredentials.swift create mode 100644 Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthDelegatedRefreshCoordinator.swift create mode 100644 Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthKeychainAccessGate.swift create mode 100644 Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthKeychainPreAlertGate.swift create mode 100644 Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthKeychainPromptMode.swift create mode 100644 Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthKeychainQueryTiming.swift create mode 100644 Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthKeychainReadStrategy.swift create mode 100644 Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthMutableKeychainOverrides.swift create mode 100644 Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthPendingCacheClearStore.swift create mode 100644 Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthRefreshFailureGate.swift create mode 100644 Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthUsageRateLimitGate.swift create mode 100644 Sources/CodexBarCore/Providers/Claude/ClaudePlan.swift create mode 100644 Sources/CodexBarCore/Providers/Claude/ClaudeProbeSessionArtifactCleaner.swift create mode 100644 Sources/CodexBarCore/Providers/Claude/ClaudeProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Claude/ClaudeScopedWeeklyLimitMapper.swift create mode 100644 Sources/CodexBarCore/Providers/Claude/ClaudeSourcePlanner.swift create mode 100644 Sources/CodexBarCore/Providers/Claude/ClaudeStatusProbe.swift create mode 100644 Sources/CodexBarCore/Providers/Claude/ClaudeSwap/ClaudeSwapAccountList.swift create mode 100644 Sources/CodexBarCore/Providers/Claude/ClaudeSwap/ClaudeSwapAccountProjection.swift create mode 100644 Sources/CodexBarCore/Providers/Claude/ClaudeSwap/ClaudeSwapAccountReader.swift create mode 100644 Sources/CodexBarCore/Providers/Claude/ClaudeSwap/ClaudeSwapAccountSwitch.swift create mode 100644 Sources/CodexBarCore/Providers/Claude/ClaudeUsageDataSource.swift create mode 100644 Sources/CodexBarCore/Providers/Claude/ClaudeUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/Claude/ClaudeWeb/ClaudeWebAPIFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/Claude/ClaudeWeb/ClaudeWebExtraRateWindowParser.swift create mode 100644 Sources/CodexBarCore/Providers/ClawRouter/ClawRouterProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/ClawRouter/ClawRouterSettingsReader.swift create mode 100644 Sources/CodexBarCore/Providers/ClawRouter/ClawRouterUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/Codebuff/CodebuffProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Codebuff/CodebuffSettingsReader.swift create mode 100644 Sources/CodexBarCore/Providers/Codebuff/CodebuffUsageError.swift create mode 100644 Sources/CodexBarCore/Providers/Codebuff/CodebuffUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/Codebuff/CodebuffUsageSnapshot.swift create mode 100644 Sources/CodexBarCore/Providers/Codex/CodexAccountReconciliation.swift create mode 100644 Sources/CodexBarCore/Providers/Codex/CodexAdditionalRateLimitMapper.swift create mode 100644 Sources/CodexBarCore/Providers/Codex/CodexAuthenticatedHTTPTransport.swift create mode 100644 Sources/CodexBarCore/Providers/Codex/CodexCLIDashboardAuthorityContext.swift create mode 100644 Sources/CodexBarCore/Providers/Codex/CodexCLILaunchGate.swift create mode 100644 Sources/CodexBarCore/Providers/Codex/CodexCLISession.swift create mode 100644 Sources/CodexBarCore/Providers/Codex/CodexDashboardAuthority.swift create mode 100644 Sources/CodexBarCore/Providers/Codex/CodexIdentity.swift create mode 100644 Sources/CodexBarCore/Providers/Codex/CodexOAuth/CodexOAuthCredentials.swift create mode 100644 Sources/CodexBarCore/Providers/Codex/CodexOAuth/CodexOAuthUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/Codex/CodexOAuth/CodexTokenRefresher.swift create mode 100644 Sources/CodexBarCore/Providers/Codex/CodexOpenAIWorkspaceIdentityCache.swift create mode 100644 Sources/CodexBarCore/Providers/Codex/CodexOpenAIWorkspaceResolver.swift create mode 100644 Sources/CodexBarCore/Providers/Codex/CodexPlanFormatting.swift create mode 100644 Sources/CodexBarCore/Providers/Codex/CodexProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Codex/CodexProviderSettingsBuilder.swift create mode 100644 Sources/CodexBarCore/Providers/Codex/CodexRateWindowNormalizer.swift create mode 100644 Sources/CodexBarCore/Providers/Codex/CodexReconciledState.swift create mode 100644 Sources/CodexBarCore/Providers/Codex/CodexSpendControlLimitMapping.swift create mode 100644 Sources/CodexBarCore/Providers/Codex/CodexStatusProbe.swift create mode 100644 Sources/CodexBarCore/Providers/Codex/CodexStatusProbeIsolation.swift create mode 100644 Sources/CodexBarCore/Providers/Codex/CodexSystemAccountObserver.swift create mode 100644 Sources/CodexBarCore/Providers/Codex/CodexUsageDataSource.swift create mode 100644 Sources/CodexBarCore/Providers/Codex/CodexVisibleAccountProjection.swift create mode 100644 Sources/CodexBarCore/Providers/Codex/CodexWebDashboardStrategy.swift create mode 100644 Sources/CodexBarCore/Providers/CommandCode/CommandCodeCookieHeader.swift create mode 100644 Sources/CodexBarCore/Providers/CommandCode/CommandCodeCookieImporter.swift create mode 100644 Sources/CodexBarCore/Providers/CommandCode/CommandCodePlanCatalog.swift create mode 100644 Sources/CodexBarCore/Providers/CommandCode/CommandCodeProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/CommandCode/CommandCodeUsageError.swift create mode 100644 Sources/CodexBarCore/Providers/CommandCode/CommandCodeUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/CommandCode/CommandCodeUsageSnapshot.swift create mode 100644 Sources/CodexBarCore/Providers/Copilot/CopilotBudgetWebFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/Copilot/CopilotDeviceFlow.swift create mode 100644 Sources/CodexBarCore/Providers/Copilot/CopilotProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Copilot/CopilotUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/Crof/CrofProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Crof/CrofSettingsReader.swift create mode 100644 Sources/CodexBarCore/Providers/Crof/CrofUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/Crof/CrofUsageSnapshot.swift create mode 100644 Sources/CodexBarCore/Providers/CrossModel/CrossModelProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/CrossModel/CrossModelSettingsReader.swift create mode 100644 Sources/CodexBarCore/Providers/CrossModel/CrossModelUsageStats.swift create mode 100644 Sources/CodexBarCore/Providers/Cursor/CursorProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Cursor/CursorRequestUsage.swift create mode 100644 Sources/CodexBarCore/Providers/Cursor/CursorStatusProbe.swift create mode 100644 Sources/CodexBarCore/Providers/DeepSeek/DeepSeekProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/DeepSeek/DeepSeekSettingsReader.swift create mode 100644 Sources/CodexBarCore/Providers/DeepSeek/DeepSeekUsageCostParser.swift create mode 100644 Sources/CodexBarCore/Providers/DeepSeek/DeepSeekUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/Deepgram/DeepgramProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Deepgram/DeepgramSettingsReader.swift create mode 100644 Sources/CodexBarCore/Providers/Deepgram/DeepgramUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/Devin/DevinProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Devin/DevinSessionImporter.swift create mode 100644 Sources/CodexBarCore/Providers/Devin/DevinUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/Devin/DevinUsageSnapshot.swift create mode 100644 Sources/CodexBarCore/Providers/Doubao/DoubaoProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Doubao/DoubaoSettingsReader.swift create mode 100644 Sources/CodexBarCore/Providers/Doubao/DoubaoUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/Doubao/DoubaoVolcengineSigner.swift create mode 100644 Sources/CodexBarCore/Providers/ElevenLabs/ElevenLabsProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/ElevenLabs/ElevenLabsSettingsReader.swift create mode 100644 Sources/CodexBarCore/Providers/ElevenLabs/ElevenLabsUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/Factory/FactoryLocalStorageImporter.swift create mode 100644 Sources/CodexBarCore/Providers/Factory/FactoryManualCredentials.swift create mode 100644 Sources/CodexBarCore/Providers/Factory/FactoryProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Factory/FactorySessionStore.swift create mode 100644 Sources/CodexBarCore/Providers/Factory/FactorySettingsReader.swift create mode 100644 Sources/CodexBarCore/Providers/Factory/FactoryStatusProbe+APIKey.swift create mode 100644 Sources/CodexBarCore/Providers/Factory/FactoryStatusProbe.swift create mode 100644 Sources/CodexBarCore/Providers/Factory/FactoryStatusProbeError.swift create mode 100644 Sources/CodexBarCore/Providers/Gemini/GeminiConsumerTierMigration.swift create mode 100644 Sources/CodexBarCore/Providers/Gemini/GeminiOAuthConfig.swift create mode 100644 Sources/CodexBarCore/Providers/Gemini/GeminiProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Gemini/GeminiStatusProbe+DataLoader.swift create mode 100644 Sources/CodexBarCore/Providers/Gemini/GeminiStatusProbe.swift create mode 100644 Sources/CodexBarCore/Providers/Grok/GrokAuth.swift create mode 100644 Sources/CodexBarCore/Providers/Grok/GrokCookieImporter.swift create mode 100644 Sources/CodexBarCore/Providers/Grok/GrokLocalSessionScanner.swift create mode 100644 Sources/CodexBarCore/Providers/Grok/GrokProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Grok/GrokRPCClient.swift create mode 100644 Sources/CodexBarCore/Providers/Grok/GrokStatusProbe.swift create mode 100644 Sources/CodexBarCore/Providers/Grok/GrokWebBillingFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/Groq/GroqProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Groq/GroqSettingsReader.swift create mode 100644 Sources/CodexBarCore/Providers/Groq/GroqUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/JetBrains/JetBrainsIDEDetector.swift create mode 100644 Sources/CodexBarCore/Providers/JetBrains/JetBrainsProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/JetBrains/JetBrainsStatusProbe.swift create mode 100644 Sources/CodexBarCore/Providers/Kilo/KiloBearerTokenResolver.swift create mode 100644 Sources/CodexBarCore/Providers/Kilo/KiloOrganization.swift create mode 100644 Sources/CodexBarCore/Providers/Kilo/KiloProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Kilo/KiloSettingsReader.swift create mode 100644 Sources/CodexBarCore/Providers/Kilo/KiloUsageDataSource.swift create mode 100644 Sources/CodexBarCore/Providers/Kilo/KiloUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/Kilo/KiloUsageScope.swift create mode 100644 Sources/CodexBarCore/Providers/Kimi/KimiAPIError.swift create mode 100644 Sources/CodexBarCore/Providers/Kimi/KimiCookieHeader.swift create mode 100644 Sources/CodexBarCore/Providers/Kimi/KimiCookieImporter.swift create mode 100644 Sources/CodexBarCore/Providers/Kimi/KimiModels.swift create mode 100644 Sources/CodexBarCore/Providers/Kimi/KimiProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Kimi/KimiSettingsReader.swift create mode 100644 Sources/CodexBarCore/Providers/Kimi/KimiUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/Kimi/KimiUsageSnapshot.swift create mode 100644 Sources/CodexBarCore/Providers/KimiK2/KimiK2ProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/KimiK2/KimiK2SettingsReader.swift create mode 100644 Sources/CodexBarCore/Providers/KimiK2/KimiK2UsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/Kiro/KiroProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Kiro/KiroStatusProbe.swift create mode 100644 Sources/CodexBarCore/Providers/LLMProxy/LLMProxyProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/LLMProxy/LLMProxySettingsReader.swift create mode 100644 Sources/CodexBarCore/Providers/LLMProxy/LLMProxyUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/LiteLLM/LiteLLMProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/LiteLLM/LiteLLMSettingsReader.swift create mode 100644 Sources/CodexBarCore/Providers/LiteLLM/LiteLLMUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/Manus/ManusCookieHeader.swift create mode 100644 Sources/CodexBarCore/Providers/Manus/ManusCookieImporter.swift create mode 100644 Sources/CodexBarCore/Providers/Manus/ManusProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Manus/ManusSettingsReader.swift create mode 100644 Sources/CodexBarCore/Providers/Manus/ManusUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/MiMo/MiMoCookieImporter.swift create mode 100644 Sources/CodexBarCore/Providers/MiMo/MiMoLocalUsageFallback.swift create mode 100644 Sources/CodexBarCore/Providers/MiMo/MiMoProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/MiMo/MiMoUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/MiMo/MiMoUsageSnapshot.swift create mode 100644 Sources/CodexBarCore/Providers/MiniMax/MiniMaxAPIRegion.swift create mode 100644 Sources/CodexBarCore/Providers/MiniMax/MiniMaxAPISettingsReader.swift create mode 100644 Sources/CodexBarCore/Providers/MiniMax/MiniMaxAuthMode.swift create mode 100644 Sources/CodexBarCore/Providers/MiniMax/MiniMaxBillingHistory.swift create mode 100644 Sources/CodexBarCore/Providers/MiniMax/MiniMaxCookieHeader.swift create mode 100644 Sources/CodexBarCore/Providers/MiniMax/MiniMaxCookieImporter.swift create mode 100644 Sources/CodexBarCore/Providers/MiniMax/MiniMaxDecoding.swift create mode 100644 Sources/CodexBarCore/Providers/MiniMax/MiniMaxLocalStorageImporter.swift create mode 100644 Sources/CodexBarCore/Providers/MiniMax/MiniMaxModelRemains.swift create mode 100644 Sources/CodexBarCore/Providers/MiniMax/MiniMaxProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/MiniMax/MiniMaxServiceUsage.swift create mode 100644 Sources/CodexBarCore/Providers/MiniMax/MiniMaxSettingsReader.swift create mode 100644 Sources/CodexBarCore/Providers/MiniMax/MiniMaxSubscriptionMetadata.swift create mode 100644 Sources/CodexBarCore/Providers/MiniMax/MiniMaxUsageError.swift create mode 100644 Sources/CodexBarCore/Providers/MiniMax/MiniMaxUsageFetcher+ModelMapping.swift create mode 100644 Sources/CodexBarCore/Providers/MiniMax/MiniMaxUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/MiniMax/MiniMaxUsageSnapshot+Metadata.swift create mode 100644 Sources/CodexBarCore/Providers/MiniMax/MiniMaxUsageSnapshot.swift create mode 100644 Sources/CodexBarCore/Providers/Mistral/MistralCookieImporter.swift create mode 100644 Sources/CodexBarCore/Providers/Mistral/MistralErrors.swift create mode 100644 Sources/CodexBarCore/Providers/Mistral/MistralModels.swift create mode 100644 Sources/CodexBarCore/Providers/Mistral/MistralProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Mistral/MistralUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/Moonshot/MoonshotProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Moonshot/MoonshotRegion.swift create mode 100644 Sources/CodexBarCore/Providers/Moonshot/MoonshotSettingsReader.swift create mode 100644 Sources/CodexBarCore/Providers/Moonshot/MoonshotUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/Ollama/OllamaProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Ollama/OllamaUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/Ollama/OllamaUsageParser.swift create mode 100644 Sources/CodexBarCore/Providers/Ollama/OllamaUsageSnapshot.swift create mode 100644 Sources/CodexBarCore/Providers/OpenAI/OpenAIAPICreditBalanceFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/OpenAI/OpenAIAPIProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/OpenAI/OpenAIAPISettingsReader.swift create mode 100644 Sources/CodexBarCore/Providers/OpenAI/OpenAIAPIUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/OpenAI/OpenAIAPIUsageResponses.swift create mode 100644 Sources/CodexBarCore/Providers/OpenAI/OpenAIAPIUsageSnapshot.swift create mode 100644 Sources/CodexBarCore/Providers/OpenCode/OpenCodeCookieImporter.swift create mode 100644 Sources/CodexBarCore/Providers/OpenCode/OpenCodeProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/OpenCode/OpenCodeUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/OpenCode/OpenCodeUsageSnapshot.swift create mode 100644 Sources/CodexBarCore/Providers/OpenCode/OpenCodeWebCookieSupport.swift create mode 100644 Sources/CodexBarCore/Providers/OpenCodeGo/OpenCodeGoLocalUsageReader.swift create mode 100644 Sources/CodexBarCore/Providers/OpenCodeGo/OpenCodeGoProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/OpenCodeGo/OpenCodeGoUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/OpenCodeGo/OpenCodeGoUsageSnapshot.swift create mode 100644 Sources/CodexBarCore/Providers/OpenCodeGo/OpenCodeGoZenBalanceFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/OpenCodeGo/OpenCodeGoZenBalanceParser.swift create mode 100644 Sources/CodexBarCore/Providers/OpenRouter/OpenRouterProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/OpenRouter/OpenRouterSettingsReader.swift create mode 100644 Sources/CodexBarCore/Providers/OpenRouter/OpenRouterUsageStats.swift create mode 100644 Sources/CodexBarCore/Providers/Perplexity/PerplexityAPIError.swift create mode 100644 Sources/CodexBarCore/Providers/Perplexity/PerplexityCookieHeader.swift create mode 100644 Sources/CodexBarCore/Providers/Perplexity/PerplexityCookieImporter.swift create mode 100644 Sources/CodexBarCore/Providers/Perplexity/PerplexityModels.swift create mode 100644 Sources/CodexBarCore/Providers/Perplexity/PerplexityProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Perplexity/PerplexitySettingsReader.swift create mode 100644 Sources/CodexBarCore/Providers/Perplexity/PerplexityUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/Perplexity/PerplexityUsageSnapshot.swift create mode 100644 Sources/CodexBarCore/Providers/Poe/PoeProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Poe/PoeSettingsReader.swift create mode 100644 Sources/CodexBarCore/Providers/Poe/PoeUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/Poe/PoeUsageHistorySnapshot.swift create mode 100644 Sources/CodexBarCore/Providers/Poe/PoeUsageSnapshot.swift create mode 100644 Sources/CodexBarCore/Providers/ProviderBranding.swift create mode 100644 Sources/CodexBarCore/Providers/ProviderCLIConfig.swift create mode 100644 Sources/CodexBarCore/Providers/ProviderCandidateRetryRunner.swift create mode 100644 Sources/CodexBarCore/Providers/ProviderCookieSettingsResolver.swift create mode 100644 Sources/CodexBarCore/Providers/ProviderCookieSource.swift create mode 100644 Sources/CodexBarCore/Providers/ProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/ProviderDiagnosticExport.swift create mode 100644 Sources/CodexBarCore/Providers/ProviderEnvironmentResolver.swift create mode 100644 Sources/CodexBarCore/Providers/ProviderFetchPlan.swift create mode 100644 Sources/CodexBarCore/Providers/ProviderInteractionContext.swift create mode 100644 Sources/CodexBarCore/Providers/ProviderSettingsSnapshot.swift create mode 100644 Sources/CodexBarCore/Providers/ProviderTokenResolver.swift create mode 100644 Sources/CodexBarCore/Providers/ProviderVersionDetector.swift create mode 100644 Sources/CodexBarCore/Providers/Providers.swift create mode 100644 Sources/CodexBarCore/Providers/Qoder/QoderCookieImporter.swift create mode 100644 Sources/CodexBarCore/Providers/Qoder/QoderProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Qoder/QoderUsageError.swift create mode 100644 Sources/CodexBarCore/Providers/Qoder/QoderUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/Qoder/QoderUsageSnapshot.swift create mode 100644 Sources/CodexBarCore/Providers/Sakana/SakanaProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Sakana/SakanaSettingsReader.swift create mode 100644 Sources/CodexBarCore/Providers/Sakana/SakanaUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/StepFun/StepFunProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/StepFun/StepFunSettingsReader.swift create mode 100644 Sources/CodexBarCore/Providers/StepFun/StepFunUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/Sub2API/Sub2APIProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Sub2API/Sub2APISettingsReader.swift create mode 100644 Sources/CodexBarCore/Providers/Sub2API/Sub2APIUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/Synthetic/SyntheticProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Synthetic/SyntheticSettingsReader.swift create mode 100644 Sources/CodexBarCore/Providers/Synthetic/SyntheticUsageStats.swift create mode 100644 Sources/CodexBarCore/Providers/T3Chat/T3ChatProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/T3Chat/T3ChatUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/T3Chat/T3ChatUsageSnapshot.swift create mode 100644 Sources/CodexBarCore/Providers/Venice/VeniceProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Venice/VeniceSettingsReader.swift create mode 100644 Sources/CodexBarCore/Providers/Venice/VeniceUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/VertexAI/VertexAIOAuth/VertexAIOAuthCredentials.swift create mode 100644 Sources/CodexBarCore/Providers/VertexAI/VertexAIOAuth/VertexAITokenRefresher.swift create mode 100644 Sources/CodexBarCore/Providers/VertexAI/VertexAIOAuth/VertexAIUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/VertexAI/VertexAIProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Warp/WarpProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Warp/WarpSettingsReader.swift create mode 100644 Sources/CodexBarCore/Providers/Warp/WarpUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/Wayfinder/WayfinderProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Wayfinder/WayfinderSettingsReader.swift create mode 100644 Sources/CodexBarCore/Providers/Wayfinder/WayfinderUsageFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/Windsurf/WindsurfDevinSessionImporter.swift create mode 100644 Sources/CodexBarCore/Providers/Windsurf/WindsurfProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Windsurf/WindsurfStatusProbe.swift create mode 100644 Sources/CodexBarCore/Providers/Windsurf/WindsurfUsageDataSource.swift create mode 100644 Sources/CodexBarCore/Providers/Windsurf/WindsurfWebFetcher.swift create mode 100644 Sources/CodexBarCore/Providers/Zai/ZaiAPIRegion.swift create mode 100644 Sources/CodexBarCore/Providers/Zai/ZaiProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Zai/ZaiSettingsReader.swift create mode 100644 Sources/CodexBarCore/Providers/Zai/ZaiUsageStats.swift create mode 100644 Sources/CodexBarCore/Providers/Zed/ZedProviderDescriptor.swift create mode 100644 Sources/CodexBarCore/Providers/Zed/ZedStatusProbe.swift create mode 100644 Sources/CodexBarCore/RemoteSessionFetcher.swift create mode 100644 Sources/CodexBarCore/SessionWindowFocuser.swift create mode 100644 Sources/CodexBarCore/TextParsing.swift create mode 100644 Sources/CodexBarCore/TokenAccountSupport.swift create mode 100644 Sources/CodexBarCore/TokenAccountSupportCatalog+Data.swift create mode 100644 Sources/CodexBarCore/TokenAccounts.swift create mode 100644 Sources/CodexBarCore/UsageChartScale.swift create mode 100644 Sources/CodexBarCore/UsageFetcher.swift create mode 100644 Sources/CodexBarCore/UsageFormatter.swift create mode 100644 Sources/CodexBarCore/UsagePace.swift create mode 100644 Sources/CodexBarCore/Vendored/CostUsage/CostUsageCache.swift create mode 100644 Sources/CodexBarCore/Vendored/CostUsage/CostUsageJsonl.swift create mode 100644 Sources/CodexBarCore/Vendored/CostUsage/CostUsagePricing.swift create mode 100644 Sources/CodexBarCore/Vendored/CostUsage/CostUsagePricingKey.swift create mode 100644 Sources/CodexBarCore/Vendored/CostUsage/CostUsageScanner+CacheHelpers.swift create mode 100644 Sources/CodexBarCore/Vendored/CostUsage/CostUsageScanner+Claude.swift create mode 100644 Sources/CodexBarCore/Vendored/CostUsage/CostUsageScanner+CodexFastJSON.swift create mode 100644 Sources/CodexBarCore/Vendored/CostUsage/CostUsageScanner+CodexPriority.swift create mode 100644 Sources/CodexBarCore/Vendored/CostUsage/CostUsageScanner+CodexTruncatedPrefix.swift create mode 100644 Sources/CodexBarCore/Vendored/CostUsage/CostUsageScanner+Projects.swift create mode 100644 Sources/CodexBarCore/Vendored/CostUsage/CostUsageScanner+Timestamp.swift create mode 100644 Sources/CodexBarCore/Vendored/CostUsage/CostUsageScanner.swift create mode 100644 Sources/CodexBarCore/Vendored/CostUsage/ModelsDevPricing.swift create mode 100644 Sources/CodexBarCore/WebKit/WebKitTeardown.swift create mode 100644 Sources/CodexBarCore/WidgetSnapshot.swift create mode 100644 Sources/CodexBarWidget/BurnDownWidgetProvider.swift create mode 100644 Sources/CodexBarWidget/BurnDownWidgetViews.swift create mode 100644 Sources/CodexBarWidget/CodexBarWidgetBundle.swift create mode 100644 Sources/CodexBarWidget/CodexBarWidgetProvider.swift create mode 100644 Sources/CodexBarWidget/CodexBarWidgetViews.swift create mode 100644 Sources/CodexBarWidget/CombinedBurnDownWidgetViews.swift create mode 100644 Tests/AdaptiveReplayCLITests/CLIArgumentsTests.swift create mode 100644 Tests/AdaptiveReplayKitTests/ActivityCoverageStatsTests.swift create mode 100644 Tests/AdaptiveReplayKitTests/AdaptiveRefreshPolicyCoreTests.swift create mode 100644 Tests/AdaptiveReplayKitTests/AdaptiveReplayEngineTests.swift create mode 100644 Tests/AdaptiveReplayKitTests/AdaptiveReplayPolicyTests.swift create mode 100644 Tests/AdaptiveReplayKitTests/AdaptiveReplayTraceParserTests.swift create mode 100644 Tests/AdaptiveReplayKitTests/CodingActivityReplayPolicyTests.swift create mode 100644 Tests/AdaptiveReplayKitTests/RecordedScheduleAuditTests.swift create mode 100644 Tests/AdaptiveReplayKitTests/ReplayTraceSegmentationTests.swift create mode 100644 Tests/CodexBarTests/APITokenFetchStrategyTests.swift create mode 100644 Tests/CodexBarTests/AbacusProviderTests.swift create mode 100644 Tests/CodexBarTests/AdaptiveRefreshHeuristicsTests.swift create mode 100644 Tests/CodexBarTests/AdaptiveRefreshPolicyTests.swift create mode 100644 Tests/CodexBarTests/AdaptiveRefreshTimerTests.swift create mode 100644 Tests/CodexBarTests/AdminAPIUsageLocalDaySelectionTests.swift create mode 100644 Tests/CodexBarTests/AgentSessionJSONTests.swift create mode 100644 Tests/CodexBarTests/AgentSessionMenuDescriptorTests.swift create mode 100644 Tests/CodexBarTests/AgentSessionParserTests.swift create mode 100644 Tests/CodexBarTests/AlibabaCodingPlanCookieImporterTests.swift create mode 100644 Tests/CodexBarTests/AlibabaCodingPlanMenuCardModelTests.swift create mode 100644 Tests/CodexBarTests/AlibabaCodingPlanProviderTests.swift create mode 100644 Tests/CodexBarTests/AlibabaTokenPlanDashboardActionTests.swift create mode 100644 Tests/CodexBarTests/AlibabaTokenPlanMenuCardModelTests.swift create mode 100644 Tests/CodexBarTests/AlibabaTokenPlanProviderTests.swift create mode 100644 Tests/CodexBarTests/AmpUsageFetcherTests.swift create mode 100644 Tests/CodexBarTests/AmpUsageParserTests.swift create mode 100644 Tests/CodexBarTests/AntigravityCLIHTTPSFetchStrategyTests.swift create mode 100644 Tests/CodexBarTests/AntigravityCLISessionTests.swift create mode 100644 Tests/CodexBarTests/AntigravityCompactFallbackTests.swift create mode 100644 Tests/CodexBarTests/AntigravityDeadlineTests.swift create mode 100644 Tests/CodexBarTests/AntigravityLocalSnapshotSelectionTests.swift create mode 100644 Tests/CodexBarTests/AntigravityLoginAlertTests.swift create mode 100644 Tests/CodexBarTests/AntigravityModelLabelTests.swift create mode 100644 Tests/CodexBarTests/AntigravityOAuthCredentialsStoreTests.swift create mode 100644 Tests/CodexBarTests/AntigravityQuotaSummaryTests.swift create mode 100644 Tests/CodexBarTests/AntigravityRemoteUsageFetcherTests.swift create mode 100644 Tests/CodexBarTests/AntigravityStatusProbeTests.swift create mode 100644 Tests/CodexBarTests/AntigravityWarmAgyReuseTests.swift create mode 100644 Tests/CodexBarTests/AppDelegateTests.swift create mode 100644 Tests/CodexBarTests/AppGroupSupportTests.swift create mode 100644 Tests/CodexBarTests/AuggieCLIProbeParseTests.swift create mode 100644 Tests/CodexBarTests/AugmentCLIFetchStrategyFallbackTests.swift create mode 100644 Tests/CodexBarTests/AugmentProviderRuntimeTests.swift create mode 100644 Tests/CodexBarTests/AugmentStatusProbeTests.swift create mode 100644 Tests/CodexBarTests/AzureOpenAIUsageFetcherTests.swift create mode 100644 Tests/CodexBarTests/BatteryDrainDiagnosticTests.swift create mode 100644 Tests/CodexBarTests/BedrockCredentialResolverTests.swift create mode 100644 Tests/CodexBarTests/BedrockMenuCardTests.swift create mode 100644 Tests/CodexBarTests/BedrockProfileCredentialProviderTests.swift create mode 100644 Tests/CodexBarTests/BedrockSettingsFlowTests.swift create mode 100644 Tests/CodexBarTests/BedrockSettingsReaderTests.swift create mode 100644 Tests/CodexBarTests/BedrockUsageStatsTests.swift create mode 100644 Tests/CodexBarTests/BrowserCookieOrderLabelTests.swift create mode 100644 Tests/CodexBarTests/BrowserDetectionTests.swift create mode 100644 Tests/CodexBarTests/CLIArgumentParsingTests.swift create mode 100644 Tests/CodexBarTests/CLICacheTests.swift create mode 100644 Tests/CodexBarTests/CLICardsRendererTests.swift create mode 100644 Tests/CodexBarTests/CLIConfigCommandTests.swift create mode 100644 Tests/CodexBarTests/CLICostTests.swift create mode 100644 Tests/CodexBarTests/CLIDiagnoseCommandTests.swift create mode 100644 Tests/CodexBarTests/CLIEntryTests.swift create mode 100644 Tests/CodexBarTests/CLIOpenAIDashboardCacheTests.swift create mode 100644 Tests/CodexBarTests/CLIOutputTests.swift create mode 100644 Tests/CodexBarTests/CLIProviderSelectionTests.swift create mode 100644 Tests/CodexBarTests/CLIServeRouterTests.swift create mode 100644 Tests/CodexBarTests/CLIServeTimeoutTests.swift create mode 100644 Tests/CodexBarTests/CLISnapshotTests.swift create mode 100644 Tests/CodexBarTests/CLIWebFallbackTests.swift create mode 100644 Tests/CodexBarTests/ChartBarHoverSelectionTests.swift create mode 100644 Tests/CodexBarTests/ChutesProviderTests.swift create mode 100644 Tests/CodexBarTests/ClaudeAdminAPIInlineDashboardModelTests.swift create mode 100644 Tests/CodexBarTests/ClaudeAdminAPIUsageTests.swift create mode 100644 Tests/CodexBarTests/ClaudeBaselineCharacterizationTests.swift create mode 100644 Tests/CodexBarTests/ClaudeCLIAuthStatusProbeTests.swift create mode 100644 Tests/CodexBarTests/ClaudeCLIScopedWeeklyUsageTests.swift create mode 100644 Tests/CodexBarTests/ClaudeCLITimeoutRetryTests.swift create mode 100644 Tests/CodexBarTests/ClaudeCredentialRoutingTests.swift create mode 100644 Tests/CodexBarTests/ClaudeDebugDiagnosticsTests.swift create mode 100644 Tests/CodexBarTests/ClaudeDirectUsageFallbackTests.swift create mode 100644 Tests/CodexBarTests/ClaudeEducationAvailabilityTests.swift create mode 100644 Tests/CodexBarTests/ClaudeExtraWindowQuotaWarningTests.swift create mode 100644 Tests/CodexBarTests/ClaudeLoginFlowPolicyTests.swift create mode 100644 Tests/CodexBarTests/ClaudeLoginRunnerTests.swift create mode 100644 Tests/CodexBarTests/ClaudeOAuthCredentialsStoreCLIStorageOwnershipTests.swift create mode 100644 Tests/CodexBarTests/ClaudeOAuthCredentialsStoreIsolatedSecurityCLITests.swift create mode 100644 Tests/CodexBarTests/ClaudeOAuthCredentialsStoreMCPOnlyGuardTests.swift create mode 100644 Tests/CodexBarTests/ClaudeOAuthCredentialsStoreNeverPromptCacheTests.swift create mode 100644 Tests/CodexBarTests/ClaudeOAuthCredentialsStorePromptPolicyTests.swift create mode 100644 Tests/CodexBarTests/ClaudeOAuthCredentialsStoreSecurityCLIFallbackPolicyTests.swift create mode 100644 Tests/CodexBarTests/ClaudeOAuthCredentialsStoreSecurityCLITests.swift create mode 100644 Tests/CodexBarTests/ClaudeOAuthCredentialsStoreTemporaryKeychainCacheTests.swift create mode 100644 Tests/CodexBarTests/ClaudeOAuthCredentialsStoreTests.swift create mode 100644 Tests/CodexBarTests/ClaudeOAuthDelegatedRefreshCoordinatorTests.swift create mode 100644 Tests/CodexBarTests/ClaudeOAuthDelegatedRefreshRecoveryTests.swift create mode 100644 Tests/CodexBarTests/ClaudeOAuthFetchStrategyAvailabilityTests.swift create mode 100644 Tests/CodexBarTests/ClaudeOAuthHistoryCredentialRoutingTests.swift create mode 100644 Tests/CodexBarTests/ClaudeOAuthKeychainAccessGateTests.swift create mode 100644 Tests/CodexBarTests/ClaudeOAuthKeychainPreAlertGateTests.swift create mode 100644 Tests/CodexBarTests/ClaudeOAuthRefreshDispositionTests.swift create mode 100644 Tests/CodexBarTests/ClaudeOAuthRefreshFailureGateTests.swift create mode 100644 Tests/CodexBarTests/ClaudeOAuthTests.swift create mode 100644 Tests/CodexBarTests/ClaudePlanResolverTests.swift create mode 100644 Tests/CodexBarTests/ClaudeProbeWorkingDirectoryTests.swift create mode 100644 Tests/CodexBarTests/ClaudeProviderRuntimeTests.swift create mode 100644 Tests/CodexBarTests/ClaudeResetJSONParserTests.swift create mode 100644 Tests/CodexBarTests/ClaudeResetOccurrenceTests.swift create mode 100644 Tests/CodexBarTests/ClaudeResilienceTests.swift create mode 100644 Tests/CodexBarTests/ClaudeScopedWeeklyLimitMapperTests.swift create mode 100644 Tests/CodexBarTests/ClaudeSessionMappingTests.swift create mode 100644 Tests/CodexBarTests/ClaudeSourcePlannerTests.swift create mode 100644 Tests/CodexBarTests/ClaudeSwapAccountProjectionTests.swift create mode 100644 Tests/CodexBarTests/ClaudeSwapAccountReaderTests.swift create mode 100644 Tests/CodexBarTests/ClaudeSwapListParserTests.swift create mode 100644 Tests/CodexBarTests/ClaudeSwapMenuPrecedenceTests.swift create mode 100644 Tests/CodexBarTests/ClaudeSwapSwitchParserTests.swift create mode 100644 Tests/CodexBarTests/ClaudeSyntheticPlaceholderNotificationTests.swift create mode 100644 Tests/CodexBarTests/ClaudeSyntheticPlaceholderPlanUtilizationTests.swift create mode 100644 Tests/CodexBarTests/ClaudeUsageDelegatedRefreshEnvironmentTests.swift create mode 100644 Tests/CodexBarTests/ClaudeUsageTests.swift create mode 100644 Tests/CodexBarTests/ClaudeWebCookieRenewalTests.swift create mode 100644 Tests/CodexBarTests/ClaudeWebEnterpriseUsageTests.swift create mode 100644 Tests/CodexBarTests/ClaudeWebFetchDeadlineTests.swift create mode 100644 Tests/CodexBarTests/ClaudeWebRecoveryMenuTests.swift create mode 100644 Tests/CodexBarTests/ClaudeWebRefreshResilienceTests.swift create mode 100644 Tests/CodexBarTests/ClaudeWebUsageExtraWindowTests.swift create mode 100644 Tests/CodexBarTests/ClawRouterUsageFetcherTests.swift create mode 100644 Tests/CodexBarTests/ClickToCopyOverlayTests.swift create mode 100644 Tests/CodexBarTests/CodebuffSettingsReaderTests.swift create mode 100644 Tests/CodexBarTests/CodebuffUsageFetcherTests.swift create mode 100644 Tests/CodexBarTests/CodexAccountAuthFingerprintApplyTests.swift create mode 100644 Tests/CodexBarTests/CodexAccountCompositeGuardTests.swift create mode 100644 Tests/CodexBarTests/CodexAccountEmailOnlyHistoryBackfillTests.swift create mode 100644 Tests/CodexBarTests/CodexAccountFingerprintReconciliationTests.swift create mode 100644 Tests/CodexBarTests/CodexAccountMenuDisplaySnapshotTests.swift create mode 100644 Tests/CodexBarTests/CodexAccountPromotionExecutionTests.swift create mode 100644 Tests/CodexBarTests/CodexAccountPromotionPlanningTests.swift create mode 100644 Tests/CodexBarTests/CodexAccountPromotionPreparationTests.swift create mode 100644 Tests/CodexBarTests/CodexAccountPromotionServiceTests.swift create mode 100644 Tests/CodexBarTests/CodexAccountPromotionTestSupport.swift create mode 100644 Tests/CodexBarTests/CodexAccountProviderIdentityReconciliationTests.swift create mode 100644 Tests/CodexBarTests/CodexAccountReconciliationTests.swift create mode 100644 Tests/CodexBarTests/CodexAccountRefreshProjectionTests.swift create mode 100644 Tests/CodexBarTests/CodexAccountScopedRefreshCreditsTests.swift create mode 100644 Tests/CodexBarTests/CodexAccountScopedRefreshDashboardCleanupTests.swift create mode 100644 Tests/CodexBarTests/CodexAccountScopedRefreshTestSupport.swift create mode 100644 Tests/CodexBarTests/CodexAccountScopedRefreshTests.swift create mode 100644 Tests/CodexBarTests/CodexAccountVisibleHistoryBackfillTests.swift create mode 100644 Tests/CodexBarTests/CodexAccountsSectionStateTests.swift create mode 100644 Tests/CodexBarTests/CodexAccountsSettingsSectionTests.swift create mode 100644 Tests/CodexBarTests/CodexActiveSourceConfigTests.swift create mode 100644 Tests/CodexBarTests/CodexAdditionalRateLimitsTests.swift create mode 100644 Tests/CodexBarTests/CodexBackgroundRefreshCoalescingTests.swift create mode 100644 Tests/CodexBarTests/CodexBarConfigMigratorTests.swift create mode 100644 Tests/CodexBarTests/CodexBarWidgetProviderTests.swift create mode 100644 Tests/CodexBarTests/CodexBaselineCharacterizationTests.swift create mode 100644 Tests/CodexBarTests/CodexCLILaunchGateTests.swift create mode 100644 Tests/CodexBarTests/CodexCLIWindowNormalizationTests.swift create mode 100644 Tests/CodexBarTests/CodexCombinedMetricHighestUsageTests.swift create mode 100644 Tests/CodexBarTests/CodexConsumerProjectionCharacterizationTests.swift create mode 100644 Tests/CodexBarTests/CodexConsumerProjectionTests.swift create mode 100644 Tests/CodexBarTests/CodexDashboardAuthorityTests.swift create mode 100644 Tests/CodexBarTests/CodexDashboardWeeklyPublicationTests.swift create mode 100644 Tests/CodexBarTests/CodexDashboardWorkedExampleParityTests.swift create mode 100644 Tests/CodexBarTests/CodexHistoryOwnershipTests.swift create mode 100644 Tests/CodexBarTests/CodexIdentityResolverTests.swift create mode 100644 Tests/CodexBarTests/CodexLegacyWidgetSnapshotTests.swift create mode 100644 Tests/CodexBarTests/CodexLimitResetOwnerKeyTests.swift create mode 100644 Tests/CodexBarTests/CodexLoginRunnerTests.swift create mode 100644 Tests/CodexBarTests/CodexManagedOpenAIWebRefreshTests.swift create mode 100644 Tests/CodexBarTests/CodexManagedOpenAIWebTestSupport.swift create mode 100644 Tests/CodexBarTests/CodexManagedOpenAIWebTests.swift create mode 100644 Tests/CodexBarTests/CodexManagedRoutingTests.swift create mode 100644 Tests/CodexBarTests/CodexOAuthCredentialsStorePermissionsTests.swift create mode 100644 Tests/CodexBarTests/CodexOAuthCreditLimitTests.swift create mode 100644 Tests/CodexBarTests/CodexOAuthRequestTests.swift create mode 100644 Tests/CodexBarTests/CodexOAuthResetCreditFetchTests.swift create mode 100644 Tests/CodexBarTests/CodexOAuthTests.swift create mode 100644 Tests/CodexBarTests/CodexOpenAIWorkspaceResolverTests.swift create mode 100644 Tests/CodexBarTests/CodexPlanFormattingTests.swift create mode 100644 Tests/CodexBarTests/CodexPresentationCharacterizationTests.swift create mode 100644 Tests/CodexBarTests/CodexProfileHomeAccountTests.swift create mode 100644 Tests/CodexBarTests/CodexProviderSettingsBuilderTests.swift create mode 100644 Tests/CodexBarTests/CodexRateLimitResetCreditsTests.swift create mode 100644 Tests/CodexBarTests/CodexResetBackfillSemanticsTests.swift create mode 100644 Tests/CodexBarTests/CodexResetCreditExpiryNotifierTests.swift create mode 100644 Tests/CodexBarTests/CodexResetCreditOutcomeTests.swift create mode 100644 Tests/CodexBarTests/CodexResetCreditsMenuCardTests.swift create mode 100644 Tests/CodexBarTests/CodexSessionQuotaFalseRestoreTests.swift create mode 100644 Tests/CodexBarTests/CodexSessionRolloutTests.swift create mode 100644 Tests/CodexBarTests/CodexSystemAccountObserverTests.swift create mode 100644 Tests/CodexBarTests/CodexSystemPromotionUITests.swift create mode 100644 Tests/CodexBarTests/CodexUsageFetcherFallbackTests.swift create mode 100644 Tests/CodexBarTests/CodexUsageOwnerRaceTests.swift create mode 100644 Tests/CodexBarTests/CodexUserFacingErrorTests.swift create mode 100644 Tests/CodexBarTests/CodexVisibleAccountProjectionRuntimeIdentityTests.swift create mode 100644 Tests/CodexBarTests/CodexVisibleAccountTests.swift create mode 100644 Tests/CodexBarTests/CodexWebDashboardStrategyAuthorityTests.swift create mode 100644 Tests/CodexBarTests/CodexWeeklyCapSurfaceTests.swift create mode 100644 Tests/CodexBarTests/CodexWeeklyResetConfirmationTests.swift create mode 100644 Tests/CodexBarTests/CodexWeeklyResetFailureBaselineTests.swift create mode 100644 Tests/CodexBarTests/CodexWeeklyResetOwnerTransitionTests.swift create mode 100644 Tests/CodexBarTests/CodexWeeklyResetPublicationTests.swift create mode 100644 Tests/CodexBarTests/CodexbarTests.swift create mode 100644 Tests/CodexBarTests/CommandCodeProviderTests.swift create mode 100644 Tests/CodexBarTests/CommandCodeQuotaTransitionTests.swift create mode 100644 Tests/CodexBarTests/CommandCodeUsageFetcherTests.swift create mode 100644 Tests/CodexBarTests/ConfigValidationTests.swift create mode 100644 Tests/CodexBarTests/ConfigurationDocsProviderIDTests.swift create mode 100644 Tests/CodexBarTests/CookieHeaderCacheConditionalMutationTests.swift create mode 100644 Tests/CodexBarTests/CookieHeaderCacheTests.swift create mode 100644 Tests/CodexBarTests/CookieHeaderNormalizerTests.swift create mode 100644 Tests/CodexBarTests/CopilotBudgetCookieRoutingTests.swift create mode 100644 Tests/CodexBarTests/CopilotBudgetWebFetcherTests.swift create mode 100644 Tests/CodexBarTests/CopilotDeviceFlowTests.swift create mode 100644 Tests/CodexBarTests/CopilotMenuCardModelTests.swift create mode 100644 Tests/CodexBarTests/CopilotMultiAccountTests.swift create mode 100644 Tests/CodexBarTests/CopilotUsageFetcherTests.swift create mode 100644 Tests/CodexBarTests/CopilotUsageModelsTests.swift create mode 100644 Tests/CodexBarTests/CostHistoryChartMenuViewTests.swift create mode 100644 Tests/CodexBarTests/CostUsageCacheTests.swift create mode 100644 Tests/CodexBarTests/CostUsageCancellationTests.swift create mode 100644 Tests/CodexBarTests/CostUsageDailyReportMergeTests.swift create mode 100644 Tests/CodexBarTests/CostUsageDecodingTests.swift create mode 100644 Tests/CodexBarTests/CostUsageFetcherCacheSnapshotTests.swift create mode 100644 Tests/CodexBarTests/CostUsageFetcherTests.swift create mode 100644 Tests/CodexBarTests/CostUsageFetcherUnknownModelPricingTests.swift create mode 100644 Tests/CodexBarTests/CostUsageJsonlPerformanceTests.swift create mode 100644 Tests/CodexBarTests/CostUsageJsonlScannerTests.swift create mode 100644 Tests/CodexBarTests/CostUsageJsonlShapeBenchmarkTests.swift create mode 100644 Tests/CodexBarTests/CostUsagePerformanceGateTests.swift create mode 100644 Tests/CodexBarTests/CostUsagePricingTests.swift create mode 100644 Tests/CodexBarTests/CostUsageScanExecutorTests.swift create mode 100644 Tests/CodexBarTests/CostUsageScannerBreakdownTests.swift create mode 100644 Tests/CodexBarTests/CostUsageScannerClaudeDesktopTests.swift create mode 100644 Tests/CodexBarTests/CostUsageScannerClaudeFableTests.swift create mode 100644 Tests/CodexBarTests/CostUsageScannerClaudeRegressionTests.swift create mode 100644 Tests/CodexBarTests/CostUsageScannerCodexPriorityTests.swift create mode 100644 Tests/CodexBarTests/CostUsageScannerPriorityTests.swift create mode 100644 Tests/CodexBarTests/CostUsageScannerTests.swift create mode 100644 Tests/CodexBarTests/CostUsageTokenSnapshotDaySelectionTests.swift create mode 100644 Tests/CodexBarTests/CostUsageWindowSummaryTests.swift create mode 100644 Tests/CodexBarTests/CrofMenuCardTests.swift create mode 100644 Tests/CodexBarTests/CrofProviderImplementationTests.swift create mode 100644 Tests/CodexBarTests/CrofUsageFetcherTests.swift create mode 100644 Tests/CodexBarTests/CrossModelUsageStatsTests.swift create mode 100644 Tests/CodexBarTests/CursorEnterpriseUsageTests.swift create mode 100644 Tests/CodexBarTests/CursorLegacyRequestProjectionTests.swift create mode 100644 Tests/CodexBarTests/CursorLoginRunnerTests.swift create mode 100644 Tests/CodexBarTests/CursorMenuCardModelTests.swift create mode 100644 Tests/CodexBarTests/CursorStatusProbeTests.swift create mode 100644 Tests/CodexBarTests/DeepSeekSettingsReaderTests.swift create mode 100644 Tests/CodexBarTests/DeepSeekUsageCostParserTests.swift create mode 100644 Tests/CodexBarTests/DeepSeekUsageFetcherTests.swift create mode 100644 Tests/CodexBarTests/DeepgramProviderTests.swift create mode 100644 Tests/CodexBarTests/DeferredMenuInteractionRefreshTailTests.swift create mode 100644 Tests/CodexBarTests/DevinUsageFetcherTests.swift create mode 100644 Tests/CodexBarTests/DocumentationLinkTests.swift create mode 100644 Tests/CodexBarTests/DoubaoMenuCardModelTests.swift create mode 100644 Tests/CodexBarTests/DoubaoProviderTests.swift create mode 100644 Tests/CodexBarTests/DoubaoUsageFetcherTests.swift create mode 100644 Tests/CodexBarTests/ElevenLabsUsageFetcherTests.swift create mode 100644 Tests/CodexBarTests/FactoryAPIKeyUsageTests.swift create mode 100644 Tests/CodexBarTests/FactoryManualCredentialTests.swift create mode 100644 Tests/CodexBarTests/FactoryProviderImplementationTests.swift create mode 100644 Tests/CodexBarTests/FactoryStatusProbeFetchTests.swift create mode 100644 Tests/CodexBarTests/FactoryStatusProbeTests.swift create mode 100644 Tests/CodexBarTests/Fixtures/CostUsage/Issue2037/archived-fork-33ce-3869/ORACLE.md create mode 100644 Tests/CodexBarTests/Fixtures/CostUsage/Issue2037/archived-fork-33ce-3869/codex-home/archived_sessions/child.jsonl create mode 100644 Tests/CodexBarTests/Fixtures/CostUsage/Issue2037/archived-fork-33ce-3869/codex-home/archived_sessions/parent.jsonl create mode 100644 Tests/CodexBarTests/Fixtures/CostUsage/Issue2037/archived-fork-33ce-3869/manifest.json create mode 100644 Tests/CodexBarTests/Fixtures/CostUsage/Issue2037/harness-smoke/codex-home/archived_sessions/child.jsonl create mode 100644 Tests/CodexBarTests/Fixtures/CostUsage/Issue2037/harness-smoke/codex-home/sessions/2026/07/11/parent.jsonl create mode 100644 Tests/CodexBarTests/Fixtures/CostUsage/Issue2037/harness-smoke/manifest.json create mode 100644 Tests/CodexBarTests/Fixtures/CostUsage/Issue2037/live-fork-4d90-52bf/ORACLE.md create mode 100644 Tests/CodexBarTests/Fixtures/CostUsage/Issue2037/live-fork-4d90-52bf/codex-home/archived_sessions/child.jsonl create mode 100644 Tests/CodexBarTests/Fixtures/CostUsage/Issue2037/live-fork-4d90-52bf/codex-home/archived_sessions/parent.jsonl create mode 100644 Tests/CodexBarTests/Fixtures/CostUsage/Issue2037/live-fork-4d90-52bf/manifest.json create mode 100644 Tests/CodexBarTests/Fixtures/CostUsage/Issue2037/missing-parent-siblings/ORACLE.md create mode 100644 Tests/CodexBarTests/Fixtures/CostUsage/Issue2037/missing-parent-siblings/codex-home/archived_sessions/sibling-a.jsonl create mode 100644 Tests/CodexBarTests/Fixtures/CostUsage/Issue2037/missing-parent-siblings/codex-home/archived_sessions/sibling-b.jsonl create mode 100644 Tests/CodexBarTests/Fixtures/CostUsage/Issue2037/missing-parent-siblings/manifest.json create mode 100644 Tests/CodexBarTests/Fixtures/Providers/Claude/weekly-limit.json create mode 100644 Tests/CodexBarTests/Fixtures/Providers/MiniMax/token-plan-missing-reset.json create mode 100644 Tests/CodexBarTests/Fixtures/Providers/MiniMax/token-plan-normal.json create mode 100644 Tests/CodexBarTests/Fixtures/Providers/OpenAI/pro-normal.html create mode 100644 Tests/CodexBarTests/Fixtures/agent-session-rollout.jsonl create mode 100644 Tests/CodexBarTests/Fixtures/agent-sessions-lsof.txt create mode 100644 Tests/CodexBarTests/Fixtures/agent-sessions-ps.txt create mode 100644 Tests/CodexBarTests/Fixtures/agent-sessions-tailscale.json create mode 100644 Tests/CodexBarTests/Fixtures/codex-historical-usage-real-legacy.jsonl create mode 100644 Tests/CodexBarTests/Fixtures/codex-plan-utilization-real-migration.json create mode 100644 Tests/CodexBarTests/Fixtures/models-dev-subset.json create mode 100644 Tests/CodexBarTests/GeminiAPITestHelpers.swift create mode 100644 Tests/CodexBarTests/GeminiConsumerTierMigrationTests.swift create mode 100644 Tests/CodexBarTests/GeminiLoginAlertTests.swift create mode 100644 Tests/CodexBarTests/GeminiMenuCardTests.swift create mode 100644 Tests/CodexBarTests/GeminiOAuthConfigTests.swift create mode 100644 Tests/CodexBarTests/GeminiOAuthRecoveryAPITests.swift create mode 100644 Tests/CodexBarTests/GeminiPrimaryWindowTests.swift create mode 100644 Tests/CodexBarTests/GeminiProviderMigrationSettingsTests.swift create mode 100644 Tests/CodexBarTests/GeminiSourceLabelTests.swift create mode 100644 Tests/CodexBarTests/GeminiStatusProbeAPITests.swift create mode 100644 Tests/CodexBarTests/GeminiStatusProbePlanTests.swift create mode 100644 Tests/CodexBarTests/GeminiStatusProbeTests.swift create mode 100644 Tests/CodexBarTests/GeminiTestEnvironment.swift create mode 100644 Tests/CodexBarTests/GoogleWorkspaceStatusNetworkTests.swift create mode 100644 Tests/CodexBarTests/GoogleWorkspaceStatusTests.swift create mode 100644 Tests/CodexBarTests/GrokAuthTests.swift create mode 100644 Tests/CodexBarTests/GrokBillingResponseTests.swift create mode 100644 Tests/CodexBarTests/GrokWebBillingFetcherTests.swift create mode 100644 Tests/CodexBarTests/GroqUsageFetcherTests.swift create mode 100644 Tests/CodexBarTests/HistoricalUsagePaceBackfillAuthorityTests.swift create mode 100644 Tests/CodexBarTests/HistoricalUsagePaceOwnershipTests.swift create mode 100644 Tests/CodexBarTests/HistoricalUsagePaceTestSupport.swift create mode 100644 Tests/CodexBarTests/HistoricalUsagePaceTests.swift create mode 100644 Tests/CodexBarTests/IconRendererHideCrittersTests.swift create mode 100644 Tests/CodexBarTests/InlineCostHistoryDashboardLabelTests.swift create mode 100644 Tests/CodexBarTests/InlineUsageDashboardBarColorTests.swift create mode 100644 Tests/CodexBarTests/InstallOriginTests.swift create mode 100644 Tests/CodexBarTests/Issue2037FixtureHarnessTests.swift create mode 100644 Tests/CodexBarTests/Issue2037FixtureSupport.swift create mode 100644 Tests/CodexBarTests/Issue2037ProvenanceFixtureTests.swift create mode 100644 Tests/CodexBarTests/Issue2037ScannerIntegrationTests.swift create mode 100644 Tests/CodexBarTests/JetBrainsIDEDetectorTests.swift create mode 100644 Tests/CodexBarTests/JetBrainsStatusProbeTests.swift create mode 100644 Tests/CodexBarTests/KeyboardShortcutsBundleTests.swift create mode 100644 Tests/CodexBarTests/KeychainCacheStoreTests.swift create mode 100644 Tests/CodexBarTests/KeychainMigrationTests.swift create mode 100644 Tests/CodexBarTests/KeychainNoUIQueryTests.swift create mode 100644 Tests/CodexBarTests/KeychainPromptCoordinatorTests.swift create mode 100644 Tests/CodexBarTests/KeychainPromptSafetyAuditTests.swift create mode 100644 Tests/CodexBarTests/KiloBearerTokenResolverTests.swift create mode 100644 Tests/CodexBarTests/KiloOrganizationTests.swift create mode 100644 Tests/CodexBarTests/KiloSettingsReaderTests.swift create mode 100644 Tests/CodexBarTests/KiloSettingsStoreTests.swift create mode 100644 Tests/CodexBarTests/KiloUsageFetcherTests.swift create mode 100644 Tests/CodexBarTests/KimiK2SettingsReaderTests.swift create mode 100644 Tests/CodexBarTests/KimiK2TokenStoreTestSupport.swift create mode 100644 Tests/CodexBarTests/KimiK2UsageFetcherTests.swift create mode 100644 Tests/CodexBarTests/KimiProviderTests.swift create mode 100644 Tests/CodexBarTests/KiroMenuCardModelTests.swift create mode 100644 Tests/CodexBarTests/KiroStatusProbeTestSupport.swift create mode 100644 Tests/CodexBarTests/KiroStatusProbeTests.swift create mode 100644 Tests/CodexBarTests/KiroTransportRaceTests.swift create mode 100644 Tests/CodexBarTests/LLMProxyUsageFetcherTests.swift create mode 100644 Tests/CodexBarTests/LaunchAtLoginManagerTests.swift create mode 100644 Tests/CodexBarTests/LiteLLMMenuCardModelTests.swift create mode 100644 Tests/CodexBarTests/LiteLLMUsageFetcherTests.swift create mode 100644 Tests/CodexBarTests/LiveAccountTests.swift create mode 100644 Tests/CodexBarTests/LoadingPatternTests.swift create mode 100644 Tests/CodexBarTests/LocalizationBundleCacheTests.swift create mode 100644 Tests/CodexBarTests/LocalizationBundleTests.swift create mode 100644 Tests/CodexBarTests/LocalizationLanguageCatalogTests.swift create mode 100644 Tests/CodexBarTests/LoginNotificationLogicTests.swift create mode 100644 Tests/CodexBarTests/MainThreadHangWatchdogTests.swift create mode 100644 Tests/CodexBarTests/ManagedCodexAccountCoordinatorTests.swift create mode 100644 Tests/CodexBarTests/ManagedCodexAccountServiceTests.swift create mode 100644 Tests/CodexBarTests/ManagedCodexAccountStoreTests.swift create mode 100644 Tests/CodexBarTests/ManusCookieHeaderTests.swift create mode 100644 Tests/CodexBarTests/ManusProviderTests.swift create mode 100644 Tests/CodexBarTests/MemoryPressureCacheTrimTests.swift create mode 100644 Tests/CodexBarTests/MenuBarCountdownRefreshTests.swift create mode 100644 Tests/CodexBarTests/MenuBarMetricWindowResolverTests.swift create mode 100644 Tests/CodexBarTests/MenuBarPaceTextTests.swift create mode 100644 Tests/CodexBarTests/MenuBarResetTimeDisplayTests.swift create mode 100644 Tests/CodexBarTests/MenuBarSmartResetIntegrationTests.swift create mode 100644 Tests/CodexBarTests/MenuBarVisibilityWatcherTests.swift create mode 100644 Tests/CodexBarTests/MenuCardAntigravityTests.swift create mode 100644 Tests/CodexBarTests/MenuCardClaudeSwapAccountTests.swift create mode 100644 Tests/CodexBarTests/MenuCardCostComparisonTests.swift create mode 100644 Tests/CodexBarTests/MenuCardCostHintTests.swift create mode 100644 Tests/CodexBarTests/MenuCardDeepSeekTests.swift create mode 100644 Tests/CodexBarTests/MenuCardHeightFingerprintTests.swift create mode 100644 Tests/CodexBarTests/MenuCardKiloPassTests.swift create mode 100644 Tests/CodexBarTests/MenuCardModelCodexDegradedQuotaTests.swift create mode 100644 Tests/CodexBarTests/MenuCardModelCodexProjectionTests.swift create mode 100644 Tests/CodexBarTests/MenuCardModelTests.swift create mode 100644 Tests/CodexBarTests/MenuCardOptionalUsageModelTests.swift create mode 100644 Tests/CodexBarTests/MenuCardOverrideIsolationTests.swift create mode 100644 Tests/CodexBarTests/MenuCardProviderRegressionTests.swift create mode 100644 Tests/CodexBarTests/MenuCardQuotaWarningMarkerTests.swift create mode 100644 Tests/CodexBarTests/MenuCardRefreshTests.swift create mode 100644 Tests/CodexBarTests/MenuCardSubtitleTests.swift create mode 100644 Tests/CodexBarTests/MenuCardTestDateFormatting.swift create mode 100644 Tests/CodexBarTests/MenuCardViewRecyclingTests.swift create mode 100644 Tests/CodexBarTests/MenuCardWorkdayPaceTests.swift create mode 100644 Tests/CodexBarTests/MenuDescriptorAntigravityTests.swift create mode 100644 Tests/CodexBarTests/MenuDescriptorCodexManagedFallbackTests.swift create mode 100644 Tests/CodexBarTests/MenuDescriptorCrossModelTests.swift create mode 100644 Tests/CodexBarTests/MenuDescriptorKiloTests.swift create mode 100644 Tests/CodexBarTests/MenuDescriptorKimiK2Tests.swift create mode 100644 Tests/CodexBarTests/MenuDescriptorOpenAIAPITests.swift create mode 100644 Tests/CodexBarTests/MenuDescriptorPoeTests.swift create mode 100644 Tests/CodexBarTests/MenuDescriptorSakanaTests.swift create mode 100644 Tests/CodexBarTests/MenuDescriptorSub2APITests.swift create mode 100644 Tests/CodexBarTests/MenuOpenRefreshPlanTests.swift create mode 100644 Tests/CodexBarTests/MenuSessionCoordinatorTests.swift create mode 100644 Tests/CodexBarTests/MiMoLocalUsageFallbackTests.swift create mode 100644 Tests/CodexBarTests/MiMoProviderTests.swift create mode 100644 Tests/CodexBarTests/MiMoUsageScriptTests.swift create mode 100644 Tests/CodexBarTests/MiniMaxAPITokenFetchTests.swift create mode 100644 Tests/CodexBarTests/MiniMaxCurrentTokenPlanResponseTests.swift create mode 100644 Tests/CodexBarTests/MiniMaxLocalStorageImporterTests.swift create mode 100644 Tests/CodexBarTests/MiniMaxLogRedactorTests.swift create mode 100644 Tests/CodexBarTests/MiniMaxMenuCardBillingTests.swift create mode 100644 Tests/CodexBarTests/MiniMaxMenuCardModelPlanTests.swift create mode 100644 Tests/CodexBarTests/MiniMaxProviderTests.swift create mode 100644 Tests/CodexBarTests/MiniMaxTokenPlanChangeTests.swift create mode 100644 Tests/CodexBarTests/MistralMenuCardModelTests.swift create mode 100644 Tests/CodexBarTests/MistralUsageParserTests.swift create mode 100644 Tests/CodexBarTests/MistralVibeUsageTests.swift create mode 100644 Tests/CodexBarTests/ModelsDevPricingTests.swift create mode 100644 Tests/CodexBarTests/MoonshotSettingsReaderTests.swift create mode 100644 Tests/CodexBarTests/MoonshotUsageFetcherTests.swift create mode 100644 Tests/CodexBarTests/OllamaUsageFetcherRetryMappingTests.swift create mode 100644 Tests/CodexBarTests/OllamaUsageFetcherTests.swift create mode 100644 Tests/CodexBarTests/OllamaUsageParserTests.swift create mode 100644 Tests/CodexBarTests/OpenAIAPICreditBalanceTests.swift create mode 100644 Tests/CodexBarTests/OpenAIAPIMenuCardModelTests.swift create mode 100644 Tests/CodexBarTests/OpenAIAPIProjectScopeTests.swift create mode 100644 Tests/CodexBarTests/OpenAIAPIStatusMenuTests.swift create mode 100644 Tests/CodexBarTests/OpenAIAPIUsageFetcherTests.swift create mode 100644 Tests/CodexBarTests/OpenAIDashboardBrowserCookieImporterTests.swift create mode 100644 Tests/CodexBarTests/OpenAIDashboardFetcherCreditsWaitTests.swift create mode 100644 Tests/CodexBarTests/OpenAIDashboardModelsTests.swift create mode 100644 Tests/CodexBarTests/OpenAIDashboardNavigationDelegateTests.swift create mode 100644 Tests/CodexBarTests/OpenAIDashboardOffscreenHostTests.swift create mode 100644 Tests/CodexBarTests/OpenAIDashboardParserTests.swift create mode 100644 Tests/CodexBarTests/OpenAIDashboardScrapeScriptTests.swift create mode 100644 Tests/CodexBarTests/OpenAIDashboardSparkTests.swift create mode 100644 Tests/CodexBarTests/OpenAIDashboardWebViewCacheTests.swift create mode 100644 Tests/CodexBarTests/OpenAIWebAccountSwitchTests.swift create mode 100644 Tests/CodexBarTests/OpenAIWebRefreshGateTests.swift create mode 100644 Tests/CodexBarTests/OpenCodeGoLocalUsageReaderTests.swift create mode 100644 Tests/CodexBarTests/OpenCodeGoMenuCardModelTests.swift create mode 100644 Tests/CodexBarTests/OpenCodeGoProviderStrategyTests.swift create mode 100644 Tests/CodexBarTests/OpenCodeGoUsageFetcherErrorTests.swift create mode 100644 Tests/CodexBarTests/OpenCodeGoUsageParserTests.swift create mode 100644 Tests/CodexBarTests/OpenCodeUsageFetcherErrorTests.swift create mode 100644 Tests/CodexBarTests/OpenCodeUsageParserTests.swift create mode 100644 Tests/CodexBarTests/OpenCodeWebCookieSupportTests.swift create mode 100644 Tests/CodexBarTests/OpenRouterUsageStatsTests.swift create mode 100644 Tests/CodexBarTests/PathBuilderTests.swift create mode 100644 Tests/CodexBarTests/PerplexityCookieCacheTests.swift create mode 100644 Tests/CodexBarTests/PerplexityCookieHeaderTests.swift create mode 100644 Tests/CodexBarTests/PerplexityProviderTests.swift create mode 100644 Tests/CodexBarTests/PerplexitySettingsReaderTests.swift create mode 100644 Tests/CodexBarTests/PerplexityUsageFetcherTests.swift create mode 100644 Tests/CodexBarTests/PersistentRefreshAccessibilityTests.swift create mode 100644 Tests/CodexBarTests/PiSessionCostScannerTests.swift create mode 100644 Tests/CodexBarTests/PlanUtilizationHistoryChartMenuViewTests.swift create mode 100644 Tests/CodexBarTests/PoeCurrentDayPresentationTests.swift create mode 100644 Tests/CodexBarTests/PoeProviderDescriptorTests.swift create mode 100644 Tests/CodexBarTests/PoeSettingsReaderTests.swift create mode 100644 Tests/CodexBarTests/PoeUsageFetcherTests.swift create mode 100644 Tests/CodexBarTests/PoeUsageHistorySnapshotTests.swift create mode 100644 Tests/CodexBarTests/PopupLocalizationTests.swift create mode 100644 Tests/CodexBarTests/PredictivePaceWarningTests.swift create mode 100644 Tests/CodexBarTests/PreferencesPaneSmokeTests.swift create mode 100644 Tests/CodexBarTests/PreferencesSelectionTests.swift create mode 100644 Tests/CodexBarTests/ProviderCandidateRetryRunnerTests.swift create mode 100644 Tests/CodexBarTests/ProviderChangelogLinkTests.swift create mode 100644 Tests/CodexBarTests/ProviderConfigEnvironmentTests.swift create mode 100644 Tests/CodexBarTests/ProviderCookieSettingsResolverTests.swift create mode 100644 Tests/CodexBarTests/ProviderDetectionPolicyTests.swift create mode 100644 Tests/CodexBarTests/ProviderDiagnosticExportTests.swift create mode 100644 Tests/CodexBarTests/ProviderEndpointOverrideSecurityTests.swift create mode 100644 Tests/CodexBarTests/ProviderEnvironmentResolverTests.swift create mode 100644 Tests/CodexBarTests/ProviderHTTPClientTests.swift create mode 100644 Tests/CodexBarTests/ProviderHTTPTransportStub.swift create mode 100644 Tests/CodexBarTests/ProviderIconResourcesTests.swift create mode 100644 Tests/CodexBarTests/ProviderLabelMetadataCharacterizationTests.swift create mode 100644 Tests/CodexBarTests/ProviderMetadataStatusLinkTests.swift create mode 100644 Tests/CodexBarTests/ProviderPlanLineParsingTests.swift create mode 100644 Tests/CodexBarTests/ProviderQuotaFixtureContractTests.swift create mode 100644 Tests/CodexBarTests/ProviderRefreshCoordinatorTests.swift create mode 100644 Tests/CodexBarTests/ProviderRegistryTests.swift create mode 100644 Tests/CodexBarTests/ProviderSettingsDescriptorTests.swift create mode 100644 Tests/CodexBarTests/ProviderStorageFootprintTests.swift create mode 100644 Tests/CodexBarTests/ProviderSwitcherEventPeekGateTests.swift create mode 100644 Tests/CodexBarTests/ProviderToggleStoreTests.swift create mode 100644 Tests/CodexBarTests/ProviderTokenResolverTests.swift create mode 100644 Tests/CodexBarTests/ProviderVersionDetectorTests.swift create mode 100644 Tests/CodexBarTests/ProvidersPaneCoverageTests.swift create mode 100644 Tests/CodexBarTests/QoderDashboardActionTests.swift create mode 100644 Tests/CodexBarTests/QoderProviderBehaviorTests.swift create mode 100644 Tests/CodexBarTests/QoderProviderTests.swift create mode 100644 Tests/CodexBarTests/QoderUsageFetcherTests.swift create mode 100644 Tests/CodexBarTests/QuotaWarningAlertPresentationStateTests.swift create mode 100644 Tests/CodexBarTests/QuotaWarningNotificationLogicTests.swift create mode 100644 Tests/CodexBarTests/RateWindowSyntheticPlaceholderTests.swift create mode 100644 Tests/CodexBarTests/RequiredRefreshCoalescingTests.swift create mode 100644 Tests/CodexBarTests/ResetTimeBackfillTests.swift create mode 100644 Tests/CodexBarTests/SakanaUsageFetcherTests.swift create mode 100644 Tests/CodexBarTests/SessionQuotaNotificationLogicTests.swift create mode 100644 Tests/CodexBarTests/SettingsStoreAdditionalTests.swift create mode 100644 Tests/CodexBarTests/SettingsStoreCoverageTests.swift create mode 100644 Tests/CodexBarTests/SettingsStoreTests.swift create mode 100644 Tests/CodexBarTests/SettingsWindowAppearanceTests.swift create mode 100644 Tests/CodexBarTests/ShellCommandForegroundTests.swift create mode 100644 Tests/CodexBarTests/SpawnedProcessGroupTests.swift create mode 100644 Tests/CodexBarTests/StatusItemAnimationCodexCreditsTests.swift create mode 100644 Tests/CodexBarTests/StatusItemAnimationSignatureTests.swift create mode 100644 Tests/CodexBarTests/StatusItemAnimationTests.swift create mode 100644 Tests/CodexBarTests/StatusItemBalanceDisplayTests.swift create mode 100644 Tests/CodexBarTests/StatusItemCombinedMetricPlaceholderTests.swift create mode 100644 Tests/CodexBarTests/StatusItemControllerMenuTests.swift create mode 100644 Tests/CodexBarTests/StatusItemControllerShutdownTests.swift create mode 100644 Tests/CodexBarTests/StatusItemControllerSplitLifecycleTests.swift create mode 100644 Tests/CodexBarTests/StatusItemExtraUsageMetricTests.swift create mode 100644 Tests/CodexBarTests/StatusItemIconObservationSignatureTests.swift create mode 100644 Tests/CodexBarTests/StatusItemPurchaseURLTests.swift create mode 100644 Tests/CodexBarTests/StatusItemQuotaWarningFlashTests.swift create mode 100644 Tests/CodexBarTests/StatusMenuAppearanceTests.swift create mode 100644 Tests/CodexBarTests/StatusMenuClosedPreparationTests.swift create mode 100644 Tests/CodexBarTests/StatusMenuCodexCostHistoryRefreshTests.swift create mode 100644 Tests/CodexBarTests/StatusMenuCodexSwitcherPresentationTests.swift create mode 100644 Tests/CodexBarTests/StatusMenuCodexSwitcherTests.swift create mode 100644 Tests/CodexBarTests/StatusMenuCostMenuCardTests.swift create mode 100644 Tests/CodexBarTests/StatusMenuCostSummaryDisplayStyleTests.swift create mode 100644 Tests/CodexBarTests/StatusMenuHeightCacheTests.swift create mode 100644 Tests/CodexBarTests/StatusMenuHighlightTests.swift create mode 100644 Tests/CodexBarTests/StatusMenuHostedSubmenuRefreshTests.swift create mode 100644 Tests/CodexBarTests/StatusMenuInstantOpenTests.swift create mode 100644 Tests/CodexBarTests/StatusMenuLocalizationRefreshTests.swift create mode 100644 Tests/CodexBarTests/StatusMenuMergedOverviewRefreshTests.swift create mode 100644 Tests/CodexBarTests/StatusMenuNativeSectionSpacingTests.swift create mode 100644 Tests/CodexBarTests/StatusMenuOpenRefreshTests.swift create mode 100644 Tests/CodexBarTests/StatusMenuOverviewClickTests.swift create mode 100644 Tests/CodexBarTests/StatusMenuOverviewScrollTests.swift create mode 100644 Tests/CodexBarTests/StatusMenuOverviewSubmenuTests.swift create mode 100644 Tests/CodexBarTests/StatusMenuPersistentRefreshTests.swift create mode 100644 Tests/CodexBarTests/StatusMenuReadinessBaselineTests.swift create mode 100644 Tests/CodexBarTests/StatusMenuScopedCodexRefreshTests.swift create mode 100644 Tests/CodexBarTests/StatusMenuSwitcherClickTests.swift create mode 100644 Tests/CodexBarTests/StatusMenuSwitcherLayoutTests.swift create mode 100644 Tests/CodexBarTests/StatusMenuSwitcherRefreshTests.swift create mode 100644 Tests/CodexBarTests/StatusMenuSwitcherTrackingTests.swift create mode 100644 Tests/CodexBarTests/StatusMenuTests.swift create mode 100644 Tests/CodexBarTests/StatusMenuTokenAccountSwitcherTests.swift create mode 100644 Tests/CodexBarTests/StatusMenuUsageDisplayTests.swift create mode 100644 Tests/CodexBarTests/StatusMenuViewportRestoreTests.swift create mode 100644 Tests/CodexBarTests/StatusProbeTests.swift create mode 100644 Tests/CodexBarTests/StatuspageSummaryTests.swift create mode 100644 Tests/CodexBarTests/StepFunUsageFetcherTests.swift create mode 100644 Tests/CodexBarTests/StorageBreakdownSegmentTests.swift create mode 100644 Tests/CodexBarTests/Sub2APICLIOutputTests.swift create mode 100644 Tests/CodexBarTests/Sub2APIMenuCardModelTests.swift create mode 100644 Tests/CodexBarTests/Sub2APIUsageFetcherTests.swift create mode 100644 Tests/CodexBarTests/SubprocessRunnerTests.swift create mode 100644 Tests/CodexBarTests/SubscriptionDetectionTests.swift create mode 100644 Tests/CodexBarTests/SyntheticMenuCardTests.swift create mode 100644 Tests/CodexBarTests/SyntheticProviderTests.swift create mode 100644 Tests/CodexBarTests/T3ChatUsageFetcherTests.swift create mode 100644 Tests/CodexBarTests/TTYCommandRunnerTests.swift create mode 100644 Tests/CodexBarTests/TTYIntegrationTests.swift create mode 100644 Tests/CodexBarTests/TailscaleSessionTests.swift create mode 100644 Tests/CodexBarTests/TerminalAppTests.swift create mode 100644 Tests/CodexBarTests/TestProcessCleanup.swift create mode 100644 Tests/CodexBarTests/TestProcessCleanupTests.swift create mode 100644 Tests/CodexBarTests/TestStores.swift create mode 100644 Tests/CodexBarTests/TextParsingTests.swift create mode 100644 Tests/CodexBarTests/TokenAccountEnvironmentPrecedenceTests.swift create mode 100644 Tests/CodexBarTests/TokenAccountStoreTests.swift create mode 100644 Tests/CodexBarTests/UpdateChannelTests.swift create mode 100644 Tests/CodexBarTests/UsageBreakdownChartMenuViewTests.swift create mode 100644 Tests/CodexBarTests/UsageChartScaleTests.swift create mode 100644 Tests/CodexBarTests/UsageFormatterTests.swift create mode 100644 Tests/CodexBarTests/UsageMenuCardLayoutTests.swift create mode 100644 Tests/CodexBarTests/UsagePaceTests.swift create mode 100644 Tests/CodexBarTests/UsagePaceTextTests.swift create mode 100644 Tests/CodexBarTests/UsageStoreCachedTokenHydrationTests.swift create mode 100644 Tests/CodexBarTests/UsageStoreCoverageTests.swift create mode 100644 Tests/CodexBarTests/UsageStoreDisabledProviderCleanupTests.swift create mode 100644 Tests/CodexBarTests/UsageStoreHighestUsageTests.swift create mode 100644 Tests/CodexBarTests/UsageStoreManualTokenRefreshTests.swift create mode 100644 Tests/CodexBarTests/UsageStorePathDebugTests.swift create mode 100644 Tests/CodexBarTests/UsageStorePlanUtilizationAsyncLoadTests.swift create mode 100644 Tests/CodexBarTests/UsageStorePlanUtilizationCelebrationTests.swift create mode 100644 Tests/CodexBarTests/UsageStorePlanUtilizationClaudeIdentityBoundaryTests.swift create mode 100644 Tests/CodexBarTests/UsageStorePlanUtilizationClaudeIdentityTests.swift create mode 100644 Tests/CodexBarTests/UsageStorePlanUtilizationCodexOwnershipTests.swift create mode 100644 Tests/CodexBarTests/UsageStorePlanUtilizationCodexResetOwnershipTests.swift create mode 100644 Tests/CodexBarTests/UsageStorePlanUtilizationDerivedChartTests.swift create mode 100644 Tests/CodexBarTests/UsageStorePlanUtilizationExactFitResetTests.swift create mode 100644 Tests/CodexBarTests/UsageStorePlanUtilizationResetCoalescingTests.swift create mode 100644 Tests/CodexBarTests/UsageStorePlanUtilizationTests.swift create mode 100644 Tests/CodexBarTests/UsageStoreResetBoundaryRefreshTests.swift create mode 100644 Tests/CodexBarTests/UsageStoreSessionQuotaTransitionTests.swift create mode 100644 Tests/CodexBarTests/UsageStoreTimeoutTests.swift create mode 100644 Tests/CodexBarTests/UsageStoreTokenRetryPolicyTests.swift create mode 100644 Tests/CodexBarTests/UsageStoreWidgetSnapshotTests.swift create mode 100644 Tests/CodexBarTests/UserFacingLocalizationCoverageTests.swift create mode 100644 Tests/CodexBarTests/VeniceSettingsReaderTests.swift create mode 100644 Tests/CodexBarTests/VeniceUsageFetcherTests.swift create mode 100644 Tests/CodexBarTests/VertexAIOAuthCredentialsTests.swift create mode 100644 Tests/CodexBarTests/WarpUsageFetcherTests.swift create mode 100644 Tests/CodexBarTests/WayfinderProviderTests.swift create mode 100644 Tests/CodexBarTests/WebKitTeardownTests.swift create mode 100644 Tests/CodexBarTests/WidgetSnapshotTests.swift create mode 100644 Tests/CodexBarTests/WindsurfDevinSessionImporterTests.swift create mode 100644 Tests/CodexBarTests/WindsurfProviderTests.swift create mode 100644 Tests/CodexBarTests/WindsurfStatusProbeTests.swift create mode 100644 Tests/CodexBarTests/WindsurfWebFetcherTests.swift create mode 100644 Tests/CodexBarTests/ZaiAvailabilityTests.swift create mode 100644 Tests/CodexBarTests/ZaiMenuCardTests.swift create mode 100644 Tests/CodexBarTests/ZaiProviderTests.swift create mode 100644 Tests/CodexBarTests/ZaiTokenAccountEnvironmentTests.swift create mode 100644 Tests/CodexBarTests/ZaiTokenStoreTestSupport.swift create mode 100644 Tests/CodexBarTests/ZedStatusProbeTests.swift create mode 100644 TestsLinux/AntigravityCLIStrategyLinuxTests.swift create mode 100644 TestsLinux/AntigravityProcessLauncherLinuxTests.swift create mode 100644 TestsLinux/AzureEndpointOverrideSecurityTests.swift create mode 100644 TestsLinux/CLICardsRendererTests.swift create mode 100644 TestsLinux/CLITerminalCapabilitiesTests.swift create mode 100644 TestsLinux/ClaudeOAuthCredentialHistoryLinuxTests.swift create mode 100644 TestsLinux/ClaudeOAuthDelegatedRefreshLinuxTests.swift create mode 100644 TestsLinux/CodexBarLoggingPerformanceTests.swift create mode 100644 TestsLinux/CodexOAuthCredentialsStoreLinuxTests.swift create mode 100644 TestsLinux/CostUsageScanExecutorLinuxTests.swift create mode 100644 TestsLinux/CursorLinuxTests.swift create mode 100644 TestsLinux/JetBrainsParserLinuxTests.swift create mode 100644 TestsLinux/OpenAIDashboardParserLinuxTests.swift create mode 100644 TestsLinux/OpenCodeGoLinuxTests.swift create mode 100644 TestsLinux/PlatformGatingTests.swift create mode 100644 TestsLinux/ProcNetTCPListeningPortParserLinuxTests.swift create mode 100644 TestsLinux/ProviderEndpointOverrideSecurityLinuxTests.swift create mode 100644 TestsLinux/SettingsReaderQuoteUnwrapTrapTests.swift create mode 100644 TestsLinux/ShellCommandSessionLinuxTests.swift create mode 100644 TestsLinux/UsageFormatterLinuxTests.swift create mode 100644 TestsLinux/WayfinderProviderLinuxTests.swift create mode 100644 VISION.md create mode 100644 WidgetExtension/CodexBarWidgetExtension.xcodeproj/project.pbxproj create mode 100644 WidgetExtension/CodexBarWidgetExtension.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 WidgetExtension/CodexBarWidgetExtension.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved create mode 100644 WidgetExtension/Info.plist create mode 100644 WidgetExtension/project.yml create mode 100644 appcast.xml create mode 100755 bin/docs-list create mode 100755 bin/install-codexbar-cli.sh create mode 100644 docs/.nojekyll create mode 100644 docs/CNAME create mode 100644 docs/DEVELOPMENT.md create mode 100644 docs/DEVELOPMENT_SETUP.md create mode 100644 docs/FORK_QUICK_START.md create mode 100644 docs/FORK_ROADMAP.md create mode 100644 docs/FORK_SETUP.md create mode 100644 docs/ISSUE_LABELING.md create mode 100644 docs/KEYCHAIN_FIX.md create mode 100644 docs/QUOTIO_ANALYSIS.md create mode 100644 docs/RELEASING.md create mode 100644 docs/TODO.md create mode 100644 docs/UPSTREAM_STRATEGY.md create mode 100644 docs/abacus.md create mode 100644 docs/agent-sessions-design.md create mode 100644 docs/alibaba-coding-plan.md create mode 100644 docs/alibaba-token-plan.md create mode 100644 docs/amp.md create mode 100644 docs/antigravity.md create mode 100644 docs/architecture.md create mode 100644 docs/augment.md create mode 100644 docs/azure-openai.md create mode 100644 docs/bedrock.md create mode 100644 docs/chutes.md create mode 100644 docs/claude-comparison-since-0.18.0beta2.md create mode 100644 docs/claude-multi-account-and-status-items.md create mode 100644 docs/claude.md create mode 100644 docs/clawrouter.md create mode 100644 docs/cli-configuration.md create mode 100644 docs/cli.md create mode 100644 docs/codebuff.md create mode 100644 docs/codex-oauth.md create mode 100644 docs/codex.md create mode 100644 docs/codexbar.png create mode 100644 docs/command-code.md create mode 100644 docs/configuration.md create mode 100644 docs/copilot.md create mode 100644 docs/cost-window-comparisons.md create mode 100644 docs/crof.md create mode 100644 docs/crossmodel.md create mode 100644 docs/cursor.md create mode 100644 docs/custom-provider-design.md create mode 100644 docs/deepgram.md create mode 100644 docs/deepseek.md create mode 100644 docs/devin.md create mode 100644 docs/doubao.md create mode 100644 docs/elevenlabs.md create mode 100644 docs/factory.md create mode 100644 docs/features/feature-credits.webp create mode 100644 docs/features/feature-resets.webp create mode 100644 docs/features/feature-status.webp create mode 100644 docs/gemini.md create mode 100644 docs/grok.md create mode 100644 docs/groqcloud.md create mode 100644 docs/hero-mockup.svg create mode 100644 docs/icon.md create mode 100644 docs/icon.png create mode 100644 docs/images/apple.svg create mode 100644 docs/images/menubar/github-circle-fill.png create mode 100644 docs/images/menubar/openclaw-menubar.svg create mode 100644 docs/images/menubar/person-circle.png create mode 100644 docs/images/menubar/personalhotspot.png create mode 100644 docs/images/menubar/wifi.png create mode 100644 docs/index.html create mode 100644 docs/issue-2037-fork-family-provenance-spec.md create mode 100644 docs/issue-2037-p0-local-corpus-findings.md create mode 100644 docs/issue-2037-ultra-fork-overcount-spec.md create mode 100644 docs/jetbrains.md create mode 100644 docs/keychain-allow.png create mode 100644 docs/keychain-prompts.md create mode 100644 docs/kilo.md create mode 100644 docs/kimi-k2.md create mode 100644 docs/kimi.md create mode 100644 docs/kiro.md create mode 100644 docs/litellm.md create mode 100644 docs/llm-proxy.md create mode 100644 docs/llms.txt create mode 100644 docs/logos/abacus-ai-dark.svg create mode 100644 docs/logos/abacus-ai.png create mode 100644 docs/logos/alibaba.svg create mode 100644 docs/logos/amp.svg create mode 100644 docs/logos/antigravity.svg create mode 100644 docs/logos/augment.svg create mode 100644 docs/logos/chutes.svg create mode 100644 docs/logos/claude.svg create mode 100644 docs/logos/codebuff-dark.svg create mode 100644 docs/logos/codebuff.png create mode 100644 docs/logos/codebuff.svg create mode 100644 docs/logos/codex-dark.svg create mode 100644 docs/logos/codex.svg create mode 100644 docs/logos/copilot.svg create mode 100644 docs/logos/cursor.svg create mode 100644 docs/logos/deepseek.svg create mode 100644 docs/logos/devin.svg create mode 100644 docs/logos/droid-dark.svg create mode 100644 docs/logos/droid.svg create mode 100644 docs/logos/elevenlabs.svg create mode 100644 docs/logos/gemini.svg create mode 100644 docs/logos/jetbrains-ai.svg create mode 100644 docs/logos/kilo.svg create mode 100644 docs/logos/kimi-k2.svg create mode 100644 docs/logos/kimi.svg create mode 100644 docs/logos/kiro-dark.svg create mode 100644 docs/logos/kiro.svg create mode 100644 docs/logos/litellm.svg create mode 100644 docs/logos/minimax.svg create mode 100644 docs/logos/mistral.svg create mode 100644 docs/logos/ollama.svg create mode 100644 docs/logos/opencode-dark.svg create mode 100644 docs/logos/opencode.svg create mode 100644 docs/logos/openrouter.svg create mode 100644 docs/logos/perplexity.svg create mode 100644 docs/logos/poe.svg create mode 100644 docs/logos/synthetic-dark.svg create mode 100644 docs/logos/synthetic.svg create mode 100644 docs/logos/t3chat.svg create mode 100644 docs/logos/vertex-ai.svg create mode 100644 docs/logos/warp.svg create mode 100644 docs/logos/zai-dark.svg create mode 100644 docs/logos/zai.svg create mode 100644 docs/logos/zed.svg create mode 100644 docs/manus.md create mode 100644 docs/mimo.md create mode 100644 docs/minimax.md create mode 100644 docs/mistral.md create mode 100644 docs/model-pricing.md create mode 100644 docs/moonshot.md create mode 100644 docs/ollama.md create mode 100644 docs/openai.md create mode 100644 docs/opencode.md create mode 100644 docs/openrouter.md create mode 100644 docs/overview-scroll-stutter-investigation.md create mode 100644 docs/packaging.md create mode 100644 docs/perf-energy-issue-139-main-fix-validation-2026-02-19.md create mode 100644 docs/perf-energy-issue-139-simulation-report-2026-02-19.md create mode 100644 docs/perplexity.md create mode 100644 docs/poe.md create mode 100644 docs/pr-1848-body.md create mode 100644 docs/pr-1848-verification-comment.md create mode 100644 docs/predictive-refresh-policy.md create mode 100644 docs/provider.md create mode 100644 docs/providers.md create mode 100644 docs/qoder.md create mode 100644 docs/quotio-comparison.md create mode 100644 docs/refactor/claude-current-baseline.md create mode 100644 docs/refactor/claude-provider-vnext-locked.md create mode 100644 docs/refactor/cli.md create mode 100644 docs/refresh-loop.md create mode 100644 docs/releasing-homebrew.md create mode 100644 docs/repository-size.md create mode 100644 docs/sakana.md create mode 100644 docs/screenshots/claude-extra-usage-bug.png create mode 100644 docs/screenshots/claude-multi-account-status-items-proposal.svg create mode 100644 docs/screenshots/claude-sign-in-synthetic-proof.png create mode 100644 docs/screenshots/claude-swap-accounts-synthetic-proof.png create mode 100644 docs/screenshots/clawrouter-settings.png create mode 100644 docs/screenshots/clawrouter-usage.png create mode 100644 docs/screenshots/codex-upstream-weekly-exhausted-session-misleading.png create mode 100644 docs/screenshots/codexbar-weekly-caps-session-fix.png create mode 100644 docs/screenshots/cost-chart-yaxis-labels.png create mode 100644 docs/screenshots/current-merged-menu-redacted.png create mode 100644 docs/screenshots/factory-api-key-details-source-api.png create mode 100644 docs/screenshots/factory-api-key-menu-usage.png create mode 100644 docs/screenshots/factory-api-key-settings-connection.png create mode 100644 docs/screenshots/settings-sidebar-card-before.png create mode 100644 docs/screenshots/settings-sidebar-goldengate-after.png create mode 100644 docs/session-keepalive-design.md create mode 100644 docs/sessions.md create mode 100644 docs/site-locales.mjs create mode 100644 docs/site-utilities.css create mode 100644 docs/site.css create mode 100644 docs/site.js create mode 100644 docs/social.html create mode 100644 docs/social.png create mode 100644 docs/solutions/performance-issues/openai-web-extras-default-off-codexbar-20260307.md create mode 100644 docs/sparkle.md create mode 100644 docs/status.md create mode 100644 docs/stepfun.md create mode 100644 docs/sub2api.md create mode 100644 docs/superpowers/plans/2026-05-11-kilo-organization-selection.md create mode 100644 docs/superpowers/specs/2026-05-11-kilo-organization-selection-design.md create mode 100644 docs/superpowers/specs/2026-07-01-mimo-reserve-decision.md create mode 100644 docs/superpowers/specs/2026-07-01-opencode-go-multi-workspace-decision.md create mode 100644 docs/superpowers/specs/2026-07-01-predictive-pace-warning-notifications-design.md create mode 100644 docs/superpowers/specs/2026-07-01-provider-presentation-and-focus-design.md create mode 100644 docs/synthetic.md create mode 100644 docs/t3chat.md create mode 100644 docs/ui.md create mode 100644 docs/venice.md create mode 100644 docs/verify-1844-proof.md create mode 100644 docs/vertexai.md create mode 100644 docs/warp.md create mode 100644 docs/wayfinder.md create mode 100644 docs/web-integration.md create mode 100644 docs/webkit.md create mode 100644 docs/widgets.md create mode 100644 docs/widgets/01-codexbar-history-small.png create mode 100644 docs/widgets/02-codexbar-history-large.png create mode 100644 docs/widgets/03-codexbar-metric-compact.png create mode 100644 docs/widgets/04-codexbar-burndown.png create mode 100644 docs/widgets/05-codexbar-burndown-combined.png create mode 100644 docs/widgets/06-codexbar-usage-compact.png create mode 100644 docs/widgets/07-codexbar-usage-wide.png create mode 100644 docs/widgets/08-codexbar-usage-large.png create mode 100644 docs/widgets/09-codexbar-switcher-compact.png create mode 100644 docs/widgets/10-codexbar-switcher-wide.png create mode 100644 docs/widgets/11-codexbar-switcher-large.png create mode 100644 docs/windsurf.md create mode 100644 docs/zai.md create mode 100644 docs/zed.md diff --git a/.agents/skills/codexbar/SKILL.md b/.agents/skills/codexbar/SKILL.md new file mode 100644 index 0000000..abcc6e3 --- /dev/null +++ b/.agents/skills/codexbar/SKILL.md @@ -0,0 +1,38 @@ +--- +name: codexbar +description: "CodexBar read. Provider usage, limits, credits, config health. JSON. No writes." +--- + +# CodexBar + +Read CodexBar. Never mutate config/auth. + +## Run + +```bash +skill="${CODEX_HOME:-$HOME/.codex}/skills/codexbar" +"$skill/scripts/codexbar" doctor +"$skill/scripts/codexbar" providers +"$skill/scripts/codexbar" usage +"$skill/scripts/codexbar" usage --provider codex +"$skill/scripts/codexbar" usage --all +``` + +All stdout: JSON. Upstream CodexBar shape kept. Less drift, fewer tokens. + +## Rules + +- Start `doctor` when install/config unknown. +- `usage` reads enabled providers. Prefer this. +- `usage --provider ID` reads one provider. +- `usage --all` expensive; use only when needed. +- Identities hidden by default. `--include-identities` only when user explicitly needs them. +- Secrets always hidden. +- Helper read-only: fixed allowlist only. No config writes, auth repair, enable/disable, key storage. +- Timeout means upstream stuck. Narrow provider or raise `CODEXBAR_TIMEOUT` (default 120 seconds). + +## Binary + +Auto-find: `CODEXBAR_BIN`, PATH, app bundle, Homebrew cask. If missing: open CodexBar, Preferences > Advanced > Install CLI; or set `CODEXBAR_BIN`. + +Each stdout/stderr stream capped at 1 MiB while fully drained. Timeout kills process group. diff --git a/.agents/skills/codexbar/scripts/codexbar b/.agents/skills/codexbar/scripts/codexbar new file mode 100755 index 0000000..d60c8d4 --- /dev/null +++ b/.agents/skills/codexbar/scripts/codexbar @@ -0,0 +1,321 @@ +#!/usr/bin/env python3 +"""Read-only, bounded CodexBar CLI bridge.""" + +from __future__ import annotations + +import argparse +import json +import os +import re +import shutil +import signal +import subprocess +import sys +import threading +from dataclasses import dataclass +from pathlib import Path +from typing import Any, Sequence + + +MAX_CAPTURE_BYTES = 1024 * 1024 +DEFAULT_TIMEOUT = 120.0 +BIN_ENV = "CODEXBAR_BIN" +TIMEOUT_ENV = "CODEXBAR_TIMEOUT" +SKIP_DISCOVERY_ENV = "CODEXBAR_SKIP_DISCOVERY" + +SECRET = "" +IDENTITY = "" +EMAIL = "" + +EMAIL_RE = re.compile(r"\b[A-Z0-9._%+\-]+@[A-Z0-9.\-]+\.[A-Z]{2,}\b", re.I) +BEARER_RE = re.compile(r"(?i)\bbearer\s+[A-Z0-9._~+/=\-]+") +JWT_RE = re.compile(r"\beyJ[A-Za-z0-9_\-]+\.[A-Za-z0-9_\-]+\.[A-Za-z0-9_\-]+\b") +LABELED_SECRET_RE = re.compile( + r"(?i)\b(authorization|api[_-]?key|access[_-]?token|refresh[_-]?token|id[_-]?token|" + r"session(?:id)?|secret|password|passwd|cookie|set-cookie)(\s*[:=]\s*)([^\s,;]+)" +) +WORD_SECRET_RE = re.compile( + r"(?i)\b(token|secret|password|passwd|cookie)\s+([A-Z0-9._~+/=\-]{6,})\b" +) +SECRET_KEY_RE = re.compile( + r"(?i)(authorization|api[_-]?key|access[_-]?token|refresh[_-]?token|id[_-]?token|" + r"session(?:id)?|secret|password|passwd|cookie)" +) +IDENTITY_KEYS = { + "accountemail", + "accountorganization", + "accountid", + "accountname", + "email", + "organization", + "userid", + "username", +} +# ProviderIdentitySnapshot.providerID is UsageProvider, not an account identifier. + + +@dataclass(frozen=True) +class Binary: + path: str + source: str + + +@dataclass(frozen=True) +class Result: + returncode: int + stdout: bytes + stderr: bytes + timed_out: bool + + +def normalized_key(value: str) -> str: + return re.sub(r"[^a-z0-9]", "", value.lower()) + + +def timeout_seconds() -> float: + try: + return max(1.0, float(os.environ.get(TIMEOUT_ENV, DEFAULT_TIMEOUT))) + except ValueError: + return DEFAULT_TIMEOUT + + +def safe_path(path: str) -> str: + home = str(Path.home()) + if path == home: + return "~" + if path.startswith(home + os.sep): + return "~" + path[len(home) :] + return re.sub(r"^/Users/[^/]+", "/Users/", path) + + +def candidates() -> list[tuple[str, Path]]: + found: list[tuple[str, Path]] = [] + override = os.environ.get(BIN_ENV) + if override: + found.append(("env", Path(override).expanduser())) + + path_hit = shutil.which("codexbar") + if path_hit: + found.append(("path", Path(path_hit))) + + if os.environ.get(SKIP_DISCOVERY_ENV) == "1": + return found + + home = Path.home() + found.extend( + [ + ("homebrew", Path("/opt/homebrew/bin/codexbar")), + ("homebrew", Path("/usr/local/bin/codexbar")), + ("app", Path("/Applications/CodexBar.app/Contents/Helpers/CodexBarCLI")), + ("app", home / "Applications/CodexBar.app/Contents/Helpers/CodexBarCLI"), + ] + ) + for root in (Path("/opt/homebrew/Caskroom/codexbar"), Path("/usr/local/Caskroom/codexbar")): + found.extend(("cask", app / "Contents/Helpers/CodexBarCLI") for app in sorted(root.glob("*/CodexBar.app"))) + return found + + +def resolve_binary() -> Binary | None: + self_path = Path(__file__).resolve() + seen: set[Path] = set() + for source, candidate in candidates(): + try: + resolved = candidate.resolve() + if resolved in seen or resolved == self_path: + continue + seen.add(resolved) + if resolved.is_file() and os.access(resolved, os.X_OK): + return Binary(str(resolved), source) + except OSError: + continue + return None + + +def drain(pipe: Any, target: bytearray) -> None: + try: + while True: + chunk = pipe.read(65536) + if not chunk: + break + room = MAX_CAPTURE_BYTES - len(target) + if room > 0: + target.extend(chunk[:room]) + finally: + pipe.close() + + +def stop_group(process: subprocess.Popen[bytes], sig: signal.Signals) -> None: + try: + os.killpg(process.pid, sig) + except ProcessLookupError: + pass + + +def run_process(argv: Sequence[str]) -> Result: + process = subprocess.Popen( + list(argv), + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + start_new_session=True, + ) + assert process.stdout is not None + assert process.stderr is not None + stdout = bytearray() + stderr = bytearray() + readers = [ + threading.Thread(target=drain, args=(process.stdout, stdout), daemon=True), + threading.Thread(target=drain, args=(process.stderr, stderr), daemon=True), + ] + for reader in readers: + reader.start() + + timed_out = False + try: + process.wait(timeout=timeout_seconds()) + except subprocess.TimeoutExpired: + timed_out = True + stop_group(process, signal.SIGTERM) + try: + process.wait(timeout=2) + except subprocess.TimeoutExpired: + stop_group(process, signal.SIGKILL) + process.wait() + + for reader in readers: + reader.join(timeout=3) + return Result(124 if timed_out else process.returncode, bytes(stdout), bytes(stderr), timed_out) + + +def decode(value: bytes) -> str: + return value.decode("utf-8", errors="replace") + + +def sanitize_text(value: str, include_identities: bool) -> str: + value = JWT_RE.sub(SECRET, value) + value = BEARER_RE.sub("Bearer " + SECRET, value) + value = LABELED_SECRET_RE.sub(lambda match: match.group(1) + match.group(2) + SECRET, value) + value = WORD_SECRET_RE.sub(lambda match: match.group(1) + " " + SECRET, value) + if not include_identities: + value = EMAIL_RE.sub(EMAIL, value) + return value + + +def sanitize(value: Any, include_identities: bool, key: str | None = None) -> Any: + if key and SECRET_KEY_RE.search(key): + return SECRET + if key and normalized_key(key) in IDENTITY_KEYS and not include_identities and value is not None: + return EMAIL if "email" in normalized_key(key) else IDENTITY + if isinstance(value, dict): + return {str(child_key): sanitize(child, include_identities, str(child_key)) for child_key, child in value.items()} + if isinstance(value, list): + return [sanitize(child, include_identities) for child in value] + if isinstance(value, str): + return sanitize_text(value, include_identities) + return value + + +def print_json(value: Any) -> None: + print(json.dumps(value, indent=2, sort_keys=True)) + + +def print_error(kind: str, message: str, *, binary: Binary | None = None) -> None: + payload: dict[str, Any] = {"error": {"kind": kind, "message": sanitize_text(message, False)}} + if binary: + payload["binary"] = {"path": safe_path(binary.path), "source": binary.source} + print_json(payload) + + +def emit_stderr(result: Result, include_identities: bool) -> None: + text = sanitize_text(decode(result.stderr), include_identities).strip() + if text: + print(text, file=sys.stderr) + + +def read_json(binary: Binary, argv: Sequence[str], include_identities: bool) -> int: + result = run_process([binary.path, *argv]) + emit_stderr(result, include_identities) + if result.timed_out: + print_error("timeout", f"CodexBar exceeded {timeout_seconds():g}s and was stopped.", binary=binary) + return 124 + try: + payload = json.loads(decode(result.stdout)) + except json.JSONDecodeError as error: + preview = sanitize_text(decode(result.stdout[:400]), False) + print_error("invalid_json", f"CodexBar JSON failed: {error.msg}. stdout={preview!r}", binary=binary) + return result.returncode or 1 + print_json(sanitize(payload, include_identities)) + return result.returncode + + +def doctor(binary: Binary, include_identities: bool) -> int: + version = run_process([binary.path, "--version"]) + if version.timed_out: + print_error("timeout", f"CodexBar version exceeded {timeout_seconds():g}s.", binary=binary) + return 124 + validation = run_process([binary.path, "config", "validate", "--format", "json", "--json-only"]) + emit_stderr(version, include_identities) + emit_stderr(validation, include_identities) + if validation.timed_out: + print_error("timeout", f"CodexBar config validation exceeded {timeout_seconds():g}s.", binary=binary) + return 124 + try: + issues = json.loads(decode(validation.stdout)) + except json.JSONDecodeError as error: + print_error("invalid_json", f"CodexBar config validation failed: {error.msg}.", binary=binary) + return validation.returncode or 1 + print_json( + { + "binary": {"path": safe_path(binary.path), "source": binary.source}, + "configIssues": sanitize(issues, include_identities), + "version": sanitize_text((decode(version.stdout) or decode(version.stderr)).strip(), include_identities), + } + ) + return version.returncode or validation.returncode + + +def parser() -> argparse.ArgumentParser: + root = argparse.ArgumentParser(prog="codexbar", description="CodexBar read. JSON out. No writes.") + commands = root.add_subparsers(dest="command", required=True) + for name in ("doctor", "providers"): + command = commands.add_parser(name) + command.add_argument("--include-identities", action="store_true") + usage = commands.add_parser("usage") + scope = usage.add_mutually_exclusive_group() + scope.add_argument("--all", action="store_true") + scope.add_argument("--provider") + usage.add_argument("--include-identities", action="store_true") + return root + + +def main(argv: Sequence[str] | None = None) -> int: + args = parser().parse_args(argv) + binary = resolve_binary() + if not binary: + print_error("missing", "CodexBar CLI not found. Install CLI in CodexBar Advanced settings or set CODEXBAR_BIN.") + return 1 + try: + if args.command == "doctor": + return doctor(binary, args.include_identities) + if args.command == "providers": + return read_json( + binary, + ["config", "providers", "--format", "json", "--json-only"], + args.include_identities, + ) + usage_args = ["usage", "--format", "json", "--json-only"] + if args.all: + usage_args.extend(["--provider", "all"]) + elif args.provider: + usage_args.extend(["--provider", args.provider]) + return read_json(binary, usage_args, args.include_identities) + except OSError as error: + print_error("launch", str(error), binary=binary) + return 1 + + +if __name__ == "__main__": + try: + raise SystemExit(main()) + except KeyboardInterrupt: + print_error("interrupted", "Interrupted.") + raise SystemExit(130) diff --git a/.agents/skills/codexbar/scripts/test_codexbar.py b/.agents/skills/codexbar/scripts/test_codexbar.py new file mode 100644 index 0000000..ceb9dc7 --- /dev/null +++ b/.agents/skills/codexbar/scripts/test_codexbar.py @@ -0,0 +1,231 @@ +from __future__ import annotations + +import json +import os +import runpy +import subprocess +import sys +import tempfile +import textwrap +import time +import unittest +from pathlib import Path + + +SCRIPT = Path(__file__).with_name("codexbar") +MODULE = runpy.run_path(str(SCRIPT), run_name="codexbar_skill") +MAX_CAPTURE_BYTES = MODULE["MAX_CAPTURE_BYTES"] +run_process = MODULE["run_process"] + +FAKE = textwrap.dedent( + """\ + #!/usr/bin/env python3 + import json + import os + import subprocess + import sys + import time + + argv = sys.argv[1:] + log = os.environ.get("FAKE_LOG") + if log: + with open(log, "a", encoding="utf-8") as handle: + handle.write(json.dumps(argv) + "\\n") + + if argv == ["--version"]: + key = "VERSION" + elif argv[:2] == ["config", "validate"]: + key = "VALIDATE" + elif argv[:2] == ["config", "providers"]: + key = "PROVIDERS" + elif argv and argv[0] == "usage": + key = "USAGE" + else: + key = "OTHER" + + if os.environ.get("FAKE_SPAWN_CHILD") == "1": + marker = os.environ["FAKE_MARKER"] + subprocess.Popen([ + sys.executable, + "-c", + f"import pathlib,time; time.sleep(2); pathlib.Path({marker!r}).write_text('alive')", + ]) + time.sleep(5) + + delay = os.environ.get(f"FAKE_{key}_DELAY") + if delay: + time.sleep(float(delay)) + stdout = os.environ.get(f"FAKE_{key}_STDOUT", "") + stderr = os.environ.get(f"FAKE_{key}_STDERR", "") + sys.stdout.write(stdout) + sys.stderr.write(stderr) + raise SystemExit(int(os.environ.get(f"FAKE_{key}_EXIT", "0"))) + """ +) + + +def make_env(root: Path, *, install: bool = True) -> tuple[dict[str, str], Path]: + binary = root / "CodexBar.app" / "Contents" / "Helpers" / "CodexBarCLI" + binary.parent.mkdir(parents=True) + binary.write_text(FAKE, encoding="utf-8") + binary.chmod(0o755) + env = os.environ.copy() + env["CODEXBAR_SKIP_DISCOVERY"] = "1" + env["CODEXBAR_TIMEOUT"] = "3" + env["FAKE_LOG"] = str(root / "argv.log") + env["FAKE_VERSION_STDOUT"] = "CodexBar 1.2.3\n" + env["FAKE_VALIDATE_STDOUT"] = "[]" + env["FAKE_PROVIDERS_STDOUT"] = json.dumps( + [{"provider": "codex", "displayName": "Codex", "enabled": True}] + ) + env["FAKE_USAGE_STDOUT"] = json.dumps( + [ + { + "provider": "codex", + "source": "oauth", + "usage": { + "accountEmail": "alice@example.com", + "accountOrganization": "Example Org", + "identity": {"providerID": "codex", "accountID": "acct-123"}, + "primary": {"usedPercent": 42, "windowMinutes": 300}, + }, + } + ] + ) + if install: + env["CODEXBAR_BIN"] = str(binary) + else: + env.pop("CODEXBAR_BIN", None) + env["PATH"] = "/usr/bin:/bin:/usr/sbin:/sbin" + return env, binary + + +def helper(*args: str, env: dict[str, str], cwd: Path | None = None) -> subprocess.CompletedProcess[str]: + return subprocess.run( + [sys.executable, str(SCRIPT), *args], + capture_output=True, + text=True, + check=False, + env=env, + cwd=cwd, + ) + + +class CodexBarSkillTests(unittest.TestCase): + def test_help_is_small_and_read_only(self) -> None: + result = helper("--help", env=os.environ.copy()) + self.assertEqual(result.returncode, 0) + self.assertIn("CodexBar read. JSON out. No writes.", result.stdout) + self.assertNotIn("enable", result.stdout) + self.assertNotIn("set-api-key", result.stdout) + + def test_missing_binary_is_json(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + env, _ = make_env(Path(tmp), install=False) + result = helper("doctor", env=env) + self.assertEqual(result.returncode, 1) + self.assertEqual(json.loads(result.stdout)["error"]["kind"], "missing") + + def test_doctor_reports_version_and_raw_validation_shape(self) -> None: + with tempfile.TemporaryDirectory(dir=Path.home()) as tmp: + env, binary = make_env(Path(tmp)) + result = helper("doctor", env=env) + self.assertEqual(result.returncode, 0) + payload = json.loads(result.stdout) + self.assertEqual(payload["version"], "CodexBar 1.2.3") + self.assertEqual(payload["configIssues"], []) + self.assertEqual(payload["binary"]["path"], "~" + str(binary)[len(str(Path.home())) :]) + + def test_providers_passes_upstream_json_without_second_schema(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + env, _ = make_env(Path(tmp)) + result = helper("providers", env=env) + self.assertEqual(result.returncode, 0) + self.assertEqual( + json.loads(result.stdout), + [{"provider": "codex", "displayName": "Codex", "enabled": True}], + ) + + def test_usage_defaults_to_enabled_and_runs_from_any_cwd(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + env, _ = make_env(root) + elsewhere = root / "elsewhere" + elsewhere.mkdir() + result = helper("usage", env=env, cwd=elsewhere) + calls = [json.loads(line) for line in (root / "argv.log").read_text().splitlines()] + self.assertEqual(result.returncode, 0) + self.assertEqual(calls, [["usage", "--format", "json", "--json-only"]]) + + def test_usage_scope_maps_to_upstream_cli(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + env, _ = make_env(root) + self.assertEqual(helper("usage", "--all", env=env).returncode, 0) + self.assertEqual(helper("usage", "--provider", "zai", env=env).returncode, 0) + calls = [json.loads(line) for line in (root / "argv.log").read_text().splitlines()] + self.assertEqual(calls[0][-2:], ["--provider", "all"]) + self.assertEqual(calls[1][-2:], ["--provider", "zai"]) + + def test_usage_hides_identity_but_preserves_provider_id(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + env, _ = make_env(Path(tmp)) + env["FAKE_USAGE_STDERR"] = ( + "Authorization: Bearer secret-token alice@example.com; token sk-live-prose-secret\n" + ) + result = helper("usage", env=env) + payload = json.loads(result.stdout)[0] + self.assertEqual(payload["provider"], "codex") + self.assertEqual(payload["usage"]["identity"]["providerID"], "codex") + self.assertEqual(payload["usage"]["accountEmail"], "") + self.assertEqual(payload["usage"]["accountOrganization"], "") + self.assertEqual(payload["usage"]["identity"]["accountID"], "") + self.assertNotIn("secret-token", result.stderr) + self.assertNotIn("sk-live-prose-secret", result.stderr) + self.assertIn("", result.stderr) + + def test_include_identities_never_exposes_secret_keys(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + env, _ = make_env(Path(tmp)) + payload = json.loads(env["FAKE_USAGE_STDOUT"]) + payload[0]["usage"]["apiKey"] = "super-secret" + env["FAKE_USAGE_STDOUT"] = json.dumps(payload) + result = helper("usage", "--include-identities", env=env) + usage = json.loads(result.stdout)[0]["usage"] + self.assertEqual(usage["accountEmail"], "alice@example.com") + self.assertEqual(usage["apiKey"], "") + + def test_each_stream_is_capped_while_fully_drained(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + writer = root / "writer" + writer.write_text( + "#!/usr/bin/env python3\n" + "import sys\n" + "sys.stdout.buffer.write(b'o' * 2000000)\n" + "sys.stderr.buffer.write(b'e' * 2000000)\n", + encoding="utf-8", + ) + writer.chmod(0o755) + result = run_process([str(writer)]) + self.assertEqual(result.returncode, 0) + self.assertEqual(len(result.stdout), MAX_CAPTURE_BYTES) + self.assertEqual(len(result.stderr), MAX_CAPTURE_BYTES) + + def test_timeout_kills_process_group(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + env, _ = make_env(root) + marker = root / "child-survived" + env["CODEXBAR_TIMEOUT"] = "1" + env["FAKE_SPAWN_CHILD"] = "1" + env["FAKE_MARKER"] = str(marker) + result = helper("usage", env=env) + time.sleep(2.2) + self.assertEqual(result.returncode, 124) + self.assertEqual(json.loads(result.stdout)["error"]["kind"], "timeout") + self.assertFalse(marker.exists()) + + +if __name__ == "__main__": + unittest.main() diff --git a/.agents/skills/qa-test/SKILL.md b/.agents/skills/qa-test/SKILL.md new file mode 100644 index 0000000..81c752a --- /dev/null +++ b/.agents/skills/qa-test/SKILL.md @@ -0,0 +1,118 @@ +--- +name: qa-test +description: "CodexBar live QA/e2e testing: run provider usage matrix checks, validate real app config, use Peekaboo for menu proof, use Browser Use/official docs for API spec or logged-in dashboard checks, and handle 1Password credentials safely." +--- + +# CodexBar Live QA + +Use for live provider testing, release smoke tests, menu verification, or debugging “provider works/fails” reports. + +## Rules + +- Work from the CodexBar repo checkout. +- Use the packaged CLI first: `CodexBar.app/Contents/Helpers/CodexBarCLI`. +- Do not use `CodexBar.app/Contents/MacOS/codexbar`; that is the app binary and may appear to hang as a CLI. +- Never run broad `env`, `set`, or secret regex dumps. +- Use `$one-password` for secrets: all `op` commands inside one persistent tmux session, service account first, no raw secret output. +- Treat browser-cookie/keychain flows as prompt-risky. Prefer CLI/API-token checks and `KeychainNoUIQuery`-safe tests unless the user explicitly requested live UI. +- For current API behavior, browse official provider docs only. + +## CLI Matrix + +Run the bundled script: + +```bash +.agents/skills/qa-test/scripts/live_provider_matrix.sh --enabled +``` + +Useful modes: + +```bash +.agents/skills/qa-test/scripts/live_provider_matrix.sh --provider all +.agents/skills/qa-test/scripts/live_provider_matrix.sh --providers openai,zai,deepseek +.agents/skills/qa-test/scripts/live_provider_matrix.sh --default +``` + +Interpretation: + +- `--enabled` asks `CodexBarCLI config providers` for enabled providers, honoring `CODEXBAR_CONFIG` and default toggles. +- `--default` runs the app-facing default command with no provider override. +- `--provider all` forces every registered provider and is expected to fail for providers without sessions/keys. +- A green app config needs `--enabled` and `--default` clean; `--provider all` is a discovery/triage tool. + +## Config QA + +Validate config: + +```bash +CodexBar.app/Contents/Helpers/CodexBarCLI config validate +stat -f '%Lp %N' "$HOME/.codexbar/config.json" +``` + +Redact config shape: + +```bash +jq '(.providers // []) |= map(.apiKey = (if .apiKey then "" else .apiKey end) | + .secretKey = (if .secretKey then "" else .secretKey end) | + .cookieHeader = (if .cookieHeader then "" else .cookieHeader end) | + (if .id == "stepfun" and has("region") then .region = "" else . end) | + .tokenAccounts = (if .tokenAccounts then (.tokenAccounts | .accounts = (.accounts | map(.token = ""))) else .tokenAccounts end))' \ + "$HOME/.codexbar/config.json" +``` + +Before editing config, make a backup: + +```bash +cp "$HOME/.codexbar/config.json" "$HOME/.codexbar/config.pre-qa-$(date +%Y%m%d%H%M%S).json" +chmod 600 "$HOME/.codexbar"/config.pre-qa-*.json +``` + +## Live Menu QA + +Use Peekaboo after CLI checks: + +```bash +pkill -x CodexBar || pkill -f 'CodexBar.app/Contents/MacOS/CodexBar' || true +open -n "$PWD/CodexBar.app" +peekaboo menu list-all --json | rg -i 'codexbar' +peekaboo menu click-extra --title codexbar-merged --json +screencapture -x /tmp/codexbar-live-menu.png +``` + +Crop top-right menu if needed: + +```bash +sips --cropToHeightWidth 900 340 --cropOffset 20 2650 /tmp/codexbar-live-menu.png \ + --out /tmp/codexbar-live-menu-crop.png >/dev/null +``` + +Verify visually with `view_image`. Confirm provider tabs/rows match enabled config and no failing provider dominates the first screen. + +## Browser Use + +Use `$browser-use` only when a logged-in dashboard, API key page, or provider docs need browser/profile state. + +Existing Chrome path: + +```bash +mcporter call chrome-devtools.list_pages --args '{}' --output text +mcporter call chrome-devtools.navigate_page --args '{"url":"https://provider.example"}' --output text +mcporter call chrome-devtools.take_snapshot --args '{}' --output text +``` + +If Browser Use is unavailable, say so and use web search for public official docs; do not substitute isolated Playwright for login/profile-dependent pages. + +## Fix Triage + +- Missing auth/session: configure key/session if available; otherwise leave provider disabled or report blocked auth. +- Wrong provider API/spec: inspect official docs, then patch fetcher/settings/tests. +- Provider key exists but live API rejects it: keep key stored if useful, disable provider if the menu would show a persistent error. +- User-facing behavior changes need `CHANGELOG.md`. +- Code fixes need focused tests, `make check`, `$autoreview`, and live CLI proof before landing. + +## Known CodexBar QA Notes + +- OpenAI Admin API key is the useful usage provider key. Project `OPENAI_API_KEY` values can fail legacy credit-balance fallback with 403. +- Deepgram usage requires a key/project with Management API permissions; transcription-only keys can return 403. +- Groq usage uses the Prometheus metrics API, not ordinary inference endpoints. +- MiniMax pay-as-you-go API keys and Token Plan/Coding Plan keys are different; wrong key kind can leave usage unavailable. diff --git a/.agents/skills/qa-test/agents/openai.yaml b/.agents/skills/qa-test/agents/openai.yaml new file mode 100644 index 0000000..3bf7a7b --- /dev/null +++ b/.agents/skills/qa-test/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "CodexBar QA Test" + short_description: "Run live CodexBar CLI and menu QA safely." + default_prompt: "Run CodexBar live QA with CLI, Peekaboo, browser docs, and 1Password-safe credential checks." diff --git a/.agents/skills/qa-test/references/api-specs.md b/.agents/skills/qa-test/references/api-specs.md new file mode 100644 index 0000000..8bb7298 --- /dev/null +++ b/.agents/skills/qa-test/references/api-specs.md @@ -0,0 +1,10 @@ +# API Spec Pointers + +Use current official docs for provider API behavior. Prefer these searches/pages before patching fetchers: + +- MiniMax: `https://platform.minimax.io/docs/llms.txt`; key types differ between pay-as-you-go API keys and Token Plan/Coding Plan keys. +- Deepgram: `https://developers.deepgram.com/llms.txt`; usage/project APIs require Management permissions and project-scoped keys. +- Groq: `https://console.groq.com/docs/prometheus-metrics`; usage metrics use `https://api.groq.com/v1/metrics/prometheus`. +- LLM Proxy/LiteLLM: `https://docs.litellm.ai/`; CodexBar expects an LLM-API-Key-Proxy compatible `/v1/quota-stats` endpoint plus base URL. + +When citing docs in a user-facing answer, browse the current page and include source links. diff --git a/.agents/skills/qa-test/scripts/live_provider_matrix.sh b/.agents/skills/qa-test/scripts/live_provider_matrix.sh new file mode 100755 index 0000000..0c8240c --- /dev/null +++ b/.agents/skills/qa-test/scripts/live_provider_matrix.sh @@ -0,0 +1,183 @@ +#!/usr/bin/env bash +set -u + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../../.." && pwd)" +CLI="${CODEXBAR_CLI:-$ROOT/CodexBar.app/Contents/Helpers/CodexBarCLI}" +TIMEOUT_BIN="${TIMEOUT_BIN:-$(command -v gtimeout || command -v timeout || true)}" +WEB_TIMEOUT="${CODEXBAR_QA_WEB_TIMEOUT:-12}" +CASE_TIMEOUT="${CODEXBAR_QA_CASE_TIMEOUT:-60}" + +usage() { + cat <<'USAGE' +Usage: + live_provider_matrix.sh --enabled + live_provider_matrix.sh --default + live_provider_matrix.sh --provider all + live_provider_matrix.sh --providers openai,zai,deepseek + +Environment: + CODEXBAR_CLI=/path/to/CodexBarCLI + CODEXBAR_CONFIG=/path/to/config.json + CODEXBAR_QA_WEB_TIMEOUT=12 + CODEXBAR_QA_CASE_TIMEOUT=60 +USAGE +} + +if [[ ! -x "$CLI" ]]; then + echo "missing CodexBarCLI at $CLI" >&2 + exit 2 +fi +if [[ -z "$TIMEOUT_BIN" ]]; then + echo "missing timeout command (install coreutils for gtimeout)" >&2 + exit 2 +fi +if ! command -v node >/dev/null 2>&1; then + echo "missing node" >&2 + exit 2 +fi + +mode="${1:-}" +shift || true + +providers=() +case "$mode" in + --enabled) + provider_status="$(mktemp)" + provider_err="$(mktemp)" + provider_list="$(mktemp)" + if ! "$CLI" config providers --format json --json-only >"$provider_status" 2>"$provider_err"; then + rm -f "$provider_status" "$provider_err" "$provider_list" + echo "failed to list providers via CodexBarCLI config providers" >&2 + exit 2 + fi + if ! node - "$provider_status" >"$provider_list" <<'NODE'; then +const fs = require("fs"); +const path = process.argv[2]; +const raw = fs.readFileSync(path, "utf8").trim(); +const payload = JSON.parse(raw); +if (!Array.isArray(payload)) { + throw new Error("config providers output is not an array"); +} +for (const item of payload) { + if (item && item.enabled === true && typeof item.provider === "string" && item.provider) { + console.log(item.provider); + } +} +NODE + rm -f "$provider_status" "$provider_err" "$provider_list" + echo "failed to parse CodexBarCLI config providers output" >&2 + exit 2 + fi + while IFS= read -r provider; do + [[ -n "$provider" ]] && providers+=("$provider") + done <"$provider_list" + rm -f "$provider_status" "$provider_err" "$provider_list" + if [[ "${#providers[@]}" -eq 0 ]]; then + echo "no enabled providers found via CodexBarCLI config providers" >&2 + exit 2 + fi + ;; + --default) + providers=("__default__") + ;; + --provider) + if [[ -z "${1:-}" ]]; then + echo "missing provider" >&2 + exit 2 + fi + providers=("${1:-}") + ;; + --providers) + if [[ -z "${1:-}" ]]; then + echo "missing providers" >&2 + exit 2 + fi + IFS=',' read -r -a providers <<< "${1:-}" + ;; + -h|--help|"") + usage + exit 0 + ;; + *) + echo "unknown mode: $mode" >&2 + usage >&2 + exit 2 + ;; +esac + +redact_node=' +const redact = s => String(s || "") + .replace(/[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+/g, "") + .replace(/sk-[A-Za-z0-9_-]{12,}/g, "sk-REDACTED") + .replace(/gsk_[A-Za-z0-9_-]{12,}/g, "gsk_REDACTED") + .replace(/[A-Za-z0-9_-]{32,}/g, m => /[A-Za-z]/.test(m) && /[0-9]/.test(m) ? "" : m); +' + +run_one() { + local name="$1" + shift + local out err start end elapsed st node_status + out="$(mktemp)" + err="$(mktemp)" + start="$(date +%s)" + "$TIMEOUT_BIN" "$CASE_TIMEOUT" "$CLI" usage "$@" --format json --json-only --web-timeout "$WEB_TIMEOUT" >"$out" 2>"$err" + st=$? + end="$(date +%s)" + elapsed=$((end - start)) + node - "$name" "$st" "$elapsed" "$out" "$err" <&2 + exit 2 +fi +exit "$overall" diff --git a/.agents/skills/release-codexbar/SKILL.md b/.agents/skills/release-codexbar/SKILL.md new file mode 100644 index 0000000..2d823e8 --- /dev/null +++ b/.agents/skills/release-codexbar/SKILL.md @@ -0,0 +1,141 @@ +--- +name: release-codexbar +description: "CodexBar release: versioning, notarization, appcast, Homebrew, post-release bump." +--- + +# CodexBar Release + +Use for releasing signed/notarized macOS apps, especially repos with Sparkle appcasts and Homebrew casks. + +## Start + +1. Work from the app repo unless asked otherwise. +2. Check repo state, current version, latest tag/release, and release docs/scripts. +3. Confirm `CHANGELOG.md` is complete, user-facing, deduped, and dated for the release. +4. Prefer the repo release script; patch small script/test blockers instead of bypassing the release path. +5. Never print key material. Keep 1Password references and local key paths as references only. +6. Load `$release-private` if it exists before resolving Peter-owned credential locators. + +## Key Material + +Use `$one-password` for secret handling. `op` only in tmux/persistent shell; no broad `env`, `set`, `export -p`, or secret scans. + +Known App Store Connect shape: + +- fields: `private_key_p8`, `key_id`, `issuer_id` +- keep all three fields from the same 1Password item; do not mix with stale values from `~/.profile` +- resolve Peter-owned item refs from `$release-private` + +Known Sparkle key: + +- resolve the private key file from `$release-private` +- pass as `SPARKLE_PRIVATE_KEY_FILE` + +Safe env file pattern: + +```text +APP_STORE_CONNECT_API_KEY_P8=<1Password ref from release-private> +APP_STORE_CONNECT_KEY_ID=<1Password ref from release-private> +APP_STORE_CONNECT_ISSUER_ID=<1Password ref from release-private> +SPARKLE_PRIVATE_KEY_FILE= +``` + +Run with `op run --account my.1password.com --env-file -- `. + /// WebKit `document.body.innerText` often does not include the email, so we parse it from HTML. + public static func parseSignedInEmailFromClientBootstrap(html: String) -> String? { + guard let data = self.clientBootstrapJSONData(fromHTML: html) else { return nil } + guard let json = try? JSONSerialization.jsonObject(with: data, options: []) else { return nil } + + // Fast path: common structure. + if let dict = json as? [String: Any] { + if let session = dict["session"] as? [String: Any], + let user = session["user"] as? [String: Any], + let email = user["email"] as? String, + email.contains("@") + { + return email.trimmingCharacters(in: .whitespacesAndNewlines) + } + + if let user = dict["user"] as? [String: Any], + let email = user["email"] as? String, + email.contains("@") + { + return email.trimmingCharacters(in: .whitespacesAndNewlines) + } + } + + // Fallback: BFS scan for an email key/value. + var queue: [Any] = [json] + var seen = 0 + while !queue.isEmpty, seen < 4000 { + let cur = queue.removeFirst() + seen += 1 + if let dict = cur as? [String: Any] { + for (k, v) in dict { + if k.lowercased() == "email", let email = v as? String, email.contains("@") { + return email.trimmingCharacters(in: .whitespacesAndNewlines) + } + queue.append(v) + } + } else if let arr = cur as? [Any] { + queue.append(contentsOf: arr) + } + } + return nil + } + + /// Extracts the auth status from `client-bootstrap`, if present. + /// Expected values include `logged_in` and `logged_out`. + public static func parseAuthStatusFromClientBootstrap(html: String) -> String? { + guard let data = self.clientBootstrapJSONData(fromHTML: html) else { return nil } + guard let json = try? JSONSerialization.jsonObject(with: data, options: []) else { return nil } + guard let dict = json as? [String: Any] else { return nil } + if let authStatus = dict["authStatus"] as? String, !authStatus.isEmpty { + return authStatus.trimmingCharacters(in: .whitespacesAndNewlines) + } + return nil + } + + public static func parseCodeReviewRemainingPercent(bodyText: String) -> Double? { + let cleaned = bodyText.replacingOccurrences(of: "\r", with: "\n") + for regex in self.codeReviewRegexes { + let range = NSRange(cleaned.startIndex..= 2, + let r = Range(match.range(at: 1), in: cleaned) + else { continue } + if let val = Double(cleaned[r]) { return min(100, max(0, val)) } + } + return nil + } + + public static func parseCreditsRemaining(bodyText: String) -> Double? { + let cleaned = bodyText.replacingOccurrences(of: "\r", with: "\n") + let patterns = [ + #"credits\s*remaining[^0-9]*([0-9][0-9.,]*)"#, + #"remaining\s*credits[^0-9]*([0-9][0-9.,]*)"#, + #"credit\s*balance[^0-9]*([0-9][0-9.,]*)"#, + ] + for pattern in patterns { + if let val = TextParsing.firstNumber(pattern: pattern, text: cleaned) { return val } + } + return nil + } + + public static func parseRateLimits( + bodyText: String, + now: Date = .init()) -> (primary: RateWindow?, secondary: RateWindow?) + { + let cleaned = bodyText.replacingOccurrences(of: "\r", with: "\n") + let lines = cleaned + .split(whereSeparator: \.isNewline) + .map { $0.trimmingCharacters(in: .whitespacesAndNewlines) } + .filter { !$0.isEmpty } + + let primary = self.parseRateWindow( + lines: lines, + match: self.isFiveHourLimitLine, + windowMinutes: 5 * 60, + now: now) + let secondary = self.parseRateWindow( + lines: lines, + match: self.isWeeklyLimitLine, + windowMinutes: 7 * 24 * 60, + now: now) + return (primary, secondary) + } + + public static func parseCodeReviewLimit(bodyText: String, now: Date = .init()) -> RateWindow? { + let cleaned = bodyText.replacingOccurrences(of: "\r", with: "\n") + let lines = cleaned + .split(whereSeparator: \.isNewline) + .map { $0.trimmingCharacters(in: .whitespacesAndNewlines) } + .filter { !$0.isEmpty } + + return self.parseRateWindow( + lines: lines, + match: self.isCodeReviewLimitLine, + windowMinutes: nil, + now: now) + } + + public static func parsePlanFromHTML(html: String) -> String? { + if let data = self.clientBootstrapJSONData(fromHTML: html), + let plan = self.findPlan(in: data) + { + return plan + } + if let data = self.nextDataJSONData(fromHTML: html), + let plan = self.findPlan(in: data) + { + return plan + } + return nil + } + + public static func parseCreditEvents(rows: [[String]]) -> [CreditEvent] { + let formatter = self.creditDateFormatter() + + return rows.compactMap { row in + guard row.count >= 3 else { return nil } + let dateString = row[0] + let service = row[1].trimmingCharacters(in: .whitespacesAndNewlines) + let amountString = row[2] + guard let date = formatter.date(from: dateString) else { return nil } + let creditsUsed = Self.parseCreditsUsed(amountString) + return CreditEvent(date: date, service: service, creditsUsed: creditsUsed) + } + .sorted { $0.date > $1.date } + } + + private static func parseCreditsUsed(_ text: String) -> Double { + guard let raw = self.firstNumberToken(in: text) else { return 0 } + let token = raw + .replacingOccurrences(of: "\u{00A0}", with: "") + .replacingOccurrences(of: "\u{202F}", with: "") + .replacingOccurrences(of: " ", with: "") + let hasComma = token.contains(",") + let hasDot = token.contains(".") + if hasComma, hasDot { + return TextParsing.firstNumber(pattern: #"([0-9][0-9.,\s\p{Zs}]*)"#, text: token) ?? 0 + } + if hasComma { + if self.usesLocalizedDecimalCommaCreditLabel(text) { + return Double(token.replacingOccurrences(of: ",", with: ".")) ?? 0 + } + if token.range(of: #"^\d{1,3}(,\d{3})+$"#, options: .regularExpression) != nil { + return Double(token.replacingOccurrences(of: ",", with: "")) ?? 0 + } + return Double(token.replacingOccurrences(of: ",", with: ".")) ?? 0 + } + return Double(token) ?? 0 + } + + private static func usesLocalizedDecimalCommaCreditLabel(_ text: String) -> Bool { + text + .lowercased() + .contains("crédit") + } + + private static func firstNumberToken(in text: String) -> String? { + guard let regex = try? NSRegularExpression( + pattern: #"([0-9][0-9.,\s\p{Zs}]*)"#, + options: []) + else { + return nil + } + let range = NSRange(text.startIndex..= 2, + let tokenRange = Range(match.range(at: 1), in: text) + else { + return nil + } + return String(text[tokenRange]) + } + + // MARK: - Private + + private static let codeReviewRegexes: [NSRegularExpression] = { + let patterns = [ + #"Code\s*review[^0-9%]*([0-9]{1,3})%\s*remaining"#, + #"Core\s*review[^0-9%]*([0-9]{1,3})%\s*remaining"#, + ] + return patterns.compactMap { pattern in + try? NSRegularExpression(pattern: pattern, options: [.caseInsensitive]) + } + }() + + private static let creditDateFormatterKey = "OpenAIDashboardParser.creditDateFormatter" + private static let clientBootstrapNeedle = Data("id=\"client-bootstrap\"".utf8) + private static let nextDataNeedle = Data("id=\"__NEXT_DATA__\"".utf8) + private static let scriptCloseNeedle = Data("".utf8) + + private static func creditDateFormatter() -> DateFormatter { + let threadDict = Thread.current.threadDictionary + if let cached = threadDict[self.creditDateFormatterKey] as? DateFormatter { + return cached + } + let formatter = DateFormatter() + formatter.locale = Locale(identifier: "en_US_POSIX") + formatter.dateFormat = "MMM d, yyyy" + threadDict[self.creditDateFormatterKey] = formatter + return formatter + } + + private static func clientBootstrapJSONData(fromHTML html: String) -> Data? { + let data = Data(html.utf8) + guard let idRange = data.range(of: self.clientBootstrapNeedle) else { return nil } + + guard let openTagEnd = data[idRange.upperBound...].firstIndex(of: UInt8(ascii: ">")) else { return nil } + let contentStart = data.index(after: openTagEnd) + guard let closeRange = data.range( + of: self.scriptCloseNeedle, + options: [], + in: contentStart.. Data? { + let data = Data(html.utf8) + guard let idRange = data.range(of: self.nextDataNeedle) else { return nil } + + guard let openTagEnd = data[idRange.upperBound...].firstIndex(of: UInt8(ascii: ">")) else { return nil } + let contentStart = data.index(after: openTagEnd) + guard let closeRange = data.range( + of: self.scriptCloseNeedle, + options: [], + in: contentStart.. Data { + guard !data.isEmpty else { return data } + var start = data.startIndex + var end = data.endIndex + + while start < end, data[start].isASCIIWhitespace { + start = data.index(after: start) + } + while end > start { + let prev = data.index(before: end) + if data[prev].isASCIIWhitespace { + end = prev + } else { + break + } + } + return data.subdata(in: start.. Bool, + windowMinutes: Int?, + now: Date) -> RateWindow? + { + for idx in lines.indices where match(lines[idx]) { + let end = min(lines.count - 1, idx + 5) + let windowLines = Array(lines[idx...end]) + + var percentValue: Double? + var isRemaining = true + for line in windowLines { + if let percent = self.parsePercent(from: line) { + percentValue = percent.value + isRemaining = percent.isRemaining + break + } + } + + guard let percentValue else { continue } + let usedPercent = isRemaining ? max(0, min(100, 100 - percentValue)) : max(0, min(100, percentValue)) + + let resetLine = windowLines.first { $0.localizedCaseInsensitiveContains("reset") } + let resetDescription = resetLine?.trimmingCharacters(in: .whitespacesAndNewlines) + let resetsAt = resetLine.flatMap { self.parseResetDate(from: $0, now: now) } + let fallbackDescription = resetsAt.map { UsageFormatter.resetDescription(from: $0) } + + return RateWindow( + usedPercent: usedPercent, + windowMinutes: windowMinutes, + resetsAt: resetsAt, + resetDescription: resetDescription ?? fallbackDescription) + } + return nil + } + + private static func parsePercent(from line: String) -> (value: Double, isRemaining: Bool)? { + guard let percent = TextParsing.firstNumber(pattern: #"([0-9]{1,3})\s*%"#, text: line) else { return nil } + let lower = line.lowercased() + let isRemaining = lower.contains("remaining") || lower.contains("left") + let isUsed = lower.contains("used") || lower.contains("spent") || lower.contains("consumed") + if isUsed { return (percent, false) } + if isRemaining { return (percent, true) } + return (percent, true) + } + + private static func isFiveHourLimitLine(_ line: String) -> Bool { + let lower = line.lowercased() + if lower.contains("5h") { return true } + if lower.range(of: #"\b5\s*h\b"#, options: .regularExpression) != nil { return true } + if lower.contains("5-hour") { return true } + if lower.contains("5 hour") { return true } + return false + } + + private static func isWeeklyLimitLine(_ line: String) -> Bool { + let lower = line.lowercased() + if lower.contains("weekly") { return true } + if lower.contains("7-day") { return true } + if lower.contains("7 day") { return true } + if lower.contains("7d") { return true } + if lower.range(of: #"\b7\s*d\b"#, options: .regularExpression) != nil { return true } + return false + } + + private static func isCodeReviewLimitLine(_ line: String) -> Bool { + let lower = line.lowercased() + guard lower.contains("code review") || lower.contains("core review") else { return false } + if lower.contains("github code review") { return false } + return true + } + + private static func parseResetDate(from line: String, now: Date) -> Date? { + var raw = line.trimmingCharacters(in: .whitespacesAndNewlines) + raw = raw.replacingOccurrences(of: #"(?i)^resets?:?\s*"#, with: "", options: .regularExpression) + raw = raw.replacingOccurrences(of: " at ", with: " ", options: .caseInsensitive) + raw = raw.replacingOccurrences(of: " on ", with: " ", options: .caseInsensitive) + raw = raw.replacingOccurrences(of: #"\s+"#, with: " ", options: .regularExpression) + .trimmingCharacters(in: .whitespacesAndNewlines) + + let calendar = Calendar(identifier: .gregorian) + let monthDayFormatter = DateFormatter() + monthDayFormatter.locale = Locale(identifier: "en_US_POSIX") + monthDayFormatter.timeZone = TimeZone.current + monthDayFormatter.dateFormat = "MMM d" + + var candidate = raw + let lower = candidate.lowercased() + var usedRelativeDay = false + + if lower.contains("today") { + usedRelativeDay = true + let dateText = monthDayFormatter.string(from: now) + candidate = candidate.replacingOccurrences(of: "today", with: dateText, options: .caseInsensitive) + } else if lower.contains("tomorrow") { + usedRelativeDay = true + if let tomorrow = calendar.date(byAdding: .day, value: 1, to: now) { + let dateText = monthDayFormatter.string(from: tomorrow) + candidate = candidate.replacingOccurrences(of: "tomorrow", with: dateText, options: .caseInsensitive) + } + } + + if let weekdayMatch = self.weekdayMatch(in: candidate) { + usedRelativeDay = true + let target = self.nextWeekdayDate(weekday: weekdayMatch.weekday, now: now, calendar: calendar) + let dateText = monthDayFormatter.string(from: target) + candidate = candidate.replacingOccurrences( + of: weekdayMatch.matched, + with: dateText, + options: .caseInsensitive) + } + + let formatter = DateFormatter() + formatter.locale = Locale(identifier: "en_US_POSIX") + formatter.timeZone = TimeZone.current + formatter.defaultDate = now + + let formats = [ + "MMM d h:mma", + "MMM d, h:mma", + "MMM d h:mm a", + "MMM d, h:mm a", + "MMM d HH:mm", + "MMM d, HH:mm", + "MMM d", + "M/d h:mma", + "M/d h:mm a", + "M/d/yyyy h:mm a", + "M/d/yy h:mm a", + "M/d", + "yyyy-MM-dd HH:mm", + "yyyy-MM-dd h:mm a", + "yyyy-MM-dd", + ] + + for format in formats { + formatter.dateFormat = format + if let date = formatter.date(from: candidate) { + if usedRelativeDay, date < now { + if lower.contains("today"), + let bumped = calendar.date(byAdding: .day, value: 1, to: date) + { + return bumped + } + if let bumped = calendar.date(byAdding: .day, value: 7, to: date) { + return bumped + } + } + return date + } + } + return nil + } + + private struct WeekdayMatch { + let matched: String + let weekday: Int + } + + private static func weekdayMatch(in text: String) -> WeekdayMatch? { + // The optional "(day)?" suffix requires each alternative to be long enough that + // adding "day" reproduces the full weekday name. "wed"+"day"="wedday" and + // "sat"+"day"="satday", so the longer prefixes "wednes" and "satur" are needed + // to cover the full "Wednesday" and "Saturday" forms — mirroring how the existing + // "tue|tues" and "thu|thur|thurs" alternatives layer up to "tuesday"/"thursday". + let pattern = #"\b(mon|tue|tues|wed|wednes|thu|thur|thurs|fri|sat|satur|sun)(day)?\b"# + guard let regex = try? NSRegularExpression(pattern: pattern, options: [.caseInsensitive]) else { return nil } + let range = NSRange(text.startIndex.. Date { + let currentWeekday = calendar.component(.weekday, from: now) + var delta = weekday - currentWeekday + if delta < 0 { delta += 7 } + guard let next = calendar.date(byAdding: .day, value: delta, to: calendar.startOfDay(for: now)) else { + return now + } + return next + } + + private static func findPlan(in data: Data) -> String? { + guard let json = try? JSONSerialization.jsonObject(with: data, options: []) else { return nil } + return self.findPlan(in: json) + } + + private static func findPlan(in json: Any) -> String? { + var queue: [Any] = [json] + var seen = 0 + while !queue.isEmpty, seen < 6000 { + let cur = queue.removeFirst() + seen += 1 + if let dict = cur as? [String: Any] { + for (k, v) in dict { + if let plan = self.planCandidate(forKey: k, value: v) { return plan } + queue.append(v) + } + } else if let arr = cur as? [Any] { + queue.append(contentsOf: arr) + } + } + return nil + } + + private static func planCandidate(forKey key: String, value: Any) -> String? { + guard self.isPlanKey(key) else { return nil } + if let str = value as? String { + return self.normalizePlanValue(str) + } + if let dict = value as? [String: Any] { + if let name = dict["name"] as? String, let plan = self.normalizePlanValue(name) { return plan } + if let display = dict["displayName"] as? String, let plan = self.normalizePlanValue(display) { return plan } + if let tier = dict["tier"] as? String, let plan = self.normalizePlanValue(tier) { return plan } + } + return nil + } + + private static func isPlanKey(_ key: String) -> Bool { + let lower = key.lowercased() + return lower.contains("plan") || lower.contains("tier") || lower.contains("subscription") + } + + private static func normalizePlanValue(_ value: String) -> String? { + let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines) + guard !trimmed.isEmpty else { return nil } + let lower = trimmed.lowercased() + let allowed = [ + "free", + "plus", + "pro", + "team", + "enterprise", + "business", + "edu", + "education", + "gov", + "premium", + "essential", + ] + guard allowed.contains(where: { lower.contains($0) }) else { return nil } + return CodexPlanFormatting.displayName(trimmed) ?? UsageFormatter.cleanPlanName(trimmed) + } +} + +extension UInt8 { + fileprivate var isASCIIWhitespace: Bool { + switch self { + case 9, 10, 13, 32: true + default: false + } + } +} diff --git a/Sources/CodexBarCore/OpenAIWeb/OpenAIDashboardScrapeScript.swift b/Sources/CodexBarCore/OpenAIWeb/OpenAIDashboardScrapeScript.swift new file mode 100644 index 0000000..b45d573 --- /dev/null +++ b/Sources/CodexBarCore/OpenAIWeb/OpenAIDashboardScrapeScript.swift @@ -0,0 +1,907 @@ +#if os(macOS) +let openAIDashboardScrapeScript = """ + + (() => { + const textOf = el => { + const raw = el && (el.innerText || el.textContent) ? String(el.innerText || el.textContent) : ''; + return raw.trim(); + }; + const parseHexColor = (color) => { + if (!color) return null; + const c = String(color).trim().toLowerCase(); + if (c.startsWith('#')) { + if (c.length === 4) { + return '#' + c[1] + c[1] + c[2] + c[2] + c[3] + c[3]; + } + if (c.length === 7) return c; + return c; + } + const m = c.match(/^rgba?\\(([^)]+)\\)$/); + if (m) { + const parts = m[1].split(',').map(x => parseFloat(x.trim())).filter(x => Number.isFinite(x)); + if (parts.length >= 3) { + const r = Math.max(0, Math.min(255, Math.round(parts[0]))); + const g = Math.max(0, Math.min(255, Math.round(parts[1]))); + const b = Math.max(0, Math.min(255, Math.round(parts[2]))); + const toHex = n => n.toString(16).padStart(2, '0'); + return '#' + toHex(r) + toHex(g) + toHex(b); + } + } + return c; + }; + const reactPropsOf = (el) => { + if (!el) return null; + try { + const keys = Object.keys(el); + const propsKey = keys.find(k => k.startsWith('__reactProps$')); + if (propsKey) return el[propsKey] || null; + const fiberKey = keys.find(k => k.startsWith('__reactFiber$')); + if (fiberKey) { + const fiber = el[fiberKey]; + return (fiber && (fiber.memoizedProps || fiber.pendingProps)) || null; + } + } catch {} + return null; + }; + const reactFiberOf = (el) => { + if (!el) return null; + try { + const keys = Object.keys(el); + const fiberKey = keys.find(k => k.startsWith('__reactFiber$')); + return fiberKey ? (el[fiberKey] || null) : null; + } catch { + return null; + } + }; + const nestedBarMetaOf = (root) => { + if (!root || typeof root !== 'object') return null; + const queue = [root]; + const seen = typeof WeakSet !== 'undefined' ? new WeakSet() : null; + let steps = 0; + while (queue.length && steps < 250) { + const cur = queue.shift(); + steps++; + if (!cur || typeof cur !== 'object') continue; + if (seen) { + if (seen.has(cur)) continue; + seen.add(cur); + } + if (cur.payload && (cur.dataKey || cur.name || cur.value !== undefined)) return cur; + const values = Array.isArray(cur) ? cur : Object.values(cur); + for (const v of values) { + if (v && typeof v === 'object') queue.push(v); + } + } + return null; + }; + const barMetaFromElement = (el) => { + const direct = reactPropsOf(el); + if (direct && direct.payload && (direct.dataKey || direct.name || direct.value !== undefined)) return direct; + + const fiber = reactFiberOf(el); + if (fiber) { + let cur = fiber; + for (let i = 0; i < 10 && cur; i++) { + const props = (cur.memoizedProps || cur.pendingProps) || null; + if (props && props.payload && (props.dataKey || props.name || props.value !== undefined)) return props; + const nested = props ? nestedBarMetaOf(props) : null; + if (nested) return nested; + cur = cur.return || null; + } + } + + if (direct) { + const nested = nestedBarMetaOf(direct); + if (nested) return nested; + } + return null; + }; + const normalizeHref = (raw) => { + if (!raw) return null; + const href = String(raw).trim(); + if (!href) return null; + if (href.startsWith('http://') || href.startsWith('https://')) return href; + if (href.startsWith('//')) return window.location.protocol + href; + if (href.startsWith('/')) return window.location.origin + href; + return window.location.origin + '/' + href; + }; + const isLikelyCreditsURL = (raw) => { + if (!raw) return false; + try { + const url = new URL(raw, window.location.origin); + if (!url.host || !url.host.includes('chatgpt.com')) return false; + const path = url.pathname.toLowerCase(); + return ( + path.includes('settings') || + path.includes('usage') || + path.includes('billing') || + path.includes('credits') + ); + } catch { + return false; + } + }; + const purchaseTextMatches = (text) => { + const lower = String(text || '').trim().toLowerCase(); + if (!lower) return false; + if (lower.includes('add more')) return true; + if (!lower.includes('credit')) return false; + return ( + lower.includes('buy') || + lower.includes('add') || + lower.includes('purchase') || + lower.includes('top up') || + lower.includes('top-up') + ); + }; + const elementLabel = (el) => { + if (!el) return ''; + return ( + textOf(el) || + el.getAttribute('aria-label') || + el.getAttribute('title') || + '' + ); + }; + const urlFromProps = (props) => { + if (!props || typeof props !== 'object') return null; + const candidates = [ + props.href, + props.to, + props.url, + props.link, + props.destination, + props.navigateTo + ]; + for (const candidate of candidates) { + if (typeof candidate === 'string' && candidate.trim()) { + return normalizeHref(candidate); + } + } + return null; + }; + const purchaseURLFromElement = (el) => { + if (!el) return null; + const isAnchor = el.tagName && el.tagName.toLowerCase() === 'a'; + const anchor = isAnchor ? el : (el.closest ? el.closest('a') : null); + const anchorHref = anchor ? anchor.getAttribute('href') : null; + const dataHref = el.getAttribute + ? (el.getAttribute('data-href') || + el.getAttribute('data-url') || + el.getAttribute('data-link') || + el.getAttribute('data-destination')) + : null; + const propHref = urlFromProps(reactPropsOf(el)) || urlFromProps(reactPropsOf(anchor)); + const normalized = normalizeHref(anchorHref || dataHref || propHref); + return normalized && isLikelyCreditsURL(normalized) ? normalized : null; + }; + const cleanPlanName = (raw) => String(raw || '') + .replace(/\\b(claude|codex|account|plan)\\b/gi, ' ') + .replace(/_/g, ' ') + .replace(/-/g, ' ') + .replace(/\\s+/g, ' ') + .trim(); + const codexPlanDisplayName = (raw) => { + const trimmed = String(raw || '').trim(); + if (!trimmed) return null; + const lower = trimmed.toLowerCase(); + const exact = { + pro: 'Pro 20x', + prolite: 'Pro 5x', + 'pro_lite': 'Pro 5x', + 'pro-lite': 'Pro 5x', + 'pro lite': 'Pro 5x' + }; + if (exact[lower]) return exact[lower]; + const cleaned = cleanPlanName(trimmed); + if (!cleaned) return trimmed; + if (exact[cleaned.toLowerCase()]) return exact[cleaned.toLowerCase()]; + return cleaned.split(' ') + .filter(Boolean) + .map(word => { + const wordLower = word.toLowerCase(); + if (wordLower === 'cbp' || wordLower === 'k12') return wordLower.toUpperCase(); + if (word === word.toUpperCase() && /[a-z]/i.test(word)) return word; + return word.charAt(0).toUpperCase() + word.slice(1); + }) + .join(' ') || cleaned; + }; + const normalizePlanValue = (value) => { + const trimmed = String(value || '').trim(); + if (!trimmed) return null; + const lower = trimmed.toLowerCase(); + const allowed = [ + 'free', + 'plus', + 'pro', + 'team', + 'enterprise', + 'business', + 'edu', + 'education', + 'gov', + 'premium', + 'essential' + ]; + if (!allowed.some(token => lower.includes(token))) return null; + return codexPlanDisplayName(trimmed) || cleanPlanName(trimmed); + }; + const planCandidate = (key, value) => { + const lower = String(key || '').toLowerCase(); + if (!lower.includes('plan') && !lower.includes('tier') && !lower.includes('subscription')) return null; + if (typeof value === 'string') return normalizePlanValue(value); + if (value && typeof value === 'object' && !Array.isArray(value)) { + return normalizePlanValue(value.name) || + normalizePlanValue(value.displayName) || + normalizePlanValue(value.tier); + } + return null; + }; + const findPlan = (root) => { + if (!root || typeof root !== 'object') return null; + const queue = [root]; + const seenObjects = typeof WeakSet !== 'undefined' ? new WeakSet() : null; + let index = 0; + let seen = 0; + while (index < queue.length && seen < 6000) { + const cur = queue[index++]; + seen++; + if (!cur || typeof cur !== 'object') continue; + if (seenObjects) { + if (seenObjects.has(cur)) continue; + seenObjects.add(cur); + } + if (Array.isArray(cur)) { + for (const v of cur) { + if (v && typeof v === 'object') queue.push(v); + } + continue; + } + for (const [k, v] of Object.entries(cur)) { + const plan = planCandidate(k, v); + if (plan) return plan; + if (v && typeof v === 'object') queue.push(v); + } + } + return null; + }; + const parseJSONScript = (id) => { + try { + const node = document.getElementById(id); + const raw = node && node.textContent ? String(node.textContent) : ''; + return raw ? JSON.parse(raw) : null; + } catch { + return null; + } + }; + const pickLikelyPurchaseButton = (buttons) => { + if (!buttons || buttons.length === 0) return null; + const labeled = buttons.find(btn => { + const label = elementLabel(btn); + if (purchaseTextMatches(label)) return true; + const aria = String(btn.getAttribute('aria-label') || '').toLowerCase(); + return aria.includes('credit') || aria.includes('buy') || aria.includes('add'); + }); + return labeled || buttons[0]; + }; + const findCreditsPurchaseButton = () => { + const nodes = Array.from(document.querySelectorAll('h1,h2,h3,div,span,p')); + const labelMatch = nodes.find(node => { + const lower = textOf(node).toLowerCase(); + return lower === 'credits remaining' || (lower.includes('credits') && lower.includes('remaining')); + }); + if (!labelMatch) return null; + let cur = labelMatch; + for (let i = 0; i < 6 && cur; i++) { + const buttons = Array.from(cur.querySelectorAll('button, a')); + const picked = pickLikelyPurchaseButton(buttons); + if (picked) return picked; + cur = cur.parentElement; + } + return null; + }; + const dayKeyFromPayload = (payload) => { + if (!payload || typeof payload !== 'object') return null; + const localDayKeyForDate = (date) => { + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, '0'); + const day = String(date.getDate()).padStart(2, '0'); + return `${year}-${month}-${day}`; + }; + const keys = ['day', 'date', 'name', 'label', 'x', 'time', 'timestamp']; + for (const k of keys) { + const v = payload[k]; + if (typeof v === 'string') { + const s = v.trim(); + if (/^\\d{4}-\\d{2}-\\d{2}$/.test(s)) return s; + const iso = s.match(/^(\\d{4}-\\d{2}-\\d{2})/); + if (iso) return iso[1]; + } + if (typeof v === 'number' && Number.isFinite(v) && (k === 'timestamp' || k === 'time' || k === 'x')) { + try { + const d = new Date(v); + if (!isNaN(d.getTime())) return localDayKeyForDate(d); + } catch {} + } + } + return null; + }; + const isSkillUsageServiceKey = (raw) => { + const key = raw === null || raw === undefined ? '' : String(raw).trim().toLowerCase(); + return key.startsWith('skillusage:'); + }; + const displayNameForUsageServiceKey = (raw) => { + const key = raw === null || raw === undefined ? '' : String(raw).trim(); + if (!key) return key; + if (isSkillUsageServiceKey(key)) return null; + if (key.toUpperCase() === key && key.length <= 6) return key; + const lower = key.toLowerCase(); + if (lower === 'cli') return 'CLI'; + if (lower.includes('github') && lower.includes('review')) return 'GitHub Code Review'; + const words = lower.replace(/[_-]+/g, ' ').split(' ').filter(Boolean); + return words.map(w => w.length <= 2 ? w.toUpperCase() : w.charAt(0).toUpperCase() + w.slice(1)).join(' '); + }; + const isLikelyCodexUsageService = (raw) => { + const service = raw === null || raw === undefined ? '' : String(raw).trim().toLowerCase(); + return ( + service === 'cli' || + service === 'desktop' || + service === 'desktop app' || + service === 'vscode' || + service === 'vs code' || + service === 'unknown' || + (service.includes('github') && service.includes('review')) + ); + }; + const usageChartRootForPath = (path) => { + if (!path || !path.closest) return null; + return ( + path.closest('.recharts-wrapper') || + path.closest('svg.recharts-surface') || + path.closest('section') || + path.parentElement || + null + ); + }; + const uniqueUsageChartRoots = (paths) => { + const roots = []; + for (const path of paths) { + const root = usageChartRootForPath(path); + if (root && !roots.includes(root)) roots.push(root); + } + return roots; + }; + const usageBreakdownTitleScore = (title) => { + const lower = String(title || '').trim().toLowerCase().replace(/\\s+/g, ' '); + if (!lower) return 0; + if (lower === 'usage breakdown') return 1000000; + if (lower.includes('usage breakdown')) return 900000; + if (lower === 'personal usage') return 800000; + if (lower.includes('threads') || + lower.includes('turns') || + lower.includes('client') || + lower.includes('skill') || + lower.includes('invocation')) return -1000000; + return 0; + }; + const titleLikeElements = (scope) => { + try { + return Array.from(scope.querySelectorAll('h1,h2,h3,[role=\"heading\"],div,span,p')) + .filter(el => { + const title = textOf(el); + const lower = title.toLowerCase(); + const tag = el.tagName ? el.tagName.toLowerCase() : ''; + const isHeading = tag === 'h1' || + tag === 'h2' || + tag === 'h3' || + String(el.getAttribute('role') || '').toLowerCase() === 'heading'; + return title.length > 0 && + title.length <= 80 && + ( + isHeading || + usageBreakdownTitleScore(title) !== 0 || + lower.includes('usage breakdown') || + lower.includes('threads') || + lower.includes('turns') || + lower.includes('client') || + lower.includes('skill') || + lower.includes('invocation') + ); + }); + } catch { + return []; + } + }; + const titleNodePrecedesRoot = (titleNode, root) => { + if (!titleNode || titleNode === root || root.contains(titleNode) || titleNode.contains(root)) return false; + const relation = titleNode.compareDocumentPosition(root); + return Boolean(relation & Node.DOCUMENT_POSITION_FOLLOWING); + }; + const nearestScoredChartTitleInScope = (scope, root) => { + let best = null; + for (const titleNode of titleLikeElements(scope)) { + if (!titleNodePrecedesRoot(titleNode, root)) continue; + const title = textOf(titleNode); + const score = usageBreakdownTitleScore(title); + if (score === 0) continue; + if (!best || score >= best.score) best = { title, score }; + } + return best ? best.title : ''; + }; + const chartTitleBoundaryForRoot = (root) => { + if (!root) return null; + try { + return root.closest('section,[role=\"region\"],article') || root.parentElement || null; + } catch { + return root.parentElement || null; + } + }; + const nearestTitleTextInScope = (scope, root) => { + if (!scope) return ''; + let nearest = null; + for (const titleNode of titleLikeElements(scope)) { + if (titleNodePrecedesRoot(titleNode, root)) nearest = titleNode; + } + return textOf(nearest); + }; + const nearestChartTitleTextForRoot = (root) => { + if (!root) return ''; + try { + const boundary = chartTitleBoundaryForRoot(root) || root.parentElement || null; + let ancestor = root.parentElement || null; + for (let i = 0; i < 8 && ancestor; i++) { + const scoredTitle = nearestScoredChartTitleInScope(ancestor, root); + if (scoredTitle) return scoredTitle; + if (ancestor === boundary) break; + ancestor = ancestor.parentElement || null; + } + + return nearestTitleTextInScope(boundary, root); + } catch { + return ''; + } + }; + const legendMapForUsageChartRoot = (root) => { + const legendMap = {}; + const scopes = [ + root, + root && root.parentElement, + root && root.closest ? root.closest('section') : null + ].filter(Boolean); + for (const scope of scopes) { + try { + const legendItems = Array.from(scope.querySelectorAll('div[title]')); + for (const item of legendItems) { + const title = item.getAttribute('title') ? String(item.getAttribute('title')).trim() : ''; + const square = item.querySelector('div[style*=\"background-color\"]'); + const color = (square && square.style && square.style.backgroundColor) + ? square.style.backgroundColor + : null; + const hex = parseHexColor(color); + if (title && hex) legendMap[hex] = title; + } + } catch {} + if (Object.keys(legendMap).length > 0) break; + } + return legendMap; + }; + const parseUsageBreakdownFromChartPaths = (paths, legendMap) => { + const totalsByDay = {}; // day -> service -> value + const addValue = (day, service, value) => { + if (!day || !service || isSkillUsageServiceKey(service)) return false; + if (typeof value !== 'number' || !Number.isFinite(value) || value <= 0) return false; + if (!totalsByDay[day]) totalsByDay[day] = {}; + totalsByDay[day][service] = (totalsByDay[day][service] || 0) + value; + return true; + }; + let pointCount = 0; + for (const path of paths) { + const meta = barMetaFromElement(path) || barMetaFromElement(path.parentElement) || null; + if (!meta) continue; + + const payload = meta.payload || null; + const day = dayKeyFromPayload(payload); + if (!day) continue; + + const valuesObj = (payload && payload.values && typeof payload.values === 'object') ? payload.values : null; + if (valuesObj) { + for (const [k, v] of Object.entries(valuesObj)) { + const service = displayNameForUsageServiceKey(k); + if (addValue(day, service, v)) pointCount++; + } + continue; + } + + let value = null; + if (typeof meta.value === 'number' && Number.isFinite(meta.value)) value = meta.value; + if (value === null && typeof meta.value === 'string') { + const v = parseFloat(meta.value.replace(/,/g, '')); + if (Number.isFinite(v)) value = v; + } + if (value === null) continue; + + const fill = parseHexColor(meta.fill || path.getAttribute('fill')); + const service = + (fill && legendMap[fill]) || + (typeof meta.name === 'string' && meta.name) || + null; + if (addValue(day, service, value)) pointCount++; + } + + const dayKeys = Object.keys(totalsByDay) + .filter(day => Object.keys(totalsByDay[day] || {}).length > 0) + .sort((a, b) => b.localeCompare(a)) + .slice(0, 30); + const breakdown = dayKeys.map(day => { + const servicesMap = totalsByDay[day] || {}; + const services = Object.keys(servicesMap).map(service => ({ + service, + creditsUsed: servicesMap[service] + })).sort((a, b) => { + if (a.creditsUsed === b.creditsUsed) return a.service.localeCompare(b.service); + return b.creditsUsed - a.creditsUsed; + }); + const totalCreditsUsed = services.reduce((sum, s) => sum + (Number(s.creditsUsed) || 0), 0); + return { day, services, totalCreditsUsed }; + }); + const services = Array.from(new Set(breakdown.flatMap(day => day.services.map(service => service.service)))); + const totalCreditsUsed = breakdown.reduce((sum, day) => sum + (Number(day.totalCreditsUsed) || 0), 0); + const likelyCodexServiceCount = services.filter(isLikelyCodexUsageService).length; + return { + breakdown, + pointCount, + services, + totalCreditsUsed, + likelyCodexServiceCount, + score: likelyCodexServiceCount * 1000 + services.length * 100 + pointCount + totalCreditsUsed / 1000 + }; + }; + const usageBreakdownJSON = (() => { + try { + if (window.__codexbarUsageBreakdownJSON) return window.__codexbarUsageBreakdownJSON; + + const paths = Array.from(document.querySelectorAll('g.recharts-bar-rectangle path.recharts-rectangle')); + let debug = { + pathCount: paths.length, + chartCount: 0, + eligibleCandidateCount: 0, + selectedCandidateTitle: null, + candidateSummaries: [], + sampleReactKeys: null, + sampleMetaKeys: null, + samplePayloadKeys: null, + sampleValuesKeys: null, + sampleDayKey: null + }; + try { + const sample = paths[0] || null; + if (sample) { + const names = Object.getOwnPropertyNames(sample); + debug.sampleReactKeys = names.filter(k => k.includes('react')).slice(0, 10); + const metaSample = barMetaFromElement(sample) || barMetaFromElement(sample.parentElement) || null; + if (metaSample) { + debug.sampleMetaKeys = Object.keys(metaSample).slice(0, 12); + const payload = metaSample.payload || null; + if (payload && typeof payload === 'object') { + debug.samplePayloadKeys = Object.keys(payload).slice(0, 12); + debug.sampleDayKey = dayKeyFromPayload(payload); + const values = payload.values || null; + if (values && typeof values === 'object') { + debug.sampleValuesKeys = Object.keys(values).slice(0, 12); + } + } + } + } + } catch {} + + const roots = uniqueUsageChartRoots(paths); + debug.chartCount = roots.length; + const candidates = roots.map(root => { + const chartPaths = paths.filter(path => usageChartRootForPath(path) === root); + const title = nearestChartTitleTextForRoot(root); + const titleScore = usageBreakdownTitleScore(title); + const parsed = parseUsageBreakdownFromChartPaths(chartPaths, legendMapForUsageChartRoot(root)); + return { + root, + title, + titleScore, + pathCount: chartPaths.length, + ...parsed, + score: titleScore + parsed.score + }; + }).filter(candidate => candidate.breakdown.length > 0); + const rejectedTitleCandidates = candidates.filter(candidate => candidate.titleScore < 0); + const titledCandidates = candidates.filter(candidate => candidate.titleScore > 0); + const unknownTitleCandidates = candidates.filter(candidate => candidate.titleScore === 0); + const eligibleCandidates = titledCandidates; + eligibleCandidates.sort((a, b) => b.score - a.score); + debug.eligibleCandidateCount = eligibleCandidates.length; + debug.selectedCandidateTitle = eligibleCandidates[0] ? eligibleCandidates[0].title : null; + if (eligibleCandidates.length === 0 && candidates.length > 0) { + if (unknownTitleCandidates.length > 0) { + debug.error = 'No English usage breakdown chart title found. Candidate titles: ' + + candidates.map(candidate => candidate.title || 'Untitled chart').join(', '); + } else if (rejectedTitleCandidates.length > 0) { + debug.error = 'Only non-usage chart candidates found: ' + + rejectedTitleCandidates.map(candidate => candidate.title || 'Untitled chart').join(', '); + } + } + debug.candidateSummaries = candidates.slice(0, 6).map(candidate => ({ + title: candidate.title, + titleScore: candidate.titleScore, + pathCount: candidate.pathCount, + dayCount: candidate.breakdown.length, + pointCount: candidate.pointCount, + serviceCount: candidate.services.length, + likelyCodexServiceCount: candidate.likelyCodexServiceCount, + services: candidate.services.slice(0, 8) + })); + + const breakdown = eligibleCandidates[0] ? eligibleCandidates[0].breakdown : []; + const json = (breakdown.length > 0) ? JSON.stringify(breakdown) : null; + window.__codexbarUsageBreakdownJSON = json; + window.__codexbarUsageBreakdownDebug = json ? null : JSON.stringify(debug); + return json; + } catch { + return null; + } + })(); + const usageBreakdownDebug = (() => { + try { + return window.__codexbarUsageBreakdownDebug || null; + } catch { + return null; + } + })(); + const usageBreakdownError = (() => { + try { + if (!usageBreakdownDebug) return null; + const parsed = JSON.parse(usageBreakdownDebug); + return parsed && parsed.error ? String(parsed.error) : null; + } catch { + return null; + } + })(); + const bodyText = document.body ? String(document.body.innerText || '').trim() : ''; + const href = window.location ? String(window.location.href || '') : ''; + const workspacePicker = bodyText.includes('Select a workspace'); + const title = document.title ? String(document.title || '') : ''; + const cloudflareInterstitial = + title.toLowerCase().includes('just a moment') || + bodyText.toLowerCase().includes('checking your browser') || + bodyText.toLowerCase().includes('cloudflare'); + const authSelector = [ + 'input[type="email"]', + 'input[type="password"]', + 'input[name="username"]' + ].join(', '); + const hasAuthInputs = !!document.querySelector(authSelector); + const lower = bodyText.toLowerCase(); + const loginCTA = + lower.includes('sign in') || + lower.includes('log in') || + lower.includes('continue with google') || + lower.includes('continue with apple') || + lower.includes('continue with microsoft'); + const loginRequired = + href.includes('/auth/') || + href.includes('/login') || + (hasAuthInputs && loginCTA) || + (!hasAuthInputs && loginCTA && href.includes('chatgpt.com')); + const scrollY = (typeof window.scrollY === 'number') ? window.scrollY : 0; + const scrollHeight = document.documentElement ? (document.documentElement.scrollHeight || 0) : 0; + const viewportHeight = (typeof window.innerHeight === 'number') ? window.innerHeight : 0; + + let creditsHeaderPresent = false; + let creditsHeaderInViewport = false; + let didScrollToCredits = false; + let rows = []; + try { + const looksLikeCreditsEventRow = (cells) => { + if (!cells || cells.length < 3) return false; + const first = String(cells[0] || ''); + const amount = String(cells[2] || ''); + return /\\d{4}|\\d{1,2}[\\/.\\-]\\d{1,2}/.test(first) && /\\d/.test(amount); + }; + const allTableRows = () => Array.from(document.querySelectorAll('tbody tr')).map(tr => { + const cells = Array.from(tr.querySelectorAll('td')).map(td => textOf(td)); + return cells; + }).filter(looksLikeCreditsEventRow); + const headings = Array.from(document.querySelectorAll('h1,h2,h3')); + const header = headings.find(h => textOf(h).toLowerCase() === 'credits usage history'); + if (header) { + creditsHeaderPresent = true; + const rect = header.getBoundingClientRect(); + creditsHeaderInViewport = rect.top >= 0 && rect.top <= viewportHeight; + + // Only scrape rows from the *credits usage history* table. The page can contain other tables, + // and treating any as credits history can prevent our scroll-to-load logic from running. + const container = header.closest('section') || header.parentElement || document; + const table = container.querySelector('table') || null; + const scope = table || container; + rows = Array.from(scope.querySelectorAll('tbody tr')).map(tr => { + const cells = Array.from(tr.querySelectorAll('td')).map(td => textOf(td)); + return cells; + }).filter(r => r.length >= 3); + if (rows.length === 0) { + rows = allTableRows(); + } + if (rows.length === 0 && !window.__codexbarDidScrollToCredits) { + window.__codexbarDidScrollToCredits = true; + // If the table is virtualized/lazy-loaded, we need to scroll to trigger rendering even if the + // header is already in view. + header.scrollIntoView({ block: 'start', inline: 'nearest' }); + if (creditsHeaderInViewport) { + window.scrollBy(0, Math.max(220, viewportHeight * 0.6)); + } + didScrollToCredits = true; + } + } else if (rows.length === 0 && !window.__codexbarDidScrollToCredits && scrollHeight > viewportHeight * 1.5) { + rows = allTableRows(); + if (rows.length > 0) { + creditsHeaderPresent = true; + creditsHeaderInViewport = true; + } + } + if (rows.length === 0 && !window.__codexbarDidScrollToCredits && scrollHeight > viewportHeight * 1.5) { + // The credits history section often isn't part of the DOM until you scroll down. Nudge the page + // once so subsequent scrapes can find the header and rows. + window.__codexbarDidScrollToCredits = true; + window.scrollTo(0, Math.max(0, scrollHeight - viewportHeight - 40)); + didScrollToCredits = true; + } + } catch {} + + let creditsPurchaseURL = null; + try { + const creditsButton = findCreditsPurchaseButton(); + if (creditsButton) { + const url = purchaseURLFromElement(creditsButton); + if (url) creditsPurchaseURL = url; + } + const candidates = Array.from(document.querySelectorAll('a, button')); + for (const node of candidates) { + const label = elementLabel(node); + if (!purchaseTextMatches(label)) continue; + const url = purchaseURLFromElement(node); + if (url) { + creditsPurchaseURL = url; + break; + } + } + if (!creditsPurchaseURL) { + const anchors = Array.from(document.querySelectorAll('a[href]')); + for (const anchor of anchors) { + const label = elementLabel(anchor); + const href = anchor.getAttribute('href') || ''; + const hrefLooksRelevant = /credits|billing/i.test(href); + if (!hrefLooksRelevant && !purchaseTextMatches(label)) continue; + const url = normalizeHref(href); + if (url) { + creditsPurchaseURL = url; + break; + } + } + } + } catch {} + + let signedInEmail = null; + let authStatus = null; + let accountPlan = null; + try { + const next = window.__NEXT_DATA__ || null; + const props = (next && next.props && next.props.pageProps) ? next.props.pageProps : null; + const userEmail = (props && props.user) ? props.user.email : null; + const sessionEmail = (props && props.session && props.session.user) ? props.session.user.email : null; + signedInEmail = userEmail || sessionEmail || null; + } catch {} + + const clientBootstrap = parseJSONScript('client-bootstrap'); + if (clientBootstrap) { + try { + authStatus = typeof clientBootstrap.authStatus === 'string' ? clientBootstrap.authStatus : null; + if (!signedInEmail) { + const session = clientBootstrap.session || null; + const user = (session && session.user) || clientBootstrap.user || null; + const email = user && typeof user.email === 'string' ? user.email : null; + if (email && email.includes('@')) signedInEmail = email; + } + if (!accountPlan) accountPlan = findPlan(clientBootstrap); + } catch {} + } + if (!accountPlan) { + try { + accountPlan = findPlan(window.__NEXT_DATA__ || parseJSONScript('__NEXT_DATA__')); + } catch {} + } + + if (!signedInEmail) { + try { + const obj = parseJSONScript('__NEXT_DATA__'); + if (obj) { + const queue = [obj]; + let seen = 0; + while (queue.length && seen < 2000 && !signedInEmail) { + const cur = queue.shift(); + seen++; + if (!cur) continue; + if (typeof cur === 'string') { + if (cur.includes('@')) signedInEmail = cur; + continue; + } + if (typeof cur !== 'object') continue; + for (const [k, v] of Object.entries(cur)) { + if (signedInEmail) break; + if (k === 'email' && typeof v === 'string' && v.includes('@')) { + signedInEmail = v; + break; + } + if (typeof v === 'object' && v) queue.push(v); + } + } + } + } catch {} + } + + if (!signedInEmail) { + try { + const emailRe = /[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}/ig; + const found = (bodyText.match(emailRe) || []).map(x => String(x).trim().toLowerCase()); + const unique = Array.from(new Set(found)); + if (unique.length === 1) { + signedInEmail = unique[0]; + } else if (unique.length > 1) { + signedInEmail = unique[0]; + } + } catch {} + } + + if (!signedInEmail) { + // Last resort: open the account menu so the email becomes part of the DOM text. + try { + const emailRe = /[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}/ig; + const hasMenu = Boolean(document.querySelector('[role="menu"]')); + if (!hasMenu) { + const button = + document.querySelector('button[aria-haspopup="menu"]') || + document.querySelector('button[aria-expanded]'); + if (button && !button.disabled) { + button.click(); + } + } + const afterText = document.body ? String(document.body.innerText || '').trim() : ''; + const found = (afterText.match(emailRe) || []).map(x => String(x).trim().toLowerCase()); + const unique = Array.from(new Set(found)); + if (unique.length === 1) { + signedInEmail = unique[0]; + } else if (unique.length > 1) { + signedInEmail = unique[0]; + } + } catch {} + } + + return { + loginRequired, + workspacePicker, + cloudflareInterstitial, + href, + bodyText, + signedInEmail, + authStatus, + accountPlan, + creditsPurchaseURL, + rows, + usageBreakdownJSON, + usageBreakdownDebug, + usageBreakdownError, + scrollY, + scrollHeight, + viewportHeight, + creditsHeaderPresent, + creditsHeaderInViewport, + didScrollToCredits + }; + })(); + +""" +#endif diff --git a/Sources/CodexBarCore/OpenAIWeb/OpenAIDashboardWebViewCache.swift b/Sources/CodexBarCore/OpenAIWeb/OpenAIDashboardWebViewCache.swift new file mode 100644 index 0000000..c406e99 --- /dev/null +++ b/Sources/CodexBarCore/OpenAIWeb/OpenAIDashboardWebViewCache.swift @@ -0,0 +1,782 @@ +#if os(macOS) +import AppKit +import Foundation +import WebKit + +struct OpenAIDashboardWebViewLease { + let webView: WKWebView + let log: (String) -> Void + let setPreserveLoadedPageOnRelease: (Bool) -> Void + let release: () -> Void +} + +@MainActor +final class OpenAIDashboardWebViewCache { + static let shared = OpenAIDashboardWebViewCache() + fileprivate static let log = CodexBarLog.logger(LogCategories.openAIWebview) + + private final class ReleaseState { + var preserveLoadedPageOnRelease: Bool + + init(preserveLoadedPageOnRelease: Bool) { + self.preserveLoadedPageOnRelease = preserveLoadedPageOnRelease + } + } + + private struct AcquireOptions { + let allowTimeoutRetry: Bool + let preserveLoadedPageOnRelease: Bool + } + + @MainActor + private final class NavigationCancellationState { + private weak var webView: WKWebView? + private var delegate: NavigationDelegate? + private var isCancelled = false + + func install(webView: WKWebView, delegate: NavigationDelegate) { + self.webView = webView + self.delegate = delegate + if self.isCancelled { + self.cancel() + } + } + + func cancel() { + self.isCancelled = true + guard let webView, let delegate else { return } + delegate.cancel() + if webView.codexNavigationDelegate === delegate { + webView.stopLoading() + webView.navigationDelegate = nil + webView.codexNavigationDelegate = nil + } + self.delegate = nil + self.webView = nil + } + } + + private final class Entry { + let webView: WKWebView + let host: OffscreenWebViewHost + var lastUsedAt: Date + var isBusy: Bool + var preservedPageExpiresAt: Date? + var preservedPageExpiryWorkItem: DispatchWorkItem? + + init( + webView: WKWebView, + host: OffscreenWebViewHost, + lastUsedAt: Date, + isBusy: Bool, + preservedPageExpiresAt: Date? = nil) + { + self.webView = webView + self.host = host + self.lastUsedAt = lastUsedAt + self.isBusy = isBusy + self.preservedPageExpiresAt = preservedPageExpiresAt + } + + func armPreservedPage(until expiry: Date) { + self.preservedPageExpiresAt = expiry + } + + func setPreservedPageExpiryWorkItem(_ workItem: DispatchWorkItem?) { + self.preservedPageExpiryWorkItem?.cancel() + self.preservedPageExpiryWorkItem = workItem + } + + func clearPreservedPage() { + self.preservedPageExpiresAt = nil + self.preservedPageExpiryWorkItem?.cancel() + self.preservedPageExpiryWorkItem = nil + } + + func consumePreservedPageReuseIfAvailable(now: Date) -> Bool { + guard let preservedPageExpiresAt else { return false } + self.preservedPageExpiresAt = nil + self.preservedPageExpiryWorkItem?.cancel() + self.preservedPageExpiryWorkItem = nil + return preservedPageExpiresAt > now + } + + func hasExpiredPreservedPage(now: Date) -> Bool { + guard let preservedPageExpiresAt else { return false } + return preservedPageExpiresAt <= now + } + } + + private var entries: [ObjectIdentifier: Entry] = [:] + /// Keep the WebView alive only long enough for immediate retries/menu reopens. + /// Long-lived hidden ChatGPT tabs still consume noticeable energy on some setups. + private let idleTimeout: TimeInterval + private var idlePruneWorkItem: DispatchWorkItem? + private var idlePruneGeneration = 0 + #if DEBUG + private(set) var idlePruneDeadlineForTesting: Date? + #endif + /// Reuse the validated analytics page only for the immediate next handoff. + private let preservedPageHandoffTimeout: TimeInterval = 5 + private let blankURL = URL(string: "about:blank")! + private let idlePageClearScript = """ + (() => { + try { + document.documentElement.innerHTML = ''; + return true; + } catch { + return false; + } + })(); + """ + private let reusablePageResetScript = """ + (() => { + try { + delete window.__codexbarDidScrollToCredits; + delete window.__codexbarUsageBreakdownJSON; + delete window.__codexbarUsageBreakdownDebug; + return true; + } catch { + return false; + } + })(); + """ + private let preferredLanguageScript = """ + (() => { + const define = (target, name, value) => { + try { + Object.defineProperty(target, name, { + get: () => value, + configurable: true + }); + } catch {} + }; + define(Navigator.prototype, 'language', 'en-US'); + define(Navigator.prototype, 'languages', ['en-US', 'en']); + define(navigator, 'language', 'en-US'); + define(navigator, 'languages', ['en-US', 'en']); + })(); + """ + + init(idleTimeout: TimeInterval = 60) { + self.idleTimeout = idleTimeout + } + + nonisolated static func remainingNavigationTimeout( + until deadline: Date, + now: Date = Date()) throws -> TimeInterval + { + let remaining = deadline.timeIntervalSince(now) + guard remaining > 0 else { throw URLError(.timedOut) } + return remaining + } + + private func releaseCachedEntry(_ entry: Entry, preserveLoadedPage: Bool) { + entry.isBusy = false + let now = Date() + entry.lastUsedAt = now + self.updatePreservedPageState(for: entry, preserveLoadedPage: preserveLoadedPage) + self.prepareCachedWebViewForIdle( + entry.webView, + host: entry.host, + preserveLoadedPage: preserveLoadedPage) + self.prune(now: now) + self.scheduleNextIdlePrune(now: now) + } + + private func releaseNewEntry(_ entry: Entry, webView: WKWebView, preserveLoadedPage: Bool) { + entry.isBusy = false + let now = Date() + entry.lastUsedAt = now + self.updatePreservedPageState(for: entry, preserveLoadedPage: preserveLoadedPage) + self.prepareCachedWebViewForIdle( + webView, + host: entry.host, + preserveLoadedPage: preserveLoadedPage) + self.prune(now: now) + self.scheduleNextIdlePrune(now: now) + } + + // MARK: - Testing support + + #if DEBUG + /// Number of cached WebView entries (for testing). + var entryCount: Int { + self.entries.count + } + + /// Check if a WebView is cached for the given data store (for testing). + func hasCachedEntry(for websiteDataStore: WKWebsiteDataStore) -> Bool { + let key = ObjectIdentifier(websiteDataStore) + return self.entries[key] != nil + } + + /// Force prune with a custom "now" timestamp (for testing idle timeout). + func pruneForTesting(now: Date) { + self.prune(now: now) + } + + var idleTimeoutForTesting: TimeInterval { + self.idleTimeout + } + + var preservedPageHandoffTimeoutForTesting: TimeInterval { + self.preservedPageHandoffTimeout + } + + func hasPreservedPageForTesting(for websiteDataStore: WKWebsiteDataStore) -> Bool { + let key = ObjectIdentifier(websiteDataStore) + return self.entries[key]?.preservedPageExpiresAt != nil + } + + func markPreservedPageForTesting( + websiteDataStore: WKWebsiteDataStore, + expiresAt: Date = .init().addingTimeInterval(5)) + { + let key = ObjectIdentifier(websiteDataStore) + guard let entry = self.entries[key] else { return } + entry.armPreservedPage(until: expiresAt) + self.schedulePreservedPageExpiry(for: key, entry: entry, expiresAt: expiresAt) + } + + func consumePreservedPageForTesting(websiteDataStore: WKWebsiteDataStore, now: Date = Date()) -> Bool { + let key = ObjectIdentifier(websiteDataStore) + guard let entry = self.entries[key] else { return false } + return entry.consumePreservedPageReuseIfAvailable(now: now) + } + + /// Seed a cached entry without navigating a real page (for test stability). + @discardableResult + func cacheEntryForTesting( + websiteDataStore: WKWebsiteDataStore, + lastUsedAt: Date = Date(), + isBusy: Bool = false) -> WKWebView + { + let key = ObjectIdentifier(websiteDataStore) + if let existing = self.entries.removeValue(forKey: key) { + existing.host.close() + } + + let (webView, host) = self.makeWebView(websiteDataStore: websiteDataStore) + let entry = Entry(webView: webView, host: host, lastUsedAt: lastUsedAt, isBusy: isBusy) + self.entries[key] = entry + if isBusy { + host.show() + } else { + host.hide() + } + return webView + } + + /// Clear all cached entries (for test isolation). + func clearAllForTesting() { + self.cancelIdlePrune() + for (_, entry) in self.entries { + entry.clearPreservedPage() + entry.host.close() + } + self.entries.removeAll() + } + + func resetReusablePageStateForTesting(_ webView: WKWebView) async -> Bool { + await self.resetReusablePageState(webView) + } + #endif + + func acquire( + websiteDataStore: WKWebsiteDataStore, + usageURL: URL, + logger: ((String) -> Void)?, + navigationTimeout: TimeInterval = 15, + allowTimeoutRetry: Bool = true, + preserveLoadedPageOnRelease: Bool = false) async throws -> OpenAIDashboardWebViewLease + { + let deadline = Date().addingTimeInterval(max(navigationTimeout, 0.01)) + return try await self.acquire( + websiteDataStore: websiteDataStore, + usageURL: usageURL, + logger: logger, + deadline: deadline, + options: .init( + allowTimeoutRetry: allowTimeoutRetry, + preserveLoadedPageOnRelease: preserveLoadedPageOnRelease)) + } + + private func acquire( + websiteDataStore: WKWebsiteDataStore, + usageURL: URL, + logger: ((String) -> Void)?, + deadline: Date, + options: AcquireOptions) async throws -> OpenAIDashboardWebViewLease + { + let now = Date() + self.prune(now: now) + + let log: (String) -> Void = { message in + logger?("[webview] \(message)") + } + let key = ObjectIdentifier(websiteDataStore) + let remainingTimeout = try Self.remainingNavigationTimeout(until: deadline, now: now) + + if let entry = self.entries[key] { + if entry.isBusy { + log("Cached WebView busy; using a temporary WebView.") + let (webView, host) = self.makeWebView(websiteDataStore: websiteDataStore) + host.show() + do { + try await self.prepareWebView( + webView, + usageURL: usageURL, + timeout: remainingTimeout, + canReuseLoadedPage: false) + } catch { + if options.allowTimeoutRetry, Self.isPrepareTimeout(error) { + host.close() + log("Temporary OpenAI WebView timed out; retrying with a fresh WebView.") + return try await self.acquireTemporaryWebView( + websiteDataStore: websiteDataStore, + usageURL: usageURL, + log: log, + deadline: deadline) + } + host.close() + throw error + } + return OpenAIDashboardWebViewLease( + webView: webView, + log: log, + setPreserveLoadedPageOnRelease: { _ in }, + release: { host.close() }) + } + + entry.isBusy = true + entry.lastUsedAt = now + let canReuseLoadedPage = entry.consumePreservedPageReuseIfAvailable(now: now) + let releaseState = ReleaseState(preserveLoadedPageOnRelease: options.preserveLoadedPageOnRelease) + entry.host.show() + do { + try await self.prepareWebView( + entry.webView, + usageURL: usageURL, + timeout: remainingTimeout, + canReuseLoadedPage: canReuseLoadedPage) + } catch { + if options.allowTimeoutRetry, Self.isPrepareTimeout(error) { + entry.isBusy = false + entry.lastUsedAt = Date() + entry.clearPreservedPage() + entry.host.close() + self.entries.removeValue(forKey: key) + log("Cached OpenAI WebView timed out; recreating it.") + return try await self.acquire( + websiteDataStore: websiteDataStore, + usageURL: usageURL, + logger: logger, + deadline: deadline, + options: .init( + allowTimeoutRetry: false, + preserveLoadedPageOnRelease: options.preserveLoadedPageOnRelease)) + } + entry.isBusy = false + entry.lastUsedAt = Date() + entry.clearPreservedPage() + entry.host.close() + self.entries.removeValue(forKey: key) + Self.log.warning("OpenAI webview prepare failed") + throw error + } + + return OpenAIDashboardWebViewLease( + webView: entry.webView, + log: log, + setPreserveLoadedPageOnRelease: { preserveLoadedPageOnRelease in + releaseState.preserveLoadedPageOnRelease = preserveLoadedPageOnRelease + }, + release: { [weak self, weak entry] in + guard let self, let entry else { return } + self.releaseCachedEntry( + entry, + preserveLoadedPage: releaseState.preserveLoadedPageOnRelease) + }) + } + + let (webView, host) = self.makeWebView(websiteDataStore: websiteDataStore) + let entry = Entry(webView: webView, host: host, lastUsedAt: now, isBusy: true) + self.entries[key] = entry + host.show() + let releaseState = ReleaseState(preserveLoadedPageOnRelease: options.preserveLoadedPageOnRelease) + + do { + try await self.prepareWebView( + webView, + usageURL: usageURL, + timeout: remainingTimeout, + canReuseLoadedPage: false) + } catch { + if options.allowTimeoutRetry, Self.isPrepareTimeout(error) { + self.entries.removeValue(forKey: key) + host.close() + log("OpenAI WebView timed out during prepare; retrying once.") + return try await self.acquire( + websiteDataStore: websiteDataStore, + usageURL: usageURL, + logger: logger, + deadline: deadline, + options: .init( + allowTimeoutRetry: false, + preserveLoadedPageOnRelease: options.preserveLoadedPageOnRelease)) + } + self.entries.removeValue(forKey: key) + host.close() + Self.log.warning("OpenAI webview prepare failed") + throw error + } + + return OpenAIDashboardWebViewLease( + webView: webView, + log: log, + setPreserveLoadedPageOnRelease: { preserveLoadedPageOnRelease in + releaseState.preserveLoadedPageOnRelease = preserveLoadedPageOnRelease + }, + release: { [weak self, weak entry] in + guard let self, let entry else { return } + self.releaseNewEntry( + entry, + webView: webView, + preserveLoadedPage: releaseState.preserveLoadedPageOnRelease) + }) + } + + func evict(websiteDataStore: WKWebsiteDataStore) { + let key = ObjectIdentifier(websiteDataStore) + guard let entry = self.entries.removeValue(forKey: key) else { return } + entry.clearPreservedPage() + Self.log.debug("OpenAI webview evicted") + entry.host.close() + self.scheduleNextIdlePrune() + } + + func evictAll() { + self.cancelIdlePrune() + let existing = self.entries + self.entries.removeAll() + for (_, entry) in existing { + entry.clearPreservedPage() + entry.host.close() + } + if !existing.isEmpty { + Self.log.debug("OpenAI webview evicted all") + } + } + + func evictIdle() { + let idleEntries = self.entries.filter { _, entry in + !entry.isBusy + } + guard !idleEntries.isEmpty else { return } + + for (key, entry) in idleEntries { + entry.clearPreservedPage() + entry.host.close() + self.entries.removeValue(forKey: key) + } + Self.log.debug("OpenAI idle webviews evicted", metadata: ["count": "\(idleEntries.count)"]) + self.scheduleNextIdlePrune() + } + + private func prepareCachedWebViewForIdle( + _ webView: WKWebView, + host: OffscreenWebViewHost, + preserveLoadedPage: Bool) + { + webView.navigationDelegate = nil + webView.codexNavigationDelegate = nil + if preserveLoadedPage { + host.hide() + return + } + + // Detach the heavyweight ChatGPT SPA as soon as a scrape completes. Keeping the WebView object around + // still helps with immediate reuse, but letting chatgpt.com remain the active document is too expensive. + webView.stopLoading() + webView.evaluateJavaScript(self.idlePageClearScript, completionHandler: nil) + _ = webView.load(URLRequest(url: self.blankURL)) + host.hide() + } + + /// Schedule against the oldest idle entry so later releases cannot postpone its eviction. + private func scheduleNextIdlePrune(now: Date = Date()) { + self.cancelIdlePrune() + + guard let nextExpiry = self.entries.values + .filter({ !$0.isBusy }) + .map({ $0.lastUsedAt.addingTimeInterval(self.idleTimeout) }) + .min() + else { return } + + let generation = self.idlePruneGeneration + let workItem = DispatchWorkItem { [weak self] in + MainActor.assumeIsolated { + guard let self, self.idlePruneGeneration == generation else { return } + self.idlePruneWorkItem = nil + #if DEBUG + self.idlePruneDeadlineForTesting = nil + #endif + let pruneTime = Date() + self.prune(now: pruneTime) + self.scheduleNextIdlePrune(now: pruneTime) + } + } + self.idlePruneWorkItem = workItem + #if DEBUG + self.idlePruneDeadlineForTesting = nextExpiry + #endif + let delay = max(0, nextExpiry.timeIntervalSince(now)) + 0.01 + DispatchQueue.main.asyncAfter(deadline: .now() + delay, execute: workItem) + } + + private func cancelIdlePrune() { + self.idlePruneGeneration &+= 1 + self.idlePruneWorkItem?.cancel() + self.idlePruneWorkItem = nil + #if DEBUG + self.idlePruneDeadlineForTesting = nil + #endif + } + + private func prune(now: Date) { + for entry in self.entries.values where !entry.isBusy && entry.hasExpiredPreservedPage(now: now) { + entry.clearPreservedPage() + self.prepareCachedWebViewForIdle( + entry.webView, + host: entry.host, + preserveLoadedPage: false) + Self.log.debug("OpenAI webview preserved page expired") + } + + let expired = self.entries.filter { _, entry in + !entry.isBusy && now.timeIntervalSince(entry.lastUsedAt) >= self.idleTimeout + } + for (key, entry) in expired { + entry.host.close() + self.entries.removeValue(forKey: key) + Self.log.debug("OpenAI webview pruned") + } + } + + private func makeWebView(websiteDataStore: WKWebsiteDataStore) -> (WKWebView, OffscreenWebViewHost) { + let config = WKWebViewConfiguration() + config.websiteDataStore = websiteDataStore + let userContentController = WKUserContentController() + userContentController.addUserScript(WKUserScript( + source: self.preferredLanguageScript, + injectionTime: .atDocumentStart, + forMainFrameOnly: false)) + config.userContentController = userContentController + if #available(macOS 14.0, *) { + config.preferences.inactiveSchedulingPolicy = .suspend + } + + let webView = WKWebView(frame: .zero, configuration: config) + let host = OffscreenWebViewHost(webView: webView) + return (webView, host) + } + + private func prepareWebView( + _ webView: WKWebView, + usageURL: URL, + timeout: TimeInterval, + canReuseLoadedPage: Bool) async throws + { + #if DEBUG + if usageURL.absoluteString == "about:blank" { + _ = webView.loadHTMLString("", baseURL: nil) + return + } + #endif + + if canReuseLoadedPage, + let currentURL = webView.url?.absoluteString, + OpenAIDashboardFetcher.isUsageRoute(currentURL) + { + if await self.resetReusablePageState(webView) { + return + } + + Self.log.debug("OpenAI preserved page reset failed; reloading usage URL") + } + + try Task.checkCancellation() + let cancellationState = NavigationCancellationState() + try await withTaskCancellationHandler { + try await withCheckedThrowingContinuation { (cont: CheckedContinuation) in + let delegate = NavigationDelegate { result in + cont.resume(with: result) + } + webView.navigationDelegate = delegate + webView.codexNavigationDelegate = delegate + cancellationState.install(webView: webView, delegate: delegate) + delegate.armTimeout(seconds: timeout) + _ = webView.load(OpenAIDashboardFetcher.usageURLRequest(url: usageURL)) + if Task.isCancelled { + cancellationState.cancel() + } + } + } onCancel: { + Task { @MainActor in + cancellationState.cancel() + } + } + } + + private func acquireTemporaryWebView( + websiteDataStore: WKWebsiteDataStore, + usageURL: URL, + log: @escaping (String) -> Void, + deadline: Date) async throws -> OpenAIDashboardWebViewLease + { + let remainingTimeout = try Self.remainingNavigationTimeout(until: deadline) + let (webView, host) = self.makeWebView(websiteDataStore: websiteDataStore) + host.show() + do { + try await self.prepareWebView( + webView, + usageURL: usageURL, + timeout: remainingTimeout, + canReuseLoadedPage: false) + } catch { + host.close() + throw error + } + return OpenAIDashboardWebViewLease( + webView: webView, + log: log, + setPreserveLoadedPageOnRelease: { _ in }, + release: { host.close() }) + } + + private static func isPrepareTimeout(_ error: Error) -> Bool { + let nsError = error as NSError + return nsError.domain == NSURLErrorDomain && nsError.code == NSURLErrorTimedOut + } + + private func updatePreservedPageState(for entry: Entry, preserveLoadedPage: Bool) { + if preserveLoadedPage { + let expiresAt = Date().addingTimeInterval(self.preservedPageHandoffTimeout) + entry.armPreservedPage(until: expiresAt) + if let key = self.entries.first(where: { $0.value === entry })?.key { + self.schedulePreservedPageExpiry(for: key, entry: entry, expiresAt: expiresAt) + } + } else { + entry.clearPreservedPage() + } + } + + private func schedulePreservedPageExpiry( + for key: ObjectIdentifier, + entry: Entry, + expiresAt: Date) + { + let delay = max(0, expiresAt.timeIntervalSinceNow) + let workItem = DispatchWorkItem { [weak self] in + MainActor.assumeIsolated { + self?.expirePreservedPageIfNeeded(for: key, expectedExpiry: expiresAt) + } + } + entry.setPreservedPageExpiryWorkItem(workItem) + DispatchQueue.main.asyncAfter(deadline: .now() + delay, execute: workItem) + } + + private func expirePreservedPageIfNeeded(for key: ObjectIdentifier, expectedExpiry: Date) { + guard let entry = self.entries[key], + !entry.isBusy, + let preservedPageExpiresAt = entry.preservedPageExpiresAt, + preservedPageExpiresAt == expectedExpiry, + preservedPageExpiresAt <= Date() + else { + return + } + + entry.clearPreservedPage() + self.prepareCachedWebViewForIdle( + entry.webView, + host: entry.host, + preserveLoadedPage: false) + Self.log.debug("OpenAI webview preserved page expired") + self.prune(now: Date()) + } + + private func resetReusablePageState(_ webView: WKWebView) async -> Bool { + do { + let any = try await webView.evaluateJavaScript(self.reusablePageResetScript) + return (any as? Bool) ?? true + } catch { + return false + } + } +} + +@MainActor +private final class OffscreenWebViewHost { + private let window: NSWindow + private weak var webView: WKWebView? + + init(webView: WKWebView) { + // WebKit throttles timers/RAF aggressively when a WKWebView is not considered "visible". + // The Codex usage page uses streaming SSR + client hydration; if RAF is throttled, the + // dashboard never becomes part of the visible DOM and `document.body.innerText` stays tiny. + // + // Keep a transparent (mouse-ignoring) window technically "on-screen" while scraping, but + // place it almost entirely off-screen so we never ghost-render dashboard UI over the desktop. + let visibleFrame = NSScreen.main?.visibleFrame ?? NSRect(x: 0, y: 0, width: 900, height: 700) + let frame = OpenAIDashboardFetcher.offscreenHostWindowFrame(for: visibleFrame) + let window = NSWindow( + contentRect: frame, + styleMask: [.borderless], + backing: .buffered, + defer: false) + window.isReleasedWhenClosed = false + window.backgroundColor = .clear + window.isOpaque = false + // Keep it effectively invisible, but non-zero alpha so WebKit treats it as "visible" and doesn't + // stall hydration (we've observed a head-only HTML shell for minutes at alpha=0). + window.alphaValue = OpenAIDashboardFetcher.offscreenHostAlphaValue() + window.hasShadow = false + window.ignoresMouseEvents = true + window.level = .floating + window.collectionBehavior = [.canJoinAllSpaces, .fullScreenAuxiliary] + window.isExcludedFromWindowsMenu = true + window.contentView = webView + + self.window = window + self.webView = webView + } + + func show() { + OpenAIDashboardWebViewCache.log.debug("OpenAI webview show") + self.window.alphaValue = OpenAIDashboardFetcher.offscreenHostAlphaValue() + self.window.orderFrontRegardless() + } + + func hide() { + // Set alpha to 0 so WebKit recognizes the page as inactive and applies + // its scheduling policy (throttle/suspend), reducing CPU when idle. + OpenAIDashboardWebViewCache.log.debug("OpenAI webview hide") + self.window.alphaValue = 0.0 + self.window.orderOut(nil) + } + + func close() { + OpenAIDashboardWebViewCache.log.debug("OpenAI webview close") + WebKitTeardown.scheduleCleanup( + owner: self, + window: self.window, + webView: self.webView, + closeWindow: { [window] in + window.orderOut(nil) + window.close() + }) + } +} + +#endif diff --git a/Sources/CodexBarCore/OpenAIWeb/OpenAIDashboardWebsiteDataStore.swift b/Sources/CodexBarCore/OpenAIWeb/OpenAIDashboardWebsiteDataStore.swift new file mode 100644 index 0000000..a868996 --- /dev/null +++ b/Sources/CodexBarCore/OpenAIWeb/OpenAIDashboardWebsiteDataStore.swift @@ -0,0 +1,118 @@ +#if os(macOS) +import CryptoKit +import Foundation +import WebKit + +/// Per-account persistent `WKWebsiteDataStore` for the OpenAI dashboard scrape. +/// +/// Why: `WKWebsiteDataStore.default()` is a single shared cookie jar. If the user switches Codex accounts, +/// we want to keep multiple signed-in dashboard sessions around (one per email) without clearing cookies. +/// +/// Implementation detail: macOS 14+ supports `WKWebsiteDataStore.dataStore(forIdentifier:)`, which creates +/// persistent isolated stores keyed by an identifier. We derive a stable UUID from the email and optional +/// Codex source scope so distinct profiles with the same email never share a cookie store. +/// +/// Important: We cache the `WKWebsiteDataStore` instances so the same object is returned for the same +/// account email. This ensures `OpenAIDashboardWebViewCache` can use object identity for cache lookups. +@MainActor +public enum OpenAIDashboardWebsiteDataStore { + /// Cached data store instances keyed by normalized email and optional Codex source scope. + /// Using the same instance ensures stable object identity for WebView cache lookups. + private static var cachedStores: [String: WKWebsiteDataStore] = [:] + + public static func store( + forAccountEmail email: String?, + scope: CookieHeaderCache.Scope? = nil) -> WKWebsiteDataStore + { + guard let normalized = normalizeEmail(email) else { return .default() } + let storageKey = self.storageKey(normalizedEmail: normalized, scope: scope) + + // Return cached instance if available to maintain stable object identity + if let cached = cachedStores[storageKey] { + return cached + } + + let id = Self.identifier(forStorageKey: storageKey) + let store = WKWebsiteDataStore(forIdentifier: id) + self.cachedStores[storageKey] = store + return store + } + + /// Clears the persistent cookie store for a single account email. + /// + /// Note: this does *not* impact other accounts, and is safe to use when the stored session is "stuck" + /// or signed in to a different account than expected. + public static func clearStore( + forAccountEmail email: String?, + scope: CookieHeaderCache.Scope? = nil) async + { + // Clear only ChatGPT/OpenAI domain data for the per-account store. + // Avoid deleting the entire persistent store (WebKit requires all WKWebViews using it to be released). + let store = self.store(forAccountEmail: email, scope: scope) + await withCheckedContinuation { cont in + store.fetchDataRecords(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes()) { records in + let filtered = records.filter { record in + let name = record.displayName.lowercased() + return name.contains("chatgpt.com") || name.contains("openai.com") + } + store.removeData(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes(), for: filtered) { + cont.resume() + } + } + } + + // Remove from cache so a fresh instance is created on next access + if let normalized = normalizeEmail(email) { + self.cachedStores.removeValue(forKey: self.storageKey(normalizedEmail: normalized, scope: scope)) + } + } + + #if DEBUG + /// Clear all cached store instances (for test isolation). + public static func clearCacheForTesting() { + self.cachedStores.removeAll() + } + + #endif + + // MARK: - Private + + private static func normalizeEmail(_ email: String?) -> String? { + guard let raw = email?.trimmingCharacters(in: .whitespacesAndNewlines), !raw.isEmpty else { return nil } + return raw.lowercased() + } + + private static func storageKey(normalizedEmail: String, scope: CookieHeaderCache.Scope?) -> String { + guard let scope else { return normalizedEmail } + return "\(normalizedEmail)|\(scope.isolationIdentifier)" + } + + private static func identifier(forStorageKey storageKey: String) -> UUID { + let digest = SHA256.hash(data: Data(storageKey.utf8)) + var bytes = Array(digest.prefix(16)) + + // Make it a well-formed UUID (v4 + RFC4122 variant) while staying deterministic. + bytes[6] = (bytes[6] & 0x0F) | 0x40 + bytes[8] = (bytes[8] & 0x3F) | 0x80 + + let uuidBytes: uuid_t = ( + bytes[0], + bytes[1], + bytes[2], + bytes[3], + bytes[4], + bytes[5], + bytes[6], + bytes[7], + bytes[8], + bytes[9], + bytes[10], + bytes[11], + bytes[12], + bytes[13], + bytes[14], + bytes[15]) + return UUID(uuid: uuidBytes) + } +} +#endif diff --git a/Sources/CodexBarCore/PathEnvironment.swift b/Sources/CodexBarCore/PathEnvironment.swift new file mode 100644 index 0000000..631ac04 --- /dev/null +++ b/Sources/CodexBarCore/PathEnvironment.swift @@ -0,0 +1,1228 @@ +import Foundation +#if canImport(Darwin) +import Darwin +#elseif canImport(Glibc) +import Glibc +#elseif canImport(Musl) +import Musl +#endif +#if os(macOS) +import Security +#endif + +public enum PathPurpose: Hashable, Sendable { + case rpc + case tty + case nodeTooling +} + +public struct PathDebugSnapshot: Equatable, Sendable { + public let codexBinary: String? + public let claudeBinary: String? + public let geminiBinary: String? + public let effectivePATH: String + public let loginShellPATH: String? + + public static let empty = PathDebugSnapshot( + codexBinary: nil, + claudeBinary: nil, + geminiBinary: nil, + effectivePATH: "", + loginShellPATH: nil) + + public init( + codexBinary: String?, + claudeBinary: String?, + geminiBinary: String? = nil, + effectivePATH: String, + loginShellPATH: String?) + { + self.codexBinary = codexBinary + self.claudeBinary = claudeBinary + self.geminiBinary = geminiBinary + self.effectivePATH = effectivePATH + self.loginShellPATH = loginShellPATH + } +} + +public enum BinaryLocator { + /// Test-only override so parallel Gemini suites can point at fake binaries + /// without mutating process-wide `GEMINI_CLI_PATH`. + @TaskLocal public static var geminiBinaryPathOverrideForTesting: String? + + public static func resolveClaudeBinary( + env: [String: String] = ProcessInfo.processInfo.environment, + loginPATH: [String]? = LoginShellPathCache.shared.current, + commandV: (String, String?, TimeInterval, FileManager) -> String? = ShellCommandLocator.commandV, + aliasResolver: (String, String?, TimeInterval, FileManager, String) -> String? = ShellCommandLocator + .resolveAlias, + fileManager: FileManager = .default, + home: String = NSHomeDirectory()) -> String? + { + self.resolveBinary( + name: "claude", + overrideKey: "CLAUDE_CLI_PATH", + env: env, + loginPATH: loginPATH, + commandV: commandV, + aliasResolver: aliasResolver, + wellKnownPaths: self.claudeWellKnownPaths(home: home), + fileManager: fileManager, + home: home) + } + + /// Well-known installation paths for the Claude CLI binary. + /// Covers Anthropic's native installer (`~/.local/bin`), the `claude migrate-installer` + /// self-updating location (`~/.claude/local`), the legacy per-user installer + /// (`~/.claude/bin`), Homebrew, and the macOS Terminal installer (cmux.app). + static func claudeWellKnownPaths(home: String) -> [String] { + [ + "\(home)/.local/bin/claude", + "\(home)/.claude/local/claude", + "\(home)/.claude/bin/claude", + "/opt/homebrew/bin/claude", + "/usr/local/bin/claude", + "/Applications/cmux.app/Contents/Resources/bin/claude", + ] + } + + public static func resolveAntigravityBinary( + env: [String: String] = ProcessInfo.processInfo.environment, + loginPATH: [String]? = LoginShellPathCache.shared.current, + commandV: (String, String?, TimeInterval, FileManager) -> String? = ShellCommandLocator.commandV, + aliasResolver: (String, String?, TimeInterval, FileManager, String) -> String? = ShellCommandLocator + .resolveAlias, + fileManager: FileManager = .default, + home: String = NSHomeDirectory()) -> String? + { + self.resolveBinary( + name: "agy", + overrideKey: "ANTIGRAVITY_CLI_PATH", + env: env, + loginPATH: loginPATH, + commandV: commandV, + aliasResolver: aliasResolver, + wellKnownPaths: [ + "\(home)/.local/bin/agy", + "/opt/homebrew/bin/agy", + "/usr/local/bin/agy", + ], + fileManager: fileManager, + home: home) + } + + public static func resolveCodexBinary( + env: [String: String] = ProcessInfo.processInfo.environment, + loginPATH: [String]? = LoginShellPathCache.shared.current, + commandV: (String, String?, TimeInterval, FileManager) -> String? = ShellCommandLocator.commandV, + aliasResolver: (String, String?, TimeInterval, FileManager, String) -> String? = ShellCommandLocator + .resolveAlias, + launchCandidateFilter: (String, FileManager) -> Bool = CodexLaunchPreflight.isLaunchCandidateAllowed, + fileManager: FileManager = .default, + home: String = NSHomeDirectory()) -> String? + { + self.resolveBinary( + name: "codex", + overrideKey: "CODEX_CLI_PATH", + env: env, + loginPATH: loginPATH, + commandV: commandV, + aliasResolver: aliasResolver, + wellKnownPaths: self.codexWellKnownPaths(home: home), + launchCandidateFilter: launchCandidateFilter, + fileManager: fileManager, + home: home) + } + + /// Well-known installation paths for the signed Codex CLI bundled with current and legacy desktop apps. + /// Keep these after PATH lookups, but use them as a safe fallback when a PATH shim is blocked. + static func codexWellKnownPaths(home: String) -> [String] { + #if os(macOS) + [ + "\(home)/Applications/ChatGPT.app/Contents/Resources/codex", + "\(home)/Applications/Codex.app/Contents/Resources/codex", + "/Applications/ChatGPT.app/Contents/Resources/codex", + "/Applications/Codex.app/Contents/Resources/codex", + ] + #else + [] + #endif + } + + public static func resolveGeminiBinary( + env: [String: String] = ProcessInfo.processInfo.environment, + loginPATH: [String]? = LoginShellPathCache.shared.current, + commandV: (String, String?, TimeInterval, FileManager) -> String? = ShellCommandLocator.commandV, + aliasResolver: (String, String?, TimeInterval, FileManager, String) -> String? = ShellCommandLocator + .resolveAlias, + fileManager: FileManager = .default, + home: String = NSHomeDirectory()) -> String? + { + if let override = self.geminiBinaryPathOverrideForTesting, + fileManager.isExecutableFile(atPath: override) + { + return override + } + return self.resolveBinary( + name: "gemini", + overrideKey: "GEMINI_CLI_PATH", + env: env, + loginPATH: loginPATH, + commandV: commandV, + aliasResolver: aliasResolver, + fileManager: fileManager, + home: home) + } + + public static func resolveGrokBinary( + env: [String: String] = ProcessInfo.processInfo.environment, + loginPATH: [String]? = LoginShellPathCache.shared.current, + commandV: (String, String?, TimeInterval, FileManager) -> String? = ShellCommandLocator.commandV, + aliasResolver: (String, String?, TimeInterval, FileManager, String) -> String? = ShellCommandLocator + .resolveAlias, + fileManager: FileManager = .default, + home: String = NSHomeDirectory()) -> String? + { + self.resolveBinary( + name: "grok", + overrideKey: "GROK_CLI_PATH", + env: env, + loginPATH: loginPATH, + commandV: commandV, + aliasResolver: aliasResolver, + wellKnownPaths: self.grokWellKnownPaths(home: home), + fileManager: fileManager, + home: home) + } + + public static func resolveAmpBinary( + env: [String: String] = ProcessInfo.processInfo.environment, + loginPATH: [String]? = LoginShellPathCache.shared.current, + commandV: (String, String?, TimeInterval, FileManager) -> String? = ShellCommandLocator.commandV, + aliasResolver: (String, String?, TimeInterval, FileManager, String) -> String? = ShellCommandLocator + .resolveAlias, + fileManager: FileManager = .default, + home: String = NSHomeDirectory()) -> String? + { + self.resolveBinary( + name: "amp", + overrideKey: "AMP_CLI_PATH", + env: env, + loginPATH: loginPATH, + commandV: commandV, + aliasResolver: aliasResolver, + wellKnownPaths: self.ampWellKnownPaths(home: home), + fileManager: fileManager, + home: home) + } + + static func ampWellKnownPaths(home: String) -> [String] { + [ + "\(home)/.local/bin/amp", + "\(home)/.amp/bin/amp", + "/opt/homebrew/bin/amp", + "/usr/local/bin/amp", + ] + } + + /// Well-known install locations for the Grok Build CLI binary. + /// Covers the installer's default (`~/.grok/bin/grok`) and the symlinks it sometimes + /// creates into `~/.local/bin` and `/usr/local/bin`. + static func grokWellKnownPaths(home: String) -> [String] { + [ + "\(home)/.grok/bin/grok", + "\(home)/.local/bin/grok", + "/usr/local/bin/grok", + "/opt/homebrew/bin/grok", + ] + } + + public static func resolveAWSBinary( + env: [String: String] = ProcessInfo.processInfo.environment, + loginPATH: [String]? = LoginShellPathCache.shared.current, + commandV: (String, String?, TimeInterval, FileManager) -> String? = ShellCommandLocator.commandV, + aliasResolver: (String, String?, TimeInterval, FileManager, String) -> String? = ShellCommandLocator + .resolveAlias, + fileManager: FileManager = .default, + home: String = NSHomeDirectory()) -> String? + { + self.resolveBinary( + name: "aws", + overrideKey: "AWS_CLI_PATH", + env: env, + loginPATH: loginPATH, + commandV: commandV, + aliasResolver: aliasResolver, + wellKnownPaths: self.awsWellKnownPaths(home: home), + fileManager: fileManager, + home: home) + } + + /// Well-known install locations for the AWS CLI v2 (`aws`). + /// Covers Homebrew (Apple Silicon + Intel) and the per-user pip/uv install path. + static func awsWellKnownPaths(home: String) -> [String] { + [ + "/opt/homebrew/bin/aws", + "/usr/local/bin/aws", + "\(home)/.local/bin/aws", + ] + } + + public static func resolveAuggieBinary( + env: [String: String] = ProcessInfo.processInfo.environment, + loginPATH: [String]? = LoginShellPathCache.shared.current, + commandV: (String, String?, TimeInterval, FileManager) -> String? = ShellCommandLocator.commandV, + aliasResolver: (String, String?, TimeInterval, FileManager, String) -> String? = ShellCommandLocator + .resolveAlias, + fileManager: FileManager = .default, + home: String = NSHomeDirectory()) -> String? + { + self.resolveBinary( + name: "auggie", + overrideKey: "AUGGIE_CLI_PATH", + env: env, + loginPATH: loginPATH, + commandV: commandV, + aliasResolver: aliasResolver, + fileManager: fileManager, + home: home) + } + + // swiftlint:disable function_parameter_count + private static func resolveBinary( + name: String, + overrideKey: String, + env: [String: String], + loginPATH: [String]?, + commandV: (String, String?, TimeInterval, FileManager) -> String?, + aliasResolver: (String, String?, TimeInterval, FileManager, String) -> String?, + wellKnownPaths: [String] = [], + launchCandidateFilter: (String, FileManager) -> Bool = { _, _ in true }, + fileManager: FileManager, + home: String) -> String? + { + // swiftlint:enable function_parameter_count + // 1) Explicit override + if let override = env[overrideKey], fileManager.isExecutableFile(atPath: override) { + return override + } + + // 2) Login-shell PATH (captured once per launch) + if let loginPATH, + let pathHit = self.find( + name, + in: loginPATH, + fileManager: fileManager, + launchCandidateFilter: launchCandidateFilter) + { + return pathHit + } + + // 3) Existing PATH + if let existingPATH = env["PATH"], + let pathHit = self.find( + name, + in: existingPATH.split(separator: ":").map(String.init), + fileManager: fileManager, + launchCandidateFilter: launchCandidateFilter) + { + return pathHit + } + + // 4) Well-known installation paths (e.g. Homebrew, cmux.app bundle, ~/.claude/bin). + // Prefer these before shell probing to avoid running interactive shell init for common installs. + for candidate in wellKnownPaths + where fileManager.isExecutableFile(atPath: candidate) && launchCandidateFilter(candidate, fileManager) + { + return candidate + } + + // 5) Interactive login shell lookup (captures nvm/fnm/mise paths from .zshrc/.bashrc) + if let shellHit = commandV(name, env["SHELL"], 2.0, fileManager), + fileManager.isExecutableFile(atPath: shellHit), + launchCandidateFilter(shellHit, fileManager) + { + return shellHit + } + + // 5b) Alias fallback (login shell); only attempt after all standard lookups fail. + if let aliasHit = aliasResolver(name, env["SHELL"], 2.0, fileManager, home), + fileManager.isExecutableFile(atPath: aliasHit), + launchCandidateFilter(aliasHit, fileManager) + { + return aliasHit + } + + // 6) Minimal fallback + let fallback = ["/usr/bin", "/bin", "/usr/sbin", "/sbin"] + if let pathHit = self.find( + name, + in: fallback, + fileManager: fileManager, + launchCandidateFilter: launchCandidateFilter) + { + return pathHit + } + + return nil + } + + private static func find( + _ binary: String, + in paths: [String], + fileManager: FileManager, + launchCandidateFilter: (String, FileManager) -> Bool = { _, _ in true }) -> String? + { + for path in paths where !path.isEmpty { + let candidate = "\(path.hasSuffix("/") ? String(path.dropLast()) : path)/\(binary)" + if fileManager.isExecutableFile(atPath: candidate), launchCandidateFilter(candidate, fileManager) { + return candidate + } + } + return nil + } +} + +public enum CodexLaunchPreflight { + struct GatekeeperAssessment { + let output: String + let exitStatus: Int32 + } + + public static func isLaunchCandidateAllowed(path: String, fileManager: FileManager = .default) -> Bool { + #if os(macOS) + self.isLaunchCandidateAllowed( + path: path, + fileManager: fileManager, + hasExtendedAttribute: self.hasExtendedAttribute, + spctlAssessment: { self.spctlAssessment(path: $0) }, + appSignatureIsTrusted: self.isExpectedOpenAIAppSignature, + isMachOExecutable: self.isMachOExecutable) + #else + _ = path + _ = fileManager + return true + #endif + } + + #if os(macOS) + // Keep each security boundary injectable so preflight tests never inspect or launch host binaries. + // swiftlint:disable:next function_parameter_count + static func isLaunchCandidateAllowed( + path: String, + fileManager: FileManager, + hasExtendedAttribute: (String, String) -> Bool, + spctlAssessment: (String) -> GatekeeperAssessment?, + appSignatureIsTrusted: (String) -> Bool, + isMachOExecutable: (String) -> Bool) -> Bool + { + let realPath = URL(fileURLWithPath: path).resolvingSymlinksInPath().path + let sourceAppBundlePath = self.containingAppBundlePath(for: path) + let resolvedAppBundlePath = self.containingAppBundlePath(for: realPath) + let appBundlePath: String? + if let sourceAppBundlePath { + let resolvedSourceBundle = URL(fileURLWithPath: sourceAppBundlePath).resolvingSymlinksInPath().path + guard resolvedAppBundlePath == resolvedSourceBundle else { return false } + appBundlePath = resolvedSourceBundle + } else { + appBundlePath = resolvedAppBundlePath + } + let appBundlePaths = [sourceAppBundlePath, appBundlePath].compactMap(\.self) + let pathsToCheck = [path, realPath] + appBundlePaths + self + .nativeCodexExecutableCandidates( + for: realPath, + fileManager: fileManager) + + for candidate in Set(pathsToCheck) where hasExtendedAttribute(candidate, "com.apple.malware") { + return false + } + + let hasQuarantine = Set(pathsToCheck).contains { hasExtendedAttribute($0, "com.apple.quarantine") } + if let appBundlePath { + guard appSignatureIsTrusted(appBundlePath), + let assessment = spctlAssessment(appBundlePath), + assessment.exitStatus == 0, + self.isAcceptedAssessment(assessment.output, path: appBundlePath), + !self.isExplicitlyBlockedAssessment(assessment.output, path: appBundlePath) + else { + return false + } + return true + } + + guard let native = pathsToCheck.first(where: isMachOExecutable) else { + return !hasQuarantine + } + + guard let assessment = spctlAssessment(native) + else { + return !hasQuarantine + } + + return !self.isExplicitlyBlockedAssessment(assessment.output, path: native) + } + + private static func containingAppBundlePath(for path: String) -> String? { + var candidate = URL(fileURLWithPath: path).standardizedFileURL + while candidate.path != "/" { + if candidate.pathExtension.caseInsensitiveCompare("app") == .orderedSame { + return candidate.path + } + let parent = candidate.deletingLastPathComponent() + guard parent.path != candidate.path else { return nil } + candidate = parent + } + return nil + } + + private static func nativeCodexExecutableCandidates(for path: String, fileManager: FileManager) -> [String] { + let url = URL(fileURLWithPath: path) + guard url.lastPathComponent == "codex.js" else { return [] } + + let packageRoot = url.deletingLastPathComponent().deletingLastPathComponent() + return self.npmNativeCodexCandidates(packageRoot: packageRoot) + .map(\.path) + .filter { fileManager.isExecutableFile(atPath: $0) } + } + + private static func npmNativeCodexCandidates(packageRoot: URL) -> [URL] { + guard let target = self.darwinCodexTarget else { return [] } + let optionalPackage = packageRoot + .appendingPathComponent("node_modules") + .appendingPathComponent("@openai") + .appendingPathComponent(target.packageName) + + return [ + optionalPackage, + packageRoot, + ].map { + $0.appendingPathComponent("vendor") + .appendingPathComponent(target.triple) + .appendingPathComponent("codex") + .appendingPathComponent("codex") + } + } + + private static var darwinCodexTarget: (packageName: String, triple: String)? { + #if arch(arm64) + ("codex-darwin-arm64", "aarch64-apple-darwin") + #elseif arch(x86_64) + ("codex-darwin-x64", "x86_64-apple-darwin") + #else + nil + #endif + } + + private static func hasExtendedAttribute(path: String, name: String) -> Bool { + path.withCString { pathPointer in + name.withCString { namePointer in + getxattr(pathPointer, namePointer, nil, 0, 0, 0) >= 0 + } + } + } + + private static func isMachOExecutable(path: String) -> Bool { + guard let handle = try? FileHandle(forReadingFrom: URL(fileURLWithPath: path)) else { return false } + defer { try? handle.close() } + + guard let data = try? handle.read(upToCount: 4), data.count == 4 else { return false } + let bytes = [UInt8](data) + return bytes == [0xFE, 0xED, 0xFA, 0xCE] || + bytes == [0xCE, 0xFA, 0xED, 0xFE] || + bytes == [0xFE, 0xED, 0xFA, 0xCF] || + bytes == [0xCF, 0xFA, 0xED, 0xFE] || + bytes == [0xCA, 0xFE, 0xBA, 0xBE] || + bytes == [0xCA, 0xFE, 0xBA, 0xBF] + } + + private static func spctlAssessment(path: String, timeout: TimeInterval = 2.0) -> GatekeeperAssessment? { + let spctlPath = "/usr/sbin/spctl" + guard FileManager.default.isExecutableFile(atPath: spctlPath) else { return nil } + + let process = Process() + process.executableURL = URL(fileURLWithPath: spctlPath) + process.arguments = ["--assess", "--type", "execute", "--verbose=4", path] + + let output = Pipe() + process.standardOutput = output + process.standardError = output + + let finished = DispatchSemaphore(value: 0) + process.terminationHandler = { _ in finished.signal() } + + do { + try process.run() + } catch { + return nil + } + + if finished.wait(timeout: .now() + timeout) != .success { + process.terminate() + return nil + } + + let data = output.fileHandleForReading.readDataToEndOfFile() + guard let text = String(data: data, encoding: .utf8) else { return nil } + return GatekeeperAssessment(output: text, exitStatus: process.terminationStatus) + } + + private static func isExpectedOpenAIAppSignature(path: String) -> Bool { + let requirementText = + "identifier \"com.openai.codex\" and anchor apple generic " + + "and certificate leaf[subject.OU] = \"2DC432GLL2\"" + var staticCode: SecStaticCode? + guard SecStaticCodeCreateWithPath( + URL(fileURLWithPath: path) as CFURL, + SecCSFlags(), + &staticCode) == errSecSuccess, + let staticCode + else { + return false + } + + var requirement: SecRequirement? + guard SecRequirementCreateWithString( + requirementText as CFString, + SecCSFlags(), + &requirement) == errSecSuccess + else { + return false + } + + // Pin the publisher and bundle identity here; the Gatekeeper assessment below performs full bundle validation. + let validationFlags = SecCSFlags(rawValue: kSecCSBasicValidateOnly) + return SecStaticCodeCheckValidity(staticCode, validationFlags, requirement) == errSecSuccess + } + + private static func isAcceptedAssessment(_ assessment: String, path: String) -> Bool { + self.assessmentDiagnosticText(assessment, path: path) + .split(whereSeparator: \.isNewline) + .first? + .trimmingCharacters(in: .whitespacesAndNewlines) + .localizedCaseInsensitiveCompare("accepted") == .orderedSame + } + + private static func isExplicitlyBlockedAssessment(_ assessment: String, path: String) -> Bool { + let lower = self.assessmentDiagnosticText(assessment, path: path).lowercased() + if lower.contains("denied") || + lower.contains("cssmerr_tp_cert_revoked") || + lower.contains("revoked") || + lower.contains("malware") || + lower.contains("quarantine") + { + return true + } + if lower.contains("rejected") { + return !lower.contains("code is valid but does not seem to be an app") + } + return false + } + + private static func assessmentDiagnosticText(_ assessment: String, path: String) -> String { + assessment + .split(whereSeparator: \.isNewline) + .enumerated() + .compactMap { offset, line -> String? in + var text = line.trimmingCharacters(in: .whitespacesAndNewlines) + if offset == 0, text.hasPrefix("\(path):") { + text = String(text.dropFirst(path.count + 1)) + .trimmingCharacters(in: .whitespacesAndNewlines) + } + let lower = text.lowercased() + guard !lower.hasPrefix("source="), !lower.hasPrefix("origin=") else { + return nil + } + return text + } + .joined(separator: "\n") + } + #endif +} + +public enum ShellCommandLocator { + #if canImport(Darwin) + private static let shellSpawnFlags = Int16(POSIX_SPAWN_SETSID) + #else + private static let shellSpawnFlags: Int16 = 0x80 // glibc/musl POSIX_SPAWN_SETSID. + #endif + + static func test_runShellCommand( + shell: String, + arguments: [String], + timeout: TimeInterval) -> Data? + { + self.runShellCommand(shell: shell, arguments: arguments, timeout: timeout) + } + + static var test_shellSpawnFlags: Int16 { + self.shellSpawnFlags + } + + public static func commandV( + _ tool: String, + _ shell: String?, + _ timeout: TimeInterval, + _ fileManager: FileManager) -> String? + { + let text = self.runShellCapture(shell, timeout, "command -v \(tool)")? + .trimmingCharacters(in: .whitespacesAndNewlines) + guard let text, !text.isEmpty else { return nil } + + let lines = text.split(separator: "\n").map { $0.trimmingCharacters(in: .whitespacesAndNewlines) } + for line in lines.reversed() where line.hasPrefix("/") { + let path = line + if fileManager.isExecutableFile(atPath: path) { + return path + } + } + + return nil + } + + public static func resolveAlias( + _ tool: String, + _ shell: String?, + _ timeout: TimeInterval, + _ fileManager: FileManager, + _ home: String) -> String? + { + let command = "alias \(tool) 2>/dev/null; type -a \(tool) 2>/dev/null" + guard let text = self.runShellCapture(shell, timeout, command) else { return nil } + let lines = text.split(separator: "\n").map { $0.trimmingCharacters(in: .whitespacesAndNewlines) } + + if let aliasPath = self.parseAliasPath(lines, tool: tool, home: home, fileManager: fileManager) { + return aliasPath + } + + for line in lines { + if let path = self.extractPathCandidate(line: line, tool: tool, home: home), + fileManager.isExecutableFile(atPath: path) + { + return path + } + } + + return nil + } + + /// Thread-safe buffer for collecting pipe output from a readability handler. + private final class CapturedData: @unchecked Sendable { + private let lock = NSLock() + private var data = Data() + + func append(_ other: Data) { + self.lock.lock() + self.data.append(other) + self.lock.unlock() + } + + func drain() -> Data { + self.lock.lock() + let result = self.data + self.lock.unlock() + return result + } + } + + /// Idempotent one-shot flag — `fire()` returns true exactly once. + /// Used to make `DispatchGroup.leave()` safe to attempt from multiple paths. + private final class OnceFlag: @unchecked Sendable { + private let lock = NSLock() + private var fired = false + + func fire() -> Bool { + self.lock.lock() + defer { self.lock.unlock() } + if self.fired { + return false + } + self.fired = true + return true + } + } + + // swiftlint:disable cyclomatic_complexity function_body_length + /// Runs a shell command, draining both stdout and stderr concurrently so that + /// verbose shell init scripts (oh-my-zsh, nvm, pyenv, etc.) cannot deadlock on + /// a full pipe buffer. The child is launched via `posix_spawn` with + /// `POSIX_SPAWN_SETSID` so it cannot take ownership of the caller's controlling + /// terminal. The new session also makes the child its own process-group leader + /// before `exec`, which guarantees that subsequent `kill(-pgid, ...)` calls reach + /// background helpers spawned by shell init, both after timeout and normal exit. + fileprivate static func runShellCommand( + shell: String, + arguments: [String], + timeout: TimeInterval) -> Data? + { + // Pipes for stdout/stderr. stdin is redirected from /dev/null in the child + // via posix_spawn_file_actions_addopen below. + var stdoutFds: (read: Int32, write: Int32) = (-1, -1) + var stderrFds: (read: Int32, write: Int32) = (-1, -1) + guard withUnsafeMutablePointer(to: &stdoutFds, { + $0.withMemoryRebound(to: Int32.self, capacity: 2) { pipe($0) == 0 } + }) else { return nil } + guard withUnsafeMutablePointer(to: &stderrFds, { + $0.withMemoryRebound(to: Int32.self, capacity: 2) { pipe($0) == 0 } + }) else { + close(stdoutFds.read); close(stdoutFds.write) + return nil + } + + // Build file actions: redirect stdin from /dev/null, dup pipe write ends to + // fds 1 and 2, and close every pipe fd in the child. The init pattern + // differs between platforms because the typedef is an opaque pointer on + // Darwin and a struct on Linux C modules. + #if canImport(Darwin) + var fileActions: posix_spawn_file_actions_t? + #else + var fileActions = posix_spawn_file_actions_t() + #endif + guard posix_spawn_file_actions_init(&fileActions) == 0 else { + close(stdoutFds.read); close(stdoutFds.write) + close(stderrFds.read); close(stderrFds.write) + return nil + } + defer { posix_spawn_file_actions_destroy(&fileActions) } + posix_spawn_file_actions_addopen(&fileActions, 0, "/dev/null", O_RDONLY, 0) + posix_spawn_file_actions_adddup2(&fileActions, stdoutFds.write, 1) + posix_spawn_file_actions_adddup2(&fileActions, stderrFds.write, 2) + posix_spawn_file_actions_addclose(&fileActions, stdoutFds.read) + posix_spawn_file_actions_addclose(&fileActions, stdoutFds.write) + posix_spawn_file_actions_addclose(&fileActions, stderrFds.read) + posix_spawn_file_actions_addclose(&fileActions, stderrFds.write) + + // Build attributes: detach the child into a new session before exec. This + // prevents interactive shell startup from changing the caller's foreground + // process group while retaining a stable process group for cleanup. + #if canImport(Darwin) + var attr: posix_spawnattr_t? + #else + var attr = posix_spawnattr_t() + #endif + guard posix_spawnattr_init(&attr) == 0 else { + close(stdoutFds.read); close(stdoutFds.write) + close(stderrFds.read); close(stderrFds.write) + return nil + } + defer { posix_spawnattr_destroy(&attr) } + guard posix_spawnattr_setflags(&attr, self.shellSpawnFlags) == 0 else { + close(stdoutFds.read); close(stdoutFds.write) + close(stderrFds.read); close(stderrFds.write) + return nil + } + + // Build argv (argv[0] is conventionally the executable path). + var cArgs: [UnsafeMutablePointer?] = [] + cArgs.append(strdup(shell)) + for arg in arguments { + cArgs.append(strdup(arg)) + } + cArgs.append(nil) + defer { + for p in cArgs { + if let p { + free(p) + } + } + } + + // Inherit the parent environment. Build a NULL-terminated `KEY=VALUE` + // array since `extern char **environ` isn't directly visible from Swift. + var cEnv: [UnsafeMutablePointer?] = [] + for (key, value) in ProcessInfo.processInfo.environment { + cEnv.append(strdup("\(key)=\(value)")) + } + cEnv.append(nil) + defer { + for p in cEnv { + if let p { + free(p) + } + } + } + + var pid: pid_t = 0 + let spawnResult = shell.withCString { execPath in + posix_spawn(&pid, execPath, &fileActions, &attr, cArgs, cEnv) + } + + // Close the write ends in the parent so EOF will arrive on the read ends + // once every descendant in the process group also closes them. + close(stdoutFds.write) + close(stderrFds.write) + + guard spawnResult == 0 else { + close(stdoutFds.read); close(stderrFds.read) + return nil + } + + // POSIX_SPAWN_SETSID guarantees the child's session ID and pgid equal its pid. + let pgid: pid_t = pid + + // Track EOF on each pipe so we can wait for full drain instead of sleeping. + // The readability handler fires with empty data when every writer end is + // closed (i.e. the child *and* any inheriting background helpers are gone). + let drainGroup = DispatchGroup() + drainGroup.enter() + drainGroup.enter() + let stdoutDone = OnceFlag() + let stderrDone = OnceFlag() + + let stdoutCollector = CapturedData() + let stdoutHandle = FileHandle(fileDescriptor: stdoutFds.read, closeOnDealloc: true) + stdoutHandle.readabilityHandler = { handle in + let data = handle.availableData + if data.isEmpty { + handle.readabilityHandler = nil + if stdoutDone.fire() { + drainGroup.leave() + } + } else { + stdoutCollector.append(data) + } + } + + let stderrHandle = FileHandle(fileDescriptor: stderrFds.read, closeOnDealloc: true) + stderrHandle.readabilityHandler = { handle in + let data = handle.availableData + if data.isEmpty { + handle.readabilityHandler = nil + if stderrDone.fire() { + drainGroup.leave() + } + } + } + + // Reap the child on a background queue and signal a semaphore on exit. + let exitSemaphore = DispatchSemaphore(value: 0) + let waitPid = pid + DispatchQueue.global(qos: .userInitiated).async { + var status: Int32 = 0 + while waitpid(waitPid, &status, 0) == -1, errno == EINTR { + // retry + } + exitSemaphore.signal() + } + + let finishedInTime = exitSemaphore.wait(timeout: .now() + timeout) == .success + + if !finishedInTime { + kill(-pgid, SIGTERM) + kill(pid, SIGTERM) + if exitSemaphore.wait(timeout: .now() + 0.4) != .success { + kill(-pgid, SIGKILL) + kill(pid, SIGKILL) + _ = exitSemaphore.wait(timeout: .now() + 1.0) + } + stdoutHandle.readabilityHandler = nil + stderrHandle.readabilityHandler = nil + if stdoutDone.fire() { + drainGroup.leave() + } + if stderrDone.fire() { + drainGroup.leave() + } + return nil + } + + // Normal completion — clean up any background children spawned by shell init. + // Without this, helpers that inherited stdout/stderr keep the pipe write ends + // open and we never see EOF on the read ends. + kill(-pgid, SIGTERM) + + // Wait for both pipes to deliver EOF so no buffered bytes are lost. + // Bounded so a stuck handler can't hang the caller indefinitely. + if drainGroup.wait(timeout: .now() + 0.4) != .success { + kill(-pgid, SIGKILL) + } + if drainGroup.wait(timeout: .now() + 0.6) != .success { + stdoutHandle.readabilityHandler = nil + stderrHandle.readabilityHandler = nil + if stdoutDone.fire() { + drainGroup.leave() + } + if stderrDone.fire() { + drainGroup.leave() + } + } + return stdoutCollector.drain() + } + + // swiftlint:enable cyclomatic_complexity function_body_length + + private static func runShellCapture(_ shell: String?, _ timeout: TimeInterval, _ command: String) -> String? { + let shellPath = (shell?.isEmpty == false) ? shell! : "/bin/zsh" + let isCI = ["1", "true"].contains(ProcessInfo.processInfo.environment["CI"]?.lowercased()) + // Interactive login shell to pick up PATH mutations from shell init (nvm/fnm/mise). + // CI runners can have shell init hooks that emit missing CLI errors; avoid them in CI. + let args = isCI ? ["-c", command] : ["-l", "-i", "-c", command] + guard let data = runShellCommand(shell: shellPath, arguments: args, timeout: timeout) else { + return nil + } + return String(data: data, encoding: .utf8) + } + + private static func parseAliasPath( + _ lines: [String], + tool: String, + home: String, + fileManager: FileManager) -> String? + { + for line in lines { + if line.hasPrefix("alias \(tool)=") { + let value = line.replacingOccurrences(of: "alias \(tool)=", with: "") + if let path = self.extractAliasExpansion(value, home: home), + fileManager.isExecutableFile(atPath: path) + { + return path + } + } + if line.lowercased().contains("aliased to") { + if let range = line.range(of: "aliased to") { + let value = line[range.upperBound...].trimmingCharacters(in: .whitespacesAndNewlines) + if let path = self.extractAliasExpansion(String(value), home: home), + fileManager.isExecutableFile(atPath: path) + { + return path + } + } + } + } + return nil + } + + private static func extractAliasExpansion(_ raw: String, home: String) -> String? { + let trimmed = raw.trimmingCharacters(in: CharacterSet(charactersIn: " \t\"'`")) + guard !trimmed.isEmpty else { return nil } + let parts = trimmed.split(separator: " ").map(String.init) + guard let first = parts.first else { return nil } + return self.expandPath(first, home: home) + } + + private static func extractPathCandidate(line: String, tool: String, home: String) -> String? { + let tokens = line.split(whereSeparator: { $0 == " " || $0 == "\t" }).map(String.init) + for token in tokens { + let candidate = self.expandPath(token, home: home) + if candidate.hasPrefix("/"), + URL(fileURLWithPath: candidate).lastPathComponent == tool + { + return candidate + } + } + return nil + } + + private static func expandPath(_ raw: String, home: String) -> String { + if raw == "~" { + return home + } + if raw.hasPrefix("~/") { + return home + String(raw.dropFirst()) + } + return raw + } +} + +public enum PathBuilder { + public static func effectivePATH( + purposes _: Set, + env: [String: String] = ProcessInfo.processInfo.environment, + loginPATH: [String]? = LoginShellPathCache.shared.current, + home _: String = NSHomeDirectory()) -> String + { + var parts: [String] = [] + + if let loginPATH, !loginPATH.isEmpty { + parts.append(contentsOf: loginPATH) + } + + if let existing = env["PATH"], !existing.isEmpty { + parts.append(contentsOf: existing.split(separator: ":").map(String.init)) + } + + if parts.isEmpty { + parts.append(contentsOf: ["/usr/bin", "/bin", "/usr/sbin", "/sbin"]) + } + + var seen = Set() + let deduped = parts.compactMap { part -> String? in + guard !part.isEmpty else { return nil } + if seen.insert(part).inserted { + return part + } + return nil + } + + return deduped.joined(separator: ":") + } + + public static func debugSnapshot( + purposes: Set, + env: [String: String] = ProcessInfo.processInfo.environment, + home: String = NSHomeDirectory()) -> PathDebugSnapshot + { + let login = LoginShellPathCache.shared.current + let effective = self.effectivePATH( + purposes: purposes, + env: env, + loginPATH: login, + home: home) + let codex = BinaryLocator.resolveCodexBinary(env: env, loginPATH: login, home: home) + let claude = BinaryLocator.resolveClaudeBinary(env: env, loginPATH: login, home: home) + let gemini = BinaryLocator.resolveGeminiBinary(env: env, loginPATH: login, home: home) + let loginString = login?.joined(separator: ":") + return PathDebugSnapshot( + codexBinary: codex, + claudeBinary: claude, + geminiBinary: gemini, + effectivePATH: effective, + loginShellPATH: loginString) + } + + public static func debugSnapshotAsync( + purposes: Set, + env: [String: String] = ProcessInfo.processInfo.environment, + home: String = NSHomeDirectory()) async -> PathDebugSnapshot + { + await Task.detached(priority: .userInitiated) { + self.debugSnapshot(purposes: purposes, env: env, home: home) + }.value + } +} + +enum LoginShellPathCapturer { + static let defaultTimeout: TimeInterval = 6.0 + + static func capture( + shell: String? = ProcessInfo.processInfo.environment["SHELL"], + timeout: TimeInterval = Self.defaultTimeout) -> [String]? + { + let shellPath = (shell?.isEmpty == false) ? shell! : "/bin/zsh" + let isCI = ["1", "true"].contains(ProcessInfo.processInfo.environment["CI"]?.lowercased()) + let marker = "__CODEXBAR_PATH__" + // Skip interactive login shells in CI to avoid noisy init hooks. + let args = isCI + ? ["-c", "printf '\(marker)%s\(marker)' \"$PATH\""] + : ["-l", "-i", "-c", "printf '\(marker)%s\(marker)' \"$PATH\""] + guard let data = ShellCommandLocator.runShellCommand( + shell: shellPath, + arguments: args, + timeout: timeout), + let raw = String(data: data, encoding: .utf8), + !raw.isEmpty + else { return nil } + + let trimmed = raw.trimmingCharacters(in: .whitespacesAndNewlines) + let extracted = if let start = trimmed.range(of: marker), + let end = trimmed.range(of: marker, options: .backwards), + start.upperBound <= end.lowerBound + { + String(trimmed[start.upperBound.. [String]? + private var captured: [String]? + private var isCapturing = false + private var callbacks: [([String]?) -> Void] = [] + + init(capture: @escaping @Sendable (String?, TimeInterval) -> [String]? = LoginShellPathCapturer.capture) { + self.capture = capture + } + + public var current: [String]? { + self.lock.lock() + let value = self.captured + self.lock.unlock() + return value + } + + public func captureOnce( + shell: String? = ProcessInfo.processInfo.environment["SHELL"], + timeout: TimeInterval = 6.0, + onFinish: (([String]?) -> Void)? = nil) + { + self.lock.lock() + if let captured { + self.lock.unlock() + onFinish?(captured) + return + } + + if let onFinish { + self.callbacks.append(onFinish) + } + + if self.isCapturing { + self.lock.unlock() + return + } + + self.isCapturing = true + self.lock.unlock() + + let capture = self.capture + DispatchQueue.global(qos: .utility).async { [weak self] in + let result = capture(shell, timeout) + guard let self else { return } + + self.lock.lock() + self.captured = result + self.isCapturing = false + let callbacks = self.callbacks + self.callbacks.removeAll() + self.lock.unlock() + + callbacks.forEach { $0(result) } + } + } + + public func currentOrCapture( + shell: String? = ProcessInfo.processInfo.environment["SHELL"], + timeout: TimeInterval = 6.0) -> [String]? + { + self.lock.lock() + if let captured { + self.lock.unlock() + return captured + } + + if self.isCapturing { + let semaphore = DispatchSemaphore(value: 0) + var callbackResult: [String]? + self.callbacks.append { result in + callbackResult = result + semaphore.signal() + } + self.lock.unlock() + let deadline = DispatchTime.now() + timeout + _ = semaphore.wait(timeout: deadline) + return callbackResult ?? self.current + } + + self.isCapturing = true + self.lock.unlock() + + let result = self.capture(shell, timeout) + self.lock.lock() + self.captured = result + self.isCapturing = false + let callbacks = self.callbacks + self.callbacks.removeAll() + self.lock.unlock() + + callbacks.forEach { $0(result) } + return result + } +} diff --git a/Sources/CodexBarCore/PiSessionCostCache.swift b/Sources/CodexBarCore/PiSessionCostCache.swift new file mode 100644 index 0000000..355be9c --- /dev/null +++ b/Sources/CodexBarCore/PiSessionCostCache.swift @@ -0,0 +1,97 @@ +import Foundation + +enum PiSessionCostCacheIO { + /// Artifact schema version. Pricing changes are tracked separately by `pricingKey`. + private static let artifactVersion = 5 + + private static func defaultCacheRoot() -> URL { + let root = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first! + return root.appendingPathComponent("CodexBar", isDirectory: true) + } + + static func cacheFileURL(cacheRoot: URL? = nil) -> URL { + let root = cacheRoot ?? self.defaultCacheRoot() + return root + .appendingPathComponent("cost-usage", isDirectory: true) + .appendingPathComponent("pi-sessions-v\(Self.artifactVersion).json", isDirectory: false) + } + + static func load(cacheRoot: URL? = nil) -> PiSessionCostCache { + let url = self.cacheFileURL(cacheRoot: cacheRoot) + guard let data = try? Data(contentsOf: url), + let decoded = try? JSONDecoder().decode(PiSessionCostCache.self, from: data), + decoded.version == Self.artifactVersion + else { + return PiSessionCostCache(version: Self.artifactVersion) + } + return decoded + } + + static func save(cache: PiSessionCostCache, cacheRoot: URL? = nil) { + let url = self.cacheFileURL(cacheRoot: cacheRoot) + let dir = url.deletingLastPathComponent() + try? FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true) + + let tmp = dir.appendingPathComponent(".tmp-\(UUID().uuidString).json", isDirectory: false) + let data = (try? JSONEncoder().encode(cache)) ?? Data() + do { + try data.write(to: tmp, options: [.atomic]) + if FileManager.default.fileExists(atPath: url.path) { + _ = try FileManager.default.replaceItemAt(url, withItemAt: tmp) + } else { + try FileManager.default.moveItem(at: tmp, to: url) + } + } catch { + try? FileManager.default.removeItem(at: tmp) + } + } +} + +struct PiSessionCostCache: Codable { + var version: Int + var lastScanUnixMs: Int64 = 0 + var scanSinceKey: String? + var scanUntilKey: String? + var pricingKey: String? + var daysByProvider: [String: [String: [String: PiPackedUsage]]] = [:] + var files: [String: PiSessionFileUsage] = [:] + + init(version: Int = 5) { + self.version = version + } +} + +struct PiSessionFileUsage: Codable { + var mtimeUnixMs: Int64 + var size: Int64 + var parsedBytes: Int64 + var lastModelContext: PiModelContext? + var contributions: [String: [String: [String: PiPackedUsage]]] +} + +struct PiModelContext: Codable, Equatable { + var providerRawValue: String + var modelName: String +} + +struct PiPackedUsage: Codable, Equatable { + var inputTokens: Int = 0 + var cacheReadTokens: Int = 0 + var cacheWriteTokens: Int = 0 + var outputTokens: Int = 0 + var totalTokens: Int = 0 + var costNanos: Int64 = 0 + var costSampleCount: Int = 0 + var usageSampleCount: Int? + + var isZero: Bool { + self.inputTokens == 0 + && self.cacheReadTokens == 0 + && self.cacheWriteTokens == 0 + && self.outputTokens == 0 + && self.totalTokens == 0 + && self.costNanos == 0 + && self.costSampleCount == 0 + && (self.usageSampleCount ?? 0) == 0 + } +} diff --git a/Sources/CodexBarCore/PiSessionCostScanner.swift b/Sources/CodexBarCore/PiSessionCostScanner.swift new file mode 100644 index 0000000..27b3568 --- /dev/null +++ b/Sources/CodexBarCore/PiSessionCostScanner.swift @@ -0,0 +1,943 @@ +import Foundation + +private final class PiSessionISO8601FormatterBox: @unchecked Sendable { + let lock = NSLock() + let withFractional: ISO8601DateFormatter = { + let formatter = ISO8601DateFormatter() + formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds] + return formatter + }() + + let plain: ISO8601DateFormatter = { + let formatter = ISO8601DateFormatter() + formatter.formatOptions = [.withInternetDateTime] + return formatter + }() +} + +enum PiSessionCostScanner { + struct Options { + var piSessionsRoot: URL? + var cacheRoot: URL? + var refreshMinIntervalSeconds: TimeInterval = 60 + var forceRescan: Bool = false + + init( + piSessionsRoot: URL? = nil, + cacheRoot: URL? = nil, + refreshMinIntervalSeconds: TimeInterval = 60, + forceRescan: Bool = false) + { + self.piSessionsRoot = piSessionsRoot + self.cacheRoot = cacheRoot + self.refreshMinIntervalSeconds = refreshMinIntervalSeconds + self.forceRescan = forceRescan + } + } + + private struct ParseResult { + let contributions: [String: [String: [String: PiPackedUsage]]] + let parsedBytes: Int64 + let lastModelContext: PiModelContext? + } + + private struct AssistantIdentity { + let provider: UsageProvider + let modelName: String + } + + private struct ModelsDevPricingContext { + let catalog: ModelsDevCatalog? + let cacheRoot: URL? + let pricingKey: String + } + + private struct ScanContext { + let range: CostUsageScanner.CostUsageDayRange + let forceRescan: Bool + let pricingContext: ModelsDevPricingContext + let checkCancellation: CostUsageScanner.CancellationCheck? + } + + private static let costScale = 1_000_000_000.0 + /// Bump for Pi-only cost formula changes not represented by the parser or pricing fingerprints. + private static let costFormulaVersion = 1 + private static let maxLineBytes = 16 * 1024 * 1024 + private static let maxSafeRoundedInt = Double(Int.max) - 1 + private static let sessionStartFilenameRegex = try? NSRegularExpression( + pattern: "^(\\d{4}-\\d{2}-\\d{2})T(\\d{2})-(\\d{2})-(\\d{2})-(\\d{3})Z_") + private static let isoFormatterBox = PiSessionISO8601FormatterBox() + + static func loadDailyReport( + provider: UsageProvider, + since: Date, + until: Date, + now: Date = Date(), + options: Options = Options()) -> CostUsageDailyReport + { + ( + try? self.loadDailyReportCancellable( + provider: provider, + since: since, + until: until, + now: now, + options: options, + checkCancellation: nil)) ?? CostUsageDailyReport(data: [], summary: nil) + } + + static func loadDailyReportCancellable( + provider: UsageProvider, + since: Date, + until: Date, + now: Date = Date(), + options: Options = Options(), + checkCancellation: CostUsageScanner.CancellationCheck?) throws -> CostUsageDailyReport + { + guard provider == .codex || provider == .claude else { + return CostUsageDailyReport(data: [], summary: nil) + } + + let range = CostUsageScanner.CostUsageDayRange(since: since, until: until) + var cache = PiSessionCostCacheIO.load(cacheRoot: options.cacheRoot) + let nowMs = Int64(now.timeIntervalSince1970 * 1000) + let refreshMs = Int64(max(0, options.refreshMinIntervalSeconds) * 1000) + let pricingContext = self.pricingContext(now: now, cacheRoot: options.cacheRoot) + let windowExpanded = self.requestedWindowExpandsCache(range: range, cache: cache) + let pricingChanged = cache.pricingKey != pricingContext.pricingKey + let shouldRefresh = options.forceRescan + || windowExpanded + || pricingChanged + || refreshMs == 0 + || cache.lastScanUnixMs == 0 + || nowMs - cache.lastScanUnixMs > refreshMs + + if shouldRefresh { + try checkCancellation?() + let root = self.defaultPiSessionsRoot(options: options) + let startCutoff = self.dateFromDayKey(range.scanSinceKey) ?? since + let files = self.listPiSessionFiles(root: root, startCutoffLocal: startCutoff) + let filePathsInScan = Set(files.map(\.path)) + + for fileURL in files { + try self.scanPiSessionFile( + fileURL: fileURL, + cache: &cache, + context: ScanContext( + range: range, + forceRescan: options.forceRescan || windowExpanded || pricingChanged, + pricingContext: pricingContext, + checkCancellation: checkCancellation)) + } + try checkCancellation?() + + for key in cache.files.keys where !filePathsInScan.contains(key) { + if let old = cache.files[key] { + self.applyContributions( + daysByProvider: &cache.daysByProvider, + contributions: old.contributions, + sign: -1) + } + cache.files.removeValue(forKey: key) + } + + cache.scanSinceKey = range.scanSinceKey + cache.scanUntilKey = range.scanUntilKey + cache.pricingKey = pricingContext.pricingKey + cache.lastScanUnixMs = nowMs + try checkCancellation?() + PiSessionCostCacheIO.save(cache: cache, cacheRoot: options.cacheRoot) + } + + return self.buildReport( + provider: provider, + cache: cache, + range: range, + pricingContext: pricingContext) + } + + struct CachedDailyReportResult { + let report: CostUsageDailyReport + let lastScanAt: Date? + } + + static func loadCachedDailyReport( + provider: UsageProvider, + since: Date, + until: Date, + now: Date = Date(), + cacheRoot: URL? = nil) -> CostUsageDailyReport? + { + self.loadCachedDailyReportResult( + provider: provider, + since: since, + until: until, + now: now, + cacheRoot: cacheRoot)?.report + } + + static func loadCachedDailyReportResult( + provider: UsageProvider, + since: Date, + until: Date, + now: Date = Date(), + cacheRoot: URL? = nil) -> CachedDailyReportResult? + { + guard provider == .codex || provider == .claude else { return nil } + + let range = CostUsageScanner.CostUsageDayRange(since: since, until: until) + let cache = PiSessionCostCacheIO.load(cacheRoot: cacheRoot) + guard !cache.daysByProvider.isEmpty else { return nil } + guard !self.requestedWindowExpandsCache(range: range, cache: cache) else { return nil } + + let pricingContext = self.pricingContext(now: now, cacheRoot: cacheRoot) + guard cache.pricingKey == pricingContext.pricingKey else { return nil } + let report = self.buildReport( + provider: provider, + cache: cache, + range: range, + pricingContext: pricingContext) + guard !report.data.isEmpty else { return nil } + let lastScanAt = cache.lastScanUnixMs > 0 + ? Date(timeIntervalSince1970: TimeInterval(cache.lastScanUnixMs) / 1000) + : nil + return CachedDailyReportResult(report: report, lastScanAt: lastScanAt) + } + + private static func pricingContext(now: Date, cacheRoot: URL?) -> ModelsDevPricingContext { + let modelsDevArtifact = ModelsDevCache.load(now: now, cacheRoot: cacheRoot).artifact + return ModelsDevPricingContext( + catalog: modelsDevArtifact?.catalog, + cacheRoot: cacheRoot, + pricingKey: CostUsagePricingKey.codex( + modelsDevArtifact: modelsDevArtifact, + formulaVersion: Self.costFormulaVersion, + parserHash: CodexParserHash.value, + modelsDevProviderIDs: ["anthropic", "openai"])) + } + + private static func requestedWindowExpandsCache( + range: CostUsageScanner.CostUsageDayRange, + cache: PiSessionCostCache) -> Bool + { + guard let cachedSince = cache.scanSinceKey, + let cachedUntil = cache.scanUntilKey + else { + return true + } + + if range.scanSinceKey < cachedSince { + return true + } + if range.scanUntilKey > cachedUntil { + return true + } + return false + } + + private static func defaultPiSessionsRoot(options: Options) -> URL { + if let override = options.piSessionsRoot { return override } + return FileManager.default.homeDirectoryForCurrentUser + .appendingPathComponent(".pi", isDirectory: true) + .appendingPathComponent("agent", isDirectory: true) + .appendingPathComponent("sessions", isDirectory: true) + } + + private static func listPiSessionFiles(root: URL, startCutoffLocal: Date) -> [URL] { + guard FileManager.default.fileExists(atPath: root.path) else { return [] } + + let keys: Set = [.isRegularFileKey, .contentModificationDateKey] + guard let enumerator = FileManager.default.enumerator( + at: root, + includingPropertiesForKeys: Array(keys), + options: [.skipsHiddenFiles]) + else { + return [] + } + + var output: [URL] = [] + while let item = enumerator.nextObject() as? URL { + guard item.pathExtension.lowercased() == "jsonl" else { continue } + let values = try? item.resourceValues(forKeys: keys) + guard values?.isRegularFile == true else { continue } + + let startedAt = self.parseSessionStartFromFilename(item.lastPathComponent) + let modifiedAt = values?.contentModificationDate + if self + .shouldIncludeFile(startedAt: startedAt, modifiedAt: modifiedAt, startCutoffLocal: startCutoffLocal) + { + output.append(item) + } + } + + return output.sorted(by: { $0.path < $1.path }) + } + + private static func shouldIncludeFile( + startedAt: Date?, + modifiedAt: Date?, + startCutoffLocal: Date) -> Bool + { + if let modifiedAt, self.localMidnight(modifiedAt) >= startCutoffLocal { + return true + } + if let startedAt, self.localMidnight(startedAt) >= startCutoffLocal { + return true + } + return false + } + + private static func scanPiSessionFile( + fileURL: URL, + cache: inout PiSessionCostCache, + context: ScanContext) + throws + { + try context.checkCancellation?() + let path = fileURL.path + let attrs = (try? FileManager.default.attributesOfItem(atPath: path)) ?? [:] + let mtime = (attrs[.modificationDate] as? Date)?.timeIntervalSince1970 ?? 0 + let size = (attrs[.size] as? NSNumber)?.int64Value ?? 0 + let mtimeMs = Int64(mtime * 1000) + + func storeFileUsage(_ usage: PiSessionFileUsage) { + cache.files[path] = usage + } + + let cached = cache.files[path] + if !context.forceRescan, + let cached, + cached.mtimeUnixMs == mtimeMs, + cached.size == size + { + return + } + + if !context.forceRescan, + let cached, + size > cached.size, + cached.parsedBytes > 0, + cached.parsedBytes <= size + { + let delta = try self.parsePiSessionFile( + fileURL: fileURL, + range: context.range, + startOffset: cached.parsedBytes, + initialModelContext: cached.lastModelContext, + pricingContext: context.pricingContext, + checkCancellation: context.checkCancellation) + if !delta.contributions.isEmpty { + self.applyContributions( + daysByProvider: &cache.daysByProvider, + contributions: delta.contributions, + sign: 1) + } + let merged = self.mergedContributions(existing: cached.contributions, delta: delta.contributions) + storeFileUsage(PiSessionFileUsage( + mtimeUnixMs: mtimeMs, + size: size, + parsedBytes: delta.parsedBytes, + lastModelContext: delta.lastModelContext, + contributions: merged)) + return + } + + if let cached { + self.applyContributions( + daysByProvider: &cache.daysByProvider, + contributions: cached.contributions, + sign: -1) + } + + let parsed = try self.parsePiSessionFile( + fileURL: fileURL, + range: context.range, + pricingContext: context.pricingContext, + checkCancellation: context.checkCancellation) + if !parsed.contributions.isEmpty { + self.applyContributions(daysByProvider: &cache.daysByProvider, contributions: parsed.contributions, sign: 1) + } + + storeFileUsage(PiSessionFileUsage( + mtimeUnixMs: mtimeMs, + size: size, + parsedBytes: parsed.parsedBytes, + lastModelContext: parsed.lastModelContext, + contributions: parsed.contributions)) + } + + private static func parsePiSessionFile( + fileURL: URL, + range: CostUsageScanner.CostUsageDayRange, + startOffset: Int64 = 0, + initialModelContext: PiModelContext? = nil, + pricingContext: ModelsDevPricingContext? = nil, + checkCancellation: CostUsageScanner.CancellationCheck? = nil) throws -> ParseResult + { + var currentModelContext = initialModelContext + var contributions: [String: [String: [String: PiPackedUsage]]] = [:] + + func add(provider: UsageProvider, dayKey: String, modelName: String, usage: PiPackedUsage) { + guard !usage.isZero else { return } + guard CostUsageScanner.CostUsageDayRange.isInRange( + dayKey: dayKey, + since: range.scanSinceKey, + until: range.scanUntilKey) + else { + return + } + + let providerKey = provider.rawValue + var providerDays = contributions[providerKey] ?? [:] + var dayModels = providerDays[dayKey] ?? [:] + let merged = self.addPacked(a: dayModels[modelName] ?? PiPackedUsage(), b: usage, sign: 1) + if merged.isZero { + dayModels.removeValue(forKey: modelName) + } else { + dayModels[modelName] = merged + } + if dayModels.isEmpty { + providerDays.removeValue(forKey: dayKey) + } else { + providerDays[dayKey] = dayModels + } + if providerDays.isEmpty { + contributions.removeValue(forKey: providerKey) + } else { + contributions[providerKey] = providerDays + } + } + + let parsedBytes: Int64 + do { + parsedBytes = try CostUsageJsonl.scan( + fileURL: fileURL, + offset: startOffset, + maxLineBytes: Self.maxLineBytes, + prefixBytes: Self.maxLineBytes, + checkCancellation: checkCancellation, + onLine: { line in + guard !line.bytes.isEmpty, !line.wasTruncated else { return } + autoreleasepool { + guard let object = (try? JSONSerialization.jsonObject(with: line.bytes)) as? [String: Any] + else { return } + guard let type = object["type"] as? String else { return } + + if type == "model_change" { + currentModelContext = self.modelContext(from: object) + return + } + + guard type == "message", let message = object["message"] as? [String: Any] else { return } + guard (message["role"] as? String) == "assistant" else { return } + + let identity = self.resolveAssistantIdentity( + entry: object, + message: message, + fallback: currentModelContext) + guard let identity else { return } + guard let date = self.timestampDate(entry: object, message: message) else { return } + let dayKey = CostUsageScanner.CostUsageDayRange.dayKey(from: date) + let usage = self.extractUsage( + provider: identity.provider, + modelName: identity.modelName, + message: message, + pricingDate: date, + pricingContext: pricingContext) + add(provider: identity.provider, dayKey: dayKey, modelName: identity.modelName, usage: usage) + } + }) + } catch is CancellationError { + throw CancellationError() + } catch { + parsedBytes = startOffset + } + + return ParseResult( + contributions: contributions, + parsedBytes: parsedBytes, + lastModelContext: currentModelContext) + } + + private static func modelContext(from object: [String: Any]) -> PiModelContext? { + guard let providerText = object["provider"] as? String, + let provider = self.mappedProvider(fromPiProvider: providerText) + else { + return nil + } + let rawModelName = (object["modelId"] as? String)?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" + guard let modelName = self.normalizeModelName(rawModelName, provider: provider) else { return nil } + return PiModelContext(providerRawValue: provider.rawValue, modelName: modelName) + } + + private static func resolveAssistantIdentity( + entry: [String: Any], + message: [String: Any], + fallback: PiModelContext?) -> AssistantIdentity? + { + let explicitProviderText = self.extractProviderText(entry: entry, message: message) + let explicitProvider = explicitProviderText.flatMap(self.mappedProvider(fromPiProvider:)) + let explicitModelText = self.extractModelText(entry: entry, message: message) + + if explicitProviderText != nil, explicitProvider == nil { + return nil + } + + if let explicitProvider, + let explicitModelText, + let explicitModel = self.normalizeModelName(explicitModelText, provider: explicitProvider) + { + return AssistantIdentity(provider: explicitProvider, modelName: explicitModel) + } + + if let explicitProvider, + let fallback, + fallback.providerRawValue == explicitProvider.rawValue + { + return AssistantIdentity(provider: explicitProvider, modelName: fallback.modelName) + } + + if explicitProviderText == nil, + let explicitModelText, + let fallbackProvider = fallback.flatMap({ UsageProvider(rawValue: $0.providerRawValue) }), + let explicitModel = self.normalizeModelName(explicitModelText, provider: fallbackProvider) + { + return AssistantIdentity(provider: fallbackProvider, modelName: explicitModel) + } + + if explicitProviderText == nil, + let fallback, + let provider = UsageProvider(rawValue: fallback.providerRawValue) + { + return AssistantIdentity(provider: provider, modelName: fallback.modelName) + } + + return nil + } + + private static func extractProviderText(entry: [String: Any], message: [String: Any]) -> String? { + if let provider = (message["provider"] as? String)?.trimmingCharacters(in: .whitespacesAndNewlines), + !provider.isEmpty + { + return provider + } + if let provider = (entry["provider"] as? String)?.trimmingCharacters(in: .whitespacesAndNewlines), + !provider.isEmpty + { + return provider + } + return nil + } + + private static func extractModelText(entry: [String: Any], message: [String: Any]) -> String? { + for value in [message["model"], entry["model"], message["modelId"], entry["modelId"]] { + if let model = (value as? String)?.trimmingCharacters(in: .whitespacesAndNewlines), !model.isEmpty { + return model + } + } + return nil + } + + private static func normalizeModelName(_ raw: String, provider: UsageProvider) -> String? { + let trimmed = raw.trimmingCharacters(in: .whitespacesAndNewlines) + guard !trimmed.isEmpty else { return nil } + return switch provider { + case .codex: + CostUsagePricing.normalizeCodexModel(trimmed) + case .claude: + CostUsagePricing.normalizeClaudeModel(trimmed) + default: + trimmed + } + } + + private static func timestampDate(entry: [String: Any], message: [String: Any]) -> Date? { + self.parseTimestampValue(message["timestamp"]) + ?? self.parseTimestampValue(entry["timestamp"]) + } + + private static func parseTimestampValue(_ value: Any?) -> Date? { + if let number = value as? NSNumber { + let raw = number.doubleValue + guard raw.isFinite else { return nil } + if raw > 1_000_000_000_000 { + return Date(timeIntervalSince1970: raw / 1000) + } + return Date(timeIntervalSince1970: raw) + } + + if let string = value as? String { + if let numeric = Double(string), numeric.isFinite { + if numeric > 1_000_000_000_000 { + return Date(timeIntervalSince1970: numeric / 1000) + } + return Date(timeIntervalSince1970: numeric) + } + return self.parseISO(string) + } + + return nil + } + + private static func extractUsage( + provider: UsageProvider, + modelName: String, + message: [String: Any], + pricingDate: Date? = nil, + pricingContext: ModelsDevPricingContext? = nil) -> PiPackedUsage + { + let usage = (message["usage"] as? [String: Any]) ?? [:] + let input = self.readNonNegativeInt( + usage["input"] + ?? usage["inputTokens"] + ?? usage["input_tokens"] + ?? usage["promptTokens"] + ?? usage["prompt_tokens"]) + let cacheRead = self.readNonNegativeInt( + usage["cacheRead"] + ?? usage["cacheReadTokens"] + ?? usage["cache_read"] + ?? usage["cache_read_tokens"] + ?? usage["cacheReadInputTokens"] + ?? usage["cache_read_input_tokens"]) + let cacheWrite = self.readNonNegativeInt( + usage["cacheWrite"] + ?? usage["cacheWriteTokens"] + ?? usage["cache_write"] + ?? usage["cache_write_tokens"] + ?? usage["cacheCreationTokens"] + ?? usage["cache_creation_tokens"] + ?? usage["cacheCreationInputTokens"] + ?? usage["cache_creation_input_tokens"]) + let output = self.readNonNegativeInt( + usage["output"] + ?? usage["outputTokens"] + ?? usage["output_tokens"] + ?? usage["completionTokens"] + ?? usage["completion_tokens"]) + + let directTotal = self.readNonNegativeInt( + usage["totalTokens"] + ?? usage["total_tokens"] + ?? usage["tokenCount"] + ?? usage["token_count"] + ?? usage["tokens"]) + let derivedTotal = input + cacheRead + cacheWrite + output + let totalTokens = max(directTotal, derivedTotal) + + let rawUsage = PiPackedUsage( + inputTokens: input, + cacheReadTokens: cacheRead, + cacheWriteTokens: cacheWrite, + outputTokens: output, + totalTokens: totalTokens) + // Pi JSONL does not record Anthropic cache retention, so use Pi's persisted default tariff. + let costUSD = self.computedCostUSD( + provider: provider, + modelName: modelName, + usage: rawUsage, + pricingDate: pricingDate, + pricingContext: pricingContext) + let costNanos = costUSD.map { Int64(($0 * self.costScale).rounded()) } ?? 0 + + return PiPackedUsage( + inputTokens: rawUsage.inputTokens, + cacheReadTokens: rawUsage.cacheReadTokens, + cacheWriteTokens: rawUsage.cacheWriteTokens, + outputTokens: rawUsage.outputTokens, + totalTokens: rawUsage.totalTokens, + costNanos: costNanos, + costSampleCount: costUSD == nil ? 0 : 1, + usageSampleCount: 1) + } + + private static func computedCostUSD( + provider: UsageProvider, + modelName: String, + usage: PiPackedUsage, + pricingDate: Date? = nil, + pricingContext: ModelsDevPricingContext? = nil) -> Double? + { + switch provider { + case .codex: + // Pi records input, cache reads, and cache writes as disjoint counts. Codex pricing + // expects cached/write tokens to be subsets of total input, so reconstruct that total + // here and pass writes separately (1.25x input for GPT-5.6 when rates are known). + CostUsagePricing.codexCostUSD( + model: modelName, + inputTokens: usage.inputTokens + usage.cacheReadTokens + usage.cacheWriteTokens, + cachedInputTokens: usage.cacheReadTokens, + outputTokens: usage.outputTokens, + cacheWriteInputTokens: usage.cacheWriteTokens, + modelsDevCatalog: pricingContext?.catalog, + modelsDevCacheRoot: pricingContext?.cacheRoot) + case .claude: + CostUsagePricing.claudeCostUSD( + model: modelName, + inputTokens: usage.inputTokens, + cacheReadInputTokens: usage.cacheReadTokens, + cacheCreationInputTokens: usage.cacheWriteTokens, + outputTokens: usage.outputTokens, + pricingDate: pricingDate, + modelsDevCatalog: pricingContext?.catalog, + modelsDevCacheRoot: pricingContext?.cacheRoot) + default: + nil + } + } + + private static func readNonNegativeInt(_ value: Any?) -> Int { + if let number = value as? NSNumber { + let numeric = number.doubleValue + guard numeric.isFinite, numeric >= 0, numeric <= self.maxSafeRoundedInt else { return 0 } + return Int(numeric.rounded()) + } + if let string = value as? String, + let numeric = Double(string), + numeric.isFinite, + numeric >= 0, + numeric <= self.maxSafeRoundedInt + { + return Int(numeric.rounded()) + } + return 0 + } +} + +extension PiSessionCostScanner { + private static func mappedProvider(fromPiProvider provider: String) -> UsageProvider? { + switch provider.lowercased() { + case "openai-codex": + .codex + case "anthropic": + .claude + default: + nil + } + } + + private static func buildReport( + provider: UsageProvider, + cache: PiSessionCostCache, + range: CostUsageScanner.CostUsageDayRange, + pricingContext: ModelsDevPricingContext? = nil) -> CostUsageDailyReport + { + guard let providerDays = cache.daysByProvider[provider.rawValue] else { + return CostUsageDailyReport(data: [], summary: nil) + } + + let dayKeys = providerDays.keys.sorted().filter { + CostUsageScanner.CostUsageDayRange.isInRange(dayKey: $0, since: range.sinceKey, until: range.untilKey) + } + + var entries: [CostUsageDailyReport.Entry] = [] + var totalInput = 0 + var totalOutput = 0 + var totalCacheRead = 0 + var totalCacheWrite = 0 + var totalTokens = 0 + var totalCostNanos: Int64 = 0 + var totalCostSamples = 0 + + for dayKey in dayKeys { + guard let models = providerDays[dayKey] else { continue } + let modelNames = models.keys.sorted() + + var dayInput = 0 + var dayOutput = 0 + var dayCacheRead = 0 + var dayCacheWrite = 0 + var dayTotalTokens = 0 + var dayCostNanos: Int64 = 0 + var dayCostSamples = 0 + var breakdown: [CostUsageDailyReport.ModelBreakdown] = [] + + for modelName in modelNames { + let packed = models[modelName] ?? PiPackedUsage() + let modelTotalTokens = max( + packed.totalTokens, + packed.inputTokens + packed.cacheReadTokens + packed.cacheWriteTokens + packed.outputTokens) + let currentPricingCost = self.computedCostUSD( + provider: provider, + modelName: modelName, + usage: packed, + pricingContext: pricingContext) + let usageSampleCount = packed.usageSampleCount + let hasCompleteCachedCost = (usageSampleCount ?? 0) > 0 + && packed.costSampleCount == usageSampleCount + // Cached costs are accumulated per message, which preserves Claude long-context threshold boundaries. + let costNanos = hasCompleteCachedCost + ? packed.costNanos + : currentPricingCost.map { Int64(($0 * self.costScale).rounded()) } + breakdown.append(CostUsageDailyReport.ModelBreakdown( + modelName: modelName, + costUSD: costNanos.map { Double($0) / Self.costScale }, + totalTokens: modelTotalTokens > 0 ? modelTotalTokens : nil)) + dayInput += packed.inputTokens + dayOutput += packed.outputTokens + dayCacheRead += packed.cacheReadTokens + dayCacheWrite += packed.cacheWriteTokens + dayTotalTokens += modelTotalTokens + if let costNanos { + dayCostNanos += costNanos + dayCostSamples += 1 + } + } + + let sortedBreakdown = self.sortedModelBreakdowns(breakdown) + entries.append(CostUsageDailyReport.Entry( + date: dayKey, + inputTokens: dayInput > 0 ? dayInput : nil, + outputTokens: dayOutput > 0 ? dayOutput : nil, + cacheReadTokens: dayCacheRead > 0 ? dayCacheRead : nil, + cacheCreationTokens: dayCacheWrite > 0 ? dayCacheWrite : nil, + totalTokens: dayTotalTokens > 0 ? dayTotalTokens : nil, + costUSD: dayCostSamples > 0 ? Double(dayCostNanos) / Self.costScale : nil, + modelsUsed: modelNames, + modelBreakdowns: sortedBreakdown)) + + totalInput += dayInput + totalOutput += dayOutput + totalCacheRead += dayCacheRead + totalCacheWrite += dayCacheWrite + totalTokens += dayTotalTokens + totalCostNanos += dayCostNanos + totalCostSamples += dayCostSamples + } + + guard !entries.isEmpty else { return CostUsageDailyReport(data: [], summary: nil) } + return CostUsageDailyReport( + data: entries, + summary: CostUsageDailyReport.Summary( + totalInputTokens: totalInput > 0 ? totalInput : nil, + totalOutputTokens: totalOutput > 0 ? totalOutput : nil, + cacheReadTokens: totalCacheRead > 0 ? totalCacheRead : nil, + cacheCreationTokens: totalCacheWrite > 0 ? totalCacheWrite : nil, + totalTokens: totalTokens > 0 ? totalTokens : nil, + totalCostUSD: totalCostSamples > 0 ? Double(totalCostNanos) / Self.costScale : nil)) + } + + private static func mergedContributions( + existing: [String: [String: [String: PiPackedUsage]]], + delta: [String: [String: [String: PiPackedUsage]]]) -> [String: [String: [String: PiPackedUsage]]] + { + var merged = existing + self.applyContributions(daysByProvider: &merged, contributions: delta, sign: 1) + return merged + } + + private static func applyContributions( + daysByProvider: inout [String: [String: [String: PiPackedUsage]]], + contributions: [String: [String: [String: PiPackedUsage]]], + sign: Int) + { + for (providerKey, providerDays) in contributions { + var mergedProviderDays = daysByProvider[providerKey] ?? [:] + for (dayKey, dayModels) in providerDays { + var mergedDayModels = mergedProviderDays[dayKey] ?? [:] + for (modelName, packed) in dayModels { + let updated = self.addPacked( + a: mergedDayModels[modelName] ?? PiPackedUsage(), + b: packed, + sign: sign) + if updated.isZero { + mergedDayModels.removeValue(forKey: modelName) + } else { + mergedDayModels[modelName] = updated + } + } + if mergedDayModels.isEmpty { + mergedProviderDays.removeValue(forKey: dayKey) + } else { + mergedProviderDays[dayKey] = mergedDayModels + } + } + if mergedProviderDays.isEmpty { + daysByProvider.removeValue(forKey: providerKey) + } else { + daysByProvider[providerKey] = mergedProviderDays + } + } + } + + private static func addPacked(a: PiPackedUsage, b: PiPackedUsage, sign: Int) -> PiPackedUsage { + let aUsageSampleCount = a.usageSampleCount ?? (a.isZero ? 0 : nil) + let bUsageSampleCount = b.usageSampleCount ?? (b.isZero ? 0 : nil) + let usageSampleCount: Int? = if let aCount = aUsageSampleCount, let bCount = bUsageSampleCount { + max(0, aCount + sign * bCount) + } else { + nil + } + + return PiPackedUsage( + inputTokens: max(0, a.inputTokens + sign * b.inputTokens), + cacheReadTokens: max(0, a.cacheReadTokens + sign * b.cacheReadTokens), + cacheWriteTokens: max(0, a.cacheWriteTokens + sign * b.cacheWriteTokens), + outputTokens: max(0, a.outputTokens + sign * b.outputTokens), + totalTokens: max(0, a.totalTokens + sign * b.totalTokens), + costNanos: max(0, a.costNanos + Int64(sign) * b.costNanos), + costSampleCount: max(0, a.costSampleCount + sign * b.costSampleCount), + usageSampleCount: usageSampleCount) + } + + private static func parseSessionStartFromFilename(_ filename: String) -> Date? { + guard let regex = self.sessionStartFilenameRegex else { return nil } + let range = NSRange(filename.startIndex.. Date? { + self.isoFormatterBox.lock.lock() + defer { self.isoFormatterBox.lock.unlock() } + return self.isoFormatterBox.withFractional.date(from: text) + ?? self.isoFormatterBox.plain.date(from: text) + } + + private static func localMidnight(_ date: Date) -> Date { + let components = Calendar.current.dateComponents([.year, .month, .day], from: date) + return Calendar.current.date(from: components) ?? date + } + + private static func dateFromDayKey(_ key: String) -> Date? { + let parts = key.split(separator: "-") + guard parts.count == 3, + let year = Int(parts[0]), + let month = Int(parts[1]), + let day = Int(parts[2]) else { return nil } + + var components = DateComponents() + components.calendar = Calendar.current + components.timeZone = TimeZone.current + components.year = year + components.month = month + components.day = day + components.hour = 0 + return components.date + } + + private static func sortedModelBreakdowns(_ breakdowns: [CostUsageDailyReport.ModelBreakdown]) + -> [CostUsageDailyReport.ModelBreakdown] + { + breakdowns.sorted { lhs, rhs in + let lhsCost = lhs.costUSD ?? -1 + let rhsCost = rhs.costUSD ?? -1 + if lhsCost != rhsCost { + return lhsCost > rhsCost + } + + let lhsTokens = lhs.totalTokens ?? -1 + let rhsTokens = rhs.totalTokens ?? -1 + if lhsTokens != rhsTokens { + return lhsTokens > rhsTokens + } + + return lhs.modelName > rhs.modelName + } + } +} diff --git a/Sources/CodexBarCore/ProviderAccountSnapshot.swift b/Sources/CodexBarCore/ProviderAccountSnapshot.swift new file mode 100644 index 0000000..6a569c1 --- /dev/null +++ b/Sources/CodexBarCore/ProviderAccountSnapshot.swift @@ -0,0 +1,55 @@ +import Foundation + +/// Stable identity for one account row surfaced by a multi-account source adapter. +/// +/// `source` names the adapter (for example `claude-swap`) and `opaqueID` is the +/// source-issued identifier (for example a numeric slot). Identity never derives +/// from emails or credential material, per +/// `docs/claude-multi-account-and-status-items.md`. +public struct ProviderAccountIdentity: Hashable, Sendable { + public let source: String + public let opaqueID: String + + public init(source: String, opaqueID: String) { + self.source = source + self.opaqueID = opaqueID + } +} + +/// Provider-neutral projection of one account's usage, consumed by menus (and, +/// later, per-account status items) without teaching UI code about any specific +/// credential source. +public struct ProviderAccountUsageSnapshot: Identifiable, Sendable { + public let id: ProviderAccountIdentity + public let provider: UsageProvider + /// Display-only label (may contain personal data such as an email); UI is + /// responsible for privacy redaction. Never logged or persisted. + public let displayLabel: String + public let isActive: Bool + /// Whether the source can make this inactive account the provider's active account. + /// Activation remains source-owned; CodexBar never handles credential material. + public let canActivate: Bool + public let snapshot: UsageSnapshot? + public let error: String? + public let sourceLabel: String? + + public init( + id: ProviderAccountIdentity, + provider: UsageProvider, + displayLabel: String, + isActive: Bool, + canActivate: Bool = false, + snapshot: UsageSnapshot?, + error: String?, + sourceLabel: String?) + { + self.id = id + self.provider = provider + self.displayLabel = displayLabel + self.isActive = isActive + self.canActivate = canActivate + self.snapshot = snapshot + self.error = error + self.sourceLabel = sourceLabel + } +} diff --git a/Sources/CodexBarCore/ProviderCostSnapshot.swift b/Sources/CodexBarCore/ProviderCostSnapshot.swift new file mode 100644 index 0000000..5d838d5 --- /dev/null +++ b/Sources/CodexBarCore/ProviderCostSnapshot.swift @@ -0,0 +1,38 @@ +import Foundation + +/// Provider-specific spend/budget snapshot (e.g. Claude "Extra usage" monthly spend vs limit). +public struct ProviderCostSnapshot: Equatable, Codable, Sendable { + public let used: Double + public let limit: Double + public let currencyCode: String + /// Human-friendly period label (e.g. "Monthly"). Optional; some providers don't expose a period. + public let period: String? + /// Optional renewal/reset timestamp for the period. + public let resetsAt: Date? + /// Optional amount restored on the next regeneration tick for providers with rolling credit recovery. + public let nextRegenAmount: Double? + /// This account's own contribution when `used`/`limit` describe a shared/pooled budget + /// (e.g. Cursor team on-demand pool). nil when the budget is already personal. + public let personalUsed: Double? + public let updatedAt: Date + + public init( + used: Double, + limit: Double, + currencyCode: String, + period: String? = nil, + resetsAt: Date? = nil, + nextRegenAmount: Double? = nil, + personalUsed: Double? = nil, + updatedAt: Date) + { + self.used = used + self.limit = limit + self.currencyCode = currencyCode + self.period = period + self.resetsAt = resetsAt + self.nextRegenAmount = nextRegenAmount + self.personalUsed = personalUsed + self.updatedAt = updatedAt + } +} diff --git a/Sources/CodexBarCore/ProviderEndpointOverrideValidator.swift b/Sources/CodexBarCore/ProviderEndpointOverrideValidator.swift new file mode 100644 index 0000000..6b4ee4a --- /dev/null +++ b/Sources/CodexBarCore/ProviderEndpointOverrideValidator.swift @@ -0,0 +1,170 @@ +import Foundation + +enum ProviderEndpointOverrideError: LocalizedError, Equatable { + case minimax(String) + case alibabaCodingPlan(String) + + var errorDescription: String? { + switch self { + case let .minimax(key): + "MiniMax endpoint override \(key) is not allowed. " + + "Use an HTTPS endpoint without user info or encoded host tricks. " + + "If MINIMAX_REQUIRE_PROVIDER_ENDPOINT_OVERRIDES=true is set, the endpoint must also be MiniMax-owned." + case let .alibabaCodingPlan(key): + "Alibaba Coding Plan endpoint override \(key) is not allowed. " + + "Use an HTTPS endpoint without user info or encoded host tricks. " + + "If ALIBABA_CODING_PLAN_REQUIRE_PROVIDER_ENDPOINT_OVERRIDES=true is set, " + + "the endpoint must also be Alibaba-owned." + } + } +} + +struct ProviderEndpointOverrideValidator { + enum HostPolicy { + case allowAnyHTTPSHost + case providerOwnedOnly + } + + private let allowedHosts: Set + private let allowedDomainSuffixes: Set + + init(allowedHosts: [String] = [], allowedDomainSuffixes: [String] = []) { + self.allowedHosts = Set(allowedHosts.map { $0.lowercased() }) + self.allowedDomainSuffixes = Set(allowedDomainSuffixes.map { $0.lowercased() }) + } + + func validatedHost(_ raw: String?, policy: HostPolicy = .allowAnyHTTPSHost) -> String? { + guard let raw, + let url = self.url(from: raw), + let host = self.validatedDecodedHost(for: url, policy: policy) + else { return nil } + return self.hostAuthority(host: host, port: url.port) + } + + func validatedURL(_ raw: String?, policy: HostPolicy = .allowAnyHTTPSHost) -> URL? { + guard let raw, + let url = self.url(from: raw), + self.validatedDecodedHost(for: url, policy: policy) != nil + else { return nil } + return url + } + + func validatedURLAllowingLoopbackHTTP(_ raw: String?) -> URL? { + guard let raw, + Self.hasExplicitURLScheme(raw), + let url = URL(string: raw), + let scheme = url.scheme?.lowercased(), + scheme == "https" || scheme == "http", + url.user == nil, + url.password == nil, + let host = self.validatedDecodedHost(for: url, policy: .allowAnyHTTPSHost), + scheme == "https" || Self.isLoopbackHost(host) + else { return nil } + return url + } + + static func normalizedHTTPSURL(from raw: String) -> URL? { + let url = if Self.hasExplicitURLScheme(raw) { + URL(string: raw) + } else { + URL(string: "https://\(raw)") + } + guard let url else { return nil } + guard let scheme = url.scheme?.lowercased(), scheme == "https" else { return nil } + guard url.user == nil, url.password == nil else { return nil } + guard let decodedHost = url.host(percentEncoded: false)?.lowercased(), + !decodedHost.isEmpty, + !decodedHost.contains("%"), + decodedHost.rangeOfCharacter(from: .whitespacesAndNewlines) == nil, + decodedHost.rangeOfCharacter(from: .controlCharacters) == nil, + let encodedHost = url.host(percentEncoded: true)?.lowercased(), + Self.hostHasNoEncodedDelimiters(encodedHost, decodedHost: decodedHost, url: url) + else { return nil } + return url + } + + private func url(from raw: String) -> URL? { + Self.normalizedHTTPSURL(from: raw) + } + + private static func hasExplicitURLScheme(_ raw: String) -> Bool { + guard let colonIndex = raw.firstIndex(of: ":") else { return false } + if raw[colonIndex...].hasPrefix("://") { return true } + + if let authorityEnd = raw.firstIndex(where: { ["/", "?", "#"].contains($0) }), + colonIndex > authorityEnd + { + return false + } + + let afterColon = raw.index(after: colonIndex) + guard afterColon < raw.endIndex else { return true } + let portEnd = raw[afterColon...].firstIndex { Set(["/", "?", "#"]).contains($0) } ?? raw.endIndex + let suffix = raw[afterColon.. Bool { + if host == "localhost" || host == "::1" { return true } + let octets = host.split(separator: ".", omittingEmptySubsequences: false) + guard octets.count == 4, + let first = UInt8(octets[0]), + octets.dropFirst().allSatisfy({ UInt8($0) != nil }) + else { return false } + return first == 127 + } + + private func hostAuthority(host: String, port: Int?) -> String { + let authorityHost = host.contains(":") ? "[\(host)]" : host + guard let port else { return authorityHost } + return "\(authorityHost):\(port)" + } + + private func validatedDecodedHost(for url: URL, policy: HostPolicy) -> String? { + guard let decodedHost = url.host(percentEncoded: false)?.lowercased(), + !decodedHost.isEmpty, + !decodedHost.contains("%"), + decodedHost.rangeOfCharacter(from: .whitespacesAndNewlines) == nil, + decodedHost.rangeOfCharacter(from: .controlCharacters) == nil, + let encodedHost = url.host(percentEncoded: true)?.lowercased(), + Self.hostHasNoEncodedDelimiters(encodedHost, decodedHost: decodedHost, url: url) + else { return nil } + + switch policy { + case .allowAnyHTTPSHost: + return decodedHost + case .providerOwnedOnly: + let isAllowedHost = self.allowedHosts.contains(decodedHost) + let isAllowedSuffix = self.allowedDomainSuffixes.contains { suffix in + decodedHost == suffix || decodedHost.hasSuffix(".\(suffix)") + } + guard isAllowedHost || isAllowedSuffix else { return nil } + return decodedHost + } + } + + private static func hostHasNoEncodedDelimiters(_ encodedHost: String, decodedHost: String, url: URL) -> Bool { + if decodedHost.contains(":") { + guard encodedHost == decodedHost, + let componentHost = URLComponents(url: url, resolvingAgainstBaseURL: false)?.host, + componentHost.hasPrefix("["), + componentHost.hasSuffix("]") + else { return false } + + let address = componentHost.dropFirst().dropLast() + return !address.isEmpty && address.allSatisfy { $0.isHexDigit || $0 == ":" || $0 == "." } + } + + let decodedDelimiters = CharacterSet(charactersIn: "/\\?#@:") + guard decodedHost.rangeOfCharacter(from: decodedDelimiters) == nil else { return false } + + let encodedDelimiters = ["%2f", "%5c", "%3f", "%23", "%40", "%3a"] + return !encodedDelimiters.contains { encodedHost.contains($0) } + } +} diff --git a/Sources/CodexBarCore/ProviderHTTPClient.swift b/Sources/CodexBarCore/ProviderHTTPClient.swift new file mode 100644 index 0000000..68b8b38 --- /dev/null +++ b/Sources/CodexBarCore/ProviderHTTPClient.swift @@ -0,0 +1,253 @@ +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +public protocol ProviderHTTPTransport: Sendable { + func data(for request: URLRequest) async throws -> (Data, URLResponse) +} + +#if !os(Linux) +extension URLSession: ProviderHTTPTransport {} +#endif + +extension URLSession { + public func response(for request: URLRequest) async throws -> ProviderHTTPResponse { + let (data, response) = try await self.data(for: request) + guard let httpResponse = response as? HTTPURLResponse else { + throw URLError(.badServerResponse) + } + return ProviderHTTPResponse(data: data, response: httpResponse) + } +} + +public struct ProviderHTTPResponse: Sendable { + public let data: Data + public let response: HTTPURLResponse + + public init(data: Data, response: HTTPURLResponse) { + self.data = data + self.response = response + } + + public var statusCode: Int { + self.response.statusCode + } +} + +public struct ProviderHTTPRetryPolicy: Sendable { + public let maxRetries: Int + public let retryableStatusCodes: Set + public let retryableURLErrorCodes: Set + public let retryableMethods: Set + public let baseDelaySeconds: TimeInterval + public let maxDelaySeconds: TimeInterval + + public init( + maxRetries: Int, + retryableStatusCodes: Set = [408, 429, 500, 502, 503, 504], + retryableURLErrorCodes: Set = [ + .timedOut, + .networkConnectionLost, + .cannotConnectToHost, + .cannotFindHost, + .dnsLookupFailed, + ], + retryableMethods: Set = ["GET", "HEAD", "OPTIONS"], + baseDelaySeconds: TimeInterval = 1, + maxDelaySeconds: TimeInterval = 10) + { + self.maxRetries = max(0, maxRetries) + self.retryableStatusCodes = retryableStatusCodes + self.retryableURLErrorCodes = retryableURLErrorCodes + self.retryableMethods = retryableMethods + self.baseDelaySeconds = max(0, baseDelaySeconds) + self.maxDelaySeconds = max(0, maxDelaySeconds) + } + + public static let disabled = ProviderHTTPRetryPolicy( + maxRetries: 0, + retryableStatusCodes: [], + retryableURLErrorCodes: [], + baseDelaySeconds: 0, + maxDelaySeconds: 0) + + public static let transientIdempotent = ProviderHTTPRetryPolicy(maxRetries: 1) + + func shouldRetry(request: URLRequest, attempt: Int, statusCode: Int) -> Bool { + self.canRetry(request: request, attempt: attempt) + && self.retryableStatusCodes.contains(statusCode) + } + + func shouldRetry(request: URLRequest, attempt: Int, error: Error) -> Bool { + guard self.canRetry(request: request, attempt: attempt) else { return false } + guard let urlError = error as? URLError else { return false } + return self.retryableURLErrorCodes.contains(urlError.code) + } + + func delaySeconds(attempt: Int, response: HTTPURLResponse?) -> TimeInterval { + if let retryAfter = response?.value(forHTTPHeaderField: "Retry-After"), + let seconds = TimeInterval(retryAfter.trimmingCharacters(in: .whitespacesAndNewlines)), + seconds >= 0 + { + return min(seconds, self.maxDelaySeconds) + } + + guard self.baseDelaySeconds > 0 else { return 0 } + let multiplier = pow(2, Double(max(0, attempt))) + return min(self.baseDelaySeconds * multiplier, self.maxDelaySeconds) + } + + private func canRetry(request: URLRequest, attempt: Int) -> Bool { + guard attempt < self.maxRetries else { return false } + let method = request.httpMethod?.uppercased() ?? "GET" + return self.retryableMethods.contains(method) + } +} + +public struct ProviderHTTPTransportHandler: ProviderHTTPTransport { + private let handler: @Sendable (URLRequest) async throws -> (Data, URLResponse) + + public init(_ handler: @escaping @Sendable (URLRequest) async throws -> (Data, URLResponse)) { + self.handler = handler + } + + public func data(for request: URLRequest) async throws -> (Data, URLResponse) { + try await self.handler(request) + } +} + +extension ProviderHTTPTransport { + public func response(for request: URLRequest) async throws -> ProviderHTTPResponse { + try await self.response(for: request, retryPolicy: .disabled) + } + + public func response( + for request: URLRequest, + retryPolicy: ProviderHTTPRetryPolicy) async throws -> ProviderHTTPResponse + { + var attempt = 0 + + while true { + do { + let (data, response) = try await self.data(for: request) + guard let httpResponse = response as? HTTPURLResponse else { + throw URLError(.badServerResponse) + } + let providerResponse = ProviderHTTPResponse(data: data, response: httpResponse) + guard retryPolicy.shouldRetry( + request: request, + attempt: attempt, + statusCode: providerResponse.statusCode) + else { + return providerResponse + } + try await Self.sleepBeforeRetry(policy: retryPolicy, attempt: attempt, response: httpResponse) + attempt += 1 + } catch { + guard retryPolicy.shouldRetry(request: request, attempt: attempt, error: error) else { + throw error + } + try await Self.sleepBeforeRetry(policy: retryPolicy, attempt: attempt, response: nil) + attempt += 1 + } + } + } + + private static func sleepBeforeRetry( + policy: ProviderHTTPRetryPolicy, + attempt: Int, + response: HTTPURLResponse?) async throws + { + let delay = policy.delaySeconds(attempt: attempt, response: response) + guard delay > 0 else { return } + try await Task.sleep(nanoseconds: UInt64(delay * 1_000_000_000)) + } +} + +public final class ProviderHTTPClient: ProviderHTTPTransport, @unchecked Sendable { + public static let shared = ProviderHTTPClient(session: ProviderHTTPClient.sharedSession()) + + private let session: URLSession + + public init(session: URLSession? = nil) { + self.session = session ?? Self.redirectGuardedSession() + } + + static func defaultConfiguration() -> URLSessionConfiguration { + let configuration = URLSessionConfiguration.default + configuration.timeoutIntervalForRequest = 30 + configuration.timeoutIntervalForResource = 90 + #if !os(Linux) + configuration.waitsForConnectivity = false + #endif + return configuration + } + + private static func sharedSession() -> URLSession { + if self.isRunningTests { + // XCTest URLProtocol.registerClass stubs only intercept URLSession.shared on macOS. + return .shared + } + return self.redirectGuardedSession() + } + + static func redirectGuardedSession( + configuration: URLSessionConfiguration = ProviderHTTPClient.defaultConfiguration()) -> URLSession + { + URLSession( + configuration: configuration, + delegate: ProviderHTTPRedirectGuardDelegate(), + delegateQueue: nil) + } + + private static var isRunningTests: Bool { + let environment = ProcessInfo.processInfo.environment + if environment["XCTestConfigurationFilePath"] != nil || environment["XCTestBundlePath"] != nil { + return true + } + if ProcessInfo.processInfo.processName.lowercased().contains("xctest") { + return true + } + return CommandLine.arguments.contains { $0.lowercased().contains(".xctest") } + } + + public func data(for request: URLRequest) async throws -> (Data, URLResponse) { + try await self.session.data(for: request) + } +} + +final class ProviderHTTPRedirectGuardDelegate: NSObject, URLSessionTaskDelegate, @unchecked Sendable { + func urlSession( + _: URLSession, + task: URLSessionTask, + willPerformHTTPRedirection _: HTTPURLResponse, + newRequest request: URLRequest, + completionHandler: @escaping @Sendable (URLRequest?) -> Void) + { + completionHandler(Self.guardedRedirectRequest(originalURL: task.originalRequest?.url, redirectRequest: request)) + } + + static func guardedRedirectRequest(originalURL: URL?, redirectRequest request: URLRequest) -> URLRequest? { + guard let originalURL, let redirectedURL = request.url else { return nil } + guard originalURL.scheme?.caseInsensitiveCompare("https") == .orderedSame else { return nil } + guard redirectedURL.scheme?.caseInsensitiveCompare("https") == .orderedSame else { return nil } + guard self.isSameOrigin(originalURL, redirectedURL) else { return nil } + return request + } + + private static func isSameOrigin(_ lhs: URL, _ rhs: URL) -> Bool { + lhs.scheme?.lowercased() == rhs.scheme?.lowercased() + && lhs.host?.lowercased() == rhs.host?.lowercased() + && self.normalizedPort(lhs) == self.normalizedPort(rhs) + } + + private static func normalizedPort(_ url: URL) -> Int? { + if let port = url.port { return port } + switch url.scheme?.lowercased() { + case "http": return 80 + case "https": return 443 + default: return nil + } + } +} diff --git a/Sources/CodexBarCore/ProviderStorageFootprint.swift b/Sources/CodexBarCore/ProviderStorageFootprint.swift new file mode 100644 index 0000000..75feb7a --- /dev/null +++ b/Sources/CodexBarCore/ProviderStorageFootprint.swift @@ -0,0 +1,543 @@ +import Foundation + +public struct ProviderStorageFootprint: Sendable, Equatable { + public struct Component: Sendable, Equatable, Identifiable { + public let id: String + public let path: String + public let totalBytes: Int64 + + public init(path: String, totalBytes: Int64) { + self.id = path + self.path = path + self.totalBytes = totalBytes + } + + public var name: String { + let url = URL(fileURLWithPath: self.path) + let last = url.lastPathComponent + if last.isEmpty { return self.path } + return last + } + } + + public let provider: UsageProvider + public let totalBytes: Int64 + public let paths: [String] + public let missingPaths: [String] + public let unreadablePaths: [String] + public let components: [Component] + public let updatedAt: Date + + public init( + provider: UsageProvider, + totalBytes: Int64, + paths: [String], + missingPaths: [String], + unreadablePaths: [String], + components: [Component] = [], + updatedAt: Date) + { + self.provider = provider + self.totalBytes = totalBytes + self.paths = paths + self.missingPaths = missingPaths + self.unreadablePaths = unreadablePaths + self.components = components + self.updatedAt = updatedAt + } + + public var hasLocalData: Bool { + self.totalBytes > 0 + } + + /// Value equality that ignores `updatedAt`. Two scans of identical on-disk data differ only by + /// their scan timestamp, so callers use this to avoid re-publishing observable state (and the + /// menu-invalidation churn that follows) when nothing the user sees has actually changed. + public func hasSameContents(as other: ProviderStorageFootprint) -> Bool { + self.provider == other.provider && + self.totalBytes == other.totalBytes && + self.paths == other.paths && + self.missingPaths == other.missingPaths && + self.unreadablePaths == other.unreadablePaths && + self.components == other.components + } + + public var cleanupRecommendations: [ProviderStorageRecommendation] { + ProviderStorageRecommendation.recommendations(for: self) + } + + public func replacingProvider(_ provider: UsageProvider) -> ProviderStorageFootprint { + ProviderStorageFootprint( + provider: provider, + totalBytes: self.totalBytes, + paths: self.paths, + missingPaths: self.missingPaths, + unreadablePaths: self.unreadablePaths, + components: self.components, + updatedAt: self.updatedAt) + } +} + +public struct ProviderStorageRecommendation: Sendable, Equatable, Identifiable { + public enum RiskLevel: String, Sendable { + case informational + case manualCleanup + } + + public let id: String + public let provider: UsageProvider + public let path: String + public let bytes: Int64 + public let title: String + public let riskLevel: RiskLevel + public let consequence: String + public let sortPriority: Int + + public init( + provider: UsageProvider, + path: String, + bytes: Int64, + title: String, + riskLevel: RiskLevel, + consequence: String, + sortPriority: Int) + { + self.id = path + self.provider = provider + self.path = path + self.bytes = bytes + self.title = title + self.riskLevel = riskLevel + self.consequence = consequence + self.sortPriority = sortPriority + } + + public static func recommendations(for footprint: ProviderStorageFootprint) -> [ProviderStorageRecommendation] { + let candidates: [ProviderStorageRecommendation] = footprint.components.compactMap { component in + switch footprint.provider { + case .claude: + self.claudeRecommendation(for: component) + case .codex: + self.codexRecommendation(for: component, roots: footprint.paths) + default: + nil + } + } + + return candidates.sorted { lhs, rhs in + if lhs.sortPriority == rhs.sortPriority { + if lhs.bytes == rhs.bytes { + return lhs.path.localizedCaseInsensitiveCompare(rhs.path) == .orderedAscending + } + return lhs.bytes > rhs.bytes + } + return lhs.sortPriority < rhs.sortPriority + } + } + + private static func claudeRecommendation( + for component: ProviderStorageFootprint.Component) + -> ProviderStorageRecommendation? + { + switch component.name { + case "projects": + self.make( + provider: .claude, + component: component, + title: "Manual cleanup: past sessions", + consequence: "Clearing removes past resume, continue, and rewind history.", + priority: 10) + case "file-history": + self.make( + provider: .claude, + component: component, + title: "Manual cleanup: file checkpoints", + consequence: "Clearing removes checkpoint restore data for previous edits.", + priority: 20) + case "plans": + self.make( + provider: .claude, + component: component, + title: "Manual cleanup: saved plans", + consequence: "Clearing removes old plan-mode files.", + priority: 30) + case "debug": + self.make( + provider: .claude, + component: component, + title: "Manual cleanup: debug logs", + consequence: "Clearing removes past debug logs.", + priority: 40) + case "paste-cache", "image-cache": + self.make( + provider: .claude, + component: component, + title: "Manual cleanup: attachment cache", + consequence: "Clearing removes cached large pastes or attached images.", + priority: 50) + case "session-env": + self.make( + provider: .claude, + component: component, + title: "Manual cleanup: session metadata", + consequence: "Clearing removes per-session environment metadata.", + priority: 60) + case "shell-snapshots": + self.make( + provider: .claude, + component: component, + title: "Manual cleanup: shell snapshots", + consequence: "Clearing removes leftover runtime shell snapshot files.", + priority: 70) + case "todos": + self.make( + provider: .claude, + component: component, + title: "Manual cleanup: legacy todos", + consequence: "Clearing removes legacy per-session task lists.", + priority: 80) + default: + nil + } + } + + private static func codexRecommendation( + for component: ProviderStorageFootprint.Component, + roots: [String]) + -> ProviderStorageRecommendation? + { + guard self.path(component.path, isContainedIn: roots) else { return nil } + + return switch component.name { + case "sessions": + self.make( + provider: .codex, + component: component, + title: "Manual cleanup: sessions", + consequence: "Clearing removes past Codex session history.", + priority: 10) + case "archived_sessions": + self.make( + provider: .codex, + component: component, + title: "Manual cleanup: archived sessions", + consequence: "Clearing removes archived Codex session history.", + priority: 20) + case "cache", "caches", "Cache", "Caches": + self.make( + provider: .codex, + component: component, + title: "Manual cleanup: cache", + consequence: "Clearing removes provider-owned cached data.", + priority: 30) + case "log", "logs", "debug": + self.make( + provider: .codex, + component: component, + title: "Manual cleanup: logs", + consequence: "Clearing removes local diagnostic logs.", + priority: 40) + case let name where name.hasPrefix("logs_") && name.hasSuffix(".sqlite"): + self.make( + provider: .codex, + component: component, + title: "Manual cleanup: logs", + consequence: "Clearing removes local diagnostic logs.", + priority: 40) + case "file-history": + self.make( + provider: .codex, + component: component, + title: "Manual cleanup: file history", + consequence: "Clearing removes local edit checkpoint history.", + priority: 50) + case "paste-cache", "image-cache", "session-env", "shell-snapshots", "shell_snapshots", "tmp", "temp", ".tmp": + self.make( + provider: .codex, + component: component, + title: "Manual cleanup: temporary data", + consequence: "Clearing removes local temporary provider data.", + priority: 60) + default: + nil + } + } + + private static func make( + provider: UsageProvider, + component: ProviderStorageFootprint.Component, + title: String, + consequence: String, + priority: Int) + -> ProviderStorageRecommendation + { + ProviderStorageRecommendation( + provider: provider, + path: component.path, + bytes: component.totalBytes, + title: title, + riskLevel: .manualCleanup, + consequence: consequence, + sortPriority: priority) + } + + private static func path(_ path: String, isContainedIn roots: [String]) -> Bool { + let standardizedPath = URL(fileURLWithPath: path).standardizedFileURL.path + return roots.contains { root in + let standardizedRoot = URL(fileURLWithPath: root, isDirectory: true).standardizedFileURL.path + return standardizedPath == standardizedRoot || standardizedPath.hasPrefix(standardizedRoot + "/") + } + } +} + +public enum ProviderStoragePathCatalog { + public static func candidatePaths( + for provider: UsageProvider, + environment: [String: String], + managedCodexAccounts: [ManagedCodexAccount] = [], + fileManager: FileManager = .default) + -> [String] + { + let home = fileManager.homeDirectoryForCurrentUser + + func homePath(_ relativePath: String) -> String { + home.appendingPathComponent(relativePath, isDirectory: true).path + } + + let candidates: [String] = switch provider { + case .codex: + [CodexHomeScope.ambientHomeURL(env: environment, fileManager: fileManager).path] + + managedCodexAccounts.map(\.managedHomePath) + case .claude: + [ + homePath(".claude"), + homePath(".config/claude"), + home + .appendingPathComponent("Library/Application Support/CodexBar/ClaudeProbe", isDirectory: true) + .path, + ] + case .gemini: + [ + homePath(".gemini"), + homePath(".config/gemini"), + ] + case .opencode, .opencodego: + [ + homePath(".config/opencode"), + ] + case .copilot: + [ + homePath(".config/github-copilot"), + ] + case .cursor: + [ + homePath("Library/Application Support/Cursor"), + homePath("Library/Application Support/Caches/cursor-updater"), + homePath(".cursor"), + homePath("Library/Caches/Cursor"), + homePath("Library/Caches/com.todesktop.230313mzl4w4u92"), + homePath("Library/Caches/com.todesktop.230313mzl4w4u92.ShipIt"), + homePath("Library/Caches/cursor-compile-cache"), + homePath("Library/HTTPStorages/com.todesktop.230313mzl4w4u92"), + ] + default: + [] + } + + return Self.uniqueStandardizedPaths(candidates) + } + + private static func uniqueStandardizedPaths(_ paths: [String]) -> [String] { + var seen: Set = [] + var result: [String] = [] + for path in paths { + let trimmed = path.trimmingCharacters(in: .whitespacesAndNewlines) + guard !trimmed.isEmpty else { continue } + let standardized = URL(fileURLWithPath: trimmed, isDirectory: true).standardizedFileURL.path + guard seen.insert(standardized).inserted else { continue } + result.append(standardized) + } + return result + } +} + +public struct ProviderStorageScanner: @unchecked Sendable { + private struct DirectoryScanResult { + var bytes: Int64 = 0 + var unreadablePaths: [String] = [] + var componentBytes: [String: Int64] = [:] + } + + private let fileManager: FileManager + + public init(fileManager: FileManager = .default) { + self.fileManager = fileManager + } + + public func scan( + provider: UsageProvider, + candidatePaths: [String], + now: Date = Date()) + -> ProviderStorageFootprint + { + var totalBytes: Int64 = 0 + var existingPaths: [String] = [] + var missingPaths: [String] = [] + var unreadablePaths: [String] = [] + var components: [ProviderStorageFootprint.Component] = [] + + for path in candidatePaths { + if Task.isCancelled { break } + var isDirectory: ObjCBool = false + guard self.fileManager.fileExists(atPath: path, isDirectory: &isDirectory) else { + missingPaths.append(path) + continue + } + + existingPaths.append(path) + let url = URL(fileURLWithPath: path, isDirectory: isDirectory.boolValue) + if self.isSymbolicLink(at: url) { + continue + } + if isDirectory.boolValue { + let result = self.scanDirectory(at: url) + if Task.isCancelled { break } + totalBytes += result.bytes + unreadablePaths.append(contentsOf: result.unreadablePaths) + components.append(contentsOf: result.componentBytes.map { + ProviderStorageFootprint.Component(path: $0.key, totalBytes: $0.value) + }) + } else { + let result = self.sizeOfFile(at: url) + totalBytes += result.bytes + unreadablePaths.append(contentsOf: result.unreadablePaths) + if result.bytes > 0 { + components.append(.init(path: url.path, totalBytes: result.bytes)) + } + } + } + + return ProviderStorageFootprint( + provider: provider, + totalBytes: totalBytes, + paths: existingPaths, + missingPaths: missingPaths, + unreadablePaths: unreadablePaths, + components: components.sorted { lhs, rhs in + if lhs.totalBytes == rhs.totalBytes { + return lhs.path.localizedCaseInsensitiveCompare(rhs.path) == .orderedAscending + } + return lhs.totalBytes > rhs.totalBytes + }, + updatedAt: now) + } + + private func isSymbolicLink(at url: URL) -> Bool { + (try? url.resourceValues(forKeys: [.isSymbolicLinkKey]).isSymbolicLink) == true + } + + private func sizeOfFile(at url: URL) -> (bytes: Int64, unreadablePaths: [String]) { + if Task.isCancelled { return (0, []) } + let keys: Set = [ + .isRegularFileKey, + .isSymbolicLinkKey, + .fileSizeKey, + ] + + guard let values = try? url.resourceValues(forKeys: keys) else { + return (0, [url.path]) + } + + if values.isSymbolicLink == true { + return (0, []) + } + + if values.isRegularFile == true { + return (Int64(values.fileSize ?? 0), []) + } + + return (0, []) + } + + private func scanDirectory(at url: URL) -> DirectoryScanResult { + if Task.isCancelled { return DirectoryScanResult() } + let keys: Set = [ + .isDirectoryKey, + .isRegularFileKey, + .isSymbolicLinkKey, + .fileSizeKey, + ] + + let unreadableCollector = ProviderStorageUnreadablePathCollector() + guard let enumerator = self.fileManager.enumerator( + at: url, + includingPropertiesForKeys: Array(keys), + options: [.skipsPackageDescendants], + errorHandler: { url, _ in + unreadableCollector.append(url.path) + return true + }) + else { + return DirectoryScanResult(unreadablePaths: [url.path]) + } + + var result = DirectoryScanResult() + let rootPath = url.standardizedFileURL.path + for case let itemURL as URL in enumerator { + if Task.isCancelled { + enumerator.skipDescendants() + break + } + guard let itemValues = try? itemURL.resourceValues(forKeys: keys) else { + unreadableCollector.append(itemURL.path) + continue + } + if itemValues.isSymbolicLink == true { + if itemValues.isDirectory == true { + enumerator.skipDescendants() + } + continue + } + if itemValues.isRegularFile == true { + let bytes = Int64(itemValues.fileSize ?? 0) + result.bytes += bytes + if bytes > 0, let componentPath = self.topLevelComponentPath(for: itemURL, rootPath: rootPath) { + result.componentBytes[componentPath, default: 0] += bytes + } + } + } + result.unreadablePaths = unreadableCollector.paths + return result + } + + private func topLevelComponentPath(for url: URL, rootPath: String) -> String? { + let itemPath = url.standardizedFileURL.path + let pathPrefix = rootPath.hasSuffix("/") ? rootPath : "\(rootPath)/" + guard itemPath.hasPrefix(pathPrefix) else { return nil } + let suffix = itemPath.dropFirst(pathPrefix.count) + let relative = suffix.drop { $0 == "/" } + guard let first = relative.split(separator: "/", maxSplits: 1, omittingEmptySubsequences: true).first else { + return nil + } + return URL(fileURLWithPath: rootPath, isDirectory: true) + .appendingPathComponent(String(first)) + .path + } +} + +private final class ProviderStorageUnreadablePathCollector: @unchecked Sendable { + private let lock = NSLock() + private var storage: [String] = [] + + var paths: [String] { + self.lock.lock() + defer { self.lock.unlock() } + return self.storage + } + + func append(_ path: String) { + self.lock.lock() + defer { self.lock.unlock() } + self.storage.append(path) + } +} diff --git a/Sources/CodexBarCore/Providers/APITokenFetchStrategy.swift b/Sources/CodexBarCore/Providers/APITokenFetchStrategy.swift new file mode 100644 index 0000000..8e33789 --- /dev/null +++ b/Sources/CodexBarCore/Providers/APITokenFetchStrategy.swift @@ -0,0 +1,72 @@ +import Foundation + +public struct APITokenFetchStrategy: ProviderFetchStrategy { + public typealias TokenResolver = @Sendable ([String: String]) -> String? + public typealias MissingCredentialsError = @Sendable () -> (any Error & Sendable) + public typealias UsageLoader = @Sendable (String, ProviderFetchContext) async throws -> UsageSnapshot + + public let id: String + public let kind: ProviderFetchKind = .apiToken + + private let sourceLabel: String + private let reportsMissingCredentials: Bool + private let resolveToken: TokenResolver + private let missingCredentialsError: MissingCredentialsError + private let loadUsage: UsageLoader + + public init( + id: String, + sourceLabel: String = "api", + reportsMissingCredentials: Bool = false, + resolveToken: @escaping TokenResolver, + missingCredentialsError: @escaping MissingCredentialsError, + loadUsage: @escaping UsageLoader) + { + self.id = id + self.sourceLabel = sourceLabel + self.reportsMissingCredentials = reportsMissingCredentials + self.resolveToken = resolveToken + self.missingCredentialsError = missingCredentialsError + self.loadUsage = loadUsage + } + + public func isAvailable(_ context: ProviderFetchContext) async -> Bool { + self.reportsMissingCredentials || self.resolveToken(context.env) != nil + } + + public func fetch(_ context: ProviderFetchContext) async throws -> ProviderFetchResult { + guard let token = self.resolveToken(context.env) else { + throw self.missingCredentialsError() + } + return try await self.makeResult( + usage: self.loadUsage(token, context), + sourceLabel: self.sourceLabel) + } + + public func shouldFallback(on _: Error, context _: ProviderFetchContext) -> Bool { + false + } +} + +extension ProviderFetchPlan { + public static func apiToken( + strategyID: String, + sourceLabel: String = "api", + reportsMissingCredentials: Bool = false, + resolveToken: @escaping APITokenFetchStrategy.TokenResolver, + missingCredentialsError: @escaping APITokenFetchStrategy.MissingCredentialsError, + loadUsage: @escaping APITokenFetchStrategy.UsageLoader) -> ProviderFetchPlan + { + ProviderFetchPlan( + sourceModes: [.auto, .api], + pipeline: ProviderFetchPipeline(resolveStrategies: { _ in + [APITokenFetchStrategy( + id: strategyID, + sourceLabel: sourceLabel, + reportsMissingCredentials: reportsMissingCredentials, + resolveToken: resolveToken, + missingCredentialsError: missingCredentialsError, + loadUsage: loadUsage)] + })) + } +} diff --git a/Sources/CodexBarCore/Providers/Abacus/AbacusCookieImporter.swift b/Sources/CodexBarCore/Providers/Abacus/AbacusCookieImporter.swift new file mode 100644 index 0000000..c32c8bb --- /dev/null +++ b/Sources/CodexBarCore/Providers/Abacus/AbacusCookieImporter.swift @@ -0,0 +1,134 @@ +import Foundation + +#if os(macOS) +import SweetCookieKit + +// MARK: - Abacus Cookie Importer + +public enum AbacusCookieImporter { + private static let log = CodexBarLog.logger(LogCategories.abacusCookie) + private static let cookieClient = BrowserCookieClient() + private static let cookieDomains = ["abacus.ai", "apps.abacus.ai"] + private static let cookieImportOrder: BrowserCookieImportOrder = + ProviderDefaults.metadata[.abacus]?.browserCookieOrder ?? Browser.defaultImportOrder + + /// Exact cookie names known to carry Abacus session state. + /// CSRF tokens are deliberately excluded — they are present in anonymous + /// jars and do not indicate an authenticated session. + private static let knownSessionCookieNames: Set = [ + "sessionid", "session_id", "session_token", + "auth_token", "access_token", + ] + + /// Substrings that indicate a session or auth cookie (applied only when + /// no exact-name match is found). Deliberately excludes overly broad + /// patterns like "id" and "token" that match analytics/CSRF cookies. + private static let sessionCookieSubstrings = ["session", "auth", "sid", "jwt"] + + /// Cookie name prefixes that indicate a non-session cookie even when a + /// substring match would otherwise accept it (e.g. "csrftoken"). + private static let excludedCookiePrefixes = ["csrf", "_ga", "_gid", "tracking", "analytics"] + + public struct SessionInfo: Sendable { + public let cookies: [HTTPCookie] + public let sourceLabel: String + + public init(cookies: [HTTPCookie], sourceLabel: String) { + self.cookies = cookies + self.sourceLabel = sourceLabel + } + + public var cookieHeader: String { + self.cookies.map { "\($0.name)=\($0.value)" }.joined(separator: "; ") + } + } + + /// Returns all candidate sessions across browsers/profiles, ordered by + /// import priority. Callers should try each in turn so that a stale + /// session in the first source doesn't block a valid one further down. + /// + /// Defaults to Chrome-only per AGENTS.md guideline. Pass an empty + /// `preferredBrowsers` list to fall back to the full descriptor-defined + /// import order (Safari, Firefox, etc.) when Chrome has no cookies. + public static func importSessions( + browserDetection: BrowserDetection = BrowserDetection(), + preferredBrowsers: [Browser] = [.chrome], + logger: ((String) -> Void)? = nil) throws -> [SessionInfo] + { + var candidates: [SessionInfo] = [] + let installedBrowsers = preferredBrowsers.isEmpty + ? self.cookieImportOrder.cookieImportCandidates(using: browserDetection) + : preferredBrowsers.cookieImportCandidates(using: browserDetection) + + for browserSource in installedBrowsers { + do { + let query = BrowserCookieQuery(domains: self.cookieDomains) + let sources = try Self.cookieClient.codexBarRecords( + matching: query, + in: browserSource, + logger: { msg in self.emit(msg, logger: logger) }) + for source in sources where !source.records.isEmpty { + let httpCookies = BrowserCookieClient.makeHTTPCookies(source.records, origin: query.origin) + guard !httpCookies.isEmpty else { continue } + + guard Self.containsSessionCookie(httpCookies) else { + self.emit( + "Skipping \(source.label): no session cookie found", + logger: logger) + continue + } + + self.emit( + "Found \(httpCookies.count) session cookies in \(source.label)", + logger: logger) + candidates.append(SessionInfo(cookies: httpCookies, sourceLabel: source.label)) + } + } catch { + BrowserCookieAccessGate.recordIfNeeded(error) + self.emit( + "\(browserSource.displayName) cookie import failed: \(error.localizedDescription)", + logger: logger) + } + } + + guard !candidates.isEmpty else { + throw AbacusUsageError.noSessionCookie + } + return candidates + } + + /// Cheap check for whether any browser has an Abacus session cookie, + /// used by the fetch strategy's `isAvailable()`. + public static func hasSession( + browserDetection: BrowserDetection = BrowserDetection(), + preferredBrowsers: [Browser] = [.chrome], + logger: ((String) -> Void)? = nil) -> Bool + { + do { + return try !self.importSessions( + browserDetection: browserDetection, + preferredBrowsers: preferredBrowsers, + logger: logger).isEmpty + } catch { + return false + } + } + + /// Returns `true` if the cookie set contains at least one cookie whose name + /// indicates session or authentication state. Checks exact known names + /// first, then falls back to conservative substring matching. + private static func containsSessionCookie(_ cookies: [HTTPCookie]) -> Bool { + cookies.contains { cookie in + let lower = cookie.name.lowercased() + if self.knownSessionCookieNames.contains(lower) { return true } + if self.excludedCookiePrefixes.contains(where: { lower.hasPrefix($0) }) { return false } + return self.sessionCookieSubstrings.contains { lower.contains($0) } + } + } + + private static func emit(_ message: String, logger: ((String) -> Void)?) { + logger?("[abacus-cookie] \(message)") + self.log.debug(message) + } +} +#endif diff --git a/Sources/CodexBarCore/Providers/Abacus/AbacusProviderDescriptor.swift b/Sources/CodexBarCore/Providers/Abacus/AbacusProviderDescriptor.swift new file mode 100644 index 0000000..2afe1dd --- /dev/null +++ b/Sources/CodexBarCore/Providers/Abacus/AbacusProviderDescriptor.swift @@ -0,0 +1,91 @@ +import Foundation + +#if os(macOS) +import SweetCookieKit +#endif + +public enum AbacusProviderDescriptor { + public static let descriptor: ProviderDescriptor = Self.makeDescriptor() + + static func makeDescriptor() -> ProviderDescriptor { + ProviderDescriptor( + id: .abacus, + metadata: ProviderMetadata( + id: .abacus, + displayName: "Abacus AI", + sessionLabel: "Credits", + weeklyLabel: "Weekly", + opusLabel: nil, + supportsOpus: false, + supportsCredits: false, + creditsHint: "", + toggleTitle: "Show Abacus AI usage", + cliName: "abacusai", + defaultEnabled: false, + isPrimaryProvider: false, + usesAccountFallback: false, + browserCookieOrder: ProviderBrowserCookieDefaults.defaultImportOrder, + dashboardURL: "https://apps.abacus.ai/chatllm/admin/compute-points-usage", + statusPageURL: nil, + statusLinkURL: nil), + branding: ProviderBranding( + iconStyle: .abacus, + iconResourceName: "ProviderIcon-abacus", + color: ProviderColor(red: 56 / 255, green: 189 / 255, blue: 248 / 255)), + tokenCost: ProviderTokenCostConfig( + supportsTokenCost: false, + noDataMessage: { "Abacus AI cost summary is not supported." }), + fetchPlan: ProviderFetchPlan( + sourceModes: [.auto, .web], + pipeline: ProviderFetchPipeline(resolveStrategies: { _ in + [AbacusWebFetchStrategy()] + })), + cli: ProviderCLIConfig( + name: "abacusai", + aliases: ["abacus-ai"], + versionDetector: nil)) + } +} + +// MARK: - Fetch Strategy + +struct AbacusWebFetchStrategy: ProviderFetchStrategy { + let id: String = "abacus.web" + let kind: ProviderFetchKind = .web + + func isAvailable(_ context: ProviderFetchContext) async -> Bool { + context.settings?.abacus?.cookieSource != .off + } + + func fetch(_ context: ProviderFetchContext) async throws -> ProviderFetchResult { + let manual: String? + if context.settings?.abacus?.cookieSource == .manual { + guard let header = Self.manualCookieHeader(from: context) else { + throw AbacusUsageError.noSessionCookie + } + manual = header + } else { + manual = nil + } + let logger: ((String) -> Void)? = context.verbose + ? { msg in CodexBarLog.logger(LogCategories.abacusUsage).verbose(msg) } + : nil + let snap = try await AbacusUsageFetcher.fetchUsage( + cookieHeaderOverride: manual, + browserDetection: context.browserDetection, + timeout: context.webTimeout, + logger: logger) + return self.makeResult( + usage: snap.toUsageSnapshot(), + sourceLabel: "web") + } + + func shouldFallback(on _: Error, context _: ProviderFetchContext) -> Bool { + false + } + + private static func manualCookieHeader(from context: ProviderFetchContext) -> String? { + guard context.settings?.abacus?.cookieSource == .manual else { return nil } + return CookieHeaderNormalizer.normalize(context.settings?.abacus?.manualCookieHeader) + } +} diff --git a/Sources/CodexBarCore/Providers/Abacus/AbacusUsageError.swift b/Sources/CodexBarCore/Providers/Abacus/AbacusUsageError.swift new file mode 100644 index 0000000..0f5c6cc --- /dev/null +++ b/Sources/CodexBarCore/Providers/Abacus/AbacusUsageError.swift @@ -0,0 +1,67 @@ +import Foundation + +// MARK: - Abacus Usage Error + +public enum AbacusUsageError: LocalizedError, Sendable, Equatable { + case noSessionCookie + case sessionExpired + case networkError(String) + case parseFailed(String) + case unauthorized + + /// Whether this error indicates an authentication/session problem that + /// should trigger cache eviction. + public var isRecoverable: Bool { + switch self { + case .unauthorized, .sessionExpired: true + default: false + } + } + + public var isAuthRelated: Bool { + self.isRecoverable + } + + /// Whether browser-import scanning should continue to later sessions after + /// this failure. Imported sessions can differ by profile/browser, so we keep + /// scanning on per-session fetch failures and surface the first one only if + /// every candidate is exhausted. + var shouldTryNextImportedSession: Bool { + switch self { + case .unauthorized, .sessionExpired, .networkError, .parseFailed: true + case .noSessionCookie: false + } + } + + /// Whether a cached cookie header should be evicted before falling back to + /// a fresh browser import. Parse/auth failures usually indicate that the + /// cached session is stale or no longer accepted. + var shouldClearCachedCookie: Bool { + switch self { + case .unauthorized, .sessionExpired, .parseFailed: true + case .networkError, .noSessionCookie: false + } + } + + public var errorDescription: String? { + switch self { + case .noSessionCookie: + "No Abacus AI session found. Please log in to apps.abacus.ai in your browser " + + "or paste a Cookie header in manual mode." + case .sessionExpired: + "Abacus AI session expired. Please log in again." + case let .networkError(msg): + "Abacus AI API error: \(msg)" + case let .parseFailed(msg): + "Could not parse Abacus AI usage: \(msg)" + case .unauthorized: + "Unauthorized. Please log in to Abacus AI." + } + } +} + +#if !os(macOS) +extension AbacusUsageError { + public static let notSupported = AbacusUsageError.networkError("Abacus AI is only supported on macOS.") +} +#endif diff --git a/Sources/CodexBarCore/Providers/Abacus/AbacusUsageFetcher.swift b/Sources/CodexBarCore/Providers/Abacus/AbacusUsageFetcher.swift new file mode 100644 index 0000000..1c449d4 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Abacus/AbacusUsageFetcher.swift @@ -0,0 +1,336 @@ +import Foundation + +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +#if os(macOS) +import SweetCookieKit + +// MARK: - Abacus Usage Fetcher + +public enum AbacusUsageFetcher { + private struct BrowserFetchRequest { + let browserDetection: BrowserDetection + let preferredBrowsers: [Browser] + let label: String + let timeout: TimeInterval + let logger: ((String) -> Void)? + } + + /// Parsed JSON dictionaries are treated as immutable snapshots here and are + /// only moved between sibling fetch tasks before being consumed locally. + private struct JSONDictionaryBox: @unchecked Sendable { + let value: [String: Any] + } + + private static let log = CodexBarLog.logger(LogCategories.abacusUsage) + private static let computePointsURL = + URL(string: "https://apps.abacus.ai/api/_getOrganizationComputePoints")! + private static let billingInfoURL = + URL(string: "https://apps.abacus.ai/api/_getBillingInfo")! + + public static func fetchUsage( + cookieHeaderOverride: String? = nil, + browserDetection: BrowserDetection = BrowserDetection(), + timeout: TimeInterval = 15.0, + logger: ((String) -> Void)? = nil) async throws -> AbacusUsageSnapshot + { + // Manual cookie header — no fallback, errors propagate directly + if let override = CookieHeaderNormalizer.normalize(cookieHeaderOverride) { + self.emit("Using manual cookie header", logger: logger) + return try await self.fetchWithCookieHeader(override, timeout: timeout, logger: logger) + } + + // Cached cookie header — fall back to a fresh browser import when the + // cached session is rejected or looks stale. + if let cached = CookieHeaderCache.load(provider: .abacus), + !cached.cookieHeader.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty + { + self.emit("Using cached cookie header from \(cached.sourceLabel)", logger: logger) + do { + return try await self.fetchWithCookieHeader( + cached.cookieHeader, timeout: timeout, logger: logger) + } catch let error as AbacusUsageError where error.shouldTryNextImportedSession { + if error.shouldClearCachedCookie { + CookieHeaderCache.clear(provider: .abacus) + self.emit( + "Cached cookie failed (\(error.localizedDescription)); cleared, trying fresh import", + logger: logger) + } else { + self.emit( + "Cached cookie failed (\(error.localizedDescription)); trying fresh import", + logger: logger) + } + } + } + + // Fresh browser import — try Chrome first (AGENTS.md default), then broaden + // to all browsers if Chrome has no sessions OR if every imported Chrome + // session is exhausted without a successful fetch. + var lastError: AbacusUsageError = .noSessionCookie + if let snapshot = try await self.tryFetchFromBrowsers( + BrowserFetchRequest( + browserDetection: browserDetection, + preferredBrowsers: [.chrome], + label: "Chrome", + timeout: timeout, + logger: logger), + lastError: &lastError) + { + return snapshot + } + + self.emit("Chrome sessions exhausted; falling back to all browsers", logger: logger) + if let snapshot = try await self.tryFetchFromBrowsers( + BrowserFetchRequest( + browserDetection: browserDetection, + preferredBrowsers: [], + label: "all browsers", + timeout: timeout, + logger: logger), + lastError: &lastError) + { + return snapshot + } + + throw lastError + } + + /// Tries to import sessions from `preferredBrowsers` and fetch usage. Returns + /// the snapshot on success, nil if no sessions were available or every + /// imported session was exhausted without success. + private static func tryFetchFromBrowsers( + _ request: BrowserFetchRequest, + lastError: inout AbacusUsageError) async throws -> AbacusUsageSnapshot? + { + let sessions: [AbacusCookieImporter.SessionInfo] + do { + sessions = try AbacusCookieImporter.importSessions( + browserDetection: request.browserDetection, + preferredBrowsers: request.preferredBrowsers, + logger: request.logger) + } catch { + BrowserCookieAccessGate.recordIfNeeded(error) + self.emit( + "\(request.label) cookie import failed: \(error.localizedDescription)", + logger: request.logger) + return nil + } + + for session in sessions { + self.emit("Trying cookies from \(session.sourceLabel)", logger: request.logger) + do { + let snapshot = try await self.fetchWithCookieHeader( + session.cookieHeader, + timeout: request.timeout, + logger: request.logger) + CookieHeaderCache.store( + provider: .abacus, + cookieHeader: session.cookieHeader, + sourceLabel: session.sourceLabel) + return snapshot + } catch let error as AbacusUsageError where error.shouldTryNextImportedSession { + self.emit( + "\(session.sourceLabel): \(error.localizedDescription), trying next source", + logger: request.logger) + lastError = error + continue + } catch { + self.emit( + "\(session.sourceLabel): \(error.localizedDescription), trying next source", + logger: request.logger) + lastError = .networkError(error.localizedDescription) + continue + } + } + return nil + } + + // MARK: - API Requests + + private static func fetchWithCookieHeader( + _ cookieHeader: String, + timeout: TimeInterval, + logger: ((String) -> Void)? = nil) async throws -> AbacusUsageSnapshot + { + enum FetchPart: Sendable { + case computePoints(JSONDictionaryBox) + case billingInfoSuccess(JSONDictionaryBox) + case billingInfoFailure(String) + } + + // Fetch compute points (required, full timeout) and billing info + // (optional, shorter budget) concurrently. Billing is bounded so a + // slow/flaky billing endpoint can't delay credit rendering. + let billingBudget = min(timeout, 5.0) + + var computePointsResult: [String: Any]? + var billingInfoResult: [String: Any] = [:] + + try await withThrowingTaskGroup(of: FetchPart.self) { group in + group.addTask { + let result = try await self.fetchJSON( + url: self.computePointsURL, + method: "GET", + cookieHeader: cookieHeader, + timeout: timeout) + return .computePoints(JSONDictionaryBox(value: result)) + } + group.addTask { + do { + let result = try await self.fetchJSON( + url: self.billingInfoURL, + method: "POST", + cookieHeader: cookieHeader, + timeout: billingBudget) + return .billingInfoSuccess(JSONDictionaryBox(value: result)) + } catch { + return .billingInfoFailure(error.localizedDescription) + } + } + + while let result = try await group.next() { + switch result { + case let .computePoints(value): + computePointsResult = value.value + case let .billingInfoSuccess(value): + billingInfoResult = value.value + case let .billingInfoFailure(message): + self.emit( + "Billing info fetch failed: \(message); credits shown without plan/reset", + logger: logger) + } + } + } + + guard let computePointsResult else { + throw AbacusUsageError.networkError("Abacus compute points fetch did not complete") + } + + return try self.parseResults(computePoints: computePointsResult, billingInfo: billingInfoResult) + } + + private static func fetchJSON( + url: URL, method: String, cookieHeader: String, timeout: TimeInterval) async throws -> [String: Any] + { + var request = URLRequest(url: url) + request.httpMethod = method + request.timeoutInterval = timeout + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + request.setValue("application/json", forHTTPHeaderField: "Accept") + request.setValue(cookieHeader, forHTTPHeaderField: "Cookie") + if method == "POST" { + request.httpBody = Data("{}".utf8) + } + + let response = try await ProviderHTTPClient.shared.response(for: request) + let data = response.data + let statusCode = response.statusCode + + if statusCode == 401 || statusCode == 403 { + throw AbacusUsageError.unauthorized + } + + guard statusCode == 200 else { + let body = String(data: data.prefix(200), encoding: .utf8) ?? "" + throw AbacusUsageError.networkError("HTTP \(statusCode): \(body)") + } + + let parsed: Any + do { + parsed = try JSONSerialization.jsonObject(with: data) + } catch { + let preview = String(data: data.prefix(200), encoding: .utf8) ?? "" + throw AbacusUsageError.parseFailed( + "\(url.lastPathComponent): \(error.localizedDescription) — preview: \(preview)") + } + + guard let root = parsed as? [String: Any] else { + throw AbacusUsageError.parseFailed("\(url.lastPathComponent): top-level JSON is not a dictionary") + } + + guard root["success"] as? Bool == true, + let result = root["result"] as? [String: Any] + else { + let errorMsg = (root["error"] as? String ?? "Unknown error").lowercased() + if errorMsg.contains("expired") || errorMsg.contains("session") + || errorMsg.contains("login") || errorMsg.contains("authenticate") + || errorMsg.contains("unauthorized") || errorMsg.contains("unauthenticated") + || errorMsg.contains("forbidden") + { + throw AbacusUsageError.unauthorized + } + throw AbacusUsageError.parseFailed("\(url.lastPathComponent): \(errorMsg)") + } + + return result + } + + // MARK: - Parsing + + private static func parseResults( + computePoints: [String: Any], billingInfo: [String: Any]) throws -> AbacusUsageSnapshot + { + let totalCredits = self.double(from: computePoints["totalComputePoints"]) + let creditsLeft = self.double(from: computePoints["computePointsLeft"]) + + guard let totalCredits, let creditsLeft else { + let keys = computePoints.keys.sorted().joined(separator: ", ") + throw AbacusUsageError.parseFailed( + "Missing credit fields in compute points response. Keys: [\(keys)]") + } + + let creditsUsed = totalCredits - creditsLeft + + let nextBillingDate = billingInfo["nextBillingDate"] as? String + let currentTier = billingInfo["currentTier"] as? String + let resetsAt = self.parseDate(nextBillingDate) + + return AbacusUsageSnapshot( + creditsUsed: creditsUsed, + creditsTotal: totalCredits, + resetsAt: resetsAt, + planName: currentTier) + } + + private static func double(from value: Any?) -> Double? { + if let d = value as? Double { return d } + if let i = value as? Int { return Double(i) } + if let n = value as? NSNumber { return n.doubleValue } + return nil + } + + private static func parseDate(_ isoString: String?) -> Date? { + guard let isoString else { return nil } + let formatter = ISO8601DateFormatter() + formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds] + if let date = formatter.date(from: isoString) { return date } + formatter.formatOptions = [.withInternetDateTime] + return formatter.date(from: isoString) + } + + // MARK: - Logging + + private static func emit(_ message: String, logger: ((String) -> Void)?) { + logger?("[abacus] \(message)") + self.log.debug(message) + } +} + +#else + +// MARK: - Abacus (Unsupported) + +public enum AbacusUsageFetcher { + public static func fetchUsage( + cookieHeaderOverride _: String? = nil, + browserDetection _: BrowserDetection = BrowserDetection(), + timeout _: TimeInterval = 15.0, + logger _: ((String) -> Void)? = nil) async throws -> AbacusUsageSnapshot + { + throw AbacusUsageError.notSupported + } +} + +#endif diff --git a/Sources/CodexBarCore/Providers/Abacus/AbacusUsageSnapshot.swift b/Sources/CodexBarCore/Providers/Abacus/AbacusUsageSnapshot.swift new file mode 100644 index 0000000..0186844 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Abacus/AbacusUsageSnapshot.swift @@ -0,0 +1,77 @@ +import Foundation + +// MARK: - Abacus Usage Snapshot + +public struct AbacusUsageSnapshot: Sendable { + public let creditsUsed: Double? + public let creditsTotal: Double? + public let resetsAt: Date? + public let planName: String? + + public init( + creditsUsed: Double? = nil, + creditsTotal: Double? = nil, + resetsAt: Date? = nil, + planName: String? = nil) + { + self.creditsUsed = creditsUsed + self.creditsTotal = creditsTotal + self.resetsAt = resetsAt + self.planName = planName + } + + public func toUsageSnapshot() -> UsageSnapshot { + let percentUsed: Double = if let used = self.creditsUsed, let total = self.creditsTotal, total > 0 { + (used / total) * 100.0 + } else { + 0 + } + + let resetDesc: String? = if let used = self.creditsUsed, let total = self.creditsTotal { + "\(Self.formatCredits(used)) / \(Self.formatCredits(total)) credits" + } else { + nil + } + + // Derive window from actual billing cycle when possible. + // Assume the cycle started one calendar month before resetsAt. + let windowMinutes: Int = if let resetDate = self.resetsAt, + let cycleStart = Calendar.current.date(byAdding: .month, value: -1, to: resetDate) + { + max(1, Int(resetDate.timeIntervalSince(cycleStart) / 60)) + } else { + 30 * 24 * 60 + } + + let primary = RateWindow( + usedPercent: percentUsed, + windowMinutes: windowMinutes, + resetsAt: self.resetsAt, + resetDescription: resetDesc) + + let identity = ProviderIdentitySnapshot( + providerID: .abacus, + accountEmail: nil, + accountOrganization: nil, + loginMethod: self.planName) + + return UsageSnapshot( + primary: primary, + secondary: nil, + tertiary: nil, + providerCost: nil, + updatedAt: Date(), + identity: identity) + } + + // MARK: - Formatting + + /// Thread-safe credit formatting — allocates per call to avoid shared mutable state. + private static func formatCredits(_ value: Double) -> String { + let formatter = NumberFormatter() + formatter.numberStyle = .decimal + formatter.locale = Locale(identifier: "en_US") + formatter.maximumFractionDigits = value >= 1000 ? 0 : 1 + return formatter.string(from: NSNumber(value: value)) ?? String(format: "%.0f", value) + } +} diff --git a/Sources/CodexBarCore/Providers/Alibaba/AlibabaCodingPlanAPIRegion.swift b/Sources/CodexBarCore/Providers/Alibaba/AlibabaCodingPlanAPIRegion.swift new file mode 100644 index 0000000..d86585a --- /dev/null +++ b/Sources/CodexBarCore/Providers/Alibaba/AlibabaCodingPlanAPIRegion.swift @@ -0,0 +1,133 @@ +import Foundation + +public enum AlibabaCodingPlanAPIRegion: String, CaseIterable, Sendable { + case international = "intl" + case chinaMainland = "cn" + + private static let endpointPath = "data/api.json" + + public var displayName: String { + switch self { + case .international: + "International (modelstudio.console.alibabacloud.com)" + case .chinaMainland: + "China mainland (bailian.console.aliyun.com)" + } + } + + public var gatewayBaseURLString: String { + switch self { + case .international: + "https://modelstudio.console.alibabacloud.com" + case .chinaMainland: + "https://bailian.console.aliyun.com" + } + } + + public var dashboardURL: URL { + switch self { + case .international: + URL( + string: "https://modelstudio.console.alibabacloud.com/ap-southeast-1/?tab=coding-plan#/efm/coding_plan")! + case .chinaMainland: + URL(string: "https://bailian.console.aliyun.com/cn-beijing/?tab=model#/efm/coding_plan")! + } + } + + public var consoleDomain: String { + switch self { + case .international: + "modelstudio.console.alibabacloud.com" + case .chinaMainland: + "bailian.console.aliyun.com" + } + } + + public var consoleSite: String { + switch self { + case .international: + "MODELSTUDIO_ALIBABACLOUD" + case .chinaMainland: + "BAILIAN_ALIYUN" + } + } + + public var consoleRefererURL: URL { + switch self { + case .international: + URL(string: "https://modelstudio.console.alibabacloud.com/ap-southeast-1/?tab=coding-plan")! + case .chinaMainland: + URL(string: "https://bailian.console.aliyun.com/cn-beijing/?tab=model")! + } + } + + public var quotaURL: URL { + var components = URLComponents(string: self.gatewayBaseURLString)! + components.path = "/" + Self.endpointPath + components.queryItems = [ + URLQueryItem( + name: "action", + value: "zeldaEasy.broadscope-bailian.codingPlan.queryCodingPlanInstanceInfoV2"), + URLQueryItem(name: "product", value: "broadscope-bailian"), + URLQueryItem(name: "api", value: "queryCodingPlanInstanceInfoV2"), + URLQueryItem(name: "currentRegionId", value: self.currentRegionID), + ] + return components.url! + } + + public var consoleRPCBaseURLString: String { + switch self { + case .international: + "https://bailian-singapore-cs.alibabacloud.com" + case .chinaMainland: + "https://bailian-cs.console.aliyun.com" + } + } + + public var consoleRPCURL: URL { + var components = URLComponents(string: self.consoleRPCBaseURLString)! + components.path = "/" + Self.endpointPath + components.queryItems = [ + URLQueryItem(name: "action", value: self.consoleRPCAction), + URLQueryItem(name: "product", value: self.consoleRPCProduct), + URLQueryItem(name: "api", value: self.consoleQuotaAPIName), + URLQueryItem(name: "_v", value: "undefined"), + ] + return components.url! + } + + public var consoleRPCAction: String { + switch self { + case .international: + "IntlBroadScopeAspnGateway" + case .chinaMainland: + "BroadScopeAspnGateway" + } + } + + public var consoleRPCProduct: String { + "sfm_bailian" + } + + public var consoleQuotaAPIName: String { + "zeldaEasy.broadscope-bailian.codingPlan.queryCodingPlanInstanceInfoV2" + } + + public var commodityCode: String { + switch self { + case .international: + "sfm_codingplan_public_intl" + case .chinaMainland: + "sfm_codingplan_public_cn" + } + } + + public var currentRegionID: String { + switch self { + case .international: + "ap-southeast-1" + case .chinaMainland: + "cn-beijing" + } + } +} diff --git a/Sources/CodexBarCore/Providers/Alibaba/AlibabaCodingPlanCookieImporter.swift b/Sources/CodexBarCore/Providers/Alibaba/AlibabaCodingPlanCookieImporter.swift new file mode 100644 index 0000000..1eb1e1f --- /dev/null +++ b/Sources/CodexBarCore/Providers/Alibaba/AlibabaCodingPlanCookieImporter.swift @@ -0,0 +1,510 @@ +import Foundation + +#if os(macOS) +import CommonCrypto +import Security +import SQLite3 +import SweetCookieKit + +private let alibabaCookieImportOrder: BrowserCookieImportOrder = + ProviderDefaults.metadata[.alibaba]?.browserCookieOrder ?? Browser.defaultImportOrder + +public enum AlibabaCodingPlanCookieImporter { + private static let cookieClient = BrowserCookieClient() + private static let cookieDomains = [ + "bailian-singapore-cs.alibabacloud.com", + "bailian-cs.console.aliyun.com", + "bailian-beijing-cs.aliyuncs.com", + "modelstudio.console.alibabacloud.com", + "bailian.console.aliyun.com", + "free.aliyun.com", + "account.aliyun.com", + "signin.aliyun.com", + "passport.alibabacloud.com", + "console.alibabacloud.com", + "console.aliyun.com", + "alibabacloud.com", + "aliyun.com", + ] + + public struct SessionInfo: Sendable { + public let cookies: [HTTPCookie] + public let sourceLabel: String + + public init(cookies: [HTTPCookie], sourceLabel: String) { + self.cookies = cookies + self.sourceLabel = sourceLabel + } + + public var cookieHeader: String { + var byName: [String: HTTPCookie] = [:] + byName.reserveCapacity(self.cookies.count) + + for cookie in self.cookies { + if let expiry = cookie.expiresDate, expiry < Date() { + continue + } + guard !cookie.value.isEmpty else { continue } + if let existing = byName[cookie.name] { + let existingExpiry = existing.expiresDate ?? .distantPast + let candidateExpiry = cookie.expiresDate ?? .distantPast + if candidateExpiry >= existingExpiry { + byName[cookie.name] = cookie + } + } else { + byName[cookie.name] = cookie + } + } + + return byName.keys.sorted().compactMap { name in + guard let cookie = byName[name] else { return nil } + return "\(cookie.name)=\(cookie.value)" + }.joined(separator: "; ") + } + } + + nonisolated(unsafe) static var importSessionOverrideForTesting: + ((BrowserDetection, ((String) -> Void)?) throws -> SessionInfo)? + + public static func importSession( + browserDetection: BrowserDetection, + logger: ((String) -> Void)? = nil) throws -> SessionInfo + { + if let override = self.importSessionOverrideForTesting { + return try override(browserDetection, logger) + } + let log: (String) -> Void = { msg in logger?("[alibaba-cookie] \(msg)") } + var accessDeniedHints: [String] = [] + var failureDetails: [String] = [] + let installedBrowsers = self.cookieImportCandidates(browserDetection: browserDetection) + log("Cookie import candidates: \(installedBrowsers.map(\.displayName).joined(separator: ", "))") + + for browserSource in installedBrowsers { + do { + log("Checking \(browserSource.displayName)") + let query = BrowserCookieQuery(domains: self.cookieDomains) + let sources = try Self.cookieClient.codexBarRecords( + matching: query, + in: browserSource, + logger: log) + if sources.isEmpty { + log("No matching cookie records in \(browserSource.displayName)") + if let fallbackSession = try Self.importChromiumFallbackSession( + browser: browserSource, + logger: log) + { + return fallbackSession + } + } + for source in sources where !source.records.isEmpty { + let httpCookies = BrowserCookieClient.makeHTTPCookies(source.records, origin: query.origin) + if self.isAuthenticatedSession(cookies: httpCookies) { + log("Found \(httpCookies.count) Alibaba cookies in \(source.label)") + return SessionInfo(cookies: httpCookies, sourceLabel: source.label) + } + let cookieNames = Set(httpCookies.map(\.name)) + let hasTicket = cookieNames.contains("login_aliyunid_ticket") + let hasAccount = + cookieNames.contains("login_aliyunid_pk") || + cookieNames.contains("login_current_pk") || + cookieNames.contains("login_aliyunid") + log("Skipping \(source.label): missing auth cookies (ticket=\(hasTicket), account=\(hasAccount))") + } + if let fallbackSession = try Self.importChromiumFallbackSession(browser: browserSource, logger: log) { + return fallbackSession + } + } catch let error as BrowserCookieError { + BrowserCookieAccessGate.recordIfNeeded(error) + if let hint = error.accessDeniedHint { + accessDeniedHints.append(hint) + } + failureDetails.append("\(browserSource.displayName): \(error.localizedDescription)") + log("\(browserSource.displayName) cookie import failed: \(error.localizedDescription)") + } catch { + failureDetails.append("\(browserSource.displayName): \(error.localizedDescription)") + log("\(browserSource.displayName) cookie import failed: \(error.localizedDescription)") + } + } + + let details = (Array(Set(accessDeniedHints)).sorted() + Array(Set(failureDetails)).sorted()) + .joined(separator: " ") + throw AlibabaCodingPlanSettingsError.missingCookie(details: details.isEmpty ? nil : details) + } + + private static func isAuthenticatedSession(cookies: [HTTPCookie]) -> Bool { + guard !cookies.isEmpty else { return false } + let names = Set(cookies.map(\.name)) + let hasTicket = names.contains("login_aliyunid_ticket") + let hasAccount = + names.contains("login_aliyunid_pk") || + names.contains("login_current_pk") || + names.contains("login_aliyunid") + return hasTicket && hasAccount + } + + public static func hasSession( + browserDetection: BrowserDetection, + logger: ((String) -> Void)? = nil) -> Bool + { + do { + _ = try self.importSession(browserDetection: browserDetection, logger: logger) + return true + } catch { + return false + } + } + + private static func importChromiumFallbackSession( + browser: Browser, + logger: ((String) -> Void)? = nil) throws -> SessionInfo? + { + guard browser.usesChromiumProfileStore else { return nil } + return try AlibabaChromiumCookieFallbackImporter.importSession( + browser: browser, + domains: self.cookieDomains, + logger: logger) + } + + static func cookieImportCandidates( + browserDetection: BrowserDetection, + importOrder: BrowserCookieImportOrder = alibabaCookieImportOrder) -> [Browser] + { + importOrder.cookieImportCandidates(using: browserDetection) + } + + static func matchesCookieDomain(_ domain: String, patterns: [String] = Self.cookieDomains) -> Bool { + let normalized = self.normalizeCookieDomain(domain) + return patterns.contains { pattern in + let normalizedPattern = self.normalizeCookieDomain(pattern) + return normalized == normalizedPattern || normalized.hasSuffix(".\(normalizedPattern)") + } + } + + static func normalizeCookieDomain(_ domain: String) -> String { + let trimmed = domain.trimmingCharacters(in: .whitespacesAndNewlines) + let normalized = trimmed.hasPrefix(".") ? String(trimmed.dropFirst()) : trimmed + return normalized.lowercased() + } +} + +enum AlibabaChromiumCookieFallbackImporter { + private struct ChromiumCookieRecord { + let domain: String + let name: String + let path: String + let value: String + let expires: Date? + let isSecure: Bool + } + + enum ImportError: LocalizedError { + case keyUnavailable(browser: Browser) + case keychainDenied(browser: Browser) + case sqliteFailed(label: String, details: String) + + var errorDescription: String? { + switch self { + case let .keyUnavailable(browser): + "\(browser.displayName) Safe Storage key not found." + case let .keychainDenied(browser): + "macOS Keychain denied access to \(browser.displayName) Safe Storage." + case let .sqliteFailed(label, details): + "\(label) cookie fallback failed: \(details)" + } + } + } + + static func importSession( + browser: Browser, + domains: [String], + cookieClient: BrowserCookieClient = BrowserCookieClient(), + logger: ((String) -> Void)? = nil) throws -> AlibabaCodingPlanCookieImporter.SessionInfo? + { + let stores = try cookieClient.codexBarStores(for: browser).filter { $0.databaseURL != nil } + guard !stores.isEmpty else { return nil } + + logger?("[alibaba-cookie] Trying \(browser.displayName) Chromium fallback") + let keys = try self.derivedKeys(for: browser) + for store in stores { + let cookies = try self.loadCookies(from: store, domains: domains, keys: keys) + guard !cookies.isEmpty else { continue } + if self.isAuthenticatedSession(cookies) { + logger?("[alibaba-cookie] Found \(cookies.count) Alibaba cookies via \(store.label) fallback") + return AlibabaCodingPlanCookieImporter.SessionInfo(cookies: cookies, sourceLabel: store.label) + } + } + return nil + } + + private static func isAuthenticatedSession(_ cookies: [HTTPCookie]) -> Bool { + let names = Set(cookies.map(\.name)) + let hasTicket = names.contains("login_aliyunid_ticket") + let hasAccount = + names.contains("login_aliyunid_pk") || + names.contains("login_current_pk") || + names.contains("login_aliyunid") + return hasTicket && hasAccount + } + + private static func loadCookies( + from store: BrowserCookieStore, + domains: [String], + keys: [Data]) throws -> [HTTPCookie] + { + guard let sourceDB = store.databaseURL else { return [] } + let records = try self.readCookiesFromLockedDB( + sourceDB: sourceDB, + domains: domains, + keys: keys, + label: store.label) + return records.compactMap(self.makeCookie) + } + + private static func readCookiesFromLockedDB( + sourceDB: URL, + domains: [String], + keys: [Data], + label: String) throws -> [ChromiumCookieRecord] + { + let tempDir = FileManager.default.temporaryDirectory + .appendingPathComponent("alibaba-chromium-cookies-\(UUID().uuidString)", isDirectory: true) + try FileManager.default.createDirectory(at: tempDir, withIntermediateDirectories: true) + + let copiedDB = tempDir.appendingPathComponent("Cookies") + try FileManager.default.copyItem(at: sourceDB, to: copiedDB) + for suffix in ["-wal", "-shm"] { + let src = URL(fileURLWithPath: sourceDB.path + suffix) + if FileManager.default.fileExists(atPath: src.path) { + let dst = URL(fileURLWithPath: copiedDB.path + suffix) + try? FileManager.default.copyItem(at: src, to: dst) + } + } + defer { try? FileManager.default.removeItem(at: tempDir) } + + return try self.readCookies(fromDB: copiedDB.path, domains: domains, keys: keys, label: label) + } + + private static func readCookies( + fromDB path: String, + domains: [String], + keys: [Data], + label: String) throws -> [ChromiumCookieRecord] + { + var db: OpaquePointer? + guard sqlite3_open_v2(path, &db, SQLITE_OPEN_READONLY, nil) == SQLITE_OK else { + throw ImportError.sqliteFailed(label: label, details: String(cString: sqlite3_errmsg(db))) + } + defer { sqlite3_close(db) } + + let sql = "SELECT host_key, name, path, expires_utc, is_secure, value, encrypted_value FROM cookies" + var stmt: OpaquePointer? + guard sqlite3_prepare_v2(db, sql, -1, &stmt, nil) == SQLITE_OK else { + throw ImportError.sqliteFailed(label: label, details: String(cString: sqlite3_errmsg(db))) + } + defer { sqlite3_finalize(stmt) } + + var records: [ChromiumCookieRecord] = [] + while sqlite3_step(stmt) == SQLITE_ROW { + guard let hostKey = self.readText(stmt, index: 0), self.matches(domain: hostKey, patterns: domains) else { + continue + } + guard let name = self.readText(stmt, index: 1), let path = self.readText(stmt, index: 2) else { + continue + } + + let value: String? = if let plain = self.readText(stmt, index: 5), !plain.isEmpty { + plain + } else if let encrypted = self.readBlob(stmt, index: 6) { + self.decrypt(encrypted, usingAnyOf: keys) + } else { + nil + } + guard let value, !value.isEmpty else { continue } + + records.append(ChromiumCookieRecord( + domain: AlibabaCodingPlanCookieImporter.normalizeCookieDomain(hostKey), + name: name, + path: path, + value: value, + expires: self.chromiumExpiry(sqlite3_column_int64(stmt, 3)), + isSecure: sqlite3_column_int(stmt, 4) != 0)) + } + + return records.filter { record in + guard let expires = record.expires else { return true } + return expires >= Date() + } + } + + private static func derivedKeys(for browser: Browser) throws -> [Data] { + var keys: [Data] = [] + var sawDenied = false + + for label in browser.safeStorageLabels { + switch KeychainAccessPreflight.checkGenericPassword(service: label.service, account: label.account) { + case .interactionRequired: + sawDenied = true + continue + case .allowed, .notFound, .failure: + break + } + + if let password = self.safeStoragePassword(service: label.service, account: label.account) { + keys.append(self.deriveKey(from: password)) + } + } + + if !keys.isEmpty { + return keys + } + if sawDenied { + throw ImportError.keychainDenied(browser: browser) + } + throw ImportError.keyUnavailable(browser: browser) + } + + private static func safeStoragePassword(service: String, account: String) -> String? { + // The preflight classifies prompt-requiring items as .interactionRequired, but its + // .notFound (gate disabled) and .failure outcomes still reach this read. Honor the + // access gate and keep the read strictly non-interactive so it can never prompt. + guard !KeychainAccessGate.isDisabled else { return nil } + var query: [String: Any] = [ + kSecClass as String: kSecClassGenericPassword, + kSecAttrService as String: service, + kSecAttrAccount as String: account, + kSecMatchLimit as String: kSecMatchLimitOne, + kSecReturnData as String: true, + ] + KeychainNoUIQuery.apply(to: &query) + + var result: AnyObject? + let status = KeychainSecurity.copyMatching(query as CFDictionary, &result) + guard status == errSecSuccess, let data = result as? Data else { return nil } + return String(data: data, encoding: .utf8) + } + + private static func deriveKey(from password: String) -> Data { + let salt = Data("saltysalt".utf8) + var key = Data(count: kCCKeySizeAES128) + let keyLength = key.count + _ = key.withUnsafeMutableBytes { keyBytes in + password.utf8CString.withUnsafeBytes { passBytes in + salt.withUnsafeBytes { saltBytes in + CCKeyDerivationPBKDF( + CCPBKDFAlgorithm(kCCPBKDF2), + passBytes.bindMemory(to: Int8.self).baseAddress, + passBytes.count - 1, + saltBytes.bindMemory(to: UInt8.self).baseAddress, + salt.count, + CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA1), + 1003, + keyBytes.bindMemory(to: UInt8.self).baseAddress, + keyLength) + } + } + } + return key + } + + private static func decrypt(_ encryptedValue: Data, usingAnyOf keys: [Data]) -> String? { + for key in keys { + if let value = self.decrypt(encryptedValue, key: key) { + return value + } + } + return nil + } + + private static func decrypt(_ encryptedValue: Data, key: Data) -> String? { + guard encryptedValue.count > 3 else { return nil } + let prefix = String(data: encryptedValue.prefix(3), encoding: .utf8) + guard prefix == "v10" else { return nil } + + let payload = Data(encryptedValue.dropFirst(3)) + let iv = Data(repeating: 0x20, count: kCCBlockSizeAES128) + var outLength = 0 + var out = Data(count: payload.count + kCCBlockSizeAES128) + let outCapacity = out.count + + let status = out.withUnsafeMutableBytes { outBytes in + payload.withUnsafeBytes { payloadBytes in + key.withUnsafeBytes { keyBytes in + iv.withUnsafeBytes { ivBytes in + CCCrypt( + CCOperation(kCCDecrypt), + CCAlgorithm(kCCAlgorithmAES), + CCOptions(kCCOptionPKCS7Padding), + keyBytes.baseAddress, + key.count, + ivBytes.baseAddress, + payloadBytes.baseAddress, + payload.count, + outBytes.baseAddress, + outCapacity, + &outLength) + } + } + } + } + + guard status == kCCSuccess else { return nil } + out.count = outLength + + if let value = String(data: out, encoding: .utf8), !value.isEmpty { + return value + } + if out.count > 32 { + let trimmed = out.dropFirst(32) + if let value = String(data: trimmed, encoding: .utf8), !value.isEmpty { + return value + } + } + return nil + } + + private static func makeCookie(from record: ChromiumCookieRecord) -> HTTPCookie? { + var properties: [HTTPCookiePropertyKey: Any] = [ + .domain: record.domain, + .path: record.path, + .name: record.name, + .value: record.value, + ] + if record.isSecure { + properties[.secure] = true + } + if let expires = record.expires { + properties[.expires] = expires + } + return HTTPCookie(properties: properties) + } + + private static func readText(_ stmt: OpaquePointer?, index: Int32) -> String? { + guard sqlite3_column_type(stmt, index) != SQLITE_NULL, + let value = sqlite3_column_text(stmt, index) + else { + return nil + } + return String(cString: value) + } + + private static func readBlob(_ stmt: OpaquePointer?, index: Int32) -> Data? { + guard sqlite3_column_type(stmt, index) != SQLITE_NULL, + let bytes = sqlite3_column_blob(stmt, index) + else { + return nil + } + return Data(bytes: bytes, count: Int(sqlite3_column_bytes(stmt, index))) + } + + private static func matches(domain: String, patterns: [String]) -> Bool { + AlibabaCodingPlanCookieImporter.matchesCookieDomain(domain, patterns: patterns) + } + + private static func chromiumExpiry(_ expiresUTC: Int64) -> Date? { + guard expiresUTC > 0 else { return nil } + let seconds = (Double(expiresUTC) / 1_000_000.0) - 11_644_473_600.0 + guard seconds > 0 else { return nil } + return Date(timeIntervalSince1970: seconds) + } +} +#endif diff --git a/Sources/CodexBarCore/Providers/Alibaba/AlibabaCodingPlanProviderDescriptor.swift b/Sources/CodexBarCore/Providers/Alibaba/AlibabaCodingPlanProviderDescriptor.swift new file mode 100644 index 0000000..3958664 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Alibaba/AlibabaCodingPlanProviderDescriptor.swift @@ -0,0 +1,266 @@ +import Foundation + +#if os(macOS) +import SweetCookieKit +#endif + +public enum AlibabaCodingPlanProviderDescriptor { + public static let descriptor: ProviderDescriptor = Self.makeDescriptor() + + static func makeDescriptor() -> ProviderDescriptor { + #if os(macOS) + let browserOrder: BrowserCookieImportOrder = [ + .chrome, + .chromeBeta, + .brave, + .edge, + .arc, + .firefox, + .safari, + ] + #else + let browserOrder: BrowserCookieImportOrder? = nil + #endif + + return ProviderDescriptor( + id: .alibaba, + metadata: ProviderMetadata( + id: .alibaba, + displayName: "Alibaba", + sessionLabel: "5-hour", + weeklyLabel: "Weekly", + opusLabel: "Monthly", + supportsOpus: true, + supportsCredits: false, + creditsHint: "", + toggleTitle: "Show Alibaba usage", + cliName: "alibaba-coding-plan", + defaultEnabled: false, + isPrimaryProvider: false, + usesAccountFallback: false, + browserCookieOrder: browserOrder, + dashboardURL: AlibabaCodingPlanAPIRegion.international.dashboardURL.absoluteString, + statusPageURL: nil, + statusLinkURL: "https://status.aliyun.com"), + branding: ProviderBranding( + iconStyle: .alibaba, + iconResourceName: "ProviderIcon-alibaba", + color: ProviderColor(red: 1.0, green: 106 / 255, blue: 0)), + tokenCost: ProviderTokenCostConfig( + supportsTokenCost: false, + noDataMessage: { "Alibaba Coding Plan cost summary is not supported." }), + fetchPlan: ProviderFetchPlan( + sourceModes: [.auto, .web, .api], + pipeline: ProviderFetchPipeline(resolveStrategies: self.resolveStrategies)), + cli: ProviderCLIConfig( + name: "alibaba-coding-plan", + aliases: ["alibaba", "bailian"], + versionDetector: nil)) + } + + private static func resolveStrategies(context: ProviderFetchContext) async -> [any ProviderFetchStrategy] { + switch context.sourceMode { + case .web: + return [AlibabaCodingPlanWebFetchStrategy()] + case .api: + return [AlibabaCodingPlanAPIFetchStrategy()] + case .cli, .oauth: + return [] + case .auto: + break + } + + if context.settings?.alibaba?.cookieSource == .off { + return [AlibabaCodingPlanAPIFetchStrategy()] + } + + return [AlibabaCodingPlanWebFetchStrategy(), AlibabaCodingPlanAPIFetchStrategy()] + } +} + +struct AlibabaCodingPlanWebFetchStrategy: ProviderFetchStrategy { + let id: String = "alibaba-coding-plan.web" + let kind: ProviderFetchKind = .web + + func isAvailable(_ context: ProviderFetchContext) async -> Bool { + guard context.settings?.alibaba?.cookieSource != .off else { return false } + + if AlibabaCodingPlanSettingsReader.cookieHeader(environment: context.env) != nil { + return true + } + + if let settings = context.settings?.alibaba, + settings.cookieSource == .manual + { + return CookieHeaderNormalizer.normalize(settings.manualCookieHeader) != nil + } + + #if os(macOS) + if let cached = CookieHeaderCache.load(provider: .alibaba), + !cached.cookieHeader.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty + { + return true + } + if AlibabaCodingPlanCookieImporter.hasSession(browserDetection: context.browserDetection) { + return true + } + return false + #else + return false + #endif + } + + func fetch(_ context: ProviderFetchContext) async throws -> ProviderFetchResult { + let cookieSource = context.settings?.alibaba?.cookieSource ?? .auto + let cookieHeader = try Self.resolveCookieHeader(context: context, allowCached: true) + do { + let region = context.settings?.alibaba?.apiRegion ?? .international + let usage = try await AlibabaCodingPlanUsageFetcher.fetchUsage( + cookieHeader: cookieHeader, + region: region, + environment: context.env) + return self.makeResult(usage: usage.toUsageSnapshot(), sourceLabel: "web") + } catch let error as AlibabaCodingPlanUsageError + where (error == .invalidCredentials || error == .loginRequired) && cookieSource != .manual + { + #if os(macOS) + CookieHeaderCache.clear(provider: .alibaba) + let refreshedHeader = try Self.resolveCookieHeader(context: context, allowCached: false) + let region = context.settings?.alibaba?.apiRegion ?? .international + let usage = try await AlibabaCodingPlanUsageFetcher.fetchUsage( + cookieHeader: refreshedHeader, + region: region, + environment: context.env) + return self.makeResult(usage: usage.toUsageSnapshot(), sourceLabel: "web") + #else + throw AlibabaCodingPlanUsageError.invalidCredentials + #endif + } + } + + func shouldFallback(on error: Error, context: ProviderFetchContext) -> Bool { + guard context.sourceMode == .auto else { return false } + + if let urlError = error as? URLError { + switch urlError.code { + case .timedOut, + .cannotFindHost, + .cannotConnectToHost, + .networkConnectionLost, + .dnsLookupFailed, + .secureConnectionFailed, + .serverCertificateHasBadDate, + .serverCertificateUntrusted, + .serverCertificateHasUnknownRoot, + .serverCertificateNotYetValid, + .clientCertificateRejected, + .clientCertificateRequired, + .cannotLoadFromNetwork, + .internationalRoamingOff, + .callIsActive, + .dataNotAllowed, + .requestBodyStreamExhausted, + .resourceUnavailable, + .notConnectedToInternet: + return true + default: + break + } + } + + if let settingsError = error as? AlibabaCodingPlanSettingsError { + switch settingsError { + case .missingCookie, .invalidCookie: + return true + case .missingToken: + return false + } + } + + guard let alibabaError = error as? AlibabaCodingPlanUsageError else { return false } + switch alibabaError { + case .loginRequired: + return true + case .invalidCredentials: + return true + case .apiKeyUnavailableInRegion: + return false + case let .apiError(message): + return message.contains("HTTP 404") || message.contains("HTTP 403") + case .networkError: + return true + case .parseFailed: + return false + } + } + + static func resolveCookieHeader(context: ProviderFetchContext, allowCached: Bool) throws -> String { + if let settings = context.settings?.alibaba, + settings.cookieSource == .manual + { + guard let header = CookieHeaderNormalizer.normalize(settings.manualCookieHeader) else { + throw AlibabaCodingPlanSettingsError.invalidCookie + } + return header + } + + if let envCookie = AlibabaCodingPlanSettingsReader.cookieHeader(environment: context.env), + let normalized = CookieHeaderNormalizer.normalize(envCookie) + { + return normalized + } + + #if os(macOS) + if allowCached, + let cached = CookieHeaderCache.load(provider: .alibaba), + !cached.cookieHeader.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty + { + return cached.cookieHeader + } + + do { + let session = try AlibabaCodingPlanCookieImporter.importSession(browserDetection: context.browserDetection) + CookieHeaderCache.store( + provider: .alibaba, + cookieHeader: session.cookieHeader, + sourceLabel: session.sourceLabel) + return session.cookieHeader + } catch { + throw error + } + #else + throw AlibabaCodingPlanSettingsError.missingCookie() + #endif + } +} + +struct AlibabaCodingPlanAPIFetchStrategy: ProviderFetchStrategy { + let id: String = "alibaba-coding-plan.api" + let kind: ProviderFetchKind = .apiToken + + func isAvailable(_ context: ProviderFetchContext) async -> Bool { + Self.resolveToken(environment: context.env) != nil + } + + func fetch(_ context: ProviderFetchContext) async throws -> ProviderFetchResult { + guard let apiKey = Self.resolveToken(environment: context.env) else { + throw AlibabaCodingPlanSettingsError.missingToken + } + let region = context.settings?.alibaba?.apiRegion ?? .international + let usage = try await AlibabaCodingPlanUsageFetcher.fetchUsage( + apiKey: apiKey, + region: region, + environment: context.env) + return self.makeResult( + usage: usage.toUsageSnapshot(), + sourceLabel: "api") + } + + func shouldFallback(on _: Error, context _: ProviderFetchContext) -> Bool { + false + } + + private static func resolveToken(environment: [String: String]) -> String? { + ProviderTokenResolver.alibabaToken(environment: environment) + } +} diff --git a/Sources/CodexBarCore/Providers/Alibaba/AlibabaCodingPlanSettingsReader.swift b/Sources/CodexBarCore/Providers/Alibaba/AlibabaCodingPlanSettingsReader.swift new file mode 100644 index 0000000..c082477 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Alibaba/AlibabaCodingPlanSettingsReader.swift @@ -0,0 +1,118 @@ +import Foundation + +public struct AlibabaCodingPlanSettingsReader: Sendable { + private static let endpointValidator = ProviderEndpointOverrideValidator( + allowedHosts: [ + "modelstudio.console.alibabacloud.com", + "bailian-singapore-cs.alibabacloud.com", + "bailian.console.aliyun.com", + "bailian-cs.console.aliyun.com", + "bailian-beijing-cs.aliyuncs.com", + ]) + + public static let apiTokenKey = "ALIBABA_CODING_PLAN_API_KEY" + public static let qwenAPITokenKey = "ALIBABA_QWEN_API_KEY" + public static let dashScopeAPITokenKey = "DASHSCOPE_API_KEY" + public static let apiTokenEnvironmentKeys = [ + Self.apiTokenKey, + Self.qwenAPITokenKey, + Self.dashScopeAPITokenKey, + ] + public static let cookieHeaderKey = "ALIBABA_CODING_PLAN_COOKIE" + public static let hostKey = "ALIBABA_CODING_PLAN_HOST" + public static let quotaURLKey = "ALIBABA_CODING_PLAN_QUOTA_URL" + public static let requireProviderEndpointOverridesKey = "ALIBABA_CODING_PLAN_REQUIRE_PROVIDER_ENDPOINT_OVERRIDES" + private static let endpointOverrideKeys = [ + Self.hostKey, + Self.quotaURLKey, + ] + + public static func apiToken( + environment: [String: String] = ProcessInfo.processInfo.environment) -> String? + { + for key in self.apiTokenEnvironmentKeys { + if let token = self.cleaned(environment[key]) { return token } + } + return nil + } + + public static func hostOverride( + environment: [String: String] = ProcessInfo.processInfo.environment) -> String? + { + self.endpointValidator.validatedHost( + self.cleaned(environment[self.hostKey]), + policy: self.endpointOverrideHostPolicy(environment: environment)) + } + + public static func rejectedEndpointOverrideKey( + environment: [String: String] = ProcessInfo.processInfo.environment) -> String? + { + let policy = self.endpointOverrideHostPolicy(environment: environment) + return self.endpointOverrideKeys.first { key in + guard let value = self.cleaned(environment[key]) else { return false } + if key == Self.hostKey { + return self.endpointValidator.validatedHost(value, policy: policy) == nil + } + return self.endpointValidator.validatedURL(value, policy: policy) == nil + } + } + + public static func cookieHeader( + environment: [String: String] = ProcessInfo.processInfo.environment) -> String? + { + self.cleaned(environment[self.cookieHeaderKey]) + } + + public static func quotaURL( + environment: [String: String] = ProcessInfo.processInfo.environment) -> URL? + { + self.endpointValidator.validatedURL( + self.cleaned(environment[self.quotaURLKey]), + policy: self.endpointOverrideHostPolicy(environment: environment)) + } + + static func endpointOverrideHostPolicy(environment: [String: String]) -> ProviderEndpointOverrideValidator + .HostPolicy { + guard let value = self.cleaned(environment[self.requireProviderEndpointOverridesKey])?.lowercased(), + ["1", "true", "yes", "on"].contains(value) + else { return .allowAnyHTTPSHost } + return .providerOwnedOnly + } + + static func cleaned(_ raw: String?) -> String? { + guard var value = raw?.trimmingCharacters(in: .whitespacesAndNewlines), !value.isEmpty else { + return nil + } + + if (value.hasPrefix("\"") && value.hasSuffix("\"")) || + (value.hasPrefix("'") && value.hasSuffix("'")) + { + value = String(value.dropFirst().dropLast()) + } + + value = value.trimmingCharacters(in: .whitespacesAndNewlines) + return value.isEmpty ? nil : value + } +} + +public enum AlibabaCodingPlanSettingsError: LocalizedError, Sendable { + case missingToken + case missingCookie(details: String? = nil) + case invalidCookie + + public var errorDescription: String? { + switch self { + case .missingToken: + return "Alibaba Coding Plan API key not found. " + + "Set apiKey in ~/.codexbar/config.json, ALIBABA_CODING_PLAN_API_KEY, " + + "ALIBABA_QWEN_API_KEY, or DASHSCOPE_API_KEY." + case let .missingCookie(details): + let base = "No Alibaba Coding Plan session cookies found in browsers. " + + "If you use Safari, enable Full Disk Access for CodexBar/Terminal or paste a manual Cookie header." + guard let details, !details.isEmpty else { return base } + return "\(base) \(details)" + case .invalidCookie: + return "Alibaba Coding Plan cookie header is invalid." + } + } +} diff --git a/Sources/CodexBarCore/Providers/Alibaba/AlibabaCodingPlanUsageFetcher.swift b/Sources/CodexBarCore/Providers/Alibaba/AlibabaCodingPlanUsageFetcher.swift new file mode 100644 index 0000000..2eb7918 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Alibaba/AlibabaCodingPlanUsageFetcher.swift @@ -0,0 +1,1121 @@ +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +// swiftlint:disable type_body_length +public struct AlibabaCodingPlanUsageFetcher: Sendable { + private static let log = CodexBarLog.logger("alibaba-coding-plan") + private static let browserLikeUserAgent = + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) " + + "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36" + private static let safariLikeUserAgent = + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) " + + "AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.3 Safari/605.1.15" + + enum AuthMode { + case apiKey + case webSession + } + + public static func fetchUsage( + apiKey: String, + region: AlibabaCodingPlanAPIRegion = .international, + environment: [String: String] = ProcessInfo.processInfo.environment, + now: Date = Date(), + transport: any ProviderHTTPTransport = ProviderHTTPClient.shared) async throws -> AlibabaCodingPlanUsageSnapshot + { + let cleanedKey = apiKey.trimmingCharacters(in: .whitespacesAndNewlines) + guard !cleanedKey.isEmpty else { + throw AlibabaCodingPlanUsageError.invalidCredentials + } + if let rejectedKey = AlibabaCodingPlanSettingsReader.rejectedEndpointOverrideKey(environment: environment) { + throw ProviderEndpointOverrideError.alibabaCodingPlan(rejectedKey) + } + + if region != .international { + return try await self.fetchUsageOnce( + apiKey: cleanedKey, + region: region, + environment: environment, + now: now, + transport: transport) + } + + do { + return try await self.fetchUsageOnce( + apiKey: cleanedKey, + region: .international, + environment: environment, + now: now, + transport: transport) + } catch let error as AlibabaCodingPlanUsageError { + guard error.shouldRetryOnAlternateRegion else { throw error } + Self.log.debug("Alibaba Coding Plan request failed on intl host; retrying cn host") + return try await self.fetchUsageOnce( + apiKey: cleanedKey, + region: .chinaMainland, + environment: environment, + now: now, + transport: transport) + } + } + + public static func fetchUsage( + cookieHeader: String, + region: AlibabaCodingPlanAPIRegion = .international, + environment: [String: String] = ProcessInfo.processInfo.environment, + now: Date = Date(), + transport: any ProviderHTTPTransport = ProviderHTTPClient.shared) async throws -> AlibabaCodingPlanUsageSnapshot + { + guard let normalizedCookie = CookieHeaderNormalizer.normalize(cookieHeader) else { + throw AlibabaCodingPlanSettingsError.invalidCookie + } + if let rejectedKey = AlibabaCodingPlanSettingsReader.rejectedEndpointOverrideKey(environment: environment) { + throw ProviderEndpointOverrideError.alibabaCodingPlan(rejectedKey) + } + + if region != .international { + return try await self.fetchUsageOnce( + cookieHeader: normalizedCookie, + region: region, + environment: environment, + now: now, + transport: transport) + } + + do { + return try await self.fetchUsageOnce( + cookieHeader: normalizedCookie, + region: .international, + environment: environment, + now: now, + transport: transport) + } catch let error as AlibabaCodingPlanUsageError { + guard error.shouldRetryOnAlternateRegion else { throw error } + Self.log.debug("Alibaba Coding Plan cookie request failed on intl host; retrying cn host") + return try await self.fetchUsageOnce( + cookieHeader: normalizedCookie, + region: .chinaMainland, + environment: environment, + now: now, + transport: transport) + } + } + + private static func fetchUsageOnce( + apiKey: String, + region: AlibabaCodingPlanAPIRegion, + environment: [String: String], + now: Date, + transport: any ProviderHTTPTransport) async throws -> AlibabaCodingPlanUsageSnapshot + { + let url = self.resolveQuotaURL(region: region, environment: environment) + var request = URLRequest(url: url) + request.httpMethod = "POST" + request.httpBody = self.queryCodingPlanAPIRequestBody(region: region) + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + request.setValue("application/json", forHTTPHeaderField: "Accept") + request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization") + request.setValue(apiKey, forHTTPHeaderField: "x-api-key") + request.setValue(apiKey, forHTTPHeaderField: "X-DashScope-API-Key") + request.setValue(Self.browserLikeUserAgent, forHTTPHeaderField: "User-Agent") + request.setValue(region.gatewayBaseURLString, forHTTPHeaderField: "Origin") + request.setValue(region.dashboardURL.absoluteString, forHTTPHeaderField: "Referer") + + let response = try await transport.response(for: request) + let data = response.data + guard response.statusCode == 200 else { + if response.statusCode == 401 || response.statusCode == 403 { + throw AlibabaCodingPlanUsageError.invalidCredentials + } + let body = String(data: data, encoding: .utf8) ?? "" + Self.log.error("Alibaba Coding Plan returned \(response.statusCode): \(body)") + throw AlibabaCodingPlanUsageError.apiError("HTTP \(response.statusCode)") + } + + return try self.parseUsageSnapshot(from: data, now: now, authMode: .apiKey) + } + + private static func fetchUsageOnce( + cookieHeader: String, + region: AlibabaCodingPlanAPIRegion, + environment: [String: String], + now: Date, + transport: any ProviderHTTPTransport) async throws -> AlibabaCodingPlanUsageSnapshot + { + let url = self.resolveConsoleQuotaURL(region: region, environment: environment) + let secToken = try await self.resolveConsoleSECToken( + cookieHeader: cookieHeader, + region: region, + environment: environment, + transport: transport) + let anonymousID = self.extractCookieValue(name: "cna", from: cookieHeader) + + var request = URLRequest(url: url) + request.httpMethod = "POST" + request.httpBody = self.queryCodingPlanConsoleRequestBody( + region: region, + secToken: secToken, + anonymousID: anonymousID) + request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") + request.setValue("*/*", forHTTPHeaderField: "Accept") + request.setValue(cookieHeader, forHTTPHeaderField: "Cookie") + if let csrf = self.extractCookieValue(name: "login_aliyunid_csrf", from: cookieHeader) ?? + self.extractCookieValue(name: "csrf", from: cookieHeader) + { + request.setValue(csrf, forHTTPHeaderField: "x-xsrf-token") + request.setValue(csrf, forHTTPHeaderField: "x-csrf-token") + } + request.setValue("XMLHttpRequest", forHTTPHeaderField: "X-Requested-With") + request.setValue(Self.browserLikeUserAgent, forHTTPHeaderField: "User-Agent") + request.setValue(region.gatewayBaseURLString, forHTTPHeaderField: "Origin") + request.setValue(region.consoleRefererURL.absoluteString, forHTTPHeaderField: "Referer") + + let response = try await transport.response(for: request) + let data = response.data + guard response.statusCode == 200 else { + if response.statusCode == 401 || response.statusCode == 403 { + throw AlibabaCodingPlanUsageError.loginRequired + } + let body = String(data: data, encoding: .utf8) ?? "" + Self.log.error("Alibaba Coding Plan returned \(response.statusCode): \(body)") + throw AlibabaCodingPlanUsageError.apiError("HTTP \(response.statusCode)") + } + + return try self.parseUsageSnapshot(from: data, now: now, authMode: .webSession) + } + + private static func queryCodingPlanAPIRequestBody(region: AlibabaCodingPlanAPIRegion) -> Data { + let payload: [String: Any] = [ + "queryCodingPlanInstanceInfoRequest": [ + "commodityCode": region.commodityCode, + ], + ] + return (try? JSONSerialization.data(withJSONObject: payload, options: [])) ?? Data("{}".utf8) + } + + private static func queryCodingPlanConsoleRequestBody( + region: AlibabaCodingPlanAPIRegion, + secToken: String, + anonymousID: String?) -> Data + { + let traceID = UUID().uuidString.lowercased() + var cornerstoneParam: [String: Any] = [ + "feTraceId": traceID, + "feURL": region.dashboardURL.absoluteString, + "protocol": "V2", + "console": "ONE_CONSOLE", + "productCode": "p_efm", + "domain": region.consoleDomain, + "consoleSite": region.consoleSite, + "userNickName": "", + "userPrincipalName": "", + "xsp_lang": "en-US", + ] + if let anonymousID, !anonymousID.isEmpty { + cornerstoneParam["X-Anonymous-Id"] = anonymousID + } + + let paramsObject: [String: Any] = [ + "Api": region.consoleQuotaAPIName, + "V": "1.0", + "Data": [ + "queryCodingPlanInstanceInfoRequest": [ + "commodityCode": region.commodityCode, + "onlyLatestOne": true, + ], + "cornerstoneParam": cornerstoneParam, + ], + ] + + guard let paramsData = try? JSONSerialization.data(withJSONObject: paramsObject, options: []), + let paramsString = String(data: paramsData, encoding: .utf8) + else { + return Data() + } + + var components = URLComponents() + components.queryItems = [ + URLQueryItem(name: "params", value: paramsString), + URLQueryItem(name: "region", value: region.currentRegionID), + URLQueryItem(name: "sec_token", value: secToken), + ] + return Data((components.percentEncodedQuery ?? "").utf8) + } + + static func resolveConsoleQuotaURL( + region: AlibabaCodingPlanAPIRegion, + environment: [String: String]) -> URL + { + if let override = AlibabaCodingPlanSettingsReader.quotaURL(environment: environment) { + return override + } + if let host = AlibabaCodingPlanSettingsReader.hostOverride(environment: environment), + let hostURL = self.consoleURL(from: host, region: region) + { + return hostURL + } + return region.consoleRPCURL + } + + static func resolveQuotaURL( + region: AlibabaCodingPlanAPIRegion, + environment: [String: String]) -> URL + { + if let override = AlibabaCodingPlanSettingsReader.quotaURL(environment: environment) { + return override + } + if let host = AlibabaCodingPlanSettingsReader.hostOverride(environment: environment), + let hostURL = self.url(from: host, region: region) + { + return hostURL + } + return region.quotaURL + } + + static func resolveConsoleDashboardURL( + region: AlibabaCodingPlanAPIRegion, + environment: [String: String]) -> URL + { + if let override = AlibabaCodingPlanSettingsReader.hostOverride(environment: environment), + let hostURL = self.dashboardURL(from: override, region: region) + { + return hostURL + } + return region.dashboardURL + } + + static func url(from rawHost: String, region: AlibabaCodingPlanAPIRegion) -> URL? { + let cleaned = AlibabaCodingPlanSettingsReader.cleaned(rawHost) + guard let cleaned else { return nil } + + let base = ProviderEndpointOverrideValidator.normalizedHTTPSURL(from: cleaned) + guard let base else { return nil } + + var components = URLComponents(url: base, resolvingAgainstBaseURL: false) + components?.path = "/data/api.json" + components?.queryItems = [ + URLQueryItem( + name: "action", + value: "zeldaEasy.broadscope-bailian.codingPlan.queryCodingPlanInstanceInfoV2"), + URLQueryItem(name: "product", value: "broadscope-bailian"), + URLQueryItem(name: "api", value: "queryCodingPlanInstanceInfoV2"), + URLQueryItem(name: "currentRegionId", value: region.currentRegionID), + ] + return components?.url + } + + static func consoleURL(from rawHost: String, region: AlibabaCodingPlanAPIRegion) -> URL? { + let cleaned = AlibabaCodingPlanSettingsReader.cleaned(rawHost) + guard let cleaned else { return nil } + + let base = ProviderEndpointOverrideValidator.normalizedHTTPSURL(from: cleaned) + guard let base else { return nil } + + var components = URLComponents(url: base, resolvingAgainstBaseURL: false) + components?.path = "/data/api.json" + components?.queryItems = [ + URLQueryItem(name: "action", value: region.consoleRPCAction), + URLQueryItem(name: "product", value: region.consoleRPCProduct), + URLQueryItem(name: "api", value: region.consoleQuotaAPIName), + URLQueryItem(name: "_v", value: "undefined"), + ] + return components?.url + } + + private static func resolveConsoleSECToken( + cookieHeader: String, + region: AlibabaCodingPlanAPIRegion, + environment: [String: String], + transport: any ProviderHTTPTransport) async throws -> String + { + let cookieSECToken = self.extractCookieValue(name: "sec_token", from: cookieHeader) + + let dashboardURL = self.resolveConsoleDashboardURL(region: region, environment: environment) + + var request = URLRequest(url: dashboardURL) + request.httpMethod = "GET" + request.setValue(cookieHeader, forHTTPHeaderField: "Cookie") + request.setValue(Self.safariLikeUserAgent, forHTTPHeaderField: "User-Agent") + request.setValue( + "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", + forHTTPHeaderField: "Accept") + + if let response = try? await transport.response(for: request), + response.statusCode == 200, + let html = String(data: response.data, encoding: .utf8), + let token = self.extractConsoleSECToken(from: html), + !token.isEmpty + { + return token + } + + if let token = try? await self.fetchSECTokenFromUserInfo( + cookieHeader: cookieHeader, + region: region, + environment: environment, + transport: transport) + { + return token + } + + if let cookieSECToken, !cookieSECToken.isEmpty { + return cookieSECToken + } + + throw AlibabaCodingPlanUsageError.loginRequired + } + + static func dashboardURL(from rawHost: String, region: AlibabaCodingPlanAPIRegion) -> URL? { + let cleaned = AlibabaCodingPlanSettingsReader.cleaned(rawHost) + guard let cleaned else { return nil } + + let base = ProviderEndpointOverrideValidator.normalizedHTTPSURL(from: cleaned) + guard let base else { return nil } + + guard var components = URLComponents(url: base, resolvingAgainstBaseURL: false), + let dashboardComponents = URLComponents( + url: region.dashboardURL, + resolvingAgainstBaseURL: false) + else { + return nil + } + + components.path = dashboardComponents.path + components.percentEncodedQuery = dashboardComponents.percentEncodedQuery + components.fragment = dashboardComponents.fragment + return components.url + } + + private static func fetchSECTokenFromUserInfo( + cookieHeader: String, + region: AlibabaCodingPlanAPIRegion, + environment: [String: String], + transport: any ProviderHTTPTransport) async throws -> String? + { + let gatewayBaseURL = self.resolveConsoleGatewayBaseURL(region: region, environment: environment) + let userInfoURL = gatewayBaseURL.appendingPathComponent("tool/user/info.json") + var request = URLRequest(url: userInfoURL) + request.httpMethod = "GET" + request.setValue(cookieHeader, forHTTPHeaderField: "Cookie") + request.setValue(Self.safariLikeUserAgent, forHTTPHeaderField: "User-Agent") + request.setValue("application/json, text/plain, */*", forHTTPHeaderField: "Accept") + let referer = gatewayBaseURL.absoluteString.hasSuffix("/") ? gatewayBaseURL.absoluteString : gatewayBaseURL + .absoluteString + "/" + request.setValue(referer, forHTTPHeaderField: "Referer") + + let response = try await transport.response(for: request) + guard response.statusCode == 200 else { + return nil + } + + let object = try JSONSerialization.jsonObject(with: response.data, options: []) + let expanded = self.expandedJSON(object) + return self.findFirstString(forKeys: ["secToken", "sec_token"], in: expanded) + } + + private static func resolveConsoleGatewayBaseURL( + region: AlibabaCodingPlanAPIRegion, + environment: [String: String]) -> URL + { + if let host = AlibabaCodingPlanSettingsReader.hostOverride(environment: environment), + let hostURL = self.baseURL(from: host) + { + return hostURL + } + return URL(string: region.gatewayBaseURLString)! + } + + private static func baseURL(from rawHost: String) -> URL? { + let cleaned = AlibabaCodingPlanSettingsReader.cleaned(rawHost) + guard let cleaned else { return nil } + + let base = ProviderEndpointOverrideValidator.normalizedHTTPSURL(from: cleaned) + guard let base else { return nil } + + guard var components = URLComponents(url: base, resolvingAgainstBaseURL: false) else { + return nil + } + components.path = "" + components.query = nil + components.fragment = nil + return components.url + } + + static func parseUsageSnapshot( + from data: Data, + now: Date = Date(), + authMode: AuthMode = .webSession) throws -> AlibabaCodingPlanUsageSnapshot + { + guard !data.isEmpty else { + throw AlibabaCodingPlanUsageError.parseFailed("Empty response body") + } + + let object = try JSONSerialization.jsonObject(with: data, options: []) + let expanded = self.expandedJSON(object) + guard let dictionary = expanded as? [String: Any] else { + throw AlibabaCodingPlanUsageError.parseFailed("Unexpected payload") + } + + if let statusCode = self.findFirstInt(forKeys: ["statusCode", "status_code", "code"], in: dictionary), + statusCode != 0, + statusCode != 200 + { + let message = self.findFirstString( + forKeys: ["statusMessage", "status_msg", "message", "msg"], + in: dictionary) + ?? "status code \(statusCode)" + let lower = message.lowercased() + if statusCode == 401 || statusCode == 403 || lower.contains("api key") || lower.contains("unauthorized") { + throw AlibabaCodingPlanUsageError.invalidCredentials + } + throw AlibabaCodingPlanUsageError.apiError(message) + } + + if let codeText = self.findFirstString(forKeys: ["code", "status", "statusCode"], in: dictionary) { + let normalizedCode = codeText.lowercased() + if normalizedCode.contains("needlogin") || normalizedCode.contains("login") { + if authMode == .apiKey { + throw AlibabaCodingPlanUsageError.apiKeyUnavailableInRegion + } + throw AlibabaCodingPlanUsageError.loginRequired + } + } + if let messageText = self.findFirstString(forKeys: ["message", "msg", "statusMessage"], in: dictionary) { + let normalizedMessage = messageText.lowercased() + if normalizedMessage.contains("log in") || normalizedMessage.contains("login") { + if authMode == .apiKey { + throw AlibabaCodingPlanUsageError.apiKeyUnavailableInRegion + } + throw AlibabaCodingPlanUsageError.loginRequired + } + if authMode == .apiKey, + normalizedMessage.contains("console session") || + normalizedMessage.contains("api key mode may be unavailable") + { + throw AlibabaCodingPlanUsageError.apiKeyUnavailableInRegion + } + } + + let instanceInfo = self.findActiveInstanceInfo(in: dictionary, now: now) + let instanceCount = self.findFirstArray( + forKeys: ["codingPlanInstanceInfos", "coding_plan_instance_infos"], + in: dictionary)? + .compactMap { $0 as? [String: Any] } + .count ?? 0 + let shouldScopeQuotaToSelectedInstance = + instanceCount > 1 && + (instanceInfo.map { self.activeSignalScore(in: $0, now: now) > 0 } ?? false) + let quota = if shouldScopeQuotaToSelectedInstance, let instanceInfo { + self.findQuotaInfo(in: instanceInfo) + } else { + self.findQuotaInfo(in: instanceInfo ?? [:]) ?? self.findQuotaInfo(in: dictionary) + } + guard let quota else { + if let fallback = self.parsePlanVisibleActiveFallback( + payload: dictionary, + instanceInfo: instanceInfo, + now: now) + { + return fallback + } + let diagnostics = self.payloadDiagnostics(payload: dictionary) + Self.log.error("Alibaba coding plan quota payload missing expected fields: \(diagnostics)") + throw AlibabaCodingPlanUsageError.parseFailed("Missing coding plan quota data (\(diagnostics))") + } + + let planName = self.findPlanName(in: instanceInfo ?? [:]) ?? self.findPlanName(in: dictionary) + + let snapshot = AlibabaCodingPlanUsageSnapshot( + planName: planName, + fiveHourUsedQuota: self.anyInt(for: ["per5HourUsedQuota", "perFiveHourUsedQuota"], in: quota), + fiveHourTotalQuota: self.anyInt(for: ["per5HourTotalQuota", "perFiveHourTotalQuota"], in: quota), + fiveHourNextRefreshTime: self.anyDate( + for: ["per5HourQuotaNextRefreshTime", "perFiveHourQuotaNextRefreshTime"], + in: quota), + weeklyUsedQuota: self.anyInt(for: ["perWeekUsedQuota"], in: quota), + weeklyTotalQuota: self.anyInt(for: ["perWeekTotalQuota"], in: quota), + weeklyNextRefreshTime: self.anyDate(for: ["perWeekQuotaNextRefreshTime"], in: quota), + monthlyUsedQuota: self.anyInt(for: ["perBillMonthUsedQuota", "perMonthUsedQuota"], in: quota), + monthlyTotalQuota: self.anyInt(for: ["perBillMonthTotalQuota", "perMonthTotalQuota"], in: quota), + monthlyNextRefreshTime: self.anyDate( + for: ["perBillMonthQuotaNextRefreshTime", "perMonthQuotaNextRefreshTime"], + in: quota), + updatedAt: now) + + if snapshot.fiveHourTotalQuota == nil, + snapshot.weeklyTotalQuota == nil, + snapshot.monthlyTotalQuota == nil + { + if let fallback = self.parsePlanVisibleActiveFallback( + payload: dictionary, + instanceInfo: instanceInfo, + now: now) + { + return fallback + } + let diagnostics = self.payloadDiagnostics(payload: dictionary) + Self.log.error("Alibaba coding plan payload had no usable windows: \(diagnostics)") + throw AlibabaCodingPlanUsageError.parseFailed("No quota windows found in payload (\(diagnostics))") + } + + return snapshot + } + + private static func findPlanName(in payload: [String: Any]) -> String? { + if let infos = self.findFirstArray( + forKeys: ["codingPlanInstanceInfos", "coding_plan_instance_infos"], + in: payload) + { + for item in infos { + guard let info = item as? [String: Any] else { continue } + let candidates = [ + self.anyString(for: ["planName", "plan_name"], in: info), + self.anyString(for: ["instanceName", "instance_name"], in: info), + self.anyString(for: ["packageName", "package_name"], in: info), + ] + for candidate in candidates { + if let candidate, !candidate.isEmpty { + return candidate + } + } + } + } + return self.findFirstString(forKeys: ["planName", "plan_name", "packageName", "package_name"], in: payload) + } + + private static func findActiveInstanceInfo(in payload: [String: Any], now: Date = Date()) -> [String: Any]? { + guard let infos = self.findFirstArray( + forKeys: ["codingPlanInstanceInfos", "coding_plan_instance_infos"], + in: payload) + else { + return nil + } + + var first: [String: Any]? + var best: [String: Any]? + var bestScore = Int.min + for item in infos { + guard let info = item as? [String: Any] else { continue } + first = first ?? info + let score = self.activeSignalScore(in: info, now: now) + if score > bestScore { + best = info + bestScore = score + } + } + if bestScore > 0 { + return best + } + return first + } + + private static func parsePlanVisibleActiveFallback( + payload: [String: Any], + instanceInfo: [String: Any]?, + now: Date) -> AlibabaCodingPlanUsageSnapshot? + { + let source = instanceInfo ?? payload + guard self.hasPositiveActivePlanSignal(in: source, payload: payload, now: now), + let planName = self.findPlanName(in: source) ?? self.findPlanName(in: payload) + else { + return nil + } + + return AlibabaCodingPlanUsageSnapshot( + planName: planName, + fiveHourUsedQuota: nil, + fiveHourTotalQuota: nil, + fiveHourNextRefreshTime: nil, + weeklyUsedQuota: nil, + weeklyTotalQuota: nil, + weeklyNextRefreshTime: nil, + monthlyUsedQuota: nil, + monthlyTotalQuota: nil, + monthlyNextRefreshTime: nil, + updatedAt: now) + } + + private static func hasPositiveActivePlanSignal( + in source: [String: Any], + payload: [String: Any], + now: Date) -> Bool + { + if self.containsPlanInstances(in: payload) { + return self.activeSignalScore(in: source, now: now) > 0 + } + return self.activeSignalScore(in: source, now: now) > 0 || self.activeSignalScore(in: payload, now: now) > 0 + } + + private static func containsPlanInstances(in payload: [String: Any]) -> Bool { + guard let infos = self.findFirstArray( + forKeys: ["codingPlanInstanceInfos", "coding_plan_instance_infos"], + in: payload) + else { + return false + } + return infos.contains { $0 is [String: Any] } + } + + private static func activeSignalScore(in source: [String: Any], now: Date) -> Int { + if let status = self.anyString(for: ["status", "instanceStatus"], in: source)?.uppercased() { + if ["VALID", "ACTIVE"].contains(status) { + return 3 + } + if ["EXPIRED", "INVALID", "INACTIVE", "DISABLED", "TERMINATED", "STOPPED"].contains(status) { + return -1 + } + } + + if let isActive = self.anyBool(for: ["isActive", "active"], in: source) { + return isActive ? 3 : -1 + } + + if let expiry = self.anyDate(for: ["endTime", "periodEndTime", "expireTime", "expirationTime"], in: source), + expiry.timeIntervalSince(now) > 0 + { + return 1 + } + + return 0 + } + + private static func payloadDiagnostics(payload: [String: Any]) -> String { + let topKeys = payload.keys.sorted() + let dataDict = self.findFirstDictionary(forKeys: ["data", "successResponse", "success_response"], in: payload) + let dataKeys = dataDict?.keys.sorted() ?? [] + let instanceInfo = self.findActiveInstanceInfo(in: payload) + let instanceKeys = instanceInfo?.keys.sorted() ?? [] + let hasQuota = self.findQuotaInfo(in: payload) != nil + let planUsage = + self.anyString(for: ["planUsage", "usageRate", "usage", "usageValue"], in: instanceInfo ?? [:]) ?? + self.findFirstString(forKeys: ["planUsage", "usageRate", "usage", "usageValue"], in: payload) + let compactPlanUsage = planUsage?.replacingOccurrences(of: "\n", with: " ") ?? "none" + let status = self.anyString(for: ["status", "instanceStatus"], in: instanceInfo ?? [:]) ?? "none" + + return "topKeys=\(topKeys.joined(separator: ",")) dataKeys=\(dataKeys.joined(separator: ",")) " + + "instanceKeys=\(instanceKeys.joined(separator: ",")) hasQuota=\(hasQuota ? "1" : "0") " + + "status=\(status) planUsage=\(compactPlanUsage)" + } + + private static func findQuotaInfo(in payload: [String: Any]) -> [String: Any]? { + if let direct = self.findFirstDictionary( + forKeys: ["codingPlanQuotaInfo", "coding_plan_quota_info"], + in: payload) + { + return direct + } + return self.findFirstDictionary( + matchingAnyKey: [ + "per5HourUsedQuota", + "per5HourTotalQuota", + "perWeekUsedQuota", + "perWeekTotalQuota", + "perBillMonthUsedQuota", + "perBillMonthTotalQuota", + ], + in: payload) + } + + private static func findFirstDictionary(forKeys keys: [String], in value: Any) -> [String: Any]? { + guard let dict = value as? [String: Any] else { return nil } + for key in keys { + if let nested = dict[key] as? [String: Any] { + return nested + } + } + for nestedValue in dict.values { + if let nested = self.findFirstDictionary(forKeys: keys, in: nestedValue) { + return nested + } + } + if let array = value as? [Any] { + for item in array { + if let nested = self.findFirstDictionary(forKeys: keys, in: item) { + return nested + } + } + } + return nil + } + + private static func findFirstDictionary(matchingAnyKey keys: [String], in value: Any) -> [String: Any]? { + if let dict = value as? [String: Any] { + if keys.contains(where: { dict[$0] != nil }) { + return dict + } + for nestedValue in dict.values { + if let nested = self.findFirstDictionary(matchingAnyKey: keys, in: nestedValue) { + return nested + } + } + return nil + } + if let array = value as? [Any] { + for item in array { + if let nested = self.findFirstDictionary(matchingAnyKey: keys, in: item) { + return nested + } + } + } + return nil + } + + private static func findFirstArray(forKeys keys: [String], in value: Any) -> [Any]? { + guard let dict = value as? [String: Any] else { + if let array = value as? [Any] { + for item in array { + if let found = self.findFirstArray(forKeys: keys, in: item) { + return found + } + } + } + return nil + } + for key in keys { + if let array = dict[key] as? [Any] { + return array + } + } + for nested in dict.values { + if let found = self.findFirstArray(forKeys: keys, in: nested) { + return found + } + } + return nil + } + + private static func findFirstInt(forKeys keys: [String], in value: Any) -> Int? { + if let dict = value as? [String: Any] { + for key in keys { + if let parsed = self.parseInt(dict[key]) { + return parsed + } + } + for nested in dict.values { + if let parsed = self.findFirstInt(forKeys: keys, in: nested) { + return parsed + } + } + return nil + } + if let array = value as? [Any] { + for item in array { + if let parsed = self.findFirstInt(forKeys: keys, in: item) { + return parsed + } + } + } + return nil + } + + private static func findFirstString(forKeys keys: [String], in value: Any) -> String? { + if let dict = value as? [String: Any] { + for key in keys { + if let parsed = self.parseString(dict[key]) { + return parsed + } + } + for nested in dict.values { + if let parsed = self.findFirstString(forKeys: keys, in: nested) { + return parsed + } + } + return nil + } + if let array = value as? [Any] { + for item in array { + if let parsed = self.findFirstString(forKeys: keys, in: item) { + return parsed + } + } + } + return nil + } + + private static func findFirstDate(forKeys keys: [String], in value: Any) -> Date? { + if let dict = value as? [String: Any] { + for key in keys { + if let parsed = self.parseDate(dict[key]) { + return parsed + } + } + for nested in dict.values { + if let parsed = self.findFirstDate(forKeys: keys, in: nested) { + return parsed + } + } + return nil + } + if let array = value as? [Any] { + for item in array { + if let parsed = self.findFirstDate(forKeys: keys, in: item) { + return parsed + } + } + } + return nil + } + + private static func expandedJSON(_ value: Any) -> Any { + if let dict = value as? [String: Any] { + var expanded: [String: Any] = [:] + expanded.reserveCapacity(dict.count) + for (key, nested) in dict { + expanded[key] = self.expandedJSON(nested) + } + return expanded + } + if let array = value as? [Any] { + return array.map { self.expandedJSON($0) } + } + if let string = value as? String, + let data = string.data(using: .utf8), + let nested = try? JSONSerialization.jsonObject(with: data, options: []), + nested is [String: Any] || nested is [Any] + { + return self.expandedJSON(nested) + } + return value + } + + private static func anyInt(for keys: [String], in dict: [String: Any]) -> Int? { + for key in keys { + if let value = self.parseInt(dict[key]) { + return value + } + } + return nil + } + + private static func anyString(for keys: [String], in dict: [String: Any]) -> String? { + for key in keys { + if let value = self.parseString(dict[key]) { + return value + } + } + return nil + } + + private static func anyDate(for keys: [String], in dict: [String: Any]) -> Date? { + for key in keys { + if let value = self.parseDate(dict[key]) { + return value + } + } + return nil + } + + private static func anyPercent(for keys: [String], in dict: [String: Any]) -> Double? { + for key in keys { + if let value = self.parsePercent(dict[key]) { + return value + } + } + return nil + } + + private static func anyBool(for keys: [String], in dict: [String: Any]) -> Bool? { + for key in keys { + if let value = self.parseBool(dict[key]) { + return value + } + } + return nil + } + + private static func findFirstPercent(forKeys keys: [String], in value: Any) -> Double? { + if let dict = value as? [String: Any] { + for key in keys { + if let parsed = self.parsePercent(dict[key]) { + return parsed + } + } + for nested in dict.values { + if let parsed = self.findFirstPercent(forKeys: keys, in: nested) { + return parsed + } + } + return nil + } + if let array = value as? [Any] { + for item in array { + if let parsed = self.findFirstPercent(forKeys: keys, in: item) { + return parsed + } + } + } + return nil + } + + private static func parseDate(_ raw: Any?) -> Date? { + if let intValue = self.parseInt(raw) { + if intValue > 1_000_000_000_000 { + return Date(timeIntervalSince1970: TimeInterval(intValue) / 1000) + } + if intValue > 1_000_000_000 { + return Date(timeIntervalSince1970: TimeInterval(intValue)) + } + } + if let string = self.parseString(raw) { + let formatter = ISO8601DateFormatter() + if let date = formatter.date(from: string) { + return date + } + let dateFormatter = DateFormatter() + dateFormatter.locale = Locale(identifier: "en_US_POSIX") + for format in ["yyyy-MM-dd HH:mm", "yyyy-MM-dd HH:mm:ss"] { + dateFormatter.dateFormat = format + if let date = dateFormatter.date(from: string) { + return date + } + } + } + return nil + } + + private static func parseInt(_ raw: Any?) -> Int? { + if let value = raw as? Int { return value } + if let value = raw as? Int64 { return Int(value) } + if let value = raw as? Double { return Int(value) } + if let value = raw as? NSNumber { return value.intValue } + if let value = raw as? String { + let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines) + return Int(trimmed) + } + return nil + } + + private static func parseString(_ raw: Any?) -> String? { + guard let value = raw as? String else { return nil } + let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines) + return trimmed.isEmpty ? nil : trimmed + } + + private static func parsePercent(_ raw: Any?) -> Double? { + if let intValue = self.parseInt(raw) { + return max(0, min(Double(intValue), 100)) + } + guard let rawString = self.parseString(raw) else { return nil } + let cleaned = rawString + .replacingOccurrences(of: "%", with: "") + .trimmingCharacters(in: .whitespacesAndNewlines) + guard let parsed = Double(cleaned) else { return nil } + return max(0, min(parsed, 100)) + } + + private static func parseBool(_ raw: Any?) -> Bool? { + if let value = raw as? Bool { + return value + } + if let number = raw as? NSNumber { + return number.boolValue + } + guard let string = self.parseString(raw)?.lowercased() else { return nil } + switch string { + case "true", "1", "yes", "active", "valid": + return true + case "false", "0", "no", "inactive", "invalid", "expired": + return false + default: + return nil + } + } + + private static func matchFirstGroup(pattern: String, in text: String) -> String? { + guard let regex = try? NSRegularExpression(pattern: pattern, options: []) else { + return nil + } + let range = NSRange(text.startIndex.. 1, + let valueRange = Range(match.range(at: 1), in: text) + else { + return nil + } + let value = text[valueRange].trimmingCharacters(in: .whitespacesAndNewlines) + return value.isEmpty ? nil : String(value) + } + + private static func extractConsoleSECToken(from html: String) -> String? { + let patterns = [ + #"SEC_TOKEN\s*:\s*\"([^\"]+)\""#, + #"SEC_TOKEN\s*:\s*'([^']+)'"#, + #"secToken\s*:\s*\"([^\"]+)\""#, + #"sec_token\s*:\s*\"([^\"]+)\""#, + #"sec_token\s*:\s*'([^']+)'"#, + #"\"SEC_TOKEN\"\s*:\s*\"([^\"]+)\""#, + #"\"sec_token\"\s*:\s*\"([^\"]+)\""#, + ] + + for pattern in patterns { + if let token = self.matchFirstGroup(pattern: pattern, in: html), !token.isEmpty { + return token + } + } + return nil + } + + private static func extractCookieValue(name: String, from cookieHeader: String) -> String? { + let segments = cookieHeader.split(separator: ";") + for segment in segments { + let part = segment.trimmingCharacters(in: .whitespacesAndNewlines) + guard let index = part.firstIndex(of: "=") else { continue } + let key = String(part[.. Providers -> Alibaba if the Alibaba console exposes a " + + "compatible session, or switch regions if quota API access is available there." + case let .networkError(message): + "Alibaba Coding Plan network error: \(message)" + case let .apiError(message): + "Alibaba Coding Plan API error: \(message)" + case let .parseFailed(message): + "Failed to parse Alibaba Coding Plan response: \(message)" + } + } +} + +// swiftlint:enable type_body_length diff --git a/Sources/CodexBarCore/Providers/Alibaba/AlibabaCodingPlanUsageSnapshot.swift b/Sources/CodexBarCore/Providers/Alibaba/AlibabaCodingPlanUsageSnapshot.swift new file mode 100644 index 0000000..2385b9b --- /dev/null +++ b/Sources/CodexBarCore/Providers/Alibaba/AlibabaCodingPlanUsageSnapshot.swift @@ -0,0 +1,126 @@ +import Foundation + +public struct AlibabaCodingPlanUsageSnapshot: Sendable { + public let planName: String? + public let fiveHourUsedQuota: Int? + public let fiveHourTotalQuota: Int? + public let fiveHourNextRefreshTime: Date? + public let weeklyUsedQuota: Int? + public let weeklyTotalQuota: Int? + public let weeklyNextRefreshTime: Date? + public let monthlyUsedQuota: Int? + public let monthlyTotalQuota: Int? + public let monthlyNextRefreshTime: Date? + public let updatedAt: Date + + public init( + planName: String?, + fiveHourUsedQuota: Int?, + fiveHourTotalQuota: Int?, + fiveHourNextRefreshTime: Date?, + weeklyUsedQuota: Int?, + weeklyTotalQuota: Int?, + weeklyNextRefreshTime: Date?, + monthlyUsedQuota: Int?, + monthlyTotalQuota: Int?, + monthlyNextRefreshTime: Date?, + updatedAt: Date) + { + self.planName = planName + self.fiveHourUsedQuota = fiveHourUsedQuota + self.fiveHourTotalQuota = fiveHourTotalQuota + self.fiveHourNextRefreshTime = fiveHourNextRefreshTime + self.weeklyUsedQuota = weeklyUsedQuota + self.weeklyTotalQuota = weeklyTotalQuota + self.weeklyNextRefreshTime = weeklyNextRefreshTime + self.monthlyUsedQuota = monthlyUsedQuota + self.monthlyTotalQuota = monthlyTotalQuota + self.monthlyNextRefreshTime = monthlyNextRefreshTime + self.updatedAt = updatedAt + } +} + +extension AlibabaCodingPlanUsageSnapshot { + public func toUsageSnapshot() -> UsageSnapshot { + let primaryPercent = Self.usedPercent(used: self.fiveHourUsedQuota, total: self.fiveHourTotalQuota) + let secondaryPercent = Self.usedPercent(used: self.weeklyUsedQuota, total: self.weeklyTotalQuota) + let tertiaryPercent = Self.usedPercent(used: self.monthlyUsedQuota, total: self.monthlyTotalQuota) + + let primary: RateWindow? = if let primaryPercent { + RateWindow( + usedPercent: primaryPercent, + windowMinutes: 5 * 60, + resetsAt: Self.normalizedFiveHourReset( + self.fiveHourNextRefreshTime, + updatedAt: self.updatedAt), + resetDescription: Self.usageDetail(used: self.fiveHourUsedQuota, total: self.fiveHourTotalQuota)) + } else { + nil + } + + let secondary: RateWindow? = if let secondaryPercent { + RateWindow( + usedPercent: secondaryPercent, + windowMinutes: 7 * 24 * 60, + resetsAt: self.weeklyNextRefreshTime, + resetDescription: Self.usageDetail(used: self.weeklyUsedQuota, total: self.weeklyTotalQuota)) + } else { + nil + } + + let tertiary: RateWindow? = if let tertiaryPercent { + RateWindow( + usedPercent: tertiaryPercent, + windowMinutes: 30 * 24 * 60, + resetsAt: self.monthlyNextRefreshTime, + resetDescription: Self.usageDetail(used: self.monthlyUsedQuota, total: self.monthlyTotalQuota)) + } else { + nil + } + + let loginMethod = self.planName?.trimmingCharacters(in: .whitespacesAndNewlines) + let identity = ProviderIdentitySnapshot( + providerID: .alibaba, + accountEmail: nil, + accountOrganization: nil, + loginMethod: loginMethod) + + return UsageSnapshot( + primary: primary, + secondary: secondary, + tertiary: tertiary, + providerCost: nil, + updatedAt: self.updatedAt, + identity: identity) + } + + private static func usedPercent(used: Int?, total: Int?) -> Double? { + guard let used, let total, total > 0 else { return nil } + let normalizedUsed = max(0, min(used, total)) + return Double(normalizedUsed) / Double(total) * 100 + } + + private static func limitDescription(total: Int?, label: String) -> String? { + guard let total, total > 0 else { return nil } + return "\(total) requests / \(label)" + } + + private static func usageDetail(used: Int?, total: Int?) -> String? { + guard let used, let total, total > 0 else { return nil } + return "\(used) / \(total) used" + } + + private static func normalizedFiveHourReset(_ raw: Date?, updatedAt: Date) -> Date? { + guard let raw else { return nil } + if raw.timeIntervalSince(updatedAt) >= 60 { + return raw + } + + let shifted = raw.addingTimeInterval(TimeInterval(5 * 60 * 60)) + if shifted.timeIntervalSince(updatedAt) >= 60 { + return shifted + } + + return updatedAt.addingTimeInterval(TimeInterval(5 * 60 * 60)) + } +} diff --git a/Sources/CodexBarCore/Providers/Alibaba/AlibabaTokenPlanAPIRegion.swift b/Sources/CodexBarCore/Providers/Alibaba/AlibabaTokenPlanAPIRegion.swift new file mode 100644 index 0000000..ae7453f --- /dev/null +++ b/Sources/CodexBarCore/Providers/Alibaba/AlibabaTokenPlanAPIRegion.swift @@ -0,0 +1,60 @@ +import Foundation + +public enum AlibabaTokenPlanAPIRegion: String, CaseIterable, Sendable { + case international = "intl" + case chinaMainland = "cn" + + public var displayName: String { + switch self { + case .international: + "International (modelstudio.console.alibabacloud.com)" + case .chinaMainland: + "China mainland (bailian.console.aliyun.com)" + } + } + + public var gatewayBaseURLString: String { + switch self { + case .international: + "https://modelstudio.console.alibabacloud.com" + case .chinaMainland: + "https://bailian.console.aliyun.com" + } + } + + public var dashboardOriginURLString: String { + self.gatewayBaseURLString + } + + public var dashboardURL: URL { + switch self { + case .international: + URL( + string: "https://modelstudio.console.alibabacloud.com/ap-southeast-1/?tab=plan#/efm/subscription/token-plan")! + case .chinaMainland: + URL(string: "https://bailian.console.aliyun.com/cn-beijing?tab=plan#/efm/subscription/token-plan")! + } + } + + public var currentRegionID: String { + switch self { + case .international: + "ap-southeast-1" + case .chinaMainland: + "cn-beijing" + } + } + + public var tokenPlanProductCode: String { + switch self { + case .international: + "sfm_tokenplanteams_dp_intl" + case .chinaMainland: + "sfm_tokenplanteams_dp_cn" + } + } + + public var cookieCacheScope: CookieHeaderCache.Scope { + .providerVariant("alibaba-token-plan.\(self.rawValue)") + } +} diff --git a/Sources/CodexBarCore/Providers/Alibaba/AlibabaTokenPlanCookieHeader.swift b/Sources/CodexBarCore/Providers/Alibaba/AlibabaTokenPlanCookieHeader.swift new file mode 100644 index 0000000..14a99af --- /dev/null +++ b/Sources/CodexBarCore/Providers/Alibaba/AlibabaTokenPlanCookieHeader.swift @@ -0,0 +1,163 @@ +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +struct AlibabaTokenPlanCookieHeaders { + private static let cachedAPIHeaderName = "__codexbar_alibaba_token_plan_api" + private static let cachedDashboardHeaderName = "__codexbar_alibaba_token_plan_dashboard" + + let apiCookieHeader: String + let dashboardCookieHeader: String + + init(apiCookieHeader: String, dashboardCookieHeader: String) { + self.apiCookieHeader = apiCookieHeader + self.dashboardCookieHeader = dashboardCookieHeader + } + + init?(singleHeader raw: String?) { + guard let normalized = CookieHeaderNormalizer.normalize(raw) else { return nil } + self.apiCookieHeader = normalized + self.dashboardCookieHeader = normalized + } + + init?(cachedHeader raw: String?) { + var valuesByName: [String: String] = [:] + for pair in CookieHeaderNormalizer.pairs(from: raw ?? "") { + valuesByName[pair.name] = pair.value + } + if let encodedAPI = valuesByName[Self.cachedAPIHeaderName], + let encodedDashboard = valuesByName[Self.cachedDashboardHeaderName], + let apiHeader = Self.decodeCachedHeader(encodedAPI), + let dashboardHeader = Self.decodeCachedHeader(encodedDashboard), + let normalizedAPI = CookieHeaderNormalizer.normalize(apiHeader), + let normalizedDashboard = CookieHeaderNormalizer.normalize(dashboardHeader) + { + self.init(apiCookieHeader: normalizedAPI, dashboardCookieHeader: normalizedDashboard) + return + } + + self.init(singleHeader: raw) + } + + var cacheCookieHeader: String { + [ + "\(Self.cachedAPIHeaderName)=\(Self.encodeCachedHeader(self.apiCookieHeader))", + "\(Self.cachedDashboardHeaderName)=\(Self.encodeCachedHeader(self.dashboardCookieHeader))", + ].joined(separator: "; ") + } + + var apiCookieNames: [String] { + Self.cookieNames(from: self.apiCookieHeader) + } + + var dashboardCookieNames: [String] { + Self.cookieNames(from: self.dashboardCookieHeader) + } + + func hasCookie(named name: String) -> Bool { + Self.cookieNames(from: self.apiCookieHeader).contains(name) || + Self.cookieNames(from: self.dashboardCookieHeader).contains(name) + } + + private static func cookieNames(from header: String) -> [String] { + CookieHeaderNormalizer.pairs(from: header) + .map(\.name) + .filter { !$0.isEmpty } + .uniquedSorted() + } + + private static func encodeCachedHeader(_ header: String) -> String { + Data(header.utf8).base64EncodedString() + } + + private static func decodeCachedHeader(_ encoded: String) -> String? { + guard let data = Data(base64Encoded: encoded) else { return nil } + return String(data: data, encoding: .utf8) + } +} + +enum AlibabaTokenPlanCookieHeader { + static func headers( + from cookies: [HTTPCookie], + region: AlibabaTokenPlanAPIRegion = .international, + environment: [String: String] = ProcessInfo.processInfo.environment) -> AlibabaTokenPlanCookieHeaders? + { + guard let apiHeader = self.header( + from: cookies, + targetURL: AlibabaTokenPlanUsageFetcher.resolveQuotaURL(region: region, environment: environment)), + let dashboardHeader = self.header( + from: cookies, + targetURL: AlibabaTokenPlanUsageFetcher.dashboardURL(region: region, environment: environment)) + else { + return nil + } + return AlibabaTokenPlanCookieHeaders(apiCookieHeader: apiHeader, dashboardCookieHeader: dashboardHeader) + } + + static func header(from cookies: [HTTPCookie], targetURL: URL) -> String? { + var byName: [String: HTTPCookie] = [:] + for cookie in cookies { + guard !cookie.name.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else { continue } + guard !cookie.value.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else { continue } + if let expiry = cookie.expiresDate, expiry < Date() { continue } + guard self.matchesRequestURL(cookie: cookie, url: targetURL) else { continue } + + if let existing = byName[cookie.name] { + if self.cookieSortKey(for: cookie) >= self.cookieSortKey(for: existing) { + byName[cookie.name] = cookie + } + } else { + byName[cookie.name] = cookie + } + } + + guard !byName.isEmpty else { return nil } + return byName.keys.sorted().compactMap { name in + guard let cookie = byName[name] else { return nil } + return "\(cookie.name)=\(cookie.value)" + }.joined(separator: "; ") + } + + private static func matchesRequestURL(cookie: HTTPCookie, url: URL) -> Bool { + guard let host = url.host?.lowercased() else { return false } + let normalizedDomain = cookie.domain.lowercased().trimmingCharacters(in: CharacterSet(charactersIn: ".")) + guard !normalizedDomain.isEmpty else { return false } + guard host == normalizedDomain || host.hasSuffix(".\(normalizedDomain)") else { return false } + + let cookiePath = cookie.path.isEmpty ? "/" : cookie.path + let requestPath = url.path.isEmpty ? "/" : url.path + if requestPath == cookiePath { + return true + } + guard requestPath.hasPrefix(cookiePath) else { return false } + guard cookiePath != "/" else { return true } + if cookiePath.hasSuffix("/") { + return true + } + guard + let boundaryIndex = requestPath.index( + requestPath.startIndex, + offsetBy: cookiePath.count, + limitedBy: requestPath.endIndex), + boundaryIndex < requestPath.endIndex + else { + return true + } + return requestPath[boundaryIndex] == "/" + } + + private static func cookieSortKey(for cookie: HTTPCookie) -> (Int, Int, Date) { + let pathLength = cookie.path.count + let normalizedDomain = cookie.domain.lowercased().trimmingCharacters(in: CharacterSet(charactersIn: ".")) + let domainLength = normalizedDomain.count + let expiry = cookie.expiresDate ?? .distantPast + return (pathLength, domainLength, expiry) + } +} + +extension [String] { + fileprivate func uniquedSorted() -> [String] { + Array(Set(self)).sorted() + } +} diff --git a/Sources/CodexBarCore/Providers/Alibaba/AlibabaTokenPlanProviderDescriptor.swift b/Sources/CodexBarCore/Providers/Alibaba/AlibabaTokenPlanProviderDescriptor.swift new file mode 100644 index 0000000..6b5012a --- /dev/null +++ b/Sources/CodexBarCore/Providers/Alibaba/AlibabaTokenPlanProviderDescriptor.swift @@ -0,0 +1,289 @@ +import Foundation + +#if os(macOS) +import SweetCookieKit +#endif + +public enum AlibabaTokenPlanProviderDescriptor { + public static let descriptor: ProviderDescriptor = Self.makeDescriptor() + + static func makeDescriptor() -> ProviderDescriptor { + #if os(macOS) + let browserOrder: BrowserCookieImportOrder = [ + .chrome, + .chromeBeta, + .brave, + .edge, + .arc, + .firefox, + .safari, + ] + #else + let browserOrder: BrowserCookieImportOrder? = nil + #endif + + return ProviderDescriptor( + id: .alibabatokenplan, + metadata: ProviderMetadata( + id: .alibabatokenplan, + displayName: "Alibaba Token Plan", + sessionLabel: "Credits", + weeklyLabel: "Usage", + opusLabel: nil, + supportsOpus: false, + supportsCredits: false, + creditsHint: "", + toggleTitle: "Show Alibaba Token Plan usage", + cliName: "alibaba-token-plan", + defaultEnabled: false, + isPrimaryProvider: false, + usesAccountFallback: false, + browserCookieOrder: browserOrder, + dashboardURL: AlibabaTokenPlanUsageFetcher.dashboardURL.absoluteString, + statusPageURL: nil, + statusLinkURL: "https://status.aliyun.com"), + branding: ProviderBranding( + iconStyle: .alibaba, + iconResourceName: "ProviderIcon-alibaba", + color: ProviderColor(red: 1.0, green: 106 / 255, blue: 0)), + tokenCost: ProviderTokenCostConfig( + supportsTokenCost: false, + noDataMessage: { "Alibaba Token Plan cost summary is not supported." }), + fetchPlan: ProviderFetchPlan( + sourceModes: [.auto, .web], + pipeline: ProviderFetchPipeline(resolveStrategies: self.resolveStrategies)), + cli: ProviderCLIConfig( + name: "alibaba-token-plan", + aliases: ["alibaba-token", "bailian-token-plan"], + versionDetector: nil)) + } + + private static func resolveStrategies(context: ProviderFetchContext) async -> [any ProviderFetchStrategy] { + guard context.settings?.alibabaTokenPlan?.cookieSource != .off else { return [] } + switch context.sourceMode { + case .auto, .web: + return [AlibabaTokenPlanWebFetchStrategy()] + case .api, .cli, .oauth: + return [] + } + } +} + +struct AlibabaTokenPlanWebFetchStrategy: ProviderFetchStrategy { + private static let log = CodexBarLog.logger("alibaba-token-plan") + + let id: String = "alibaba-token-plan.web" + let kind: ProviderFetchKind = .web + + func isAvailable(_ context: ProviderFetchContext) async -> Bool { + guard context.settings?.alibabaTokenPlan?.cookieSource != .off else { return false } + let region = context.settings?.alibabaTokenPlan?.apiRegion ?? .international + + if AlibabaTokenPlanSettingsReader.cookieHeader(environment: context.env) != nil { + return true + } + + if let settings = context.settings?.alibabaTokenPlan, + settings.cookieSource == .manual + { + return CookieHeaderNormalizer.normalize(settings.manualCookieHeader) != nil + } + + #if os(macOS) + if let cached = Self.cachedCookieEntry(region: region), + !cached.cookieHeader.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty + { + return true + } + return true + #else + return false + #endif + } + + func fetch(_ context: ProviderFetchContext) async throws -> ProviderFetchResult { + let cookieSource = context.settings?.alibabaTokenPlan?.cookieSource ?? .auto + let region = context.settings?.alibabaTokenPlan?.apiRegion ?? .international + let cookieHeaders = try Self.resolveCookieHeaders(context: context, allowCached: true, region: region) + do { + let usage = try await AlibabaTokenPlanUsageFetcher.fetchUsage( + apiCookieHeader: cookieHeaders.apiCookieHeader, + dashboardCookieHeader: cookieHeaders.dashboardCookieHeader, + region: region, + environment: context.env) + return self.makeResult(usage: usage.toUsageSnapshot(), sourceLabel: "web") + } catch let error as AlibabaTokenPlanUsageError + where error.isCredentialFailure && cookieSource != .manual + { + #if os(macOS) + CookieHeaderCache.clear(provider: .alibabatokenplan, scope: region.cookieCacheScope) + let refreshedHeaders = try Self.resolveCookieHeaders(context: context, allowCached: false, region: region) + let usage = try await AlibabaTokenPlanUsageFetcher.fetchUsage( + apiCookieHeader: refreshedHeaders.apiCookieHeader, + dashboardCookieHeader: refreshedHeaders.dashboardCookieHeader, + region: region, + environment: context.env) + return self.makeResult(usage: usage.toUsageSnapshot(), sourceLabel: "web") + #else + throw error + #endif + } + } + + func shouldFallback(on _: Error, context _: ProviderFetchContext) -> Bool { + false + } + + static func resolveCookieHeader(context: ProviderFetchContext, allowCached: Bool) throws -> String { + try self.resolveCookieHeaders(context: context, allowCached: allowCached, region: .international) + .apiCookieHeader + } + + static func resolveCookieHeaders( + context: ProviderFetchContext, + allowCached: Bool, + region: AlibabaTokenPlanAPIRegion = .international) throws -> AlibabaTokenPlanCookieHeaders + { + if let settings = context.settings?.alibabaTokenPlan, + settings.cookieSource == .manual + { + guard let headers = AlibabaTokenPlanCookieHeaders(singleHeader: settings.manualCookieHeader) else { + self.log.warning("Alibaba Token Plan manual cookie header is invalid") + throw AlibabaTokenPlanSettingsError.invalidCookie + } + Self.log.info( + "Alibaba Token Plan using manual cookie header", + metadata: [ + "apiCookieNames": headers.apiCookieNames.joined(separator: ","), + "dashboardCookieNames": headers.dashboardCookieNames.joined(separator: ","), + "hasSecToken": headers.hasCookie(named: "sec_token") ? "1" : "0", + ]) + return headers + } + + if let envCookie = AlibabaTokenPlanSettingsReader.cookieHeader(environment: context.env), + let headers = AlibabaTokenPlanCookieHeaders(singleHeader: envCookie) + { + Self.log.info( + "Alibaba Token Plan using environment cookie header", + metadata: [ + "apiCookieNames": headers.apiCookieNames.joined(separator: ","), + "dashboardCookieNames": headers.dashboardCookieNames.joined(separator: ","), + "hasSecToken": headers.hasCookie(named: "sec_token") ? "1" : "0", + ]) + return headers + } + + #if os(macOS) + if allowCached, + let cached = Self.cachedCookieEntry(region: region), + let headers = AlibabaTokenPlanCookieHeaders(cachedHeader: cached.cookieHeader) + { + Self.log.info( + "Alibaba Token Plan using cached browser cookie header", + metadata: [ + "source": cached.sourceLabel, + "apiCookieNames": headers.apiCookieNames.joined(separator: ","), + "dashboardCookieNames": headers.dashboardCookieNames.joined(separator: ","), + "hasSecToken": headers.hasCookie(named: "sec_token") ? "1" : "0", + ]) + return headers + } + + do { + var importLog: [String] = [] + let session = try AlibabaCodingPlanCookieImporter.importSession( + browserDetection: context.browserDetection, + logger: { importLog.append($0) }) + let rawCookieNames = session.cookies.map(\.name).filter { !$0.isEmpty }.uniquedSorted() + guard let headers = AlibabaTokenPlanCookieHeader.headers( + from: session.cookies, + region: region, + environment: context.env) + else { + Self.log.warning( + "Alibaba Token Plan browser cookie header was empty", + metadata: [ + "source": session.sourceLabel, + "rawCookieNames": rawCookieNames.joined(separator: ","), + ]) + throw AlibabaTokenPlanSettingsError.missingCookie( + details: "No Alibaba Token Plan browser cookies were available after import.") + } + CookieHeaderCache.store( + provider: .alibabatokenplan, + scope: region.cookieCacheScope, + cookieHeader: headers.cacheCookieHeader, + sourceLabel: session.sourceLabel) + Self.log.info( + "Alibaba Token Plan imported browser cookies", + metadata: [ + "source": session.sourceLabel, + "rawCookieNames": rawCookieNames.joined(separator: ","), + "apiCookieNames": headers.apiCookieNames.joined(separator: ","), + "dashboardCookieNames": headers.dashboardCookieNames.joined(separator: ","), + "hasSecToken": headers.hasCookie(named: "sec_token") ? "1" : "0", + "importLogLines": "\(importLog.count)", + ]) + return headers + } catch { + Self.log.warning( + "Alibaba Token Plan cookie resolution failed", + metadata: ["error": error.localizedDescription]) + throw AlibabaTokenPlanSettingsError.missingCookie(details: Self.missingCookieDetails(from: error)) + } + #else + throw AlibabaTokenPlanSettingsError.missingCookie() + #endif + } + + #if os(macOS) + /// The former unscoped cache only ever represented the China gateway. Never expose it to + /// International requests; migrate it into the China scope after a successful scoped write. + private static func cachedCookieEntry(region: AlibabaTokenPlanAPIRegion) -> CookieHeaderCache.Entry? { + if let scoped = CookieHeaderCache.load(provider: .alibabatokenplan, scope: region.cookieCacheScope) { + return scoped + } + guard region == .chinaMainland, + let legacy = CookieHeaderCache.load(provider: .alibabatokenplan) + else { return nil } + + CookieHeaderCache.store( + provider: .alibabatokenplan, + scope: region.cookieCacheScope, + cookieHeader: legacy.cookieHeader, + sourceLabel: legacy.sourceLabel, + now: legacy.storedAt) + if let migrated = CookieHeaderCache.load(provider: .alibabatokenplan, scope: region.cookieCacheScope) { + CookieHeaderCache.clear(provider: .alibabatokenplan) + return migrated + } + return legacy + } + #endif + + private static func missingCookieDetails(from error: Error) -> String? { + if case let AlibabaCodingPlanSettingsError.missingCookie(details) = error { + return details + } + let message = error.localizedDescription.trimmingCharacters(in: .whitespacesAndNewlines) + return message.isEmpty ? nil : message + } +} + +extension [String] { + fileprivate func uniquedSorted() -> [String] { + Array(Set(self)).sorted() + } +} + +extension AlibabaTokenPlanUsageError { + fileprivate var isCredentialFailure: Bool { + switch self { + case .loginRequired, .invalidCredentials: + true + case .apiError, .networkError, .parseFailed: + false + } + } +} diff --git a/Sources/CodexBarCore/Providers/Alibaba/AlibabaTokenPlanSettingsReader.swift b/Sources/CodexBarCore/Providers/Alibaba/AlibabaTokenPlanSettingsReader.swift new file mode 100644 index 0000000..1074d6c --- /dev/null +++ b/Sources/CodexBarCore/Providers/Alibaba/AlibabaTokenPlanSettingsReader.swift @@ -0,0 +1,67 @@ +import Foundation + +public struct AlibabaTokenPlanSettingsReader: Sendable { + public static let cookieHeaderKey = "ALIBABA_TOKEN_PLAN_COOKIE" + public static let hostKey = "ALIBABA_TOKEN_PLAN_HOST" + public static let quotaURLKey = "ALIBABA_TOKEN_PLAN_QUOTA_URL" + + private static let endpointValidator = ProviderEndpointOverrideValidator( + allowedHosts: [ + "modelstudio.console.alibabacloud.com", + "bailian.console.aliyun.com", + ]) + + public static func cookieHeader( + environment: [String: String] = ProcessInfo.processInfo.environment) -> String? + { + self.cleaned(environment[self.cookieHeaderKey]) + } + + public static func hostOverride( + environment: [String: String] = ProcessInfo.processInfo.environment) -> String? + { + self.endpointValidator.validatedHost( + self.cleaned(environment[self.hostKey]), + policy: .allowAnyHTTPSHost) + } + + public static func quotaURL( + environment: [String: String] = ProcessInfo.processInfo.environment) -> URL? + { + self.endpointValidator.validatedURL( + self.cleaned(environment[self.quotaURLKey]), + policy: .allowAnyHTTPSHost) + } + + static func cleaned(_ raw: String?) -> String? { + guard var value = raw?.trimmingCharacters(in: .whitespacesAndNewlines), !value.isEmpty else { + return nil + } + if (value.hasPrefix("\"") && value.hasSuffix("\"")) || + (value.hasPrefix("'") && value.hasSuffix("'")) + { + value = String(value.dropFirst().dropLast()) + } + value = value.trimmingCharacters(in: .whitespacesAndNewlines) + return value.isEmpty ? nil : value + } +} + +public enum AlibabaTokenPlanSettingsError: LocalizedError, Sendable { + case missingCookie(details: String? = nil) + case invalidCookie + + public var errorDescription: String? { + switch self { + case let .missingCookie(details): + let base = "No Alibaba Token Plan session cookies found in browsers. " + + "Sign in to Model Studio/Bailian in Chrome, " + + "allow CodexBar to access Chrome Safe Storage in Keychain Access, " + + "or paste a manual Cookie header." + guard let details, !details.isEmpty else { return base } + return "\(base) \(details)" + case .invalidCookie: + return "Alibaba Token Plan cookie header is invalid." + } + } +} diff --git a/Sources/CodexBarCore/Providers/Alibaba/AlibabaTokenPlanUsageFetcher.swift b/Sources/CodexBarCore/Providers/Alibaba/AlibabaTokenPlanUsageFetcher.swift new file mode 100644 index 0000000..27aee5a --- /dev/null +++ b/Sources/CodexBarCore/Providers/Alibaba/AlibabaTokenPlanUsageFetcher.swift @@ -0,0 +1,997 @@ +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +public enum AlibabaTokenPlanUsageError: LocalizedError, Sendable, Equatable { + case loginRequired + case invalidCredentials + case apiError(String) + case networkError(String) + case parseFailed(String) + + public var errorDescription: String? { + switch self { + case .loginRequired: + "Alibaba Token Plan login required." + case .invalidCredentials: + "Alibaba Token Plan credentials are invalid." + case let .apiError(message): + "Alibaba Token Plan API error: \(message)" + case let .networkError(message): + "Alibaba Token Plan network error: \(message)" + case let .parseFailed(message): + "Could not parse Alibaba Token Plan usage: \(message)" + } + } +} + +// swiftlint:disable:next type_body_length +public struct AlibabaTokenPlanUsageFetcher: Sendable { + private static let log = CodexBarLog.logger("alibaba-token-plan") + private static let bssServiceCode = "BssOpenAPI-V3" + private static let subscriptionSummaryAction = "GetSubscriptionSummary" + private static let browserLikeUserAgent = + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) " + + "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36" + private static let safariLikeUserAgent = + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) " + + "AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.3 Safari/605.1.15" + + public static var dashboardURL: URL { + Self.dashboardURL(region: .international, environment: ProcessInfo.processInfo.environment) + } + + public static func dashboardURL( + region: AlibabaTokenPlanAPIRegion, + environment: [String: String] = ProcessInfo.processInfo.environment) -> URL + { + if let host = AlibabaTokenPlanSettingsReader.hostOverride(environment: environment), + let base = ProviderEndpointOverrideValidator.normalizedHTTPSURL(from: host), + var components = URLComponents(url: base, resolvingAgainstBaseURL: false), + let dashboardComponents = URLComponents(url: region.dashboardURL, resolvingAgainstBaseURL: false) + { + components.path = dashboardComponents.path + components.percentEncodedQuery = dashboardComponents.percentEncodedQuery + components.fragment = dashboardComponents.fragment + return components.url ?? region.dashboardURL + } + return region.dashboardURL + } + + public static func fetchUsage( + cookieHeader: String, + region: AlibabaTokenPlanAPIRegion = .international, + environment: [String: String] = ProcessInfo.processInfo.environment, + now: Date = Date()) async throws -> AlibabaTokenPlanUsageSnapshot + { + guard let headers = AlibabaTokenPlanCookieHeaders(singleHeader: cookieHeader) else { + throw AlibabaTokenPlanSettingsError.invalidCookie + } + return try await self.fetchUsage( + apiCookieHeader: headers.apiCookieHeader, + dashboardCookieHeader: headers.dashboardCookieHeader, + region: region, + environment: environment, + now: now) + } + + static func fetchUsage( + apiCookieHeader: String, + dashboardCookieHeader: String, + region: AlibabaTokenPlanAPIRegion = .international, + environment: [String: String] = ProcessInfo.processInfo.environment, + now: Date = Date(), + session overrideSession: URLSession? = nil) async throws -> AlibabaTokenPlanUsageSnapshot + { + guard let normalizedAPIHeader = CookieHeaderNormalizer.normalize(apiCookieHeader), + let normalizedDashboardHeader = CookieHeaderNormalizer.normalize(dashboardCookieHeader) + else { + throw AlibabaTokenPlanSettingsError.invalidCookie + } + + let url = self.resolveQuotaURL(region: region, environment: environment) + let apiRedirectDiagnostics = RedirectDiagnostics(cookieHeader: normalizedAPIHeader) + let dashboardRedirectDiagnostics: RedirectDiagnostics? + let apiSession: URLSession + let dashboardSession: URLSession + if let overrideSession { + apiSession = overrideSession + dashboardSession = overrideSession + dashboardRedirectDiagnostics = nil + } else { + let dashboardDiagnostics = RedirectDiagnostics(cookieHeader: normalizedDashboardHeader) + apiSession = URLSession( + configuration: .default, + delegate: apiRedirectDiagnostics, + delegateQueue: nil) + dashboardSession = URLSession( + configuration: .default, + delegate: dashboardDiagnostics, + delegateQueue: nil) + dashboardRedirectDiagnostics = dashboardDiagnostics + } + defer { + if overrideSession == nil { + apiSession.invalidateAndCancel() + dashboardSession.invalidateAndCancel() + } + } + let secToken = await self.resolveSECToken( + dashboardCookieHeader: normalizedDashboardHeader, + apiCookieHeader: normalizedAPIHeader, + region: region, + environment: environment, + session: dashboardSession) + Self.log.info( + "Fetching Alibaba Token Plan usage", + metadata: [ + "apiHost": url.host ?? "unknown", + "region": region.rawValue, + "apiCookieNames": self.cookieNamesDescription(from: normalizedAPIHeader), + "dashboardCookieNames": self.cookieNamesDescription(from: normalizedDashboardHeader), + "hasCSRF": self.hasCSRF(in: normalizedAPIHeader) ? "1" : "0", + "secTokenSource": secToken == nil ? "missing" : "resolved", + ]) + + var request = URLRequest(url: url) + request.httpMethod = "POST" + request.timeoutInterval = 20 + request.httpBody = self.subscriptionSummaryRequestBody(region: region, secToken: secToken) + request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") + request.setValue("*/*", forHTTPHeaderField: "Accept") + request.setValue(normalizedAPIHeader, forHTTPHeaderField: "Cookie") + if let csrf = self.extractCookieValue(name: "login_aliyunid_csrf", from: normalizedAPIHeader) ?? + self.extractCookieValue(name: "csrf", from: normalizedAPIHeader) + { + request.setValue(csrf, forHTTPHeaderField: "x-xsrf-token") + request.setValue(csrf, forHTTPHeaderField: "x-csrf-token") + } + request.setValue("XMLHttpRequest", forHTTPHeaderField: "X-Requested-With") + request.setValue(Self.browserLikeUserAgent, forHTTPHeaderField: "User-Agent") + request.setValue(region.dashboardOriginURLString, forHTTPHeaderField: "Origin") + request.setValue( + Self.dashboardURL(region: region, environment: environment).absoluteString, + forHTTPHeaderField: "Referer") + + let data: Data + let response: URLResponse + do { + (data, response) = try await apiSession.data(for: request) + } catch { + Self.log.error( + "Alibaba Token Plan request failed", + metadata: [ + "apiHost": url.host ?? "unknown", + "error": error.localizedDescription, + ]) + throw AlibabaTokenPlanUsageError.networkError(error.localizedDescription) + } + if let dashboardRedirectDiagnostics, !dashboardRedirectDiagnostics.redirects.isEmpty { + Self.log.info( + "Alibaba Token Plan dashboard redirects", + metadata: [ + "count": "\(dashboardRedirectDiagnostics.redirects.count)", + "items": dashboardRedirectDiagnostics.redirects.joined(separator: " | "), + ]) + } + if !apiRedirectDiagnostics.redirects.isEmpty { + Self.log.info( + "Alibaba Token Plan redirects", + metadata: [ + "count": "\(apiRedirectDiagnostics.redirects.count)", + "items": apiRedirectDiagnostics.redirects.joined(separator: " | "), + ]) + } + guard let httpResponse = response as? HTTPURLResponse else { + Self.log.error("Alibaba Token Plan response was not HTTP") + throw AlibabaTokenPlanUsageError.networkError("Invalid response") + } + Self.log.info( + "Alibaba Token Plan HTTP response", + metadata: [ + "status": "\(httpResponse.statusCode)", + "bodyBytes": "\(data.count)", + "contentType": httpResponse.value(forHTTPHeaderField: "Content-Type") ?? "none", + ]) + guard httpResponse.statusCode == 200 else { + if httpResponse.statusCode == 401 || httpResponse.statusCode == 403 { + throw AlibabaTokenPlanUsageError.loginRequired + } + Self.log.error("Alibaba Token Plan returned HTTP \(httpResponse.statusCode)") + throw AlibabaTokenPlanUsageError.apiError("HTTP \(httpResponse.statusCode)") + } + + return try self.parseUsageSnapshot(from: data, now: now) + } + + static func resolveQuotaURL( + region: AlibabaTokenPlanAPIRegion, + environment: [String: String]) -> URL + { + if let override = AlibabaTokenPlanSettingsReader.quotaURL(environment: environment) { + return override + } + if let host = AlibabaTokenPlanSettingsReader.hostOverride(environment: environment), + let hostURL = self.quotaURL(from: host) + { + return hostURL + } + return self.defaultQuotaURL(region: region) + } + + static var defaultQuotaURL: URL { + self.defaultQuotaURL(region: .international) + } + + static func defaultQuotaURL(region: AlibabaTokenPlanAPIRegion) -> URL { + var components = URLComponents(string: region.gatewayBaseURLString)! + components.path = "/data/api.json" + components.queryItems = [ + URLQueryItem(name: "action", value: Self.subscriptionSummaryAction), + URLQueryItem(name: "product", value: Self.bssServiceCode), + URLQueryItem(name: "_tag", value: ""), + ] + return components.url! + } + + static func parseUsageSnapshot(from data: Data, now: Date = Date()) throws -> AlibabaTokenPlanUsageSnapshot { + guard !data.isEmpty else { + throw AlibabaTokenPlanUsageError.parseFailed("Empty response body") + } + + let object: Any + do { + object = try JSONSerialization.jsonObject(with: data, options: []) + } catch { + if self.isLikelyLoginHTML(data) { + throw AlibabaTokenPlanUsageError.loginRequired + } + throw AlibabaTokenPlanUsageError.parseFailed("Invalid JSON response") + } + let expanded = self.expandedJSON(object) + guard let dictionary = expanded as? [String: Any] else { + throw AlibabaTokenPlanUsageError.parseFailed("Unexpected payload") + } + + try self.throwIfErrorPayload(dictionary) + + let summary = self.findSubscriptionSummary(in: dictionary) ?? dictionary + let total = self.anyDouble(for: Self.totalQuotaKeys, in: summary) + let remaining = self.anyDouble(for: Self.remainingQuotaKeys, in: summary) + let used = self.anyDouble(for: Self.usedQuotaKeys, in: summary) ?? + total.flatMap { total in remaining.map { max(0, total - $0) } } + let resetsAt = self.findResetDate(in: summary) ?? self.findResetDate(in: dictionary) + let totalCount = self.anyDouble(for: Self.subscriptionCountKeys, in: summary) + let planName = self.findPlanName(in: summary) ?? ((totalCount ?? 0) > 0 || total != nil ? "TOKEN PLAN" : nil) + + if planName == nil, total == nil, used == nil, remaining == nil, totalCount == nil { + let diagnostics = self.payloadDiagnostics(payload: dictionary) + Self.log.error("Alibaba Token Plan payload missing expected fields: \(diagnostics)") + throw AlibabaTokenPlanUsageError.parseFailed("Missing token plan data (\(diagnostics))") + } + + return AlibabaTokenPlanUsageSnapshot( + planName: planName, + usedQuota: used, + totalQuota: total, + remainingQuota: remaining, + resetsAt: resetsAt, + updatedAt: now) + } + + private static func subscriptionSummaryRequestBody(region: AlibabaTokenPlanAPIRegion, secToken: String?) -> Data { + let paramsObject = ["ProductCode": region.tokenPlanProductCode] + guard let paramsData = try? JSONSerialization.data(withJSONObject: paramsObject, options: []), + let paramsString = String(data: paramsData, encoding: .utf8) + else { + return Data() + } + + var components = URLComponents() + var queryItems = [ + URLQueryItem(name: "product", value: Self.bssServiceCode), + URLQueryItem(name: "action", value: Self.subscriptionSummaryAction), + URLQueryItem(name: "params", value: paramsString), + URLQueryItem(name: "region", value: region.currentRegionID), + ] + if let secToken, !secToken.isEmpty { + queryItems.append(URLQueryItem(name: "sec_token", value: secToken)) + } + components.queryItems = queryItems + return Data((components.percentEncodedQuery ?? "").utf8) + } + + private static func resolveSECToken( + dashboardCookieHeader: String, + apiCookieHeader: String, + region: AlibabaTokenPlanAPIRegion, + environment: [String: String], + session: URLSession) async -> String? + { + let cookieSECToken = self.extractCookieValue(name: "sec_token", from: dashboardCookieHeader) ?? + self.extractCookieValue(name: "sec_token", from: apiCookieHeader) + var request = URLRequest(url: self.dashboardURL(region: region, environment: environment)) + request.httpMethod = "GET" + request.timeoutInterval = 10 + request.setValue(dashboardCookieHeader, forHTTPHeaderField: "Cookie") + request.setValue(Self.safariLikeUserAgent, forHTTPHeaderField: "User-Agent") + request.setValue( + "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", + forHTTPHeaderField: "Accept") + + if let (data, response) = try? await session.data(for: request), + let httpResponse = response as? HTTPURLResponse, + httpResponse.statusCode == 200, + let html = String(data: data, encoding: .utf8), + let token = self.extractSECToken(from: html) + { + Self.log.info( + "Resolved Alibaba Token Plan sec_token from dashboard HTML", + metadata: [ + "dashboardHost": request.url?.host ?? "unknown", + "htmlBytes": "\(data.count)", + ]) + return token + } + + if let token = await self.fetchSECTokenFromUserInfo( + cookieHeader: dashboardCookieHeader, + region: region, + environment: environment, + session: session) + { + return token + } + + if let cookieSECToken, !cookieSECToken.isEmpty { + Self.log.info("Resolved Alibaba Token Plan sec_token from cookies") + return cookieSECToken + } + + Self.log.info( + "Alibaba Token Plan sec_token missing; continuing with cookie-only request", + metadata: [ + "dashboardCookieNames": self.cookieNamesDescription(from: dashboardCookieHeader), + "apiCookieNames": self.cookieNamesDescription(from: apiCookieHeader), + ]) + return nil + } + + private static func fetchSECTokenFromUserInfo( + cookieHeader: String, + region: AlibabaTokenPlanAPIRegion, + environment: [String: String], + session: URLSession) async -> String? + { + let baseURL = self.consoleBaseURL(region: region, environment: environment) + let userInfoURL = baseURL.appendingPathComponent("tool/user/info.json") + var request = URLRequest(url: userInfoURL) + request.httpMethod = "GET" + request.timeoutInterval = 10 + request.setValue(cookieHeader, forHTTPHeaderField: "Cookie") + request.setValue(Self.safariLikeUserAgent, forHTTPHeaderField: "User-Agent") + request.setValue("application/json, text/plain, */*", forHTTPHeaderField: "Accept") + let referer = baseURL.absoluteString.hasSuffix("/") ? baseURL.absoluteString : "\(baseURL.absoluteString)/" + request.setValue(referer, forHTTPHeaderField: "Referer") + + guard let (data, response) = try? await session.data(for: request), + let httpResponse = response as? HTTPURLResponse, + httpResponse.statusCode == 200, + let object = try? JSONSerialization.jsonObject(with: data, options: []) + else { + return nil + } + + let expanded = self.expandedJSON(object) + guard let token = self.findFirstString(forKeys: ["secToken", "sec_token"], in: expanded), + !token.isEmpty + else { + return nil + } + + Self.log.info( + "Resolved Alibaba Token Plan sec_token from user info", + metadata: [ + "userInfoHost": userInfoURL.host ?? "unknown", + "bodyBytes": "\(data.count)", + ]) + return token + } + + private static func consoleBaseURL( + region: AlibabaTokenPlanAPIRegion, + environment: [String: String]) -> URL + { + let dashboard = self.dashboardURL(region: region, environment: environment) + var components = URLComponents() + components.scheme = dashboard.scheme + components.host = dashboard.host + components.port = dashboard.port + return components.url ?? URL(string: region.dashboardOriginURLString)! + } + + private static func quotaURL(from rawHost: String) -> URL? { + let cleaned = AlibabaTokenPlanSettingsReader.cleaned(rawHost) + guard let cleaned else { return nil } + guard let base = ProviderEndpointOverrideValidator.normalizedHTTPSURL(from: cleaned) else { return nil } + var components = URLComponents(url: base, resolvingAgainstBaseURL: false) + let defaultComponents = URLComponents( + url: Self.defaultQuotaURL(region: .international), + resolvingAgainstBaseURL: false) + components?.path = "/data/api.json" + components?.queryItems = defaultComponents?.queryItems + return components?.url + } + + private final class RedirectDiagnostics: NSObject, URLSessionTaskDelegate, @unchecked Sendable { + private let cookieHeader: String + var redirects: [String] = [] + + init(cookieHeader: String) { + self.cookieHeader = cookieHeader + } + + func urlSession( + _: URLSession, + task _: URLSessionTask, + willPerformHTTPRedirection response: HTTPURLResponse, + newRequest request: URLRequest, + completionHandler: @escaping (URLRequest?) -> Void) + { + let from = AlibabaTokenPlanUsageFetcher.redactedURLDescription(response.url) + let to = AlibabaTokenPlanUsageFetcher.redactedURLDescription(request.url) + self.redirects.append("\(response.statusCode) \(from) -> \(to)") + + completionHandler(AlibabaTokenPlanUsageFetcher.redirectedRequest( + response: response, + request: request, + cookieHeader: self.cookieHeader)) + } + } + + private static func redactedURLDescription(_ url: URL?) -> String { + guard let url else { return "unknown" } + var components = URLComponents(url: url, resolvingAgainstBaseURL: false) + components?.query = nil + components?.fragment = nil + return components?.string ?? "\(url.scheme ?? "unknown")://\(url.host ?? "unknown")" + } + + static func redirectedRequest( + response: HTTPURLResponse, + request: URLRequest, + cookieHeader: String) -> URLRequest? + { + guard request.url?.scheme?.lowercased() == "https" else { + return nil + } + + var updated = request + if self.shouldForwardRedirectCookies(from: response.url, to: request.url) { + updated.setValue(cookieHeader, forHTTPHeaderField: "Cookie") + } else { + updated.setValue(nil, forHTTPHeaderField: "Cookie") + } + return updated + } + + private static func shouldForwardRedirectCookies(from sourceURL: URL?, to targetURL: URL?) -> Bool { + guard let sourceHost = sourceURL?.host?.lowercased(), + let targetHost = targetURL?.host?.lowercased() + else { + return false + } + return sourceHost == targetHost + } + + private static func throwIfErrorPayload(_ dictionary: [String: Any]) throws { + if self.parseBool(dictionary["successResponse"]) == false { + if let statusCode = self.findFirstInt(forKeys: ["statusCode", "status_code", "code"], in: dictionary), + statusCode == 401 || statusCode == 403 + { + throw AlibabaTokenPlanUsageError.invalidCredentials + } + let code = self.findFirstString(forKeys: ["code", "status", "statusCode"], in: dictionary) + let message = self.findFirstString(forKeys: ["message", "msg", "statusMessage"], in: dictionary) ?? + code ?? + "request was not successful" + if self.isLoginOrTokenError(code: code, message: message) { + throw AlibabaTokenPlanUsageError.loginRequired + } + throw AlibabaTokenPlanUsageError.apiError(message) + } + + if self.findBoolValues(forKeys: ["Success", "success"], in: dictionary).contains(false) { + let code = self.findFirstString(forKeys: ["Code", "code"], in: dictionary) + let message = self.findFirstString(forKeys: ["Message", "message", "msg", "Code", "code"], in: dictionary) + ?? "request was not successful" + if self.isLoginOrTokenError(code: code, message: message) { + throw AlibabaTokenPlanUsageError.loginRequired + } + throw AlibabaTokenPlanUsageError.apiError(message) + } + + if let statusCode = self.findFirstInt(forKeys: ["statusCode", "status_code", "code"], in: dictionary), + statusCode != 0, + statusCode != 200 + { + let message = self.findFirstString( + forKeys: ["statusMessage", "status_msg", "message", "msg"], + in: dictionary) + ?? "status code \(statusCode)" + if statusCode == 401 || statusCode == 403 { + throw AlibabaTokenPlanUsageError.invalidCredentials + } + throw AlibabaTokenPlanUsageError.apiError(message) + } + + let codeText = self.findFirstString(forKeys: ["code", "status", "statusCode"], in: dictionary)?.lowercased() + let messageText = self.findFirstString(forKeys: ["message", "msg", "statusMessage"], in: dictionary)? + .lowercased() + if self.isLoginOrTokenError(code: codeText, message: messageText) { + throw AlibabaTokenPlanUsageError.loginRequired + } + } + + private static func isLoginOrTokenError(code: String?, message: String?) -> Bool { + let combined = [code, message] + .compactMap { $0?.lowercased() } + .joined(separator: " ") + return combined.contains("needlogin") || + combined.contains("login") || + combined.contains("postonlyortokenerror") || + combined.contains("tokenerror") || + combined.contains("request has expired") || + combined.contains("refresh page") || + combined.contains("请求已经过期") + } + + private static let planNameKeys = [ + "planName", + "plan_name", + "packageName", + "package_name", + "commodityName", + "commodity_name", + "instanceName", + "instance_name", + "displayName", + "display_name", + "ProductName", + "productName", + "name", + "title", + "planType", + "plan_type", + ] + private static let usedQuotaKeys = [ + "usedQuota", + "used_quota", + "usedCredits", + "usedCredit", + "consumedCredits", + "usage", + "used", + "usedAmount", + "consumeAmount", + "usedValue", + "UsedValue", + "consumedValue", + "ConsumedValue", + ] + private static let totalQuotaKeys = [ + "totalQuota", + "total_quota", + "totalCredits", + "totalCredit", + "quota", + "creditLimit", + "creditsTotal", + "monthlyTotalQuota", + "amount", + "totalValue", + "TotalValue", + ] + private static let remainingQuotaKeys = [ + "remainingQuota", + "remainQuota", + "remainingCredits", + "remainingCredit", + "availableCredits", + "balance", + "remaining", + "availableAmount", + "remainAmount", + "totalSurplusValue", + "TotalSurplusValue", + "surplusValue", + "SurplusValue", + ] + private static let subscriptionCountKeys = [ + "totalCount", + "TotalCount", + "subscriptionTotalNumber", + "SubscriptionTotalNumber", + ] + private static let resetDateKeys = [ + "nextRefreshTime", + "resetTime", + "periodEndTime", + "billingCycleEnd", + "billCycleEndTime", + "expireTime", + "expirationTime", + "endTime", + "validEndTime", + "instanceEndTime", + "nearestExpireDate", + "NearestExpireDate", + ] + + private static func findSubscriptionSummary(in payload: [String: Any]) -> [String: Any]? { + if let data = self.findFirstDictionary( + forKeys: ["Data", "data", "successResponse", "success_response"], + in: payload), + self.containsSubscriptionSummaryFields(data) + { + return data + } + return self.findFirstDictionary( + matchingAnyKey: Self.usedQuotaKeys + Self.totalQuotaKeys + Self.remainingQuotaKeys + + Self.subscriptionCountKeys, + in: payload) + } + + private static func containsSubscriptionSummaryFields(_ payload: [String: Any]) -> Bool { + let keys = self.usedQuotaKeys + self.totalQuotaKeys + self.remainingQuotaKeys + self.subscriptionCountKeys + return keys.contains { payload[$0] != nil } + } + + private static func findPlanName(in payload: [String: Any]) -> String? { + self.anyString(for: self.planNameKeys, in: payload) ?? + self.findFirstString(forKeys: self.planNameKeys, in: payload) + } + + private static func findResetDate(in payload: [String: Any]) -> Date? { + self.anyDate(for: self.resetDateKeys, in: payload) ?? + self.findFirstDate(forKeys: self.resetDateKeys, in: payload) + } + + private static func payloadDiagnostics(payload: [String: Any]) -> String { + let topKeys = payload.keys.sorted() + let dataDict = self.findFirstDictionary( + forKeys: ["Data", "data", "successResponse", "success_response"], + in: payload) + let dataKeys = dataDict?.keys.sorted() ?? [] + return "topKeys=\(topKeys.joined(separator: ",")) dataKeys=\(dataKeys.joined(separator: ","))" + } + + private static func isLikelyLoginHTML(_ data: Data) -> Bool { + guard let text = String(data: data, encoding: .utf8)?.lowercased() else { return false } + return text.contains(" [String: Any]? { + if let dict = value as? [String: Any] { + for key in keys { + if let nested = dict[key] as? [String: Any] { + return nested + } + } + for nestedValue in dict.values { + if let nested = self.findFirstDictionary(forKeys: keys, in: nestedValue) { + return nested + } + } + return nil + } + if let array = value as? [Any] { + for item in array { + if let nested = self.findFirstDictionary(forKeys: keys, in: item) { + return nested + } + } + } + return nil + } + + private static func findFirstDictionary(matchingAnyKey keys: [String], in value: Any) -> [String: Any]? { + if let dict = value as? [String: Any] { + if keys.contains(where: { dict[$0] != nil }) { + return dict + } + for nestedValue in dict.values { + if let nested = self.findFirstDictionary(matchingAnyKey: keys, in: nestedValue) { + return nested + } + } + return nil + } + if let array = value as? [Any] { + for item in array { + if let nested = self.findFirstDictionary(matchingAnyKey: keys, in: item) { + return nested + } + } + } + return nil + } + + private static func findFirstString(forKeys keys: [String], in value: Any) -> String? { + if let dict = value as? [String: Any] { + for key in keys { + if let parsed = self.parseString(dict[key]) { + return parsed + } + } + for nestedValue in dict.values { + if let parsed = self.findFirstString(forKeys: keys, in: nestedValue) { + return parsed + } + } + return nil + } + if let array = value as? [Any] { + for item in array { + if let parsed = self.findFirstString(forKeys: keys, in: item) { + return parsed + } + } + } + return nil + } + + private static func findBoolValues(forKeys keys: [String], in value: Any) -> [Bool] { + if let dict = value as? [String: Any] { + let directValues = keys.compactMap { self.parseBool(dict[$0]) } + let nestedValues = dict.values.flatMap { self.findBoolValues(forKeys: keys, in: $0) } + return directValues + nestedValues + } + if let array = value as? [Any] { + return array.flatMap { self.findBoolValues(forKeys: keys, in: $0) } + } + return [] + } + + private static func findFirstInt(forKeys keys: [String], in value: Any) -> Int? { + if let dict = value as? [String: Any] { + for key in keys { + if let parsed = self.parseInt(dict[key]) { + return parsed + } + } + for nestedValue in dict.values { + if let parsed = self.findFirstInt(forKeys: keys, in: nestedValue) { + return parsed + } + } + return nil + } + if let array = value as? [Any] { + for item in array { + if let parsed = self.findFirstInt(forKeys: keys, in: item) { + return parsed + } + } + } + return nil + } + + private static func findFirstDate(forKeys keys: [String], in value: Any) -> Date? { + if let dict = value as? [String: Any] { + for key in keys { + if let parsed = self.parseDate(dict[key]) { + return parsed + } + } + for nestedValue in dict.values { + if let parsed = self.findFirstDate(forKeys: keys, in: nestedValue) { + return parsed + } + } + return nil + } + if let array = value as? [Any] { + for item in array { + if let parsed = self.findFirstDate(forKeys: keys, in: item) { + return parsed + } + } + } + return nil + } + + private static func expandedJSON(_ value: Any) -> Any { + if let dict = value as? [String: Any] { + var expanded: [String: Any] = [:] + expanded.reserveCapacity(dict.count) + for (key, nested) in dict { + expanded[key] = self.expandedJSON(nested) + } + return expanded + } + if let array = value as? [Any] { + return array.map { self.expandedJSON($0) } + } + if let string = value as? String, + let data = string.data(using: .utf8), + let nested = try? JSONSerialization.jsonObject(with: data, options: []), + nested is [String: Any] || nested is [Any] + { + return self.expandedJSON(nested) + } + return value + } + + private static func anyString(for keys: [String], in dict: [String: Any]) -> String? { + for key in keys { + if let value = self.parseString(dict[key]) { + return value + } + } + return nil + } + + private static func anyDouble(for keys: [String], in dict: [String: Any]) -> Double? { + for key in keys { + if let value = self.parseDouble(dict[key]) { + return value + } + } + return nil + } + + private static func anyDate(for keys: [String], in dict: [String: Any]) -> Date? { + for key in keys { + if let value = self.parseDate(dict[key]) { + return value + } + } + return nil + } + + private static func anyBool(for keys: [String], in dict: [String: Any]) -> Bool? { + for key in keys { + if let value = self.parseBool(dict[key]) { + return value + } + } + return nil + } + + private static func parseInt(_ raw: Any?) -> Int? { + if let value = raw as? Int { return value } + if let value = raw as? Int64 { return Int(value) } + if let value = raw as? Double { return Int(value) } + if let value = raw as? NSNumber { return value.intValue } + if let value = self.parseString(raw) { return Int(value) } + return nil + } + + private static func parseDouble(_ raw: Any?) -> Double? { + if let value = raw as? Double { return value } + if let value = raw as? Int { return Double(value) } + if let value = raw as? Int64 { return Double(value) } + if let value = raw as? NSNumber { return value.doubleValue } + if let value = self.parseString(raw) { + let cleaned = value.replacingOccurrences(of: ",", with: "") + return Double(cleaned) + } + return nil + } + + private static func parseString(_ raw: Any?) -> String? { + guard let value = raw as? String else { return nil } + let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines) + return trimmed.isEmpty ? nil : trimmed + } + + private static func parseDate(_ raw: Any?) -> Date? { + if let intValue = self.parseInt(raw) { + if intValue > 1_000_000_000_000 { + return Date(timeIntervalSince1970: TimeInterval(intValue) / 1000) + } + if intValue > 1_000_000_000 { + return Date(timeIntervalSince1970: TimeInterval(intValue)) + } + } + if let string = self.parseString(raw) { + let formatter = ISO8601DateFormatter() + if let date = formatter.date(from: string) { + return date + } + let dateFormatter = DateFormatter() + dateFormatter.locale = Locale(identifier: "en_US_POSIX") + for format in ["yyyy-MM-dd", "yyyy-MM-dd HH:mm", "yyyy-MM-dd HH:mm:ss"] { + dateFormatter.dateFormat = format + if let date = dateFormatter.date(from: string) { + return date + } + } + } + return nil + } + + private static func parseBool(_ raw: Any?) -> Bool? { + if let value = raw as? Bool { return value } + if let number = raw as? NSNumber { return number.boolValue } + guard let string = self.parseString(raw)?.lowercased() else { return nil } + switch string { + case "true", "1", "yes", "active", "valid", "normal": + return true + case "false", "0", "no", "inactive", "invalid", "expired": + return false + default: + return nil + } + } + + private static func extractCookieValue(name: String, from cookieHeader: String) -> String? { + cookieHeader + .split(separator: ";") + .compactMap { part -> (String, String)? in + let pieces = part.split(separator: "=", maxSplits: 1).map { + $0.trimmingCharacters(in: .whitespacesAndNewlines) + } + guard pieces.count == 2 else { return nil } + return (pieces[0], pieces[1]) + } + .first { $0.0 == name }? + .1 + } + + private static func hasCSRF(in cookieHeader: String) -> Bool { + self.extractCookieValue(name: "login_aliyunid_csrf", from: cookieHeader) != nil || + self.extractCookieValue(name: "csrf", from: cookieHeader) != nil + } + + static func cookieNames(from cookieHeader: String) -> [String] { + CookieHeaderNormalizer.pairs(from: cookieHeader) + .map(\.name) + .filter { !$0.isEmpty } + .uniquedSorted() + } + + static func cookieNamesDescription(from cookieHeader: String) -> String { + let names = self.cookieNames(from: cookieHeader) + return names.isEmpty ? "none" : names.joined(separator: ",") + } + + private static func extractSECToken(from html: String) -> String? { + let patterns = [ + #""secToken"\s*:\s*"([^"]+)""#, + #""sec_token"\s*:\s*"([^"]+)""#, + #"secToken['"]?\s*[:=]\s*['"]([^'"]+)['"]"#, + #"sec_token['"]?\s*[:=]\s*['"]([^'"]+)['"]"#, + ] + for pattern in patterns { + if let token = self.matchFirstGroup(pattern: pattern, in: html), !token.isEmpty { + return token + } + } + return nil + } + + private static func matchFirstGroup(pattern: String, in text: String) -> String? { + guard let regex = try? NSRegularExpression(pattern: pattern, options: []) else { + return nil + } + let range = NSRange(text.startIndex.. 1, + let valueRange = Range(match.range(at: 1), in: text) + else { + return nil + } + let value = text[valueRange].trimmingCharacters(in: .whitespacesAndNewlines) + return value.isEmpty ? nil : String(value) + } +} + +extension [String] { + fileprivate func uniquedSorted() -> [String] { + Array(Set(self)).sorted() + } +} diff --git a/Sources/CodexBarCore/Providers/Alibaba/AlibabaTokenPlanUsageSnapshot.swift b/Sources/CodexBarCore/Providers/Alibaba/AlibabaTokenPlanUsageSnapshot.swift new file mode 100644 index 0000000..36cee2a --- /dev/null +++ b/Sources/CodexBarCore/Providers/Alibaba/AlibabaTokenPlanUsageSnapshot.swift @@ -0,0 +1,96 @@ +import Foundation + +public struct AlibabaTokenPlanUsageSnapshot: Sendable { + public let planName: String? + public let usedQuota: Double? + public let totalQuota: Double? + public let remainingQuota: Double? + public let resetsAt: Date? + public let updatedAt: Date + + public init( + planName: String?, + usedQuota: Double?, + totalQuota: Double?, + remainingQuota: Double?, + resetsAt: Date?, + updatedAt: Date) + { + self.planName = planName + self.usedQuota = usedQuota + self.totalQuota = totalQuota + self.remainingQuota = remainingQuota + self.resetsAt = resetsAt + self.updatedAt = updatedAt + } +} + +extension AlibabaTokenPlanUsageSnapshot { + public func toUsageSnapshot() -> UsageSnapshot { + let primary: RateWindow? = Self.usedPercent( + used: self.usedQuota, + total: self.totalQuota, + remaining: self.remainingQuota).map { + RateWindow( + usedPercent: $0, + windowMinutes: 30 * 24 * 60, + resetsAt: self.resetsAt, + resetDescription: Self.quotaDetail( + used: self.usedQuota, + total: self.totalQuota, + remaining: self.remainingQuota)) + } + + let planName = self.planName?.trimmingCharacters(in: .whitespacesAndNewlines) + let loginMethod = (planName?.isEmpty ?? true) ? nil : planName + let identity = ProviderIdentitySnapshot( + providerID: .alibabatokenplan, + accountEmail: nil, + accountOrganization: nil, + loginMethod: loginMethod) + + return UsageSnapshot( + primary: primary, + secondary: nil, + tertiary: nil, + providerCost: nil, + updatedAt: self.updatedAt, + identity: identity) + } + + private static func usedPercent(used: Double?, total: Double?, remaining: Double?) -> Double? { + guard let total, total > 0 else { return nil } + let usedValue: Double? = if let used { + used + } else if let remaining { + total - remaining + } else { + nil + } + guard let usedValue else { return nil } + let normalizedUsed = max(0, min(usedValue, total)) + return normalizedUsed / total * 100 + } + + private static func quotaDetail(used: Double?, total: Double?, remaining: Double?) -> String? { + if let used, let total, total > 0 { + return "\(self.format(used)) / \(self.format(total)) credits used" + } + if let remaining, let total, total > 0 { + return "\(Self.format(remaining)) / \(Self.format(total)) credits left" + } + if let remaining { + return "\(Self.format(remaining)) credits left" + } + return nil + } + + private static func format(_ value: Double) -> String { + let formatter = NumberFormatter() + formatter.numberStyle = .decimal + formatter.usesGroupingSeparator = true + formatter.maximumFractionDigits = value.rounded() == value ? 0 : 2 + formatter.locale = Locale(identifier: "en_US_POSIX") + return formatter.string(from: NSNumber(value: value)) ?? String(format: "%.2f", value) + } +} diff --git a/Sources/CodexBarCore/Providers/Amp/AmpCLIProbe.swift b/Sources/CodexBarCore/Providers/Amp/AmpCLIProbe.swift new file mode 100644 index 0000000..ab995dd --- /dev/null +++ b/Sources/CodexBarCore/Providers/Amp/AmpCLIProbe.swift @@ -0,0 +1,46 @@ +import Foundation + +public struct AmpCLIProbe: Sendable { + private static let commandTimeout: TimeInterval = 15 + private let arguments: [String] + + public init() { + self.arguments = ["usage"] + } + + init(arguments: [String]) { + self.arguments = arguments + } + + public func fetch( + environment: [String: String] = ProcessInfo.processInfo.environment, + now: Date = Date()) async throws -> AmpUsageSnapshot + { + let loginPATH = LoginShellPathCache.shared.current + guard let executable = BinaryLocator.resolveAmpBinary(env: environment, loginPATH: loginPATH) else { + throw SubprocessRunnerError.binaryNotFound("amp") + } + + var commandEnvironment = environment + commandEnvironment["NO_COLOR"] = "1" + commandEnvironment["PATH"] = PathBuilder.effectivePATH( + purposes: [.tty, .nodeTooling], + env: environment, + loginPATH: loginPATH) + + let result = try await SubprocessRunner.run( + binary: executable, + arguments: self.arguments, + environment: commandEnvironment, + timeout: Self.commandTimeout, + standardInput: FileHandle.nullDevice, + label: "amp-usage") + let output = result.stdout.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty + ? result.stderr + : result.stdout + guard !output.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else { + throw AmpUsageError.parseFailed("The Amp CLI returned no usage data.") + } + return try AmpUsageParser.parse(displayText: output, now: now) + } +} diff --git a/Sources/CodexBarCore/Providers/Amp/AmpProviderDescriptor.swift b/Sources/CodexBarCore/Providers/Amp/AmpProviderDescriptor.swift new file mode 100644 index 0000000..91ecef4 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Amp/AmpProviderDescriptor.swift @@ -0,0 +1,169 @@ +import Foundation + +public enum AmpProviderDescriptor { + public static let descriptor: ProviderDescriptor = Self.makeDescriptor() + + static func makeDescriptor() -> ProviderDescriptor { + ProviderDescriptor( + id: .amp, + metadata: ProviderMetadata( + id: .amp, + displayName: "Amp", + sessionLabel: "Amp Free", + weeklyLabel: "Balance", + opusLabel: nil, + supportsOpus: false, + supportsCredits: true, + creditsHint: "Individual and workspace credit balances from Amp.", + toggleTitle: "Show Amp usage", + cliName: "amp", + defaultEnabled: false, + isPrimaryProvider: false, + usesAccountFallback: false, + browserCookieOrder: ProviderBrowserCookieDefaults.defaultImportOrder, + dashboardURL: "https://ampcode.com/settings/usage", + statusPageURL: nil), + branding: ProviderBranding( + iconStyle: .amp, + iconResourceName: "ProviderIcon-amp", + color: ProviderColor(red: 220 / 255, green: 38 / 255, blue: 38 / 255)), + tokenCost: ProviderTokenCostConfig( + supportsTokenCost: false, + noDataMessage: { "Amp cost summary is not supported." }), + fetchPlan: ProviderFetchPlan( + sourceModes: [.auto, .api, .web, .cli], + pipeline: ProviderFetchPipeline(resolveStrategies: self.resolveStrategies)), + cli: ProviderCLIConfig( + name: "amp", + versionDetector: nil)) + } + + private static func resolveStrategies(context: ProviderFetchContext) async -> [any ProviderFetchStrategy] { + switch context.sourceMode { + case .auto: + [AmpCLIFetchStrategy(), AmpAPIFetchStrategy(), AmpStatusFetchStrategy()] + case .cli: + [AmpCLIFetchStrategy()] + case .api: + [AmpAPIFetchStrategy()] + case .web: + [AmpStatusFetchStrategy()] + case .oauth: + [] + } + } +} + +struct AmpCLIFetchStrategy: ProviderFetchStrategy { + let id: String = "amp.cli" + let kind: ProviderFetchKind = .cli + + func isAvailable(_ context: ProviderFetchContext) async -> Bool { + BinaryLocator.resolveAmpBinary( + env: context.env, + loginPATH: LoginShellPathCache.shared.current) != nil + } + + func fetch(_ context: ProviderFetchContext) async throws -> ProviderFetchResult { + let snapshot = try await AmpCLIProbe().fetch(environment: context.env) + return self.makeResult( + usage: snapshot.toUsageSnapshot(now: snapshot.updatedAt), + sourceLabel: "cli") + } + + func shouldFallback(on error: Error, context: ProviderFetchContext) -> Bool { + if error is CancellationError || (error as? URLError)?.code == .cancelled { + return false + } + return context.sourceMode == .auto + } +} + +struct AmpAPIFetchStrategy: ProviderFetchStrategy { + let id: String = "amp.api" + let kind: ProviderFetchKind = .apiToken + + func isAvailable(_ context: ProviderFetchContext) async -> Bool { + _ = context + return true + } + + func fetch(_ context: ProviderFetchContext) async throws -> ProviderFetchResult { + guard let token = ProviderTokenResolver.ampToken(environment: context.env) else { + throw AmpUsageError.missingAPIToken + } + let logger: ((String) -> Void)? = context.verbose + ? { msg in CodexBarLog.logger(LogCategories.amp).verbose(msg) } + : nil + let snapshot = try await AmpUsageFetcher(browserDetection: context.browserDetection) + .fetch(apiToken: token, logger: logger) + return self.makeResult( + usage: snapshot.toUsageSnapshot(now: snapshot.updatedAt), + sourceLabel: "api") + } + + func shouldFallback(on error: Error, context: ProviderFetchContext) -> Bool { + guard context.sourceMode == .auto else { return false } + return !(error is CancellationError) && (error as? URLError)?.code != .cancelled + } +} + +struct AmpStatusFetchStrategy: ProviderFetchStrategy { + let id: String = "amp.web" + let kind: ProviderFetchKind = .web + + func isAvailable(_ context: ProviderFetchContext) async -> Bool { + guard context.sourceMode.usesWeb else { return false } + #if os(macOS) + let canImportBrowserCookies = true + #else + let canImportBrowserCookies = false + #endif + return Self.canUseWebFallback( + settings: context.settings?.amp, + canImportBrowserCookies: canImportBrowserCookies) + } + + func fetch(_ context: ProviderFetchContext) async throws -> ProviderFetchResult { + let fetcher = AmpUsageFetcher(browserDetection: context.browserDetection) + let manual = Self.manualCookieHeader(from: context) + let logger: ((String) -> Void)? = context.verbose + ? { msg in CodexBarLog.logger(LogCategories.amp).verbose(msg) } + : nil + let snap = try await fetcher.fetch(cookieHeaderOverride: manual, logger: logger) + return self.makeResult( + usage: snap.toUsageSnapshot(now: snap.updatedAt), + sourceLabel: "web") + } + + func shouldFallback(on _: Error, context _: ProviderFetchContext) -> Bool { + false + } + + static func canUseWebFallback( + settings: ProviderSettingsSnapshot.AmpProviderSettings?, + canImportBrowserCookies: Bool) -> Bool + { + guard let settings else { return canImportBrowserCookies } + switch settings.cookieSource { + case .auto: + return canImportBrowserCookies + case .manual: + return Self.manualCookieHeader(from: settings.manualCookieHeader) != nil + case .off: + return false + } + } + + private static func manualCookieHeader(from context: ProviderFetchContext) -> String? { + guard let settings = context.settings?.amp, settings.cookieSource == .manual else { return nil } + return Self.manualCookieHeader(from: settings.manualCookieHeader) + } + + private static func manualCookieHeader(from rawHeader: String?) -> String? { + guard let header = CookieHeaderNormalizer.normalize(rawHeader), + CookieHeaderNormalizer.pairs(from: header).contains(where: { $0.name == "session" }) + else { return nil } + return header + } +} diff --git a/Sources/CodexBarCore/Providers/Amp/AmpSettingsReader.swift b/Sources/CodexBarCore/Providers/Amp/AmpSettingsReader.swift new file mode 100644 index 0000000..5997e35 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Amp/AmpSettingsReader.swift @@ -0,0 +1,22 @@ +import Foundation + +public enum AmpSettingsReader { + public static let apiTokenKey = "AMP_API_KEY" + + public static func apiToken(environment: [String: String] = ProcessInfo.processInfo.environment) -> String? { + self.cleaned(environment[self.apiTokenKey]) + } + + static func cleaned(_ raw: String?) -> String? { + guard var value = raw?.trimmingCharacters(in: .whitespacesAndNewlines), !value.isEmpty else { + return nil + } + if (value.hasPrefix("\"") && value.hasSuffix("\"")) || + (value.hasPrefix("'") && value.hasSuffix("'")) + { + value = String(value.dropFirst().dropLast()) + } + value = value.trimmingCharacters(in: .whitespacesAndNewlines) + return value.isEmpty ? nil : value + } +} diff --git a/Sources/CodexBarCore/Providers/Amp/AmpUsageFetcher.swift b/Sources/CodexBarCore/Providers/Amp/AmpUsageFetcher.swift new file mode 100644 index 0000000..17d9c29 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Amp/AmpUsageFetcher.swift @@ -0,0 +1,491 @@ +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +#if os(macOS) +import SweetCookieKit +#endif + +public enum AmpUsageError: LocalizedError, Sendable { + case notLoggedIn + case invalidCredentials + case missingAPIToken + case invalidAPIToken + case parseFailed(String) + case networkError(String) + case noSessionCookie + + public var errorDescription: String? { + switch self { + case .notLoggedIn: + "Not logged in to Amp. Please log in via ampcode.com." + case .invalidCredentials: + "Amp session cookie expired. Please log in again." + case .missingAPIToken: + "Amp access token not configured. Set AMP_API_KEY or add it in Settings." + case .invalidAPIToken: + "Amp access token is invalid or expired." + case let .parseFailed(message): + "Could not parse Amp usage: \(message)" + case let .networkError(message): + "Amp request failed: \(message)" + case .noSessionCookie: + "No Amp session cookie found. Please log in to ampcode.com in your browser." + } + } +} + +#if os(macOS) +private let ampCookieImportOrder: BrowserCookieImportOrder = + ProviderDefaults.metadata[.amp]?.browserCookieOrder ?? Browser.defaultImportOrder + +public enum AmpCookieImporter { + private static let cookieClient = BrowserCookieClient() + private static let cookieDomains = ["ampcode.com", "www.ampcode.com"] + private static let sessionCookieNames: Set = [ + "session", + ] + + public struct SessionInfo: Sendable { + public let cookies: [HTTPCookie] + public let sourceLabel: String + + public init(cookies: [HTTPCookie], sourceLabel: String) { + self.cookies = cookies + self.sourceLabel = sourceLabel + } + + public var cookieHeader: String { + self.cookies.map { "\($0.name)=\($0.value)" }.joined(separator: "; ") + } + } + + public static func importSession( + browserDetection: BrowserDetection, + logger: ((String) -> Void)? = nil) throws -> SessionInfo + { + let log: (String) -> Void = { msg in logger?("[amp-cookie] \(msg)") } + + let installed = ampCookieImportOrder.cookieImportCandidates(using: browserDetection) + for browserSource in installed { + do { + let query = BrowserCookieQuery(domains: self.cookieDomains) + let sources = try Self.cookieClient.codexBarRecords( + matching: query, + in: browserSource, + logger: log) + for source in sources where !source.records.isEmpty { + let cookies = BrowserCookieClient.makeHTTPCookies(source.records, origin: query.origin) + guard !cookies.isEmpty else { continue } + let names = cookies.map(\.name).joined(separator: ", ") + log("\(source.label) cookies: \(names)") + let sessionCookies = cookies.filter { Self.sessionCookieNames.contains($0.name) } + if !sessionCookies.isEmpty { + log("Found Amp session cookie in \(source.label)") + return SessionInfo(cookies: sessionCookies, sourceLabel: source.label) + } + log("\(source.label) cookies found, but no Amp session cookie present") + log("Expected one of: \(Self.sessionCookieNames.joined(separator: ", "))") + } + } catch { + BrowserCookieAccessGate.recordIfNeeded(error) + log("\(browserSource.displayName) cookie import failed: \(error.localizedDescription)") + } + } + + throw AmpUsageError.noSessionCookie + } +} +#endif + +public struct AmpUsageFetcher: Sendable { + private static let settingsURL = URL(string: "https://ampcode.com/settings")! + static let usageURL = URL(string: "https://ampcode.com/api/internal?userDisplayBalanceInfo")! + @MainActor private static var recentDumps: [String] = [] + + public let browserDetection: BrowserDetection + + public init(browserDetection: BrowserDetection) { + self.browserDetection = browserDetection + } + + public func fetch( + cookieHeaderOverride: String? = nil, + logger: ((String) -> Void)? = nil, + now: Date = Date()) async throws -> AmpUsageSnapshot + { + let log: (String) -> Void = { msg in logger?("[amp] \(msg)") } + let cookieHeader = try await self.resolveCookieHeader(override: cookieHeaderOverride, logger: log) + + if let logger { + let names = self.cookieNames(from: cookieHeader) + if !names.isEmpty { + logger("[amp] Cookie names: \(names.joined(separator: ", "))") + } + let diagnostics = RedirectDiagnostics(cookieHeader: cookieHeader, logger: logger) + do { + let (html, responseInfo) = try await self.fetchLegacyHTMLWithDiagnostics( + cookieHeader: cookieHeader, + diagnostics: diagnostics) + self.logDiagnostics(responseInfo: responseInfo, diagnostics: diagnostics, logger: logger) + return try AmpUsageParser.parse(html: html, now: now) + } catch { + self.logDiagnostics(responseInfo: nil, diagnostics: diagnostics, logger: logger) + logger("[amp] Fetch failed: \(error.localizedDescription)") + throw error + } + } + + let diagnostics = RedirectDiagnostics(cookieHeader: cookieHeader, logger: nil) + let (html, _) = try await self.fetchLegacyHTMLWithDiagnostics( + cookieHeader: cookieHeader, + diagnostics: diagnostics) + return try AmpUsageParser.parse(html: html, now: now) + } + + public func fetch( + apiToken: String, + logger: ((String) -> Void)? = nil, + now: Date = Date()) async throws -> AmpUsageSnapshot + { + guard let token = AmpSettingsReader.cleaned(apiToken) else { + throw AmpUsageError.missingAPIToken + } + let request = try Self.makeUsageAPIRequest(apiToken: token) + let diagnostics = APIRedirectDiagnostics(logger: logger) + let session = URLSession(configuration: .ephemeral, delegate: diagnostics, delegateQueue: nil) + let httpResponse = try await session.response(for: request) + logger?("[amp] API response: \(httpResponse.statusCode) " + + "\(httpResponse.response.url?.absoluteString ?? "unknown")") + try Self.validateAPIResponse(httpResponse) + return try Self.parseUsageAPIResponse(httpResponse.data, now: now) + } + + public func debugRawProbe(cookieHeaderOverride: String? = nil) async -> String { + let stamp = ISO8601DateFormatter().string(from: Date()) + var lines: [String] = [] + lines.append("=== Amp Debug Probe @ \(stamp) ===") + lines.append("") + + do { + let cookieHeader = try await self.resolveCookieHeader( + override: cookieHeaderOverride, + logger: { msg in lines.append("[cookie] \(msg)") }) + let diagnostics = RedirectDiagnostics(cookieHeader: cookieHeader, logger: nil) + let cookieNames = CookieHeaderNormalizer.pairs(from: cookieHeader).map(\.name) + lines.append("Cookie names: \(cookieNames.joined(separator: ", "))") + + let (html, responseInfo) = try await self.fetchLegacyHTMLWithDiagnostics( + cookieHeader: cookieHeader, + diagnostics: diagnostics) + let snapshot = try AmpUsageParser.parse(html: html) + + lines.append("") + lines.append("Fetch Success") + lines.append("Status: \(responseInfo.statusCode) \(responseInfo.url)") + + if !diagnostics.redirects.isEmpty { + lines.append("") + lines.append("Redirects:") + for entry in diagnostics.redirects { + lines.append(" \(entry)") + } + } + + lines.append("") + lines.append("Amp Free:") + lines.append(" quota=\(snapshot.freeQuota?.description ?? "nil")") + lines.append(" used=\(snapshot.freeUsed?.description ?? "nil")") + lines.append(" hourlyReplenishment=\(snapshot.hourlyReplenishment?.description ?? "nil")") + lines.append(" windowHours=\(snapshot.windowHours?.description ?? "nil")") + lines.append(" individualCredits=\(snapshot.individualCredits?.description ?? "nil")") + for workspace in snapshot.workspaceBalances { + lines.append(" workspace[\(workspace.name)]=\(workspace.remaining)") + } + + let output = lines.joined(separator: "\n") + Task { @MainActor in Self.recordDump(output) } + return output + } catch { + lines.append("") + lines.append("Probe Failed: \(error.localizedDescription)") + let output = lines.joined(separator: "\n") + Task { @MainActor in Self.recordDump(output) } + return output + } + } + + public static func latestDumps() async -> String { + await MainActor.run { + let result = Self.recentDumps.joined(separator: "\n\n---\n\n") + return result.isEmpty ? "No Amp probe dumps captured yet." : result + } + } + + private func resolveCookieHeader( + override: String?, + logger: ((String) -> Void)?) async throws -> String + { + if let override = CookieHeaderNormalizer.normalize(override) { + if let sessionHeader = self.sessionCookieHeader(from: override) { + logger?("[amp] Using manual session cookie") + return sessionHeader + } + throw AmpUsageError.noSessionCookie + } + #if os(macOS) + let session = try AmpCookieImporter.importSession(browserDetection: self.browserDetection, logger: logger) + logger?("[amp] Using cookies from \(session.sourceLabel)") + return session.cookieHeader + #else + throw AmpUsageError.noSessionCookie + #endif + } + + static func makeUsageAPIRequest(apiToken: String) throws -> URLRequest { + var request = URLRequest(url: Self.usageURL) + request.httpMethod = "POST" + request.httpBody = try JSONSerialization.data(withJSONObject: [ + "method": "userDisplayBalanceInfo", + "params": [:], + ]) + request.setValue("Bearer \(apiToken)", forHTTPHeaderField: "Authorization") + request.setValue("application/json", forHTTPHeaderField: "accept") + request.setValue("application/json", forHTTPHeaderField: "content-type") + return request + } + + private func fetchLegacyHTMLWithDiagnostics( + cookieHeader: String, + diagnostics: RedirectDiagnostics) async throws -> (String, ResponseInfo) + { + var request = URLRequest(url: Self.settingsURL) + request.httpMethod = "GET" + request.setValue(cookieHeader, forHTTPHeaderField: "Cookie") + request.setValue( + "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", + forHTTPHeaderField: "accept") + Self.applyBrowserHeaders(to: &request) + + let session = URLSession(configuration: .ephemeral, delegate: diagnostics, delegateQueue: nil) + let httpResponse = try await session.response(for: request) + let responseInfo = ResponseInfo( + statusCode: httpResponse.statusCode, + url: httpResponse.response.url?.absoluteString ?? "unknown") + try Self.validateBrowserResponse(response: httpResponse, diagnostics: diagnostics) + + let html = String(data: httpResponse.data, encoding: .utf8) ?? "" + return (html, responseInfo) + } + + static func parseUsageAPIResponse(_ data: Data, now: Date = Date()) throws -> AmpUsageSnapshot { + let response: UsageAPIResponse + do { + response = try JSONDecoder().decode(UsageAPIResponse.self, from: data) + } catch { + throw AmpUsageError.parseFailed("Invalid Amp usage API response.") + } + + guard response.ok else { + if response.error?.code == "auth-required" { + throw AmpUsageError.invalidAPIToken + } + throw AmpUsageError.networkError(response.error?.message ?? "Amp usage API returned an error.") + } + guard let displayText = response.result?.displayText, !displayText.isEmpty else { + throw AmpUsageError.parseFailed("Missing Amp usage display text.") + } + return try AmpUsageParser.parse(displayText: displayText, now: now) + } + + private static func applyBrowserHeaders(to request: inout URLRequest) { + request.setValue( + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) " + + "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36", + forHTTPHeaderField: "user-agent") + request.setValue("en-US,en;q=0.9", forHTTPHeaderField: "accept-language") + request.setValue("https://ampcode.com", forHTTPHeaderField: "origin") + request.setValue(self.settingsURL.absoluteString, forHTTPHeaderField: "referer") + } + + private static func validateBrowserResponse( + response: ProviderHTTPResponse, + diagnostics: RedirectDiagnostics) throws + { + guard response.statusCode == 200 else { + if response.statusCode == 401 || response.statusCode == 403 || diagnostics.detectedLoginRedirect { + throw AmpUsageError.invalidCredentials + } + throw AmpUsageError.networkError("HTTP \(response.statusCode)") + } + } + + private static func validateAPIResponse(_ response: ProviderHTTPResponse) throws { + guard response.statusCode == 200 else { + if response.statusCode == 401 || response.statusCode == 403 { + throw AmpUsageError.invalidAPIToken + } + throw AmpUsageError.networkError("HTTP \(response.statusCode)") + } + } + + @MainActor private static func recordDump(_ text: String) { + if self.recentDumps.count >= 5 { self.recentDumps.removeFirst() } + self.recentDumps.append(text) + } + + private final class RedirectDiagnostics: NSObject, URLSessionTaskDelegate, @unchecked Sendable { + private let cookieHeader: String + private let logger: ((String) -> Void)? + var redirects: [String] = [] + private(set) var detectedLoginRedirect = false + + init(cookieHeader: String, logger: ((String) -> Void)?) { + self.cookieHeader = cookieHeader + self.logger = logger + } + + func urlSession( + _: URLSession, + task: URLSessionTask, + willPerformHTTPRedirection response: HTTPURLResponse, + newRequest request: URLRequest, + completionHandler: @escaping (URLRequest?) -> Void) + { + let from = response.url?.absoluteString ?? "unknown" + let to = request.url?.absoluteString ?? "unknown" + self.redirects.append("\(response.statusCode) \(from) -> \(to)") + + if let toURL = request.url, AmpUsageFetcher.isLoginRedirect(toURL) { + if let logger { + logger("[amp] Detected login redirect, aborting (invalid session)") + } + self.detectedLoginRedirect = true + completionHandler(nil) + return + } + + var updated = request + if AmpUsageFetcher.shouldAttachCookie(to: request.url), !self.cookieHeader.isEmpty { + updated.setValue(self.cookieHeader, forHTTPHeaderField: "Cookie") + } else { + updated.setValue(nil, forHTTPHeaderField: "Cookie") + } + if let referer = response.url?.absoluteString { + updated.setValue(referer, forHTTPHeaderField: "referer") + } + if let logger { + logger("[amp] Redirect \(response.statusCode) \(from) -> \(to)") + } + completionHandler(updated) + } + } + + /// Amp's balance RPC should not redirect. Refusing redirects guarantees the bearer token cannot cross hosts. + private final class APIRedirectDiagnostics: NSObject, URLSessionTaskDelegate, @unchecked Sendable { + private let logger: ((String) -> Void)? + + init(logger: ((String) -> Void)?) { + self.logger = logger + } + + func urlSession( + _: URLSession, + task _: URLSessionTask, + willPerformHTTPRedirection response: HTTPURLResponse, + newRequest request: URLRequest, + completionHandler: @escaping (URLRequest?) -> Void) + { + let from = response.url?.absoluteString ?? "unknown" + let to = request.url?.absoluteString ?? "unknown" + self.logger?("[amp] API redirect blocked: \(response.statusCode) \(from) -> \(to)") + completionHandler(nil) + } + } + + private struct ResponseInfo { + let statusCode: Int + let url: String + } + + private struct UsageAPIResponse: Decodable { + let ok: Bool + let result: Result? + let error: APIError? + + struct Result: Decodable { + let displayText: String + } + + struct APIError: Decodable { + let code: String? + let message: String? + } + } + + private func logDiagnostics( + responseInfo: ResponseInfo?, + diagnostics: RedirectDiagnostics, + logger: (String) -> Void) + { + if let responseInfo { + logger("[amp] Response: \(responseInfo.statusCode) \(responseInfo.url)") + } + if !diagnostics.redirects.isEmpty { + logger("[amp] Redirects:") + for entry in diagnostics.redirects { + logger("[amp] \(entry)") + } + } + } + + private func cookieNames(from header: String) -> [String] { + header.split(separator: ";").compactMap { part in + let trimmed = part.trimmingCharacters(in: .whitespacesAndNewlines) + guard let idx = trimmed.firstIndex(of: "=") else { return nil } + let name = trimmed[.. String? { + let pairs = CookieHeaderNormalizer.pairs(from: header) + let sessionPairs = pairs.filter { $0.name == "session" } + guard !sessionPairs.isEmpty else { return nil } + return sessionPairs.map { "\($0.name)=\($0.value)" }.joined(separator: "; ") + } + + static func shouldAttachCookie(to url: URL?) -> Bool { + guard url?.scheme?.lowercased() == "https" else { return false } + return self.isAmpHost(url) + } + + private static func isAmpHost(_ url: URL?) -> Bool { + guard let host = url?.host?.lowercased() else { return false } + if host == "ampcode.com" || host == "www.ampcode.com" { return true } + return host.hasSuffix(".ampcode.com") + } + + static func isLoginRedirect(_ url: URL) -> Bool { + guard self.isAmpHost(url) else { return false } + if url.host?.lowercased() == "auth.ampcode.com" { return true } + + let path = url.path.lowercased() + let components = path.split(separator: "/").map(String.init) + if components.contains("login") { return true } + if components.contains("signin") { return true } + if components.contains("sign-in") { return true } + + // Amp currently redirects to /auth/sign-in?returnTo=... when session is invalid. Keep this slightly broader + // than one exact path so we keep working if Amp changes auth routes. + if components.contains("auth") { + let query = url.query?.lowercased() ?? "" + if query.contains("returnto=") { return true } + if query.contains("redirect=") { return true } + if query.contains("redirectto=") { return true } + } + + return false + } +} diff --git a/Sources/CodexBarCore/Providers/Amp/AmpUsageParser.swift b/Sources/CodexBarCore/Providers/Amp/AmpUsageParser.swift new file mode 100644 index 0000000..90ac8fc --- /dev/null +++ b/Sources/CodexBarCore/Providers/Amp/AmpUsageParser.swift @@ -0,0 +1,221 @@ +import Foundation + +enum AmpUsageParser { + static func parse(html: String, now: Date = Date()) throws -> AmpUsageSnapshot { + guard let usage = self.parseFreeTierUsage(html) else { + if self.looksSignedOut(html) { + throw AmpUsageError.notLoggedIn + } + throw AmpUsageError.parseFailed("Missing Amp Free usage data.") + } + + return AmpUsageSnapshot( + freeQuota: usage.quota, + freeUsed: usage.used, + hourlyReplenishment: usage.hourlyReplenishment, + windowHours: usage.windowHours, + updatedAt: now) + } + + static func parse(displayText: String, now: Date = Date()) throws -> AmpUsageSnapshot { + let text = TextParsing.stripANSICodes(displayText) + let identityPattern = #"(?im)^\s*Signed in as\s+([^\s(]+)(?:\s+\(([^\r\n)]+)\))?\s*$"# + let identity = self.captures(in: text, pattern: identityPattern) + if identity == nil, self.looksSignedOut(text) { + throw AmpUsageError.notLoggedIn + } + + let amountPattern = #"([0-9][0-9,]*(?:\.[0-9]+)?)"# + let freePattern = #"(?im)^\s*Amp Free:\s*\$?"# + amountPattern + + #"\s*/\s*\$?"# + amountPattern + + #"\s+remaining(?:\s*\(replenishes\s*\+\$?"# + amountPattern + #"\s*/\s*hour\))?"# + let freePercentPattern = #"(?im)^\s*Amp Free:\s*"# + amountPattern + + #"\s*%\s+remaining(?:\s+today)?(?:\s*\(resets\s+daily\))?"# + let creditsPattern = #"(?im)^\s*Individual credits:\s*\$?"# + amountPattern + #"\s+remaining"# + let individualCredits = self.captures(in: text, pattern: creditsPattern)?.first + .flatMap(self.number(from:)) + let workspacePattern = #"(?im)^\s*Workspace\s+(.+?):\s*\$?"# + amountPattern + #"\s+remaining"# + let workspaceBalances: [AmpWorkspaceBalance] = self.allCaptures( + in: text, + pattern: workspacePattern).compactMap { captures -> AmpWorkspaceBalance? in + guard captures.count == 2, + let name = self.nonEmpty(captures[0]), + let remaining = self.number(from: captures[1]) + else { return nil } + return AmpWorkspaceBalance(name: name, remaining: remaining) + } + let freeUsage: FreeTierUsage? = { + guard let free = self.captures(in: text, pattern: freePattern), + let remaining = self.number(from: free[0]), + let quota = self.number(from: free[1]) + else { return nil } + let hourlyReplenishment = self.number(from: free[2]) ?? 0 + let windowHours = hourlyReplenishment > 0 + ? max(1, (quota / hourlyReplenishment).rounded()) + : nil + return FreeTierUsage( + quota: quota, + used: max(0, quota - remaining), + hourlyReplenishment: hourlyReplenishment, + windowHours: windowHours, + resetDescription: nil) + }() + let freePercentUsage: FreeTierUsage? = { + guard let remainingText = self.captures(in: text, pattern: freePercentPattern)?.first, + let remaining = self.number(from: remainingText) + else { return nil } + let clampedRemaining = min(100, max(0, remaining)) + return FreeTierUsage( + quota: 100, + used: 100 - clampedRemaining, + hourlyReplenishment: 0, + windowHours: 24, + resetDescription: "resets daily") + }() + let resolvedFreeUsage = freeUsage ?? freePercentUsage + guard resolvedFreeUsage != nil || individualCredits != nil || !workspaceBalances.isEmpty else { + throw AmpUsageError.parseFailed("Missing Amp usage data.") + } + + return AmpUsageSnapshot( + freeQuota: resolvedFreeUsage?.quota, + freeUsed: resolvedFreeUsage?.used, + hourlyReplenishment: resolvedFreeUsage?.hourlyReplenishment, + windowHours: resolvedFreeUsage?.windowHours, + individualCredits: individualCredits, + workspaceBalances: workspaceBalances, + accountEmail: self.nonEmpty(identity?[0]), + accountOrganization: self.nonEmpty(identity?[1]), + updatedAt: now, + freeResetDescription: resolvedFreeUsage?.resetDescription) + } + + private struct FreeTierUsage { + let quota: Double + let used: Double + let hourlyReplenishment: Double + let windowHours: Double? + let resetDescription: String? + } + + private static func parseFreeTierUsage(_ html: String) -> FreeTierUsage? { + let tokens = ["freeTierUsage", "getFreeTierUsage"] + for token in tokens { + if let object = self.extractObject(named: token, in: html), + let usage = self.parseFreeTierUsageObject(object) + { + return usage + } + } + return nil + } + + private static func parseFreeTierUsageObject(_ object: String) -> FreeTierUsage? { + guard let quota = self.number(for: "quota", in: object), + let used = self.number(for: "used", in: object), + let hourly = self.number(for: "hourlyReplenishment", in: object) + else { return nil } + + let windowHours = self.number(for: "windowHours", in: object) + return FreeTierUsage( + quota: quota, + used: used, + hourlyReplenishment: hourly, + windowHours: windowHours, + resetDescription: nil) + } + + private static func extractObject(named token: String, in text: String) -> String? { + guard let tokenRange = text.range(of: token) else { return nil } + guard let braceIndex = text[tokenRange.upperBound...].firstIndex(of: "{") else { return nil } + + var depth = 0 + var inString = false + var isEscaped = false + var index = braceIndex + + while index < text.endIndex { + let char = text[index] + if inString { + if isEscaped { + isEscaped = false + } else if char == "\\" { + isEscaped = true + } else if char == "\"" { + inString = false + } + } else { + if char == "\"" { + inString = true + } else if char == "{" { + depth += 1 + } else if char == "}" { + depth -= 1 + if depth == 0 { + return String(text[braceIndex...index]) + } + } + } + index = text.index(after: index) + } + + return nil + } + + private static func number(for key: String, in text: String) -> Double? { + let pattern = "\\b\(NSRegularExpression.escapedPattern(for: key))\\b\\s*:\\s*([0-9]+(?:\\.[0-9]+)?)" + guard let regex = try? NSRegularExpression(pattern: pattern) else { return nil } + let range = NSRange(text.startIndex.. 1, + let valueRange = Range(match.range(at: 1), in: text) + else { return nil } + return Double(text[valueRange]) + } + + private static func captures(in text: String, pattern: String) -> [String]? { + guard let regex = try? NSRegularExpression(pattern: pattern) else { return nil } + let range = NSRange(text.startIndex.. [[String]] { + guard let regex = try? NSRegularExpression(pattern: pattern) else { return [] } + let range = NSRange(text.startIndex.. [String] { + (1.. Double? { + Double(text.replacingOccurrences(of: ",", with: "")) + } + + private static func nonEmpty(_ text: String?) -> String? { + guard let text, !text.isEmpty else { return nil } + return text + } + + private static func looksSignedOut(_ html: String) -> Bool { + let lower = html.lowercased() + if lower.contains("sign in") || lower.contains("log in") || lower.contains("login") { + return true + } + if lower.contains("/login") || lower.contains("ampcode.com/login") { + return true + } + return false + } +} diff --git a/Sources/CodexBarCore/Providers/Amp/AmpUsageSnapshot.swift b/Sources/CodexBarCore/Providers/Amp/AmpUsageSnapshot.swift new file mode 100644 index 0000000..dfa670d --- /dev/null +++ b/Sources/CodexBarCore/Providers/Amp/AmpUsageSnapshot.swift @@ -0,0 +1,109 @@ +import Foundation + +public struct AmpWorkspaceBalance: Codable, Equatable, Sendable { + public let name: String + public let remaining: Double + + public init(name: String, remaining: Double) { + self.name = name + self.remaining = remaining + } +} + +public struct AmpUsageDetails: Codable, Equatable, Sendable { + public let individualCredits: Double? + public let workspaceBalances: [AmpWorkspaceBalance] + + public init(individualCredits: Double?, workspaceBalances: [AmpWorkspaceBalance]) { + self.individualCredits = individualCredits + self.workspaceBalances = workspaceBalances + } +} + +public struct AmpUsageSnapshot: Sendable { + public let freeQuota: Double? + public let freeUsed: Double? + public let hourlyReplenishment: Double? + public let windowHours: Double? + public let individualCredits: Double? + public let workspaceBalances: [AmpWorkspaceBalance] + public let accountEmail: String? + public let accountOrganization: String? + public let updatedAt: Date + public let freeResetDescription: String? + + public init( + freeQuota: Double?, + freeUsed: Double?, + hourlyReplenishment: Double?, + windowHours: Double?, + individualCredits: Double? = nil, + workspaceBalances: [AmpWorkspaceBalance] = [], + accountEmail: String? = nil, + accountOrganization: String? = nil, + updatedAt: Date, + freeResetDescription: String? = nil) + { + self.freeQuota = freeQuota + self.freeUsed = freeUsed + self.hourlyReplenishment = hourlyReplenishment + self.windowHours = windowHours + self.individualCredits = individualCredits + self.workspaceBalances = workspaceBalances + self.accountEmail = accountEmail + self.accountOrganization = accountOrganization + self.updatedAt = updatedAt + self.freeResetDescription = freeResetDescription + } +} + +extension AmpUsageSnapshot { + public func toUsageSnapshot(now: Date = Date()) -> UsageSnapshot { + let primary: RateWindow? = if let freeQuota, let freeUsed { + { + let quota = max(0, freeQuota) + let used = max(0, freeUsed) + let percent = quota > 0 ? min(100, (used / quota) * 100) : 0 + let windowMinutes: Int? = if let hours = self.windowHours, hours > 0 { + Int((hours * 60).rounded()) + } else { + nil + } + let resetsAt: Date? = { + guard quota > 0, let hourlyReplenishment, hourlyReplenishment > 0 else { return nil } + return now.addingTimeInterval(max(0, used / hourlyReplenishment * 3600)) + }() + return RateWindow( + usedPercent: percent, + windowMinutes: windowMinutes, + resetsAt: resetsAt, + resetDescription: self.freeResetDescription) + }() + } else { + nil + } + + let identity = ProviderIdentitySnapshot( + providerID: .amp, + accountEmail: self.accountEmail, + accountOrganization: self.accountOrganization, + loginMethod: primary == nil ? "Amp" : "Amp Free") + + let ampUsage: AmpUsageDetails? = if self.individualCredits != nil || !self.workspaceBalances.isEmpty { + AmpUsageDetails( + individualCredits: self.individualCredits, + workspaceBalances: self.workspaceBalances) + } else { + nil + } + + return UsageSnapshot( + primary: primary, + secondary: nil, + tertiary: nil, + ampUsage: ampUsage, + providerCost: nil, + updatedAt: self.updatedAt, + identity: identity) + } +} diff --git a/Sources/CodexBarCore/Providers/Antigravity/AntigravityCLISession.swift b/Sources/CodexBarCore/Providers/Antigravity/AntigravityCLISession.swift new file mode 100644 index 0000000..d86d929 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Antigravity/AntigravityCLISession.swift @@ -0,0 +1,1297 @@ +#if canImport(Darwin) +import Darwin +#elseif canImport(Glibc) +import Glibc +#elseif canImport(Musl) +import Musl +#endif +import Foundation + +// MARK: - Antigravity CLI Process Abstractions + +protocol AntigravityCLIProcessHandle: AnyObject, Sendable { + var pid: pid_t { get } + var isRunning: Bool { get } + var processGroup: pid_t? { get } + + func assignProcessGroup() -> pid_t? + func sendExit() throws + func closePTY() + func terminateRoot() + func killRoot() + func descendantPIDs() -> [pid_t] + func terminateTree(signal: Int32, knownDescendants: [pid_t]) + func killDescendants(_ descendants: [pid_t]) + func drainOutput() -> Data +} + +protocol AntigravityCLIProcessLaunching: Sendable { + func launch(binary: String) throws -> any AntigravityCLIProcessHandle +} + +enum AntigravityCLIAuthenticationPrompt { + static let evidence = Data("Select login method:".utf8) + private static let promptPattern = #"select\s+login\s+method\s*:?"# + + static func contains(_ output: Data) -> Bool { + // `agy` briefly prints "You are currently not signed in" before it + // auto-refreshes an existing login. The actual blocking state is the + // interactive login-method prompt. The exact prompt is a CLI-owned TUI + // string, so keep matching tolerant to casing and whitespace changes. + if output.range(of: self.evidence) != nil { + return true + } + let asciiBytes = output.map { $0 < 0x80 ? $0 : 0x20 } + let text = String(bytes: asciiBytes, encoding: .utf8) ?? "" + return text.range( + of: self.promptPattern, + options: [.regularExpression, .caseInsensitive]) != nil + } +} + +struct AntigravityCLIProcessIdentity: Equatable { + let executablePath: String + let startEpoch: TimeInterval +} + +protocol AntigravityCLIProcessIdentityProviding: Sendable { + func identity(for pid: pid_t) -> AntigravityCLIProcessIdentity? +} + +struct AntigravityCLISessionRecord: Codable, Equatable { + let pid: pid_t + let requestedBinaryPath: String + let executablePath: String + let startEpoch: TimeInterval + let processGroup: pid_t? + let ownerPID: pid_t? + let ownerExecutablePath: String? + let ownerStartEpoch: TimeInterval? + + init( + pid: pid_t, + requestedBinaryPath: String, + executablePath: String, + startEpoch: TimeInterval, + processGroup: pid_t?, + ownerPID: pid_t? = nil, + ownerExecutablePath: String? = nil, + ownerStartEpoch: TimeInterval? = nil) + { + self.pid = pid + self.requestedBinaryPath = requestedBinaryPath + self.executablePath = executablePath + self.startEpoch = startEpoch + self.processGroup = processGroup + self.ownerPID = ownerPID + self.ownerExecutablePath = ownerExecutablePath + self.ownerStartEpoch = ownerStartEpoch + } +} + +protocol AntigravityCLISessionRecordStoring: Sendable { + func load() throws -> [AntigravityCLISessionRecord] + func save(_ record: AntigravityCLISessionRecord) throws + func remove(_ record: AntigravityCLISessionRecord) throws +} + +protocol AntigravityCLISessionLaunchLocking: Sendable { + func withLock(_ operation: () throws -> T) throws -> T +} + +// MARK: - AntigravityCLISession + +/// Manages a bounded background ``agy`` process whose embedded localhost server +/// provides the same ``GetUserStatus`` endpoint as the desktop Antigravity app's +/// ``language_server``. The CLI is kept alive in a PTY so its daemon stays bound +/// to a local port - this lets CodexBar read Claude + Gemini quotas even when +/// the desktop Antigravity app is closed. +/// +/// The session intentionally does not scrape TUI output. It only launches and +/// keeps the process reachable for HTTPS probing, drains discarded PTY output so +/// the CLI cannot block on a full terminal buffer, and bounds the warm lifetime +/// with an idle timer so CodexBar does not run an IDE backend forever. +actor AntigravityCLISession { + static let shared = AntigravityCLISession() + private static let log = CodexBarLog.logger(LogCategories.antigravity) + + enum ResetCause: Int { + case deferred + case oneShotCLI + case unhealthy + case authentication + + var message: String { + switch self { + case .deferred: "deferred reset" + case .oneShotCLI: "one-shot CLI fetch" + case .unhealthy: "unhealthy CLI HTTPS session" + case .authentication: "authentication required" + } + } + } + + private struct LaunchOutcome { + let pid: pid_t + let rejectedProcess: (any AntigravityCLIProcessHandle)? + let rejectionMessage: String? + let holdsLaunchReservation: Bool + } + + struct Dependencies { + var launcher: any AntigravityCLIProcessLaunching + var identityProvider: any AntigravityCLIProcessIdentityProviding + var recordStore: any AntigravityCLISessionRecordStoring + var launchLock: any AntigravityCLISessionLaunchLocking + var beginAppShutdownTrackedLaunch: @Sendable () -> Bool + var endAppShutdownTrackedLaunch: @Sendable () -> Void + var registerForAppShutdown: @Sendable (pid_t, String) -> Bool + var updateAppShutdownProcessGroup: @Sendable (pid_t, pid_t?) -> Void + var unregisterForAppShutdown: @Sendable (pid_t) -> Void + var descendantPIDs: @Sendable (pid_t) -> [pid_t] + var terminateProcessTree: @Sendable (pid_t, pid_t?, Int32, [pid_t]) -> Void + var currentProcessID: @Sendable () -> pid_t + var now: @Sendable () -> Date + var sleep: @Sendable (UInt64) async throws -> Void + var idleWindow: TimeInterval + var failureRelaunchThreshold: Int + var terminationGracePeriod: TimeInterval + + static func live() -> Self { + Self( + launcher: AntigravityPTYProcessLauncher(), + identityProvider: AntigravityProcessIdentityProvider(), + recordStore: AntigravityFileCLISessionRecordStore(), + launchLock: AntigravityFileCLISessionLaunchLock(), + beginAppShutdownTrackedLaunch: { + TTYCommandRunner.beginActiveProcessLaunchForAppShutdown() + }, + endAppShutdownTrackedLaunch: { + TTYCommandRunner.endActiveProcessLaunchForAppShutdown() + }, + registerForAppShutdown: { pid, binary in + TTYCommandRunner.registerActiveProcessForAppShutdown(pid: pid, binary: binary) + }, + updateAppShutdownProcessGroup: { pid, group in + TTYCommandRunner.updateActiveProcessGroupForAppShutdown(pid: pid, processGroup: group) + }, + unregisterForAppShutdown: { pid in + TTYCommandRunner.unregisterActiveProcessForAppShutdown(pid: pid) + }, + descendantPIDs: { pid in + TTYProcessTreeTerminator.descendantPIDs(of: pid) + }, + terminateProcessTree: { pid, group, signal, knownDescendants in + TTYProcessTreeTerminator.terminateProcessTree( + rootPID: pid, + processGroup: group, + signal: signal, + knownDescendants: knownDescendants) + }, + currentProcessID: getpid, + now: Date.init, + sleep: { nanoseconds in + try await Task.sleep(nanoseconds: nanoseconds) + }, + idleWindow: 180, + failureRelaunchThreshold: 2, + terminationGracePeriod: 1) + } + } + + // MARK: State + + private let dependencies: Dependencies + private var process: (any AntigravityCLIProcessHandle)? + private var binaryPath: String? + private var sessionIdleWindow: TimeInterval + private var activeProbeCount = 0 + private var activeSessionProbeCount = 0 + private var resetRequestedWhenIdle = false + private var hardResetRequestedWhenIdle = false + private var pendingResetCause: ResetCause? + private var idleTask: Task? + private var sessionGeneration: UInt64 = 0 + private var consecutiveProbeFailures = 0 + private var persistedProcessIdentity: AntigravityCLIProcessIdentity? + private var recentOutput = Data() + private var authenticationPromptObserved = false + private var lastStopReason: String? + private var lifecycleOperationInProgress = false + private var lifecycleWaiters: [CheckedContinuation] = [] + private var exclusiveProbeWaiters: [CheckedContinuation] = [] + + init(dependencies: Dependencies = .live()) { + self.dependencies = dependencies + self.sessionIdleWindow = dependencies.idleWindow + } + + /// The pid of the running ``agy`` process, exposed so callers can discover + /// its listening ports via `lsof`. + var pid: pid_t? { + guard let proc = self.process, proc.isRunning else { return nil } + return proc.pid + } + + /// Whether the managed process is alive and matches ``binaryPath``. + var isRunning: Bool { + guard let proc = self.process, proc.isRunning, self.binaryPath != nil else { return false } + return true + } + + var failureCountForTesting: Int { + self.consecutiveProbeFailures + } + + var idleWindowForTesting: TimeInterval { + self.sessionIdleWindow + } + + var activeProbeCountForTesting: Int { + self.activeProbeCount + } + + var lastStopReasonForTesting: String? { + self.lastStopReason + } + + // MARK: Lifecycle + + /// Mark a probe as active and ensure a warm ``agy`` is running on the given binary path. + /// + /// Callers must balance this with ``finishProbe(success:resetAfterFetch:)`` so + /// idle/reset cleanup cannot kill the process while its ports are being probed. + /// If previous probes repeatedly failed while the process stayed alive, this + /// force-relaunches instead of reusing a wedged HTTPS server forever. + func beginProbe(binary: String, idleWindow: TimeInterval? = nil) async throws -> pid_t { + self.activeProbeCount += 1 + if let idleWindow, idleWindow > 0 { + self.sessionIdleWindow = max(self.dependencies.idleWindow, idleWindow) + } + self.cancelIdleTimer() + do { + return try await self.withLifecycleOperation { + let pid = try await self.ensureStartedLocked(binary: binary) + self.activeSessionProbeCount += 1 + return pid + } + } catch { + self.activeProbeCount = max(0, self.activeProbeCount - 1) + self.notifyExclusiveProbeWaitersIfNeeded() + if self.activeProbeCount == 0, self.resetRequestedWhenIdle { + await self.withLifecycleOperation { + guard self.activeProbeCount == 0 else { + self.resetRequestedWhenIdle = true + return + } + let forceTerminate = self.hardResetRequestedWhenIdle || self.consecutiveProbeFailures > 0 + self.resetRequestedWhenIdle = false + self.hardResetRequestedWhenIdle = false + await self.stopCurrentSessionLocked( + reason: "deferred reset after failed begin", + clearRecord: true, + graceful: !forceTerminate) + } + } + throw error + } + } + + /// Record probe completion and either keep the session warm for the bounded + /// idle window or tear it down immediately for one-shot CLI invocations. + func finishProbe(success: Bool, resetAfterFetch: Bool, forceTerminate: Bool = false) async { + if success { + self.consecutiveProbeFailures = 0 + } else { + self.consecutiveProbeFailures += 1 + } + + self.activeProbeCount = max(0, self.activeProbeCount - 1) + self.activeSessionProbeCount = max(0, self.activeSessionProbeCount - 1) + self.notifyExclusiveProbeWaitersIfNeeded() + let shouldForceStopUnhealthy = !success && + self.consecutiveProbeFailures >= max(1, self.dependencies.failureRelaunchThreshold) + let shouldReset = forceTerminate || resetAfterFetch || self.resetRequestedWhenIdle || shouldForceStopUnhealthy + let currentResetCause = Self.resetCause( + authenticationRequired: forceTerminate, + resetAfterFetch: resetAfterFetch, + shouldForceStopUnhealthy: shouldForceStopUnhealthy) + + guard self.activeProbeCount == 0 else { + if shouldReset { + self.resetRequestedWhenIdle = true + self.pendingResetCause = Self.strongestResetCause(self.pendingResetCause, currentResetCause) + } + if shouldReset, !success || forceTerminate { + self.hardResetRequestedWhenIdle = true + } + return + } + + if shouldReset { + let shouldForceTerminate = !success || forceTerminate || self.hardResetRequestedWhenIdle + let resetCause = Self.strongestResetCause(self.pendingResetCause, currentResetCause) + await self.withLifecycleOperation { + guard self.activeProbeCount == 0 else { + self.resetRequestedWhenIdle = true + self.pendingResetCause = Self.strongestResetCause(self.pendingResetCause, resetCause) + if shouldForceTerminate { + self.hardResetRequestedWhenIdle = true + } + return + } + self.resetRequestedWhenIdle = false + self.hardResetRequestedWhenIdle = false + self.pendingResetCause = nil + await self.stopCurrentSessionLocked( + reason: resetCause.message, + clearRecord: true, + graceful: !shouldForceTerminate) + } + } else { + self.armIdleTimer() + } + } + + static func resetCause( + authenticationRequired: Bool, + resetAfterFetch: Bool, + shouldForceStopUnhealthy: Bool) -> ResetCause + { + if authenticationRequired { + .authentication + } else if shouldForceStopUnhealthy { + .unhealthy + } else if resetAfterFetch { + .oneShotCLI + } else { + .deferred + } + } + + static func strongestResetCause(_ existing: ResetCause?, _ incoming: ResetCause) -> ResetCause { + guard let existing else { return incoming } + return existing.rawValue >= incoming.rawValue ? existing : incoming + } + + /// Ensure a warm ``agy`` is running on the given binary path. + /// + /// - If the process is already alive with the same binary, this returns immediately. + /// - If the process died, the binary changed, or repeated probes failed, it tears down the old one first. + /// - Returns the process identifier for port discovery. + func ensureStarted(binary: String) async throws -> pid_t { + try await self.withLifecycleOperation { + try await self.ensureStartedLocked(binary: binary) + } + } + + /// Request teardown. If a probe is in flight, cleanup is deferred until the + /// matching ``finishProbe(success:resetAfterFetch:)`` call. + func reset() async { + self.cancelIdleTimer() + guard self.activeProbeCount == 0 else { + self.resetRequestedWhenIdle = true + return + } + await self.withLifecycleOperation { + guard self.activeProbeCount == 0 else { + self.resetRequestedWhenIdle = true + return + } + self.resetRequestedWhenIdle = false + let forceTerminate = self.hardResetRequestedWhenIdle || self.consecutiveProbeFailures > 0 + self.hardResetRequestedWhenIdle = false + await self.stopCurrentSessionLocked( + reason: "manual reset", + clearRecord: true, + graceful: !forceTerminate) + } + } + + /// Drain PTY output into one rolling buffer shared by concurrent probes. + func drainOutput() -> Data { + var searchableOutput = self.recentOutput + if let output = self.process?.drainOutput(), !output.isEmpty { + searchableOutput.append(output) + self.recentOutput = Data(searchableOutput.suffix(4096)) + } + + if !self.authenticationPromptObserved, + AntigravityCLIAuthenticationPrompt.contains(searchableOutput) + { + self.authenticationPromptObserved = true + } + if self.authenticationPromptObserved, + !AntigravityCLIAuthenticationPrompt.contains(searchableOutput) + { + searchableOutput.append(AntigravityCLIAuthenticationPrompt.evidence) + } + return searchableOutput + } + + // MARK: Errors + + enum SessionError: LocalizedError { + case launchFailed(String) + + var errorDescription: String? { + switch self { + case let .launchFailed(msg): "Failed to launch Antigravity CLI session: \(msg)" + } + } + } + + // MARK: Private + + private func withLifecycleOperation(_ operation: () async throws -> T) async throws -> T { + await self.acquireLifecycleOperation() + defer { self.releaseLifecycleOperation() } + return try await operation() + } + + private func withLifecycleOperation(_ operation: () async -> Void) async { + await self.acquireLifecycleOperation() + defer { self.releaseLifecycleOperation() } + await operation() + } + + private func acquireLifecycleOperation() async { + guard self.lifecycleOperationInProgress else { + self.lifecycleOperationInProgress = true + return + } + await withCheckedContinuation { continuation in + self.lifecycleWaiters.append(continuation) + } + } + + private func releaseLifecycleOperation() { + guard !self.lifecycleWaiters.isEmpty else { + self.lifecycleOperationInProgress = false + return + } + let next = self.lifecycleWaiters.removeFirst() + next.resume() + } + + private func waitForExclusiveProbeIfNeeded() async { + while self.activeSessionProbeCount > 0 { + await withCheckedContinuation { continuation in + self.exclusiveProbeWaiters.append(continuation) + } + } + } + + private func notifyExclusiveProbeWaitersIfNeeded() { + guard self.activeSessionProbeCount == 0, !self.exclusiveProbeWaiters.isEmpty else { return } + let waiters = self.exclusiveProbeWaiters + self.exclusiveProbeWaiters.removeAll() + for waiter in waiters { + waiter.resume() + } + } + + private func ensureStartedLocked(binary: String) async throws -> pid_t { + while true { + if let proc = self.process, + proc.isRunning, + self.binaryPath == binary, + !self.resetRequestedWhenIdle, + !self.hardResetRequestedWhenIdle, + self.consecutiveProbeFailures < max(1, self.dependencies.failureRelaunchThreshold) + { + try? self.dependencies.launchLock.withLock { + self.reapRecordedSessionsIfNeeded() + } + self.persistCurrentRecordIfNeeded(proc, binary: binary) + Self.log.debug("Antigravity CLI session reused", metadata: ["pid": "\(proc.pid)"]) + return proc.pid + } + + if self.process != nil { + if self.activeSessionProbeCount > 0 { + await self.waitForExclusiveProbeIfNeeded() + continue + } + + let reason = self.consecutiveProbeFailures >= max(1, self.dependencies.failureRelaunchThreshold) + ? "relaunching unhealthy session" + : "replacing stale session" + let forceTerminate = self.hardResetRequestedWhenIdle || self.consecutiveProbeFailures > 0 + self.resetRequestedWhenIdle = false + self.hardResetRequestedWhenIdle = false + await self.stopCurrentSessionLocked( + reason: reason, + clearRecord: true, + graceful: !forceTerminate) + } + + let binaryName = URL(fileURLWithPath: binary).lastPathComponent + let launch: (Bool) throws -> LaunchOutcome = { canPersistRecord in + if canPersistRecord { + self.prepareRecordStoreForLaunch() + } + guard self.dependencies.beginAppShutdownTrackedLaunch() else { + throw SessionError.launchFailed("App shutdown in progress") + } + let launched: any AntigravityCLIProcessHandle + do { + launched = try self.dependencies.launcher.launch(binary: binary) + } catch { + self.dependencies.endAppShutdownTrackedLaunch() + throw error + } + let launchedPID = launched.pid + guard self.dependencies.registerForAppShutdown(launchedPID, binaryName) else { + return LaunchOutcome( + pid: launchedPID, + rejectedProcess: launched, + rejectionMessage: "App shutdown in progress", + holdsLaunchReservation: true) + } + + let processGroup = launched.processGroup ?? launched.assignProcessGroup() + self.dependencies.updateAppShutdownProcessGroup(launchedPID, processGroup) + + self.process = launched + self.binaryPath = binary + self.recentOutput.removeAll(keepingCapacity: true) + self.authenticationPromptObserved = false + self.consecutiveProbeFailures = 0 + self.sessionGeneration &+= 1 + if canPersistRecord { + _ = self.persistRecord(pid: launchedPID, binary: binary, processGroup: processGroup) + } else { + self.persistedProcessIdentity = nil + } + self.dependencies.endAppShutdownTrackedLaunch() + return LaunchOutcome( + pid: launchedPID, + rejectedProcess: nil, + rejectionMessage: nil, + holdsLaunchReservation: false) + } + + var lockedLaunch: Result? + var lockFailure: Error? + do { + try self.dependencies.launchLock.withLock { + lockedLaunch = Result { try launch(true) } + } + } catch { + lockFailure = error + } + + let outcome: LaunchOutcome + if let lockFailure { + Self.log.warning( + "Antigravity CLI session coordination unavailable", + metadata: ["error": lockFailure.localizedDescription]) + outcome = try launch(false) + } else if let lockedLaunch { + outcome = try lockedLaunch.get() + } else { + throw SessionError.launchFailed("CLI session launch did not complete") + } + if let rejectedProcess = outcome.rejectedProcess { + await self.terminateLaunchedProcess(rejectedProcess, graceful: false) + if outcome.holdsLaunchReservation { + self.dependencies.endAppShutdownTrackedLaunch() + } + throw SessionError.launchFailed(outcome.rejectionMessage ?? "App shutdown in progress") + } + + Self.log.debug( + "Antigravity CLI session started", + metadata: [ + "binary": binaryName, + "pid": "\(outcome.pid)", + ]) + return outcome.pid + } + } + + private func prepareRecordStoreForLaunch() { + guard self.process == nil || self.persistedProcessIdentity == nil else { return } + self.reapRecordedSessionsIfNeeded() + } + + private func persistCurrentRecordIfNeeded(_ proc: any AntigravityCLIProcessHandle, binary: String) { + guard self.persistedProcessIdentity == nil else { return } + try? self.dependencies.launchLock.withLock { + self.prepareRecordStoreForLaunch() + _ = self.persistRecord(pid: proc.pid, binary: binary, processGroup: proc.processGroup) + } + } + + private func cancelIdleTimer() { + self.idleTask?.cancel() + self.idleTask = nil + } + + private func armIdleTimer() { + guard self.process != nil, self.sessionIdleWindow > 0 else { return } + self.cancelIdleTimer() + let generation = self.sessionGeneration + let nanoseconds = Self.nanoseconds(from: self.sessionIdleWindow) + let sleep = self.dependencies.sleep + self.idleTask = Task { [weak self] in + do { + try await sleep(nanoseconds) + await self?.stopIfIdle(generation: generation) + } catch { + // Cancellation is the normal path when a refresh reuses the warm session. + } + } + } + + private func stopIfIdle(generation: UInt64) async { + await self.withLifecycleOperation { + guard generation == self.sessionGeneration else { return } + guard self.activeProbeCount == 0 else { + self.armIdleTimer() + return + } + let forceTerminate = self.hardResetRequestedWhenIdle || self.consecutiveProbeFailures > 0 + self.resetRequestedWhenIdle = false + self.hardResetRequestedWhenIdle = false + await self.stopCurrentSessionLocked( + reason: "idle timeout", + clearRecord: true, + graceful: !forceTerminate) + } + } + + private func stopCurrentSessionLocked(reason: String, clearRecord: Bool, graceful: Bool = true) async { + self.cancelIdleTimer() + let effectiveReason = self.pendingResetCause?.message ?? reason + self.pendingResetCause = nil + self.lastStopReason = effectiveReason + guard let proc = self.process else { + if clearRecord { + try? self.dependencies.launchLock.withLock { + self.reapRecordedSessionsIfNeeded() + } + } + self.sessionIdleWindow = self.dependencies.idleWindow + self.recentOutput.removeAll(keepingCapacity: true) + self.authenticationPromptObserved = false + return + } + + let pid = proc.pid + let identity = self.persistedProcessIdentity + Self.log.debug("Antigravity CLI session stopping", metadata: ["pid": "\(pid)", "reason": "\(effectiveReason)"]) + + self.process = nil + self.binaryPath = nil + self.persistedProcessIdentity = nil + self.sessionIdleWindow = self.dependencies.idleWindow + self.recentOutput.removeAll(keepingCapacity: true) + self.authenticationPromptObserved = false + self.sessionGeneration &+= 1 + + await self.terminateLaunchedProcess(proc, graceful: graceful) + self.dependencies.unregisterForAppShutdown(pid) + if clearRecord { + self.removeRecordIfMatches(pid: pid, identity: identity) + } + } + + private func terminateLaunchedProcess( + _ proc: any AntigravityCLIProcessHandle, + graceful: Bool = true) async + { + if graceful { + try? proc.sendExit() + } + proc.closePTY() + + let descendants = proc.descendantPIDs() + if proc.isRunning { + proc.terminateRoot() + } + proc.terminateTree(signal: SIGTERM, knownDescendants: descendants) + + let gracePeriod = self.dependencies.terminationGracePeriod + if gracePeriod > 0 { + let deadline = self.dependencies.now().addingTimeInterval(gracePeriod) + while proc.isRunning, self.dependencies.now() < deadline { + try? await self.dependencies.sleep(100_000_000) + } + } + + if proc.isRunning { + proc.terminateTree(signal: SIGKILL, knownDescendants: descendants) + await self.waitUntilProcessExits(proc, timeout: 1) + } else { + proc.killDescendants(descendants) + } + } + + private func waitUntilProcessExits(_ proc: any AntigravityCLIProcessHandle, timeout: TimeInterval) async { + let deadline = self.dependencies.now().addingTimeInterval(timeout) + while proc.isRunning, self.dependencies.now() < deadline { + try? await self.dependencies.sleep(50_000_000) + } + _ = proc.isRunning + } + + @discardableResult + private func persistRecord(pid: pid_t, binary: String, processGroup: pid_t?) -> Bool { + guard let identity = self.dependencies.identityProvider.identity(for: pid) else { + self.persistedProcessIdentity = nil + return false + } + let ownerPID = self.dependencies.currentProcessID() + let ownerIdentity = self.dependencies.identityProvider.identity(for: ownerPID) + let record = AntigravityCLISessionRecord( + pid: pid, + requestedBinaryPath: binary, + executablePath: identity.executablePath, + startEpoch: identity.startEpoch, + processGroup: processGroup, + ownerPID: ownerPID, + ownerExecutablePath: ownerIdentity?.executablePath, + ownerStartEpoch: ownerIdentity?.startEpoch) + do { + try self.dependencies.recordStore.save(record) + self.persistedProcessIdentity = identity + return true + } catch { + self.persistedProcessIdentity = nil + return false + } + } + + private func reapRecordedSessionsIfNeeded() { + guard let records = try? self.dependencies.recordStore.load() else { return } + for record in records { + guard let liveIdentity = self.dependencies.identityProvider.identity(for: record.pid), + liveIdentity.executablePath == record.executablePath, + abs(liveIdentity.startEpoch - record.startEpoch) < 0.001 + else { + try? self.dependencies.recordStore.remove(record) + continue + } + if let proc = self.process, proc.pid == record.pid { + self.persistedProcessIdentity = liveIdentity + continue + } + if let ownerPID = record.ownerPID, + ownerPID != self.dependencies.currentProcessID(), + let ownerExecutablePath = record.ownerExecutablePath, + let ownerStartEpoch = record.ownerStartEpoch, + let liveOwnerIdentity = self.dependencies.identityProvider.identity(for: ownerPID), + liveOwnerIdentity.executablePath == ownerExecutablePath, + abs(liveOwnerIdentity.startEpoch - ownerStartEpoch) < 0.001 + { + continue + } + + let knownDescendants = self.dependencies.descendantPIDs(record.pid) + Self.log.debug("Reaping stale Antigravity CLI session", metadata: ["pid": "\(record.pid)"]) + self.dependencies.terminateProcessTree(record.pid, record.processGroup, SIGTERM, knownDescendants) + self.dependencies.terminateProcessTree(record.pid, record.processGroup, SIGKILL, knownDescendants) + try? self.dependencies.recordStore.remove(record) + } + } + + private func removeRecordIfMatches(pid: pid_t, identity: AntigravityCLIProcessIdentity?) { + try? self.dependencies.launchLock.withLock { + guard let identity, let records = try? self.dependencies.recordStore.load() else { return } + for record in records + where record.pid == pid && + record.executablePath == identity.executablePath && + abs(record.startEpoch - identity.startEpoch) < 0.001 + { + try? self.dependencies.recordStore.remove(record) + } + } + } + + private static func nanoseconds(from interval: TimeInterval) -> UInt64 { + guard interval > 0 else { return 0 } + guard interval.isFinite else { return UInt64.max } + let nanoseconds = interval * 1_000_000_000 + guard nanoseconds < TimeInterval(UInt64.max) else { return UInt64.max } + return UInt64(nanoseconds) + } +} + +// MARK: - Production Process Implementation + +struct AntigravityPTYProcessLauncher: AntigravityCLIProcessLaunching { + static func defaultSignalsForSpawn() -> sigset_t { + var signals = sigset_t() + sigemptyset(&signals) + sigaddset(&signals, SIGINT) + sigaddset(&signals, SIGTERM) + sigaddset(&signals, SIGHUP) + return signals + } + + static func spawnWithTextBusyRetry( + maxAttempts: Int = 3, + retryDelay: TimeInterval = 0.01, + spawn: () -> Int32) -> Int32 + { + var result = spawn() + guard maxAttempts > 1 else { return result } + + for _ in 1.. 0 { + Thread.sleep(forTimeInterval: retryDelay) + } + result = spawn() + } + return result + } + + func launch(binary: String) throws -> any AntigravityCLIProcessHandle { + try self.launch(binary: binary, arguments: []) + } + + func launch(binary: String, arguments: [String]) throws -> any AntigravityCLIProcessHandle { + var primaryFD: Int32 = -1 + var secondaryFD: Int32 = -1 + var win = winsize(ws_row: 50, ws_col: 160, ws_xpixel: 0, ws_ypixel: 0) + guard openpty(&primaryFD, &secondaryFD, nil, nil, &win) == 0 else { + throw AntigravityCLISession.SessionError.launchFailed("openpty failed") + } + _ = fcntl(primaryFD, F_SETFL, O_NONBLOCK) + + let primaryHandle = FileHandle(fileDescriptor: primaryFD, closeOnDealloc: true) + let secondaryHandle = FileHandle(fileDescriptor: secondaryFD, closeOnDealloc: true) + + #if canImport(Darwin) + var fileActions: posix_spawn_file_actions_t? + #else + var fileActions = posix_spawn_file_actions_t() + #endif + guard posix_spawn_file_actions_init(&fileActions) == 0 else { + try? primaryHandle.close() + try? secondaryHandle.close() + throw AntigravityCLISession.SessionError.launchFailed("posix_spawn_file_actions_init failed") + } + defer { posix_spawn_file_actions_destroy(&fileActions) } + + posix_spawn_file_actions_adddup2(&fileActions, secondaryFD, 0) + posix_spawn_file_actions_adddup2(&fileActions, secondaryFD, 1) + posix_spawn_file_actions_adddup2(&fileActions, secondaryFD, 2) + posix_spawn_file_actions_addclose(&fileActions, primaryFD) + posix_spawn_file_actions_addclose(&fileActions, secondaryFD) + + let homeDirectory = NSHomeDirectory() + _ = homeDirectory.withCString { path in + posix_spawn_file_actions_addchdir_np(&fileActions, path) + } + #if canImport(Glibc) || canImport(Musl) + do { + try PosixSpawnFileActionsCloseFrom.addCloseFrom(&fileActions, startingAt: 3) + } catch { + try? primaryHandle.close() + try? secondaryHandle.close() + throw AntigravityCLISession.SessionError.launchFailed(error.localizedDescription) + } + #endif + + #if canImport(Darwin) + var attr: posix_spawnattr_t? + #else + var attr = posix_spawnattr_t() + #endif + guard posix_spawnattr_init(&attr) == 0 else { + try? primaryHandle.close() + try? secondaryHandle.close() + throw AntigravityCLISession.SessionError.launchFailed("posix_spawnattr_init failed") + } + defer { posix_spawnattr_destroy(&attr) } + var defaultSignals = Self.defaultSignalsForSpawn() + posix_spawnattr_setsigdefault(&attr, &defaultSignals) + #if canImport(Darwin) + let spawnFlags = POSIX_SPAWN_SETPGROUP | POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_CLOEXEC_DEFAULT + #else + let spawnFlags = POSIX_SPAWN_SETPGROUP | POSIX_SPAWN_SETSIGDEF + #endif + posix_spawnattr_setflags(&attr, Int16(spawnFlags)) + posix_spawnattr_setpgroup(&attr, 0) + + var env = TTYCommandRunner.enrichedEnvironment() + env["PWD"] = NSHomeDirectory() + env["TERM"] = "xterm-256color" + + var cArgs = ([binary] + arguments).map { strdup($0) as UnsafeMutablePointer? } + cArgs.append(nil) + defer { + for arg in cArgs { + if let arg { + free(arg) + } + } + } + + var cEnv: [UnsafeMutablePointer?] = env.map { key, value in + strdup("\(key)=\(value)") + } + cEnv.append(nil) + defer { + for entry in cEnv { + if let entry { + free(entry) + } + } + } + + var pid: pid_t = 0 + let spawnResult = Self.spawnWithTextBusyRetry { + binary.withCString { execPath in + posix_spawn(&pid, execPath, &fileActions, &attr, cArgs, cEnv) + } + } + guard spawnResult == 0 else { + try? primaryHandle.close() + try? secondaryHandle.close() + throw AntigravityCLISession.SessionError.launchFailed(String(cString: strerror(spawnResult))) + } + + return AntigravitySpawnedPTYProcessHandle( + pid: pid, + processGroup: pid, + primaryFD: primaryFD, + primaryHandle: primaryHandle, + secondaryHandle: secondaryHandle) + } +} + +final class AntigravitySpawnedPTYProcessHandle: AntigravityCLIProcessHandle, @unchecked Sendable { + private let lock = NSLock() + private let processPID: pid_t + private let processGroupID: pid_t + private let primaryFD: Int32 + private let primaryHandle: FileHandle + private let secondaryHandle: FileHandle + private var reaped = false + + init( + pid: pid_t, + processGroup: pid_t, + primaryFD: Int32, + primaryHandle: FileHandle, + secondaryHandle: FileHandle) + { + self.processPID = pid + self.processGroupID = processGroup + self.primaryFD = primaryFD + self.primaryHandle = primaryHandle + self.secondaryHandle = secondaryHandle + } + + var pid: pid_t { + self.processPID + } + + var isRunning: Bool { + self.lock.lock() + if self.reaped { + self.lock.unlock() + return false + } + self.lock.unlock() + + var status: Int32 = 0 + let result = waitpid(self.processPID, &status, WNOHANG) + + self.lock.lock() + defer { self.lock.unlock() } + switch result { + case 0: + return true + case self.processPID: + self.reaped = true + return false + case -1 where errno == ECHILD: + self.reaped = true + return false + default: + return kill(self.processPID, 0) == 0 || errno == EPERM + } + } + + var processGroup: pid_t? { + self.processGroupID + } + + func assignProcessGroup() -> pid_t? { + self.processGroupID + } + + func sendExit() throws { + try self.writeAllToPrimary(Data("/exit\r".utf8)) + } + + func closePTY() { + try? self.primaryHandle.close() + try? self.secondaryHandle.close() + } + + func terminateRoot() { + kill(self.processPID, SIGTERM) + } + + func killRoot() { + kill(self.processPID, SIGKILL) + } + + func descendantPIDs() -> [pid_t] { + TTYProcessTreeTerminator.descendantPIDs(of: self.processPID) + } + + func terminateTree(signal: Int32, knownDescendants: [pid_t]) { + TTYProcessTreeTerminator.terminateProcessTree( + rootPID: self.processPID, + processGroup: self.processGroupID, + signal: signal, + knownDescendants: knownDescendants) + } + + func killDescendants(_ descendants: [pid_t]) { + for pid in descendants where pid > 0 { + kill(pid, SIGKILL) + } + } + + func drainOutput() -> Data { + var tmp = [UInt8](repeating: 0, count: 8192) + var output: [UInt8] = [] + for _ in 0..<64 { + let n = read(self.primaryFD, &tmp, tmp.count) + if n > 0 { + output.append(contentsOf: tmp.prefix(n)) + continue + } + break + } + return Data(output) + } + + private func writeAllToPrimary(_ data: Data) throws { + data.withUnsafeBytes { rawBytes in + guard let baseAddress = rawBytes.baseAddress else { return } + var offset = 0 + var retries = 0 + while offset < rawBytes.count { + let written = write(self.primaryFD, baseAddress.advanced(by: offset), rawBytes.count - offset) + if written > 0 { + offset += written + retries = 0 + continue + } + if written == 0 { break } + + let err = errno + if err == EINTR || err == EAGAIN || err == EWOULDBLOCK { + retries += 1 + if retries > 200 { return } + usleep(5000) + continue + } + return + } + } + } +} + +// MARK: - Production Stale Session Identity + Storage + +struct AntigravityProcessIdentityProvider: AntigravityCLIProcessIdentityProviding { + static var currentUserID: UInt32 { + UInt32(getuid()) + } + + func ownerUserID(for pid: pid_t) -> UInt32? { + #if canImport(Darwin) + var info = proc_bsdinfo() + let size = proc_pidinfo( + pid, + PROC_PIDTBSDINFO, + 0, + &info, + Int32(MemoryLayout.stride)) + guard size == Int32(MemoryLayout.stride) else { return nil } + return info.pbi_uid + #else + guard let status = try? String(contentsOfFile: "/proc/\(pid)/status", encoding: .utf8), + let uidLine = status.split(separator: "\n").first(where: { $0.hasPrefix("Uid:") }), + let owner = uidLine.split(whereSeparator: \.isWhitespace).dropFirst().first, + let userID = UInt32(owner) + else { + return nil + } + return userID + #endif + } + + func identity(for pid: pid_t) -> AntigravityCLIProcessIdentity? { + #if canImport(Darwin) + var pathBuffer = [CChar](repeating: 0, count: 4096) + let pathLength = proc_pidpath(pid, &pathBuffer, UInt32(pathBuffer.count)) + guard pathLength > 0 else { return nil } + let executablePath = pathBuffer.withUnsafeBufferPointer { buffer -> String? in + let rawBytes = UnsafeRawBufferPointer(start: buffer.baseAddress, count: Int(pathLength)) + return String(bytes: rawBytes.prefix { $0 != 0 }, encoding: .utf8) + } + guard let executablePath, !executablePath.isEmpty else { return nil } + + var info = proc_bsdinfo() + let size = proc_pidinfo( + pid, + PROC_PIDTBSDINFO, + 0, + &info, + Int32(MemoryLayout.stride)) + guard size == Int32(MemoryLayout.stride) else { return nil } + let startEpoch = TimeInterval(info.pbi_start_tvsec) + (TimeInterval(info.pbi_start_tvusec) / 1_000_000) + return AntigravityCLIProcessIdentity(executablePath: executablePath, startEpoch: startEpoch) + #else + let procDirectory = "/proc/\(pid)" + guard let executablePath = try? FileManager.default.destinationOfSymbolicLink( + atPath: "\(procDirectory)/exe"), + let stat = try? String(contentsOfFile: "\(procDirectory)/stat", encoding: .utf8), + let closeParen = stat.lastIndex(of: ")") + else { + return nil + } + let fields = stat[stat.index(after: closeParen)...].split(whereSeparator: \.isWhitespace) + let clockTicksPerSecond = sysconf(Int32(_SC_CLK_TCK)) + let systemStat = try? String(contentsOfFile: "/proc/stat", encoding: .utf8) + let bootEpoch = systemStat? + .split(separator: "\n") + .first { $0.hasPrefix("btime ") }? + .split(whereSeparator: \.isWhitespace) + .dropFirst() + .first + .flatMap { TimeInterval($0) } + guard fields.count > 19, + let startTicks = TimeInterval(fields[19]), + clockTicksPerSecond > 0, + let bootEpoch + else { + return nil + } + let startEpoch = bootEpoch + (startTicks / TimeInterval(clockTicksPerSecond)) + return AntigravityCLIProcessIdentity(executablePath: executablePath, startEpoch: startEpoch) + #endif + } +} + +final class AntigravityFileCLISessionRecordStore: AntigravityCLISessionRecordStoring, @unchecked Sendable { + private let fileURL: URL + private let fileManager: FileManager + + init( + fileURL: URL = URL(fileURLWithPath: NSHomeDirectory(), isDirectory: true) + .appendingPathComponent(".codexbar", isDirectory: true) + .appendingPathComponent("antigravity", isDirectory: true) + .appendingPathComponent("agy-session.json"), + fileManager: FileManager = .default) + { + self.fileURL = fileURL + self.fileManager = fileManager + } + + func load() throws -> [AntigravityCLISessionRecord] { + guard self.fileManager.fileExists(atPath: self.fileURL.path) else { return [] } + let data = try Data(contentsOf: self.fileURL) + let decoder = JSONDecoder() + if let records = try? decoder.decode([AntigravityCLISessionRecord].self, from: data) { + return records + } + return try [decoder.decode(AntigravityCLISessionRecord.self, from: data)] + } + + func save(_ record: AntigravityCLISessionRecord) throws { + var records = (try? self.load()) ?? [] + records.removeAll { Self.sameOwner($0, record) } + records.append(record) + try self.write(records) + } + + func remove(_ record: AntigravityCLISessionRecord) throws { + var records = try self.load() + records.removeAll { + $0.pid == record.pid && + $0.executablePath == record.executablePath && + abs($0.startEpoch - record.startEpoch) < 0.001 + } + if records.isEmpty { + guard self.fileManager.fileExists(atPath: self.fileURL.path) else { return } + try self.fileManager.removeItem(at: self.fileURL) + } else { + try self.write(records) + } + } + + private func write(_ records: [AntigravityCLISessionRecord]) throws { + let directory = self.fileURL.deletingLastPathComponent() + try self.fileManager.createDirectory(at: directory, withIntermediateDirectories: true) + let data = try JSONEncoder().encode(records) + try data.write(to: self.fileURL, options: [.atomic]) + } + + private static func sameOwner( + _ lhs: AntigravityCLISessionRecord, + _ rhs: AntigravityCLISessionRecord) -> Bool + { + if let lhsOwnerPID = lhs.ownerPID, + let rhsOwnerPID = rhs.ownerPID, + let lhsOwnerPath = lhs.ownerExecutablePath, + let rhsOwnerPath = rhs.ownerExecutablePath, + let lhsOwnerStart = lhs.ownerStartEpoch, + let rhsOwnerStart = rhs.ownerStartEpoch + { + return lhsOwnerPID == rhsOwnerPID && + lhsOwnerPath == rhsOwnerPath && + abs(lhsOwnerStart - rhsOwnerStart) < 0.001 + } + return lhs.pid == rhs.pid && + lhs.executablePath == rhs.executablePath && + abs(lhs.startEpoch - rhs.startEpoch) < 0.001 + } +} + +final class AntigravityFileCLISessionLaunchLock: AntigravityCLISessionLaunchLocking, @unchecked Sendable { + private let fileURL: URL + private let fileManager: FileManager + + init( + fileURL: URL = URL(fileURLWithPath: NSHomeDirectory(), isDirectory: true) + .appendingPathComponent(".codexbar", isDirectory: true) + .appendingPathComponent("antigravity", isDirectory: true) + .appendingPathComponent("agy-session.lock"), + fileManager: FileManager = .default) + { + self.fileURL = fileURL + self.fileManager = fileManager + } + + func withLock(_ operation: () throws -> T) throws -> T { + let directory = self.fileURL.deletingLastPathComponent() + try self.fileManager.createDirectory(at: directory, withIntermediateDirectories: true) + let fd = open(self.fileURL.path, O_CREAT | O_RDWR | O_CLOEXEC, S_IRUSR | S_IWUSR) + guard fd >= 0 else { + throw POSIXError(POSIXErrorCode(rawValue: errno) ?? .EIO) + } + defer { + _ = flock(fd, LOCK_UN) + close(fd) + } + + while flock(fd, LOCK_EX) != 0 { + guard errno == EINTR else { + throw POSIXError(POSIXErrorCode(rawValue: errno) ?? .EIO) + } + } + return try operation() + } +} diff --git a/Sources/CodexBarCore/Providers/Antigravity/AntigravityLocalSnapshotSelection.swift b/Sources/CodexBarCore/Providers/Antigravity/AntigravityLocalSnapshotSelection.swift new file mode 100644 index 0000000..83785a1 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Antigravity/AntigravityLocalSnapshotSelection.swift @@ -0,0 +1,37 @@ +import Foundation + +extension AntigravityStatusProbe { + static func preferredLocalSnapshot( + _ snapshots: [AntigravityStatusSnapshot], + matchingAccountEmail expectedAccountEmail: String?) -> AntigravityStatusSnapshot? + { + var candidates = snapshots + if let expected = self.normalizedAccountEmail(expectedAccountEmail) { + let matches = snapshots.filter { + guard let found = self.normalizedAccountEmail($0.accountEmail) else { return false } + return found.caseInsensitiveCompare(expected) == .orderedSame + } + if !matches.isEmpty { + candidates = matches + } + } + + var bestSnapshot: AntigravityStatusSnapshot? + var bestScore = Int.min + for snapshot in candidates { + let score = self.localSnapshotScore(snapshot) + if score > bestScore { + bestSnapshot = snapshot + bestScore = score + } + } + return bestSnapshot + } + + private static func normalizedAccountEmail(_ email: String?) -> String? { + guard let trimmed = email?.trimmingCharacters(in: .whitespacesAndNewlines), !trimmed.isEmpty else { + return nil + } + return trimmed + } +} diff --git a/Sources/CodexBarCore/Providers/Antigravity/AntigravityLocalhostSession.swift b/Sources/CodexBarCore/Providers/Antigravity/AntigravityLocalhostSession.swift new file mode 100644 index 0000000..5a372ea --- /dev/null +++ b/Sources/CodexBarCore/Providers/Antigravity/AntigravityLocalhostSession.swift @@ -0,0 +1,109 @@ +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +enum LocalhostTrustPolicy { + static func shouldAcceptServerTrust( + host: String, + authenticationMethod: String, + hasServerTrust: Bool) -> Bool + { + #if !os(Linux) + guard authenticationMethod == NSURLAuthenticationMethodServerTrust else { return false } + #endif + let normalizedHost = host.lowercased() + guard normalizedHost == "127.0.0.1" || normalizedHost == "localhost" else { return false } + return hasServerTrust + } +} + +final class LocalhostSessionDelegate: NSObject { + func data(for request: URLRequest, session: URLSession) async throws -> (Data, URLResponse) { + let state = LocalhostSessionTaskState() + return try await withTaskCancellationHandler { + try await withCheckedThrowingContinuation { continuation in + let task = session.dataTask(with: request) { data, response, error in + if let error { + continuation.resume(throwing: error) + return + } + guard let data, let response else { + continuation.resume(throwing: AntigravityStatusProbeError.apiError("Invalid response")) + return + } + continuation.resume(returning: (data, response)) + } + state.setTask(task) + task.resume() + } + } onCancel: { + state.cancel() + } + } + + private func challengeResult(_ challenge: URLAuthenticationChallenge) -> ( + disposition: URLSession.AuthChallengeDisposition, + credential: URLCredential?) + { + #if os(Linux) + return (.performDefaultHandling, nil) + #else + let protectionSpace = challenge.protectionSpace + let trust = protectionSpace.serverTrust + guard LocalhostTrustPolicy.shouldAcceptServerTrust( + host: protectionSpace.host, + authenticationMethod: protectionSpace.authenticationMethod, + hasServerTrust: trust != nil), + let trust + else { + return (.performDefaultHandling, nil) + } + return (.useCredential, URLCredential(trust: trust)) + #endif + } +} + +extension LocalhostSessionDelegate: URLSessionDelegate { + func urlSession( + _ session: URLSession, + didReceive challenge: URLAuthenticationChallenge) async -> (URLSession.AuthChallengeDisposition, URLCredential?) + { + self.challengeResult(challenge) + } +} + +extension LocalhostSessionDelegate: URLSessionTaskDelegate { + func urlSession( + _ session: URLSession, + task: URLSessionTask, + didReceive challenge: URLAuthenticationChallenge) async -> (URLSession.AuthChallengeDisposition, URLCredential?) + { + self.challengeResult(challenge) + } +} + +private final class LocalhostSessionTaskState: @unchecked Sendable { + private let lock = NSLock() + private var task: URLSessionDataTask? + private var isCancelled = false + + func setTask(_ task: URLSessionDataTask) { + self.lock.lock() + self.task = task + let shouldCancel = self.isCancelled + self.lock.unlock() + + if shouldCancel { + task.cancel() + } + } + + func cancel() { + self.lock.lock() + self.isCancelled = true + let task = self.task + self.lock.unlock() + task?.cancel() + } +} diff --git a/Sources/CodexBarCore/Providers/Antigravity/AntigravityOAuthCredentialsStore.swift b/Sources/CodexBarCore/Providers/Antigravity/AntigravityOAuthCredentialsStore.swift new file mode 100644 index 0000000..06819e0 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Antigravity/AntigravityOAuthCredentialsStore.swift @@ -0,0 +1,516 @@ +import Foundation + +public struct AntigravityOAuthCredentials: Codable, Sendable, Equatable { + public var accessToken: String? + public var refreshToken: String? + public var expiryDateMilliseconds: Double? + public var idToken: String? + public var email: String? + public var projectID: String? + public var clientID: String? + public var clientSecret: String? + + public init( + accessToken: String?, + refreshToken: String?, + expiryDate: Date?, + idToken: String? = nil, + email: String? = nil, + projectID: String? = nil, + clientID: String? = nil, + clientSecret: String? = nil) + { + self.accessToken = accessToken + self.refreshToken = refreshToken + self.expiryDateMilliseconds = expiryDate.map { $0.timeIntervalSince1970 * 1000 } + self.idToken = idToken + self.email = email + self.projectID = projectID + self.clientID = clientID + self.clientSecret = clientSecret + } + + public var expiryDate: Date? { + guard let expiryDateMilliseconds else { return nil } + return Date(timeIntervalSince1970: expiryDateMilliseconds / 1000) + } + + /// Email of the Google account these credentials authenticate, preferring the + /// signed `id_token` claim (what the remote OAuth fetcher reports) and falling + /// back to the stored `email` field. Used to verify that an ambient local/CLI + /// Antigravity snapshot belongs to the account the user explicitly selected. + public var resolvedAccountEmail: String? { + Self.email(fromIDToken: self.idToken) ?? self.email?.trimmedNonEmptyEmail + } + + static func email(fromIDToken idToken: String?) -> String? { + guard let idToken else { return nil } + let parts = idToken.components(separatedBy: ".") + guard parts.count >= 2 else { return nil } + var payload = parts[1] + .replacingOccurrences(of: "-", with: "+") + .replacingOccurrences(of: "_", with: "/") + let remainder = payload.count % 4 + if remainder > 0 { + payload += String(repeating: "=", count: 4 - remainder) + } + guard let data = Data(base64Encoded: payload, options: .ignoreUnknownCharacters), + let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] + else { + return nil + } + return (json["email"] as? String)?.trimmedNonEmptyEmail + } + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.accessToken = + try container.decodeIfPresent(String.self, forKey: .accessTokenSnake) + ?? container.decodeIfPresent(String.self, forKey: .accessTokenCamel) + self.refreshToken = + try container.decodeIfPresent(String.self, forKey: .refreshTokenSnake) + ?? container.decodeIfPresent(String.self, forKey: .refreshTokenCamel) + self.idToken = + try container.decodeIfPresent(String.self, forKey: .idTokenSnake) + ?? container.decodeIfPresent(String.self, forKey: .idTokenCamel) + self.email = try container.decodeIfPresent(String.self, forKey: .email) + self.projectID = + try container.decodeIfPresent(String.self, forKey: .projectIDSnake) + ?? container.decodeIfPresent(String.self, forKey: .projectIDCamel) + self.clientID = + try container.decodeIfPresent(String.self, forKey: .clientIDSnake) + ?? container.decodeIfPresent(String.self, forKey: .clientIDCamel) + self.clientSecret = + try container.decodeIfPresent(String.self, forKey: .clientSecretSnake) + ?? container.decodeIfPresent(String.self, forKey: .clientSecretCamel) + + if let expiryDateMilliseconds = try container.decodeIfPresent(Double.self, forKey: .expiryDateSnake) + ?? container.decodeIfPresent(Double.self, forKey: .expiresAtCamel) + { + self.expiryDateMilliseconds = expiryDateMilliseconds + } else if let expiryDateMilliseconds = try container.decodeIfPresent(Int.self, forKey: .expiryDateSnake) + ?? container.decodeIfPresent(Int.self, forKey: .expiresAtCamel) + { + self.expiryDateMilliseconds = Double(expiryDateMilliseconds) + } else { + self.expiryDateMilliseconds = nil + } + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encodeIfPresent(self.accessToken, forKey: .accessTokenSnake) + try container.encodeIfPresent(self.refreshToken, forKey: .refreshTokenSnake) + try container.encodeIfPresent(self.expiryDateMilliseconds, forKey: .expiryDateSnake) + try container.encodeIfPresent(self.idToken, forKey: .idTokenSnake) + try container.encodeIfPresent(self.email, forKey: .email) + try container.encodeIfPresent(self.projectID, forKey: .projectIDSnake) + try container.encodeIfPresent(self.clientID, forKey: .clientIDSnake) + try container.encodeIfPresent(self.clientSecret, forKey: .clientSecretSnake) + } + + enum CodingKeys: String, CodingKey { + case accessTokenSnake = "access_token" + case accessTokenCamel = "accessToken" + case refreshTokenSnake = "refresh_token" + case refreshTokenCamel = "refreshToken" + case expiryDateSnake = "expiry_date" + case expiresAtCamel = "expiresAt" + case idTokenSnake = "id_token" + case idTokenCamel = "idToken" + case email + case projectIDSnake = "project_id" + case projectIDCamel = "projectId" + case clientIDSnake = "client_id" + case clientIDCamel = "clientId" + case clientSecretSnake = "client_secret" + case clientSecretCamel = "clientSecret" + } +} + +public struct AntigravityOAuthClient: Sendable, Equatable { + public let clientID: String + public let clientSecret: String + + public init(clientID: String, clientSecret: String) { + self.clientID = clientID + self.clientSecret = clientSecret + } +} + +public enum AntigravityOAuthConfig { + public static var configuredClientID: String? { + let value = ProcessInfo.processInfo.environment["ANTIGRAVITY_OAUTH_CLIENT_ID"] + return value?.trimmingCharacters(in: .whitespacesAndNewlines).nilIfEmpty + } + + public static var configuredClientSecret: String? { + let value = ProcessInfo.processInfo.environment["ANTIGRAVITY_OAUTH_CLIENT_SECRET"] + return value?.trimmingCharacters(in: .whitespacesAndNewlines).nilIfEmpty + } + + public static let authURL = URL(string: "https://accounts.google.com/o/oauth2/v2/auth")! + public static let tokenURL = URL(string: "https://oauth2.googleapis.com/token")! + public static let userInfoURL = URL(string: "https://www.googleapis.com/oauth2/v2/userinfo")! + public static let scopes = [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/userinfo.email", + ] + + public static let missingCredentialsMessage = + """ + Antigravity OAuth client is not configured. Install Antigravity.app or set \ + ANTIGRAVITY_OAUTH_CLIENT_ID and ANTIGRAVITY_OAUTH_CLIENT_SECRET before logging in. + """ + + public static func resolvedClient() -> AntigravityOAuthClient? { + if let client = environmentClient() { + return client + } + return Self.discoverClientFromInstalledApp() + } + + private static func environmentClient() -> AntigravityOAuthClient? { + guard let clientID = configuredClientID, + let clientSecret = configuredClientSecret + else { + return nil + } + return AntigravityOAuthClient(clientID: clientID, clientSecret: clientSecret) + } + + static func discoverClientFromInstalledApp( + applicationRoots: [URL]? = nil, + fileManager: FileManager = .default) -> AntigravityOAuthClient? + { + for url in self.candidateOAuthClientArtifactURLs( + applicationRoots: applicationRoots, + fileManager: fileManager) + where fileManager.fileExists(atPath: url.path) + { + guard let data = try? Data(contentsOf: url), + let client = Self.parseClient(fromInstalledArtifactData: data) + else { + continue + } + return client + } + return nil + } + + static func candidateOAuthClientArtifactURLs( + applicationRoots: [URL]? = nil, + fileManager: FileManager = .default) -> [URL] + { + let roots = [ + URL(fileURLWithPath: "/Applications", isDirectory: true), + fileManager.homeDirectoryForCurrentUser.appendingPathComponent("Applications", isDirectory: true), + ] + let applicationRoots = applicationRoots ?? roots + let appBundleURLs = self.candidateAntigravityAppBundleURLs( + applicationRoots: applicationRoots, + fileManager: fileManager) + let relativePaths = [ + "Contents/Resources/app/extensions/antigravity/bin/language_server_macos_arm", + "Contents/Resources/app/extensions/antigravity/bin/language_server_macos_x64", + "Contents/Resources/app/extensions/antigravity/bin/language_server_macos", + "Contents/Resources/app/out/main.js", + "Contents/Resources/bin/language_server", + "Contents/Resources/bin/language_server_macos", + ] + return appBundleURLs.flatMap { bundleURL in + relativePaths.map { bundleURL.appendingPathComponent($0) } + } + } + + private static func candidateAntigravityAppBundleURLs( + applicationRoots: [URL], + fileManager: FileManager) -> [URL] + { + var urls: [URL] = [] + + for root in applicationRoots { + urls.append(root.appendingPathComponent("Antigravity.app", isDirectory: true)) + + let appURLs = (try? fileManager.contentsOfDirectory( + at: root, + includingPropertiesForKeys: [.isDirectoryKey], + options: [.skipsHiddenFiles])) ?? [] + for appURL in appURLs where appURL.pathExtension == "app" { + guard self.isAntigravityAppBundle(appURL) else { continue } + urls.append(appURL) + } + } + + var seen = Set() + return urls.filter { url in + let key = url.standardizedFileURL.path + guard !seen.contains(key) else { return false } + seen.insert(key) + return true + } + } + + private static func isAntigravityAppBundle(_ url: URL) -> Bool { + switch Bundle(url: url)?.bundleIdentifier { + case "com.google.antigravity", "com.google.antigravity-ide": + true + default: + false + } + } + + static func parseClient(fromInstalledArtifactData data: Data) -> AntigravityOAuthClient? { + if let content = String(data: data, encoding: .utf8), + let client = parseClient(fromInstalledArtifactText: content) + { + return client + } + + let clientIDs = Self.clientIDs(in: data) + let clientSecrets = Self.clientSecrets(in: data) + guard let client = Self.preferredBinaryClient( + clientIDs: clientIDs, + clientSecrets: clientSecrets) + else { + return nil + } + + return client + } + + static func parseClient(fromInstalledArtifactText content: String) -> AntigravityOAuthClient? { + let marker = "vs/platform/cloudCode/common/oauthClient.js" + let searchStart = content.range(of: marker)?.lowerBound ?? content.startIndex + let searchEnd = content.index(searchStart, offsetBy: 4000, limitedBy: content.endIndex) ?? content.endIndex + let haystack = String(content[searchStart.. [String] { + let suffix = Data(".apps.googleusercontent.com".utf8) + var searchRange = data.startIndex.. data.startIndex { + let previous = data.index(before: start) + guard Self.isOAuthClientIDPrefixByte(data[previous]) else { break } + start = previous + } + + let candidateData = Data(data[start.. [String] { + let prefix = Data("GOCSPX-".utf8) + let secretLength = 35 + var searchRange = data.startIndex.. AntigravityOAuthClient? + { + guard !clientIDs.isEmpty, + !clientSecrets.isEmpty + else { + return nil + } + + if clientSecrets.count == 1, clientIDs.count > 1 { + return AntigravityOAuthClient(clientID: clientIDs[clientIDs.count - 1], clientSecret: clientSecrets[0]) + } + + let clientSecret: String = if clientSecrets.count == clientIDs.count, clientSecrets.count > 1 { + // Antigravity 2's language_server binary stores the secret table before the client id table. + clientSecrets[clientSecrets.count - 1] + } else { + clientSecrets[0] + } + + return AntigravityOAuthClient(clientID: clientIDs[0], clientSecret: clientSecret) + } + + private static func isOAuthClientIDPrefixByte(_ byte: UInt8) -> Bool { + (byte >= 48 && byte <= 57) + || (byte >= 65 && byte <= 90) + || (byte >= 97 && byte <= 122) + || byte == 45 + || byte == 95 + } + + private static func isOAuthClientSecretByte(_ byte: UInt8) -> Bool { + self.isOAuthClientIDPrefixByte(byte) + } + + private static func firstMatch(pattern: String, in text: String) -> String? { + guard let regex = try? NSRegularExpression(pattern: pattern) else { return nil } + let range = NSRange(text.startIndex.. [String] { + var seen = Set() + return values.filter { value in + guard !seen.contains(value) else { return false } + seen.insert(value) + return true + } + } +} + +public struct AntigravityOAuthCredentialsStore: @unchecked Sendable { + public static let environmentCredentialsKey = "ANTIGRAVITY_OAUTH_CREDENTIALS_JSON" + private static let fileLock = NSLock() + + public let fileURL: URL + private let fileManager: FileManager + + public init(fileURL: URL = Self.defaultURL(), fileManager: FileManager = .default) { + self.fileURL = fileURL + self.fileManager = fileManager + } + + public func load() throws -> AntigravityOAuthCredentials? { + try Self.fileLock.withLock { + try self.loadUnlocked() + } + } + + private func loadUnlocked() throws -> AntigravityOAuthCredentials? { + guard self.fileManager.fileExists(atPath: self.fileURL.path) else { return nil } + let data = try Data(contentsOf: self.fileURL) + return try JSONDecoder().decode(AntigravityOAuthCredentials.self, from: data) + } + + public func save(_ credentials: AntigravityOAuthCredentials) throws { + try Self.fileLock.withLock { + let data = try JSONEncoder.antigravityCredentials.encode(credentials) + let directory = self.fileURL.deletingLastPathComponent() + if !self.fileManager.fileExists(atPath: directory.path) { + try self.fileManager.createDirectory(at: directory, withIntermediateDirectories: true) + } + try data.write(to: self.fileURL, options: [.atomic]) + try self.applySecurePermissionsIfNeeded() + } + } + + public func deleteIfPresent() throws { + try Self.fileLock.withLock { + try self.deleteIfPresentUnlocked() + } + } + + public func deleteIfPresent( + matching predicate: (AntigravityOAuthCredentials) -> Bool) throws + { + try Self.fileLock.withLock { + guard let credentials = try self.loadUnlocked(), predicate(credentials) else { return } + try self.deleteIfPresentUnlocked() + } + } + + private func deleteIfPresentUnlocked() throws { + guard self.fileManager.fileExists(atPath: self.fileURL.path) else { return } + try self.fileManager.removeItem(at: self.fileURL) + } + + public static func defaultDirectoryURL(home: URL = FileManager.default.homeDirectoryForCurrentUser) -> URL { + home + .appendingPathComponent(".codexbar", isDirectory: true) + .appendingPathComponent("antigravity", isDirectory: true) + } + + public static func defaultURL(home: URL = FileManager.default.homeDirectoryForCurrentUser) -> URL { + self.defaultDirectoryURL(home: home) + .appendingPathComponent("oauth_creds.json") + } + + public static func tokenAccountValue(for credentials: AntigravityOAuthCredentials) throws -> String { + let data = try JSONEncoder.antigravityCredentials.encode(credentials) + guard let value = String(data: data, encoding: .utf8) else { + throw CocoaError(.coderInvalidValue) + } + return value + } + + public static func credentials(fromTokenAccountValue value: String) -> AntigravityOAuthCredentials? { + let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines) + guard !trimmed.isEmpty, let data = trimmed.data(using: .utf8) else { return nil } + return try? JSONDecoder().decode(AntigravityOAuthCredentials.self, from: data) + } + + private func applySecurePermissionsIfNeeded() throws { + #if os(macOS) || os(Linux) + try self.fileManager.setAttributes([ + .posixPermissions: NSNumber(value: Int16(0o600)), + ], ofItemAtPath: self.fileURL.path) + #endif + } +} + +extension JSONEncoder { + fileprivate static let antigravityCredentials: JSONEncoder = { + let encoder = JSONEncoder() + encoder.outputFormatting = [.prettyPrinted, .sortedKeys] + return encoder + }() +} + +extension String { + fileprivate var nilIfEmpty: String? { + self.isEmpty ? nil : self + } + + fileprivate var trimmedNonEmptyEmail: String? { + let trimmed = self.trimmingCharacters(in: .whitespacesAndNewlines) + return trimmed.isEmpty ? nil : trimmed + } +} diff --git a/Sources/CodexBarCore/Providers/Antigravity/AntigravityProviderDescriptor.swift b/Sources/CodexBarCore/Providers/Antigravity/AntigravityProviderDescriptor.swift new file mode 100644 index 0000000..10b89cd --- /dev/null +++ b/Sources/CodexBarCore/Providers/Antigravity/AntigravityProviderDescriptor.swift @@ -0,0 +1,673 @@ +import Foundation + +public enum AntigravityProviderDescriptor { + public static let descriptor: ProviderDescriptor = Self.makeDescriptor() + + static func makeDescriptor() -> ProviderDescriptor { + ProviderDescriptor( + id: .antigravity, + metadata: ProviderMetadata( + id: .antigravity, + displayName: "Antigravity", + sessionLabel: "Gemini Models", + weeklyLabel: "Claude and GPT", + opusLabel: nil, + supportsOpus: false, + supportsCredits: false, + creditsHint: "", + toggleTitle: "Show Antigravity usage (experimental)", + cliName: "antigravity", + defaultEnabled: false, + isPrimaryProvider: false, + usesAccountFallback: false, + dashboardURL: nil, + statusPageURL: nil, + statusLinkURL: "https://www.google.com/appsstatus/dashboard/products/npdyhgECDJ6tB66MxXyo/history", + statusWorkspaceProductID: "npdyhgECDJ6tB66MxXyo"), + branding: ProviderBranding( + iconStyle: .antigravity, + iconResourceName: "ProviderIcon-antigravity", + color: ProviderColor(red: 96 / 255, green: 186 / 255, blue: 126 / 255)), + tokenCost: ProviderTokenCostConfig( + supportsTokenCost: false, + noDataMessage: { "Antigravity cost summary is not supported." }), + fetchPlan: ProviderFetchPlan( + sourceModes: [.auto, .cli, .oauth], + pipeline: ProviderFetchPipeline(resolveStrategies: self.resolveStrategies)), + cli: ProviderCLIConfig( + name: "antigravity", + versionDetector: nil)) + } + + private static func resolveStrategies(context: ProviderFetchContext) async -> [any ProviderFetchStrategy] { + let app = AntigravityStatusFetchStrategy(source: .app) + let cli = AntigravityCLIHTTPSFetchStrategy() + let ide = AntigravityStatusFetchStrategy(source: .ide) + let oauth = AntigravityOAuthFetchStrategy() + switch context.sourceMode { + case .cli: + return [app, cli, ide] + case .oauth: + return [oauth] + case .auto: + if context.selectedTokenAccountID != nil || + context.env[AntigravityOAuthCredentialsStore.environmentCredentialsKey] != nil || + self.hasSharedOAuthCredentials(context: context) + { + return [app, cli, ide, oauth] + } + return [app, cli, ide] + case .web, .api: + return [] + } + } + + private static func hasSharedOAuthCredentials(context: ProviderFetchContext) -> Bool { + let homeURL = context.env["HOME"] + .flatMap { $0.isEmpty ? nil : URL(fileURLWithPath: $0, isDirectory: true) } + ?? FileManager.default.homeDirectoryForCurrentUser + let fileURL = AntigravityOAuthCredentialsStore.defaultURL(home: homeURL) + return FileManager.default.fileExists(atPath: fileURL.path) + } +} + +struct AntigravityStatusFetchStrategy: ProviderFetchStrategy { + enum Source { + case app + case ide + + var id: String { + switch self { + case .app: "antigravity.app-local" + case .ide: "antigravity.ide-local" + } + } + + var processScope: AntigravityStatusProbe.ProcessScope { + switch self { + case .app: .appOnly + case .ide: .ideOnly + } + } + + var sourceLabel: String { + switch self { + case .app: "app" + case .ide: "ide" + } + } + } + + let source: Source + var id: String { + self.source.id + } + + let kind: ProviderFetchKind = .localProbe + + init(source: Source = .app) { + self.source = source + } + + func isAvailable(_: ProviderFetchContext) async -> Bool { + true + } + + func fetch(_ context: ProviderFetchContext) async throws -> ProviderFetchResult { + let probe = AntigravityStatusProbe(processScope: self.source.processScope) + let selectedAccountEmail: String? = if context.sourceMode == .auto, context.selectedTokenAccountID != nil { + AntigravitySelectedAccountGuard.selectedAccountEmail(context: context) + } else { + nil + } + let snap = try await probe.fetch(matchingAccountEmail: selectedAccountEmail) + let usage = try snap.toUsageSnapshot() + try AntigravitySelectedAccountGuard.validate(usage, context: context) + return self.makeResult( + usage: usage, + sourceLabel: self.source.sourceLabel) + } + + func shouldFallback(on _: Error, context: ProviderFetchContext) -> Bool { + context.sourceMode == .auto || context.sourceMode == .cli + } +} + +/// When the Antigravity 2.0 app is closed or unavailable, this strategy spawns +/// or reuses ``agy`` and talks to the localhost server embedded in that CLI +/// process. ``agy`` is an interactive REPL, not a query command, so CodexBar +/// never scrapes TUI output here; it only keeps the process alive long enough +/// for the server to answer quota endpoints. +struct AntigravityCLIHTTPSFetchStrategy: ProviderFetchStrategy { + static let sourceLabel = "cli" + let id: String = "antigravity.cli-https" + let kind: ProviderFetchKind = .cli + private static let log = CodexBarLog.logger(LogCategories.antigravity) + + struct SnapshotWaitDependencies { + let pollIntervalNanoseconds: UInt64 + let listeningPorts: @Sendable (Int, TimeInterval) async throws -> [Int] + let drainOutput: @Sendable () async -> Data + let fetchSnapshot: @Sendable ([Int]) async throws -> AntigravityStatusSnapshot + let now: @Sendable () -> Date + + init( + pollIntervalNanoseconds: UInt64, + listeningPorts: @escaping @Sendable (Int, TimeInterval) async throws -> [Int], + drainOutput: @escaping @Sendable () async -> Data, + fetchSnapshot: @escaping @Sendable ([Int]) async throws -> AntigravityStatusSnapshot, + now: @escaping @Sendable () -> Date = Date.init) + { + self.pollIntervalNanoseconds = pollIntervalNanoseconds + self.listeningPorts = listeningPorts + self.drainOutput = drainOutput + self.fetchSnapshot = fetchSnapshot + self.now = now + } + } + + /// Seams for discovering and reusing an already-running ``agy`` CLI language + /// server, so a fresh spawn (and its multi-second ``GetUserStatus`` warm-up) + /// can be skipped when a warm server is already present. + struct WarmAgyDependencies { + let processInfos: @Sendable (TimeInterval) async throws -> [AntigravityStatusProbe.ProcessInfoResult] + let listeningPorts: @Sendable (Int, TimeInterval) async throws -> [Int] + let fetchSnapshot: @Sendable ([Int], TimeInterval) async throws -> AntigravityStatusSnapshot + let processOwnerUserID: @Sendable (Int) -> UInt32? + let currentUserID: @Sendable () -> UInt32 + /// The pid of an ``agy`` that CodexBar itself spawned and manages through + /// ``AntigravityCLISession`` (if any). Such a process must NOT be reused + /// through the warm path: doing so bypasses `beginProbe`/`finishProbe`, so + /// the idle timer is never cancelled/extended and `stopIfIdle` could tear + /// the managed session down mid-poll. Externally owned `agy` (an IDE, a + /// long-lived `agy`, or another CodexBar host) has no such accounting. + let ownedPID: @Sendable () async -> Int? + let now: @Sendable () -> Date + + init( + processInfos: @escaping @Sendable (TimeInterval) async throws + -> [AntigravityStatusProbe.ProcessInfoResult], + listeningPorts: @escaping @Sendable (Int, TimeInterval) async throws -> [Int], + fetchSnapshot: @escaping @Sendable ([Int], TimeInterval) async throws -> AntigravityStatusSnapshot, + processOwnerUserID: @escaping @Sendable (Int) -> UInt32? = { _ in 0 }, + currentUserID: @escaping @Sendable () -> UInt32 = { 0 }, + ownedPID: @escaping @Sendable () async -> Int? = { nil }, + now: @escaping @Sendable () -> Date = Date.init) + { + self.processInfos = processInfos + self.listeningPorts = listeningPorts + self.fetchSnapshot = fetchSnapshot + self.processOwnerUserID = processOwnerUserID + self.currentUserID = currentUserID + self.ownedPID = ownedPID + self.now = now + } + } + + /// Discover an already-running, authenticated ``agy`` CLI language server and + /// reuse its listening ports instead of spawning a fresh process. + /// + /// One-shot CLI invocations otherwise spawn a brand-new ``agy`` on every + /// call; a fresh server binds its port quickly but ``GetUserStatus`` returns + /// transient initialization failures for a few seconds, so the readiness + /// deadline is occasionally missed. When a warm CLI server is already up, we + /// can talk to it immediately — it needs no CSRF token (``cliHTTPS``). + /// + /// Returns the snapshot from the first warm server that answers with + /// parseable usage for the requested account, or `nil` when none is found or + /// none answers — in which case the caller falls back to the existing spawn + /// path unchanged. + static func tryWarmAgyFetch( + timeout: TimeInterval, + expectedBinaryPath: String? = nil, + expectedAccountEmail: String? = nil, + dependencies: WarmAgyDependencies) async throws -> AntigravityStatusSnapshot? + { + try Task.checkCancellation() + let deadline = dependencies.now().addingTimeInterval(timeout) + guard let discoveryTimeout = Self.remainingWarmProbeTime(deadline: deadline, now: dependencies.now) else { + return nil + } + let processInfos: [AntigravityStatusProbe.ProcessInfoResult] + do { + processInfos = try await dependencies.processInfos(discoveryTimeout) + } catch let error as CancellationError { + throw error + } catch { + return nil + } + try Task.checkCancellation() + let ownedPID = await dependencies.ownedPID() + try Task.checkCancellation() + let currentUserID = dependencies.currentUserID() + // Only the CLI's language server needs no CSRF token; the IDE/app servers + // require one and must not be reused through this token-less fast path. + // Also exclude any `agy` CodexBar itself spawned and manages: reusing it + // here would bypass session lifecycle accounting (see `ownedPID`). + let cliProcesses = processInfos.filter { info in + info.pid != ownedPID && + dependencies.processOwnerUserID(info.pid) == currentUserID && + AntigravityStatusProbe.antigravityProcessKind(info.commandLine) == .cli + } + guard !cliProcesses.isEmpty else { return nil } + + for info in cliProcesses { + if let expectedBinaryPath { + guard Self.commandLine(info.commandLine, matchesBinaryPath: expectedBinaryPath) + else { + continue + } + } + guard let portTimeout = Self.remainingWarmProbeTime(deadline: deadline, now: dependencies.now) else { + return nil + } + let ports: [Int] + do { + ports = try await dependencies.listeningPorts(info.pid, portTimeout) + } catch let error as CancellationError { + throw error + } catch { + continue + } + try Task.checkCancellation() + guard !ports.isEmpty else { continue } + guard let fetchTimeout = Self.remainingWarmProbeTime(deadline: deadline, now: dependencies.now) else { + return nil + } + let snapshot: AntigravityStatusSnapshot + do { + snapshot = try await dependencies.fetchSnapshot(ports, fetchTimeout) + } catch let error as CancellationError { + throw error + } catch { + continue + } + try Task.checkCancellation() + guard (try? snapshot.toUsageSnapshot()) != nil, + AntigravitySelectedAccountGuard.matches( + snapshotAccountEmail: snapshot.accountEmail, + expectedAccountEmail: expectedAccountEmail) + else { + continue + } + Self.log.debug("Antigravity CLI HTTPS reusing warm agy", metadata: [ + "pid": "\(info.pid)", + "ports": ports.map(String.init).joined(separator: ","), + ]) + return snapshot + } + try Task.checkCancellation() + return nil + } + + private static func remainingWarmProbeTime( + deadline: Date, + now: @Sendable () -> Date) -> TimeInterval? + { + let remaining = deadline.timeIntervalSince(now()) + return remaining > 0 ? remaining : nil + } + + private static func commandLine(_ commandLine: String, matchesBinaryPath binaryPath: String) -> Bool { + let candidates = [ + URL(fileURLWithPath: binaryPath).standardizedFileURL.path, + URL(fileURLWithPath: binaryPath).resolvingSymlinksInPath().standardizedFileURL.path, + ] + return candidates.contains { candidate in + commandLine == candidate || commandLine.hasPrefix("\(candidate) ") + } + } + + /// Production wiring for ``tryWarmAgyFetch``: list processes via `ps`, find + /// listening ports via `lsof`, and probe the token-less CLI HTTPS endpoint. + static func liveWarmAgyDependencies() -> WarmAgyDependencies { + WarmAgyDependencies( + processInfos: { timeout in + // A missing-CSRF/notRunning throw means no reusable server; the + // caller maps any throw to "no warm agy" and spawns instead. + try await AntigravityStatusProbe.detectProcessInfos( + timeout: timeout, + scope: .ideAndCLI) + }, + listeningPorts: { pid, timeout in + try await AntigravityStatusProbe.listeningPorts(pid: pid, timeout: timeout) + }, + fetchSnapshot: { ports, timeout in + let deadline = Date().addingTimeInterval(timeout) + return try await AntigravityStatusProbe(timeout: timeout) + .fetchFromPorts(ports, deadline: deadline) + }, + processOwnerUserID: { pid in + AntigravityProcessIdentityProvider().ownerUserID(for: pid_t(pid)) + }, + currentUserID: { + AntigravityProcessIdentityProvider.currentUserID + }, + ownedPID: { + // The pid of the `agy` CodexBar manages through the shared + // session, so the warm scan never reuses our own process. + await AntigravityCLISession.shared.pid.map(Int.init) + }) + } + + func isAvailable(_ context: ProviderFetchContext) async -> Bool { + BinaryLocator.resolveAntigravityBinary(env: context.env) != nil + } + + func fetch(_ context: ProviderFetchContext) async throws -> ProviderFetchResult { + guard let binary = BinaryLocator.resolveAntigravityBinary(env: context.env) else { + throw AntigravityStatusProbeError.notRunning + } + let expectedAccountEmail: String? = if context.sourceMode == .auto, + context.selectedTokenAccountID != nil + { + AntigravitySelectedAccountGuard.selectedAccountEmail(context: context) + } else { + nil + } + let result = try await self.fetchUsingWarmSession( + binary: binary, + idleWindow: context.persistentCLISessionIdleWindow, + resetAfterFetch: Self.shouldResetSessionAfterFetch(context), + expectedAccountEmail: expectedAccountEmail) + try AntigravitySelectedAccountGuard.validate(result.usage, context: context) + return result + } + + private func fetchUsingWarmSession( + binary: String, + idleWindow: TimeInterval?, + resetAfterFetch: Bool, + expectedAccountEmail: String?) async throws -> ProviderFetchResult + { + try await self.fetchUsingWarmSession( + binary: binary, + idleWindow: idleWindow, + resetAfterFetch: resetAfterFetch, + expectedAccountEmail: expectedAccountEmail, + warmDependencies: Self.liveWarmAgyDependencies(), + spawnFetch: { binary, idleWindow, resetAfterFetch in + try await self.fetchBySpawning( + binary: binary, + idleWindow: idleWindow, + resetAfterFetch: resetAfterFetch) + }) + } + + /// Testable core of the CLI fetch: try the warm-reuse fast path first, then + /// fall back to spawning. The `spawnFetch` seam lets tests assert the spawn + /// path is skipped when a warm server is reused. + func fetchUsingWarmSession( + binary: String, + idleWindow: TimeInterval?, + resetAfterFetch: Bool, + expectedAccountEmail: String? = nil, + warmDependencies: WarmAgyDependencies, + spawnFetch: @Sendable (String, TimeInterval?, Bool) async throws -> ProviderFetchResult) + async throws -> ProviderFetchResult + { + // Fast path: reuse an already-running, authenticated `agy` CLI server if + // one is present, avoiding a fresh spawn and its multi-second warm-up. + // When none is found (or none answers), fall through to the spawn path. + // + // The warm path deliberately does NOT touch `AntigravityCLISession` + // (`beginProbe`/`finishProbe`): a discovered `agy` is owned by another + // process (an IDE, a long-lived `agy`, or another CodexBar host), so + // CodexBar must not manage its lifecycle, idle timeout, or + // `resetAfterFetch` teardown. Those apply only to processes CodexBar + // itself spawns on the fallback path below. + // Long-lived hosts already keep a managed session warm. Restrict external + // process reuse to one-shot CLI calls so app/server lifecycle accounting + // stays entirely inside AntigravityCLISession. + if resetAfterFetch, let warmSnapshot = try await Self.tryWarmAgyFetch( + timeout: 2.0, + expectedBinaryPath: binary, + expectedAccountEmail: expectedAccountEmail, + dependencies: warmDependencies) + { + // `tryWarmAgyFetch` only returns a snapshot whose `toUsageSnapshot()` + // already succeeded, so this conversion must not silently fail. + let warmUsage = try warmSnapshot.toUsageSnapshot() + return self.makeResult( + usage: warmUsage, + sourceLabel: Self.sourceLabel) + } + + try Task.checkCancellation() + return try await spawnFetch(binary, idleWindow, resetAfterFetch) + } + + /// Spawn (or reuse CodexBar's own warm) `agy` session and wait for the CLI + /// HTTPS endpoint to report ready. This is the original behavior, unchanged. + private func fetchBySpawning( + binary: String, + idleWindow: TimeInterval?, + resetAfterFetch: Bool) async throws -> ProviderFetchResult + { + let session = AntigravityCLISession.shared + let pid = try await session.beginProbe(binary: binary, idleWindow: idleWindow) + let deadline = Date().addingTimeInterval(5.0) + let snap: AntigravityStatusSnapshot + let usage: UsageSnapshot + do { + snap = try await Self.waitForSnapshot( + pid: pid, + deadline: deadline, + dependencies: SnapshotWaitDependencies( + pollIntervalNanoseconds: 200_000_000, + listeningPorts: { pid, timeout in + try await AntigravityStatusProbe.listeningPorts(pid: pid, timeout: timeout) + }, + drainOutput: { + await session.drainOutput() + }, + fetchSnapshot: { ports in + let timeout = min(2.0, max(0.2, deadline.timeIntervalSinceNow)) + return try await AntigravityStatusProbe(timeout: timeout) + .fetchFromPorts(ports, deadline: deadline) + })) + usage = try snap.toUsageSnapshot() + await session.finishProbe(success: true, resetAfterFetch: resetAfterFetch) + } catch { + let authenticationRequired = (error as? AntigravityStatusProbeError) == .authenticationRequired + await session.finishProbe( + success: false, + resetAfterFetch: resetAfterFetch || authenticationRequired, + forceTerminate: authenticationRequired) + throw error + } + + return self.makeResult( + usage: usage, + sourceLabel: Self.sourceLabel) + } + + static func shouldResetSessionAfterFetch(_ context: ProviderFetchContext) -> Bool { + // Long-lived hosts (the app, `codexbar serve`) keep the warm `agy` + // session between fetches; only one-shot CLI invocations reset it. + context.runtime == .cli && !context.persistsCLISessions + } + + /// Waits for real API readiness, not just socket readiness. Fresh ``agy`` + /// processes bind ports quickly, but ``GetUserStatus`` can return transient + /// initialization failures for a few seconds after the port appears. + static func waitForSnapshot( + pid: pid_t, + deadline: Date, + dependencies: SnapshotWaitDependencies) async throws -> AntigravityStatusSnapshot + { + var lastFetchError: Error? + while dependencies.now() < deadline { + try await Self.checkAuthenticationPrompt(dependencies) + let remaining = deadline.timeIntervalSince(dependencies.now()) + let portProbeTimeout = min(2.0, max(0.2, remaining)) + let ports: [Int] + do { + ports = try await dependencies.listeningPorts(Int(pid), portProbeTimeout) + } catch { + guard Self.isNoListeningPortsError(error) else { + try await Self.checkAuthenticationPrompt(dependencies) + throw error + } + ports = [] + } + if !ports.isEmpty { + var readySnapshot: AntigravityStatusSnapshot? + do { + let snapshot = try await dependencies.fetchSnapshot(ports) + _ = try snapshot.toUsageSnapshot() + readySnapshot = snapshot + } catch { + try await Self.checkAuthenticationPrompt(dependencies) + lastFetchError = error + Self.log.debug("Antigravity CLI HTTPS endpoint not ready", metadata: [ + "pid": "\(pid)", + "ports": ports.map(String.init).joined(separator: ","), + "error": error.localizedDescription, + ]) + } + if let readySnapshot { + try await Self.checkAuthenticationPrompt(dependencies) + return readySnapshot + } + } + + let remainingNanoseconds = UInt64( + max(0, deadline.timeIntervalSince(dependencies.now())) * 1_000_000_000) + guard remainingNanoseconds > 0 else { break } + let sleepNanoseconds = min(dependencies.pollIntervalNanoseconds, remainingNanoseconds) + if sleepNanoseconds > 0 { + try await Task.sleep(nanoseconds: sleepNanoseconds) + } + } + + try await Self.checkAuthenticationPrompt(dependencies) + if let lastFetchError { + throw lastFetchError + } + Self.log.warning("Antigravity CLI HTTPS: no ports found for pid \(pid)") + throw AntigravityStatusProbeError.portDetectionFailed( + "Antigravity CLI started but no listening ports found") + } + + static func containsAuthenticationPrompt(_ output: Data) -> Bool { + AntigravityCLIAuthenticationPrompt.contains(output) + } + + private static func checkAuthenticationPrompt(_ dependencies: SnapshotWaitDependencies) async throws { + let terminalOutput = await dependencies.drainOutput() + if Self.containsAuthenticationPrompt(terminalOutput) { + throw AntigravityStatusProbeError.authenticationRequired + } + } + + private static func isNoListeningPortsError(_ error: Error) -> Bool { + if case let AntigravityStatusProbeError.portDetectionFailed(message) = error { + return message == "no listening ports found" + } + if case let SubprocessRunnerError.nonZeroExit(code, stderr) = error { + return code == 1 && stderr.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty + } + return false + } + + func shouldFallback(on _: Error, context: ProviderFetchContext) -> Bool { + context.sourceMode == .auto || context.sourceMode == .cli + } +} + +struct AntigravityOAuthFetchStrategy: ProviderFetchStrategy { + let id: String = "antigravity.oauth" + let kind: ProviderFetchKind = .oauth + + func isAvailable(_: ProviderFetchContext) async -> Bool { + true + } + + static func usageSnapshot( + from snapshot: AntigravityStatusSnapshot, + updatedAt: Date = Date()) throws -> UsageSnapshot + { + if snapshot.modelQuotas.isEmpty { + return UsageSnapshot( + primary: nil, + secondary: nil, + tertiary: nil, + updatedAt: updatedAt, + identity: ProviderIdentitySnapshot( + providerID: .antigravity, + accountEmail: snapshot.accountEmail, + accountOrganization: nil, + loginMethod: snapshot.accountPlan)) + } + return try snapshot.toUsageSnapshot() + } + + func fetch(_ context: ProviderFetchContext) async throws -> ProviderFetchResult { + let fetcher = AntigravityRemoteUsageFetcher( + environment: context.env, + credentialsUpdateHandler: { credentials in + guard let accountID = context.selectedTokenAccountID, + let updater = context.tokenAccountTokenUpdater + else { + return + } + let token = try AntigravityOAuthCredentialsStore.tokenAccountValue(for: credentials) + await updater(.antigravity, accountID, token) + }) + let snapshot = try await fetcher.fetch() + let usage = try Self.usageSnapshot(from: snapshot) + return self.makeResult( + usage: usage, + sourceLabel: "oauth") + } + + func shouldFallback(on _: Error, context _: ProviderFetchContext) -> Bool { + false + } +} + +/// Guards ambient Antigravity snapshots against the explicitly selected account. +/// +/// The local desktop probe and the ``agy`` CLI HTTPS server report whichever +/// Antigravity account is signed into the local session. When the user has +/// selected a specific saved Google account, an ambient probe can return a +/// *different* account's quota. Only the OAuth strategy is account-scoped (it +/// fetches with the selected account's injected credentials), so in ``auto`` +/// mode we reject a snapshot whose identity does not match the selected account +/// and let the pipeline fall through to OAuth. Explicit ``cli``/``oauth`` source +/// modes stay authoritative and are never second-guessed here. +enum AntigravitySelectedAccountGuard { + static func matches(snapshotAccountEmail: String?, expectedAccountEmail: String?) -> Bool { + guard let expected = self.normalizedEmail(expectedAccountEmail) else { return true } + guard let found = self.normalizedEmail(snapshotAccountEmail) else { return false } + return found.caseInsensitiveCompare(expected) == .orderedSame + } + + static func validate(_ usage: UsageSnapshot, context: ProviderFetchContext) throws { + guard context.sourceMode == .auto, context.selectedTokenAccountID != nil else { return } + let expected = self.selectedAccountEmail(context: context) + let found = self.normalizedEmail(usage.identity?.accountEmail) + guard let expected, let found, found.caseInsensitiveCompare(expected) == .orderedSame else { + throw AntigravityStatusProbeError.accountMismatch(expected: expected, found: found) + } + } + + /// Email of the selected token account, read from the same injected + /// credentials the OAuth strategy would use (`ANTIGRAVITY_OAUTH_CREDENTIALS_JSON`). + static func selectedAccountEmail(context: ProviderFetchContext) -> String? { + guard let value = context.env[AntigravityOAuthCredentialsStore.environmentCredentialsKey], + let credentials = AntigravityOAuthCredentialsStore.credentials(fromTokenAccountValue: value) + else { + return nil + } + return credentials.resolvedAccountEmail + } + + private static func normalizedEmail(_ email: String?) -> String? { + guard let trimmed = email?.trimmingCharacters(in: .whitespacesAndNewlines), !trimmed.isEmpty else { + return nil + } + return trimmed + } +} diff --git a/Sources/CodexBarCore/Providers/Antigravity/AntigravityQuotaSummaryParser.swift b/Sources/CodexBarCore/Providers/Antigravity/AntigravityQuotaSummaryParser.swift new file mode 100644 index 0000000..9928f76 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Antigravity/AntigravityQuotaSummaryParser.swift @@ -0,0 +1,173 @@ +import Foundation + +// swiftformat:disable:next redundantSendable +struct AntigravityQuotaSummary: Sendable, Equatable { + let description: String? + let groups: [AntigravityQuotaSummaryGroup] +} + +// swiftformat:disable:next redundantSendable +struct AntigravityQuotaSummaryGroup: Sendable, Equatable { + let displayName: String + let description: String? + let buckets: [AntigravityQuotaSummaryBucket] +} + +// swiftformat:disable:next redundantSendable +struct AntigravityQuotaSummaryBucket: Sendable, Equatable { + let bucketId: String + let displayName: String + let remainingFraction: Double? + let resetTime: Date? + let resetDescription: String? + let disabled: Bool + + init( + bucketId: String, + displayName: String, + remainingFraction: Double?, + resetTime: Date? = nil, + resetDescription: String?, + disabled: Bool) + { + self.bucketId = bucketId + self.displayName = displayName + self.remainingFraction = remainingFraction + self.resetTime = resetTime + self.resetDescription = resetDescription + self.disabled = disabled + } +} + +extension AntigravityStatusProbe { + static func parseQuotaSummaryResponse(_ data: Data) throws -> AntigravityStatusSnapshot { + let decoder = JSONDecoder() + let response = try decoder.decode(QuotaSummaryResponse.self, from: data) + if let invalid = Self.invalidCode(response.code) { + throw AntigravityStatusProbeError.apiError(invalid) + } + let payload = response.response ?? response.summary ?? response.rootPayload + guard let payload else { + throw AntigravityStatusProbeError.parseFailed("Missing quota summary") + } + let groups = payload.groups.compactMap(self.quotaSummaryGroup(from:)) + guard !groups.isEmpty else { + throw AntigravityStatusProbeError.parseFailed("Missing quota groups") + } + return AntigravityStatusSnapshot( + quotaSummary: AntigravityQuotaSummary( + description: payload.description, + groups: groups), + accountEmail: nil, + accountPlan: nil, + source: .local) + } + + private static func quotaSummaryGroup(from payload: QuotaSummaryGroupPayload) -> AntigravityQuotaSummaryGroup? { + let displayName = payload.displayName?.trimmingCharacters(in: .whitespacesAndNewlines) + let buckets = (payload.buckets ?? []).compactMap(self.quotaSummaryBucket(from:)) + guard !buckets.isEmpty else { return nil } + return AntigravityQuotaSummaryGroup( + displayName: self.nonEmpty(displayName) ?? "Quota", + description: payload.description, + buckets: buckets) + } + + private static func quotaSummaryBucket(from payload: QuotaSummaryBucketPayload) -> AntigravityQuotaSummaryBucket? { + let bucketId = payload.bucketId?.trimmingCharacters(in: .whitespacesAndNewlines) + let displayName = payload.displayName?.trimmingCharacters(in: .whitespacesAndNewlines) + guard let resolvedBucketId = bucketId, !resolvedBucketId.isEmpty else { return nil } + let resetTime = payload.resetTime.flatMap { Self.parseDate($0) } + return AntigravityQuotaSummaryBucket( + bucketId: resolvedBucketId, + displayName: self.nonEmpty(displayName) ?? resolvedBucketId, + remainingFraction: payload.resolvedRemainingFraction, + resetTime: resetTime, + resetDescription: payload.description, + disabled: payload.disabled ?? false) + } + + private static func nonEmpty(_ value: String?) -> String? { + guard let value, !value.isEmpty else { return nil } + return value + } +} + +private struct QuotaSummaryResponse: Decodable { + let code: CodeValue? + let message: String? + let response: QuotaSummaryPayload? + let summary: QuotaSummaryPayload? + let description: String? + let groups: [QuotaSummaryGroupPayload]? + + var rootPayload: QuotaSummaryPayload? { + guard let groups else { return nil } + return QuotaSummaryPayload(description: self.description, groups: groups) + } +} + +private struct QuotaSummaryPayload: Decodable { + let description: String? + let groups: [QuotaSummaryGroupPayload] + + init(description: String?, groups: [QuotaSummaryGroupPayload]) { + self.description = description + self.groups = groups + } + + private enum CodingKeys: String, CodingKey { + case description + case groups + } + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.description = try container.decodeIfPresent(String.self, forKey: .description) + self.groups = try container.decodeIfPresent([QuotaSummaryGroupPayload].self, forKey: .groups) ?? [] + } +} + +private struct QuotaSummaryGroupPayload: Decodable { + let displayName: String? + let description: String? + let buckets: [QuotaSummaryBucketPayload]? +} + +private struct QuotaSummaryBucketPayload: Decodable { + let bucketId: String? + let displayName: String? + let description: String? + let disabled: Bool? + let remainingFraction: Double? + let remaining: QuotaSummaryRemainingPayload? + let resetTime: String? + + var resolvedRemainingFraction: Double? { + self.remainingFraction ?? self.remaining?.remainingFraction + } +} + +private struct QuotaSummaryRemainingPayload: Decodable { + let remainingFraction: Double? + + private enum CodingKeys: String, CodingKey { + case remainingFraction + case oneofCase = "case" + case value + } + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + if let remainingFraction = try container.decodeIfPresent(Double.self, forKey: .remainingFraction) { + self.remainingFraction = remainingFraction + return + } + let oneofCase = try container.decodeIfPresent(String.self, forKey: .oneofCase) + if oneofCase == "remainingFraction" { + self.remainingFraction = try container.decodeIfPresent(Double.self, forKey: .value) + } else { + self.remainingFraction = nil + } + } +} diff --git a/Sources/CodexBarCore/Providers/Antigravity/AntigravityRemoteUsageFetcher.swift b/Sources/CodexBarCore/Providers/Antigravity/AntigravityRemoteUsageFetcher.swift new file mode 100644 index 0000000..536e1e0 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Antigravity/AntigravityRemoteUsageFetcher.swift @@ -0,0 +1,777 @@ +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +public enum AntigravityRemoteFetchError: LocalizedError, Sendable, Equatable { + case notLoggedIn + case permissionDenied(String) + case apiError(String) + case parseFailed(String) + + public var errorDescription: String? { + switch self { + case .notLoggedIn: + "Antigravity Google auth not found. Use Antigravity login to authenticate." + case let .permissionDenied(message): + "Antigravity remote API permission denied: \(message)" + case let .apiError(message): + "Antigravity remote API error: \(message)" + case let .parseFailed(message): + "Could not parse Antigravity remote usage: \(message)" + } + } +} + +public struct AntigravityRemoteUsageFetcher: Sendable { + public var timeout: TimeInterval = 10.0 + public var homeDirectory: String + public var environment: [String: String] + public var dataLoader: @Sendable (URLRequest) async throws -> (Data, URLResponse) + public var oauthClientResolver: @Sendable () -> AntigravityOAuthClient? + public var credentialsUpdateHandler: @Sendable (AntigravityOAuthCredentials) async throws -> Void + + private static let log = CodexBarLog.logger(LogCategories.antigravity) + private static let userAgent = "antigravity" + private static let baseURL = "https://cloudcode-pa.googleapis.com" + private static let loadCodeAssistEndpoint = "\(baseURL)/v1internal:loadCodeAssist" + private static let onboardUserEndpoint = "\(baseURL)/v1internal:onboardUser" + private static let fetchAvailableModelsEndpoint = "\(baseURL)/v1internal:fetchAvailableModels" + private static let retrieveUserQuotaEndpoint = "\(baseURL)/v1internal:retrieveUserQuota" + private static let refreshSafetyWindow: TimeInterval = 60 + + private struct FetchContext { + let timeout: TimeInterval + let store: AntigravityOAuthCredentialsStore? + let dataLoader: @Sendable (URLRequest) async throws -> (Data, URLResponse) + let oauthClientResolver: @Sendable () -> AntigravityOAuthClient? + let credentialsUpdateHandler: @Sendable (AntigravityOAuthCredentials) async throws -> Void + + func persistCredentials(_ credentials: AntigravityOAuthCredentials) async throws { + if let store { + try store.save(credentials) + } else { + try await self.credentialsUpdateHandler(credentials) + } + } + } + + public init( + timeout: TimeInterval = 10.0, + homeDirectory: String = NSHomeDirectory(), + environment: [String: String] = ProcessInfo.processInfo.environment, + dataLoader: @escaping @Sendable (URLRequest) async throws -> (Data, URLResponse) = { request in + try await ProviderHTTPClient.shared.data(for: request) + }, + oauthClientResolver: @escaping @Sendable () -> AntigravityOAuthClient? = { + AntigravityOAuthConfig.resolvedClient() + }, + credentialsUpdateHandler: @escaping @Sendable (AntigravityOAuthCredentials) async throws -> Void = { _ in }) + { + self.timeout = timeout + self.homeDirectory = homeDirectory + self.environment = environment + self.dataLoader = dataLoader + self.oauthClientResolver = oauthClientResolver + self.credentialsUpdateHandler = credentialsUpdateHandler + } + + public func fetch() async throws -> AntigravityStatusSnapshot { + let source = try Self.resolveCredentialSource(homeDirectory: self.homeDirectory, environment: self.environment) + guard let credentials = source.credentials else { + throw AntigravityRemoteFetchError.notLoggedIn + } + return try await self.fetchSnapshot( + using: credentials, + store: source.store) + } + + private func fetchSnapshot( + using initialCredentials: AntigravityOAuthCredentials, + store: AntigravityOAuthCredentialsStore?) async throws + -> AntigravityStatusSnapshot + { + guard let storedAccessToken = initialCredentials.accessToken?.trimmedNonEmpty else { + throw AntigravityRemoteFetchError.notLoggedIn + } + + var credentials = initialCredentials + var accessToken = storedAccessToken + let context = FetchContext( + timeout: self.timeout, + store: store, + dataLoader: self.dataLoader, + oauthClientResolver: self.oauthClientResolver, + credentialsUpdateHandler: self.credentialsUpdateHandler) + if Self.shouldRefresh(expiryDate: credentials.expiryDate, now: Date()) { + guard let refreshToken = credentials.refreshToken?.trimmedNonEmpty else { + throw AntigravityRemoteFetchError.notLoggedIn + } + let refreshed = try await Self.refreshAccessToken( + credentials: credentials, + refreshToken: refreshToken, + context: context) + accessToken = refreshed.accessToken + credentials = refreshed.credentials + if let store { + credentials = try store.load() ?? credentials + } + credentials.accessToken = credentials.accessToken?.trimmedNonEmpty ?? accessToken + } + + let claims = Self.extractClaims(from: credentials) + let codeAssist = try await Self.loadCodeAssist( + accessToken: accessToken, + timeout: self.timeout, + dataLoader: self.dataLoader) + let projectId = try await Self.resolveProjectID( + accessToken: accessToken, + storedProjectID: credentials.projectID?.trimmedNonEmpty, + initialResponse: codeAssist, + context: context) + if let projectId, credentials.projectID?.trimmedNonEmpty != projectId { + credentials.projectID = projectId + do { + try await context.persistCredentials(credentials) + } catch { + Self.log.warning("Could not persist Antigravity project ID: \(error.localizedDescription)") + } + } + let models = try await Self.fetchModelQuotas( + accessToken: accessToken, + projectId: projectId, + timeout: self.timeout, + dataLoader: self.dataLoader) + + return AntigravityStatusSnapshot( + modelQuotas: models, + accountEmail: claims.email, + accountPlan: Self.resolvePlan(response: codeAssist, claims: claims), + source: .remote) + } + + private static func shouldRefresh(expiryDate: Date?, now: Date) -> Bool { + guard let expiryDate else { return false } + return expiryDate.timeIntervalSince(now) <= Self.refreshSafetyWindow + } + + private static func loadCodeAssist( + accessToken: String, + timeout: TimeInterval, + dataLoader: @escaping @Sendable (URLRequest) async throws -> (Data, URLResponse)) async throws + -> CodeAssistResponse + { + let body = [ + "metadata": [ + "ideType": "ANTIGRAVITY", + "platform": "PLATFORM_UNSPECIFIED", + "pluginType": "GEMINI", + ], + ] + return try await Self.sendRequest( + endpoint: Self.loadCodeAssistEndpoint, + accessToken: accessToken, + body: body, + timeout: timeout, + dataLoader: dataLoader) + } + + private static func fetchAvailableModels( + accessToken: String, + projectId: String?, + timeout: TimeInterval, + dataLoader: @escaping @Sendable (URLRequest) async throws -> (Data, URLResponse)) async throws + -> FetchAvailableModelsResponse + { + let body: [String: Any] = if let projectId = projectId?.trimmedNonEmpty { + ["project": projectId] + } else { + [:] + } + return try await Self.sendRequest( + endpoint: Self.fetchAvailableModelsEndpoint, + accessToken: accessToken, + body: body, + timeout: timeout, + dataLoader: dataLoader) + } + + private static func fetchModelQuotas( + accessToken: String, + projectId: String?, + timeout: TimeInterval, + dataLoader: @escaping @Sendable (URLRequest) async throws -> (Data, URLResponse)) async throws + -> [AntigravityModelQuota] + { + do { + let response = try await Self.fetchAvailableModels( + accessToken: accessToken, + projectId: projectId, + timeout: timeout, + dataLoader: dataLoader) + let modelQuotas = try Self.parseModelQuotas(response) + if Self.shouldVerifyFullRemoteQuotas(modelQuotas) { + let quotaBuckets = try await Self.fetchQuotaBucketsIfPermitted( + accessToken: accessToken, + projectId: projectId, + timeout: timeout, + dataLoader: dataLoader) + guard let quotaBuckets, Self.hasQuotaFractionData(quotaBuckets) else { + return [] + } + return Self.mergeVerifiedQuotas(modelQuotas: modelQuotas, verifiedQuotas: quotaBuckets) + } + return modelQuotas + } catch let error as AntigravityRemoteFetchError { + guard case .permissionDenied = error else { + throw error + } + Self.log.info("Falling back to retrieveUserQuota for Antigravity remote usage") + return try await Self.fetchQuotaBucketsIfPermitted( + accessToken: accessToken, + projectId: projectId, + timeout: timeout, + dataLoader: dataLoader) ?? [] + } + } + + private static func mergeVerifiedQuotas( + modelQuotas: [AntigravityModelQuota], + verifiedQuotas: [AntigravityModelQuota]) -> [AntigravityModelQuota] + { + var verifiedByModelID = Dictionary( + uniqueKeysWithValues: verifiedQuotas.map { (Self.quotaKey($0), $0) }) + var merged = modelQuotas.compactMap { modelQuota -> AntigravityModelQuota? in + guard let verifiedQuota = verifiedByModelID.removeValue(forKey: Self.quotaKey(modelQuota)) else { + return nil + } + let resetTime = verifiedQuota.resetTime ?? modelQuota.resetTime + return AntigravityModelQuota( + label: modelQuota.label, + modelId: modelQuota.modelId, + remainingFraction: verifiedQuota.remainingFraction ?? modelQuota.remainingFraction, + resetTime: resetTime, + resetDescription: resetTime.map { UsageFormatter.resetDescription(from: $0) }) + } + let unmatchedVerifiedQuotas = verifiedByModelID.values + .filter { $0.remainingFraction != nil } + .sorted { lhs, rhs in + lhs.modelId.localizedCaseInsensitiveCompare(rhs.modelId) == .orderedAscending + } + merged.append(contentsOf: unmatchedVerifiedQuotas) + return merged + } + + private static func quotaKey(_ quota: AntigravityModelQuota) -> String { + quota.modelId.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() + } + + private static func shouldVerifyFullRemoteQuotas(_ quotas: [AntigravityModelQuota]) -> Bool { + guard !quotas.isEmpty else { return false } + return quotas.allSatisfy { quota in + guard let remaining = quota.remainingFraction else { return false } + return remaining >= 0.999 + } + } + + private static func hasQuotaFractionData(_ quotas: [AntigravityModelQuota]) -> Bool { + quotas.contains { quota in + quota.remainingFraction != nil + } + } + + private static func fetchQuotaBucketsIfPermitted( + accessToken: String, + projectId: String?, + timeout: TimeInterval, + dataLoader: @escaping @Sendable (URLRequest) async throws -> (Data, URLResponse)) async throws + -> [AntigravityModelQuota]? + { + do { + let response = try await Self.retrieveUserQuota( + accessToken: accessToken, + projectId: projectId, + timeout: timeout, + dataLoader: dataLoader) + return try Self.parseQuotaBuckets(response) + } catch let quotaError as AntigravityRemoteFetchError { + guard case .permissionDenied = quotaError else { + throw quotaError + } + Self.log.info("Antigravity remote quota endpoint is not permitted for this account") + return nil + } + } + + private static func retrieveUserQuota( + accessToken: String, + projectId: String?, + timeout: TimeInterval, + dataLoader: @escaping @Sendable (URLRequest) async throws -> (Data, URLResponse)) async throws + -> RetrieveUserQuotaResponse + { + let body: [String: Any] = if let projectId = projectId?.trimmedNonEmpty { + ["project": projectId] + } else { + [:] + } + return try await Self.sendRequest( + endpoint: Self.retrieveUserQuotaEndpoint, + accessToken: accessToken, + body: body, + timeout: timeout, + dataLoader: dataLoader) + } + + private static func resolveProjectID( + accessToken: String, + storedProjectID: String?, + initialResponse: CodeAssistResponse, + context: FetchContext) async throws + -> String? + { + if let storedProjectID { + return storedProjectID + } + + if let projectID = initialResponse.projectID { + return projectID + } + + guard let tierID = Self.pickOnboardTier(from: initialResponse) else { + return nil + } + + let onboardBody: [String: Any] = [ + "tierId": tierID, + "metadata": [ + "ideType": "ANTIGRAVITY", + "platform": "PLATFORM_UNSPECIFIED", + "pluginType": "GEMINI", + ], + ] + + do { + let onboardResponse: OnboardResponse = try await Self.sendRequest( + endpoint: Self.onboardUserEndpoint, + accessToken: accessToken, + body: onboardBody, + timeout: context.timeout, + dataLoader: context.dataLoader) + if let projectID = onboardResponse.projectID { + return projectID + } + } catch { + Self.log.warning("Antigravity onboarding request failed", metadata: [ + "error": "\(error.localizedDescription)", + ]) + } + + for _ in 0..<5 { + try? await Task.sleep(for: .milliseconds(2000)) + let refreshed = try await Self.loadCodeAssist( + accessToken: accessToken, + timeout: context.timeout, + dataLoader: context.dataLoader) + if let projectID = refreshed.projectID { + return projectID + } + } + + return nil + } + + private static func sendRequest( + endpoint: String, + accessToken: String, + body: [String: Any], + timeout: TimeInterval, + dataLoader: @escaping @Sendable (URLRequest) async throws -> (Data, URLResponse)) async throws + -> Response + { + guard let url = URL(string: endpoint) else { + throw AntigravityRemoteFetchError.apiError("Invalid endpoint URL") + } + + var request = URLRequest(url: url) + request.httpMethod = "POST" + request.timeoutInterval = timeout + request.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization") + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + request.setValue(Self.userAgent, forHTTPHeaderField: "User-Agent") + request.httpBody = try JSONSerialization.data(withJSONObject: body) + + let httpResponse = try await ProviderHTTPTransportHandler(dataLoader).response(for: request) + + switch httpResponse.statusCode { + case 200: + break + case 401: + throw AntigravityRemoteFetchError.notLoggedIn + case 403: + let message = String(data: httpResponse.data, encoding: .utf8)?.trimmedNonEmpty ?? "HTTP 403" + throw AntigravityRemoteFetchError.permissionDenied(message) + default: + let message = String(data: httpResponse.data, encoding: .utf8)?.trimmedNonEmpty + ?? "HTTP \(httpResponse.statusCode)" + throw AntigravityRemoteFetchError.apiError("HTTP \(httpResponse.statusCode): \(message)") + } + + do { + return try JSONDecoder().decode(Response.self, from: httpResponse.data) + } catch { + throw AntigravityRemoteFetchError.parseFailed(error.localizedDescription) + } + } + + private static func parseModelQuotas(_ response: FetchAvailableModelsResponse) throws -> [AntigravityModelQuota] { + let models = response.models ?? [:] + return models.compactMap { modelID, model in + guard let quotaInfo = model.quotaInfo else { return nil } + let resetTime = quotaInfo.resetTime.flatMap(Self.parseResetTime(_:)) + let label = model.displayName?.trimmedNonEmpty + ?? model.label?.trimmedNonEmpty + ?? modelID + return AntigravityModelQuota( + label: label, + modelId: modelID, + remainingFraction: quotaInfo.remainingFraction, + resetTime: resetTime, + resetDescription: resetTime.map { UsageFormatter.resetDescription(from: $0) }) + } + } + + private static func parseQuotaBuckets(_ response: RetrieveUserQuotaResponse) throws -> [AntigravityModelQuota] { + guard let buckets = response.buckets else { + throw AntigravityRemoteFetchError.parseFailed("No quota buckets in response") + } + guard !buckets.isEmpty else { return [] } + + var modelQuotaMap: [String: (fraction: Double?, resetTime: String?)] = [:] + for bucket in buckets { + guard let modelID = bucket.modelId?.trimmedNonEmpty else { continue } + let next = (bucket.remainingFraction, bucket.resetTime) + if let existing = modelQuotaMap[modelID] { + let existingValue = existing.fraction ?? Double.greatestFiniteMagnitude + let nextValue = next.0 ?? Double.greatestFiniteMagnitude + if nextValue < existingValue { + modelQuotaMap[modelID] = next + } + } else { + modelQuotaMap[modelID] = next + } + } + + return modelQuotaMap.keys.sorted().compactMap { modelID in + guard let info = modelQuotaMap[modelID] else { return nil } + let resetTime = info.resetTime.flatMap(Self.parseResetTime(_:)) + return AntigravityModelQuota( + label: modelID, + modelId: modelID, + remainingFraction: info.fraction, + resetTime: resetTime, + resetDescription: resetTime.map { UsageFormatter.resetDescription(from: $0) }) + } + } + + private static func resolvePlan(response: CodeAssistResponse, claims: TokenClaims) -> String? { + if let planType = response.planInfo?.planType?.trimmedNonEmpty { + return planType + } + + switch (response.currentTier?.id?.trimmedNonEmpty, claims.hostedDomain) { + case ("standard-tier", _): + return "Paid" + case ("free-tier", .some): + return "Workspace" + case ("free-tier", .none): + return "Free" + case ("legacy-tier", _): + return "Legacy" + default: + return response.currentTier?.name?.trimmedNonEmpty + } + } + + private static func pickOnboardTier(from response: CodeAssistResponse) -> String? { + if let defaultTier = response.allowedTiers? + .first(where: { $0.isDefault == true && $0.id?.trimmedNonEmpty != nil })?.id?.trimmedNonEmpty + { + return defaultTier + } + if let firstTier = response.allowedTiers? + .first(where: { $0.id?.trimmedNonEmpty != nil })?.id?.trimmedNonEmpty + { + return firstTier + } + if let paidTier = response.paidTier?.id?.trimmedNonEmpty { + return paidTier + } + if let currentTier = response.currentTier?.id?.trimmedNonEmpty { + return currentTier + } + return nil + } + + private static func parseResetTime(_ value: String) -> Date? { + let formatter = ISO8601DateFormatter() + formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds] + if let date = formatter.date(from: value) { + return date + } + formatter.formatOptions = [.withInternetDateTime] + return formatter.date(from: value) + } + + private static func credentialsStore(homeDirectory: String) -> AntigravityOAuthCredentialsStore { + let homeURL = URL(fileURLWithPath: homeDirectory, isDirectory: true) + return AntigravityOAuthCredentialsStore(fileURL: AntigravityOAuthCredentialsStore.defaultURL(home: homeURL)) + } + + private static func resolveCredentialSource( + homeDirectory: String, + environment: [String: String]) throws -> ( + credentials: AntigravityOAuthCredentials?, + store: AntigravityOAuthCredentialsStore?) + { + let primaryStore = Self.credentialsStore(homeDirectory: homeDirectory) + if let tokenValue = environment[AntigravityOAuthCredentialsStore.environmentCredentialsKey] { + guard let credentials = AntigravityOAuthCredentialsStore.credentials(fromTokenAccountValue: tokenValue) + else { + throw AntigravityRemoteFetchError.parseFailed("Could not decode selected account credentials.") + } + return (credentials, nil) + } + return try (primaryStore.load(), primaryStore) + } + + private struct RefreshResult { + let accessToken: String + let credentials: AntigravityOAuthCredentials + } + + private static func refreshAccessToken( + credentials: AntigravityOAuthCredentials, + refreshToken: String, + context: FetchContext) async throws + -> RefreshResult + { + let oauthClient = try Self.refreshOAuthClient( + from: credentials, + oauthClientResolver: context.oauthClientResolver) + + var request = URLRequest(url: AntigravityOAuthConfig.tokenURL) + request.httpMethod = "POST" + request.timeoutInterval = context.timeout + request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") + request.httpBody = Self.formBody([ + "client_id": oauthClient.clientID, + "client_secret": oauthClient.clientSecret, + "refresh_token": refreshToken, + "grant_type": "refresh_token", + ]) + + let httpResponse = try await ProviderHTTPTransportHandler(context.dataLoader).response(for: request) + guard httpResponse.statusCode == 200 else { + throw AntigravityRemoteFetchError.notLoggedIn + } + guard let json = try JSONSerialization.jsonObject(with: httpResponse.data) as? [String: Any], + let accessToken = json["access_token"] as? String + else { + throw AntigravityRemoteFetchError.parseFailed("Could not parse refresh response") + } + + let updatedCredentials = Self.updatedCredentials(credentials, refreshResponse: json) + try await context.persistCredentials(updatedCredentials) + return RefreshResult(accessToken: accessToken, credentials: updatedCredentials) + } + + private static func refreshOAuthClient( + from credentials: AntigravityOAuthCredentials, + oauthClientResolver: @escaping @Sendable () -> AntigravityOAuthClient?) throws + -> AntigravityOAuthClient + { + if let clientID = credentials.clientID?.trimmedNonEmpty, + let clientSecret = credentials.clientSecret?.trimmedNonEmpty + { + return AntigravityOAuthClient(clientID: clientID, clientSecret: clientSecret) + } + + guard let client = oauthClientResolver() else { + throw AntigravityRemoteFetchError.apiError(AntigravityOAuthConfig.missingCredentialsMessage) + } + return client + } + + private static func updatedCredentials( + _ credentials: AntigravityOAuthCredentials, + refreshResponse: [String: Any]) -> AntigravityOAuthCredentials + { + var credentials = credentials + if let accessToken = refreshResponse["access_token"] as? String { + credentials.accessToken = accessToken + } + if let expiresIn = refreshResponse["expires_in"] as? Double { + credentials.expiryDateMilliseconds = (Date().timeIntervalSince1970 + expiresIn) * 1000 + } + if let expiresIn = refreshResponse["expires_in"] as? Int { + credentials.expiryDateMilliseconds = (Date().timeIntervalSince1970 + Double(expiresIn)) * 1000 + } + if let idToken = refreshResponse["id_token"] as? String { + credentials.idToken = idToken + } + return credentials + } + + private static func formBody(_ values: [String: String]) -> Data? { + var components = URLComponents() + components.queryItems = values.map { key, value in + URLQueryItem(name: key, value: value) + } + return components.query?.data(using: .utf8) + } + + private struct TokenClaims { + let email: String? + let hostedDomain: String? + } + + private static func extractClaims(from credentials: AntigravityOAuthCredentials) -> TokenClaims { + let tokenClaims = Self.extractClaimsFromToken(credentials.idToken) + return TokenClaims( + email: tokenClaims.email ?? credentials.email?.trimmedNonEmpty, + hostedDomain: tokenClaims.hostedDomain) + } + + private static func extractClaimsFromToken(_ idToken: String?) -> TokenClaims { + guard let idToken else { + return TokenClaims(email: nil, hostedDomain: nil) + } + + let parts = idToken.components(separatedBy: ".") + guard parts.count >= 2 else { + return TokenClaims(email: nil, hostedDomain: nil) + } + + var payload = parts[1] + .replacingOccurrences(of: "-", with: "+") + .replacingOccurrences(of: "_", with: "/") + let remainder = payload.count % 4 + if remainder > 0 { + payload += String(repeating: "=", count: 4 - remainder) + } + + guard let data = Data(base64Encoded: payload, options: .ignoreUnknownCharacters), + let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] + else { + return TokenClaims(email: nil, hostedDomain: nil) + } + + return TokenClaims( + email: (json["email"] as? String)?.trimmedNonEmpty, + hostedDomain: (json["hd"] as? String)?.trimmedNonEmpty) + } +} + +extension String { + fileprivate var trimmedNonEmpty: String? { + let trimmed = self.trimmingCharacters(in: .whitespacesAndNewlines) + return trimmed.isEmpty ? nil : trimmed + } +} + +private struct ProjectReference: Decodable { + let value: String? + + init(from decoder: Decoder) throws { + let single = try decoder.singleValueContainer() + if let stringValue = try? single.decode(String.self) { + self.value = stringValue + return + } + + let keyed = try decoder.container(keyedBy: CodingKeys.self) + self.value = try keyed.decodeIfPresent(String.self, forKey: .id) + ?? keyed.decodeIfPresent(String.self, forKey: .projectID) + } + + private enum CodingKeys: String, CodingKey { + case id + case projectID = "projectId" + } +} + +private struct CodeAssistResponse: Decodable { + let planInfo: CodeAssistPlanInfo? + let currentTier: TierInfo? + let paidTier: TierInfo? + let allowedTiers: [AllowedTier]? + let cloudaicompanionProject: ProjectReference? + + var projectID: String? { + self.cloudaicompanionProject?.value?.trimmingCharacters(in: .whitespacesAndNewlines).nilIfEmpty + } +} + +private struct CodeAssistPlanInfo: Decodable { + let planType: String? +} + +private struct TierInfo: Decodable { + let id: String? + let name: String? +} + +private struct AllowedTier: Decodable { + let id: String? + let isDefault: Bool? +} + +private struct OnboardResponse: Decodable { + let response: OnboardInnerResponse? + + var projectID: String? { + self.response?.cloudaicompanionProject?.value?.trimmingCharacters(in: .whitespacesAndNewlines).nilIfEmpty + } +} + +private struct OnboardInnerResponse: Decodable { + let cloudaicompanionProject: ProjectReference? +} + +private struct FetchAvailableModelsResponse: Decodable { + let models: [String: AntigravityRemoteModel]? +} + +private struct RetrieveUserQuotaResponse: Decodable { + let buckets: [RetrieveUserQuotaBucket]? +} + +private struct RetrieveUserQuotaBucket: Decodable { + let modelId: String? + let remainingFraction: Double? + let resetTime: String? +} + +private struct AntigravityRemoteModel: Decodable { + let displayName: String? + let label: String? + let quotaInfo: AntigravityRemoteQuotaInfo? +} + +private struct AntigravityRemoteQuotaInfo: Decodable { + let remainingFraction: Double? + let resetTime: String? +} + +extension String? { + fileprivate var trimmedNonEmpty: String? { + self?.trimmingCharacters(in: .whitespacesAndNewlines).nilIfEmpty + } +} + +extension String { + fileprivate var nilIfEmpty: String? { + self.isEmpty ? nil : self + } +} diff --git a/Sources/CodexBarCore/Providers/Antigravity/AntigravityStatusProbe+Deadline.swift b/Sources/CodexBarCore/Providers/Antigravity/AntigravityStatusProbe+Deadline.swift new file mode 100644 index 0000000..da86b63 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Antigravity/AntigravityStatusProbe+Deadline.swift @@ -0,0 +1,128 @@ +import Foundation + +extension AntigravityStatusProbe { + private static let processProbeLog = CodexBarLog.logger(LogCategories.antigravity) + + private enum ProcessSnapshotFetchFailure { + case antigravity(AntigravityStatusProbeError) + case url(URLError) + case cancellation + case other(String) + + init(_ error: Error) { + if let error = error as? AntigravityStatusProbeError { + self = .antigravity(error) + } else if let error = error as? URLError, error.code == .cancelled { + self = .cancellation + } else if let error = error as? URLError { + self = .url(error) + } else if error is CancellationError { + self = .cancellation + } else { + self = .other(error.localizedDescription) + } + } + + var error: Error { + switch self { + case let .antigravity(error): + error + case let .url(error): + error + case .cancellation: + CancellationError() + case let .other(message): + AntigravityStatusProbeError.apiError(message) + } + } + } + + private enum ProcessSnapshotFetchOutcome { + case success(index: Int, snapshot: AntigravityStatusSnapshot) + case failure(index: Int, pid: Int, failure: ProcessSnapshotFetchFailure) + } + + static func fetchProcessSnapshots( + processInfos: [ProcessInfoResult], + fetch: @escaping @Sendable (ProcessInfoResult) async throws -> AntigravityStatusSnapshot) + async throws -> (snapshots: [AntigravityStatusSnapshot], lastError: Error?) + { + let outcomes = await withTaskGroup(of: ProcessSnapshotFetchOutcome.self) { group in + for (index, processInfo) in processInfos.enumerated() { + group.addTask { + do { + return try await .success(index: index, snapshot: fetch(processInfo)) + } catch { + return .failure(index: index, pid: processInfo.pid, failure: .init(error)) + } + } + } + + var ordered = [ProcessSnapshotFetchOutcome?](repeating: nil, count: processInfos.count) + for await outcome in group { + switch outcome { + case let .success(index, _), let .failure(index, _, _): + ordered[index] = outcome + } + } + return ordered.compactMap(\.self) + } + + var snapshots: [AntigravityStatusSnapshot] = [] + var lastError: Error? + for outcome in outcomes { + switch outcome { + case let .success(_, snapshot): + snapshots.append(snapshot) + case let .failure(_, pid, failure): + if case .cancellation = failure { + throw CancellationError() + } + let error = failure.error + lastError = error + Self.processProbeLog.debug("Antigravity local process probe failed", metadata: [ + "pid": "\(pid)", + "error": error.localizedDescription, + ]) + } + } + return (snapshots, lastError) + } + + static func fetch( + processInfo: ProcessInfoResult, + timeout: TimeInterval, + deadline: Date) async throws -> AntigravityStatusSnapshot + { + guard let portTimeout = timeoutForNextAttempt(timeout: timeout, deadline: deadline) else { + throw AntigravityStatusProbeError.timedOut + } + let ports = try await Self.listeningPorts(pid: processInfo.pid, timeout: portTimeout) + let endpoint = try await Self.resolveWorkingEndpoint( + candidateEndpoints: Self.connectionCandidates( + listeningPorts: ports, + languageServerCSRFToken: processInfo.csrfToken, + extensionServerPort: processInfo.extensionPort, + extensionServerCSRFToken: processInfo.extensionServerCSRFToken), + timeout: timeout, + deadline: deadline) + let context = RequestContext( + endpoints: Self.requestEndpoints( + resolvedEndpoint: endpoint, + listeningPorts: ports, + languageServerCSRFToken: processInfo.csrfToken, + extensionServerPort: processInfo.extensionPort, + extensionServerCSRFToken: processInfo.extensionServerCSRFToken), + timeout: timeout, + deadline: deadline) + + return try await Self.fetchSnapshot(context: context) + } + + static func timeoutForNextAttempt(timeout: TimeInterval, deadline: Date?) -> TimeInterval? { + guard let deadline else { return timeout } + let remaining = deadline.timeIntervalSinceNow + guard remaining > 0 else { return nil } + return min(timeout, remaining) + } +} diff --git a/Sources/CodexBarCore/Providers/Antigravity/AntigravityStatusProbe+LocalEndpoints.swift b/Sources/CodexBarCore/Providers/Antigravity/AntigravityStatusProbe+LocalEndpoints.swift new file mode 100644 index 0000000..fdb4ff6 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Antigravity/AntigravityStatusProbe+LocalEndpoints.swift @@ -0,0 +1,23 @@ +extension AntigravityStatusProbe { + static func cliEndpoints(ports: [Int]) -> [AntigravityConnectionEndpoint] { + ports.flatMap { port in + self.localProbeSchemes.map { scheme in + AntigravityConnectionEndpoint( + scheme: scheme, + port: port, + csrfToken: "", + source: .cliHTTPS) + } + } + } + + static var localProbeSchemes: [String] { + #if os(Linux) + // FoundationNetworking cannot trust Antigravity's self-signed TLS cert. + // Requests remain pinned to 127.0.0.1 in makeRequest. + ["https", "http"] + #else + ["https"] + #endif + } +} diff --git a/Sources/CodexBarCore/Providers/Antigravity/AntigravityStatusProbe+PortDetection.swift b/Sources/CodexBarCore/Providers/Antigravity/AntigravityStatusProbe+PortDetection.swift new file mode 100644 index 0000000..7510912 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Antigravity/AntigravityStatusProbe+PortDetection.swift @@ -0,0 +1,137 @@ +import Foundation + +/// Parses Linux `/proc//net/tcp{,6}` output to recover the listening ports +/// owned by a process. The parsing is platform-independent for focused tests. +enum ProcNetTCPListeningPortParser { + /// The `st` column value for a socket in the LISTEN state. + private static let listenState = "0A" + + /// Extracts the socket inode from a `/proc//fd` symlink destination such + /// as `socket:[12345]`. Returns nil for non-socket descriptors. + static func socketInode(fromLink destination: String) -> String? { + let prefix = "socket:[" + guard destination.hasPrefix(prefix), destination.hasSuffix("]") else { return nil } + let inode = destination.dropFirst(prefix.count).dropLast() + return inode.isEmpty ? nil : String(inode) + } + + /// Returns the local ports of LISTEN sockets whose inode is in `socketInodes`. + /// + /// `content` is the raw text of a process-scoped `tcp` or `tcp6` table. Each + /// row encodes the local endpoint as `ADDRESS:PORT` (for example, + /// `0100007F:1F90` uses port 8080) and the owning socket inode in column ten. + static func listeningPorts(_ content: String, socketInodes: Set) -> Set { + var ports: Set = [] + for line in content.split(separator: "\n") { + let columns = line.split(separator: " ", omittingEmptySubsequences: true) + // Columns: sl local_address rem_address st ... uid timeout inode + guard columns.count > 9, + columns[3] == self.listenState, + socketInodes.contains(String(columns[9])) + else { continue } + let localAddress = columns[1] + guard let separator = localAddress.lastIndex(of: ":"), + let port = Int(localAddress[localAddress.index(after: separator)...], radix: 16), + (0...Int(UInt16.max)).contains(port) + else { continue } + ports.insert(port) + } + return ports + } +} + +extension AntigravityStatusProbe { + /// Resolves the TCP ports the process `pid` is listening on. Uses `lsof` when + /// present (the common denominator across macOS and Linux) and falls back to + /// the kernel's `/proc` interface on Linux hosts without `lsof`. + static func listeningPorts(pid: Int, timeout: TimeInterval) async throws -> [Int] { + let lsof = ["/usr/sbin/lsof", "/usr/bin/lsof"].first(where: { + FileManager.default.isExecutableFile(atPath: $0) + }) + + if let lsof { + return try await Self.lsofListeningPorts(lsof: lsof, pid: pid, timeout: timeout) + } + + #if os(Linux) + // `lsof` is frequently absent on minimal Linux hosts. Fall back to the + // kernel's /proc interface, mirroring the /proc//cwd fallback that + // LocalAgentSessionScanner.cwdByPID already uses when lsof is missing. + let ports = Self.procListeningPorts(pid: pid) + if ports.isEmpty { + throw AntigravityStatusProbeError.portDetectionFailed("no listening ports found") + } + return ports + #else + throw AntigravityStatusProbeError.portDetectionFailed("lsof not available") + #endif + } + + private static func lsofListeningPorts( + lsof: String, + pid: Int, + timeout: TimeInterval) async throws -> [Int] + { + let env = ProcessInfo.processInfo.environment + let result: SubprocessResult + do { + result = try await SubprocessRunner.run( + binary: lsof, + arguments: ["-nP", "-iTCP", "-sTCP:LISTEN", "-a", "-p", String(pid)], + environment: env, + timeout: timeout, + label: "antigravity-lsof") + } catch let SubprocessRunnerError.nonZeroExit(code, stderr) + where code == 1 && stderr.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty + { + throw AntigravityStatusProbeError.portDetectionFailed("no listening ports found") + } + let ports = Self.parseListeningPorts(result.stdout) + if ports.isEmpty { + throw AntigravityStatusProbeError.portDetectionFailed("no listening ports found") + } + return ports + } + + private static func parseListeningPorts(_ output: String) -> [Int] { + guard let regex = try? NSRegularExpression(pattern: #":(\d+)\s+\(LISTEN\)"#) else { return [] } + let range = NSRange(output.startIndex.. = [] + regex.enumerateMatches(in: output, options: [], range: range) { match, _, _ in + guard let match, + let range = Range(match.range(at: 1), in: output), + let value = Int(output[range]) else { return } + ports.insert(value) + } + return ports.sorted() + } + + /// Recovers the listening ports owned by `pid` by matching its open socket + /// inodes against the TCP tables from the same process/network namespace. + static func procListeningPorts(pid: Int, procRoot: String = "/proc") -> [Int] { + let processRoot = "\(procRoot)/\(pid)" + let inodes = Self.socketInodes(processRoot: processRoot) + guard !inodes.isEmpty else { return [] } + var ports: Set = [] + for path in ["\(processRoot)/net/tcp", "\(processRoot)/net/tcp6"] { + guard let content = try? String(contentsOfFile: path, encoding: .utf8) else { continue } + ports.formUnion(ProcNetTCPListeningPortParser.listeningPorts(content, socketInodes: inodes)) + } + return ports.sorted() + } + + /// Collects the socket inodes referenced by the process's open descriptors. + private static func socketInodes(processRoot: String) -> Set { + let fdDirectory = "\(processRoot)/fd" + guard let entries = try? FileManager.default.contentsOfDirectory(atPath: fdDirectory) else { return [] } + var inodes: Set = [] + for entry in entries { + guard let destination = try? FileManager.default.destinationOfSymbolicLink( + atPath: "\(fdDirectory)/\(entry)"), + let inode = ProcNetTCPListeningPortParser.socketInode(fromLink: destination) + else { continue } + inodes.insert(inode) + } + return inodes + } +} diff --git a/Sources/CodexBarCore/Providers/Antigravity/AntigravityStatusProbe+ResponseModels.swift b/Sources/CodexBarCore/Providers/Antigravity/AntigravityStatusProbe+ResponseModels.swift new file mode 100644 index 0000000..275b9d3 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Antigravity/AntigravityStatusProbe+ResponseModels.swift @@ -0,0 +1,111 @@ +import Foundation + +struct UserStatusResponse: Decodable { + let code: CodeValue? + let message: String? + let userStatus: UserStatus? +} + +struct CommandModelConfigResponse: Decodable { + let code: CodeValue? + let message: String? + let clientModelConfigs: [ModelConfig]? +} + +struct UserStatus: Decodable { + let email: String? + let planStatus: PlanStatus? + let cascadeModelConfigData: ModelConfigData? + let userTier: UserTier? +} + +struct UserTier: Decodable { + let id: String? + let name: String? + let description: String? + + var preferredName: String? { + guard let value = self.name?.trimmingCharacters(in: .whitespacesAndNewlines) else { return nil } + return value.isEmpty ? nil : value + } +} + +struct PlanStatus: Decodable { + let planInfo: PlanInfo? +} + +struct PlanInfo: Decodable { + let planName: String? + let planDisplayName: String? + let displayName: String? + let productName: String? + let planShortName: String? + + var preferredName: String? { + let candidates = [ + self.planDisplayName, + self.displayName, + self.productName, + self.planName, + self.planShortName, + ] + for candidate in candidates { + guard let value = candidate?.trimmingCharacters(in: .whitespacesAndNewlines) else { continue } + if !value.isEmpty { return value } + } + return nil + } +} + +struct ModelConfigData: Decodable { + let clientModelConfigs: [ModelConfig]? +} + +struct ModelConfig: Decodable { + let label: String + let modelOrAlias: ModelAlias + let quotaInfo: QuotaInfo? +} + +struct ModelAlias: Decodable { + let model: String +} + +struct QuotaInfo: Decodable { + let remainingFraction: Double? + let resetTime: String? +} + +enum CodeValue: Decodable { + case int(Int) + case string(String) + + var isOK: Bool { + switch self { + case let .int(value): + value == 0 + case let .string(value): + value.lowercased() == "ok" || value.lowercased() == "success" || value == "0" + } + } + + var rawValue: String { + switch self { + case let .int(value): "\(value)" + case let .string(value): value + } + } + + init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + if let value = try? container.decode(Int.self) { + self = .int(value) + return + } + if let value = try? container.decode(String.self) { + self = .string(value) + return + } + throw DecodingError.dataCorruptedError(in: container, debugDescription: "Unsupported code type") + } +} diff --git a/Sources/CodexBarCore/Providers/Antigravity/AntigravityStatusProbe.swift b/Sources/CodexBarCore/Providers/Antigravity/AntigravityStatusProbe.swift new file mode 100644 index 0000000..2093f14 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Antigravity/AntigravityStatusProbe.swift @@ -0,0 +1,1642 @@ +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +public struct AntigravityModelQuota: Sendable { + public let label: String + public let modelId: String + public let remainingFraction: Double? + public let resetTime: Date? + public let resetDescription: String? + + public init( + label: String, + modelId: String, + remainingFraction: Double?, + resetTime: Date?, + resetDescription: String?) + { + self.label = label + self.modelId = modelId + self.remainingFraction = remainingFraction + self.resetTime = resetTime + self.resetDescription = resetDescription + } + + public var remainingPercent: Double { + guard let remainingFraction else { return 0 } + return max(0, min(100, remainingFraction * 100)) + } +} + +private enum AntigravityModelFamily { + case claude + case gpt + case geminiPro + case geminiFlash + case unknown +} + +private enum AntigravityUsagePool: Hashable { + case gemini + case claudeGPT + + var id: String { + switch self { + case .gemini: "antigravity-gemini" + case .claudeGPT: "antigravity-claude-gpt" + } + } + + var title: String { + switch self { + case .gemini: "Gemini Models" + case .claudeGPT: "Claude and GPT models" + } + } + + var sortRank: Int { + switch self { + case .gemini: 0 + case .claudeGPT: 1 + } + } +} + +private struct AntigravityModelVersion: Comparable { + let major: Int + let minor: Int + + static func < (lhs: AntigravityModelVersion, rhs: AntigravityModelVersion) -> Bool { + if lhs.major != rhs.major { return lhs.major < rhs.major } + return lhs.minor < rhs.minor + } +} + +private struct AntigravityNormalizedModel { + let quota: AntigravityModelQuota + let family: AntigravityModelFamily + let selectionPriority: Int? + let isImage: Bool + let isLite: Bool + let isAutocomplete: Bool + let version: AntigravityModelVersion? + let tier: Int +} + +public enum AntigravityModelQuotaSource: Sendable { + case local + case remote +} + +public struct AntigravityStatusSnapshot: Sendable { + public let modelQuotas: [AntigravityModelQuota] + public let accountEmail: String? + public let accountPlan: String? + public let source: AntigravityModelQuotaSource + let quotaSummary: AntigravityQuotaSummary? + + public init( + modelQuotas: [AntigravityModelQuota], + accountEmail: String?, + accountPlan: String?, + source: AntigravityModelQuotaSource = .remote) + { + self.modelQuotas = modelQuotas + self.accountEmail = accountEmail + self.accountPlan = accountPlan + self.source = source + self.quotaSummary = nil + } + + init( + quotaSummary: AntigravityQuotaSummary, + accountEmail: String?, + accountPlan: String?, + source: AntigravityModelQuotaSource = .local) + { + self.modelQuotas = [] + self.accountEmail = accountEmail + self.accountPlan = accountPlan + self.source = source + self.quotaSummary = quotaSummary + } + + public func toUsageSnapshot() throws -> UsageSnapshot { + if let quotaSummary { + return try Self.usageSnapshot( + from: quotaSummary, + accountEmail: self.accountEmail, + accountPlan: self.accountPlan) + } + + guard !self.modelQuotas.isEmpty else { + throw AntigravityStatusProbeError.parseFailed("No quota models available") + } + + let normalized = Self.normalizedModels(self.modelQuotas) + let summaryCandidates = normalized.filter(Self.isSummaryCandidate) + let primaryQuota = Self.representative(for: .gemini, in: summaryCandidates) + let secondaryQuota = Self.representative(for: .claudeGPT, in: summaryCandidates) + let fallbackQuota: AntigravityModelQuota? = if primaryQuota == nil, secondaryQuota == nil { + switch self.source { + case .local: + Self.fallbackRepresentative(in: normalized.filter { + $0.family == .unknown && + Self.isSelectableTextModel($0) && + $0.quota.remainingFraction != nil + }) + case .remote: + nil + } + } else { + nil + } + + let primary = primaryQuota.map(Self.rateWindow(for:)) + let secondary = secondaryQuota.map(Self.rateWindow(for:)) + let extraWindows = Self.extraRateWindows( + from: normalized, + summaryCandidates: summaryCandidates, + compactFallbackModelID: fallbackQuota?.modelId, + representedPools: Set([ + primaryQuota.map { _ in AntigravityUsagePool.gemini }, + secondaryQuota.map { _ in AntigravityUsagePool.claudeGPT }, + ].compactMap(\.self))) + + let identity = ProviderIdentitySnapshot( + providerID: .antigravity, + accountEmail: self.accountEmail, + accountOrganization: nil, + loginMethod: self.accountPlan) + return UsageSnapshot( + primary: primary, + secondary: secondary, + tertiary: nil, + extraRateWindows: extraWindows.isEmpty ? nil : extraWindows, + updatedAt: Date(), + identity: identity) + } + + func withIdentity(from snapshot: AntigravityStatusSnapshot?) -> AntigravityStatusSnapshot { + guard let snapshot else { return self } + let accountEmail = snapshot.accountEmail ?? self.accountEmail + let accountPlan = snapshot.accountPlan ?? self.accountPlan + if let quotaSummary { + return AntigravityStatusSnapshot( + quotaSummary: quotaSummary, + accountEmail: accountEmail, + accountPlan: accountPlan, + source: self.source) + } + return AntigravityStatusSnapshot( + modelQuotas: self.modelQuotas, + accountEmail: accountEmail, + accountPlan: accountPlan, + source: self.source) + } + + private static func usageSnapshot( + from quotaSummary: AntigravityQuotaSummary, + accountEmail: String?, + accountPlan: String?) throws -> UsageSnapshot + { + let namedWindows = Self.quotaSummaryWindows(from: quotaSummary) + guard !namedWindows.isEmpty else { + throw AntigravityStatusProbeError.parseFailed("No quota buckets available") + } + + let primary = Self.quotaSummaryRepresentative( + matching: { $0.lowercased().contains("gemini") }, + in: namedWindows) + let secondary = Self.quotaSummaryRepresentative( + matching: { $0.lowercased().contains("claude") || $0.lowercased().contains("gpt") }, + in: namedWindows) + + let identity = ProviderIdentitySnapshot( + providerID: .antigravity, + accountEmail: accountEmail, + accountOrganization: nil, + loginMethod: accountPlan) + return UsageSnapshot( + primary: primary, + secondary: secondary, + tertiary: nil, + extraRateWindows: namedWindows, + updatedAt: Date(), + identity: identity) + } + + private static func quotaSummaryRepresentative( + matching predicate: (String) -> Bool, + in windows: [NamedRateWindow]) -> RateWindow? + { + windows + .filter { $0.usageKnown && predicate($0.title) } + .max { lhs, rhs in + if lhs.window.usedPercent != rhs.window.usedPercent { + return lhs.window.usedPercent < rhs.window.usedPercent + } + return lhs.title.localizedCaseInsensitiveCompare(rhs.title) == .orderedDescending + }? + .window + } + + private static func quotaSummaryWindows(from quotaSummary: AntigravityQuotaSummary) -> [NamedRateWindow] { + let sortedGroups = quotaSummary.groups.enumerated().sorted { lhs, rhs in + let lhsRank = Self.quotaGroupSortRank(lhs.element) + let rhsRank = Self.quotaGroupSortRank(rhs.element) + if lhsRank != rhsRank { + return lhsRank < rhsRank + } + return lhs.offset < rhs.offset + }.map(\.element) + + return sortedGroups.flatMap { group in + let groupTitle = Self.displayTitle(forQuotaGroup: group) + let sortedBuckets = group.buckets.enumerated().sorted { lhs, rhs in + let lhsRank = Self.quotaBucketSortRank(lhs.element) + let rhsRank = Self.quotaBucketSortRank(rhs.element) + if lhsRank != rhsRank { + return lhsRank < rhsRank + } + return lhs.offset < rhs.offset + }.map(\.element) + + return sortedBuckets.map { bucket in + let bucketTitle = Self.displayTitle(forQuotaBucket: bucket) + let remainingPercent = Self.remainingPercent(from: bucket.remainingFraction) + let usedPercent = remainingPercent.map { 100 - $0 } ?? 0 + let window = RateWindow( + usedPercent: usedPercent, + windowMinutes: Self.windowMinutes(forQuotaBucket: bucket), + resetsAt: bucket.resetTime, + resetDescription: bucket.resetDescription) + return NamedRateWindow( + id: Self.quotaSummaryWindowID(for: bucket), + title: "\(groupTitle) \(bucketTitle)", + window: window, + usageKnown: !bucket.disabled && bucket.remainingFraction != nil) + } + } + } + + static func isQuotaSummaryWindowID(_ id: String) -> Bool { + id.hasPrefix(self.quotaSummaryWindowIDPrefix) + } + + private static let quotaSummaryWindowIDPrefix = "antigravity-quota-summary-" + + private static func quotaSummaryWindowID(for bucket: AntigravityQuotaSummaryBucket) -> String { + self.quotaSummaryWindowIDPrefix + bucket.bucketId + } + + private static func remainingPercent(from remainingFraction: Double?) -> Double? { + guard let remainingFraction else { return nil } + return max(0, min(100, remainingFraction * 100)) + } + + private static func displayTitle(forQuotaGroup group: AntigravityQuotaSummaryGroup) -> String { + let title = group.displayName.trimmingCharacters(in: .whitespacesAndNewlines) + let lowercasedTitle = title.lowercased() + if lowercasedTitle.contains("gemini") { + return "Gemini" + } + if lowercasedTitle.contains("claude") || lowercasedTitle.contains("gpt") { + return "Claude/GPT" + } + return title.isEmpty ? "Quota" : title + } + + private static func displayTitle(forQuotaBucket bucket: AntigravityQuotaSummaryBucket) -> String { + switch self.quotaBucketKind(for: bucket) { + case .session: + "5-hour" + case .weekly: + "weekly" + case .other: + bucket.displayName + } + } + + private static func windowMinutes(forQuotaBucket bucket: AntigravityQuotaSummaryBucket) -> Int? { + switch self.quotaBucketKind(for: bucket) { + case .session: + 300 + case .weekly: + 10080 + case .other: + nil + } + } + + private enum QuotaBucketKind { + case session + case weekly + case other + } + + private static func quotaGroupSortRank(_ group: AntigravityQuotaSummaryGroup) -> Int { + let title = group.displayName.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() + if title.contains("gemini") { + return 0 + } + if title.contains("claude") || title.contains("gpt") { + return 1 + } + return 2 + } + + private static func quotaBucketSortRank(_ bucket: AntigravityQuotaSummaryBucket) -> Int { + switch self.quotaBucketKind(for: bucket) { + case .session: + 0 + case .weekly: + 1 + case .other: + 2 + } + } + + private static func quotaBucketKind(for bucket: AntigravityQuotaSummaryBucket) -> QuotaBucketKind { + let combined = "\(bucket.bucketId) \(bucket.displayName)".lowercased() + if combined.contains("5h") || combined.contains("5-hour") || combined.contains("five hour") { + return .session + } + if combined.contains("weekly") { + return .weekly + } + return .other + } + + static func quotaDisplayLabel(_ quota: AntigravityModelQuota) -> String { + let trimmed = quota.label.trimmingCharacters(in: .whitespacesAndNewlines) + guard trimmed.isEmpty || trimmed == quota.modelId else { return quota.label } + return Self.humanizedModelID(quota.modelId) + } + + static func humanizedModelID(_ modelId: String) -> String { + let parts = modelId.split(separator: "-").map(String.init) + var words: [String] = [] + var index = 0 + + while index < parts.count { + let part = parts[index] + if Self.isSingleDigit(part), index + 1 < parts.count, Self.isSingleDigit(parts[index + 1]) { + var versionParts = [part] + index += 1 + while index < parts.count, Self.isSingleDigit(parts[index]) { + versionParts.append(parts[index]) + index += 1 + } + words.append(versionParts.joined(separator: ".")) + continue + } + + if part.allSatisfy({ $0.isNumber || $0 == "." }) { + words.append(part) + } else if Self.modelLabelAcronyms.contains(part.lowercased()) { + words.append(part.uppercased()) + } else { + words.append(part.prefix(1).uppercased() + part.dropFirst()) + } + index += 1 + } + + return words.joined(separator: " ") + } + + private static let modelLabelAcronyms: Set = ["ai", "api", "gpt", "oss"] + + private static func isSingleDigit(_ value: String) -> Bool { + value.count == 1 && value.allSatisfy(\.isNumber) + } + + private static func rateWindow(for quota: AntigravityModelQuota) -> RateWindow { + RateWindow( + usedPercent: 100 - quota.remainingPercent, + windowMinutes: nil, + resetsAt: quota.resetTime, + resetDescription: quota.resetDescription) + } + + private static func modelOrderPrecedes( + _ lhs: AntigravityNormalizedModel, + _ rhs: AntigravityNormalizedModel) -> Bool + { + // 1. Family rank: claude=0, geminiPro=1, geminiFlash=2, unknown=3 + let lhsFamilyRank = Self.familyRank(lhs.family) + let rhsFamilyRank = Self.familyRank(rhs.family) + if lhsFamilyRank != rhsFamilyRank { + return lhsFamilyRank < rhsFamilyRank + } + + // 2. Version descending (newer first); nil version sorts after non-nil + switch (lhs.version, rhs.version) { + case let (.some(lv), .some(rv)): + if lv != rv { + return lv > rv + } + case (.some, .none): + return true + case (.none, .some): + return false + case (.none, .none): + break + } + + // 3. Tier ascending: High(0) < Medium(1) < Low(2) + if lhs.tier != rhs.tier { + return lhs.tier < rhs.tier + } + + // 4. Label tiebreaker + return lhs.quota.label.localizedCaseInsensitiveCompare(rhs.quota.label) == .orderedAscending + } + + private static func familyRank(_ family: AntigravityModelFamily) -> Int { + switch family { + case .claude: 0 + case .gpt: 1 + case .geminiPro: 2 + case .geminiFlash: 3 + case .unknown: 4 + } + } + + private static func isSummaryCandidate(_ model: AntigravityNormalizedModel) -> Bool { + self.usagePool(for: model) != nil && self.isSelectableTextModel(model) + } + + private static func isSelectableTextModel(_ model: AntigravityNormalizedModel) -> Bool { + !model.isLite && !model.isAutocomplete && !model.isImage + } + + private static func normalizedModels(_ models: [AntigravityModelQuota]) -> [AntigravityNormalizedModel] { + models.map { self.normalizeModel($0) } + } + + private static func normalizeModel(_ quota: AntigravityModelQuota) -> AntigravityNormalizedModel { + let modelId = quota.modelId.lowercased() + let label = quota.label.lowercased() + let family = Self.family(forModelID: modelId, label: label) + + let isLite = modelId.contains("lite") || label.contains("lite") + let isAutocomplete = modelId.contains("autocomplete") || label.contains("autocomplete") || modelId + .hasPrefix("tab_") + let isImage = modelId.contains("image") || label.contains("image") + let isSelectableTextModel = !isLite && !isAutocomplete && !isImage + let isLowPriorityGeminiPro = modelId.contains("pro-low") + || (label.contains("pro") && label.contains("low")) + + let selectionPriority: Int? = switch family { + case .claude, .gpt: + 0 + case .geminiPro: + if isLowPriorityGeminiPro, isSelectableTextModel { + 0 + } else if isSelectableTextModel { + 1 + } else { + nil + } + case .geminiFlash: + isSelectableTextModel ? 0 : nil + case .unknown: + nil + } + + let version = Self.parseVersion(from: label) + let tier = Self.parseTier(from: label, modelId: modelId) + + return AntigravityNormalizedModel( + quota: quota, + family: family, + selectionPriority: selectionPriority, + isImage: isImage, + isLite: isLite, + isAutocomplete: isAutocomplete, + version: version, + tier: tier) + } + + private static func parseVersion(from label: String) -> AntigravityModelVersion? { + // Accept either "." or "-" between major and minor so a raw model id used as the + // label when displayName is missing (e.g. "gemini-3-1-pro-low") still parses 3.1. + guard let regex = try? NSRegularExpression(pattern: #"(\d+)(?:[.\-](\d+))?"#) else { return nil } + let nsLabel = label as NSString + let range = NSRange(location: 0, length: nsLabel.length) + guard let match = regex.firstMatch(in: label, options: [], range: range) else { return nil } + let majorRange = Range(match.range(at: 1), in: label) + guard let majorRange, let major = Int(label[majorRange]) else { return nil } + let minor: Int = if match.range(at: 2).location != NSNotFound, + let minorRange = Range(match.range(at: 2), in: label), + let parsed = Int(label[minorRange]) + { + parsed + } else { + 0 + } + return AntigravityModelVersion(major: major, minor: minor) + } + + private static func parseTier(from label: String, modelId: String) -> Int { + let combined = label + " " + modelId + if combined.contains("high") { return 0 } + if combined.contains("medium") { return 1 } + if combined.contains("low") { return 2 } + return 1 + } + + private static func representative( + for pool: AntigravityUsagePool, + in models: [AntigravityNormalizedModel]) -> AntigravityModelQuota? + { + let candidates = models.filter { + Self.usagePool(for: $0) == pool && $0.quota.remainingFraction != nil + } + guard !candidates.isEmpty else { return nil } + return candidates.min { lhs, rhs in + if lhs.quota.remainingPercent != rhs.quota.remainingPercent { + return lhs.quota.remainingPercent < rhs.quota.remainingPercent + } + switch (lhs.quota.resetTime, rhs.quota.resetTime) { + case let (.some(left), .some(right)) where left != right: + return left < right + case (.some, .none): + return true + case (.none, .some): + return false + default: + return lhs.quota.label.localizedCaseInsensitiveCompare(rhs.quota.label) == .orderedAscending + } + }?.quota + } + + private static func fallbackRepresentative(in models: [AntigravityNormalizedModel]) -> AntigravityModelQuota? { + models.min { lhs, rhs in + if lhs.quota.remainingPercent != rhs.quota.remainingPercent { + return lhs.quota.remainingPercent < rhs.quota.remainingPercent + } + return lhs.quota.label.localizedCaseInsensitiveCompare(rhs.quota.label) == .orderedAscending + }?.quota + } + + private static func extraRateWindows( + from models: [AntigravityNormalizedModel], + summaryCandidates: [AntigravityNormalizedModel], + compactFallbackModelID: String?, + representedPools: Set) -> [NamedRateWindow] + { + let resetOnlyPoolWindows = [AntigravityUsagePool.gemini, .claudeGPT].compactMap { pool -> NamedRateWindow? in + guard !representedPools.contains(pool) else { return nil } + let candidates = summaryCandidates.filter { Self.usagePool(for: $0) == pool } + guard let resetOnly = candidates.first(where: { model in + model.quota.remainingFraction == nil && + (model.quota.resetTime != nil || model.quota.resetDescription != nil) + }) else { + return nil + } + return NamedRateWindow( + id: pool.id, + title: pool.title, + window: Self.rateWindow(for: resetOnly.quota), + usageKnown: false) + } + + let distinctWindows = models + .filter { + $0.quota.modelId == compactFallbackModelID || Self.shouldShowDistinctExtraWindow($0) + } + .sorted(by: Self.modelOrderPrecedes) + .map { m in + NamedRateWindow( + id: m.quota.modelId == compactFallbackModelID + ? Self.compactFallbackWindowID(modelID: m.quota.modelId) + : m.quota.modelId, + title: Self.quotaDisplayLabel(m.quota), + window: Self.rateWindow(for: m.quota), + usageKnown: m.quota.remainingFraction != nil) + } + + return resetOnlyPoolWindows.sorted { lhs, rhs in + guard let lhsPool = Self.pool(forExtraWindowID: lhs.id), + let rhsPool = Self.pool(forExtraWindowID: rhs.id) + else { + return lhs.title.localizedCaseInsensitiveCompare(rhs.title) == .orderedAscending + } + return lhsPool.sortRank < rhsPool.sortRank + } + distinctWindows + } + + private static func compactFallbackWindowID(modelID: String) -> String { + "antigravity-compact-fallback-\(modelID)" + } + + private static func shouldShowDistinctExtraWindow(_ model: AntigravityNormalizedModel) -> Bool { + guard !self.isSummaryCandidate(model) else { return false } + if model.quota.remainingFraction == nil { + return model.quota.resetTime != nil || model.quota.resetDescription != nil + } + return model.quota.remainingPercent < 99.9 + } + + private static func pool(forExtraWindowID id: String) -> AntigravityUsagePool? { + switch id { + case AntigravityUsagePool.gemini.id: .gemini + case AntigravityUsagePool.claudeGPT.id: .claudeGPT + default: nil + } + } + + private static func usagePool(for model: AntigravityNormalizedModel) -> AntigravityUsagePool? { + switch model.family { + case .geminiPro, .geminiFlash: + .gemini + case .claude, .gpt: + .claudeGPT + case .unknown: + nil + } + } + + private static func family(forModelID modelId: String, label: String) -> AntigravityModelFamily { + let modelIDFamily = Self.family(from: modelId) + if modelIDFamily != .unknown { + return modelIDFamily + } + return Self.family(from: label) + } + + private static func family(from text: String) -> AntigravityModelFamily { + if text.contains("claude") { + return .claude + } + if text.contains("gpt") || text.contains("openai") { + return .gpt + } + if text.contains("gemini"), text.contains("pro") { + return .geminiPro + } + if text.contains("gemini"), text.contains("flash") { + return .geminiFlash + } + return .unknown + } +} + +public struct AntigravityPlanInfoSummary: Sendable, Codable, Equatable { + public let planName: String? + public let planDisplayName: String? + public let displayName: String? + public let productName: String? + public let planShortName: String? +} + +public enum AntigravityStatusProbeError: LocalizedError, Sendable, Equatable { + case notRunning + case missingCSRFToken + case portDetectionFailed(String) + case apiError(String) + case parseFailed(String) + case timedOut + case authenticationRequired + case accountMismatch(expected: String?, found: String?) + + public var errorDescription: String? { + switch self { + case .notRunning: + "Antigravity language server not detected. Launch Antigravity and retry." + case .missingCSRFToken: + "Antigravity CSRF token not found. Restart Antigravity and retry." + case let .portDetectionFailed(message): + Self.portDetectionDescription(message) + case let .apiError(message): + Self.apiErrorDescription(message) + case let .parseFailed(message): + "Could not parse Antigravity quota: \(message)" + case .timedOut: + "Antigravity quota request timed out." + case .authenticationRequired: + "Antigravity CLI is signed out. Run agy in a terminal to sign in, then retry." + case let .accountMismatch(expected, found): + Self.accountMismatchDescription(expected: expected, found: found) + } + } + + private static func accountMismatchDescription(expected: String?, found: String?) -> String { + let selected = expected ?? "the selected account" + if let found { + return "Antigravity local session is signed in as \(found), not \(selected); " + + "using the selected account's OAuth data instead." + } + return "Antigravity local session did not report an account matching \(selected); " + + "using the selected account's OAuth data instead." + } + + private static func portDetectionDescription(_ message: String) -> String { + switch message { + case "lsof not available": + "Antigravity port detection needs lsof. Install it, then retry." + case "no listening ports found": + "Antigravity is running but not exposing ports yet. Try again in a few seconds." + default: + "Antigravity port detection failed: \(message)" + } + } + + private static func apiErrorDescription(_ message: String) -> String { + if message.contains("HTTP 401") || message.contains("HTTP 403") { + return "Antigravity session expired. Restart Antigravity and retry." + } + return "Antigravity API error: \(message)" + } +} + +public struct AntigravityStatusProbe: Sendable { + /// Which local Antigravity processes the probe may attach to. + public enum ProcessScope: Sendable { + /// Match Antigravity app, Antigravity IDE, and the `agy` CLI language server. + case ideAndCLI + /// Match only the Antigravity 2.0 app language server. + case appOnly + /// Match only the Antigravity IDE extension language server. + case ideOnly + } + + public var timeout: TimeInterval = 8.0 + public var processScope: ProcessScope = .ideAndCLI + + private static let getUserStatusPath = "/exa.language_server_pb.LanguageServerService/GetUserStatus" + private static let commandModelConfigPath = + "/exa.language_server_pb.LanguageServerService/GetCommandModelConfigs" + private static let quotaSummaryPath = + "/exa.language_server_pb.LanguageServerService/RetrieveUserQuotaSummary" + private static let unleashPath = "/exa.language_server_pb.LanguageServerService/GetUnleashData" + private static let log = CodexBarLog.logger(LogCategories.antigravity) + + public init(timeout: TimeInterval = 8.0, processScope: ProcessScope = .ideAndCLI) { + self.timeout = timeout + self.processScope = processScope + } + + public func fetch(matchingAccountEmail expectedAccountEmail: String? = nil) async throws + -> AntigravityStatusSnapshot + { + let deadline = Date().addingTimeInterval(self.timeout) + let processInfos = try await Self.detectProcessInfos(timeout: self.timeout, scope: self.processScope) + let result = try await Self.fetchProcessSnapshots(processInfos: processInfos) { processInfo in + try await Self.fetch( + processInfo: processInfo, + timeout: self.timeout, + deadline: deadline) + } + + if let bestSnapshot = Self.preferredLocalSnapshot( + result.snapshots, + matchingAccountEmail: expectedAccountEmail) + { + return bestSnapshot + } + throw result.lastError ?? AntigravityStatusProbeError.notRunning + } + + public func fetchPlanInfoSummary() async throws -> AntigravityPlanInfoSummary? { + let processInfo = try await Self.detectProcessInfo(timeout: self.timeout) + let ports = try await Self.listeningPorts(pid: processInfo.pid, timeout: self.timeout) + let endpoint = try await Self.resolveWorkingEndpoint( + candidateEndpoints: Self.connectionCandidates( + listeningPorts: ports, + languageServerCSRFToken: processInfo.csrfToken, + extensionServerPort: processInfo.extensionPort, + extensionServerCSRFToken: processInfo.extensionServerCSRFToken), + timeout: self.timeout) + return try await Self.makeParsedRequest( + payload: RequestPayload( + path: Self.getUserStatusPath, + body: Self.defaultRequestBody()), + context: RequestContext( + endpoints: Self.requestEndpoints( + resolvedEndpoint: endpoint, + listeningPorts: ports, + languageServerCSRFToken: processInfo.csrfToken, + extensionServerPort: processInfo.extensionPort, + extensionServerCSRFToken: processInfo.extensionServerCSRFToken), + timeout: self.timeout), + parse: Self.parsePlanInfoSummary) + } + + static func localSnapshotScore(_ snapshot: AntigravityStatusSnapshot) -> Int { + var score = 0 + if let quotaSummary = snapshot.quotaSummary { + let buckets = quotaSummary.groups.flatMap(\.buckets) + let knownBuckets = buckets.count(where: { !$0.disabled && $0.remainingFraction != nil }) + score += 1000 + score += quotaSummary.groups.count * 10 + score += buckets.count + score += knownBuckets * 20 + } else { + let knownRows = snapshot.modelQuotas.count(where: { $0.remainingFraction != nil }) + score += snapshot.modelQuotas.count + score += knownRows * 10 + } + if snapshot.accountEmail != nil { + score += 2 + } + if snapshot.accountPlan != nil { + score += 1 + } + return score + } + + public static func isRunning(timeout: TimeInterval = 4.0) async -> Bool { + await (try? self.detectProcessInfo(timeout: timeout)) != nil + } + + public static func detectVersion(timeout: TimeInterval = 4.0) async -> String? { + let running = await Self.isRunning(timeout: timeout) + return running ? "running" : nil + } + + // MARK: - CLI Local Fetch + + /// Fetch usage data from a known set of local ports (discovered via + /// ``AntigravityCLISession``'s ``pid``), without requiring a running + /// ``language_server`` process or CSRF token. + /// + /// The ``agy`` CLI exposes the same ``GetUserStatus`` gRPC-web endpoint as + /// the desktop ``language_server``. Unlike the desktop endpoint, it does + /// not require a CSRF token header. + public func fetchFromPorts(_ ports: [Int], deadline: Date? = nil) async throws -> AntigravityStatusSnapshot { + guard !ports.isEmpty else { + throw AntigravityStatusProbeError.portDetectionFailed("no listening ports found") + } + let endpoints = Self.cliEndpoints(ports: ports) + let context = RequestContext(endpoints: endpoints, timeout: self.timeout, deadline: deadline) + return try await Self.fetchSnapshot(context: context) + } + + // MARK: - Parsing + + public static func parseUserStatusResponse(_ data: Data) throws -> AntigravityStatusSnapshot { + let decoder = JSONDecoder() + let response = try decoder.decode(UserStatusResponse.self, from: data) + if let invalid = Self.invalidCode(response.code) { + throw AntigravityStatusProbeError.apiError(invalid) + } + guard let userStatus = response.userStatus else { + throw AntigravityStatusProbeError.parseFailed("Missing userStatus") + } + + let modelConfigs = userStatus.cascadeModelConfigData?.clientModelConfigs ?? [] + let models = modelConfigs.compactMap(Self.quotaFromConfig(_:)) + let email = userStatus.email + // Prefer userTier.name (actual subscription tier) over planInfo (shows "Pro" for Ultra users) + let planName = userStatus.userTier?.preferredName ?? userStatus.planStatus?.planInfo?.preferredName + + return AntigravityStatusSnapshot( + modelQuotas: models, + accountEmail: email, + accountPlan: planName, + source: .local) + } + + static func parsePlanInfoSummary(_ data: Data) throws -> AntigravityPlanInfoSummary? { + let decoder = JSONDecoder() + let response = try decoder.decode(UserStatusResponse.self, from: data) + if let invalid = Self.invalidCode(response.code) { + throw AntigravityStatusProbeError.apiError(invalid) + } + guard let userStatus = response.userStatus else { + throw AntigravityStatusProbeError.parseFailed("Missing userStatus") + } + guard let planInfo = userStatus.planStatus?.planInfo else { return nil } + return AntigravityPlanInfoSummary( + planName: planInfo.planName, + planDisplayName: planInfo.planDisplayName, + displayName: planInfo.displayName, + productName: planInfo.productName, + planShortName: planInfo.planShortName) + } + + static func parseCommandModelResponse(_ data: Data) throws -> AntigravityStatusSnapshot { + let decoder = JSONDecoder() + let response = try decoder.decode(CommandModelConfigResponse.self, from: data) + if let invalid = Self.invalidCode(response.code) { + throw AntigravityStatusProbeError.apiError(invalid) + } + let modelConfigs = response.clientModelConfigs ?? [] + let models = modelConfigs.compactMap(Self.quotaFromConfig(_:)) + return AntigravityStatusSnapshot(modelQuotas: models, accountEmail: nil, accountPlan: nil, source: .local) + } + + private static func quotaFromConfig(_ config: ModelConfig) -> AntigravityModelQuota? { + guard let quota = config.quotaInfo else { return nil } + let reset = quota.resetTime.flatMap { Self.parseDate($0) } + return AntigravityModelQuota( + label: config.label, + modelId: config.modelOrAlias.model, + remainingFraction: quota.remainingFraction, + resetTime: reset, + resetDescription: nil) + } + + static func invalidCode(_ code: CodeValue?) -> String? { + guard let code else { return nil } + if code.isOK { return nil } + return "\(code.rawValue)" + } + + static func parseDate(_ value: String) -> Date? { + if let date = ISO8601DateFormatter().date(from: value) { + return date + } + if let seconds = Double(value) { + return Date(timeIntervalSince1970: seconds) + } + return nil + } + + // MARK: - Port detection + + struct ProcessInfoResult { + let pid: Int + let extensionPort: Int? + let extensionServerCSRFToken: String? + let csrfToken: String + let commandLine: String + } + + struct AntigravityConnectionEndpoint: Equatable { + enum Source: String { + case languageServer = "language-server" + case extensionServer = "extension-server" + case cliHTTPS = "cli-https" + } + + let scheme: String + let port: Int + let csrfToken: String + let source: Source + /// Whether this endpoint needs a CSRF token header. + /// The CLI HTTPS endpoint (``Source/cliHTTPS``) speaks the same HTTP API + /// but does not require a CSRF token. + var requiresCSRFToken: Bool { + switch self.source { + case .languageServer, .extensionServer: true + case .cliHTTPS: false + } + } + + func matchesRequestTarget(_ other: Self) -> Bool { + self.scheme == other.scheme && self.port == other.port && self.csrfToken == other.csrfToken + } + } + + private static func detectProcessInfo( + timeout: TimeInterval, + scope: ProcessScope = .ideAndCLI) async throws -> ProcessInfoResult + { + let processInfos = try await self.detectProcessInfos(timeout: timeout, scope: scope) + guard let first = processInfos.first else { + throw AntigravityStatusProbeError.notRunning + } + return first + } + + /// Internal (not private): called by AntigravityCLIHTTPSFetchStrategy + /// .liveWarmAgyDependencies to discover an already-running `agy` for reuse. + static func detectProcessInfos( + timeout: TimeInterval, + scope: ProcessScope = .ideAndCLI) async throws -> [ProcessInfoResult] + { + let env = ProcessInfo.processInfo.environment + let result = try await SubprocessRunner.run( + binary: "/bin/ps", + arguments: ["-ax", "-o", "pid=,command="], + environment: env, + timeout: timeout, + label: "antigravity-ps") + + return try Self.processInfos(fromProcessListOutput: result.stdout, scope: scope) + } + + static func processInfo( + fromProcessListOutput output: String, + scope: ProcessScope = .ideAndCLI) throws -> ProcessInfoResult + { + let processInfos = try self.processInfos(fromProcessListOutput: output, scope: scope) + guard let first = processInfos.first else { + throw AntigravityStatusProbeError.notRunning + } + return first + } + + static func processInfos( + fromProcessListOutput output: String, + scope: ProcessScope = .ideAndCLI) throws -> [ProcessInfoResult] + { + let lines = output.split(separator: "\n") + var sawTokenlessIDE = false + var results: [ProcessInfoResult] = [] + for line in lines { + let text = String(line) + guard let match = Self.matchProcessLine(text) else { continue } + guard let kind = Self.antigravityProcessKind(match.command) else { continue } + if !Self.processKind(kind, matches: scope) { continue } + // The IDE language server authenticates local requests with a + // `--csrf_token` and must keep requiring it: skip a tokenless IDE + // or app match so a later valid server can still be found (and surface + // `missingCSRFToken` if none is). The CLI's language server exposes + // no token flag and needs none, so an empty token is allowed there. + guard let token = Self.resolvedCSRFToken(forKind: kind, command: match.command) else { + sawTokenlessIDE = true + continue + } + let port = Self.extractPort("--extension_server_port", from: match.command) + let extensionServerCSRFToken = Self.extractFlag("--extension_server_csrf_token", from: match.command) + results.append(ProcessInfoResult( + pid: match.pid, + extensionPort: port, + extensionServerCSRFToken: extensionServerCSRFToken, + csrfToken: token, + commandLine: match.command)) + } + + if !results.isEmpty { + return results + } + if sawTokenlessIDE { + throw AntigravityStatusProbeError.missingCSRFToken + } + throw AntigravityStatusProbeError.notRunning + } + + private struct ProcessLineMatch { + let pid: Int + let command: String + } + + private static func matchProcessLine(_ line: String) -> ProcessLineMatch? { + let trimmed = line.trimmingCharacters(in: .whitespacesAndNewlines) + guard !trimmed.isEmpty else { return nil } + let parts = trimmed.split(separator: " ", maxSplits: 1, omittingEmptySubsequences: true) + guard parts.count == 2, let pid = Int(parts[0]) else { return nil } + return ProcessLineMatch(pid: pid, command: String(parts[1])) + } + + enum AntigravityProcessKind: Equatable { + /// Antigravity 2.0 app language server. Requires a `--csrf_token`. + case app + /// Antigravity IDE extension language server. Requires a `--csrf_token`. + case ide + /// CLI language server (`agy` / `antigravity-cli`). Needs no CSRF token. + case cli + } + + static func isAntigravityLanguageServerCommandLine(_ command: String) -> Bool { + self.antigravityProcessKind(command) != nil + } + + /// Classify a process command line as the Antigravity app language server, + /// the Antigravity IDE language server, the Antigravity CLI language server, + /// or neither. Desktop language servers take precedence so their CSRF-token + /// requirement is preserved. + static func antigravityProcessKind(_ command: String) -> AntigravityProcessKind? { + let lower = command.lowercased() + if Self.isLanguageServerCommandLine(lower), Self.isAntigravityCommandLine(lower) { + return Self.isAntigravityIDECommandLine(lower) ? .ide : .app + } + if Self.isAntigravityCLICommandLine(lower) { + return .cli + } + return nil + } + + private static func processKind(_ kind: AntigravityProcessKind, matches scope: ProcessScope) -> Bool { + switch scope { + case .ideAndCLI: + true + case .appOnly: + kind == .app + case .ideOnly: + kind == .ide + } + } + + /// Resolve the CSRF token to use for a matched process, or `nil` when the + /// match must be skipped. IDE matches keep requiring `--csrf_token` + /// (tokenless IDE matches are skipped). CLI matches accept an empty token + /// because the CLI's language server requires none. + static func resolvedCSRFToken(forKind kind: AntigravityProcessKind, command: String) -> String? { + if let token = extractFlag("--csrf_token", from: command) { + return token + } + switch kind { + case .app, .ide: return nil + case .cli: return "" + } + } + + private static func isLanguageServerCommandLine(_ lowerCommand: String) -> Bool { + let pattern = #"(^|[/\\])language(?:_|-)server(?:[_-][a-z0-9]+)*(?:\.exe)?(\s|$)"# + return lowerCommand.range(of: pattern, options: .regularExpression) != nil + } + + /// The Antigravity CLI (`agy` / `antigravity-cli`) hosts the same language + /// server locally as the IDE, but launches it without a `--csrf_token` flag + /// and under a different process name. Match it so usage can be probed when + /// only the CLI is running. + private static func isAntigravityCLICommandLine(_ lowerCommand: String) -> Bool { + let cliPathPattern = #"(^|[/\\])(antigravity-cli|antigravity_cli)([\s/\\]|$)"# + if lowerCommand.range(of: cliPathPattern, options: .regularExpression) != nil { + return true + } + let agyPattern = #"(^|[/\\])agy(\s|$)"# + return lowerCommand.range(of: agyPattern, options: .regularExpression) != nil + } + + private static func isAntigravityCommandLine(_ command: String) -> Bool { + if command.contains("--app_data_dir") && command.contains("antigravity") { return true } + if command.contains("antigravity.app/") || command.contains("antigravity.app\\") { return true } + if command.contains("antigravity ide.app/") || command.contains("antigravity ide.app\\") { return true } + if command.contains("/antigravity/") || command.contains("\\antigravity\\") { return true } + return false + } + + private static func isAntigravityIDECommandLine(_ lowerCommand: String) -> Bool { + [ + "antigravity ide.app/", + "antigravity ide.app\\", + "--app_data_dir antigravity-ide", + "--app_data_dir=antigravity-ide", + "/extensions/antigravity/bin/language_server", + "\\extensions\\antigravity\\bin\\language_server", + ].contains { lowerCommand.contains($0) } + } + + private static func extractFlag(_ flag: String, from command: String) -> String? { + let pattern = "\(NSRegularExpression.escapedPattern(for: flag))[=\\s]+([^\\s]+)" + guard let regex = try? NSRegularExpression(pattern: pattern, options: .caseInsensitive) else { return nil } + let range = NSRange(command.startIndex.. Int? { + guard let raw = extractFlag(flag, from: command) else { return nil } + return Int(raw) + } + + static func connectionCandidates( + listeningPorts: [Int], + languageServerCSRFToken: String, + extensionServerPort: Int?, + extensionServerCSRFToken: String?) -> [AntigravityConnectionEndpoint] + { + var endpoints = Self.languageServerEndpoints( + listeningPorts: listeningPorts, + languageServerCSRFToken: languageServerCSRFToken) + + for endpoint in Self.extensionServerEndpoints( + extensionServerPort: extensionServerPort, + languageServerCSRFToken: languageServerCSRFToken, + extensionServerCSRFToken: extensionServerCSRFToken) + { + guard !endpoints.contains(where: { $0.matchesRequestTarget(endpoint) }) else { continue } + endpoints.append(endpoint) + } + + return endpoints + } + + static func requestEndpoints( + resolvedEndpoint: AntigravityConnectionEndpoint, + listeningPorts: [Int], + languageServerCSRFToken: String, + extensionServerPort: Int?, + extensionServerCSRFToken: String?) -> [AntigravityConnectionEndpoint] + { + var endpoints = [resolvedEndpoint] + + if resolvedEndpoint.source == .extensionServer { + Self.appendUniqueRequestTargets( + from: Self.extensionServerEndpoints( + extensionServerPort: extensionServerPort, + languageServerCSRFToken: languageServerCSRFToken, + extensionServerCSRFToken: extensionServerCSRFToken), + to: &endpoints) + Self.appendUniqueRequestTargets( + from: Self.languageServerEndpoints( + listeningPorts: listeningPorts, + languageServerCSRFToken: languageServerCSRFToken), + to: &endpoints) + } else { + Self.appendUniqueRequestTargets( + from: Self.languageServerEndpoints( + listeningPorts: listeningPorts, + languageServerCSRFToken: languageServerCSRFToken), + to: &endpoints) + Self.appendUniqueRequestTargets( + from: Self.extensionServerEndpoints( + extensionServerPort: extensionServerPort, + languageServerCSRFToken: languageServerCSRFToken, + extensionServerCSRFToken: extensionServerCSRFToken), + to: &endpoints) + } + + return endpoints + } + + private static func languageServerEndpoints( + listeningPorts: [Int], + languageServerCSRFToken: String) -> [AntigravityConnectionEndpoint] + { + listeningPorts.flatMap { port in + self.localProbeSchemes.map { scheme in + AntigravityConnectionEndpoint( + scheme: scheme, + port: port, + csrfToken: languageServerCSRFToken, + source: .languageServer) + } + } + } + + private static func extensionServerEndpoints( + extensionServerPort: Int?, + languageServerCSRFToken: String, + extensionServerCSRFToken: String?) -> [AntigravityConnectionEndpoint] + { + guard let extensionServerPort else { return [] } + + var endpoints: [AntigravityConnectionEndpoint] = [] + if let extensionServerCSRFToken { + endpoints.append( + AntigravityConnectionEndpoint( + scheme: "http", + port: extensionServerPort, + csrfToken: extensionServerCSRFToken, + source: .extensionServer)) + } + + if extensionServerCSRFToken != languageServerCSRFToken { + endpoints.append( + AntigravityConnectionEndpoint( + scheme: "http", + port: extensionServerPort, + csrfToken: languageServerCSRFToken, + source: .extensionServer)) + } + + return endpoints + } + + private static func appendUniqueRequestTargets( + from candidates: [AntigravityConnectionEndpoint], + to endpoints: inout [AntigravityConnectionEndpoint]) + { + for endpoint in candidates { + guard !endpoints.contains(where: { $0.matchesRequestTarget(endpoint) }) else { continue } + endpoints.append(endpoint) + } + } + + static func resolveWorkingEndpoint( + candidateEndpoints: [AntigravityConnectionEndpoint], + timeout: TimeInterval, + deadline: Date? = nil, + testConnectivity: @escaping @Sendable (AntigravityConnectionEndpoint, TimeInterval) async -> Bool = Self + .testEndpointConnectivity) async throws -> AntigravityConnectionEndpoint + { + for (index, endpoint) in candidateEndpoints.enumerated() { + let remainingAttemptCount = candidateEndpoints.count - index + guard let attemptTimeout = timeoutForEndpointAttempt( + timeout: timeout, + deadline: deadline, + remainingAttemptCount: remainingAttemptCount) + else { + throw AntigravityStatusProbeError.timedOut + } + let ok = await testConnectivity(endpoint, attemptTimeout) + if ok { return endpoint } + } + if let fallback = fallbackProbeEndpoint(candidateEndpoints) { + self.log.debug("Port probe fell back to best-effort endpoint", metadata: [ + "source": fallback.source.rawValue, + "scheme": fallback.scheme, + "port": "\(fallback.port)", + ]) + return fallback + } + throw AntigravityStatusProbeError.portDetectionFailed("no working API port found") + } + + private static func timeoutForEndpointAttempt( + timeout: TimeInterval, + deadline: Date?, + remainingAttemptCount: Int) -> TimeInterval? + { + guard let deadline else { return timeout } + let remaining = deadline.timeIntervalSinceNow + guard remaining > 0 else { return nil } + return min(timeout, remaining / Double(max(1, remainingAttemptCount))) + } + + static func fallbackProbePort(ports: [Int], extensionPort: Int?) -> Int? { + if let nonExtension = ports.first(where: { $0 != extensionPort }) { + return nonExtension + } + if let extensionPort { + return extensionPort + } + return ports.first + } + + static func isReachableProbeError(_ error: Error) -> Bool { + guard case let AntigravityStatusProbeError.apiError(message) = error else { return false } + return message.hasPrefix("HTTP ") + } + + private static func fallbackProbeEndpoint( + _ endpoints: [AntigravityConnectionEndpoint]) -> AntigravityConnectionEndpoint? + { + if let languageServerEndpoint = endpoints.first(where: { $0.source == .languageServer }) { + return languageServerEndpoint + } + return endpoints.first + } + + private static func testEndpointConnectivity( + _ endpoint: AntigravityConnectionEndpoint, + timeout: TimeInterval) async -> Bool + { + do { + _ = try await self.makeRequest( + payload: RequestPayload( + path: self.unleashPath, + body: self.unleashRequestBody()), + context: RequestContext(endpoints: [endpoint], timeout: timeout)) + return true + } catch { + if self.isReachableProbeError(error) { + self.log.debug("Port probe received HTTP response; treating endpoint as reachable", metadata: [ + "source": endpoint.source.rawValue, + "scheme": endpoint.scheme, + "port": "\(endpoint.port)", + "error": error.localizedDescription, + ]) + return true + } + self.log.debug("Port probe failed", metadata: [ + "source": endpoint.source.rawValue, + "scheme": endpoint.scheme, + "port": "\(endpoint.port)", + "error": error.localizedDescription, + ]) + return false + } + } + + // MARK: - HTTP + + struct RequestPayload { + let path: String + let body: [String: Any] + } + + struct RequestContext { + let endpoints: [AntigravityConnectionEndpoint] + let timeout: TimeInterval + let deadline: Date? + + init(endpoints: [AntigravityConnectionEndpoint], timeout: TimeInterval, deadline: Date? = nil) { + self.endpoints = endpoints + self.timeout = timeout + self.deadline = deadline + } + + func timeoutForNextAttempt() -> TimeInterval? { + AntigravityStatusProbe.timeoutForNextAttempt(timeout: self.timeout, deadline: self.deadline) + } + } + + private static func defaultRequestBody() -> [String: Any] { + [ + "metadata": [ + "ideName": "antigravity", + "extensionName": "antigravity", + "ideVersion": "unknown", + "locale": "en", + ], + ] + } + + private static func unleashRequestBody() -> [String: Any] { + [ + "context": [ + "properties": [ + "devMode": "false", + "extensionVersion": "unknown", + "hasAnthropicModelAccess": "true", + "ide": "antigravity", + "ideVersion": "unknown", + "installationId": "codexbar", + "language": "UNSPECIFIED", + "os": "macos", + "requestedModelId": "MODEL_UNSPECIFIED", + ], + ], + ] + } + + static func fetchSnapshot( + context: RequestContext, + send: @escaping @Sendable (RequestPayload, AntigravityConnectionEndpoint, TimeInterval) async throws -> Data = + sendRequest) async throws -> AntigravityStatusSnapshot + { + do { + let quotaSummary = try await self.makeParsedRequest( + payload: RequestPayload( + path: self.quotaSummaryPath, + body: ["forceRefresh": true]), + context: self.quotaSummaryRequestContext(from: context), + send: send, + parse: self.parseQuotaSummaryResponse) + guard quotaSummary.quotaSummary?.groups.contains(where: { group in + group.buckets.contains { !$0.disabled && $0.remainingFraction != nil } + }) == true else { + throw AntigravityStatusProbeError.parseFailed("Quota summary has no usable quota buckets") + } + let identity = try? await self.makeParsedRequest( + payload: RequestPayload( + path: self.getUserStatusPath, + body: self.defaultRequestBody()), + context: self.identityRequestContext(from: context), + send: send, + parse: self.parseUserStatusResponse) + return quotaSummary.withIdentity(from: identity) + } catch { + self.log.debug("Antigravity quota summary unavailable; falling back to model quotas", metadata: [ + "error": error.localizedDescription, + ]) + } + + do { + return try await self.makeParsedRequest( + payload: RequestPayload( + path: self.getUserStatusPath, + body: self.defaultRequestBody()), + context: self.legacyUserStatusRequestContext(from: context), + send: send, + parse: self.parseUserStatusResponse) + } catch { + return try await self.makeParsedRequest( + payload: RequestPayload( + path: self.commandModelConfigPath, + body: self.defaultRequestBody()), + context: context, + send: send, + parse: self.parseCommandModelResponse) + } + } + + private static func legacyUserStatusRequestContext(from context: RequestContext) -> RequestContext { + guard let deadline = context.deadline else { return context } + let remaining = max(0, deadline.timeIntervalSinceNow) + let userStatusBudget = remaining / 2 + return RequestContext( + endpoints: context.endpoints, + timeout: min(context.timeout, userStatusBudget), + deadline: Date().addingTimeInterval(userStatusBudget)) + } + + private static func quotaSummaryRequestContext(from context: RequestContext) -> RequestContext { + guard let deadline = context.deadline else { return context } + let remaining = max(0, deadline.timeIntervalSinceNow) + let quotaSummaryBudget = remaining / 2 + return RequestContext( + endpoints: context.endpoints, + timeout: min(context.timeout, quotaSummaryBudget), + deadline: Date().addingTimeInterval(quotaSummaryBudget)) + } + + private static func identityRequestContext(from context: RequestContext) -> RequestContext { + RequestContext( + endpoints: context.endpoints, + timeout: min(context.timeout, 1), + deadline: context.deadline) + } + + private static func makeRequest( + payload: RequestPayload, + context: RequestContext) async throws -> Data + { + try await self.sendRequest(payload: payload, context: context) + } + + static func makeParsedRequest( + payload: RequestPayload, + context: RequestContext, + send: @escaping @Sendable (RequestPayload, AntigravityConnectionEndpoint, TimeInterval) async throws -> Data = + sendRequest, + parse: @escaping @Sendable (Data) throws -> T) async throws -> T + { + var lastError: Error? + + for endpoint in context.endpoints { + guard let timeout = context.timeoutForNextAttempt() else { + lastError = lastError ?? AntigravityStatusProbeError.timedOut + break + } + do { + let data = try await send(payload, endpoint, timeout) + return try parse(data) + } catch { + lastError = error + Self.log.debug("Antigravity request/parse attempt failed", metadata: [ + "path": payload.path, + "source": endpoint.source.rawValue, + "scheme": endpoint.scheme, + "port": "\(endpoint.port)", + "error": error.localizedDescription, + ]) + } + } + + throw lastError ?? AntigravityStatusProbeError.apiError("Invalid response") + } + + private static func sendRequest( + payload: RequestPayload, + context: RequestContext) async throws -> Data + { + var lastError: Error? + + for endpoint in context.endpoints { + guard let timeout = context.timeoutForNextAttempt() else { + lastError = lastError ?? AntigravityStatusProbeError.timedOut + break + } + do { + return try await Self.sendRequest(payload: payload, endpoint: endpoint, timeout: timeout) + } catch { + lastError = error + Self.log.debug("Antigravity request attempt failed", metadata: [ + "path": payload.path, + "source": endpoint.source.rawValue, + "scheme": endpoint.scheme, + "port": "\(endpoint.port)", + "error": error.localizedDescription, + ]) + } + } + + throw lastError ?? AntigravityStatusProbeError.apiError("Invalid URL") + } + + private static func sendRequest( + payload: RequestPayload, + endpoint: AntigravityConnectionEndpoint, + timeout: TimeInterval) async throws -> Data + { + guard let url = URL(string: "\(endpoint.scheme)://127.0.0.1:\(endpoint.port)\(payload.path)") else { + throw AntigravityStatusProbeError.apiError("Invalid URL") + } + + let body = try JSONSerialization.data(withJSONObject: payload.body, options: []) + var request = URLRequest(url: url) + request.httpMethod = "POST" + request.httpBody = body + request.timeoutInterval = timeout + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + request.setValue(String(body.count), forHTTPHeaderField: "Content-Length") + request.setValue("1", forHTTPHeaderField: "Connect-Protocol-Version") + if endpoint.requiresCSRFToken { + request.setValue(endpoint.csrfToken, forHTTPHeaderField: "X-Codeium-Csrf-Token") + } + + let config = URLSessionConfiguration.ephemeral + config.timeoutIntervalForRequest = timeout + config.timeoutIntervalForResource = timeout + #if !os(Linux) + config.waitsForConnectivity = false + #endif + + let delegate = LocalhostSessionDelegate() + let session = URLSession(configuration: config, delegate: delegate, delegateQueue: nil) + defer { session.invalidateAndCancel() } + + let (data, response) = try await delegate.data(for: request, session: session) + guard let http = response as? HTTPURLResponse else { + throw AntigravityStatusProbeError.apiError("Invalid response") + } + guard http.statusCode == 200 else { + let message = String(data: data, encoding: .utf8) ?? "" + throw AntigravityStatusProbeError.apiError("HTTP \(http.statusCode): \(message)") + } + return data + } +} diff --git a/Sources/CodexBarCore/Providers/Antigravity/AntigravityUsageDataSource.swift b/Sources/CodexBarCore/Providers/Antigravity/AntigravityUsageDataSource.swift new file mode 100644 index 0000000..60136c6 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Antigravity/AntigravityUsageDataSource.swift @@ -0,0 +1,30 @@ +import Foundation + +public enum AntigravityUsageDataSource: String, CaseIterable, Identifiable, Sendable { + case auto + case oauth + case cli + + public var id: String { + self.rawValue + } + + public var displayName: String { + switch self { + case .auto: "Auto" + case .oauth: "Google OAuth" + case .cli: "Local API / agy CLI" + } + } + + public var sourceLabel: String { + switch self { + case .auto: + "auto" + case .oauth: + "oauth" + case .cli: + "cli" + } + } +} diff --git a/Sources/CodexBarCore/Providers/Augment/AuggieCLIProbe.swift b/Sources/CodexBarCore/Providers/Augment/AuggieCLIProbe.swift new file mode 100644 index 0000000..ddbb6de --- /dev/null +++ b/Sources/CodexBarCore/Providers/Augment/AuggieCLIProbe.swift @@ -0,0 +1,191 @@ +import Foundation + +#if os(macOS) + +/// Fetches Augment usage via `auggie account status` CLI command +public struct AuggieCLIProbe: Sendable { + private static let log = CodexBarLog.logger(LogCategories.auggieCLI) + + public init() {} + + public func fetch() async throws -> AugmentStatusSnapshot { + let output = try await self.runAuggieAccountStatus() + return try self.parse(output) + } + + /// Timeout for the `auggie account status` command. + private static let commandTimeout: TimeInterval = 15 + + private func runAuggieAccountStatus() async throws -> String { + let env = ProcessInfo.processInfo.environment + let loginPATH = LoginShellPathCache.shared.current + let executable = BinaryLocator.resolveAuggieBinary(env: env, loginPATH: loginPATH) ?? "auggie" + + var pathEnv = env + pathEnv["PATH"] = PathBuilder.effectivePATH( + purposes: [.tty, .nodeTooling], + env: env, + loginPATH: loginPATH) + + let result = try await SubprocessRunner.run( + binary: executable, + arguments: ["account", "status"], + environment: pathEnv, + timeout: Self.commandTimeout, + label: "auggie-account-status") + + let output = result.stdout + let errorOutput = result.stderr + + guard !output.isEmpty else { + if !errorOutput.isEmpty { + Self.log.error("Auggie stderr: \(errorOutput)") + } + throw AuggieCLIError.noOutput + } + + // Check for auth errors + if output.contains("Authentication failed") || output.contains("auggie login") { + throw AuggieCLIError.notAuthenticated + } + + return output + } + + func parse(_ output: String) throws -> AugmentStatusSnapshot { + // Legacy output: + // Max Plan 450,000 credits / month + // 11,657 remaining · 953,170 / 964,827 credits used + // 2 days remaining in this billing cycle (ends 1/8/2026) + // + // Current output (2026+): + // 319,054 credits remaining Max Plan + // 450,000 credits / month + // 9 days remaining in this billing cycle (ends 6/9/2026) + + var maxCredits: Int? + var remaining: Int? + var used: Int? + var total: Int? + var billingCycleEnd: Date? + + for line in output.split(separator: "\n") { + let trimmed = line.trimmingCharacters(in: .whitespaces) + + if trimmed.contains("credits / month") { + if let match = trimmed.range(of: #"([\d,]+)\s+credits\s*/\s*month"#, options: .regularExpression) { + let numberStr = String(trimmed[match]).replacingOccurrences(of: ",", with: "") + .replacingOccurrences(of: " credits", with: "") + .replacingOccurrences(of: " / month", with: "") + maxCredits = Int(numberStr) + total = total ?? Int(numberStr) + } + } else if trimmed.contains("Max Plan"), trimmed.contains("credits"), !trimmed.contains("remaining") { + if let match = trimmed.range(of: #"([\d,]+)\s+credits"#, options: .regularExpression) { + let numberStr = String(trimmed[match]).replacingOccurrences(of: ",", with: "") + .replacingOccurrences(of: " credits", with: "") + maxCredits = Int(numberStr) + } + } + + if trimmed.contains("credits remaining"), !trimmed.contains("billing cycle") { + if let match = trimmed.range(of: #"([\d,]+)\s+credits\s+remaining"#, options: .regularExpression) { + let numberStr = String(trimmed[match]).replacingOccurrences(of: ",", with: "") + .replacingOccurrences(of: " credits", with: "") + .replacingOccurrences(of: " remaining", with: "") + remaining = Int(numberStr) + } + } + + // Parse "11,657 remaining · 953,170 / 964,827 credits used" + if trimmed.contains("remaining"), trimmed.contains("credits used") { + if let remMatch = trimmed.range(of: #"([\d,]+)\s+remaining"#, options: .regularExpression) { + let numStr = String(trimmed[remMatch]) + .replacingOccurrences(of: ",", with: "") + .replacingOccurrences(of: " remaining", with: "") + remaining = Int(numStr) + } + + if let usedMatch = trimmed.range( + of: #"([\d,]+)\s*/\s*([\d,]+)\s+credits used"#, + options: .regularExpression) + { + let parts = String(trimmed[usedMatch]) + .replacingOccurrences(of: " credits used", with: "") + .split(separator: "/") + if parts.count == 2 { + used = Int(parts[0].replacingOccurrences(of: ",", with: "") + .trimmingCharacters(in: .whitespaces)) + total = Int(parts[1].replacingOccurrences(of: ",", with: "") + .trimmingCharacters(in: .whitespaces)) + } + } + } + + if trimmed.contains("billing cycle"), trimmed.contains("ends") { + if let dateMatch = trimmed.range(of: #"ends\s+([\d/]+)"#, options: .regularExpression) { + let dateStr = String(trimmed[dateMatch]) + .replacingOccurrences(of: "ends", with: "") + .trimmingCharacters(in: .whitespaces) + + let formatter = DateFormatter() + formatter.dateFormat = "M/d/yyyy" + formatter.locale = Locale(identifier: "en_US_POSIX") + formatter.timeZone = TimeZone.current + billingCycleEnd = formatter.date(from: dateStr) + } + } + } + + guard let finalRemaining = remaining else { + Self.log.error("Failed to parse auggie output: \(output)") + throw AuggieCLIError.parseError("Could not extract credits from output") + } + + let finalTotal = total ?? maxCredits + guard let finalTotal else { + Self.log.error("Failed to parse auggie output: \(output)") + throw AuggieCLIError.parseError("Could not extract credits from output") + } + + let finalUsed = used ?? max(0, finalTotal - finalRemaining) + + return AugmentStatusSnapshot( + creditsRemaining: Double(finalRemaining), + creditsUsed: Double(finalUsed), + creditsLimit: Double(finalTotal), + billingCycleEnd: billingCycleEnd, + accountEmail: nil, + accountPlan: maxCredits.map { "\($0.formatted()) credits/month" }, + rawJSON: nil) + } +} + +#else + +public struct AuggieCLIProbe: Sendable { + public init() {} + + public func fetch() async throws -> AugmentStatusSnapshot { + throw AugmentStatusProbeError.notSupported + } +} + +#endif + +public enum AuggieCLIError: LocalizedError { + case noOutput + case notAuthenticated + case parseError(String) + + public var errorDescription: String? { + switch self { + case .noOutput: + "Auggie CLI returned no output" + case .notAuthenticated: + "Not authenticated. Run 'auggie login' to authenticate." + case let .parseError(msg): + "Failed to parse auggie output: \(msg)" + } + } +} diff --git a/Sources/CodexBarCore/Providers/Augment/AugmentProviderDescriptor.swift b/Sources/CodexBarCore/Providers/Augment/AugmentProviderDescriptor.swift new file mode 100644 index 0000000..529bd39 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Augment/AugmentProviderDescriptor.swift @@ -0,0 +1,133 @@ +import Foundation + +#if os(macOS) +import SweetCookieKit +#endif + +public enum AugmentProviderDescriptor { + public static let descriptor: ProviderDescriptor = Self.makeDescriptor() + + static func makeDescriptor() -> ProviderDescriptor { + #if os(macOS) + // Custom browser order that includes Chrome Beta and other variants + // to support users running beta/canary versions + let browserOrder: BrowserCookieImportOrder = [ + .safari, + .chrome, + .chromeBeta, // Added for Chrome Beta support + .chromeCanary, // Added for Chrome Canary support + .edge, + .edgeBeta, + .brave, + .arc, + .dia, + .arcBeta, + .firefox, + ] + #else + let browserOrder: BrowserCookieImportOrder? = nil + #endif + + return ProviderDescriptor( + id: .augment, + metadata: ProviderMetadata( + id: .augment, + displayName: "Augment", + sessionLabel: "Credits", + weeklyLabel: "Usage", + opusLabel: nil, + supportsOpus: false, + supportsCredits: true, + creditsHint: "Augment Code credits for AI-powered coding assistance.", + toggleTitle: "Show Augment usage", + cliName: "augment", + defaultEnabled: false, + isPrimaryProvider: false, + usesAccountFallback: false, + browserCookieOrder: browserOrder, + dashboardURL: "https://app.augmentcode.com/account/subscription", + statusPageURL: "https://status.augmentcode.com"), + branding: ProviderBranding( + iconStyle: .augment, + iconResourceName: "ProviderIcon-augment", + color: ProviderColor(red: 99 / 255, green: 102 / 255, blue: 241 / 255)), + tokenCost: ProviderTokenCostConfig( + supportsTokenCost: false, + noDataMessage: { "Augment cost summary is not supported." }), + fetchPlan: ProviderFetchPlan( + sourceModes: [.auto, .cli], + pipeline: ProviderFetchPipeline(resolveStrategies: { _ in + var strategies: [any ProviderFetchStrategy] = [] + // Try CLI first (no browser prompts!) + strategies.append(AugmentCLIFetchStrategy()) + // Fallback to web (browser cookies) + strategies.append(AugmentStatusFetchStrategy()) + return strategies + })), + cli: ProviderCLIConfig( + name: "augment", + versionDetector: nil)) + } +} + +struct AugmentCLIFetchStrategy: ProviderFetchStrategy { + let id: String = "augment.cli" + let kind: ProviderFetchKind = .cli + + func isAvailable(_ context: ProviderFetchContext) async -> Bool { + // Check if auggie CLI is installed + let env = ProcessInfo.processInfo.environment + let loginPATH = LoginShellPathCache.shared.current + return BinaryLocator.resolveAuggieBinary(env: env, loginPATH: loginPATH) != nil + } + + func fetch(_ context: ProviderFetchContext) async throws -> ProviderFetchResult { + let probe = AuggieCLIProbe() + let snap = try await probe.fetch() + return self.makeResult( + usage: snap.toUsageSnapshot(), + sourceLabel: "cli") + } + + func shouldFallback(on error: Error, context _: ProviderFetchContext) -> Bool { + // Fallback to web if CLI fails (not authenticated, etc.) + if let cliError = error as? AuggieCLIError { + switch cliError { + case .notAuthenticated, .noOutput, .parseError: + return true + } + } + return true + } +} + +struct AugmentStatusFetchStrategy: ProviderFetchStrategy { + let id: String = "augment.web" + let kind: ProviderFetchKind = .web + + func isAvailable(_ context: ProviderFetchContext) async -> Bool { + guard context.settings?.augment?.cookieSource != .off else { return false } + return true + } + + func fetch(_ context: ProviderFetchContext) async throws -> ProviderFetchResult { + let probe = AugmentStatusProbe() + let manual = Self.manualCookieHeader(from: context) + let logger: ((String) -> Void)? = context.verbose + ? { msg in CodexBarLog.logger(LogCategories.augment).verbose(msg) } + : nil + let snap = try await probe.fetch(cookieHeaderOverride: manual, logger: logger) + return self.makeResult( + usage: snap.toUsageSnapshot(), + sourceLabel: "web") + } + + func shouldFallback(on _: Error, context _: ProviderFetchContext) -> Bool { + false + } + + private static func manualCookieHeader(from context: ProviderFetchContext) -> String? { + guard context.settings?.augment?.cookieSource == .manual else { return nil } + return CookieHeaderNormalizer.normalize(context.settings?.augment?.manualCookieHeader) + } +} diff --git a/Sources/CodexBarCore/Providers/Augment/AugmentSessionKeepalive.swift b/Sources/CodexBarCore/Providers/Augment/AugmentSessionKeepalive.swift new file mode 100644 index 0000000..7ffa2ae --- /dev/null +++ b/Sources/CodexBarCore/Providers/Augment/AugmentSessionKeepalive.swift @@ -0,0 +1,491 @@ +import Foundation + +#if os(macOS) +import AppKit +import UserNotifications + +/// Manages automatic session keepalive for Augment to prevent cookie expiration. +/// +/// This actor monitors cookie expiration and proactively refreshes the session +/// before cookies expire, ensuring uninterrupted access to Augment APIs. +@MainActor +public final class AugmentSessionKeepalive { + // MARK: - Configuration + + /// How often to check if session needs refresh (default: 1 minute for faster recovery) + private let checkInterval: TimeInterval = 60 + + /// Refresh session this many seconds before cookie expiration (default: 5 minutes) + private let refreshBufferSeconds: TimeInterval = 300 + + /// Minimum time between refresh attempts (default: 1 minute for faster recovery) + private let minRefreshInterval: TimeInterval = 60 + + /// Maximum time to wait for session refresh (default: 30 seconds) + private let refreshTimeout: TimeInterval = 30 + + // MARK: - State + + private var timerTask: Task? + private var lastRefreshAttempt: Date? + private var lastSuccessfulRefresh: Date? + private var isRefreshing = false + private let logger: ((String) -> Void)? + private var onSessionRecovered: (() async -> Void)? + + /// Track consecutive failures to stop retrying after too many failures + private var consecutiveFailures = 0 + private let maxConsecutiveFailures = 3 // Stop after 3 failures + private var hasGivenUp = false + + // MARK: - Initialization + + public init(logger: ((String) -> Void)? = nil, onSessionRecovered: (() async -> Void)? = nil) { + self.logger = logger + self.onSessionRecovered = onSessionRecovered + } + + deinit { + self.timerTask?.cancel() + } + + // MARK: - Public API + + /// Start the automatic session keepalive timer + public func start() { + guard self.timerTask == nil else { + self.log("Keepalive already running") + return + } + + self.log("🚀 Starting Augment session keepalive") + self.log( + " - Check interval: \(Int(self.checkInterval))s " + + "(\(Self.durationDescription(seconds: self.checkInterval)))") + self.log( + " - Refresh buffer: \(Int(self.refreshBufferSeconds))s " + + "(\(Self.durationDescription(seconds: self.refreshBufferSeconds)) before expiry)") + self.log( + " - Min refresh interval: \(Int(self.minRefreshInterval))s " + + "(\(Self.durationDescription(seconds: self.minRefreshInterval)))") + + self.timerTask = Task.detached(priority: .utility) { [weak self] in + while !Task.isCancelled { + try? await Task.sleep(for: .seconds(self?.checkInterval ?? 300)) + await self?.checkAndRefreshIfNeeded() + } + } + + self.log("✅ Keepalive timer started successfully") + } + + /// Stop the automatic session keepalive timer + public func stop() { + self.log("Stopping Augment session keepalive") + self.timerTask?.cancel() + self.timerTask = nil + } + + /// Manually trigger a session refresh (bypasses rate limiting) + public func forceRefresh() async { + self.log("Force refresh requested") + await self.performRefresh(forced: true) + } + + // MARK: - Private Implementation + + private func checkAndRefreshIfNeeded() async { + guard !self.isRefreshing else { + self.log("Refresh already in progress, skipping check") + return + } + + // Stop trying if we've given up + if self.hasGivenUp { + self.log("⏸️ Keepalive has given up after \(self.maxConsecutiveFailures) consecutive failures") + self.log(" User must manually log in to Augment and click 'Refresh Session'") + return + } + + // Rate limit: don't refresh too frequently + if let lastAttempt = self.lastRefreshAttempt { + let timeSinceLastAttempt = Date().timeIntervalSince(lastAttempt) + if timeSinceLastAttempt < self.minRefreshInterval { + self.log( + "Skipping refresh (last attempt \(Int(timeSinceLastAttempt))s ago, " + + "min interval: \(Int(self.minRefreshInterval))s)") + return + } + } + + // Check if cookies are about to expire + let shouldRefresh = await self.shouldRefreshSession() + if shouldRefresh { + await self.performRefresh(forced: false) + } + } + + private func shouldRefreshSession() async -> Bool { + do { + let session = try AugmentCookieImporter.importSession(logger: self.logger) + + self.log("📊 Cookie Status Check:") + self.log(" Total cookies: \(session.cookies.count)") + self.log(" Source: \(session.sourceLabel)") + + // Log each cookie's expiration status + for cookie in session.cookies { + if let expiry = cookie.expiresDate { + let timeUntil = expiry.timeIntervalSinceNow + let status = timeUntil > 0 ? "expires in \(Int(timeUntil))s" : "EXPIRED \(Int(-timeUntil))s ago" + self.log(" - \(cookie.name): \(status)") + } else { + self.log(" - \(cookie.name): session cookie (no expiry)") + } + } + + // Find the earliest expiration date among session cookies + let expirationDates = session.cookies.compactMap(\.expiresDate) + + guard !expirationDates.isEmpty else { + // Session cookies (no expiration) - refresh periodically + self.log(" All cookies are session cookies (no expiration dates)") + if let lastRefresh = self.lastSuccessfulRefresh { + let timeSinceRefresh = Date().timeIntervalSince(lastRefresh) + // Refresh every 30 minutes for session cookies + if timeSinceRefresh > 1800 { + self.log(" ⚠️ Need periodic refresh (\(Int(timeSinceRefresh))s since last refresh)") + return true + } else { + self.log(" ✅ Recently refreshed (\(Int(timeSinceRefresh))s ago)") + return false + } + } else { + // Never refreshed - do it now + self.log(" ⚠️ Never refreshed - doing initial refresh") + return true + } + } + + let earliestExpiration = expirationDates.min()! + let timeUntilExpiration = earliestExpiration.timeIntervalSinceNow + let expiringCookie = session.cookies.first { $0.expiresDate == earliestExpiration } + + if timeUntilExpiration < self.refreshBufferSeconds { + self.log(" ⚠️ REFRESH NEEDED:") + self.log(" Earliest expiring cookie: \(expiringCookie?.name ?? "unknown")") + self.log(" Time until expiration: \(Int(timeUntilExpiration))s") + self.log(" Refresh threshold: \(Int(self.refreshBufferSeconds))s") + return true + } else { + self.log(" ✅ Session healthy:") + self.log(" Earliest expiring cookie: \(expiringCookie?.name ?? "unknown")") + self.log(" Time until expiration: \(Int(timeUntilExpiration))s") + return false + } + } catch { + self.log("✗ Failed to check session: \(error.localizedDescription)") + return false + } + } + + private func performRefresh(forced: Bool) async { + self.isRefreshing = true + self.lastRefreshAttempt = Date() + defer { self.isRefreshing = false } + + self.log(forced ? "Performing forced session refresh..." : "Performing automatic session refresh...") + + // If this is a forced refresh (user clicked "Refresh Session"), reset failure tracking + if forced { + self.consecutiveFailures = 0 + self.hasGivenUp = false + self.log("🔄 Manual refresh - resetting failure tracking") + } + + do { + // Step 1: Ping the session endpoint to trigger cookie refresh + let refreshed = try await self.pingSessionEndpoint() + + if refreshed { + // Step 2: Re-import cookies from browser + try await Task.sleep(for: .seconds(1)) // Brief delay for browser to update cookies + let newSession = try AugmentCookieImporter.importSession(logger: self.logger) + + await AugmentSessionStore.shared.setCookies(newSession.cookies) + CookieHeaderCache.store( + provider: .augment, + cookieHeader: newSession.cookieHeader, + sourceLabel: newSession.sourceLabel) + + self.log( + "✅ Session refresh successful - imported \(newSession.cookies.count) cookies " + + "from \(newSession.sourceLabel)") + self.lastSuccessfulRefresh = Date() + + // Reset failure tracking on success + self.consecutiveFailures = 0 + self.hasGivenUp = false + + if let callback = self.onSessionRecovered { + self.log("🔄 Triggering usage refresh after session refresh") + await callback() + } + } else { + self.log("⚠️ Session refresh returned no new cookies") + self.consecutiveFailures += 1 + self.checkIfShouldGiveUp() + } + } catch AugmentSessionKeepaliveError.sessionExpired { + self.log("🔐 Session expired - attempting automatic recovery...") + self.consecutiveFailures += 1 + + if self.consecutiveFailures >= self.maxConsecutiveFailures { + self.log("❌ Too many consecutive failures (\(self.consecutiveFailures)) - giving up") + self.log(" User must manually log in to Augment and click 'Refresh Session'") + self.hasGivenUp = true + self.notifyUserLoginRequired() + } else { + await self.attemptSessionRecovery() + } + } catch { + self.log("✗ Session refresh failed: \(error.localizedDescription)") + self.consecutiveFailures += 1 + self.checkIfShouldGiveUp() + } + } + + private func checkIfShouldGiveUp() { + if self.consecutiveFailures >= self.maxConsecutiveFailures { + self.log("❌ Too many consecutive failures (\(self.consecutiveFailures)) - giving up") + self.log(" User must manually log in to Augment and click 'Refresh Session'") + self.hasGivenUp = true + self.notifyUserLoginRequired() + } + } + + /// Attempt to recover from an expired session by triggering browser re-authentication + private func attemptSessionRecovery() async { + self.log("🔄 Attempting automatic session recovery...") + self.log(" Strategy: Open Augment dashboard to trigger browser re-auth") + + #if os(macOS) + // Open the Augment dashboard in the default browser + // This will trigger the browser to re-authenticate if the user is still logged in + if let url = URL(string: "https://app.augmentcode.com") { + _ = await MainActor.run { + NSWorkspace.shared.open(url) + } + self.log(" ✅ Opened Augment dashboard in browser") + self.log(" ⏳ Waiting 5 seconds for browser to re-authenticate...") + + // Wait for browser to potentially re-authenticate + try? await Task.sleep(for: .seconds(5)) + + // Try to import cookies again + do { + let newSession = try AugmentCookieImporter.importSession(logger: self.logger) + self.log(" ✅ Session recovery successful - imported \(newSession.cookies.count) cookies") + self.lastSuccessfulRefresh = Date() + + // Verify the session is actually valid by pinging the API + let isValid = try await self.pingSessionEndpoint() + if isValid { + self.log(" ✅ Session verified - recovery complete!") + // Notify UsageStore to refresh Augment usage + if let callback = self.onSessionRecovered { + self.log(" 🔄 Triggering usage refresh after successful recovery") + await callback() + } + } else { + self.log(" ⚠️ Session imported but not yet valid - may need manual login") + self.notifyUserLoginRequired() + } + } catch { + self.log(" ✗ Session recovery failed: \(error.localizedDescription)") + self.log(" ℹ️ User needs to manually log in to Augment") + self.notifyUserLoginRequired() + } + } + #else + self.log(" ✗ Automatic recovery not supported on this platform") + #endif + } + + /// Notify the user that they need to log in to Augment + private func notifyUserLoginRequired() { + #if os(macOS) + self.log("📢 Sending notification: Augment session expired") + + Task { + let center = UNUserNotificationCenter.current() + + // Request authorization if needed + do { + let granted = try await center.requestAuthorization(options: [.alert, .sound]) + guard granted else { + self.log("⚠️ Notification permission denied") + return + } + } catch { + self.log("✗ Failed to request notification permission: \(error)") + return + } + + // Create notification content + let content = UNMutableNotificationContent() + content.title = "Augment Session Expired" + content.body = "Please log in to app.augmentcode.com to restore your session." + content.sound = .default + + // Create trigger (deliver immediately) + let request = UNNotificationRequest( + identifier: "augment-session-expired-\(UUID().uuidString)", + content: content, + trigger: nil) + + // Deliver notification + do { + try await center.add(request) + self.log("✅ Notification delivered successfully") + } catch { + self.log("✗ Failed to deliver notification: \(error)") + } + } + #endif + } + + /// Ping Augment's session endpoint to trigger cookie refresh + private func pingSessionEndpoint() async throws -> Bool { + // Try to get current cookies first + let currentSession = try? AugmentCookieImporter.importSession(logger: self.logger) + guard let cookieHeader = currentSession?.cookieHeader else { + self.log("No cookies available for session ping") + return false + } + + self.log("🔄 Attempting session refresh...") + self.log(" Cookies being sent: \(cookieHeader.prefix(100))...") + + // Try multiple endpoints - Augment might use different auth patterns + let endpoints = [ + "https://app.augmentcode.com/api/auth/session", // NextAuth pattern + "https://app.augmentcode.com/api/session", // Alternative + "https://app.augmentcode.com/api/user", // User endpoint + ] + + var receivedUnauthorized = false + + for (index, urlString) in endpoints.enumerated() { + self.log(" Trying endpoint \(index + 1)/\(endpoints.count): \(urlString)") + + guard let sessionURL = URL(string: urlString) else { continue } + var request = URLRequest(url: sessionURL) + request.timeoutInterval = self.refreshTimeout + request.setValue(cookieHeader, forHTTPHeaderField: "Cookie") + request.setValue("application/json", forHTTPHeaderField: "Accept") + request.setValue("https://app.augmentcode.com", forHTTPHeaderField: "Origin") + request.setValue("https://app.augmentcode.com", forHTTPHeaderField: "Referer") + + do { + let (data, response) = try await ProviderHTTPClient.shared.data(for: request) + + guard let httpResponse = response as? HTTPURLResponse else { + self.log(" ✗ Invalid response type") + continue + } + + self.log(" Response: HTTP \(httpResponse.statusCode)") + + // Log Set-Cookie headers if present + if let setCookies = httpResponse.allHeaderFields["Set-Cookie"] as? String { + self.log(" Set-Cookie headers received: \(setCookies.prefix(100))...") + } + + if httpResponse.statusCode == 200 { + // Check if we got a valid session response + if let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] { + self.log(" JSON response keys: \(json.keys.joined(separator: ", "))") + + if json["user"] != nil || json["email"] != nil || json["session"] != nil { + self.log(" ✅ Valid session data found!") + return true + } else { + self.log(" ⚠️ 200 OK but no session data in response") + // Try next endpoint + continue + } + } else { + self.log(" ⚠️ 200 OK but response is not JSON") + if let responseText = String(data: data, encoding: .utf8) { + self.log(" Response text: \(responseText.prefix(200))...") + } + continue + } + } else if httpResponse.statusCode == 401 { + self.log(" ✗ 401 Unauthorized - session expired") + receivedUnauthorized = true + // Don't throw immediately - try all endpoints first + continue + } else if httpResponse.statusCode == 404 { + self.log(" ✗ 404 Not Found - trying next endpoint") + continue + } else { + self.log(" ✗ HTTP \(httpResponse.statusCode) - trying next endpoint") + continue + } + } catch { + self.log(" ✗ Request failed: \(error.localizedDescription)") + continue + } + } + + // If we got 401 from all endpoints, the session is definitely expired + if receivedUnauthorized { + self.log("⚠️ All endpoints returned 401 - session is expired") + throw AugmentSessionKeepaliveError.sessionExpired + } + + self.log("⚠️ All session endpoints failed or returned no valid data") + return false + } + + private static let log = CodexBarLog.logger(LogCategories.augmentKeepalive) + + private static func durationDescription(seconds: TimeInterval) -> String { + let totalSeconds = max(0, Int(seconds.rounded())) + if totalSeconds >= 60, totalSeconds % 60 == 0 { + let minutes = totalSeconds / 60 + return "\(minutes) minute\(minutes == 1 ? "" : "s")" + } + return "\(totalSeconds) second\(totalSeconds == 1 ? "" : "s")" + } + + private func log(_ message: String) { + let timestamp = Date().formatted(date: .omitted, time: .standard) + let fullMessage = "[\(timestamp)] [AugmentKeepalive] \(message)" + self.logger?(fullMessage) + Self.log.debug(fullMessage) + } +} + +// MARK: - Errors + +public enum AugmentSessionKeepaliveError: LocalizedError, Sendable { + case invalidResponse + case sessionExpired + case networkError(String) + + public var errorDescription: String? { + switch self { + case .invalidResponse: + "Invalid response from session endpoint" + case .sessionExpired: + "Session has expired" + case let .networkError(message): + "Network error: \(message)" + } + } +} + +#endif diff --git a/Sources/CodexBarCore/Providers/Augment/AugmentStatusProbe.swift b/Sources/CodexBarCore/Providers/Augment/AugmentStatusProbe.swift new file mode 100644 index 0000000..52ae33a --- /dev/null +++ b/Sources/CodexBarCore/Providers/Augment/AugmentStatusProbe.swift @@ -0,0 +1,698 @@ +import Foundation +import SweetCookieKit + +#if os(macOS) + +private let augmentCookieImportOrder: BrowserCookieImportOrder = + ProviderDefaults.metadata[.augment]?.browserCookieOrder ?? Browser.defaultImportOrder + +// MARK: - Augment Cookie Importer + +/// Imports Augment session cookies from browser cookies. +public enum AugmentCookieImporter { + private static let cookieClient = BrowserCookieClient() + /// Auth0 session cookies used by Augment + /// NOTE: This list may not be exhaustive. If authentication fails with cookies present, + /// check debug logs for cookie names and report them. + private static let sessionCookieNames: Set = [ + "session", // Augment auth session (auth.augmentcode.com) + "_session", // Legacy session cookie (app.augmentcode.com) + "web_rpc_proxy_session", // Augment RPC proxy session + "auth0", // Auth0 session + "auth0.is.authenticated", // Auth0 authentication flag + "a0.spajs.txs", // Auth0 SPA transaction state + "__Secure-next-auth.session-token", // NextAuth secure session + "next-auth.session-token", // NextAuth session + "__Secure-authjs.session-token", // AuthJS secure session + "__Host-authjs.csrf-token", // AuthJS CSRF token + "authjs.session-token", // AuthJS session + ] + + public struct SessionInfo: Sendable { + public let cookies: [HTTPCookie] + public let sourceLabel: String + + public init(cookies: [HTTPCookie], sourceLabel: String) { + self.cookies = cookies + self.sourceLabel = sourceLabel + } + + public var cookieHeader: String { + self.cookies.map { "\($0.name)=\($0.value)" }.joined(separator: "; ") + } + + /// Returns cookie header filtered for a specific target URL + public func cookieHeader(for url: URL) -> String { + guard let host = url.host else { return "" } + + let matchingCookies = self.cookies.filter { cookie in + let domain = cookie.domain + + // Handle wildcard domains (e.g., ".augmentcode.com") + if domain.hasPrefix(".") { + let baseDomain = String(domain.dropFirst()) + return host == baseDomain || host.hasSuffix(".\(baseDomain)") + } + + // Exact match or subdomain match + return host == domain || host.hasSuffix(".\(domain)") + } + + return matchingCookies.map { "\($0.name)=\($0.value)" }.joined(separator: "; ") + } + } + + /// Attempts to import Augment cookies using the standard browser import order. + public static func importSession(logger: ((String) -> Void)? = nil) throws -> SessionInfo { + let log: (String) -> Void = { msg in logger?("[augment-cookie] \(msg)") } + + let cookieDomains = ["augmentcode.com", "app.augmentcode.com"] + for browserSource in augmentCookieImportOrder { + do { + let query = BrowserCookieQuery(domains: cookieDomains) + let sources = try Self.cookieClient.codexBarRecords( + matching: query, + in: browserSource, + logger: log) + for source in sources where !source.records.isEmpty { + let httpCookies = BrowserCookieClient.makeHTTPCookies(source.records, origin: query.origin) + + // Log all cookies found for debugging + let cookieNames = httpCookies.map(\.name).joined(separator: ", ") + log("Found \(httpCookies.count) cookies in \(source.label): \(cookieNames)") + + // Check if we have any session cookies + let matchingCookies = httpCookies.filter { Self.sessionCookieNames.contains($0.name) } + if !matchingCookies.isEmpty { + let matchingCookieNames = matchingCookies.map(\.name).joined(separator: ", ") + log("✓ Found Augment session cookies in \(source.label): \(matchingCookieNames)") + return SessionInfo(cookies: httpCookies, sourceLabel: source.label) + } else if !httpCookies.isEmpty { + // Log unrecognized cookies to help discover missing session cookie names + log( + "⚠️ \(source.label) has \(httpCookies.count) cookies but none match known session cookies") + log(" Cookie names found: \(cookieNames)") + log(" If you're logged into Augment, please report these cookie names") + log(" to help improve detection") + } + } + } catch { + BrowserCookieAccessGate.recordIfNeeded(error) + log("\(browserSource.displayName) cookie import failed: \(error.localizedDescription)") + } + } + + throw AugmentStatusProbeError.noSessionCookie + } + + /// Check if Augment session cookies are available + public static func hasSession(logger: ((String) -> Void)? = nil) -> Bool { + do { + let session = try self.importSession(logger: logger) + return !session.cookies.isEmpty + } catch { + return false + } + } +} + +// MARK: - Augment API Models + +public struct AugmentCreditsResponse: Codable, Sendable { + public let usageUnitsRemaining: Double? + public let usageUnitsConsumedThisBillingCycle: Double? + public let usageUnitsAvailable: Double? + public let usageBalanceStatus: String? + + /// Computed properties for compatibility with existing code + public var credits: Double? { + self.usageUnitsRemaining + } + + public var creditsUsed: Double? { + self.usageUnitsConsumedThisBillingCycle + } + + public var creditsLimit: Double? { + if let available = self.usageUnitsAvailable, available > 0 { + return available + } + + guard let remaining = self.usageUnitsRemaining, + let consumed = self.usageUnitsConsumedThisBillingCycle + else { + return nil + } + return remaining + consumed + } + + private enum CodingKeys: String, CodingKey { + case usageUnitsRemaining + case usageUnitsConsumedThisBillingCycle + case usageUnitsAvailable + case usageBalanceStatus + } +} + +public struct AugmentSubscriptionResponse: Codable, Sendable { + public let planName: String? + public let billingPeriodEnd: String? + public let email: String? + public let organization: String? + + private enum CodingKeys: String, CodingKey { + case planName + case billingPeriodEnd + case email + case organization + } +} + +// MARK: - Augment Status Snapshot + +public struct AugmentStatusSnapshot: Sendable { + public let creditsRemaining: Double? + public let creditsUsed: Double? + public let creditsLimit: Double? + public let billingCycleEnd: Date? + public let accountEmail: String? + public let accountPlan: String? + public let rawJSON: String? + + public init( + creditsRemaining: Double?, + creditsUsed: Double?, + creditsLimit: Double?, + billingCycleEnd: Date?, + accountEmail: String?, + accountPlan: String?, + rawJSON: String?) + { + self.creditsRemaining = creditsRemaining + self.creditsUsed = creditsUsed + self.creditsLimit = creditsLimit + self.billingCycleEnd = billingCycleEnd + self.accountEmail = accountEmail + self.accountPlan = accountPlan + self.rawJSON = rawJSON + } + + public func toUsageSnapshot() -> UsageSnapshot { + let percentUsed: Double = if let used = self.creditsUsed, let limit = self.creditsLimit, limit > 0 { + (used / limit) * 100.0 + } else if let remaining = self.creditsRemaining, let limit = self.creditsLimit, limit > 0 { + ((limit - remaining) / limit) * 100.0 + } else { + 0 + } + + let primary = RateWindow( + usedPercent: percentUsed, + windowMinutes: nil, + resetsAt: self.billingCycleEnd, + resetDescription: self.billingCycleEnd.map { "Resets \(Self.formatResetDate($0))" }) + + let identity = ProviderIdentitySnapshot( + providerID: .augment, + accountEmail: self.accountEmail, + accountOrganization: nil, + loginMethod: self.accountPlan) + + return UsageSnapshot( + primary: primary, + secondary: nil, + tertiary: nil, + providerCost: nil, + updatedAt: Date(), + identity: identity) + } + + private static func formatResetDate(_ date: Date) -> String { + let formatter = RelativeDateTimeFormatter() + formatter.locale = Locale(identifier: "en_US") + formatter.unitsStyle = .full + return formatter.localizedString(for: date, relativeTo: Date()) + } +} + +// MARK: - Augment Status Probe Error + +public enum AugmentStatusProbeError: LocalizedError, Sendable { + case notLoggedIn + case networkError(String) + case parseFailed(String) + case noSessionCookie + case sessionExpired + + public var errorDescription: String? { + switch self { + case .notLoggedIn: + "Not logged in to Augment. Please log in via the CodexBar menu." + case let .networkError(msg): + "Augment API error: \(msg)" + case let .parseFailed(msg): + "Could not parse Augment usage: \(msg)" + case .noSessionCookie: + "No Augment session found. Please log in to app.augmentcode.com in \(augmentCookieImportOrder.loginHint)." + case .sessionExpired: + "Augment session expired. Please log in again." + } + } +} + +// MARK: - Augment Session Store + +public actor AugmentSessionStore { + public static let shared = AugmentSessionStore() + + private var sessionCookies: [HTTPCookie] = [] + private var hasLoadedFromDisk = false + private let fileURL: URL + + private init() { + let fm = FileManager.default + let appSupport = fm.urls(for: .applicationSupportDirectory, in: .userDomainMask).first + ?? fm.temporaryDirectory + let dir = appSupport.appendingPathComponent("CodexBar", isDirectory: true) + try? fm.createDirectory(at: dir, withIntermediateDirectories: true) + self.fileURL = dir.appendingPathComponent("augment-session.json") + + // Load saved cookies on init + Task { await self.loadFromDiskIfNeeded() } + } + + public func setCookies(_ cookies: [HTTPCookie]) { + self.hasLoadedFromDisk = true + self.sessionCookies = cookies + self.saveToDisk() + } + + public func getCookies() -> [HTTPCookie] { + self.loadFromDiskIfNeeded() + return self.sessionCookies + } + + public func clearCookies() { + self.hasLoadedFromDisk = true + self.sessionCookies = [] + try? FileManager.default.removeItem(at: self.fileURL) + } + + public func hasValidSession() -> Bool { + self.loadFromDiskIfNeeded() + return !self.sessionCookies.isEmpty + } + + #if DEBUG + func resetForTesting(clearDisk: Bool = true) { + self.hasLoadedFromDisk = false + self.sessionCookies = [] + if clearDisk { + try? FileManager.default.removeItem(at: self.fileURL) + } + } + #endif + + private func loadFromDiskIfNeeded() { + guard !self.hasLoadedFromDisk else { return } + self.hasLoadedFromDisk = true + self.loadFromDisk() + } + + private func saveToDisk() { + // Convert cookie properties to JSON-serializable format + // Date values must be converted to TimeInterval (Double) + let cookieData = self.sessionCookies.compactMap { cookie -> [String: Any]? in + guard let props = cookie.properties else { return nil } + var serializable: [String: Any] = [:] + for (key, value) in props { + let keyString = key.rawValue + if let date = value as? Date { + // Convert Date to TimeInterval for JSON compatibility + serializable[keyString] = date.timeIntervalSince1970 + serializable[keyString + "_isDate"] = true + } else if let url = value as? URL { + serializable[keyString] = url.absoluteString + serializable[keyString + "_isURL"] = true + } else if JSONSerialization.isValidJSONObject([value]) || + value is String || + value is Bool || + value is NSNumber + { + serializable[keyString] = value + } + } + return serializable + } + guard !cookieData.isEmpty, + let data = try? JSONSerialization.data(withJSONObject: cookieData, options: [.prettyPrinted]) + else { + return + } + try? data.write(to: self.fileURL) + } + + private func loadFromDisk() { + guard let data = try? Data(contentsOf: self.fileURL), + let cookieArray = try? JSONSerialization.jsonObject(with: data) as? [[String: Any]] + else { return } + + self.sessionCookies = cookieArray.compactMap { props in + // Convert back to HTTPCookiePropertyKey dictionary + var cookieProps: [HTTPCookiePropertyKey: Any] = [:] + for (key, value) in props { + // Skip marker keys + if key.hasSuffix("_isDate") || key.hasSuffix("_isURL") { continue } + + let propKey = HTTPCookiePropertyKey(key) + + // Check if this was a Date + if props[key + "_isDate"] as? Bool == true, let interval = value as? TimeInterval { + cookieProps[propKey] = Date(timeIntervalSince1970: interval) + } + // Check if this was a URL + else if props[key + "_isURL"] as? Bool == true, let urlString = value as? String { + cookieProps[propKey] = URL(string: urlString) + } else { + cookieProps[propKey] = value + } + } + return HTTPCookie(properties: cookieProps) + } + } +} + +// MARK: - Augment Status Probe + +public struct AugmentStatusProbe: Sendable { + public let baseURL: URL + public var timeout: TimeInterval = 15.0 + + public init(baseURL: URL = URL(string: "https://app.augmentcode.com")!, timeout: TimeInterval = 15.0) { + self.baseURL = baseURL + self.timeout = timeout + } + + /// Fetch Augment usage with manual cookie header (for debugging). + public func fetchWithManualCookies(_ cookieHeader: String) async throws -> AugmentStatusSnapshot { + try await self.fetchWithCookieHeader(cookieHeader) + } + + /// Fetch Augment usage using browser cookies with fallback to stored session. + public func fetch(cookieHeaderOverride: String? = nil, logger: ((String) -> Void)? = nil) + async throws -> AugmentStatusSnapshot + { + let log: (String) -> Void = { msg in logger?("[augment] \(msg)") } + + if let override = CookieHeaderNormalizer.normalize(cookieHeaderOverride) { + log("Using manual cookie header") + return try await self.fetchWithCookieHeader(override) + } + + if let cached = CookieHeaderCache.load(provider: .augment), + !cached.cookieHeader.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty + { + log("Using cached cookie header from \(cached.sourceLabel)") + do { + return try await self.fetchWithCookieHeader(cached.cookieHeader) + } catch let error as AugmentStatusProbeError { + switch error { + case .notLoggedIn, .sessionExpired: + CookieHeaderCache.clear(provider: .augment) + default: + throw error + } + } catch { + throw error + } + } + + // Try importing cookies from the configured browser order first. + do { + let session = try AugmentCookieImporter.importSession(logger: log) + log("Using cookies from \(session.sourceLabel)") + let snapshot = try await self.fetchWithCookieHeader(session.cookieHeader) + + // SUCCESS: Save cookies to fallback store for future use + await AugmentSessionStore.shared.setCookies(session.cookies) + log("Saved session cookies to fallback store") + CookieHeaderCache.store( + provider: .augment, + cookieHeader: session.cookieHeader, + sourceLabel: session.sourceLabel) + + return snapshot + } catch { + BrowserCookieAccessGate.recordIfNeeded(error) + log("Browser cookie import failed: \(error.localizedDescription)") + } + + // Fall back to stored session cookies (from previous successful fetch or "Add Account" login flow) + let storedCookies = await AugmentSessionStore.shared.getCookies() + if !storedCookies.isEmpty { + log("Using stored session cookies") + let cookieHeader = storedCookies.map { "\($0.name)=\($0.value)" }.joined(separator: "; ") + do { + return try await self.fetchWithCookieHeader(cookieHeader) + } catch { + if case AugmentStatusProbeError.notLoggedIn = error { + // Clear only when auth is invalid; keep for transient failures. + await AugmentSessionStore.shared.clearCookies() + log("Stored session invalid, cleared") + } else if case AugmentStatusProbeError.sessionExpired = error { + await AugmentSessionStore.shared.clearCookies() + log("Stored session expired, cleared") + } else { + log("Stored session failed: \(error.localizedDescription)") + } + } + } + + throw AugmentStatusProbeError.noSessionCookie + } + + private func fetchWithCookieHeader(_ cookieHeader: String) async throws -> AugmentStatusSnapshot { + // Fetch credits (required) + let (creditsResponse, creditsJSON) = try await self.fetchCredits(cookieHeader: cookieHeader) + + // Fetch subscription (optional - provides plan name and billing cycle) + let subscriptionResult: (AugmentSubscriptionResponse?, String?) = await { + do { + let (response, json) = try await self.fetchSubscription(cookieHeader: cookieHeader) + return (response, json) + } catch { + // Subscription API is optional - don't fail the whole fetch if it's unavailable + return (nil, nil) + } + }() + + return self.parseResponse( + credits: creditsResponse, + subscription: subscriptionResult.0, + creditsJSON: creditsJSON, + subscriptionJSON: subscriptionResult.1) + } + + private func fetchCredits(cookieHeader: String) async throws -> (AugmentCreditsResponse, String) { + let url = self.baseURL.appendingPathComponent("/api/credits") + var request = URLRequest(url: url) + request.timeoutInterval = self.timeout + request.setValue("application/json", forHTTPHeaderField: "Accept") + request.setValue(cookieHeader, forHTTPHeaderField: "Cookie") + + let (data, response) = try await ProviderHTTPClient.shared.data(for: request) + + guard let httpResponse = response as? HTTPURLResponse else { + throw AugmentStatusProbeError.networkError("Invalid response") + } + + if httpResponse.statusCode == 401 { + // Session expired - trigger automatic recovery + throw AugmentStatusProbeError.sessionExpired + } + + if httpResponse.statusCode == 403 { + let responseBody = String(data: data, encoding: .utf8) ?? "" + throw AugmentStatusProbeError.networkError("HTTP \(httpResponse.statusCode): \(responseBody)") + } + + guard httpResponse.statusCode == 200 else { + let responseBody = String(data: data, encoding: .utf8) ?? "" + throw AugmentStatusProbeError.networkError("HTTP \(httpResponse.statusCode): \(responseBody)") + } + + let rawJSON = String(data: data, encoding: .utf8) ?? "" + let decoder = JSONDecoder() + do { + let response = try decoder.decode(AugmentCreditsResponse.self, from: data) + return (response, rawJSON) + } catch { + throw AugmentStatusProbeError.parseFailed("Credits response: \(error.localizedDescription)") + } + } + + private func fetchSubscription(cookieHeader: String) async throws -> (AugmentSubscriptionResponse, String) { + let url = self.baseURL.appendingPathComponent("/api/subscription") + var request = URLRequest(url: url) + request.timeoutInterval = self.timeout + request.setValue("application/json", forHTTPHeaderField: "Accept") + request.setValue(cookieHeader, forHTTPHeaderField: "Cookie") + + let (data, response) = try await ProviderHTTPClient.shared.data(for: request) + + guard let httpResponse = response as? HTTPURLResponse else { + throw AugmentStatusProbeError.networkError("Invalid response") + } + + if httpResponse.statusCode == 401 { + // Session expired - trigger automatic recovery + throw AugmentStatusProbeError.sessionExpired + } + + if httpResponse.statusCode == 403 { + throw AugmentStatusProbeError.notLoggedIn + } + + guard httpResponse.statusCode == 200 else { + throw AugmentStatusProbeError.networkError("HTTP \(httpResponse.statusCode)") + } + + let rawJSON = String(data: data, encoding: .utf8) ?? "" + let decoder = JSONDecoder() + do { + let response = try decoder.decode(AugmentSubscriptionResponse.self, from: data) + return (response, rawJSON) + } catch { + throw AugmentStatusProbeError.parseFailed("Subscription response: \(error.localizedDescription)") + } + } + + private func parseResponse( + credits: AugmentCreditsResponse, + subscription: AugmentSubscriptionResponse?, + creditsJSON: String, + subscriptionJSON: String?) -> AugmentStatusSnapshot + { + // Combine both API responses for debugging + var combinedJSON = "Credits API:\n\(creditsJSON)" + if let subJSON = subscriptionJSON { + combinedJSON += "\n\nSubscription API:\n\(subJSON)" + } + + // Parse billing period end date from ISO8601 string + let billingCycleEnd: Date? = { + guard let dateString = subscription?.billingPeriodEnd else { return nil } + let formatter = ISO8601DateFormatter() + return formatter.date(from: dateString) + }() + + return AugmentStatusSnapshot( + creditsRemaining: credits.credits, + creditsUsed: credits.creditsUsed, + creditsLimit: credits.creditsLimit, + billingCycleEnd: billingCycleEnd, + accountEmail: subscription?.email, + accountPlan: subscription?.planName, + rawJSON: combinedJSON) + } + + /// Debug probe that returns raw API responses + public func debugRawProbe(cookieHeaderOverride: String? = nil) async -> String { + let stamp = ISO8601DateFormatter().string(from: Date()) + var lines: [String] = [] + lines.append("=== Augment Debug Probe @ \(stamp) ===") + lines.append("") + + do { + let snapshot = try await self.fetch( + cookieHeaderOverride: cookieHeaderOverride, + logger: { msg in lines.append("[log] \(msg)") }) + lines.append("") + lines.append("Probe Success") + lines.append("") + lines.append("Credits Balance:") + lines.append(" Remaining: \(snapshot.creditsRemaining?.description ?? "nil")") + lines.append(" Used: \(snapshot.creditsUsed?.description ?? "nil")") + lines.append(" Limit: \(snapshot.creditsLimit?.description ?? "nil")") + lines.append("") + lines.append("Billing Cycle End: \(snapshot.billingCycleEnd?.description ?? "nil")") + lines.append("Account Email: \(snapshot.accountEmail ?? "nil")") + lines.append("Account Plan: \(snapshot.accountPlan ?? "nil")") + + if let rawJSON = snapshot.rawJSON { + lines.append("") + lines.append("Raw API Response:") + lines.append(rawJSON) + } + + let output = lines.joined(separator: "\n") + await MainActor.run { Self.recordDump(output) } + return output + } catch { + lines.append("") + lines.append("Probe Failed: \(error.localizedDescription)") + let output = lines.joined(separator: "\n") + await MainActor.run { Self.recordDump(output) } + return output + } + } + + // MARK: - Dump storage (in-memory ring buffer) + + @MainActor private static var recentDumps: [String] = [] + + @MainActor private static func recordDump(_ text: String) { + if self.recentDumps.count >= 5 { self.recentDumps.removeFirst() } + self.recentDumps.append(text) + } + + public static func latestDumps() async -> String { + await MainActor.run { + let result = Self.recentDumps.joined(separator: "\n\n---\n\n") + return result.isEmpty ? "No Augment probe dumps captured yet." : result + } + } +} + +#else + +// MARK: - Augment (Unsupported) + +public enum AugmentStatusProbeError: LocalizedError, Sendable { + case notSupported + + public var errorDescription: String? { + "Augment is only supported on macOS." + } +} + +public struct AugmentStatusSnapshot: Sendable { + public init() {} + + public func toUsageSnapshot() -> UsageSnapshot { + UsageSnapshot( + primary: RateWindow(usedPercent: 0, windowMinutes: nil, resetsAt: nil, resetDescription: nil), + secondary: nil, + tertiary: nil, + providerCost: nil, + updatedAt: Date(), + identity: nil) + } +} + +public struct AugmentStatusProbe: Sendable { + public init(baseURL: URL = URL(string: "https://app.augmentcode.com")!, timeout: TimeInterval = 15.0) { + _ = baseURL + _ = timeout + } + + public func fetch(cookieHeaderOverride: String? = nil, logger: ((String) -> Void)? = nil) + async throws -> AugmentStatusSnapshot + { + _ = cookieHeaderOverride + _ = logger + throw AugmentStatusProbeError.notSupported + } +} + +#endif diff --git a/Sources/CodexBarCore/Providers/AzureOpenAI/AzureOpenAIProviderDescriptor.swift b/Sources/CodexBarCore/Providers/AzureOpenAI/AzureOpenAIProviderDescriptor.swift new file mode 100644 index 0000000..52859fa --- /dev/null +++ b/Sources/CodexBarCore/Providers/AzureOpenAI/AzureOpenAIProviderDescriptor.swift @@ -0,0 +1,92 @@ +import Foundation + +public enum AzureOpenAIProviderDescriptor { + public static let descriptor: ProviderDescriptor = Self.makeDescriptor() + + static func makeDescriptor() -> ProviderDescriptor { + ProviderDescriptor( + id: .azureopenai, + metadata: ProviderMetadata( + id: .azureopenai, + displayName: "Azure OpenAI", + sessionLabel: "Status", + weeklyLabel: "Deployment", + opusLabel: nil, + supportsOpus: false, + supportsCredits: false, + creditsHint: "", + toggleTitle: "Show Azure OpenAI status", + cliName: "azure-openai", + defaultEnabled: false, + isPrimaryProvider: false, + usesAccountFallback: false, + browserCookieOrder: nil, + dashboardURL: "https://ai.azure.com", + statusPageURL: nil, + statusLinkURL: "https://azure.status.microsoft/en-us/status"), + branding: ProviderBranding( + iconStyle: .openai, + iconResourceName: "ProviderIcon-codex", + color: ProviderColor(red: 0, green: 120 / 255, blue: 212 / 255)), + tokenCost: ProviderTokenCostConfig( + supportsTokenCost: false, + noDataMessage: { "Azure OpenAI usage history is not exposed by the deployment validation probe." }), + fetchPlan: ProviderFetchPlan( + sourceModes: [.auto, .api], + pipeline: ProviderFetchPipeline(resolveStrategies: { _ in [AzureOpenAIAPIFetchStrategy()] })), + cli: ProviderCLIConfig( + name: "azure-openai", + aliases: ["azureopenai", "aoai"], + versionDetector: nil)) + } +} + +struct AzureOpenAIAPIFetchStrategy: ProviderFetchStrategy { + let id: String = "azureopenai.api" + let kind: ProviderFetchKind = .apiToken + + func isAvailable(_ context: ProviderFetchContext) async -> Bool { + _ = context + // Keep the strategy available so missing partial configuration surfaces + // as a precise settings error instead of a generic no-strategy failure. + return true + } + + func fetch(_ context: ProviderFetchContext) async throws -> ProviderFetchResult { + guard let apiKey = Self.resolveAPIKey(environment: context.env) else { + throw AzureOpenAIUsageError.missingAPIKey + } + try AzureOpenAISettingsReader.validateEndpointOverrides(environment: context.env) + guard let endpoint = Self.resolveEndpoint(environment: context.env) else { + throw AzureOpenAIUsageError.missingEndpoint + } + guard let deploymentName = Self.resolveDeploymentName(environment: context.env) else { + throw AzureOpenAIUsageError.missingDeploymentName + } + + let usage = try await AzureOpenAIUsageFetcher.fetchUsage( + apiKey: apiKey, + endpoint: endpoint, + deploymentName: deploymentName, + apiVersion: AzureOpenAISettingsReader.apiVersion(environment: context.env)) + return self.makeResult( + usage: usage.toUsageSnapshot(), + sourceLabel: "deployment") + } + + func shouldFallback(on _: Error, context _: ProviderFetchContext) -> Bool { + false + } + + private static func resolveAPIKey(environment: [String: String]) -> String? { + ProviderTokenResolver.azureOpenAIToken(environment: environment) + } + + private static func resolveEndpoint(environment: [String: String]) -> URL? { + AzureOpenAISettingsReader.endpoint(environment: environment) + } + + private static func resolveDeploymentName(environment: [String: String]) -> String? { + AzureOpenAISettingsReader.deploymentName(environment: environment) + } +} diff --git a/Sources/CodexBarCore/Providers/AzureOpenAI/AzureOpenAISettingsReader.swift b/Sources/CodexBarCore/Providers/AzureOpenAI/AzureOpenAISettingsReader.swift new file mode 100644 index 0000000..53706dd --- /dev/null +++ b/Sources/CodexBarCore/Providers/AzureOpenAI/AzureOpenAISettingsReader.swift @@ -0,0 +1,82 @@ +import Foundation + +public enum AzureOpenAISettingsReader { + public static let apiKeyEnvironmentKey = "AZURE_OPENAI_API_KEY" + public static let endpointEnvironmentKey = "AZURE_OPENAI_ENDPOINT" + public static let deploymentNameEnvironmentKey = "AZURE_OPENAI_DEPLOYMENT_NAME" + public static let apiVersionEnvironmentKey = "AZURE_OPENAI_API_VERSION" + public static let defaultAPIVersion = "2024-10-21" + + public static func apiKey(environment: [String: String] = ProcessInfo.processInfo.environment) -> String? { + self.cleaned(environment[self.apiKeyEnvironmentKey]) + } + + public static func endpoint(environment: [String: String] = ProcessInfo.processInfo.environment) -> URL? { + guard let rawEndpoint = self.rawEndpoint(environment: environment) else { return nil } + return self.endpointURL(from: rawEndpoint) + } + + public static func rawEndpoint(environment: [String: String] = ProcessInfo.processInfo.environment) -> String? { + self.cleaned(environment[self.endpointEnvironmentKey]) + } + + public static func deploymentName(environment: [String: String] = ProcessInfo.processInfo.environment) -> String? { + self.cleaned(environment[self.deploymentNameEnvironmentKey]) + } + + public static func apiVersion(environment: [String: String] = ProcessInfo.processInfo.environment) -> String { + self.cleaned(environment[self.apiVersionEnvironmentKey]) ?? self.defaultAPIVersion + } + + public static func endpointURL(from rawEndpoint: String) -> URL? { + let trimmed = rawEndpoint.trimmingCharacters(in: .whitespacesAndNewlines) + guard !trimmed.isEmpty else { return nil } + return ProviderEndpointOverrideValidator.normalizedHTTPSURL(from: trimmed) + } + + public static func validateEndpointOverrides( + environment: [String: String] = ProcessInfo.processInfo.environment) throws + { + guard let rawEndpoint = self.rawEndpoint(environment: environment) else { return } + guard self.endpointURL(from: rawEndpoint) != nil else { + throw AzureOpenAISettingsError.invalidEndpointOverride(self.endpointEnvironmentKey) + } + } + + static func cleaned(_ raw: String?) -> String? { + guard var value = raw?.trimmingCharacters(in: .whitespacesAndNewlines), !value.isEmpty else { + return nil + } + + if (value.hasPrefix("\"") && value.hasSuffix("\"")) || + (value.hasPrefix("'") && value.hasSuffix("'")) + { + value = String(value.dropFirst().dropLast()) + } + + value = value.trimmingCharacters(in: .whitespacesAndNewlines) + return value.isEmpty ? nil : value + } +} + +public enum AzureOpenAISettingsError: LocalizedError, Sendable, Equatable { + case missingAPIKey + case missingEndpoint + case missingDeploymentName + case invalidEndpointOverride(String) + + public var errorDescription: String? { + switch self { + case .missingAPIKey: + "Azure OpenAI API key not configured. Set AZURE_OPENAI_API_KEY or configure an API key in Settings." + case .missingEndpoint: + "Azure OpenAI endpoint not configured. Set AZURE_OPENAI_ENDPOINT or configure an endpoint in Settings." + case .missingDeploymentName: + "Azure OpenAI deployment not configured. Set AZURE_OPENAI_DEPLOYMENT_NAME or configure a deployment " + + "in Settings." + case let .invalidEndpointOverride(key): + "Azure OpenAI endpoint override \(key) is not allowed. " + + "Use an HTTPS endpoint without user info or encoded host tricks." + } + } +} diff --git a/Sources/CodexBarCore/Providers/AzureOpenAI/AzureOpenAIUsageFetcher.swift b/Sources/CodexBarCore/Providers/AzureOpenAI/AzureOpenAIUsageFetcher.swift new file mode 100644 index 0000000..716d75c --- /dev/null +++ b/Sources/CodexBarCore/Providers/AzureOpenAI/AzureOpenAIUsageFetcher.swift @@ -0,0 +1,244 @@ +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +public struct AzureOpenAIUsageSnapshot: Codable, Sendable, Equatable { + public let endpointHost: String + public let deploymentName: String + public let model: String? + public let apiVersion: String + public let updatedAt: Date + + public init( + endpointHost: String, + deploymentName: String, + model: String?, + apiVersion: String, + updatedAt: Date) + { + self.endpointHost = endpointHost + self.deploymentName = deploymentName + self.model = model + self.apiVersion = apiVersion + self.updatedAt = updatedAt + } + + public func toUsageSnapshot() -> UsageSnapshot { + let detail = Self.detailText(deploymentName: self.deploymentName, model: self.model) + return UsageSnapshot( + primary: RateWindow( + usedPercent: 0, + windowMinutes: nil, + resetsAt: nil, + resetDescription: detail), + secondary: nil, + tertiary: nil, + updatedAt: self.updatedAt, + identity: ProviderIdentitySnapshot( + providerID: .azureopenai, + accountEmail: nil, + accountOrganization: self.endpointHost, + loginMethod: "Deployment: \(self.deploymentName)")) + } + + private static func detailText(deploymentName: String, model: String?) -> String { + let cleanedModel = model?.trimmingCharacters(in: .whitespacesAndNewlines) + guard let cleanedModel, !cleanedModel.isEmpty else { + return "Deployment: \(deploymentName)" + } + return "Deployment: \(deploymentName) · Model: \(cleanedModel)" + } +} + +public enum AzureOpenAIUsageError: LocalizedError, Sendable, Equatable { + case missingAPIKey + case missingEndpoint + case missingDeploymentName + case invalidEndpointOverride(String) + case invalidURL + case networkError(String) + case apiError(statusCode: Int, message: String) + case parseFailed(String) + + public var errorDescription: String? { + switch self { + case .missingAPIKey: + AzureOpenAISettingsError.missingAPIKey.errorDescription + case .missingEndpoint: + AzureOpenAISettingsError.missingEndpoint.errorDescription + case .missingDeploymentName: + AzureOpenAISettingsError.missingDeploymentName.errorDescription + case let .invalidEndpointOverride(key): + AzureOpenAISettingsError.invalidEndpointOverride(key).errorDescription + case .invalidURL: + "Azure OpenAI validation URL is invalid." + case let .networkError(message): + "Azure OpenAI network error: \(message)" + case let .apiError(statusCode, message): + if message.isEmpty { + "Azure OpenAI API error: HTTP \(statusCode)" + } else { + "Azure OpenAI API error: HTTP \(statusCode): \(message)" + } + case let .parseFailed(message): + "Azure OpenAI response parse error: \(message)" + } + } +} + +private struct AzureOpenAIChatCompletionResponse: Decodable { + let model: String? +} + +public enum AzureOpenAIUsageFetcher { + private static let timeoutSeconds: TimeInterval = 20 + private static let maxErrorBodyLength = 240 + + public static func fetchUsage( + apiKey: String, + endpoint: URL, + deploymentName: String, + apiVersion: String = AzureOpenAISettingsReader.defaultAPIVersion, + transport: any ProviderHTTPTransport = ProviderHTTPClient.shared, + updatedAt: Date = Date()) async throws -> AzureOpenAIUsageSnapshot + { + let apiKey = apiKey.trimmingCharacters(in: .whitespacesAndNewlines) + let deploymentName = deploymentName.trimmingCharacters(in: .whitespacesAndNewlines) + let apiVersion = apiVersion.trimmingCharacters(in: .whitespacesAndNewlines) + guard !apiKey.isEmpty else { throw AzureOpenAIUsageError.missingAPIKey } + guard !deploymentName.isEmpty else { throw AzureOpenAIUsageError.missingDeploymentName } + guard let endpoint = ProviderEndpointOverrideValidator.normalizedHTTPSURL(from: endpoint.absoluteString) else { + throw AzureOpenAIUsageError.invalidEndpointOverride(AzureOpenAISettingsReader.endpointEnvironmentKey) + } + let effectiveAPIVersion = apiVersion.isEmpty ? AzureOpenAISettingsReader.defaultAPIVersion : apiVersion + + var request = try URLRequest(url: self.chatCompletionsURL( + endpoint: endpoint, + deploymentName: deploymentName, + apiVersion: effectiveAPIVersion)) + request.httpMethod = "POST" + request.timeoutInterval = Self.timeoutSeconds + request.setValue(apiKey, forHTTPHeaderField: "api-key") + request.setValue("application/json", forHTTPHeaderField: "Accept") + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + request.httpBody = try self.validationRequestBody( + deploymentName: deploymentName, + apiVersion: effectiveAPIVersion) + + let response: ProviderHTTPResponse + do { + response = try await transport.response(for: request) + } catch { + throw AzureOpenAIUsageError.networkError(error.localizedDescription) + } + + guard (200..<300).contains(response.statusCode) else { + throw AzureOpenAIUsageError.apiError( + statusCode: response.statusCode, + message: self.responseSummary(response.data)) + } + + let model: String? + do { + model = try JSONDecoder().decode(AzureOpenAIChatCompletionResponse.self, from: response.data).model + } catch { + throw AzureOpenAIUsageError.parseFailed(error.localizedDescription) + } + + return AzureOpenAIUsageSnapshot( + endpointHost: endpoint.host ?? endpoint.absoluteString, + deploymentName: deploymentName, + model: model, + apiVersion: effectiveAPIVersion, + updatedAt: updatedAt) + } + + public static func _chatCompletionsURLForTesting( + endpoint: URL, + deploymentName: String, + apiVersion: String) throws -> URL + { + try self.chatCompletionsURL(endpoint: endpoint, deploymentName: deploymentName, apiVersion: apiVersion) + } + + private static func chatCompletionsURL( + endpoint: URL, + deploymentName: String, + apiVersion: String) throws -> URL + { + if self.usesV1API(apiVersion) { + let base = self.apiRoot(endpoint: endpoint, pathComponents: ["openai", "v1"]) + .appendingPathComponent("chat") + .appendingPathComponent("completions") + guard let url = URLComponents(url: base, resolvingAgainstBaseURL: false)?.url else { + throw AzureOpenAIUsageError.invalidURL + } + return url + } + + let base = self.apiRoot(endpoint: endpoint, pathComponents: ["openai"]) + .appendingPathComponent("deployments") + .appendingPathComponent(deploymentName) + .appendingPathComponent("chat") + .appendingPathComponent("completions") + guard var components = URLComponents(url: base, resolvingAgainstBaseURL: false) else { + throw AzureOpenAIUsageError.invalidURL + } + components.queryItems = [URLQueryItem(name: "api-version", value: apiVersion)] + guard let url = components.url else { throw AzureOpenAIUsageError.invalidURL } + return url + } + + private static func apiRoot(endpoint: URL, pathComponents expectedComponents: [String]) -> URL { + let existingComponents = endpoint.pathComponents + .filter { $0 != "/" } + .map { $0.lowercased() } + let expectedComponents = expectedComponents.map { $0.lowercased() } + let sharedCount = stride( + from: min(existingComponents.count, expectedComponents.count), + through: 0, + by: -1) + .first { count in + count == 0 || Array(existingComponents.suffix(count)) == Array(expectedComponents.prefix(count)) + } ?? 0 + return expectedComponents.dropFirst(sharedCount).reduce(endpoint) { url, component in + url.appendingPathComponent(component) + } + } + + private static func validationRequestBody( + deploymentName: String, + apiVersion: String) throws -> Data + { + var payload: [String: Any] = [ + "messages": [ + ["role": "user", "content": "ping"], + ], + ] + if self.usesV1API(apiVersion) { + payload["model"] = deploymentName + payload["max_completion_tokens"] = 1 + } else { + payload["max_tokens"] = 1 + } + return try JSONSerialization.data(withJSONObject: payload, options: []) + } + + private static func usesV1API(_ apiVersion: String) -> Bool { + apiVersion.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() == "v1" + } + + private static func responseSummary(_ data: Data) -> String { + guard let body = String(data: data, encoding: .utf8)? + .replacingOccurrences(of: #"\s+"#, with: " ", options: .regularExpression) + .trimmingCharacters(in: .whitespacesAndNewlines), + !body.isEmpty + else { + return "" + } + guard body.count > Self.maxErrorBodyLength else { return body } + let index = body.index(body.startIndex, offsetBy: Self.maxErrorBodyLength) + return "\(body[.. SignedHeadersInfo { + var headers: [(String, String)] = [] + if let allHeaders = request.allHTTPHeaderFields { + for (key, value) in allHeaders { + headers.append((key.lowercased(), value.trimmingCharacters(in: .whitespaces))) + } + } + headers.sort { $0.0 < $1.0 } + + let keys = headers.map(\.0).joined(separator: ";") + let canonical = headers.map { "\($0.0):\($0.1)" }.joined(separator: "\n") + return SignedHeadersInfo(keys: keys, canonical: canonical) + } + + private static func canonicalRequest( + request: URLRequest, + signedHeaders: SignedHeadersInfo, + bodyHash: String) -> String + { + let method = request.httpMethod ?? "GET" + let url = request.url! + let path = url.path.isEmpty ? "/" : url.path + let query = Self.canonicalQueryString(url: url) + + return [ + method, + Self.uriEncodePath(path), + query, + signedHeaders.canonical + "\n", + signedHeaders.keys, + bodyHash, + ].joined(separator: "\n") + } + + private static func canonicalQueryString(url: URL) -> String { + guard let components = URLComponents(url: url, resolvingAgainstBaseURL: false), + let queryItems = components.queryItems, + !queryItems.isEmpty + else { + return "" + } + + return queryItems + .map { item in + let key = Self.uriEncode(item.name) + let value = Self.uriEncode(item.value ?? "") + return "\(key)=\(value)" + } + .sorted() + .joined(separator: "&") + } + + private static func calculateSignature( + secretKey: String, + dateStamp: String, + region: String, + service: String, + stringToSign: String) -> String + { + let kDate = Self.hmacSHA256(key: Data("AWS4\(secretKey)".utf8), data: Data(dateStamp.utf8)) + let kRegion = Self.hmacSHA256(key: kDate, data: Data(region.utf8)) + let kService = Self.hmacSHA256(key: kRegion, data: Data(service.utf8)) + let kSigning = Self.hmacSHA256(key: kService, data: Data("aws4_request".utf8)) + let signature = Self.hmacSHA256(key: kSigning, data: Data(stringToSign.utf8)) + return signature.map { String(format: "%02x", $0) }.joined() + } + + private static func hmacSHA256(key: Data, data: Data) -> Data { + let symmetricKey = SymmetricKey(data: key) + let mac = HMAC.authenticationCode(for: data, using: symmetricKey) + return Data(mac) + } + + private static func sha256Hex(_ data: Data) -> String { + let digest = SHA256.hash(data: data) + return digest.map { String(format: "%02x", $0) }.joined() + } + + private static func dateFormatter() -> DateFormatter { + let formatter = DateFormatter() + formatter.dateFormat = "yyyyMMdd'T'HHmmss'Z'" + formatter.timeZone = TimeZone(identifier: "UTC") + formatter.locale = Locale(identifier: "en_US_POSIX") + return formatter + } + + private static func dateStamp(date: Date) -> String { + let formatter = DateFormatter() + formatter.dateFormat = "yyyyMMdd" + formatter.timeZone = TimeZone(identifier: "UTC") + formatter.locale = Locale(identifier: "en_US_POSIX") + return formatter.string(from: date) + } + + private static func uriEncode(_ string: String) -> String { + var allowed = CharacterSet.alphanumerics + allowed.insert(charactersIn: "-._~") + return string.addingPercentEncoding(withAllowedCharacters: allowed) ?? string + } + + private static func uriEncodePath(_ path: String) -> String { + path.split(separator: "/", omittingEmptySubsequences: false) + .map { self.uriEncode(String($0)) } + .joined(separator: "/") + } +} diff --git a/Sources/CodexBarCore/Providers/Bedrock/BedrockCloudWatchUsage.swift b/Sources/CodexBarCore/Providers/Bedrock/BedrockCloudWatchUsage.swift new file mode 100644 index 0000000..98c8bc3 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Bedrock/BedrockCloudWatchUsage.swift @@ -0,0 +1,231 @@ +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +struct BedrockClaudeActivity: Equatable { + let inputTokens: Int + let outputTokens: Int + let requestCount: Int +} + +enum BedrockCloudWatchUsageFetcher { + static let lookbackDays = 14 + + private static let maxResponseBytes = 4 * 1024 * 1024 + private static let maxPages = 20 + private static let requestTimeoutSeconds: TimeInterval = 15 + + private enum Metric: String, CaseIterable { + case inputTokens + case outputTokens + case requests + + var cloudWatchName: String { + switch self { + case .inputTokens: "InputTokenCount" + case .outputTokens: "OutputTokenCount" + case .requests: "Invocations" + } + } + } + + private struct RequestContext { + let credentials: BedrockAWSSigner.Credentials + let region: String + let now: Date + let endpoint: URL + let transport: any ProviderHTTPTransport + } + + static func fetch( + credentials: BedrockAWSSigner.Credentials, + region: String, + now: Date, + endpointOverride: String?, + transport: any ProviderHTTPTransport) async throws -> BedrockClaudeActivity + { + let totals = try await self.fetchTotals( + credentials: credentials, + region: region, + now: now, + endpointOverride: endpointOverride, + transport: transport) + + return BedrockClaudeActivity( + inputTokens: totals[.inputTokens] ?? 0, + outputTokens: totals[.outputTokens] ?? 0, + requestCount: totals[.requests] ?? 0) + } + + private static func fetchTotals( + credentials: BedrockAWSSigner.Credentials, + region: String, + now: Date, + endpointOverride: String?, + transport: any ProviderHTTPTransport) async throws -> [Metric: Int] + { + let context = try RequestContext( + credentials: credentials, + region: region, + now: now, + endpoint: self.endpoint(region: region, override: endpointOverride), + transport: transport) + var totals: [Metric: Double] = [:] + var nextToken: String? + var seenTokens: Set = [] + var pageCount = 0 + + repeat { + pageCount += 1 + guard pageCount <= self.maxPages else { + throw BedrockUsageError.cloudWatchParseFailed("too many response pages") + } + + let response = try await self.callPage( + context: context, + nextToken: nextToken) + for (metric, value) in response.totals { + totals[metric, default: 0] += value + } + nextToken = response.nextToken + if let nextToken, !seenTokens.insert(nextToken).inserted { + throw BedrockUsageError.cloudWatchParseFailed("repeated NextToken") + } + } while nextToken != nil + + var converted: [Metric: Int] = [:] + for metric in Metric.allCases { + let total = totals[metric] ?? 0 + guard total.isFinite, total >= 0, total <= Double(Int.max) else { + throw BedrockUsageError.cloudWatchParseFailed("invalid metric total") + } + converted[metric] = Int(total.rounded()) + } + return converted + } + + private static func callPage( + context: RequestContext, + nextToken: String?) async throws + -> (totals: [Metric: Double], nextToken: String?) + { + let start = context.now.addingTimeInterval(-Double(self.lookbackDays) * 24 * 60 * 60) + let queries: [[String: Any]] = Metric.allCases.map { metric in + let search = "SEARCH('{AWS/Bedrock,ModelId} " + + "MetricName=\"\(metric.cloudWatchName)\" claude', 'Sum', 86400)" + return [ + "Id": metric.rawValue, + "Expression": "SUM(\(search))", + "ReturnData": true, + ] + } + var payload: [String: Any] = [ + "StartTime": start.timeIntervalSince1970, + "EndTime": context.now.timeIntervalSince1970, + "ScanBy": "TimestampAscending", + "MetricDataQueries": queries, + ] + if let nextToken { + payload["NextToken"] = nextToken + } + + var request = URLRequest(url: context.endpoint) + request.httpMethod = "POST" + request.httpBody = try JSONSerialization.data(withJSONObject: payload) + request.timeoutInterval = self.requestTimeoutSeconds + request.setValue("application/x-amz-json-1.0", forHTTPHeaderField: "Content-Type") + request.setValue( + "GraniteServiceVersion20100801.GetMetricData", + forHTTPHeaderField: "X-Amz-Target") + BedrockAWSSigner.sign( + request: &request, + credentials: context.credentials, + region: context.region, + service: "monitoring") + + let response = try await context.transport.response(for: request) + guard response.statusCode == 200 else { + throw BedrockUsageError.cloudWatchAPIError("HTTP \(response.statusCode)") + } + guard response.data.count <= self.maxResponseBytes else { + throw BedrockUsageError.cloudWatchParseFailed("response exceeds 4 MiB") + } + return try self.parsePage(response.data) + } + + private static func endpoint(region: String, override: String?) throws -> URL { + if override != nil { + guard let override = BedrockSettingsReader.cleaned(override), + let url = ProviderEndpointOverrideValidator() + .validatedURLAllowingLoopbackHTTP(override) + else { + throw BedrockUsageError.cloudWatchParseFailed("invalid endpoint override") + } + return url + } + guard region.range( + of: #"^[a-z0-9]+(?:-[a-z0-9]+)+-[0-9]+$"#, + options: .regularExpression) != nil + else { + throw BedrockUsageError.cloudWatchParseFailed("invalid region endpoint") + } + // Match the CloudWatch partition suffixes published by the AWS SDK endpoint resolver. + let suffix = switch region { + case let region where region.hasPrefix("cn-"): + "amazonaws.com.cn" + case let region where region.hasPrefix("eusc-"): + "amazonaws.eu" + case let region where region.hasPrefix("us-iso-"): + "c2s.ic.gov" + case let region where region.hasPrefix("us-isob-"): + "sc2s.sgov.gov" + case let region where region.hasPrefix("eu-isoe-"): + "cloud.adc-e.uk" + case let region where region.hasPrefix("us-isof-"): + "csp.hci.ic.gov" + default: + "amazonaws.com" + } + guard let url = URL(string: "https://monitoring.\(region).\(suffix)") else { + throw BedrockUsageError.cloudWatchParseFailed("invalid region endpoint") + } + return url + } + + private static func parsePage(_ data: Data) throws + -> (totals: [Metric: Double], nextToken: String?) + { + guard let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else { + throw BedrockUsageError.cloudWatchParseFailed("invalid JSON response") + } + + if let messages = json["Messages"] as? [[String: Any]], !messages.isEmpty { + throw BedrockUsageError.cloudWatchParseFailed("CloudWatch reported incomplete results") + } + + let results = json["MetricDataResults"] as? [[String: Any]] ?? [] + var totals: [Metric: Double] = [:] + for result in results { + guard let id = result["Id"] as? String, let metric = Metric(rawValue: id) else { + throw BedrockUsageError.cloudWatchParseFailed("metric result had an unknown ID") + } + guard result["StatusCode"] as? String == "Complete" else { + throw BedrockUsageError.cloudWatchParseFailed("metric result was incomplete") + } + guard let values = result["Values"] as? [Any] else { continue } + for value in values { + guard let number = value as? NSNumber else { + throw BedrockUsageError.cloudWatchParseFailed("metric value was not numeric") + } + let double = number.doubleValue + guard double.isFinite, double >= 0 else { + throw BedrockUsageError.cloudWatchParseFailed("metric value was invalid") + } + totals[metric, default: 0] += double + } + } + + return (totals, BedrockSettingsReader.cleaned(json["NextToken"] as? String)) + } +} diff --git a/Sources/CodexBarCore/Providers/Bedrock/BedrockCredentialResolver.swift b/Sources/CodexBarCore/Providers/Bedrock/BedrockCredentialResolver.swift new file mode 100644 index 0000000..c5f3cac --- /dev/null +++ b/Sources/CodexBarCore/Providers/Bedrock/BedrockCredentialResolver.swift @@ -0,0 +1,78 @@ +import Foundation + +/// Resolves Bedrock signing credentials + region for the configured auth mode. +/// +/// Shared by the main usage fetch (`BedrockAPIFetchStrategy`) and the daily +/// cost-history refresh (`CostUsageFetcher`) so both honor AWS-profile auth +/// identically instead of the history path silently requiring static keys. +enum BedrockCredentialResolver { + struct Resolved { + let credentials: BedrockAWSSigner.Credentials + let region: String + } + + static func resolve( + environment: [String: String], + resolveAWSBinary: ([String: String]) -> String? = { BinaryLocator.resolveAWSBinary(env: $0) }, + makeProvider: (String) -> BedrockProfileCredentialProvider = { + BedrockProfileCredentialProvider.live(awsBinaryPath: $0) + }) async throws -> Resolved + { + switch BedrockSettingsReader.authMode(environment: environment) { + case .keys: + guard let accessKeyID = BedrockSettingsReader.accessKeyID(environment: environment), + let secretAccessKey = BedrockSettingsReader.secretAccessKey(environment: environment) + else { + throw BedrockUsageError.missingCredentials + } + let credentials = BedrockAWSSigner.Credentials( + accessKeyID: accessKeyID, + secretAccessKey: secretAccessKey, + sessionToken: BedrockSettingsReader.sessionToken(environment: environment)) + return Resolved( + credentials: credentials, + region: BedrockSettingsReader.region(environment: environment)) + + case .profile: + guard let profile = BedrockSettingsReader.profile(environment: environment) else { + throw BedrockUsageError.missingCredentials + } + guard let awsBinary = resolveAWSBinary(environment) else { + throw BedrockUsageError.awsCLINotFound + } + let cliEnvironment = Self.profileCLIEnvironment(environment) + let provider = makeProvider(awsBinary) + let credentials = try await provider.exportCredentials(profile: profile, environment: cliEnvironment) + let region = try await Self.resolveRegion( + provider: provider, + profile: profile, + environment: cliEnvironment) + return Resolved(credentials: credentials, region: region) + } + } + + private static func profileCLIEnvironment(_ environment: [String: String]) -> [String: String] { + var cliEnvironment = environment + // `--profile` selects the requested profile. Leaving AWS_PROFILE set can + // break assume-role profiles that use `credential_source = Environment`; + // keep the source credential variables themselves available. + cliEnvironment[BedrockSettingsReader.profileKey] = nil + return cliEnvironment + } + + private static func resolveRegion( + provider: BedrockProfileCredentialProvider, + profile: String, + environment: [String: String]) async throws -> String + { + if let explicit = BedrockSettingsReader.cleaned(environment[BedrockSettingsReader.regionKeys[0]]) + ?? BedrockSettingsReader.cleaned(environment[BedrockSettingsReader.regionKeys[1]]) + { + return explicit + } + if let derived = try await provider.resolveRegion(profile: profile, environment: environment) { + return derived + } + return BedrockSettingsReader.defaultRegion + } +} diff --git a/Sources/CodexBarCore/Providers/Bedrock/BedrockProfileCredentialProvider.swift b/Sources/CodexBarCore/Providers/Bedrock/BedrockProfileCredentialProvider.swift new file mode 100644 index 0000000..1f692f9 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Bedrock/BedrockProfileCredentialProvider.swift @@ -0,0 +1,87 @@ +import Foundation + +/// Resolves AWS credentials for a named profile by shelling out to the AWS CLI. +/// +/// Uses `aws configure export-credentials`, which transparently resolves static +/// credentials, SSO sessions, assume-role chains, and `credential_process` profiles. +/// The runner is injected so tests never invoke a real `aws` binary. +struct BedrockProfileCredentialProvider { + typealias Runner = @Sendable ( + _ arguments: [String], + _ environment: [String: String]) async throws -> SubprocessResult + + let awsBinaryPath: String + let run: Runner + + /// Production provider that drives the real `aws` binary via `SubprocessRunner`. + static func live(awsBinaryPath: String) -> BedrockProfileCredentialProvider { + BedrockProfileCredentialProvider(awsBinaryPath: awsBinaryPath) { arguments, environment in + try await SubprocessRunner.run( + binary: awsBinaryPath, + arguments: arguments, + environment: environment, + timeout: 20, + label: "aws-bedrock-credentials") + } + } + + func exportCredentials( + profile: String, + environment: [String: String] = [:]) async throws -> BedrockAWSSigner.Credentials + { + let result: SubprocessResult + do { + result = try await self.run( + ["configure", "export-credentials", "--profile", profile, "--format", "process"], + environment) + } catch let SubprocessRunnerError.nonZeroExit(_, stderr) { + throw Self.mapExportError(stderr: stderr, profile: profile) + } + + guard let data = result.stdout.data(using: .utf8), + let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any], + let accessKeyID = Self.nonEmpty(json["AccessKeyId"] as? String), + let secretAccessKey = Self.nonEmpty(json["SecretAccessKey"] as? String) + else { + throw BedrockUsageError.parseFailed("Could not parse AWS CLI export-credentials output") + } + + return BedrockAWSSigner.Credentials( + accessKeyID: accessKeyID, + secretAccessKey: secretAccessKey, + sessionToken: Self.nonEmpty(json["SessionToken"] as? String)) + } + + /// Returns the profile's configured region, or `nil` when unset. + /// `aws configure get region` exits non-zero when the value is not configured, + /// which is a normal case rather than an error. + func resolveRegion( + profile: String, + environment: [String: String] = [:]) async throws -> String? + { + do { + let result = try await self.run( + ["configure", "get", "region", "--profile", profile], + environment) + return Self.nonEmpty(result.stdout) + } catch SubprocessRunnerError.nonZeroExit { + return nil + } + } + + static func mapExportError(stderr: String, profile: String) -> BedrockUsageError { + let lower = stderr.lowercased() + if lower.contains("sso login") || lower.contains("expired") || lower.contains("token has expired") { + return .profileSessionExpired(profile) + } + let trimmed = stderr.trimmingCharacters(in: .whitespacesAndNewlines) + return .apiError(trimmed.isEmpty ? "AWS CLI failed to export credentials" : trimmed) + } + + private static func nonEmpty(_ raw: String?) -> String? { + guard let value = raw?.trimmingCharacters(in: .whitespacesAndNewlines), !value.isEmpty else { + return nil + } + return value + } +} diff --git a/Sources/CodexBarCore/Providers/Bedrock/BedrockProviderDescriptor.swift b/Sources/CodexBarCore/Providers/Bedrock/BedrockProviderDescriptor.swift new file mode 100644 index 0000000..d0e3310 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Bedrock/BedrockProviderDescriptor.swift @@ -0,0 +1,74 @@ +import Foundation + +public enum BedrockProviderDescriptor { + public static let descriptor: ProviderDescriptor = Self.makeDescriptor() + + static func makeDescriptor() -> ProviderDescriptor { + ProviderDescriptor( + id: .bedrock, + metadata: ProviderMetadata( + id: .bedrock, + displayName: "AWS Bedrock", + sessionLabel: "Budget", + weeklyLabel: "Cost", + opusLabel: nil, + supportsOpus: false, + supportsCredits: false, + creditsHint: "", + toggleTitle: "Show AWS Bedrock usage", + cliName: "bedrock", + defaultEnabled: false, + isPrimaryProvider: false, + usesAccountFallback: false, + dashboardURL: "https://console.aws.amazon.com/bedrock", + statusPageURL: nil, + statusLinkURL: "https://health.aws.amazon.com/health/status"), + branding: ProviderBranding( + iconStyle: .bedrock, + iconResourceName: "ProviderIcon-bedrock", + color: ProviderColor(red: 1, green: 0.6, blue: 0)), + tokenCost: ProviderTokenCostConfig( + supportsTokenCost: true, + noDataMessage: { "No AWS Bedrock cost data available. Check your AWS access keys " + + "or profile, and that the AWS CLI is installed for profile auth." + }), + fetchPlan: ProviderFetchPlan( + sourceModes: [.auto, .api], + pipeline: ProviderFetchPipeline(resolveStrategies: { _ in [BedrockAPIFetchStrategy()] })), + cli: ProviderCLIConfig( + name: "bedrock", + aliases: ["aws-bedrock"], + versionDetector: nil)) + } +} + +struct BedrockAPIFetchStrategy: ProviderFetchStrategy { + let id: String = "bedrock.api" + let kind: ProviderFetchKind = .apiToken + + func isAvailable(_ context: ProviderFetchContext) async -> Bool { + switch BedrockSettingsReader.authMode(environment: context.env) { + case .keys: + BedrockSettingsReader.hasCredentials(environment: context.env) + case .profile: + BedrockSettingsReader.profile(environment: context.env) != nil + } + } + + func fetch(_ context: ProviderFetchContext) async throws -> ProviderFetchResult { + let resolved = try await BedrockCredentialResolver.resolve(environment: context.env) + let budget = BedrockSettingsReader.budget(environment: context.env) + let usage = try await BedrockUsageFetcher.fetchUsage( + credentials: resolved.credentials, + region: resolved.region, + budget: budget, + environment: context.env) + return self.makeResult( + usage: usage.toUsageSnapshot(), + sourceLabel: "api") + } + + func shouldFallback(on _: any Error, context _: ProviderFetchContext) -> Bool { + false + } +} diff --git a/Sources/CodexBarCore/Providers/Bedrock/BedrockSettingsReader.swift b/Sources/CodexBarCore/Providers/Bedrock/BedrockSettingsReader.swift new file mode 100644 index 0000000..406a8b5 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Bedrock/BedrockSettingsReader.swift @@ -0,0 +1,107 @@ +import Foundation + +public enum BedrockAuthMode: String, Codable, Sendable, CaseIterable { + case keys + case profile +} + +public enum BedrockSettingsReader { + public static let accessKeyIDKey = "AWS_ACCESS_KEY_ID" + public static let secretAccessKeyKey = "AWS_SECRET_ACCESS_KEY" + public static let sessionTokenKey = "AWS_SESSION_TOKEN" + public static let regionKeys = ["AWS_REGION", "AWS_DEFAULT_REGION"] + public static let budgetKey = "CODEXBAR_BEDROCK_BUDGET" + public static let apiURLKey = "CODEXBAR_BEDROCK_API_URL" + public static let cloudWatchAPIURLKey = "CODEXBAR_BEDROCK_CLOUDWATCH_API_URL" + public static let profileKey = "AWS_PROFILE" + public static let authModeKey = "CODEXBAR_BEDROCK_AUTH_MODE" + public static let defaultRegion = "us-east-1" + + public static func accessKeyID(environment: [String: String] = ProcessInfo.processInfo.environment) -> String? { + self.cleaned(environment[self.accessKeyIDKey]) + } + + public static func secretAccessKey( + environment: [String: String] = ProcessInfo.processInfo.environment) -> String? + { + self.cleaned(environment[self.secretAccessKeyKey]) + } + + public static func sessionToken( + environment: [String: String] = ProcessInfo.processInfo.environment) -> String? + { + self.cleaned(environment[self.sessionTokenKey]) + } + + public static func region(environment: [String: String] = ProcessInfo.processInfo.environment) -> String { + for key in self.regionKeys { + if let value = self.cleaned(environment[key]) { + return value + } + } + return self.defaultRegion + } + + public static func budget(environment: [String: String] = ProcessInfo.processInfo.environment) -> Double? { + guard let raw = self.cleaned(environment[self.budgetKey]), + let value = Double(raw), + value > 0 + else { + return nil + } + return value + } + + public static func profile( + environment: [String: String] = ProcessInfo.processInfo.environment) -> String? + { + self.cleaned(environment[self.profileKey]) + } + + public static func authMode( + environment: [String: String] = ProcessInfo.processInfo.environment) -> BedrockAuthMode + { + if let raw = self.cleaned(environment[self.authModeKey])?.lowercased(), + let mode = BedrockAuthMode(rawValue: raw) + { + return mode + } + if self.profile(environment: environment) != nil, + !self.hasStaticKeys(environment: environment) + { + return .profile + } + return .keys + } + + static func hasStaticKeys(environment: [String: String]) -> Bool { + self.accessKeyID(environment: environment) != nil && + self.secretAccessKey(environment: environment) != nil + } + + public static func hasCredentials( + environment: [String: String] = ProcessInfo.processInfo.environment) -> Bool + { + switch self.authMode(environment: environment) { + case .keys: + self.hasStaticKeys(environment: environment) + case .profile: + self.profile(environment: environment) != nil + } + } + + static func cleaned(_ raw: String?) -> String? { + guard var value = raw?.trimmingCharacters(in: .whitespacesAndNewlines), !value.isEmpty else { + return nil + } + + if (value.hasPrefix("\"") && value.hasSuffix("\"")) || + (value.hasPrefix("'") && value.hasSuffix("'")) + { + value = String(value.dropFirst().dropLast()) + } + + value = value.trimmingCharacters(in: .whitespacesAndNewlines) + return value.isEmpty ? nil : value + } +} diff --git a/Sources/CodexBarCore/Providers/Bedrock/BedrockUsageStats.swift b/Sources/CodexBarCore/Providers/Bedrock/BedrockUsageStats.swift new file mode 100644 index 0000000..5852169 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Bedrock/BedrockUsageStats.swift @@ -0,0 +1,503 @@ +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +public struct BedrockUsageSnapshot: Codable, Sendable { + public let monthlySpend: Double + public let monthlyBudget: Double? + public let inputTokens: Int? + public let outputTokens: Int? + public let requestCount: Int? + public let region: String + public let updatedAt: Date + + public init( + monthlySpend: Double, + monthlyBudget: Double?, + inputTokens: Int? = nil, + outputTokens: Int? = nil, + requestCount: Int? = nil, + region: String, + updatedAt: Date) + { + self.monthlySpend = monthlySpend + self.monthlyBudget = monthlyBudget + self.inputTokens = inputTokens + self.outputTokens = outputTokens + self.requestCount = requestCount + self.region = region + self.updatedAt = updatedAt + } + + public var budgetUsedPercent: Double? { + guard let budget = self.monthlyBudget, budget > 0 else { return nil } + return min(100, max(0, (self.monthlySpend / budget) * 100)) + } + + public var totalTokens: Int? { + guard let input = self.inputTokens, let output = self.outputTokens else { return nil } + return input + output + } +} + +extension BedrockUsageSnapshot { + public func toUsageSnapshot() -> UsageSnapshot { + let primary: RateWindow? = if let usedPercent = self.budgetUsedPercent { + RateWindow( + usedPercent: usedPercent, + windowMinutes: nil, + resetsAt: Self.endOfCurrentMonth(), + resetDescription: "Monthly budget") + } else { + nil + } + + let cost = ProviderCostSnapshot( + used: self.monthlySpend, + limit: self.monthlyBudget ?? 0, + currencyCode: "USD", + period: "Monthly", + resetsAt: Self.endOfCurrentMonth(), + updatedAt: self.updatedAt) + + var loginParts: [String] = [] + loginParts.append(String(format: "Spend: $%.2f", self.monthlySpend)) + if let budget = self.monthlyBudget { + loginParts.append(String(format: "Budget: $%.2f", budget)) + } + if let total = self.totalTokens { + loginParts.append("Claude 14d: \(Self.formattedTokenCount(total)) tokens") + } + if let requestCount = self.requestCount { + loginParts.append("Requests: \(Self.formattedTokenCount(requestCount))") + } + + let identity = ProviderIdentitySnapshot( + providerID: .bedrock, + accountEmail: nil, + accountOrganization: nil, + loginMethod: loginParts.joined(separator: " - ")) + + return UsageSnapshot( + primary: primary, + secondary: nil, + tertiary: nil, + providerCost: cost, + updatedAt: self.updatedAt, + identity: identity) + } + + private static func endOfCurrentMonth() -> Date? { + let calendar = Calendar.current + guard let range = calendar.range(of: .day, in: .month, for: Date()) else { return nil } + let components = calendar.dateComponents([.year, .month], from: Date()) + guard let startOfMonth = calendar.date(from: components) else { return nil } + return calendar.date(byAdding: .day, value: range.count, to: startOfMonth) + } + + static func formattedTokenCount(_ count: Int) -> String { + if count >= 1_000_000 { + return String(format: "%.1fM", Double(count) / 1_000_000) + } else if count >= 1000 { + return String(format: "%.1fK", Double(count) / 1000) + } + return "\(count)" + } +} + +enum BedrockUsageFetcher { + private static let log = CodexBarLog.logger(LogCategories.bedrockUsage) + private static let requestTimeoutSeconds: TimeInterval = 15 + + private struct CostExplorerQuery { + let startDate: String + let endDate: String + let granularity: String + let nextPageToken: String? + } + + static func fetchUsage( + credentials: BedrockAWSSigner.Credentials, + region: String, + budget: Double?, + environment: [String: String] = ProcessInfo.processInfo.environment, + now: Date = Date(), + cloudWatchTransport: any ProviderHTTPTransport = ProviderHTTPClient.shared) async throws + -> BedrockUsageSnapshot + { + let spend = try await Self.fetchMonthlyCost( + credentials: credentials, + environment: environment) + + var activity: BedrockClaudeActivity? + let cloudWatchOverride = environment[BedrockSettingsReader.cloudWatchAPIURLKey] + let shouldFetchCloudWatch = environment[BedrockSettingsReader.apiURLKey] == nil || cloudWatchOverride != nil + if shouldFetchCloudWatch { + do { + activity = try await BedrockCloudWatchUsageFetcher.fetch( + credentials: credentials, + region: region, + now: now, + endpointOverride: cloudWatchOverride, + transport: cloudWatchTransport) + } catch { + if Task.isCancelled { throw error } + Self.log.debug("AWS CloudWatch Claude activity unavailable; keeping Cost Explorer usage.") + } + } + + return BedrockUsageSnapshot( + monthlySpend: spend, + monthlyBudget: budget, + inputTokens: activity?.inputTokens, + outputTokens: activity?.outputTokens, + requestCount: activity?.requestCount, + region: region, + updatedAt: now) + } + + static func fetchDailyReport( + credentials: BedrockAWSSigner.Credentials, + since: Date, + until: Date, + environment: [String: String] = ProcessInfo.processInfo.environment) async throws + -> CostUsageDailyReport + { + let formatter = Self.dateFormatter() + let startDate = formatter.string(from: since) + let inclusiveEnd = Self.utcCalendar().date(byAdding: .day, value: 1, to: until) ?? until + let endDate = formatter.string(from: inclusiveEnd) + + let pages = try await Self.callCostExplorerPages( + startDate: startDate, + endDate: endDate, + granularity: "DAILY", + credentials: credentials, + environment: environment) + + let entries = try Self.parseDailyResponses(pages) + return CostUsageDailyReport(data: entries, summary: nil) + } + + private static func fetchMonthlyCost( + credentials: BedrockAWSSigner.Credentials, + environment: [String: String]) async throws -> Double + { + let (startDate, endDate) = Self.currentMonthRange() + + let pages = try await Self.callCostExplorerPages( + startDate: startDate, + endDate: endDate, + granularity: "MONTHLY", + credentials: credentials, + environment: environment) + + return try Self.parseTotalCost(pages) + } + + private static func callCostExplorerPages( + startDate: String, + endDate: String, + granularity: String, + credentials: BedrockAWSSigner.Credentials, + environment: [String: String]) async throws -> [Data] + { + var pages: [Data] = [] + var nextPageToken: String? + var seenPageTokens: Set = [] + + repeat { + let page = try await Self.callCostExplorerPage( + query: CostExplorerQuery( + startDate: startDate, + endDate: endDate, + granularity: granularity, + nextPageToken: nextPageToken), + credentials: credentials, + environment: environment) + pages.append(page) + nextPageToken = try Self.nextPageToken(from: page) + if let nextPageToken, !seenPageTokens.insert(nextPageToken).inserted { + throw BedrockUsageError.parseFailed("Cost Explorer returned repeated NextPageToken") + } + } while nextPageToken != nil + + return pages + } + + private static func callCostExplorerPage( + query: CostExplorerQuery, + credentials: BedrockAWSSigner.Credentials, + environment: [String: String]) async throws -> Data + { + let ceRegion = "us-east-1" + let baseURL: URL = if environment[BedrockSettingsReader.apiURLKey] != nil { + if let override = BedrockSettingsReader.cleaned(environment[BedrockSettingsReader.apiURLKey]), + let url = ProviderEndpointOverrideValidator().validatedURLAllowingLoopbackHTTP(override) + { + url + } else { + throw BedrockUsageError.parseFailed("invalid endpoint override") + } + } else { + URL(string: "https://ce.\(ceRegion).amazonaws.com")! + } + + var requestBody: [String: Any] = [ + "TimePeriod": [ + "Start": query.startDate, + "End": query.endDate, + ], + "Granularity": query.granularity, + "Metrics": ["UnblendedCost"], + "GroupBy": [ + ["Type": "DIMENSION", "Key": "SERVICE"], + ], + ] + if let nextPageToken = query.nextPageToken { + requestBody["NextPageToken"] = nextPageToken + } + + let bodyData = try JSONSerialization.data(withJSONObject: requestBody) + + var request = URLRequest(url: baseURL) + request.httpMethod = "POST" + request.httpBody = bodyData + request.setValue("application/x-amz-json-1.1", forHTTPHeaderField: "Content-Type") + request.setValue( + "AWSInsightsIndexService.GetCostAndUsage", + forHTTPHeaderField: "X-Amz-Target") + request.timeoutInterval = Self.requestTimeoutSeconds + + BedrockAWSSigner.sign( + request: &request, + credentials: credentials, + region: ceRegion, + service: "ce") + + let response = try await ProviderHTTPClient.shared.response(for: request) + guard response.statusCode == 200 else { + if Self.isDataUnavailableResponse(statusCode: response.statusCode, data: response.data) { + Self.log.info("AWS Cost Explorer data unavailable, assuming zero usage.") + return Data(#"{"ResultsByTime":[]}"#.utf8) + } + let summary = Self.sanitizedResponseBody(response.data) + Self.log.error("AWS Cost Explorer returned \(response.statusCode): \(summary)") + throw BedrockUsageError.apiError("HTTP \(response.statusCode)") + } + + return response.data + } + + private static func nextPageToken(from data: Data) throws -> String? { + guard let json = try JSONSerialization.jsonObject(with: data) as? [String: Any] else { + throw BedrockUsageError.parseFailed("Invalid Cost Explorer response") + } + return BedrockSettingsReader.cleaned(json["NextPageToken"] as? String) + } + + private static func parseTotalCost(_ pages: [Data]) throws -> Double { + var total = 0.0 + for page in pages { + total += try Self.parseTotalCost(page) + } + return total + } + + private static func parseTotalCost(_ data: Data) throws -> Double { + var total = 0.0 + for (_, cost, _) in try Self.parseGroupedResults(data) { + total += cost + } + return total + } + + private static func parseDailyResponses(_ pages: [Data]) throws -> [CostUsageDailyReport.Entry] { + let reports = try pages.map { page in + try CostUsageDailyReport(data: Self.parseDailyResponse(page), summary: nil) + } + return CostUsageDailyReport.merged(reports).data + } + + private static func parseDailyResponse(_ data: Data) throws -> [CostUsageDailyReport.Entry] { + guard let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any], + let results = json["ResultsByTime"] as? [[String: Any]] + else { + throw BedrockUsageError.parseFailed("Missing ResultsByTime in Cost Explorer response") + } + + var entries: [CostUsageDailyReport.Entry] = [] + for result in results { + guard let timePeriod = result["TimePeriod"] as? [String: String], + let dateStr = timePeriod["Start"] + else { continue } + + var dayCost = 0.0 + var breakdowns: [CostUsageDailyReport.ModelBreakdown] = [] + + if let groups = result["Groups"] as? [[String: Any]] { + for group in groups { + guard let keys = group["Keys"] as? [String], + let serviceName = keys.first, + serviceName.localizedCaseInsensitiveContains("Bedrock") + else { continue } + + if let metrics = group["Metrics"] as? [String: Any], + let unblended = metrics["UnblendedCost"] as? [String: Any], + let amountStr = unblended["Amount"] as? String, + let amount = Double(amountStr), + amount > 0 + { + dayCost += amount + breakdowns.append(CostUsageDailyReport.ModelBreakdown( + modelName: serviceName, + costUSD: amount)) + } + } + } + + guard dayCost > 0 else { continue } + + entries.append(CostUsageDailyReport.Entry( + date: dateStr, + inputTokens: nil, + outputTokens: nil, + totalTokens: nil, + costUSD: dayCost, + modelsUsed: breakdowns.map(\.modelName), + modelBreakdowns: breakdowns.isEmpty ? nil : breakdowns)) + } + + return entries + } + + private static func parseGroupedResults(_ data: Data) throws + -> [(service: String, cost: Double, date: String)] + { + guard let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any], + let results = json["ResultsByTime"] as? [[String: Any]] + else { + throw BedrockUsageError.parseFailed("Missing ResultsByTime in Cost Explorer response") + } + + var items: [(service: String, cost: Double, date: String)] = [] + for result in results { + let dateStr = (result["TimePeriod"] as? [String: String])?["Start"] ?? "" + guard let groups = result["Groups"] as? [[String: Any]] else { continue } + for group in groups { + guard let keys = group["Keys"] as? [String], + let serviceName = keys.first, + serviceName.localizedCaseInsensitiveContains("Bedrock") + else { continue } + + if let metrics = group["Metrics"] as? [String: Any], + let unblended = metrics["UnblendedCost"] as? [String: Any], + let amountStr = unblended["Amount"] as? String, + let amount = Double(amountStr) + { + items.append((serviceName, amount, dateStr)) + } + } + } + return items + } + + private static func dateFormatter() -> DateFormatter { + let formatter = DateFormatter() + formatter.dateFormat = "yyyy-MM-dd" + formatter.timeZone = TimeZone(identifier: "UTC") + formatter.locale = Locale(identifier: "en_US_POSIX") + return formatter + } + + private static func utcCalendar() -> Calendar { + var calendar = Calendar(identifier: .gregorian) + calendar.timeZone = TimeZone(secondsFromGMT: 0)! + return calendar + } + + static func currentMonthRange(now: Date = Date()) -> (start: String, end: String) { + let calendar = Self.utcCalendar() + let components = calendar.dateComponents([.year, .month], from: now) + let startOfMonth = calendar.date(from: components)! + + let formatter = Self.dateFormatter() + let startOfToday = calendar.startOfDay(for: now) + let tomorrow = calendar.date(byAdding: .day, value: 1, to: startOfToday)! + return (formatter.string(from: startOfMonth), formatter.string(from: tomorrow)) + } + + private static func isDataUnavailableResponse(statusCode: Int, data: Data) -> Bool { + guard statusCode == 400, + let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] + else { + return false + } + + let nestedError = json["Error"] as? [String: Any] + let candidates = [ + json["__type"], + json["code"], + json["Code"], + nestedError?["Code"], + ] + return candidates.compactMap { $0 as? String }.contains { rawCode in + rawCode.split(separator: "#").last == "DataUnavailableException" + } + } + + private static func sanitizedResponseBody(_ data: Data) -> String { + guard !data.isEmpty, + let body = String(bytes: data, encoding: .utf8) + else { + return "empty body" + } + + let trimmed = body.replacingOccurrences( + of: #"\s+"#, + with: " ", + options: .regularExpression) + .trimmingCharacters(in: .whitespacesAndNewlines) + + if trimmed.count > 240 { + let index = trimmed.index(trimmed.startIndex, offsetBy: 240) + return "\(trimmed[.. ProviderDescriptor { + ProviderDescriptor( + id: .chutes, + metadata: ProviderMetadata( + id: .chutes, + displayName: "Chutes", + sessionLabel: "4-hour quota", + weeklyLabel: "Monthly quota", + opusLabel: nil, + supportsOpus: false, + supportsCredits: false, + creditsHint: "Subscription usage from the Chutes API.", + toggleTitle: "Show Chutes usage", + cliName: "chutes", + defaultEnabled: false, + isPrimaryProvider: false, + usesAccountFallback: false, + browserCookieOrder: nil, + dashboardURL: "https://chutes.ai", + statusPageURL: nil), + branding: ProviderBranding( + iconStyle: .chutes, + iconResourceName: "ProviderIcon-chutes", + color: ProviderColor(red: 49 / 255, green: 132 / 255, blue: 255 / 255)), + tokenCost: ProviderTokenCostConfig( + supportsTokenCost: false, + noDataMessage: { "Chutes cost history is not available from CodexBar." }), + fetchPlan: ProviderFetchPlan( + sourceModes: [.auto, .api], + pipeline: ProviderFetchPipeline(resolveStrategies: { _ in [ChutesAPIFetchStrategy()] })), + cli: ProviderCLIConfig( + name: "chutes", + aliases: ["chutes.ai"], + versionDetector: nil)) + } +} + +struct ChutesAPIFetchStrategy: ProviderFetchStrategy { + let id: String = "chutes.api" + let kind: ProviderFetchKind = .apiToken + + func isAvailable(_ context: ProviderFetchContext) async -> Bool { + ChutesSettingsReader.apiKey(environment: context.env) != nil + } + + func fetch(_ context: ProviderFetchContext) async throws -> ProviderFetchResult { + guard let apiKey = ChutesSettingsReader.apiKey(environment: context.env) else { + throw ChutesSettingsError.missingToken + } + + let usage = try await ChutesUsageFetcher.fetchUsage( + apiKey: apiKey, + environment: context.env) + + return self.makeResult( + usage: usage.toUsageSnapshot(), + sourceLabel: "api") + } + + func shouldFallback(on _: Error, context _: ProviderFetchContext) -> Bool { + false + } +} diff --git a/Sources/CodexBarCore/Providers/Chutes/ChutesSettingsReader.swift b/Sources/CodexBarCore/Providers/Chutes/ChutesSettingsReader.swift new file mode 100644 index 0000000..f1bb5af --- /dev/null +++ b/Sources/CodexBarCore/Providers/Chutes/ChutesSettingsReader.swift @@ -0,0 +1,63 @@ +import Foundation + +public struct ChutesSettingsReader: Sendable { + public static let apiKeyEnvironmentKey = "CHUTES_API_KEY" + public static let apiURLEnvironmentKey = "CHUTES_API_URL" + + public static func apiKey( + environment: [String: String] = ProcessInfo.processInfo.environment) -> String? + { + self.cleaned(environment[self.apiKeyEnvironmentKey]) + } + + public static func apiURL( + environment: [String: String] = ProcessInfo.processInfo.environment) -> URL + { + if let override = self.validAPIURL(environment: environment) { + return override + } + return URL(string: "https://api.chutes.ai")! + } + + public static func validateEndpointOverrides( + environment: [String: String] = ProcessInfo.processInfo.environment) throws + { + guard let raw = self.cleaned(environment[self.apiURLEnvironmentKey]) else { return } + guard ProviderEndpointOverrideValidator.normalizedHTTPSURL(from: raw) == nil else { return } + throw ChutesSettingsError.invalidEndpointOverride(self.apiURLEnvironmentKey) + } + + static func cleaned(_ raw: String?) -> String? { + guard var value = raw?.trimmingCharacters(in: .whitespacesAndNewlines), !value.isEmpty else { + return nil + } + + if (value.hasPrefix("\"") && value.hasSuffix("\"")) || + (value.hasPrefix("'") && value.hasSuffix("'")) + { + value = String(value.dropFirst().dropLast()) + } + + value = value.trimmingCharacters(in: .whitespacesAndNewlines) + return value.isEmpty ? nil : value + } + + private static func validAPIURL(environment: [String: String]) -> URL? { + guard let raw = self.cleaned(environment[self.apiURLEnvironmentKey]) else { return nil } + return ProviderEndpointOverrideValidator.normalizedHTTPSURL(from: raw) + } +} + +public enum ChutesSettingsError: LocalizedError, Sendable, Equatable { + case missingToken + case invalidEndpointOverride(String) + + public var errorDescription: String? { + switch self { + case .missingToken: + "Chutes API key not found. Set apiKey in ~/.codexbar/config.json or CHUTES_API_KEY." + case let .invalidEndpointOverride(key): + "Chutes endpoint override \(key) must use HTTPS or a bare host." + } + } +} diff --git a/Sources/CodexBarCore/Providers/Chutes/ChutesUsageStats.swift b/Sources/CodexBarCore/Providers/Chutes/ChutesUsageStats.swift new file mode 100644 index 0000000..3dd9a88 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Chutes/ChutesUsageStats.swift @@ -0,0 +1,1045 @@ +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +public enum ChutesUsageError: LocalizedError, Sendable { + case missingCredentials + case invalidCredentials + case invalidURL + case apiError(String) + case parseFailed(String) + + public var errorDescription: String? { + switch self { + case .missingCredentials: + "Missing Chutes API key. Set apiKey in ~/.codexbar/config.json or CHUTES_API_KEY." + case .invalidCredentials: + "Chutes API key was rejected. Check the API key in Settings." + case .invalidURL: + "Chutes usage URL is invalid." + case let .apiError(message): + "Chutes usage API error: \(message)" + case let .parseFailed(message): + "Chutes usage parse error: \(message)" + } + } +} + +public enum ChutesSubscriptionState: String, Sendable, Codable { + case active + case inactive + case unknown +} + +public struct ChutesQuotaWindow: Sendable, Equatable { + public let label: String? + public let used: Double? + public let limit: Double? + public let remaining: Double? + public let usedPercent: Double? + public let windowMinutes: Int? + public let resetsAt: Date? + public let unit: String? + + public init( + label: String?, + used: Double?, + limit: Double?, + remaining: Double?, + usedPercent: Double?, + windowMinutes: Int?, + resetsAt: Date?, + unit: String? = nil) + { + self.label = label + self.used = used + self.limit = limit + self.remaining = remaining + self.usedPercent = usedPercent + self.windowMinutes = windowMinutes + self.resetsAt = resetsAt + self.unit = unit + } + + public func rateWindow(defaultWindowMinutes: Int?) -> RateWindow? { + guard let percent = self.usagePercent else { return nil } + return RateWindow( + usedPercent: max(0, min(percent, 100)), + windowMinutes: self.windowMinutes ?? defaultWindowMinutes, + resetsAt: self.resetsAt, + resetDescription: self.usageDescription) + } + + public var usagePercent: Double? { + if let usedPercent { return max(0, min(usedPercent, 100)) } + + var used = self.used + var limit = self.limit + var remaining = self.remaining + + if limit == nil, let used, let remaining { + limit = used + remaining + } + if used == nil, let limit, let remaining { + used = limit - remaining + } + if remaining == nil, let limit, let used { + remaining = max(0, limit - used) + } + + guard let used, let limit, limit > 0 else { return nil } + return (used / limit) * 100 + } + + private var usageDescription: String? { + guard let limit, limit > 0 else { return nil } + + let used: Double + if let explicitUsed = self.used { + used = explicitUsed + } else if let remaining { + used = max(0, limit - remaining) + } else { + return nil + } + + let unit = self.unit?.trimmingCharacters(in: .whitespacesAndNewlines) + let suffix = if let unit, !unit.isEmpty { + " \(unit)" + } else { + "" + } + return "\(Self.formatAmount(used))/\(Self.formatAmount(limit))\(suffix)" + } + + private static func formatAmount(_ value: Double) -> String { + let rounded = value.rounded() + if abs(value - rounded) < 0.0001 { + return String(Int(rounded)) + } + + var text = String(format: "%.2f", value) + while text.contains("."), text.hasSuffix("0") { + text.removeLast() + } + if text.hasSuffix(".") { + text.removeLast() + } + return text + } +} + +public struct ChutesUsageSnapshot: Sendable, Equatable { + public let rollingWindow: ChutesQuotaWindow? + public let monthlyWindow: ChutesQuotaWindow? + public let fallbackWindows: [ChutesQuotaWindow] + public let subscriptionState: ChutesSubscriptionState + public let planName: String? + public let subscriptionRenewsAt: Date? + public let updatedAt: Date + + public init( + rollingWindow: ChutesQuotaWindow?, + monthlyWindow: ChutesQuotaWindow?, + fallbackWindows: [ChutesQuotaWindow] = [], + subscriptionState: ChutesSubscriptionState, + planName: String?, + subscriptionRenewsAt: Date?, + updatedAt: Date) + { + self.rollingWindow = rollingWindow + self.monthlyWindow = monthlyWindow + self.fallbackWindows = fallbackWindows + self.subscriptionState = subscriptionState + self.planName = planName + self.subscriptionRenewsAt = subscriptionRenewsAt + self.updatedAt = updatedAt + } + + public var hasUsageData: Bool { + self.toUsageSnapshot().hasRateLimitWindows + } + + public func toUsageSnapshot() -> UsageSnapshot { + let fallbackRateWindows = self.fallbackWindows.compactMap { + $0.rateWindow(defaultWindowMinutes: $0.windowMinutes) + } + let monthly = self.monthlyWindow?.rateWindow(defaultWindowMinutes: Self.monthlyWindowMinutes) + let rolling = self.rollingWindow?.rateWindow(defaultWindowMinutes: Self.rollingWindowMinutes) + + let primary = rolling ?? (monthly == nil ? fallbackRateWindows.first : nil) + let secondary: RateWindow? = if let monthly { + monthly + } else if rolling != nil { + fallbackRateWindows.first + } else if primary != nil { + fallbackRateWindows.dropFirst().first + } else { + nil + } + + let identity = ProviderIdentitySnapshot( + providerID: .chutes, + accountEmail: nil, + accountOrganization: nil, + loginMethod: self.loginMethod(hasWindows: primary != nil || secondary != nil)) + + return UsageSnapshot( + primary: primary, + secondary: secondary, + tertiary: nil, + providerCost: nil, + subscriptionRenewsAt: self.subscriptionRenewsAt ?? monthly?.resetsAt, + updatedAt: self.updatedAt, + identity: identity) + } + + func preservingSubscriptionContext(from fallback: ChutesUsageSnapshot) -> ChutesUsageSnapshot { + ChutesUsageSnapshot( + rollingWindow: fallback.rollingWindow ?? self.rollingWindow, + monthlyWindow: fallback.monthlyWindow ?? self.monthlyWindow, + fallbackWindows: fallback.fallbackWindows + self.fallbackWindows, + subscriptionState: fallback.subscriptionState, + planName: fallback.planName, + subscriptionRenewsAt: fallback.subscriptionRenewsAt, + updatedAt: fallback.updatedAt) + } + + private func loginMethod(hasWindows: Bool) -> String? { + if let planName = self.planName?.trimmingCharacters(in: .whitespacesAndNewlines), !planName.isEmpty { + return planName + } + switch self.subscriptionState { + case .active: + return nil + case .inactive: + return "No active subscription" + case .unknown: + return hasWindows ? nil : "No usage data" + } + } + + static let rollingWindowMinutes = 4 * 60 + static let monthlyWindowMinutes = 30 * 24 * 60 +} + +public struct ChutesUsageFetcher: Sendable { + private static let requestTimeoutSeconds: TimeInterval = 15 + + public static func fetchUsage( + apiKey: String, + environment: [String: String] = ProcessInfo.processInfo.environment, + transport: any ProviderHTTPTransport = ProviderHTTPClient.shared, + now: Date = Date()) async throws -> ChutesUsageSnapshot + { + guard let token = ChutesSettingsReader.cleaned(apiKey) else { + throw ChutesUsageError.missingCredentials + } + try ChutesSettingsReader.validateEndpointOverrides(environment: environment) + + let baseURL = ChutesSettingsReader.apiURL(environment: environment) + let subscription = try await self.fetchSnapshot( + pathComponents: ["users", "me", "subscription_usage"], + apiKey: token, + baseURL: baseURL, + transport: transport, + now: now) + + guard subscription.rollingWindow == nil || subscription.monthlyWindow == nil else { + return subscription + } + + do { + let quotas = try await self.fetchQuotaSnapshot( + apiKey: token, + baseURL: baseURL, + transport: transport, + now: now) + return quotas.hasUsageData ? quotas.preservingSubscriptionContext(from: subscription) : subscription + } catch ChutesUsageError.invalidCredentials { + throw ChutesUsageError.invalidCredentials + } catch { + return subscription + } + } + + private static func fetchSnapshot( + pathComponents: [String], + apiKey: String, + baseURL: URL, + transport: any ProviderHTTPTransport, + now: Date) async throws -> ChutesUsageSnapshot + { + let data = try await self.fetchData( + pathComponents: pathComponents, + apiKey: apiKey, + baseURL: baseURL, + transport: transport) + do { + return try ChutesUsageParser.parse(data: data, now: now) + } catch let error as ChutesUsageError { + throw error + } catch { + throw ChutesUsageError.parseFailed(error.localizedDescription) + } + } + + private static func fetchQuotaSnapshot( + apiKey: String, + baseURL: URL, + transport: any ProviderHTTPTransport, + now: Date) async throws -> ChutesUsageSnapshot + { + let data = try await self.fetchData( + pathComponents: ["users", "me", "quotas"], + apiKey: apiKey, + baseURL: baseURL, + transport: transport) + let fallback = try ChutesUsageParser.parse(data: data, now: now) + let definitions = try self.quotaDefinitions(from: data) + guard !definitions.isEmpty else { return fallback } + + var enrichedDefinitions: [[String: Any]] = [] + for definition in definitions { + guard let identifier = self.quotaIdentifier(from: definition) else { + enrichedDefinitions.append(definition) + continue + } + + do { + let usageData = try await self.fetchData( + pathComponents: ["users", "me", "quota_usage", identifier], + apiKey: apiKey, + baseURL: baseURL, + transport: transport) + guard let usage = try self.responseDictionary(from: usageData) else { + enrichedDefinitions.append(definition) + continue + } + enrichedDefinitions.append(definition.merging(usage) { _, usageValue in usageValue }) + } catch ChutesUsageError.invalidCredentials { + throw ChutesUsageError.invalidCredentials + } catch { + enrichedDefinitions.append(definition) + } + } + + let enrichedData = try JSONSerialization.data( + withJSONObject: ["quotas": enrichedDefinitions], + options: []) + let enriched = try ChutesUsageParser.parse(data: enrichedData, now: now) + return enriched.hasUsageData ? enriched : fallback + } + + private static func fetchData( + pathComponents: [String], + apiKey: String, + baseURL: URL, + transport: any ProviderHTTPTransport) async throws -> Data + { + let url = pathComponents.reduce(baseURL) { partial, component in + partial.appendingPathComponent(component) + } + guard url.scheme?.lowercased() == "https" else { + throw ChutesUsageError.invalidURL + } + + var request = URLRequest(url: url) + request.httpMethod = "GET" + request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization") + request.setValue("application/json", forHTTPHeaderField: "Accept") + request.timeoutInterval = Self.requestTimeoutSeconds + + let response = try await transport.response(for: request) + guard (200..<300).contains(response.statusCode) else { + if response.statusCode == 401 || response.statusCode == 403 { + throw ChutesUsageError.invalidCredentials + } + throw ChutesUsageError.apiError("HTTP \(response.statusCode): \(Self.responseSummary(response.data))") + } + return response.data + } + + private static func quotaDefinitions(from data: Data) throws -> [[String: Any]] { + let object = try JSONSerialization.jsonObject(with: data, options: []) + if let array = object as? [Any] { + return array.compactMap { $0 as? [String: Any] } + } + guard let dictionary = object as? [String: Any] else { return [] } + if let quotas = dictionary["quotas"] as? [Any] { + return quotas.compactMap { $0 as? [String: Any] } + } + if let data = dictionary["data"] as? [Any] { + return data.compactMap { $0 as? [String: Any] } + } + if let data = dictionary["data"] as? [String: Any], + let quotas = data["quotas"] as? [Any] + { + return quotas.compactMap { $0 as? [String: Any] } + } + return [] + } + + private static func quotaIdentifier(from definition: [String: Any]) -> String? { + for key in ["chute_id", "chuteId", "id"] { + if let value = definition[key] as? String { + let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines) + if !trimmed.isEmpty { return trimmed } + } + if let value = definition[key] as? NSNumber { + return value.stringValue + } + } + return nil + } + + private static func responseDictionary(from data: Data) throws -> [String: Any]? { + guard let dictionary = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else { + return nil + } + return dictionary["data"] as? [String: Any] + ?? dictionary["result"] as? [String: Any] + ?? dictionary + } + + private static func responseSummary(_ data: Data) -> String { + String(bytes: data.prefix(240), encoding: .utf8)? + .trimmingCharacters(in: .whitespacesAndNewlines) + ?? "" + } +} + +private final class ChutesISO8601FormatterBox: @unchecked Sendable { + let lock = NSLock() + let withFractional: ISO8601DateFormatter = { + let formatter = ISO8601DateFormatter() + formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds] + return formatter + }() + + let plain: ISO8601DateFormatter = { + let formatter = ISO8601DateFormatter() + formatter.formatOptions = [.withInternetDateTime] + return formatter + }() +} + +private enum ChutesTimestampParser { + static let box = ChutesISO8601FormatterBox() + + static func parse(_ value: Any?) -> Date? { + switch value { + case let date as Date: + date + case let number as NSNumber: + self.date(fromEpochValue: number.doubleValue) + case let text as String: + self.parseString(text) + default: + nil + } + } + + private static func parseString(_ raw: String) -> Date? { + let text = raw.trimmingCharacters(in: .whitespacesAndNewlines) + guard !text.isEmpty else { return nil } + if let number = Double(text) { + return self.date(fromEpochValue: number) + } + + self.box.lock.lock() + defer { self.box.lock.unlock() } + return self.box.withFractional.date(from: text) ?? self.box.plain.date(from: text) + } + + private static func date(fromEpochValue value: Double) -> Date? { + guard value.isFinite, value > 0 else { return nil } + let seconds = value > 10_000_000_000 ? value / 1000 : value + return Date(timeIntervalSince1970: seconds) + } +} + +enum ChutesUsageParser { + static func parse(data: Data, now: Date = Date()) throws -> ChutesUsageSnapshot { + let object = try JSONSerialization.jsonObject(with: data, options: []) + return self.parse(object: object, now: now) + } + + private static func parse(object: Any, now: Date) -> ChutesUsageSnapshot { + let root: [String: Any] = { + if let dict = object as? [String: Any] { return dict } + if let array = object as? [Any] { return ["quotas": array] } + return [:] + }() + let dataRoot = self.dictionaryValue(self.value(in: root, keys: ["data", "result"])) ?? root + let subscription = self.subscriptionPayload(root: root, dataRoot: dataRoot) + + let explicitRolling = self.firstDictionary( + in: root, + dataRoot: dataRoot, + keys: self.rollingPayloadKeys) + .flatMap { + self.parseQuota( + $0, + defaultLabel: "4-hour quota", + defaultWindowMinutes: ChutesUsageSnapshot.rollingWindowMinutes) + } + let explicitMonthly = self.firstDictionary( + in: root, + dataRoot: dataRoot, + keys: self.monthlyPayloadKeys) + .flatMap { + self.parseQuota( + $0, + defaultLabel: "Monthly quota", + defaultWindowMinutes: ChutesUsageSnapshot.monthlyWindowMinutes) + } + + let quotaWindows = self.fallbackQuotaObjects(from: root, dataRoot: dataRoot).compactMap { + self.parseQuota($0, defaultLabel: nil, defaultWindowMinutes: nil) + } + let classifiedRolling = explicitRolling ?? quotaWindows.first { self.kind(for: $0) == .rolling } + let classifiedMonthly = explicitMonthly ?? quotaWindows.first { self.kind(for: $0) == .monthly } + + let fallbackWindows = quotaWindows.filter { window in + Optional.some(window) != classifiedRolling && Optional.some(window) != classifiedMonthly + } + + return ChutesUsageSnapshot( + rollingWindow: classifiedRolling, + monthlyWindow: classifiedMonthly, + fallbackWindows: fallbackWindows, + subscriptionState: self.subscriptionState(root: root, dataRoot: dataRoot, subscription: subscription), + planName: self.planName(root: root, dataRoot: dataRoot, subscription: subscription), + subscriptionRenewsAt: self.subscriptionRenewsAt( + root: root, + dataRoot: dataRoot, + subscription: subscription), + updatedAt: now) + } + + private enum WindowKind { + case rolling + case monthly + } + + private static func parseQuota( + _ payload: [String: Any], + defaultLabel: String?, + defaultWindowMinutes: Int?) -> ChutesQuotaWindow? + { + let label = self.firstString(in: payload, keys: self.labelKeys) ?? defaultLabel + let limit = self.firstDouble(in: payload, keys: self.limitKeys) + let used = self.firstDouble(in: payload, keys: self.usedKeys) + let remaining = self.firstDouble(in: payload, keys: self.remainingKeys) + var usedPercent = self.normalizedPercent(self.firstDouble(in: payload, keys: self.percentUsedKeys)) + if usedPercent == nil, + let remainingPercent = self.normalizedPercent(self.firstDouble(in: payload, keys: percentRemainingKeys)) + { + usedPercent = 100 - remainingPercent + } + + let window = self.windowMinutes(from: payload) ?? defaultWindowMinutes + let resetsAt = self.firstDate(in: payload, keys: self.resetKeys) + let unit = self.firstString(in: payload, keys: self.unitKeys) ?? "credits" + + let quota = ChutesQuotaWindow( + label: label, + used: used, + limit: limit, + remaining: remaining, + usedPercent: usedPercent, + windowMinutes: window, + resetsAt: resetsAt, + unit: unit) + return quota.usagePercent == nil ? nil : quota + } + + private static func subscriptionPayload(root: [String: Any], dataRoot: [String: Any]) -> [String: Any]? { + self.firstDictionary(in: root, dataRoot: dataRoot, keys: [ + "subscription", + "subscription_usage", + "subscriptionUsage", + "current_subscription", + "currentSubscription", + "plan", + ]) + } + + private static func subscriptionState( + root: [String: Any], + dataRoot: [String: Any], + subscription: [String: Any]?) -> ChutesSubscriptionState + { + if let active = self.firstBool(in: root, keys: activeKeys) + ?? self.firstBool(in: dataRoot, keys: activeKeys) + ?? subscription.flatMap({ self.firstBool(in: $0, keys: activeKeys) }) + { + return active ? .active : .inactive + } + + let status = self.firstString(in: root, keys: self.statusKeys) + ?? self.firstString(in: dataRoot, keys: self.statusKeys) + ?? subscription.flatMap { self.firstString(in: $0, keys: self.statusKeys) } + let normalizedStatus = status?.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() + guard let normalizedStatus, !normalizedStatus.isEmpty else { return .unknown } + if normalizedStatus.contains("active") && !normalizedStatus.contains("inactive") { + return .active + } + if normalizedStatus.contains("free") || + normalizedStatus.contains("inactive") || + normalizedStatus.contains("cancel") || + normalizedStatus.contains("none") || + normalizedStatus.contains("expired") + { + return .inactive + } + return .unknown + } + + private static func planName( + root: [String: Any], + dataRoot: [String: Any], + subscription: [String: Any]?) -> String? + { + self.firstString(in: root, keys: self.planKeys) + ?? self.firstString(in: dataRoot, keys: self.planKeys) + ?? subscription.flatMap { self.firstString(in: $0, keys: self.planKeys) } + } + + private static func subscriptionRenewsAt( + root: [String: Any], + dataRoot: [String: Any], + subscription: [String: Any]?) -> Date? + { + self.firstDate(in: root, keys: self.resetKeys) + ?? self.firstDate(in: dataRoot, keys: self.resetKeys) + ?? subscription.flatMap { self.firstDate(in: $0, keys: self.resetKeys) } + } + + private static func firstDictionary( + in root: [String: Any], + dataRoot: [String: Any], + keys: [String]) -> [String: Any]? + { + self.dictionaryValue(self.value(in: root, keys: keys)) + ?? self.dictionaryValue(self.value(in: dataRoot, keys: keys)) + } + + private static func fallbackQuotaObjects(from root: [String: Any], dataRoot: [String: Any]) -> [[String: Any]] { + let candidates: [Any?] = [ + self.value(in: root, keys: self.quotaContainerKeys), + self.value(in: dataRoot, keys: self.quotaContainerKeys), + dataRoot, + root, + ] + + var results: [[String: Any]] = [] + for candidate in candidates { + results.append(contentsOf: self.extractQuotaObjects(from: candidate)) + } + return self.deduplicated(results) + } + + private static func extractQuotaObjects(from candidate: Any?) -> [[String: Any]] { + if let array = candidate as? [Any] { + return array.flatMap { self.extractQuotaObjects(from: $0) } + } + + guard let dict = self.dictionaryValue(candidate) else { return [] } + var results: [[String: Any]] = self.isQuotaPayload(dict) ? [dict] : [] + for value in dict.values { + results.append(contentsOf: self.extractQuotaObjects(from: value)) + } + return results + } + + private static func deduplicated(_ objects: [[String: Any]]) -> [[String: Any]] { + var seen: Set = [] + var unique: [[String: Any]] = [] + for object in objects { + guard let key = try? JSONSerialization.data(withJSONObject: object, options: [.sortedKeys]) else { + unique.append(object) + continue + } + guard seen.insert(key).inserted else { continue } + unique.append(object) + } + return unique + } + + private static func isQuotaPayload(_ payload: [String: Any]) -> Bool { + self.firstDouble(in: payload, keys: self.limitKeys) != nil || + self.firstDouble(in: payload, keys: self.usedKeys) != nil || + self.firstDouble(in: payload, keys: self.remainingKeys) != nil || + self.firstDouble(in: payload, keys: self.percentUsedKeys) != nil || + self.firstDouble(in: payload, keys: self.percentRemainingKeys) != nil + } + + private static func kind(for window: ChutesQuotaWindow) -> WindowKind? { + let label = [ + window.label, + window.unit, + ] + .compactMap { $0?.lowercased() } + .joined(separator: " ") + + if label.contains("rolling") || + label.contains("4h") || + label.contains("4 h") || + label.contains("4-hour") || + label.contains("four hour") || + label.contains("four-hour") || + window.windowMinutes == ChutesUsageSnapshot.rollingWindowMinutes + { + return .rolling + } + + if label.contains("month") || + label.contains("billing") || + label.contains("subscription") || + (window.windowMinutes ?? 0) >= 28 * 24 * 60 + { + return .monthly + } + + return nil + } + + private static func windowMinutes(from payload: [String: Any]) -> Int? { + if let minutes = self.firstDouble(in: payload, keys: windowMinuteKeys) { + return Int(minutes.rounded()) + } + if let hours = self.firstDouble(in: payload, keys: windowHourKeys) { + return Int((hours * 60).rounded()) + } + if let days = self.firstDouble(in: payload, keys: windowDayKeys) { + return Int((days * 24 * 60).rounded()) + } + if let seconds = self.firstDouble(in: payload, keys: windowSecondKeys) { + return Int((seconds / 60).rounded()) + } + if let text = self.firstString(in: payload, keys: windowStringKeys) { + return self.windowMinutes(fromText: text) + } + return nil + } + + static func windowMinutes(fromText raw: String) -> Int? { + let text = raw.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() + guard !text.isEmpty else { return nil } + let compact = text.replacingOccurrences(of: " ", with: "") + let scanner = Scanner(string: compact) + guard let value = scanner.scanDouble(), value > 0 else { return nil } + let suffix = String(compact[scanner.currentIndex...]) + if suffix.hasPrefix("min") || suffix == "m" { + return Int(value.rounded()) + } + if suffix.hasPrefix("hour") || suffix.hasPrefix("hr") || suffix == "h" { + return Int((value * 60).rounded()) + } + if suffix.hasPrefix("day") || suffix == "d" { + return Int((value * 24 * 60).rounded()) + } + if suffix.hasPrefix("month") || suffix == "mo" { + return Int((value * 30 * 24 * 60).rounded()) + } + return nil + } + + private static func firstString(in dict: [String: Any], keys: [String]) -> String? { + guard let value = self.value(in: dict, keys: keys) else { return nil } + if let string = value as? String { + let cleaned = string.trimmingCharacters(in: .whitespacesAndNewlines) + return cleaned.isEmpty ? nil : cleaned + } + if let number = value as? NSNumber { + return number.stringValue + } + return nil + } + + private static func firstBool(in dict: [String: Any], keys: [String]) -> Bool? { + guard let value = self.value(in: dict, keys: keys) else { return nil } + if let bool = value as? Bool { return bool } + if let number = value as? NSNumber { return number.boolValue } + if let string = value as? String { + switch string.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() { + case "true", "1", "yes", "active": + return true + case "false", "0", "no", "inactive", "none": + return false + default: + return nil + } + } + return nil + } + + private static func firstDouble(in dict: [String: Any], keys: [String]) -> Double? { + self.doubleValue(self.value(in: dict, keys: keys)) + } + + private static func firstDate(in dict: [String: Any], keys: [String]) -> Date? { + ChutesTimestampParser.parse(self.value(in: dict, keys: keys)) + } + + private static func normalizedPercent(_ value: Double?) -> Double? { + guard let value, value.isFinite else { return nil } + let percent = abs(value) < 1 ? value * 100 : value + return max(0, min(percent, 100)) + } + + private static func value(in dict: [String: Any], keys: [String]) -> Any? { + for key in keys { + let normalized = self.normalizedKey(key) + for (candidateKey, value) in dict where self.normalizedKey(candidateKey) == normalized { + return value + } + } + return nil + } + + private static func dictionaryValue(_ value: Any?) -> [String: Any]? { + value as? [String: Any] + } + + private static func doubleValue(_ value: Any?) -> Double? { + switch value { + case let double as Double: + double.isFinite ? double : nil + case let int as Int: + Double(int) + case let number as NSNumber: + number.doubleValue.isFinite ? number.doubleValue : nil + case let string as String: + self.doubleValue(from: string) + default: + nil + } + } + + private static func doubleValue(from raw: String) -> Double? { + let text = raw.trimmingCharacters(in: .whitespacesAndNewlines) + .replacingOccurrences(of: ",", with: "") + .replacingOccurrences(of: "$", with: "") + .replacingOccurrences(of: "%", with: "") + guard !text.isEmpty, let value = Double(text), value.isFinite else { return nil } + return value + } + + private static func normalizedKey(_ key: String) -> String { + key.lowercased().filter { $0.isLetter || $0.isNumber } + } + + private static let rollingPayloadKeys = [ + "rolling", + "rolling_window", + "rollingWindow", + "rolling_4h", + "rolling4h", + "four_hour", + "fourHour", + "four_hour_usage", + "fourHourUsage", + "window_4h", + "window4h", + ] + private static let monthlyPayloadKeys = [ + "monthly", + "monthly_usage", + "monthlyUsage", + "subscription", + "subscription_usage", + "subscriptionUsage", + "billing_period", + "billingPeriod", + ] + private static let quotaContainerKeys = [ + "quotas", + "quota", + "quota_usage", + "quotaUsage", + "limits", + "usage", + "entries", + "subscription_usage", + "subscriptionUsage", + ] + private static let labelKeys = [ + "label", + "name", + "title", + "type", + "quota_type", + "quotaType", + "period", + "window", + "window_name", + "windowName", + "chute_id", + "chuteId", + ] + private static let limitKeys = [ + "limit", + "cap", + "max", + "maximum", + "quota", + "quota_limit", + "quotaLimit", + "monthly_cap", + "monthlyCap", + "monthly_limit", + "monthlyLimit", + "request_limit", + "requestLimit", + "token_limit", + "tokenLimit", + "hard_limit", + "hardLimit", + "total", + ] + private static let usedKeys = [ + "used", + "usage", + "used_amount", + "usedAmount", + "consumed", + "consumed_amount", + "consumedAmount", + "current", + "current_usage", + "currentUsage", + "requests", + "request_count", + "requestCount", + "tokens", + "token_usage", + "tokenUsage", + "monthly_usage", + "monthlyUsage", + ] + private static let remainingKeys = [ + "remaining", + "available", + "balance", + "left", + "remaining_amount", + "remainingAmount", + "available_amount", + "availableAmount", + ] + private static let percentUsedKeys = [ + "percent_used", + "percentUsed", + "usage_percent", + "usagePercent", + "used_percent", + "usedPercent", + "utilization", + "utilization_percent", + "utilizationPercent", + ] + private static let percentRemainingKeys = [ + "percent_remaining", + "percentRemaining", + "remaining_percent", + "remainingPercent", + ] + private static let resetKeys = [ + "reset_at", + "resetAt", + "resets_at", + "resetsAt", + "reset_time", + "resetTime", + "next_reset_at", + "nextResetAt", + "renews_at", + "renewsAt", + "renewal_at", + "renewalAt", + "period_end", + "periodEnd", + "current_period_end", + "currentPeriodEnd", + "expires_at", + "expiresAt", + "window_end", + "windowEnd", + "end_time", + "endTime", + ] + private static let unitKeys = [ + "unit", + "units", + "currency", + "quota_unit", + "quotaUnit", + ] + private static let activeKeys = [ + "active", + "is_active", + "isActive", + "subscription_active", + "subscriptionActive", + "has_subscription", + "hasSubscription", + ] + private static let statusKeys = [ + "status", + "state", + "subscription_status", + "subscriptionStatus", + ] + private static let planKeys = [ + "plan_name", + "planName", + "plan", + "tier", + "subscription_plan", + "subscriptionPlan", + "subscription_tier", + "subscriptionTier", + ] + private static let windowMinuteKeys = [ + "window_minutes", + "windowMinutes", + "period_minutes", + "periodMinutes", + "duration_minutes", + "durationMinutes", + ] + private static let windowHourKeys = [ + "window_hours", + "windowHours", + "period_hours", + "periodHours", + "duration_hours", + "durationHours", + ] + private static let windowDayKeys = [ + "window_days", + "windowDays", + "period_days", + "periodDays", + "duration_days", + "durationDays", + ] + private static let windowSecondKeys = [ + "window_seconds", + "windowSeconds", + "period_seconds", + "periodSeconds", + "duration_seconds", + "durationSeconds", + ] + private static let windowStringKeys = [ + "window", + "period", + "interval", + "duration", + ] +} diff --git a/Sources/CodexBarCore/Providers/Claude/ClaudeAdminAPISettingsReader.swift b/Sources/CodexBarCore/Providers/Claude/ClaudeAdminAPISettingsReader.swift new file mode 100644 index 0000000..cbb1791 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Claude/ClaudeAdminAPISettingsReader.swift @@ -0,0 +1,43 @@ +import Foundation + +public enum ClaudeAdminAPISettingsReader { + public static let adminAPIKeyEnvironmentKey = "ANTHROPIC_ADMIN_KEY" + public static let alternateAdminAPIKeyEnvironmentKey = "ANTHROPIC_ADMIN_API_KEY" + public static let apiKeyEnvironmentKeys = [ + Self.adminAPIKeyEnvironmentKey, + Self.alternateAdminAPIKeyEnvironmentKey, + ] + + public static func apiKey(environment: [String: String] = ProcessInfo.processInfo.environment) -> String? { + for key in self.apiKeyEnvironmentKeys { + if let token = self.cleaned(environment[key]) { return token } + } + return nil + } + + public static func cleaned(_ raw: String?) -> String? { + guard var value = raw?.trimmingCharacters(in: .whitespacesAndNewlines), !value.isEmpty else { + return nil + } + + if (value.hasPrefix("\"") && value.hasSuffix("\"")) || + (value.hasPrefix("'") && value.hasSuffix("'")) + { + value = String(value.dropFirst().dropLast()) + } + + value = value.trimmingCharacters(in: .whitespacesAndNewlines) + return value.isEmpty ? nil : value + } +} + +public enum ClaudeAdminAPISettingsError: LocalizedError, Sendable { + case missingToken + + public var errorDescription: String? { + switch self { + case .missingToken: + "Claude API usage needs an Anthropic Admin API key." + } + } +} diff --git a/Sources/CodexBarCore/Providers/Claude/ClaudeAdminAPIUsageFetcher.swift b/Sources/CodexBarCore/Providers/Claude/ClaudeAdminAPIUsageFetcher.swift new file mode 100644 index 0000000..37df52a --- /dev/null +++ b/Sources/CodexBarCore/Providers/Claude/ClaudeAdminAPIUsageFetcher.swift @@ -0,0 +1,432 @@ +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +public enum ClaudeAdminAPIUsageError: LocalizedError, Sendable, Equatable { + case missingCredentials + case networkError(String) + case apiError(endpoint: String, statusCode: Int) + case parseFailed(endpoint: String, message: String) + + public var errorDescription: String? { + switch self { + case .missingCredentials: + "Missing Anthropic Admin API key." + case let .networkError(message): + "Claude API usage network error: \(message)" + case let .apiError(endpoint, statusCode): + "Claude API usage \(endpoint) error: HTTP \(statusCode)" + case let .parseFailed(endpoint, message): + "Failed to parse Claude API usage \(endpoint): \(message)" + } + } +} + +public enum ClaudeAdminAPIUsageFetcher { + public static let costReportURL = URL(string: "https://api.anthropic.com/v1/organizations/cost_report")! + public static let messagesUsageURL = + URL(string: "https://api.anthropic.com/v1/organizations/usage_report/messages")! + + private static let anthropicVersion = "2023-06-01" + private static let timeoutSeconds: TimeInterval = 20 + private static let maxDailyBuckets = 31 + + public static func fetchUsage( + apiKey: String, + costURL: URL = Self.costReportURL, + messagesURL: URL = Self.messagesUsageURL, + session transport: any ProviderHTTPTransport = ProviderHTTPClient.shared, + now: Date = Date()) async throws -> ClaudeAdminAPIUsageSnapshot + { + let trimmed = apiKey.trimmingCharacters(in: .whitespacesAndNewlines) + guard !trimmed.isEmpty else { + throw ClaudeAdminAPIUsageError.missingCredentials + } + + let calendar = Self.utcCalendar + let range = Self.dailyRange(now: now, calendar: calendar) + let costs = try await Self.fetchCostReport( + apiKey: trimmed, + baseURL: costURL, + range: range, + transport: transport) + let messages = try await Self.fetchMessagesUsage( + apiKey: trimmed, + baseURL: messagesURL, + range: range, + transport: transport) + + return Self.makeSnapshot(costs: costs, messages: messages, now: now, calendar: calendar) + } + + static func _parseSnapshotForTesting( + costs: Data, + messages: Data, + now: Date, + calendar: Calendar = Self.utcCalendar) throws -> ClaudeAdminAPIUsageSnapshot + { + let costs = try Self.decodeCosts(costs) + let messages = try Self.decodeMessages(messages) + return Self.makeSnapshot(costs: costs, messages: messages, now: now, calendar: calendar) + } + + private static func fetchCostReport( + apiKey: String, + baseURL: URL, + range: DateRange, + transport: any ProviderHTTPTransport) async throws -> CostReportResponse + { + let url = Self.url( + baseURL: baseURL, + range: range, + queryItems: [ + URLQueryItem(name: "group_by[]", value: "description"), + ]) + let data = try await Self.fetchData(url: url, apiKey: apiKey, endpoint: "cost_report", transport: transport) + return try Self.decodeCosts(data) + } + + private static func fetchMessagesUsage( + apiKey: String, + baseURL: URL, + range: DateRange, + transport: any ProviderHTTPTransport) async throws -> MessagesUsageResponse + { + let url = Self.url( + baseURL: baseURL, + range: range, + queryItems: [ + URLQueryItem(name: "group_by[]", value: "model"), + ]) + let data = try await Self.fetchData(url: url, apiKey: apiKey, endpoint: "messages", transport: transport) + return try Self.decodeMessages(data) + } + + private static func fetchData( + url: URL, + apiKey: String, + endpoint: String, + transport: any ProviderHTTPTransport) async throws -> Data + { + var request = URLRequest(url: url) + request.httpMethod = "GET" + request.timeoutInterval = Self.timeoutSeconds + request.setValue(Self.anthropicVersion, forHTTPHeaderField: "anthropic-version") + request.setValue(apiKey, forHTTPHeaderField: "x-api-key") + request.setValue("application/json", forHTTPHeaderField: "Accept") + request.setValue("CodexBar/1.0", forHTTPHeaderField: "User-Agent") + + let response: ProviderHTTPResponse + do { + response = try await transport.response(for: request) + } catch { + throw ClaudeAdminAPIUsageError.networkError(error.localizedDescription) + } + + guard response.statusCode == 200 else { + throw ClaudeAdminAPIUsageError.apiError(endpoint: endpoint, statusCode: response.statusCode) + } + return response.data + } + + private static func decodeCosts(_ data: Data) throws -> CostReportResponse { + do { + return try JSONDecoder().decode(CostReportResponse.self, from: data) + } catch { + throw ClaudeAdminAPIUsageError.parseFailed(endpoint: "cost_report", message: error.localizedDescription) + } + } + + private static func decodeMessages(_ data: Data) throws -> MessagesUsageResponse { + do { + return try JSONDecoder().decode(MessagesUsageResponse.self, from: data) + } catch { + throw ClaudeAdminAPIUsageError.parseFailed(endpoint: "messages", message: error.localizedDescription) + } + } + + private static func makeSnapshot( + costs: CostReportResponse, + messages: MessagesUsageResponse, + now: Date, + calendar: Calendar) -> ClaudeAdminAPIUsageSnapshot + { + var accumulators: [String: DailyAccumulator] = [:] + + for bucket in costs.data { + var accumulator = accumulators[bucket.startingAt] ?? DailyAccumulator( + startingAt: bucket.startingAt, + endingAt: bucket.endingAt) + for result in bucket.results { + // Anthropic Usage & Cost API docs define `amount` as a decimal string in lowest USD units. + let value = Self.usdFromAnthropicLowestUnitAmount(result.amount) + accumulator.costUSD += value + let item = Self.displayName(result.description ?? result.costType, fallback: "Claude API") + accumulator.costItems[item, default: 0] += value + } + accumulators[bucket.startingAt] = accumulator + } + + for bucket in messages.data { + var accumulator = accumulators[bucket.startingAt] ?? DailyAccumulator( + startingAt: bucket.startingAt, + endingAt: bucket.endingAt) + for result in bucket.results { + let input = result.uncachedInputTokens ?? 0 + let cacheCreation = result.cacheCreation?.totalInputTokens ?? 0 + let cacheRead = result.cacheReadInputTokens ?? 0 + let output = result.outputTokens ?? 0 + let total = input + cacheCreation + cacheRead + output + accumulator.inputTokens += input + accumulator.cacheCreationInputTokens += cacheCreation + accumulator.cacheReadInputTokens += cacheRead + accumulator.outputTokens += output + accumulator.totalTokens += total + let modelName = Self.displayName(result.model, fallback: "Claude API") + accumulator.models[modelName, default: ModelAccumulator()].add( + inputTokens: input, + cacheCreationInputTokens: cacheCreation, + cacheReadInputTokens: cacheRead, + outputTokens: output, + totalTokens: total) + } + accumulators[bucket.startingAt] = accumulator + } + + let daily = accumulators.values + .compactMap { $0.makeBucket(calendar: calendar) } + .filter { $0.startTime <= now } + .sorted { $0.startTime < $1.startTime } + return ClaudeAdminAPIUsageSnapshot(daily: daily, updatedAt: now) + } + + private static func displayName(_ raw: String?, fallback: String) -> String { + guard let trimmed = raw?.trimmingCharacters(in: .whitespacesAndNewlines), !trimmed.isEmpty else { + return fallback + } + return trimmed + } + + private static func usdFromAnthropicLowestUnitAmount(_ raw: String) -> Double { + (Double(raw) ?? 0) / 100 + } + + private static func url(baseURL: URL, range: DateRange, queryItems extraItems: [URLQueryItem]) -> URL { + var components = URLComponents(url: baseURL, resolvingAgainstBaseURL: false)! + components.queryItems = [ + URLQueryItem(name: "starting_at", value: Self.rfc3339String(from: range.start)), + URLQueryItem(name: "ending_at", value: Self.rfc3339String(from: range.end)), + URLQueryItem(name: "bucket_width", value: "1d"), + URLQueryItem(name: "limit", value: String(Self.maxDailyBuckets)), + ] + extraItems + return components.url! + } + + private static func dailyRange(now: Date, calendar: Calendar) -> DateRange { + let today = calendar.startOfDay(for: now) + let start = calendar.date(byAdding: .day, value: -(Self.maxDailyBuckets - 1), to: today) ?? today + let end = calendar.date(byAdding: .day, value: 1, to: today) ?? now + return DateRange(start: start, end: end) + } + + private static var utcCalendar: Calendar { + var calendar = Calendar(identifier: .gregorian) + calendar.locale = Locale(identifier: "en_US_POSIX") + calendar.timeZone = TimeZone(secondsFromGMT: 0)! + return calendar + } + + private static func rfc3339Formatter() -> ISO8601DateFormatter { + let formatter = ISO8601DateFormatter() + formatter.formatOptions = [.withInternetDateTime] + formatter.timeZone = TimeZone(secondsFromGMT: 0) + return formatter + } + + private static func rfc3339String(from date: Date) -> String { + self.rfc3339Formatter().string(from: date) + } + + fileprivate static func dayKey(from date: Date, calendar: Calendar) -> String { + let formatter = DateFormatter() + formatter.locale = Locale(identifier: "en_US_POSIX") + formatter.timeZone = calendar.timeZone + formatter.dateFormat = "yyyy-MM-dd" + return formatter.string(from: date) + } + + fileprivate static func parseDate(_ raw: String) -> Date? { + self.rfc3339Formatter().date(from: raw) + } +} + +private struct DateRange { + let start: Date + let end: Date +} + +private struct DailyAccumulator { + let startingAt: String + let endingAt: String + var costUSD: Double = 0 + var inputTokens: Int = 0 + var cacheCreationInputTokens: Int = 0 + var cacheReadInputTokens: Int = 0 + var outputTokens: Int = 0 + var totalTokens: Int = 0 + var costItems: [String: Double] = [:] + var models: [String: ModelAccumulator] = [:] + + func makeBucket(calendar: Calendar) -> ClaudeAdminAPIUsageSnapshot.DailyBucket? { + guard let start = ClaudeAdminAPIUsageFetcher.parseDate(self.startingAt), + let end = ClaudeAdminAPIUsageFetcher.parseDate(self.endingAt) + else { return nil } + return ClaudeAdminAPIUsageSnapshot.DailyBucket( + day: ClaudeAdminAPIUsageFetcher.dayKey(from: start, calendar: calendar), + startTime: start, + endTime: end, + costUSD: self.costUSD, + inputTokens: self.inputTokens, + cacheCreationInputTokens: self.cacheCreationInputTokens, + cacheReadInputTokens: self.cacheReadInputTokens, + outputTokens: self.outputTokens, + totalTokens: self.totalTokens, + costItems: self.costItems + .map { ClaudeAdminAPIUsageSnapshot.CostBreakdown(name: $0.key, costUSD: $0.value) } + .sorted { + if $0.costUSD == $1.costUSD { return $0.name < $1.name } + return $0.costUSD > $1.costUSD + }, + models: self.models + .map { name, total in total.makeModel(name: name) } + .sorted { + if $0.totalTokens == $1.totalTokens { return $0.name < $1.name } + return $0.totalTokens > $1.totalTokens + }) + } +} + +private struct ModelAccumulator { + var inputTokens = 0 + var cacheCreationInputTokens = 0 + var cacheReadInputTokens = 0 + var outputTokens = 0 + var totalTokens = 0 + + mutating func add( + inputTokens: Int, + cacheCreationInputTokens: Int, + cacheReadInputTokens: Int, + outputTokens: Int, + totalTokens: Int) + { + self.inputTokens += inputTokens + self.cacheCreationInputTokens += cacheCreationInputTokens + self.cacheReadInputTokens += cacheReadInputTokens + self.outputTokens += outputTokens + self.totalTokens += totalTokens + } + + func makeModel(name: String) -> ClaudeAdminAPIUsageSnapshot.ModelBreakdown { + ClaudeAdminAPIUsageSnapshot.ModelBreakdown( + name: name, + inputTokens: self.inputTokens, + cacheCreationInputTokens: self.cacheCreationInputTokens, + cacheReadInputTokens: self.cacheReadInputTokens, + outputTokens: self.outputTokens, + totalTokens: self.totalTokens) + } +} + +private struct CostReportResponse: Decodable { + let data: [CostBucket] + let hasMore: Bool? + let nextPage: String? + + private enum CodingKeys: String, CodingKey { + case data + case hasMore = "has_more" + case nextPage = "next_page" + } +} + +private struct CostBucket: Decodable { + let startingAt: String + let endingAt: String + let results: [CostResult] + + private enum CodingKeys: String, CodingKey { + case startingAt = "starting_at" + case endingAt = "ending_at" + case results + } +} + +private struct CostResult: Decodable { + let currency: String? + let amount: String + let description: String? + let costType: String? + + private enum CodingKeys: String, CodingKey { + case currency + case amount + case description + case costType = "cost_type" + } +} + +private struct MessagesUsageResponse: Decodable { + let data: [MessagesBucket] + let hasMore: Bool? + let nextPage: String? + + private enum CodingKeys: String, CodingKey { + case data + case hasMore = "has_more" + case nextPage = "next_page" + } +} + +private struct MessagesBucket: Decodable { + let startingAt: String + let endingAt: String + let results: [MessagesResult] + + private enum CodingKeys: String, CodingKey { + case startingAt = "starting_at" + case endingAt = "ending_at" + case results + } +} + +private struct MessagesResult: Decodable { + let uncachedInputTokens: Int? + let cacheCreation: CacheCreation? + let cacheReadInputTokens: Int? + let outputTokens: Int? + let model: String? + + private enum CodingKeys: String, CodingKey { + case uncachedInputTokens = "uncached_input_tokens" + case cacheCreation = "cache_creation" + case cacheReadInputTokens = "cache_read_input_tokens" + case outputTokens = "output_tokens" + case model + } +} + +private struct CacheCreation: Decodable { + let ephemeral1HInputTokens: Int? + let ephemeral5MInputTokens: Int? + + var totalInputTokens: Int { + (self.ephemeral1HInputTokens ?? 0) + (self.ephemeral5MInputTokens ?? 0) + } + + private enum CodingKeys: String, CodingKey { + case ephemeral1HInputTokens = "ephemeral_1h_input_tokens" + case ephemeral5MInputTokens = "ephemeral_5m_input_tokens" + } +} diff --git a/Sources/CodexBarCore/Providers/Claude/ClaudeAdminAPIUsageSnapshot.swift b/Sources/CodexBarCore/Providers/Claude/ClaudeAdminAPIUsageSnapshot.swift new file mode 100644 index 0000000..96d30a2 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Claude/ClaudeAdminAPIUsageSnapshot.swift @@ -0,0 +1,242 @@ +import Foundation + +public struct ClaudeAdminAPIUsageSnapshot: Codable, Equatable, Sendable { + public struct DailyBucket: Codable, Equatable, Sendable, Identifiable { + public let day: String + public let startTime: Date + public let endTime: Date + public let costUSD: Double + public let inputTokens: Int + public let cacheCreationInputTokens: Int + public let cacheReadInputTokens: Int + public let outputTokens: Int + public let totalTokens: Int + public let costItems: [CostBreakdown] + public let models: [ModelBreakdown] + + public var id: String { + self.day + } + + public init( + day: String, + startTime: Date, + endTime: Date, + costUSD: Double, + inputTokens: Int, + cacheCreationInputTokens: Int, + cacheReadInputTokens: Int, + outputTokens: Int, + totalTokens: Int, + costItems: [CostBreakdown], + models: [ModelBreakdown]) + { + self.day = day + self.startTime = startTime + self.endTime = endTime + self.costUSD = costUSD + self.inputTokens = inputTokens + self.cacheCreationInputTokens = cacheCreationInputTokens + self.cacheReadInputTokens = cacheReadInputTokens + self.outputTokens = outputTokens + self.totalTokens = totalTokens + self.costItems = costItems + self.models = models + } + } + + public struct CostBreakdown: Codable, Equatable, Sendable, Identifiable { + public let name: String + public let costUSD: Double + + public var id: String { + self.name + } + + public init(name: String, costUSD: Double) { + self.name = name + self.costUSD = costUSD + } + } + + public struct ModelBreakdown: Codable, Equatable, Sendable, Identifiable { + public let name: String + public let inputTokens: Int + public let cacheCreationInputTokens: Int + public let cacheReadInputTokens: Int + public let outputTokens: Int + public let totalTokens: Int + + public var id: String { + self.name + } + + public init( + name: String, + inputTokens: Int, + cacheCreationInputTokens: Int, + cacheReadInputTokens: Int, + outputTokens: Int, + totalTokens: Int) + { + self.name = name + self.inputTokens = inputTokens + self.cacheCreationInputTokens = cacheCreationInputTokens + self.cacheReadInputTokens = cacheReadInputTokens + self.outputTokens = outputTokens + self.totalTokens = totalTokens + } + } + + public struct Summary: Equatable, Sendable { + public let costUSD: Double + public let inputTokens: Int + public let cacheCreationInputTokens: Int + public let cacheReadInputTokens: Int + public let outputTokens: Int + public let totalTokens: Int + + public init( + costUSD: Double, + inputTokens: Int, + cacheCreationInputTokens: Int, + cacheReadInputTokens: Int, + outputTokens: Int, + totalTokens: Int) + { + self.costUSD = costUSD + self.inputTokens = inputTokens + self.cacheCreationInputTokens = cacheCreationInputTokens + self.cacheReadInputTokens = cacheReadInputTokens + self.outputTokens = outputTokens + self.totalTokens = totalTokens + } + } + + public let daily: [DailyBucket] + public let updatedAt: Date + + public init(daily: [DailyBucket], updatedAt: Date) { + self.daily = daily.sorted { $0.startTime < $1.startTime } + self.updatedAt = updatedAt + } + + public var last30Days: Summary { + self.summary(days: 30) + } + + public var last7Days: Summary { + self.summary(days: 7) + } + + public var currentDay: Summary { + self.summary(forLocalDayContaining: self.updatedAt) + } + + public var latestDay: Summary { + self.summary(days: 1) + } + + public func summary(forLocalDayContaining date: Date, calendar _: Calendar = .current) -> Summary { + let selected = self.daily.filter { bucket in + CostUsageBucketInterval.contains( + date, + startTime: bucket.startTime, + endTime: bucket.endTime) + } + return Summary( + costUSD: selected.reduce(0) { $0 + $1.costUSD }, + inputTokens: selected.reduce(0) { $0 + $1.inputTokens }, + cacheCreationInputTokens: selected.reduce(0) { $0 + $1.cacheCreationInputTokens }, + cacheReadInputTokens: selected.reduce(0) { $0 + $1.cacheReadInputTokens }, + outputTokens: selected.reduce(0) { $0 + $1.outputTokens }, + totalTokens: selected.reduce(0) { $0 + $1.totalTokens }) + } + + public func summary(days: Int) -> Summary { + let selected = self.daily.suffix(max(1, days)) + return Summary( + costUSD: selected.reduce(0) { $0 + $1.costUSD }, + inputTokens: selected.reduce(0) { $0 + $1.inputTokens }, + cacheCreationInputTokens: selected.reduce(0) { $0 + $1.cacheCreationInputTokens }, + cacheReadInputTokens: selected.reduce(0) { $0 + $1.cacheReadInputTokens }, + outputTokens: selected.reduce(0) { $0 + $1.outputTokens }, + totalTokens: selected.reduce(0) { $0 + $1.totalTokens }) + } + + public var topModels: [ModelBreakdown] { + var totals: [String: ModelAccumulator] = [:] + for day in self.daily { + for model in day.models { + totals[model.name, default: ModelAccumulator()].add(model) + } + } + return totals + .map { name, total in total.makeModel(name: name) } + .sorted { + if $0.totalTokens == $1.totalTokens { return $0.name < $1.name } + return $0.totalTokens > $1.totalTokens + } + } + + public var topCostItems: [CostBreakdown] { + var totals: [String: Double] = [:] + for day in self.daily { + for item in day.costItems { + totals[item.name, default: 0] += item.costUSD + } + } + return totals + .map { CostBreakdown(name: $0.key, costUSD: $0.value) } + .sorted { + if $0.costUSD == $1.costUSD { return $0.name < $1.name } + return $0.costUSD > $1.costUSD + } + } + + public func toUsageSnapshot() -> UsageSnapshot { + let total = self.last30Days + return UsageSnapshot( + primary: nil, + secondary: nil, + providerCost: ProviderCostSnapshot( + used: total.costUSD, + limit: 0, + currencyCode: "USD", + period: "Last 30 days", + updatedAt: self.updatedAt), + claudeAdminAPIUsage: self, + updatedAt: self.updatedAt, + identity: ProviderIdentitySnapshot( + providerID: .claude, + accountEmail: nil, + accountOrganization: nil, + loginMethod: "Admin API")) + } + + private struct ModelAccumulator { + var inputTokens = 0 + var cacheCreationInputTokens = 0 + var cacheReadInputTokens = 0 + var outputTokens = 0 + var totalTokens = 0 + + mutating func add(_ model: ModelBreakdown) { + self.inputTokens += model.inputTokens + self.cacheCreationInputTokens += model.cacheCreationInputTokens + self.cacheReadInputTokens += model.cacheReadInputTokens + self.outputTokens += model.outputTokens + self.totalTokens += model.totalTokens + } + + func makeModel(name: String) -> ModelBreakdown { + ModelBreakdown( + name: name, + inputTokens: self.inputTokens, + cacheCreationInputTokens: self.cacheCreationInputTokens, + cacheReadInputTokens: self.cacheReadInputTokens, + outputTokens: self.outputTokens, + totalTokens: self.totalTokens) + } + } +} diff --git a/Sources/CodexBarCore/Providers/Claude/ClaudeCLIAuthStatusProbe.swift b/Sources/CodexBarCore/Providers/Claude/ClaudeCLIAuthStatusProbe.swift new file mode 100644 index 0000000..4f3b6f5 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Claude/ClaudeCLIAuthStatusProbe.swift @@ -0,0 +1,35 @@ +import Foundation + +enum ClaudeCLIAuthStatusProbe { + private struct Response: Decodable { + let loggedIn: Bool + } + + static func isLoggedIn( + binary: String, + environment: [String: String], + timeout: TimeInterval = 5) async -> Bool + { + do { + let result = try await SubprocessRunner.run( + binary: binary, + arguments: ["auth", "status", "--json"], + environment: ClaudeCLISession.launchEnvironment(baseEnv: environment), + timeout: timeout, + standardInput: FileHandle.nullDevice, + label: "claude-auth-status") + return self.parseLoggedIn(result.stdout) + } catch { + return false + } + } + + static func parseLoggedIn(_ output: String) -> Bool { + guard let data = output.data(using: .utf8), + let response = try? JSONDecoder().decode(Response.self, from: data) + else { + return false + } + return response.loggedIn + } +} diff --git a/Sources/CodexBarCore/Providers/Claude/ClaudeCLIRateLimitGate.swift b/Sources/CodexBarCore/Providers/Claude/ClaudeCLIRateLimitGate.swift new file mode 100644 index 0000000..5c06ec0 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Claude/ClaudeCLIRateLimitGate.swift @@ -0,0 +1,64 @@ +import Foundation + +enum ClaudeCLIRateLimitGate { + private static let blockedUntilKey = "claudeCLIUsageRateLimitBlockedUntilV1" + private static let defaultCooldown: TimeInterval = 60 * 5 + + static let message = "Claude CLI usage endpoint is rate limited right now. Please try again later." + + static func blockedUntil( + interaction: ProviderInteraction = ProviderInteractionContext.current, + now: Date = Date()) -> Date? + { + guard interaction != .userInitiated else { return nil } + return self.currentBlockedUntil(now: now) + } + + static func currentBlockedUntil(now: Date = Date()) -> Date? { + guard let raw = UserDefaults.standard.object(forKey: self.blockedUntilKey) as? Double else { + return nil + } + + let blockedUntil = Date(timeIntervalSince1970: raw) + guard blockedUntil > now else { + UserDefaults.standard.removeObject(forKey: self.blockedUntilKey) + return nil + } + return blockedUntil + } + + static func recordRateLimit(now: Date = Date()) { + UserDefaults.standard.set( + now.addingTimeInterval(self.defaultCooldown).timeIntervalSince1970, + forKey: self.blockedUntilKey) + } + + static func recordSuccess() { + UserDefaults.standard.removeObject(forKey: self.blockedUntilKey) + } + + static func isRateLimitError(_ error: Error) -> Bool { + if case let ClaudeStatusProbeError.parseFailed(message) = error { + return self.isRateLimitMessage(message, allowRawRateLimitToken: true) + } + if case let ClaudeUsageError.parseFailed(message) = error { + return self.isRateLimitMessage(message, allowRawRateLimitToken: true) + } + return self.isRateLimitMessage(error.localizedDescription, allowRawRateLimitToken: false) + } + + private static func isRateLimitMessage(_ message: String, allowRawRateLimitToken: Bool) -> Bool { + let lower = message.lowercased() + return lower.contains(Self.message.lowercased()) || + (allowRawRateLimitToken && lower.contains("rate_limit_error")) || + (lower.contains("claude cli") && + lower.contains("usage") && + lower.contains("rate limited")) + } + + #if DEBUG + static func resetForTesting() { + UserDefaults.standard.removeObject(forKey: self.blockedUntilKey) + } + #endif +} diff --git a/Sources/CodexBarCore/Providers/Claude/ClaudeCLISession.swift b/Sources/CodexBarCore/Providers/Claude/ClaudeCLISession.swift new file mode 100644 index 0000000..0866b35 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Claude/ClaudeCLISession.swift @@ -0,0 +1,499 @@ +#if canImport(Darwin) +import Darwin +#elseif canImport(Glibc) +import Glibc +#elseif canImport(Musl) +import Musl +#endif +import Foundation + +actor ClaudeCLISession { + static let shared = ClaudeCLISession() + private static let log = CodexBarLog.logger(LogCategories.claudeCLI) + #if DEBUG + @TaskLocal private static var sessionOverrideForTesting: ClaudeCLISession? + + static var current: ClaudeCLISession { + self.sessionOverrideForTesting ?? self.shared + } + + static func withIsolatedSessionForTesting(operation: () async throws -> T) async rethrows -> T { + let session = ClaudeCLISession() + defer { Task { await session.reset() } } + return try await self.$sessionOverrideForTesting.withValue(session) { + try await operation() + } + } + #else + static var current: ClaudeCLISession { + self.shared + } + #endif + + enum SessionError: LocalizedError { + case launchFailed(String) + case ioFailed(String) + case timedOut + case processExited + + var errorDescription: String? { + switch self { + case let .launchFailed(msg): "Failed to launch Claude CLI session: \(msg)" + case let .ioFailed(msg): "Claude CLI PTY I/O failed: \(msg)" + case .timedOut: "Claude CLI session timed out." + case .processExited: "Claude CLI session exited." + } + } + } + + private var process: Process? + private var primaryFD: Int32 = -1 + private var primaryHandle: FileHandle? + private var secondaryHandle: FileHandle? + private var processGroup: pid_t? + private var binaryPath: String? + private var startedAt: Date? + + private let promptSends: [String: String] = [ + "Do you trust the files in this folder?": "y\r", + "Quick safety check:": "\r", + "Yes, I trust this folder": "\r", + "Ready to code here?": "\r", + "Press Enter to continue": "\r", + ] + + private struct RollingBuffer { + private let maxNeedle: Int + private var tail = Data() + + init(maxNeedle: Int) { + self.maxNeedle = max(0, maxNeedle) + } + + mutating func append(_ data: Data) -> Data { + guard !data.isEmpty else { return Data() } + var combined = Data() + combined.reserveCapacity(self.tail.count + data.count) + combined.append(self.tail) + combined.append(data) + if self.maxNeedle > 1 { + if combined.count >= self.maxNeedle - 1 { + self.tail = combined.suffix(self.maxNeedle - 1) + } else { + self.tail = combined + } + } else { + self.tail.removeAll(keepingCapacity: true) + } + return combined + } + } + + private static func normalizedNeedle(_ text: String) -> String { + String(text.lowercased().filter { !$0.isWhitespace }) + } + + private static func commandPaletteSends(for subcommand: String) -> [String: String] { + let normalized = subcommand.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() + switch normalized { + case "/usage": + // Claude's command palette can render several "Show ..." actions together; only auto-confirm the + // usage-related actions here so we do not accidentally execute /status. + return [ + "Show plan": "\r", + "Show plan usage limits": "\r", + ] + case "/status": + return [ + "Show Claude Code": "\r", + "Show Claude Code status": "\r", + ] + default: + return [:] + } + } + + func capture( + subcommand: String, + binary: String, + timeout: TimeInterval, + idleTimeout: TimeInterval? = 3.0, + stopOnSubstrings: [String] = [], + stopWhenNormalized: (@Sendable (String) -> Bool)? = nil, + settleAfterStop: TimeInterval = 0.25, + sendEnterEvery: TimeInterval? = nil) async throws -> String + { + try self.ensureStarted(binary: binary) + if let startedAt { + let sinceStart = Date().timeIntervalSince(startedAt) + // Claude's TUI can drop early keystrokes while it's still initializing. Wait a bit longer than the + // original 0.4s to ensure slash commands reliably open their panels. + if sinceStart < 2.0 { + let delay = UInt64((2.0 - sinceStart) * 1_000_000_000) + try await Task.sleep(nanoseconds: delay) + } + } + self.drainOutput() + + let trimmed = subcommand.trimmingCharacters(in: .whitespacesAndNewlines) + if !trimmed.isEmpty { + try self.send(trimmed) + try self.send("\r") + } + + let stopNeedles = stopOnSubstrings.map { Self.normalizedNeedle($0) } + var sendMap = self.promptSends + for (needle, keys) in Self.commandPaletteSends(for: trimmed) { + sendMap[needle] = keys + } + let sendNeedles = sendMap.map { (needle: Self.normalizedNeedle($0.key), keys: $0.value) } + let cursorQuery = Data([0x1B, 0x5B, 0x36, 0x6E]) + let needleLengths = + stopOnSubstrings.map(\.utf8.count) + + sendMap.keys.map(\.utf8.count) + + [cursorQuery.count] + let maxNeedle = needleLengths.max() ?? cursorQuery.count + var scanBuffer = RollingBuffer(maxNeedle: maxNeedle) + var triggeredSends = Set() + + var buffer = Data() + var scanTailText = "" + var normalizedScan = "" + var utf8Carry = Data() + let deadline = Date().addingTimeInterval(timeout) + var lastOutputAt = Date() + var lastEnterAt = Date() + var stoppedEarly = false + // Only send periodic Enter when the caller explicitly asks for it (used for /usage rendering). + // For /status, periodic input can keep producing output and prevent idle-timeout short-circuiting. + let effectiveEnterEvery: TimeInterval? = sendEnterEvery + + while Date() < deadline { + let newData = self.readChunk() + if !newData.isEmpty { + buffer.append(newData) + lastOutputAt = Date() + Self.appendScanText(newData: newData, scanTailText: &scanTailText, utf8Carry: &utf8Carry) + if scanTailText.count > 8192 { + scanTailText = String(scanTailText.suffix(8192)) + } + normalizedScan = Self.normalizedNeedle(TextParsing.stripANSICodes(scanTailText)) + + let scanData = scanBuffer.append(newData) + if scanData.range(of: cursorQuery) != nil { + try? self.send("\u{1b}[1;1R") + } + + for item in sendNeedles where !triggeredSends.contains(item.needle) { + if normalizedScan.contains(item.needle) { + try? self.send(item.keys) + triggeredSends.insert(item.needle) + } + } + + if stopNeedles + .contains(where: normalizedScan.contains) || (stopWhenNormalized?(normalizedScan) == true) + { + stoppedEarly = true + break + } + } + + if self.shouldStopForIdleTimeout( + idleTimeout: idleTimeout, + bufferIsEmpty: buffer.isEmpty, + lastOutputAt: lastOutputAt) + { + stoppedEarly = true + break + } + + self.sendPeriodicEnterIfNeeded(every: effectiveEnterEvery, lastEnterAt: &lastEnterAt) + + if let proc = self.process, !proc.isRunning { + throw SessionError.processExited + } + + try await Task.sleep(nanoseconds: 60_000_000) + } + + if stoppedEarly { + let settle = max(0, min(settleAfterStop, deadline.timeIntervalSinceNow)) + if settle > 0 { + let settleDeadline = Date().addingTimeInterval(settle) + while Date() < settleDeadline { + let newData = self.readChunk() + if !newData.isEmpty { + buffer.append(newData) + } + try await Task.sleep(nanoseconds: 50_000_000) + } + } + } + + guard !buffer.isEmpty, let text = String(data: buffer, encoding: .utf8) else { + throw SessionError.timedOut + } + return text + } + + private static func appendScanText(newData: Data, scanTailText: inout String, utf8Carry: inout Data) { + // PTY reads can split multibyte UTF-8 sequences. Keep a small carry buffer so prompt/stop scanning doesn't + // drop chunks when the decode fails due to an incomplete trailing sequence. + var combined = Data() + combined.reserveCapacity(utf8Carry.count + newData.count) + combined.append(utf8Carry) + combined.append(newData) + + if let chunk = String(data: combined, encoding: .utf8) { + scanTailText.append(chunk) + utf8Carry.removeAll(keepingCapacity: true) + return + } + + for trimCount in 1...3 where combined.count > trimCount { + let prefix = combined.dropLast(trimCount) + if let chunk = String(data: prefix, encoding: .utf8) { + scanTailText.append(chunk) + utf8Carry = Data(combined.suffix(trimCount)) + return + } + } + + // If the data is still not UTF-8 decodable, keep only a small suffix to avoid unbounded growth. + utf8Carry = Data(combined.suffix(12)) + } + + func reset() { + self.cleanup() + } + + private func ensureStarted(binary: String) throws { + if let proc = self.process, proc.isRunning, self.binaryPath == binary { + Self.log.debug("Claude CLI session reused") + return + } + self.cleanup() + + var primaryFD: Int32 = -1 + var secondaryFD: Int32 = -1 + var win = winsize(ws_row: 50, ws_col: 160, ws_xpixel: 0, ws_ypixel: 0) + guard openpty(&primaryFD, &secondaryFD, nil, nil, &win) == 0 else { + Self.log.warning("Claude CLI PTY openpty failed") + throw SessionError.launchFailed("openpty failed") + } + _ = fcntl(primaryFD, F_SETFL, O_NONBLOCK) + + let primaryHandle = FileHandle(fileDescriptor: primaryFD, closeOnDealloc: true) + let secondaryHandle = FileHandle(fileDescriptor: secondaryFD, closeOnDealloc: true) + + let proc = Process() + let resolvedURL = URL(fileURLWithPath: binary) + let disableWatchdog = ProcessInfo.processInfo.environment["CODEXBAR_DISABLE_CLAUDE_WATCHDOG"] == "1" + if !disableWatchdog, + resolvedURL.lastPathComponent == "claude", + let watchdog = TTYCommandRunner.locateBundledHelper("CodexBarClaudeWatchdog") + { + proc.executableURL = URL(fileURLWithPath: watchdog) + proc.arguments = ["--", binary, "--allowed-tools", ""] + } else { + proc.executableURL = resolvedURL + proc.arguments = ["--allowed-tools", ""] + } + proc.standardInput = secondaryHandle + proc.standardOutput = secondaryHandle + proc.standardError = secondaryHandle + + let workingDirectory = ClaudeStatusProbe.preparedProbeWorkingDirectoryURL() + proc.currentDirectoryURL = workingDirectory + var env = Self.launchEnvironment() + env["PWD"] = workingDirectory.path + proc.environment = env + + guard TTYCommandRunner.beginActiveProcessLaunchForAppShutdown() else { + try? primaryHandle.close() + try? secondaryHandle.close() + throw SessionError.launchFailed("App shutdown in progress") + } + defer { TTYCommandRunner.endActiveProcessLaunchForAppShutdown() } + + do { + try proc.run() + Self.log.debug( + "Claude CLI session started", + metadata: ["binary": URL(fileURLWithPath: binary).lastPathComponent]) + } catch { + Self.log.warning("Claude CLI launch failed", metadata: ["error": error.localizedDescription]) + try? primaryHandle.close() + try? secondaryHandle.close() + throw SessionError.launchFailed(error.localizedDescription) + } + + let pid = proc.processIdentifier + guard TTYCommandRunner.registerActiveProcessForAppShutdown( + pid: pid, + binary: URL(fileURLWithPath: binary).lastPathComponent) + else { + proc.terminate() + kill(pid, SIGKILL) + try? primaryHandle.close() + try? secondaryHandle.close() + throw SessionError.launchFailed("App shutdown in progress") + } + + var processGroup: pid_t? + if setpgid(pid, pid) == 0 { + processGroup = pid + TTYCommandRunner.updateActiveProcessGroupForAppShutdown(pid: pid, processGroup: processGroup) + } + + self.process = proc + self.primaryFD = primaryFD + self.primaryHandle = primaryHandle + self.secondaryHandle = secondaryHandle + self.processGroup = processGroup + self.binaryPath = binary + self.startedAt = Date() + } + + static func launchEnvironment(baseEnv: [String: String] = ProcessInfo.processInfo.environment) -> [String: String] { + var env = self.scrubbedClaudeEnvironment(from: TTYCommandRunner.enrichedEnvironment(baseEnv: baseEnv)) + // Passive status and auth probes must not mutate or update the user's Claude CLI installation. + env["DISABLE_AUTOUPDATER"] = "1" + return env + } + + private static func scrubbedClaudeEnvironment(from base: [String: String]) -> [String: String] { + var env = base + let explicitKeys: [String] = [ + ClaudeOAuthCredentialsStore.environmentTokenKey, + ClaudeOAuthCredentialsStore.environmentScopesKey, + ] + for key in explicitKeys { + env.removeValue(forKey: key) + } + for key in env.keys where key.hasPrefix("ANTHROPIC_") { + env.removeValue(forKey: key) + } + return env + } + + private func cleanup() { + if self.process != nil { + Self.log.debug("Claude CLI session stopping") + } + if let proc = self.process, proc.isRunning { + try? self.writeAllToPrimary(Data("/exit\r".utf8)) + } + try? self.primaryHandle?.close() + try? self.secondaryHandle?.close() + + let descendants = self.process.map { TTYProcessTreeTerminator.descendantPIDs(of: $0.processIdentifier) } ?? [] + if let proc = self.process, proc.isRunning { + proc.terminate() + } + if let proc = self.process { + TTYProcessTreeTerminator.terminateProcessTree( + rootPID: proc.processIdentifier, + processGroup: self.processGroup, + signal: SIGTERM, + knownDescendants: descendants) + } + let waitDeadline = Date().addingTimeInterval(1.0) + if let proc = self.process { + while proc.isRunning, Date() < waitDeadline { + usleep(100_000) + } + if proc.isRunning { + TTYProcessTreeTerminator.terminateProcessTree( + rootPID: proc.processIdentifier, + processGroup: self.processGroup, + signal: SIGKILL, + knownDescendants: descendants) + } else { + for pid in descendants where pid > 0 { + kill(pid, SIGKILL) + } + } + TTYCommandRunner.unregisterActiveProcessForAppShutdown(pid: proc.processIdentifier) + } + + self.process = nil + self.primaryHandle = nil + self.secondaryHandle = nil + self.primaryFD = -1 + self.processGroup = nil + self.startedAt = nil + } + + private func readChunk() -> Data { + guard self.primaryFD >= 0 else { return Data() } + var appended = Data() + while true { + var tmp = [UInt8](repeating: 0, count: 8192) + let n = read(self.primaryFD, &tmp, tmp.count) + if n > 0 { + appended.append(contentsOf: tmp.prefix(n)) + continue + } + break + } + return appended + } + + private func drainOutput() { + _ = self.readChunk() + } + + private func shouldStopForIdleTimeout( + idleTimeout: TimeInterval?, + bufferIsEmpty: Bool, + lastOutputAt: Date) -> Bool + { + guard let idleTimeout, !bufferIsEmpty else { return false } + return Date().timeIntervalSince(lastOutputAt) >= idleTimeout + } + + private func sendPeriodicEnterIfNeeded(every: TimeInterval?, lastEnterAt: inout Date) { + guard let every, Date().timeIntervalSince(lastEnterAt) >= every else { return } + try? self.send("\r") + lastEnterAt = Date() + } + + private func send(_ text: String) throws { + guard let data = text.data(using: .utf8) else { return } + guard self.primaryFD >= 0 else { throw SessionError.processExited } + try self.writeAllToPrimary(data) + } + + private func writeAllToPrimary(_ data: Data) throws { + guard self.primaryFD >= 0 else { throw SessionError.processExited } + try data.withUnsafeBytes { rawBytes in + guard let baseAddress = rawBytes.baseAddress else { return } + var offset = 0 + var retries = 0 + while offset < rawBytes.count { + let written = write(self.primaryFD, baseAddress.advanced(by: offset), rawBytes.count - offset) + if written > 0 { + offset += written + retries = 0 + continue + } + if written == 0 { + break + } + + let err = errno + if err == EINTR || err == EAGAIN || err == EWOULDBLOCK { + retries += 1 + if retries > 200 { + throw SessionError.ioFailed("write to PTY would block") + } + usleep(5000) + continue + } + throw SessionError.ioFailed("write to PTY failed: \(String(cString: strerror(err)))") + } + } + } +} diff --git a/Sources/CodexBarCore/Providers/Claude/ClaudeCredentialRouting.swift b/Sources/CodexBarCore/Providers/Claude/ClaudeCredentialRouting.swift new file mode 100644 index 0000000..2472de2 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Claude/ClaudeCredentialRouting.swift @@ -0,0 +1,102 @@ +import Foundation + +public enum ClaudeCredentialRouting: Sendable, Equatable { + case none + case oauth(accessToken: String) + case webCookie(header: String) + case adminAPIKey(String) + + public static func resolve(tokenAccountToken: String?, manualCookieHeader: String?) -> Self { + if let tokenAccountToken, + let route = self.resolvePrimaryCredential(tokenAccountToken) + { + return route + } + + guard let manualCookieHeader = self.normalizedWebCookie(manualCookieHeader) else { + return .none + } + return .webCookie(header: manualCookieHeader) + } + + public var oauthAccessToken: String? { + guard case let .oauth(accessToken) = self else { return nil } + return accessToken + } + + public var manualCookieHeader: String? { + guard case let .webCookie(header) = self else { return nil } + return header + } + + public var isOAuth: Bool { + if case .oauth = self { return true } + return false + } + + public var adminAPIKey: String? { + guard case let .adminAPIKey(key) = self else { return nil } + return key + } + + private static func resolvePrimaryCredential(_ raw: String) -> Self? { + if let adminKey = self.normalizedAdminAPIKey(raw) { + return .adminAPIKey(adminKey) + } + if let accessToken = self.normalizedOAuthToken(raw) { + return .oauth(accessToken: accessToken) + } + if let cookieHeader = self.normalizedWebCookie(raw) { + return .webCookie(header: cookieHeader) + } + return nil + } + + private static func normalizedOAuthToken(_ raw: String?) -> String? { + guard let trimmed = self.cleaned(raw) else { return nil } + let lower = trimmed.lowercased() + if lower.contains("cookie:") || trimmed.contains("=") { + return nil + } + if lower.hasPrefix("bearer ") { + let bearerTrimmed = trimmed.dropFirst("bearer ".count) + .trimmingCharacters(in: .whitespacesAndNewlines) + guard !bearerTrimmed.isEmpty else { return nil } + let lowerBearerTrimmed = bearerTrimmed.lowercased() + return lowerBearerTrimmed.hasPrefix("sk-ant-oat") ? bearerTrimmed : nil + } + return lower.hasPrefix("sk-ant-oat") ? trimmed : nil + } + + private static func normalizedAdminAPIKey(_ raw: String?) -> String? { + guard let trimmed = self.cleaned(raw) else { return nil } + let lower = trimmed.lowercased() + if lower.contains("cookie:") || trimmed.contains("=") { + return nil + } + if lower.hasPrefix("bearer ") { + let bearerTrimmed = trimmed.dropFirst("bearer ".count) + .trimmingCharacters(in: .whitespacesAndNewlines) + guard !bearerTrimmed.isEmpty else { return nil } + return bearerTrimmed.lowercased().hasPrefix("sk-ant-admin") ? bearerTrimmed : nil + } + return lower.hasPrefix("sk-ant-admin") ? trimmed : nil + } + + private static func normalizedWebCookie(_ raw: String?) -> String? { + guard let normalized = CookieHeaderNormalizer.normalize(raw) else { return nil } + if normalized.contains("=") { + return normalized + } + return "sessionKey=\(normalized)" + } + + private static func cleaned(_ raw: String?) -> String? { + guard let trimmed = raw?.trimmingCharacters(in: .whitespacesAndNewlines), + !trimmed.isEmpty + else { + return nil + } + return trimmed + } +} diff --git a/Sources/CodexBarCore/Providers/Claude/ClaudeDesktopProjectsLocator.swift b/Sources/CodexBarCore/Providers/Claude/ClaudeDesktopProjectsLocator.swift new file mode 100644 index 0000000..9b886e2 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Claude/ClaudeDesktopProjectsLocator.swift @@ -0,0 +1,89 @@ +import Foundation + +public enum ClaudeDesktopProjectsLocator { + private static let sessionDirectoryNames = [ + "local-agent-mode-sessions", + "claude-code-sessions", + ] + + private static let skippedDirectoryNames = Set([ + ".build", + ".git", + "build", + "DerivedData", + "node_modules", + "outputs", + "target", + ]) + + public static func roots( + homeDirectory: URL = FileManager.default.homeDirectoryForCurrentUser, + fileManager: FileManager = .default) -> [URL] + { + let claudeApplicationSupport = homeDirectory + .appendingPathComponent("Library", isDirectory: true) + .appendingPathComponent("Application Support", isDirectory: true) + .appendingPathComponent("Claude", isDirectory: true) + let sessionRoots = self.sessionDirectoryNames.map { + claudeApplicationSupport.appendingPathComponent($0, isDirectory: true) + } + + var roots: [URL] = [] + var queue = sessionRoots.map { (url: $0, depth: 0) } + var visited = Set(sessionRoots.map(\.standardizedFileURL.path)) + var nextIndex = 0 + // Current Desktop entries under claude-code-sessions are metadata whose cliSessionId maps to the + // shared ~/.claude/projects logs. Seed that root anyway so embedded project stores are found when present. + // Covers observed Desktop layouts through account/workspace, session, agent, and local_agent + // without descending into arbitrary checked-out workspaces. + let maxDepth = 4 + + while nextIndex < queue.count { + let current = queue[nextIndex] + nextIndex += 1 + if let projects = self.projectsRoot(under: current.url, fileManager: fileManager) { + roots.append(projects) + } + + guard current.depth < maxDepth else { continue } + for child in self.childDirectories(at: current.url, fileManager: fileManager) { + let standardized = child.standardizedFileURL + guard visited.insert(standardized.path).inserted else { continue } + queue.append((standardized, current.depth + 1)) + } + } + return roots + } + + private static func projectsRoot(under base: URL, fileManager: FileManager) -> URL? { + let projects = base + .appendingPathComponent(".claude", isDirectory: true) + .appendingPathComponent("projects", isDirectory: true) + var isDirectory: ObjCBool = false + guard fileManager.fileExists(atPath: projects.path, isDirectory: &isDirectory), + isDirectory.boolValue + else { return nil } + return projects.standardizedFileURL + } + + private static func childDirectories(at url: URL, fileManager: FileManager) -> [URL] { + guard let children = try? fileManager.contentsOfDirectory( + at: url, + includingPropertiesForKeys: [.isDirectoryKey, .isSymbolicLinkKey], + options: [.skipsHiddenFiles, .skipsPackageDescendants]) + else { + return [] + } + + return children.compactMap { child in + guard !self.skippedDirectoryNames.contains(child.lastPathComponent) else { return nil } + guard let values = try? child.resourceValues(forKeys: [.isDirectoryKey, .isSymbolicLinkKey]), + values.isSymbolicLink != true, + values.isDirectory == true + else { + return nil + } + return child + } + } +} diff --git a/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthCredentialModels.swift b/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthCredentialModels.swift new file mode 100644 index 0000000..1b3401c --- /dev/null +++ b/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthCredentialModels.swift @@ -0,0 +1,301 @@ +import Foundation + +#if canImport(CryptoKit) +import CryptoKit +#else +import Crypto +#endif + +#if os(macOS) +import Security +#endif + +public struct ClaudeOAuthCredentials: Sendable { + public let accessToken: String + public let refreshToken: String? + public let expiresAt: Date? + public let scopes: [String] + public let rateLimitTier: String? + public let subscriptionType: String? + + public init( + accessToken: String, + refreshToken: String?, + expiresAt: Date?, + scopes: [String], + rateLimitTier: String?, + subscriptionType: String? = nil) + { + self.accessToken = accessToken + self.refreshToken = refreshToken + self.expiresAt = expiresAt + self.scopes = scopes + self.rateLimitTier = rateLimitTier + self.subscriptionType = subscriptionType + } + + public var isExpired: Bool { + guard let expiresAt else { return true } + return Date() >= expiresAt + } + + public var expiresIn: TimeInterval? { + guard let expiresAt else { return nil } + return expiresAt.timeIntervalSinceNow + } + + /// A one-way discriminator for history owned by this credential. + /// + /// Prefer the refresh token because access tokens routinely rotate for the same principal. If a provider + /// supplies only an access token, rotating that token intentionally starts a new history bucket rather than + /// risking that two identityless accounts share one. The source secret never leaves this computation. + var historyOwnerIdentifier: String? { + let normalizedRefreshToken = self.refreshToken?.trimmingCharacters(in: .whitespacesAndNewlines) + if let normalizedRefreshToken, !normalizedRefreshToken.isEmpty { + return Self.makeHistoryOwnerIdentifier(secretKind: "refresh", secret: normalizedRefreshToken) + } + + let normalizedAccessToken = self.accessToken.trimmingCharacters(in: .whitespacesAndNewlines) + guard !normalizedAccessToken.isEmpty else { return nil } + return Self.makeHistoryOwnerIdentifier(secretKind: "access", secret: normalizedAccessToken) + } + + static func historyOwnerIdentifier(forRefreshToken refreshToken: String) -> String? { + let normalized = refreshToken.trimmingCharacters(in: .whitespacesAndNewlines) + guard !normalized.isEmpty else { return nil } + return Self.makeHistoryOwnerIdentifier(secretKind: "refresh", secret: normalized) + } + + private static func makeHistoryOwnerIdentifier(secretKind: String, secret: String) -> String? { + let material = Data("codexbar:claude-oauth-history-owner:v1\0\(secretKind)\0\(secret)".utf8) + return SHA256.hash(data: material).map { String(format: "%02x", $0) }.joined() + } + + static func normalizedHistoryOwnerIdentifier(_ identifier: String?) -> String? { + guard let identifier else { return nil } + let normalized = identifier.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() + guard normalized.count == 64, + normalized.unicodeScalars.allSatisfy({ scalar in + switch scalar.value { + case 48...57, 97...102: + true + default: + false + } + }) + else { return nil } + return normalized + } + + public static func isMcpOAuthOnlyPayload(data: Data) -> Bool { + guard let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else { + return false + } + return json["claudeAiOauth"] == nil && json["mcpOAuth"] != nil + } + + public static func parse(data: Data) throws -> ClaudeOAuthCredentials { + if ClaudeOAuthCredentials.isMcpOAuthOnlyPayload(data: data) { + throw ClaudeOAuthCredentialsError.mcpOAuthOnlyKeychain + } + + let decoder = JSONDecoder() + guard let root = try? decoder.decode(Root.self, from: data) else { + throw ClaudeOAuthCredentialsError.decodeFailed + } + guard let oauth = root.claudeAiOauth else { + throw ClaudeOAuthCredentialsError.missingOAuth + } + let accessToken = oauth.accessToken?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" + guard !accessToken.isEmpty else { + throw ClaudeOAuthCredentialsError.missingAccessToken + } + let expiresAt = oauth.expiresAt.map { millis in + Date(timeIntervalSince1970: millis / 1000.0) + } + return ClaudeOAuthCredentials( + accessToken: accessToken, + refreshToken: oauth.refreshToken, + expiresAt: expiresAt, + scopes: oauth.scopes ?? [], + rateLimitTier: oauth.rateLimitTier, + subscriptionType: oauth.subscriptionType) + } + + private struct Root: Decodable { + let claudeAiOauth: OAuth? + } + + private struct OAuth: Decodable { + let accessToken: String? + let refreshToken: String? + let expiresAt: Double? + let scopes: [String]? + let rateLimitTier: String? + let subscriptionType: String? + + enum CodingKeys: String, CodingKey { + case accessToken + case refreshToken + case expiresAt + case scopes + case rateLimitTier + case subscriptionType + } + } +} + +extension ClaudeOAuthCredentials { + func diagnosticsMetadata(now: Date = Date()) -> [String: String] { + let hasRefreshToken = !(self.refreshToken?.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty ?? true) + let hasUserProfileScope = self.scopes.contains("user:profile") + + var metadata: [String: String] = [ + "hasRefreshToken": "\(hasRefreshToken)", + "scopesCount": "\(self.scopes.count)", + "hasUserProfileScope": "\(hasUserProfileScope)", + ] + + if let expiresAt = self.expiresAt { + let expiresAtMs = Int(expiresAt.timeIntervalSince1970 * 1000.0) + let expiresInSec = Int(expiresAt.timeIntervalSince(now).rounded()) + metadata["expiresAtMs"] = "\(expiresAtMs)" + metadata["expiresInSec"] = "\(expiresInSec)" + metadata["isExpired"] = "\(now >= expiresAt)" + } else { + metadata["expiresAtMs"] = "nil" + metadata["expiresInSec"] = "nil" + metadata["isExpired"] = "true" + } + + return metadata + } +} + +public enum ClaudeOAuthCredentialOwner: String, Codable, Sendable { + case claudeCLI + case codexbar + case environment +} + +public enum ClaudeOAuthCredentialSource: String, Sendable { + case environment + case memoryCache + case cacheKeychain + case credentialsFile + case claudeKeychain +} + +enum ClaudeKeychainCredentialMatch: Equatable, Sendable { + case notApplicable + case absent + case unavailable + case mismatch + case matched(persistentRefHash: String) + + var persistentRefHash: String? { + guard case let .matched(persistentRefHash) = self else { return nil } + return persistentRefHash + } + + var isMismatch: Bool { + self == .mismatch + } + + var isAbsent: Bool { + self == .absent + } + + var isUnavailable: Bool { + self == .unavailable + } +} + +public struct ClaudeOAuthCredentialRecord: Sendable { + public let credentials: ClaudeOAuthCredentials + public let owner: ClaudeOAuthCredentialOwner + public let source: ClaudeOAuthCredentialSource + private let inheritedHistoryOwnerIdentifier: String? + + /// An opaque, one-way owner identifier that survives a refresh-token rotation proven by a successful refresh. + /// Records from unrelated credential sources do not inherit this value and derive a fresh identifier instead. + var historyOwnerIdentifier: String? { + self.inheritedHistoryOwnerIdentifier ?? self.credentials.historyOwnerIdentifier + } + + public init( + credentials: ClaudeOAuthCredentials, + owner: ClaudeOAuthCredentialOwner, + source: ClaudeOAuthCredentialSource) + { + self.credentials = credentials + self.owner = owner + self.source = source + self.inheritedHistoryOwnerIdentifier = nil + } + + init( + credentials: ClaudeOAuthCredentials, + owner: ClaudeOAuthCredentialOwner, + source: ClaudeOAuthCredentialSource, + historyOwnerIdentifier: String?) + { + self.credentials = credentials + self.owner = owner + self.source = source + self.inheritedHistoryOwnerIdentifier = ClaudeOAuthCredentials.normalizedHistoryOwnerIdentifier( + historyOwnerIdentifier) + } +} + +public enum ClaudeOAuthCredentialsError: LocalizedError, Sendable { + case decodeFailed + case missingOAuth + case mcpOAuthOnlyKeychain + case missingAccessToken + case notFound + case keychainError(Int) + case readFailed(String) + case refreshFailed(String) + case noRefreshToken + case refreshDelegatedToClaudeCLI + + public var errorDescription: String? { + switch self { + case .decodeFailed: + return "Claude OAuth credentials are invalid." + case .missingOAuth: + return "Claude OAuth credentials missing. Run `claude` to authenticate." + case .mcpOAuthOnlyKeychain: + return "Claude keychain contains MCP OAuth state only (no claudeAiOauth). " + + "Claude Code may store subscription OAuth elsewhere now. " + + "Open the CodexBar menu and click Refresh to re-authenticate, " + + "or switch Claude Usage source to Web/CLI." + case .missingAccessToken: + return "Claude OAuth access token missing. Run `claude` to authenticate." + case .notFound: + return "Claude OAuth credentials not found. Run `claude` to authenticate." + case let .keychainError(status): + #if os(macOS) + if status == Int(errSecUserCanceled) + || status == Int(errSecAuthFailed) + || status == Int(errSecInteractionNotAllowed) + || status == Int(errSecNoAccessForItem) + { + return "Claude Keychain access was denied. CodexBar will back off in the background until you retry " + + "via a user action (menu open / manual refresh). " + + "Switch Claude Usage source to Web/CLI, or allow access in Keychain Access." + } + #endif + return "Claude OAuth keychain error: \(status)" + case let .readFailed(message): + return "Claude OAuth credentials read failed: \(message)" + case let .refreshFailed(message): + return "Claude OAuth token refresh failed: \(message)" + case .noRefreshToken: + return "Claude OAuth refresh token missing. Run `claude` to authenticate." + case .refreshDelegatedToClaudeCLI: + return "Claude OAuth refresh is delegated to Claude CLI." + } + } +} diff --git a/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthCredentials+Hashing.swift b/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthCredentials+Hashing.swift new file mode 100644 index 0000000..5e83619 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthCredentials+Hashing.swift @@ -0,0 +1,18 @@ +import Foundation + +#if canImport(CryptoKit) +import CryptoKit +#endif + +extension ClaudeOAuthCredentialsStore { + static func sha256Prefix(_ data: Data) -> String? { + #if canImport(CryptoKit) + let digest = SHA256.hash(data: data) + let hex = digest.compactMap { String(format: "%02x", $0) }.joined() + return String(hex.prefix(12)) + #else + _ = data + return nil + #endif + } +} diff --git a/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthCredentials+SecurityCLIReader.swift b/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthCredentials+SecurityCLIReader.swift new file mode 100644 index 0000000..76df9cb --- /dev/null +++ b/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthCredentials+SecurityCLIReader.swift @@ -0,0 +1,375 @@ +import Dispatch +import Foundation + +#if canImport(Darwin) +import Darwin +#elseif canImport(Glibc) +import Glibc +#elseif canImport(Musl) +import Musl +#endif + +extension ClaudeOAuthCredentialsStore { + private static let securityBinaryPath = "/usr/bin/security" + private static let securityCLIReadTimeout: TimeInterval = 1.5 + static let isolatedSecurityCLIKeychainEnvironmentKey = "CODEXBAR_CLAUDE_SECURITY_CLI_KEYCHAIN" + + struct SecurityCLIReadRequest { + let account: String? + } + + static func shouldPreferSecurityCLIKeychainRead( + readStrategy: ClaudeOAuthKeychainReadStrategy = ClaudeOAuthKeychainReadStrategyPreference.current()) + -> Bool + { + readStrategy == .securityCLIExperimental + } + + #if os(macOS) + private enum SecurityCLIReadError: Error { + case binaryUnavailable + case isolatedKeychainUnavailable + case launchFailed + case timedOut + case nonZeroExit(status: Int32, stderrLength: Int) + } + + private struct SecurityCLIReadCommandResult { + let status: Int32 + let stdout: Data + let stderrLength: Int + let durationMs: Double + } + + /// Attempts a Claude keychain read via `/usr/bin/security` when the experimental reader is enabled. + /// - Important: `interaction` is diagnostics context only and does not gate CLI execution. + static func loadFromClaudeKeychainViaSecurityCLIIfEnabled( + interaction: ProviderInteraction, + readStrategy: ClaudeOAuthKeychainReadStrategy = ClaudeOAuthKeychainReadStrategyPreference.current()) + -> Data? + { + guard let sanitized = self.readRawClaudeKeychainPayloadViaSecurityCLIIfEnabled( + interaction: interaction, + readStrategy: readStrategy) + else { + return nil + } + + let interactionMetadata = interaction == .userInitiated ? "user" : "background" + let parsedCredentials: ClaudeOAuthCredentials + do { + parsedCredentials = try ClaudeOAuthCredentials.parse(data: sanitized) + } catch { + self.log.warning( + "Claude keychain security CLI output invalid; falling back", + metadata: [ + "reader": "securityCLI", + "callerInteraction": interactionMetadata, + "payload_bytes": "\(sanitized.count)", + "parse_error_type": String(describing: type(of: error)), + ]) + return nil + } + + var metadata: [String: String] = [ + "reader": "securityCLI", + "callerInteraction": interactionMetadata, + "payload_bytes": "\(sanitized.count)", + ] + for (key, value) in parsedCredentials.diagnosticsMetadata(now: Date()) { + metadata[key] = value + } + self.log.debug( + "Claude keychain security CLI read succeeded", + metadata: metadata) + return sanitized + } + + static func readRawClaudeKeychainPayloadViaSecurityCLIIfEnabled( + interaction: ProviderInteraction, + readStrategy: ClaudeOAuthKeychainReadStrategy = ClaudeOAuthKeychainReadStrategyPreference.current(), + environment: [String: String] = ProcessInfo.processInfo.environment) + -> Data? + { + guard self.shouldPreferSecurityCLIKeychainRead(readStrategy: readStrategy) else { return nil } + let interactionMetadata = interaction == .userInitiated ? "user" : "background" + + do { + let preferredAccount = self.preferredClaudeKeychainAccountForSecurityCLIRead( + interaction: interaction) + let output: Data + let status: Int32 + let stderrLength: Int + let durationMs: Double + #if DEBUG + if let override = self.taskSecurityCLIReadOverride ?? self.securityCLIReadOverride { + switch override { + case let .data(data): + output = data ?? Data() + status = 0 + stderrLength = 0 + durationMs = 0 + case .timedOut: + throw SecurityCLIReadError.timedOut + case .nonZeroExit: + throw SecurityCLIReadError.nonZeroExit(status: 1, stderrLength: 0) + case let .dynamic(read): + output = read(SecurityCLIReadRequest(account: preferredAccount)) ?? Data() + status = 0 + stderrLength = 0 + durationMs = 0 + } + } else { + let result = try self.runClaudeSecurityCLIRead( + timeout: self.securityCLIReadTimeout, + account: preferredAccount, + environment: environment) + output = result.stdout + status = result.status + stderrLength = result.stderrLength + durationMs = result.durationMs + } + #else + let result = try self.runClaudeSecurityCLIRead( + timeout: self.securityCLIReadTimeout, + account: preferredAccount, + environment: environment) + output = result.stdout + status = result.status + stderrLength = result.stderrLength + durationMs = result.durationMs + #endif + + let sanitized = self.sanitizeSecurityCLIOutput(output) + guard !sanitized.isEmpty else { return nil } + if ClaudeOAuthCredentials.isMcpOAuthOnlyPayload(data: sanitized) { + self.log.warning( + "Claude keychain security CLI output is MCP OAuth only; falling back", + metadata: [ + "reader": "securityCLI", + "callerInteraction": interactionMetadata, + "status": "\(status)", + "duration_ms": String(format: "%.2f", durationMs), + "stderr_length": "\(stderrLength)", + "payload_bytes": "\(sanitized.count)", + ]) + } else { + self.log.debug( + "Claude keychain security CLI raw read succeeded", + metadata: [ + "reader": "securityCLI", + "callerInteraction": interactionMetadata, + "status": "\(status)", + "duration_ms": String(format: "%.2f", durationMs), + "stderr_length": "\(stderrLength)", + "payload_bytes": "\(sanitized.count)", + ]) + } + return sanitized + } catch let error as SecurityCLIReadError { + var metadata: [String: String] = [ + "reader": "securityCLI", + "callerInteraction": interactionMetadata, + "error_type": String(describing: type(of: error)), + ] + switch error { + case .binaryUnavailable: + metadata["reason"] = "binaryUnavailable" + case .isolatedKeychainUnavailable: + metadata["reason"] = "isolatedKeychainUnavailable" + case .launchFailed: + metadata["reason"] = "launchFailed" + case .timedOut: + metadata["reason"] = "timedOut" + case let .nonZeroExit(status, stderrLength): + metadata["reason"] = "nonZeroExit" + metadata["status"] = "\(status)" + metadata["stderr_length"] = "\(stderrLength)" + } + self.log.warning("Claude keychain security CLI read failed; falling back", metadata: metadata) + return nil + } catch { + self.log.warning( + "Claude keychain security CLI read failed; falling back", + metadata: [ + "reader": "securityCLI", + "callerInteraction": interactionMetadata, + "error_type": String(describing: type(of: error)), + ]) + return nil + } + } + + private static func sanitizeSecurityCLIOutput(_ data: Data) -> Data { + var sanitized = data + while let last = sanitized.last, last == 0x0A || last == 0x0D { + sanitized.removeLast() + } + return sanitized + } + + private static func runClaudeSecurityCLIRead( + timeout: TimeInterval, + account: String?, + environment: [String: String]) throws -> SecurityCLIReadCommandResult + { + guard FileManager.default.isExecutableFile(atPath: self.securityBinaryPath) else { + throw SecurityCLIReadError.binaryUnavailable + } + guard let arguments = self.securityCLIReadArguments(account: account, environment: environment) else { + throw SecurityCLIReadError.isolatedKeychainUnavailable + } + + let process = Process() + process.executableURL = URL(fileURLWithPath: self.securityBinaryPath) + process.arguments = arguments + + let stdoutPipe = Pipe() + let stderrPipe = Pipe() + process.standardOutput = stdoutPipe + process.standardError = stderrPipe + process.standardInput = nil + + let startedAt = DispatchTime.now().uptimeNanoseconds + do { + try process.run() + } catch { + throw SecurityCLIReadError.launchFailed + } + + var processGroup: pid_t? + let pid = process.processIdentifier + if setpgid(pid, pid) == 0 { + processGroup = pid + } + + let deadline = Date().addingTimeInterval(timeout) + while process.isRunning, Date() < deadline { + Thread.sleep(forTimeInterval: 0.02) + } + + if process.isRunning { + self.terminate(process: process, processGroup: processGroup) + throw SecurityCLIReadError.timedOut + } + + let stdout = stdoutPipe.fileHandleForReading.readDataToEndOfFile() + let stderr = stderrPipe.fileHandleForReading.readDataToEndOfFile() + let status = process.terminationStatus + let durationMs = Double(DispatchTime.now().uptimeNanoseconds - startedAt) / 1_000_000.0 + guard status == 0 else { + throw SecurityCLIReadError.nonZeroExit(status: status, stderrLength: stderr.count) + } + + return SecurityCLIReadCommandResult( + status: status, + stdout: stdout, + stderrLength: stderr.count, + durationMs: durationMs) + } + + static func securityCLIReadArguments( + account: String?, + environment: [String: String]) -> [String]? + { + let isolatedKeychainPath = self.isolatedSecurityCLIKeychainPath(environment: environment) + if KeychainTestSafety.shouldBlockRealKeychainAccess(environment: environment), + isolatedKeychainPath == nil + { + return nil + } + + var arguments = [ + "find-generic-password", + "-s", + self.claudeKeychainService, + ] + if let account, !account.isEmpty { + arguments.append(contentsOf: ["-a", account]) + } + arguments.append("-w") + + let rawIsolatedPath = environment[self.isolatedSecurityCLIKeychainEnvironmentKey]? + .trimmingCharacters(in: .whitespacesAndNewlines) + if rawIsolatedPath != nil || KeychainAccessGate.isDisabledByEnvironment(environment) { + guard let isolatedKeychainPath else { + return nil + } + arguments.append(isolatedKeychainPath) + } + return arguments + } + + private static func terminate(process: Process, processGroup: pid_t?) { + guard process.isRunning else { return } + process.terminate() + if let processGroup { + kill(-processGroup, SIGTERM) + } + let deadline = Date().addingTimeInterval(0.4) + while process.isRunning, Date() < deadline { + usleep(50000) + } + if process.isRunning { + if let processGroup { + kill(-processGroup, SIGKILL) + } + kill(process.processIdentifier, SIGKILL) + } + } + #else + static func loadFromClaudeKeychainViaSecurityCLIIfEnabled( + interaction _: ProviderInteraction, + readStrategy _: ClaudeOAuthKeychainReadStrategy = ClaudeOAuthKeychainReadStrategyPreference.current()) + -> Data? + { + nil + } + + static func readRawClaudeKeychainPayloadViaSecurityCLIIfEnabled( + interaction _: ProviderInteraction, + readStrategy _: ClaudeOAuthKeychainReadStrategy = ClaudeOAuthKeychainReadStrategyPreference.current(), + environment _: [String: String] = ProcessInfo.processInfo.environment) + -> Data? + { + nil + } + #endif + + private static func isolatedSecurityCLIKeychainPath(environment: [String: String]) -> String? { + guard KeychainAccessGate.isDisabledByEnvironment(environment) else { return nil } + guard let rawPath = environment[self.isolatedSecurityCLIKeychainEnvironmentKey]? + .trimmingCharacters(in: .whitespacesAndNewlines), + !rawPath.isEmpty, + (rawPath as NSString).isAbsolutePath + else { + return nil + } + return URL(fileURLWithPath: rawPath).standardizedFileURL.path + } + + static func isMcpOAuthOnlyClaudeKeychainPayloadPresent( + interaction: ProviderInteraction, + readStrategy: ClaudeOAuthKeychainReadStrategy = ClaudeOAuthKeychainReadStrategyPreference.current(), + keychainAccessDisabled: Bool = KeychainAccessGate.isDisabled, + environment: [String: String] = ProcessInfo.processInfo.environment) -> Bool + { + guard !keychainAccessDisabled || self.isolatedSecurityCLIKeychainPath(environment: environment) != nil else { + return false + } + guard ClaudeOAuthKeychainPromptPreference.effectiveMode(readStrategy: readStrategy) != .never else { + return false + } + let payload: Data? = switch readStrategy { + case .securityFramework: + self.readRawClaudeKeychainPayloadViaSecurityFrameworkWithoutPrompt() + case .securityCLIExperimental: + self.readRawClaudeKeychainPayloadViaSecurityCLIIfEnabled( + interaction: interaction, + readStrategy: readStrategy, + environment: environment) + } + guard let payload else { return false } + return ClaudeOAuthCredentials.isMcpOAuthOnlyPayload(data: payload) + } +} diff --git a/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthCredentials+TestingOverrides.swift b/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthCredentials+TestingOverrides.swift new file mode 100644 index 0000000..4510bab --- /dev/null +++ b/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthCredentials+TestingOverrides.swift @@ -0,0 +1,430 @@ +import Foundation + +#if DEBUG +extension ClaudeOAuthCredentialsStore { + nonisolated(unsafe) static var claudeKeychainDataOverride: Data? + nonisolated(unsafe) static var claudeKeychainFingerprintOverride: ClaudeKeychainFingerprint? + @TaskLocal static var taskClaudeKeychainDataOverride: Data? + @TaskLocal static var taskClaudeKeychainFingerprintOverride: ClaudeKeychainFingerprint? + @TaskLocal static var taskMemoryCacheStoreOverride: MemoryCacheStore? + @TaskLocal static var taskClaudeKeychainFingerprintStoreOverride: ClaudeKeychainFingerprintStore? + @TaskLocal static var taskPendingCacheClearStoreOverride: ClaudeOAuthPendingCacheClearStore? + + typealias OAuthCacheOperation = KeychainCacheStore.Operation + typealias OAuthCacheOperationRecorder = KeychainCacheStore.OperationRecorder + + final class PendingCacheClearMemoryStore: ClaudeOAuthPendingCacheClearStore, @unchecked Sendable { + private let lock = NSLock() + private var pending: Bool + + init(isPending: Bool = false) { + self.pending = isPending + } + + var isPending: Bool { + self.lock.lock() + defer { self.lock.unlock() } + return self.pending + } + + func markPending() { + self.lock.lock() + self.pending = true + self.lock.unlock() + } + + func withCacheTransaction(_ operation: (inout Bool) -> Void) { + self.lock.lock() + defer { self.lock.unlock() } + operation(&self.pending) + } + } + + final class ClaudeKeychainFingerprintStore: @unchecked Sendable { + var fingerprint: ClaudeKeychainFingerprint? + + init(fingerprint: ClaudeKeychainFingerprint? = nil) { + self.fingerprint = fingerprint + } + } + + final class MemoryCacheStore: @unchecked Sendable { + var record: ClaudeOAuthCredentialRecord? + var timestamp: Date? + } + + static func setClaudeKeychainDataOverrideForTesting(_ data: Data?) { + self.claudeKeychainDataOverride = data + } + + static func setClaudeKeychainFingerprintOverrideForTesting(_ fingerprint: ClaudeKeychainFingerprint?) { + self.claudeKeychainFingerprintOverride = fingerprint + } + + static func withClaudeKeychainOverridesForTesting( + data: Data?, + fingerprint: ClaudeKeychainFingerprint?, + operation: () throws -> T) rethrows -> T + { + try self.$taskClaudeKeychainDataOverride.withValue(data) { + try self.$taskClaudeKeychainFingerprintOverride.withValue(fingerprint) { + try operation() + } + } + } + + static func withClaudeKeychainOverridesForTesting( + data: Data?, + fingerprint: ClaudeKeychainFingerprint?, + operation: () async throws -> T) async rethrows -> T + { + try await self.$taskClaudeKeychainDataOverride.withValue(data) { + try await self.$taskClaudeKeychainFingerprintOverride.withValue(fingerprint) { + try await operation() + } + } + } + + static func withClaudeKeychainFingerprintStoreOverrideForTesting( + _ store: ClaudeKeychainFingerprintStore?, + operation: () throws -> T) rethrows -> T + { + try self.$taskClaudeKeychainFingerprintStoreOverride.withValue(store) { + try operation() + } + } + + static func withClaudeKeychainFingerprintStoreOverrideForTesting( + _ store: ClaudeKeychainFingerprintStore?, + operation: () async throws -> T) async rethrows -> T + { + try await self.$taskClaudeKeychainFingerprintStoreOverride.withValue(store) { + try await operation() + } + } + + static func withIsolatedMemoryCacheForTesting(operation: () throws -> T) rethrows -> T { + let store = MemoryCacheStore() + let preAlertStore = ClaudeOAuthKeychainPreAlertGate.StateStore() + return try ClaudeOAuthKeychainPreAlertGate.withStateStoreOverrideForTesting(preAlertStore) { + try self.$taskMemoryCacheStoreOverride.withValue(store) { + try operation() + } + } + } + + static func withIsolatedMemoryCacheForTesting(operation: () async throws -> T) async rethrows -> T { + let store = MemoryCacheStore() + let preAlertStore = ClaudeOAuthKeychainPreAlertGate.StateStore() + return try await ClaudeOAuthKeychainPreAlertGate.withStateStoreOverrideForTesting(preAlertStore) { + try await self.$taskMemoryCacheStoreOverride.withValue(store) { + try await operation() + } + } + } + + final class CredentialsFileFingerprintStore: @unchecked Sendable { + var fingerprint: CredentialsFileFingerprint? + + init(fingerprint: CredentialsFileFingerprint? = nil) { + self.fingerprint = fingerprint + } + + func load() -> CredentialsFileFingerprint? { + self.fingerprint + } + + func save(_ fingerprint: CredentialsFileFingerprint?) { + self.fingerprint = fingerprint + } + } + + enum SecurityCLIReadOverride { + case data(Data?) + case timedOut + case nonZeroExit + case dynamic(@Sendable (SecurityCLIReadRequest) -> Data?) + } + + @TaskLocal static var taskKeychainAccessOverride: Bool? + @TaskLocal static var taskCredentialsFileFingerprintStoreOverride: CredentialsFileFingerprintStore? + @TaskLocal static var taskSecurityCLIReadOverride: SecurityCLIReadOverride? + @TaskLocal static var taskSecurityCLIReadAccountOverride: String? + nonisolated(unsafe) static var securityCLIReadOverride: SecurityCLIReadOverride? + + public struct TestingOverridesSnapshot: Sendable { + let keychainOverrideStore: ClaudeKeychainOverrideStore? + let keychainData: Data? + let keychainFingerprint: ClaudeKeychainFingerprint? + let memoryCacheStore: MemoryCacheStore? + let fingerprintStore: ClaudeKeychainFingerprintStore? + let keychainAccessOverride: Bool? + let credentialsFileFingerprintStore: CredentialsFileFingerprintStore? + let securityCLIReadOverride: SecurityCLIReadOverride? + let securityCLIReadAccountOverride: String? + let pendingCacheClearStore: ClaudeOAuthPendingCacheClearStore? + let oauthCacheOperationRecorder: OAuthCacheOperationRecorder? + + init( + keychainOverrideStore: ClaudeKeychainOverrideStore?, + keychainData: Data?, + keychainFingerprint: ClaudeKeychainFingerprint?, + memoryCacheStore: MemoryCacheStore?, + fingerprintStore: ClaudeKeychainFingerprintStore?, + keychainAccessOverride: Bool?, + credentialsFileFingerprintStore: CredentialsFileFingerprintStore?, + securityCLIReadOverride: SecurityCLIReadOverride?, + securityCLIReadAccountOverride: String?, + pendingCacheClearStore: ClaudeOAuthPendingCacheClearStore?, + oauthCacheOperationRecorder: OAuthCacheOperationRecorder?) + { + self.keychainOverrideStore = keychainOverrideStore + self.keychainData = keychainData + self.keychainFingerprint = keychainFingerprint + self.memoryCacheStore = memoryCacheStore + self.fingerprintStore = fingerprintStore + self.keychainAccessOverride = keychainAccessOverride + self.credentialsFileFingerprintStore = credentialsFileFingerprintStore + self.securityCLIReadOverride = securityCLIReadOverride + self.securityCLIReadAccountOverride = securityCLIReadAccountOverride + self.pendingCacheClearStore = pendingCacheClearStore + self.oauthCacheOperationRecorder = oauthCacheOperationRecorder + } + } + + static func withKeychainAccessOverrideForTesting( + _ disabled: Bool?, + operation: () throws -> T) rethrows -> T + { + try self.$taskKeychainAccessOverride.withValue(disabled) { + try operation() + } + } + + static func withKeychainAccessOverrideForTesting( + _ disabled: Bool?, + operation: () async throws -> T) async rethrows -> T + { + try await self.$taskKeychainAccessOverride.withValue(disabled) { + try await operation() + } + } + + fileprivate static func withCredentialsFileFingerprintStoreOverrideForTesting( + _ store: CredentialsFileFingerprintStore?, + operation: () throws -> T) rethrows -> T + { + try self.$taskCredentialsFileFingerprintStoreOverride.withValue(store) { + try operation() + } + } + + fileprivate static func withCredentialsFileFingerprintStoreOverrideForTesting( + _ store: CredentialsFileFingerprintStore?, + operation: () async throws -> T) async rethrows -> T + { + try await self.$taskCredentialsFileFingerprintStoreOverride.withValue(store) { + try await operation() + } + } + + static func withIsolatedCredentialsFileTrackingForTesting( + operation: () throws -> T) rethrows -> T + { + let store = CredentialsFileFingerprintStore() + return try self.$taskCredentialsFileFingerprintStoreOverride.withValue(store) { + try operation() + } + } + + static func withPendingCacheClearStoreOverrideForTesting( + _ store: ClaudeOAuthPendingCacheClearStore?, + operation: () throws -> T) rethrows -> T + { + try self.$taskPendingCacheClearStoreOverride.withValue(store) { + try operation() + } + } + + static func withPendingCacheClearStoreOverrideForTesting( + _ store: ClaudeOAuthPendingCacheClearStore?, + operation: () async throws -> T) async rethrows -> T + { + try await self.$taskPendingCacheClearStoreOverride.withValue(store) { + try await operation() + } + } + + static func withOAuthCacheOperationRecorderForTesting( + _ recorder: OAuthCacheOperationRecorder?, + operation: () throws -> T) rethrows -> T + { + try KeychainCacheStore.withOperationRecorderForTesting(recorder, operation: operation) + } + + static func withOAuthCacheOperationRecorderForTesting( + _ recorder: OAuthCacheOperationRecorder?, + operation: () async throws -> T) async rethrows -> T + { + try await KeychainCacheStore.withOperationRecorderForTesting(recorder, operation: operation) + } + + static func withIsolatedCredentialsFileTrackingForTesting( + operation: () async throws -> T) async rethrows -> T + { + let store = CredentialsFileFingerprintStore() + return try await self.$taskCredentialsFileFingerprintStoreOverride.withValue(store) { + try await operation() + } + } + + static func withSecurityCLIReadOverrideForTesting( + _ readOverride: SecurityCLIReadOverride?, + operation: () throws -> T) rethrows -> T + { + try self.$taskSecurityCLIReadOverride.withValue(readOverride) { + try operation() + } + } + + static func withSecurityCLIReadOverrideForTesting( + _ readOverride: SecurityCLIReadOverride?, + operation: () async throws -> T) async rethrows -> T + { + try await self.$taskSecurityCLIReadOverride.withValue(readOverride) { + try await operation() + } + } + + static func currentSecurityCLIReadOverrideForTesting() -> SecurityCLIReadOverride? { + self.taskSecurityCLIReadOverride ?? self.securityCLIReadOverride + } + + static func withSecurityCLIReadAccountOverrideForTesting( + _ account: String?, + operation: () throws -> T) rethrows -> T + { + try self.$taskSecurityCLIReadAccountOverride.withValue(account) { + try operation() + } + } + + static func withSecurityCLIReadAccountOverrideForTesting( + _ account: String?, + operation: () async throws -> T) async rethrows -> T + { + try await self.$taskSecurityCLIReadAccountOverride.withValue(account) { + try await operation() + } + } + + public static func withCurrentTestingOverridesForTask( + operation: () async throws -> T) async rethrows -> T + { + try await self.withTestingOverridesSnapshotForTask( + self.currentTestingOverridesSnapshotForTask, + operation: operation) + } + + public static func withCurrentTestingOverridesForTask( + operation: () throws -> T) rethrows -> T + { + try self.withTestingOverridesSnapshotForTask( + self.currentTestingOverridesSnapshotForTask, + operation: operation) + } + + public static var currentTestingOverridesSnapshotForTask: TestingOverridesSnapshot { + TestingOverridesSnapshot( + keychainOverrideStore: self.taskClaudeKeychainOverrideStore, + keychainData: self.taskClaudeKeychainDataOverride, + keychainFingerprint: self.taskClaudeKeychainFingerprintOverride, + memoryCacheStore: self.taskMemoryCacheStoreOverride, + fingerprintStore: self.taskClaudeKeychainFingerprintStoreOverride, + keychainAccessOverride: self.taskKeychainAccessOverride, + credentialsFileFingerprintStore: self.taskCredentialsFileFingerprintStoreOverride, + securityCLIReadOverride: self.taskSecurityCLIReadOverride, + securityCLIReadAccountOverride: self.taskSecurityCLIReadAccountOverride, + pendingCacheClearStore: self.taskPendingCacheClearStoreOverride, + oauthCacheOperationRecorder: KeychainCacheStore.currentOperationRecorderForTesting) + } + + public static func withTestingOverridesSnapshotForTask( + _ snapshot: TestingOverridesSnapshot, + operation: () async throws -> T) async rethrows -> T + { + try await self.$taskPendingCacheClearStoreOverride.withValue(snapshot.pendingCacheClearStore) { + try await KeychainCacheStore.withOperationRecorderForTesting(snapshot.oauthCacheOperationRecorder) { + try await self.$taskClaudeKeychainOverrideStore.withValue(snapshot.keychainOverrideStore) { + try await self.$taskClaudeKeychainDataOverride.withValue(snapshot.keychainData) { + try await self.$taskClaudeKeychainFingerprintOverride.withValue(snapshot.keychainFingerprint) { + try await self.$taskMemoryCacheStoreOverride.withValue(snapshot.memoryCacheStore) { + try await self.$taskClaudeKeychainFingerprintStoreOverride + .withValue(snapshot.fingerprintStore) { + try await self.$taskKeychainAccessOverride + .withValue(snapshot.keychainAccessOverride) { + try await self.$taskCredentialsFileFingerprintStoreOverride.withValue( + snapshot.credentialsFileFingerprintStore) + { + try await self.$taskSecurityCLIReadOverride.withValue( + snapshot.securityCLIReadOverride) + { + try await self.$taskSecurityCLIReadAccountOverride.withValue( + snapshot.securityCLIReadAccountOverride) + { + try await operation() + } + } + } + } + } + } + } + } + } + } + } + } + + public static func withTestingOverridesSnapshotForTask( + _ snapshot: TestingOverridesSnapshot, + operation: () throws -> T) rethrows -> T + { + try self.$taskPendingCacheClearStoreOverride.withValue(snapshot.pendingCacheClearStore) { + try KeychainCacheStore.withOperationRecorderForTesting(snapshot.oauthCacheOperationRecorder) { + try self.$taskClaudeKeychainOverrideStore.withValue(snapshot.keychainOverrideStore) { + try self.$taskClaudeKeychainDataOverride.withValue(snapshot.keychainData) { + try self.$taskClaudeKeychainFingerprintOverride.withValue(snapshot.keychainFingerprint) { + try self.$taskMemoryCacheStoreOverride.withValue(snapshot.memoryCacheStore) { + try self.$taskClaudeKeychainFingerprintStoreOverride + .withValue(snapshot.fingerprintStore) { + try self.$taskKeychainAccessOverride + .withValue(snapshot.keychainAccessOverride) { + try self.$taskCredentialsFileFingerprintStoreOverride.withValue( + snapshot.credentialsFileFingerprintStore) + { + try self.$taskSecurityCLIReadOverride.withValue( + snapshot.securityCLIReadOverride) + { + try self.$taskSecurityCLIReadAccountOverride.withValue( + snapshot.securityCLIReadAccountOverride) + { + try operation() + } + } + } + } + } + } + } + } + } + } + } + } + + static func setSecurityCLIReadOverrideForTesting(_ readOverride: SecurityCLIReadOverride?) { + self.securityCLIReadOverride = readOverride + } +} +#endif diff --git a/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthCredentials.swift b/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthCredentials.swift new file mode 100644 index 0000000..bef352f --- /dev/null +++ b/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthCredentials.swift @@ -0,0 +1,2563 @@ +import Dispatch +import Foundation + +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +#if os(macOS) +import LocalAuthentication +import Security +#endif + +// swiftlint:disable type_body_length file_length +public enum ClaudeOAuthCredentialsStore { + private static let credentialsPath = ".claude/.credentials.json" + static let claudeKeychainService = "Claude Code-credentials" + private static let cacheKey = KeychainCacheStore.Key.oauth(provider: .claude) + public static let environmentTokenKey = "CODEXBAR_CLAUDE_OAUTH_TOKEN" + public static let environmentScopesKey = "CODEXBAR_CLAUDE_OAUTH_SCOPES" + + // Claude CLI's OAuth client ID - this is a public identifier (not a secret). + // It's the same client ID used by Claude Code CLI for OAuth PKCE flow. + // Can be overridden via environment variable if Anthropic ever changes it. + public static let defaultOAuthClientID = "9d1c250a-e61b-44d9-88ed-5944d1962f5e" + public static let environmentClientIDKey = "CODEXBAR_CLAUDE_OAUTH_CLIENT_ID" + private static let tokenRefreshEndpoint = "https://platform.claude.com/v1/oauth/token" + + private static var oauthClientID: String { + ProcessInfo.processInfo.environment[self.environmentClientIDKey]? + .trimmingCharacters(in: .whitespacesAndNewlines) + ?? self.defaultOAuthClientID + } + + static let log = CodexBarLog.logger(LogCategories.claudeUsage) + private static let fileFingerprintKey = "ClaudeOAuthCredentialsFileFingerprintV2" + private static let claudeKeychainPromptLock = NSLock() + private static let claudeKeychainFingerprintKey = "ClaudeOAuthClaudeKeychainFingerprintV2" + private static let claudeKeychainFingerprintLegacyKey = "ClaudeOAuthClaudeKeychainFingerprintV1" + private static let pendingCodexBarOAuthKeychainCacheClearKey = + "ClaudeOAuthPendingCodexBarOAuthKeychainCacheClearV1" + private static let pendingCodexBarOAuthKeychainCacheClearStore: ClaudeOAuthPendingCacheClearStore = + ClaudeOAuthPendingCacheClearUserDefaultsStore( + // The cache service is shared by release/debug apps and their CLIs, so its tombstone is shared too. + domain: "com.steipete.codexbar", + key: ClaudeOAuthCredentialsStore.pendingCodexBarOAuthKeychainCacheClearKey) + private static let claudeKeychainChangeCheckLock = NSLock() + private nonisolated(unsafe) static var lastClaudeKeychainChangeCheckAt: Date? + private static let claudeKeychainChangeCheckMinimumInterval: TimeInterval = 60 + private static let reauthenticateHint = "Run `claude` to re-authenticate." + + struct ClaudeKeychainFingerprint: Codable, Equatable { + let modifiedAt: Int? + let createdAt: Int? + let persistentRefHash: String? + } + + private struct ClaudeKeychainCredentialEvidence { + let credentials: ClaudeOAuthCredentials + let persistentRefHash: String + } + + struct CredentialsFileFingerprint: Codable, Equatable { + let modifiedAtMs: Int? + let size: Int + } + + struct CacheEntry: Codable { + let data: Data + let storedAt: Date + let owner: ClaudeOAuthCredentialOwner? + let historyOwnerIdentifier: String? + + init( + data: Data, + storedAt: Date, + owner: ClaudeOAuthCredentialOwner? = nil, + historyOwnerIdentifier: String? = nil) + { + self.data = data + self.storedAt = storedAt + self.owner = owner + self.historyOwnerIdentifier = ClaudeOAuthCredentials.normalizedHistoryOwnerIdentifier( + historyOwnerIdentifier) + } + } + + private nonisolated(unsafe) static var credentialsURLOverride: URL? + #if DEBUG + @TaskLocal private static var taskCredentialsURLOverride: URL? + #endif + @TaskLocal static var allowBackgroundPromptBootstrap: Bool = false + // In-memory cache (nonisolated for synchronous access) + private static let memoryCacheLock = NSLock() + private nonisolated(unsafe) static var cachedCredentialRecord: ClaudeOAuthCredentialRecord? + private nonisolated(unsafe) static var cacheTimestamp: Date? + private static let memoryCacheValidityDuration: TimeInterval = 1800 + + private static func readMemoryCache() -> (record: ClaudeOAuthCredentialRecord?, timestamp: Date?) { + #if DEBUG + if let store = self.taskMemoryCacheStoreOverride { + return (store.record, store.timestamp) + } + #endif + self.memoryCacheLock.lock() + defer { self.memoryCacheLock.unlock() } + return (self.cachedCredentialRecord, self.cacheTimestamp) + } + + private static func writeMemoryCache(record: ClaudeOAuthCredentialRecord?, timestamp: Date?) { + #if DEBUG + if let store = self.taskMemoryCacheStoreOverride { + store.record = record + store.timestamp = timestamp + return + } + #endif + self.memoryCacheLock.lock() + self.cachedCredentialRecord = record + self.cacheTimestamp = timestamp + self.memoryCacheLock.unlock() + } + + private struct CollaboratorContext { + let allowBackgroundPromptBootstrap: Bool + #if DEBUG + let credentialsURLOverride: URL? + let testingOverrides: TestingOverridesSnapshot + #endif + + func run(_ operation: () throws -> T) rethrows -> T { + try ClaudeOAuthCredentialsStore.$allowBackgroundPromptBootstrap + .withValue(self.allowBackgroundPromptBootstrap) { + #if DEBUG + try ClaudeOAuthCredentialsStore.withTestingOverridesSnapshotForTask(self.testingOverrides) { + try ClaudeOAuthCredentialsStore + .withCredentialsURLOverrideForTesting(self.credentialsURLOverride) { + try operation() + } + } + #else + try operation() + #endif + } + } + + func run(_ operation: () async throws -> T) async rethrows -> T { + try await ClaudeOAuthCredentialsStore.$allowBackgroundPromptBootstrap + .withValue(self.allowBackgroundPromptBootstrap) { + #if DEBUG + try await ClaudeOAuthCredentialsStore.withTestingOverridesSnapshotForTask(self.testingOverrides) { + try await ClaudeOAuthCredentialsStore.withCredentialsURLOverrideForTesting( + self.credentialsURLOverride) + { + try await operation() + } + } + #else + try await operation() + #endif + } + } + } + + private static func currentCollaboratorContext() -> CollaboratorContext { + #if DEBUG + CollaboratorContext( + allowBackgroundPromptBootstrap: self.allowBackgroundPromptBootstrap, + credentialsURLOverride: self.taskCredentialsURLOverride, + testingOverrides: self.currentTestingOverridesSnapshotForTask) + #else + CollaboratorContext( + allowBackgroundPromptBootstrap: self.allowBackgroundPromptBootstrap) + #endif + } + + private struct Repository { + let context: CollaboratorContext + + func load(environment: [String: String], allowKeychainPrompt: Bool, respectKeychainPromptCooldown: Bool) throws + -> ClaudeOAuthCredentials + { + try self.loadRecord( + environment: environment, + allowKeychainPrompt: allowKeychainPrompt, + respectKeychainPromptCooldown: respectKeychainPromptCooldown, + allowClaudeKeychainRepairWithoutPrompt: true).credentials + } + + func loadRecord( + environment: [String: String], + allowKeychainPrompt: Bool, + respectKeychainPromptCooldown: Bool, + allowClaudeKeychainRepairWithoutPrompt: Bool) throws -> ClaudeOAuthCredentialRecord + { + try self.context.run { + let shouldRespectKeychainPromptCooldownForSilentProbes = + respectKeychainPromptCooldown || !allowKeychainPrompt + + if let credentials = ClaudeOAuthCredentialsStore.loadFromEnvironment(environment) { + return ClaudeOAuthCredentialRecord( + credentials: credentials, + owner: .environment, + source: .environment) + } + + _ = self.invalidateCacheIfCredentialsFileChanged() + + let recovery = Recovery(context: self.context) + let memory = ClaudeOAuthCredentialsStore.readMemoryCache() + if ClaudeOAuthCredentialsStore.shouldUseCodexBarOAuthKeychainCache, + !ClaudeOAuthCredentialsStore.hasPendingCodexBarOAuthKeychainCacheClear, + let cachedRecord = memory.record, + let timestamp = memory.timestamp, + Date().timeIntervalSince(timestamp) < ClaudeOAuthCredentialsStore.memoryCacheValidityDuration, + !cachedRecord.credentials.isExpired + { + let owner = self.resolvedCacheOwner(cachedRecord.owner) + let record = ClaudeOAuthCredentialRecord( + credentials: cachedRecord.credentials, + owner: owner, + source: .memoryCache, + historyOwnerIdentifier: cachedRecord.historyOwnerIdentifier) + if recovery.shouldAttemptFreshnessSyncFromClaudeKeychain(cached: record), + let synced = recovery.syncWithClaudeKeychainIfChanged( + cached: record, + respectKeychainPromptCooldown: shouldRespectKeychainPromptCooldownForSilentProbes) + { + return synced + } + return record + } + + var lastError: Error? + var expiredRecord: ClaudeOAuthCredentialRecord? + var cacheTemporarilyUnavailable = false + + switch ClaudeOAuthCredentialsStore.loadCodexBarOAuthKeychainCache() { + case let .found(entry): + if let creds = try? ClaudeOAuthCredentials.parse(data: entry.data) { + let owner = self.resolvedCacheOwner(entry.owner ?? .claudeCLI) + let record = ClaudeOAuthCredentialRecord( + credentials: creds, + owner: owner, + source: .cacheKeychain, + historyOwnerIdentifier: entry.historyOwnerIdentifier) + if creds.isExpired { + expiredRecord = record + } else { + if recovery.shouldAttemptFreshnessSyncFromClaudeKeychain(cached: record), + let synced = recovery.syncWithClaudeKeychainIfChanged( + cached: record, + respectKeychainPromptCooldown: shouldRespectKeychainPromptCooldownForSilentProbes) + { + return synced + } + ClaudeOAuthCredentialsStore.writeMemoryCache( + record: ClaudeOAuthCredentialRecord( + credentials: creds, + owner: owner, + source: .memoryCache, + historyOwnerIdentifier: record.historyOwnerIdentifier), + timestamp: Date()) + return record + } + } else { + ClaudeOAuthCredentialsStore.clearCacheKeychain() + } + case .invalid: + ClaudeOAuthCredentialsStore.clearCacheKeychain() + case .temporarilyUnavailable: + cacheTemporarilyUnavailable = true + case .missing: + break + } + + do { + let fileData = try ClaudeOAuthCredentialsStore.loadFromFile() + let creds = try ClaudeOAuthCredentials.parse(data: fileData) + let record = ClaudeOAuthCredentialRecord( + credentials: creds, + owner: .claudeCLI, + source: .credentialsFile) + if creds.isExpired { + expiredRecord = record + } else { + ClaudeOAuthCredentialsStore.writeMemoryCache( + record: ClaudeOAuthCredentialRecord( + credentials: creds, + owner: .claudeCLI, + source: .memoryCache), + timestamp: Date()) + if !cacheTemporarilyUnavailable { + ClaudeOAuthCredentialsStore.saveToCacheKeychain(fileData, owner: .claudeCLI) + } + return record + } + } catch let error as ClaudeOAuthCredentialsError { + if case .notFound = error { + } else { + lastError = error + } + } catch { + lastError = error + } + + if allowClaudeKeychainRepairWithoutPrompt, !allowKeychainPrompt { + if let repaired = recovery.repairFromClaudeKeychainWithoutPromptIfAllowed( + now: Date(), + respectKeychainPromptCooldown: shouldRespectKeychainPromptCooldownForSilentProbes, + allowCacheKeychainWrite: !cacheTemporarilyUnavailable) + { + return repaired + } + } + + if let prompted = self.loadFromClaudeKeychainWithPromptIfAllowed( + allowKeychainPrompt: allowKeychainPrompt, + respectKeychainPromptCooldown: respectKeychainPromptCooldown, + allowCacheKeychainWrite: !cacheTemporarilyUnavailable, + lastError: &lastError) + { + return prompted + } + + if let expiredRecord { + return expiredRecord + } + if let lastError { + throw lastError + } + throw ClaudeOAuthCredentialsError.notFound + } + } + + private func loadFromClaudeKeychainWithPromptIfAllowed( + allowKeychainPrompt: Bool, + respectKeychainPromptCooldown: Bool, + allowCacheKeychainWrite: Bool, + lastError: inout Error?) -> ClaudeOAuthCredentialRecord? + { + let shouldApplyPromptCooldown = + ClaudeOAuthCredentialsStore.isPromptPolicyApplicable && respectKeychainPromptCooldown + let promptAllowed = + allowKeychainPrompt + && (!shouldApplyPromptCooldown || ClaudeOAuthKeychainAccessGate.shouldAllowPrompt()) + guard promptAllowed else { return nil } + + do { + ClaudeOAuthCredentialsStore.claudeKeychainPromptLock.lock() + defer { ClaudeOAuthCredentialsStore.claudeKeychainPromptLock.unlock() } + + let memory = ClaudeOAuthCredentialsStore.readMemoryCache() + if ClaudeOAuthCredentialsStore.shouldUseCodexBarOAuthKeychainCache, + !ClaudeOAuthCredentialsStore.hasPendingCodexBarOAuthKeychainCacheClear, + let cachedRecord = memory.record, + let timestamp = memory.timestamp, + Date().timeIntervalSince(timestamp) < ClaudeOAuthCredentialsStore.memoryCacheValidityDuration, + !cachedRecord.credentials.isExpired + { + let owner = self.resolvedCacheOwner(cachedRecord.owner) + return ClaudeOAuthCredentialRecord( + credentials: cachedRecord.credentials, + owner: owner, + source: .memoryCache, + historyOwnerIdentifier: cachedRecord.historyOwnerIdentifier) + } + if case let .found(entry) = ClaudeOAuthCredentialsStore.loadCodexBarOAuthKeychainCache(), + let creds = try? ClaudeOAuthCredentials.parse(data: entry.data), + !creds.isExpired + { + let owner = self.resolvedCacheOwner(entry.owner ?? .claudeCLI) + return ClaudeOAuthCredentialRecord( + credentials: creds, + owner: owner, + source: .cacheKeychain, + historyOwnerIdentifier: entry.historyOwnerIdentifier) + } + + let promptMode = ClaudeOAuthKeychainPromptPreference.current() + guard ClaudeOAuthCredentialsStore.shouldAllowClaudeCodeKeychainAccess(mode: promptMode) else { + return nil + } + + if ClaudeOAuthCredentialsStore.shouldPreferSecurityCLIKeychainRead(), + let keychainData = ClaudeOAuthCredentialsStore.loadFromClaudeKeychainViaSecurityCLIIfEnabled( + interaction: ProviderInteractionContext.current) + { + let creds = try ClaudeOAuthCredentials.parse(data: keychainData) + let record = ClaudeOAuthCredentialRecord( + credentials: creds, + owner: .claudeCLI, + source: .claudeKeychain) + ClaudeOAuthCredentialsStore.writeMemoryCache( + record: ClaudeOAuthCredentialRecord( + credentials: creds, + owner: .claudeCLI, + source: .memoryCache), + timestamp: Date()) + if allowCacheKeychainWrite { + ClaudeOAuthCredentialsStore.saveToCacheKeychain(keychainData, owner: .claudeCLI) + } + return record + } + + let shouldPreferSecurityCLIKeychainRead = + ClaudeOAuthCredentialsStore.shouldPreferSecurityCLIKeychainRead() + var fallbackPromptMode = promptMode + if shouldPreferSecurityCLIKeychainRead { + fallbackPromptMode = ClaudeOAuthKeychainPromptPreference.securityFrameworkFallbackMode() + let fallbackDecision = ClaudeOAuthCredentialsStore.securityFrameworkFallbackPromptDecision( + promptMode: fallbackPromptMode, + allowKeychainPrompt: allowKeychainPrompt, + respectKeychainPromptCooldown: respectKeychainPromptCooldown) + ClaudeOAuthCredentialsStore.log.debug( + "Claude keychain Security.framework fallback prompt policy evaluated", + metadata: [ + "reader": "securityFrameworkFallback", + "fallbackPromptMode": fallbackPromptMode.rawValue, + "fallbackPromptAllowed": "\(fallbackDecision.allowed)", + "fallbackBlockedReason": fallbackDecision.blockedReason ?? "none", + ]) + guard fallbackDecision.allowed else { return nil } + } + + if ClaudeOAuthCredentialsStore.shouldNotifyClaudeKeychainPreAlert() { + ClaudeOAuthKeychainPreAlertGate.presentIfNeeded { + KeychainPromptHandler.notifyIfHandled( + KeychainPromptContext( + kind: .claudeOAuth, + service: ClaudeOAuthCredentialsStore.claudeKeychainService, + account: nil)) + } + } + let keychainData: Data = if shouldPreferSecurityCLIKeychainRead { + try ClaudeOAuthCredentialsStore.loadFromClaudeKeychainUsingSecurityFramework( + promptMode: fallbackPromptMode, + allowKeychainPrompt: true) + } else { + try ClaudeOAuthCredentialsStore.loadFromClaudeKeychain() + } + let creds = try ClaudeOAuthCredentials.parse(data: keychainData) + let record = ClaudeOAuthCredentialRecord( + credentials: creds, + owner: .claudeCLI, + source: .claudeKeychain) + ClaudeOAuthCredentialsStore.writeMemoryCache( + record: ClaudeOAuthCredentialRecord( + credentials: creds, + owner: .claudeCLI, + source: .memoryCache), + timestamp: Date()) + if allowCacheKeychainWrite { + ClaudeOAuthCredentialsStore.saveToCacheKeychain(keychainData, owner: .claudeCLI) + } + return record + } catch let error as ClaudeOAuthCredentialsError { + if case .notFound = error { + } else { + lastError = error + } + } catch { + lastError = error + } + return nil + } + + private func resolvedCacheOwner(_ owner: ClaudeOAuthCredentialOwner) -> ClaudeOAuthCredentialOwner { + guard owner == .codexbar else { return owner } + guard self.hasClaudeCLIStorageWithoutPrompt() else { return owner } + // Claude Code rotates refresh tokens; when its storage exists, it owns the refresh lifecycle. + return .claudeCLI + } + + private func hasClaudeCLIStorageWithoutPrompt() -> Bool { + if ClaudeOAuthCredentialsStore.currentFileFingerprint() != nil { + return true + } + guard ClaudeOAuthKeychainPromptPreference.storedMode() != .never else { return false } + return ClaudeOAuthCredentialsStore.hasClaudeKeychainItemWithoutPrompt() + } + + @discardableResult + func invalidateCacheIfCredentialsFileChanged() -> Bool { + self.context.run { + let current = ClaudeOAuthCredentialsStore.currentFileFingerprint() + let stored = ClaudeOAuthCredentialsStore.loadFileFingerprint() + guard current != stored else { return false } + ClaudeOAuthCredentialsStore.log.info("Claude OAuth credentials file changed; invalidating cache") + + ClaudeOAuthCredentialsStore.writeMemoryCache(record: nil, timestamp: nil) + + var shouldClearKeychainCache = false + var shouldSaveFileFingerprint = true + if ClaudeOAuthCredentialsStore.shouldUseCodexBarOAuthKeychainCache { + if ClaudeOAuthCredentialsStore.hasPendingCodexBarOAuthKeychainCacheClear { + // The next cache access owns the deferred clear. Avoid repeated delete attempts inside one + // load and leave the fingerprint pending until that clear succeeds. + shouldSaveFileFingerprint = false + } else if let current { + if let modifiedAtMs = current.modifiedAtMs { + let modifiedAt = Date( + timeIntervalSince1970: TimeInterval(Double(modifiedAtMs) / 1000.0)) + switch ClaudeOAuthCredentialsStore.loadCodexBarOAuthKeychainCache() { + case let .found(entry): + if entry.storedAt < modifiedAt { + shouldClearKeychainCache = true + } + case .missing, .invalid: + shouldClearKeychainCache = true + case .temporarilyUnavailable: + shouldClearKeychainCache = false + shouldSaveFileFingerprint = false + } + } else { + shouldClearKeychainCache = true + } + } else { + shouldClearKeychainCache = true + } + } else { + ClaudeOAuthCredentialsStore.markPendingCodexBarOAuthKeychainCacheClear() + } + + if shouldClearKeychainCache { + ClaudeOAuthCredentialsStore.clearCacheKeychain() + } + if shouldSaveFileFingerprint { + ClaudeOAuthCredentialsStore.saveFileFingerprint(current) + } + return true + } + } + + func invalidateCache() { + self.context.run { + ClaudeOAuthCredentialsStore.writeMemoryCache(record: nil, timestamp: nil) + ClaudeOAuthCredentialsStore.clearCacheKeychain() + } + } + + func hasCachedCredentials(environment: [String: String]) -> Bool { + self.context.run { + func isRefreshableOrValid(_ record: ClaudeOAuthCredentialRecord) -> Bool { + let creds = record.credentials + if !creds.isExpired { + return true + } + switch record.owner { + case .claudeCLI: + return true + case .codexbar: + let refreshToken = creds.refreshToken?.trimmingCharacters( + in: .whitespacesAndNewlines) ?? "" + return !refreshToken.isEmpty + case .environment: + return false + } + } + + if let creds = ClaudeOAuthCredentialsStore.loadFromEnvironment(environment), + isRefreshableOrValid( + ClaudeOAuthCredentialRecord( + credentials: creds, + owner: .environment, + source: .environment)) + { + return true + } + + let memory = ClaudeOAuthCredentialsStore.readMemoryCache() + if ClaudeOAuthCredentialsStore.shouldUseCodexBarOAuthKeychainCache, + !ClaudeOAuthCredentialsStore.hasPendingCodexBarOAuthKeychainCacheClear, + let timestamp = memory.timestamp, + let cached = memory.record, + Date().timeIntervalSince(timestamp) < ClaudeOAuthCredentialsStore.memoryCacheValidityDuration, + isRefreshableOrValid(cached) + { + return true + } + + switch ClaudeOAuthCredentialsStore.loadCodexBarOAuthKeychainCache() { + case let .found(entry): + guard let creds = try? ClaudeOAuthCredentials.parse(data: entry.data) else { return false } + let record = ClaudeOAuthCredentialRecord( + credentials: creds, + owner: entry.owner ?? .claudeCLI, + source: .cacheKeychain) + return isRefreshableOrValid(record) + case .temporarilyUnavailable: + if ClaudeOAuthCredentialsStore.hasPendingCodexBarOAuthKeychainCacheClear { + break + } + return true + case .missing, .invalid: + break + } + + if let fileData = try? ClaudeOAuthCredentialsStore.loadFromFile(), + let creds = try? ClaudeOAuthCredentials.parse(data: fileData), + isRefreshableOrValid( + ClaudeOAuthCredentialRecord( + credentials: creds, + owner: .claudeCLI, + source: .credentialsFile)) + { + return true + } + return false + } + } + + func hasClaudeKeychainCredentialsWithoutPrompt() -> Bool { + self.context.run { + #if os(macOS) + let mode = ClaudeOAuthKeychainPromptPreference.current() + guard ClaudeOAuthCredentialsStore.shouldAllowClaudeCodeKeychainAccess(mode: mode) else { return false } + if ClaudeOAuthCredentialsStore.loadFromClaudeKeychainViaSecurityCLIIfEnabled( + interaction: ProviderInteractionContext.current) != nil + { + return true + } + + let fallbackPromptMode = ClaudeOAuthKeychainPromptPreference.securityFrameworkFallbackMode() + guard ClaudeOAuthCredentialsStore.shouldAllowClaudeCodeKeychainAccess(mode: fallbackPromptMode) else { + return false + } + if ProviderInteractionContext.current == .background, + !ClaudeOAuthKeychainAccessGate.shouldAllowPrompt() + { + return false + } + #if DEBUG + if let store = ClaudeOAuthCredentialsStore.taskClaudeKeychainOverrideStore, + let data = store.data + { + return (try? ClaudeOAuthCredentials.parse(data: data)) != nil + } + if let data = ClaudeOAuthCredentialsStore.taskClaudeKeychainDataOverride + ?? ClaudeOAuthCredentialsStore.claudeKeychainDataOverride + { + return (try? ClaudeOAuthCredentials.parse(data: data)) != nil + } + #endif + + var query: [String: Any] = [ + kSecClass as String: kSecClassGenericPassword, + kSecAttrService as String: ClaudeOAuthCredentialsStore.claudeKeychainService, + kSecMatchLimit as String: kSecMatchLimitOne, + kSecReturnAttributes as String: true, + ] + KeychainNoUIQuery.apply(to: &query) + + let (status, _, durationMs) = ClaudeOAuthKeychainQueryTiming.copyMatching(query) + if ClaudeOAuthKeychainQueryTiming + .backoffIfSlowNoUIQuery( + durationMs, + ClaudeOAuthCredentialsStore.claudeKeychainService, + ClaudeOAuthCredentialsStore.log) + { + return false + } + switch status { + case errSecSuccess, errSecInteractionNotAllowed: + return true + case errSecUserCanceled, errSecAuthFailed, errSecNoAccessForItem: + ClaudeOAuthKeychainAccessGate.recordDenied() + return false + default: + return false + } + #else + return false + #endif + } + } + } + + private struct Recovery { + let context: CollaboratorContext + + func shouldAttemptFreshnessSyncFromClaudeKeychain(cached: ClaudeOAuthCredentialRecord) -> Bool { + guard !cached.credentials.isExpired else { return false } + guard cached.owner == .claudeCLI else { return false } + guard ClaudeOAuthCredentialsStore.keychainAccessAllowed else { return false } + + let mode = ClaudeOAuthKeychainPromptPreference.storedMode() + switch mode { + case .never: + return false + case .onlyOnUserAction: + if ProviderInteractionContext.current != .userInitiated { + if ProcessInfo.processInfo.environment["CODEXBAR_DEBUG_CLAUDE_OAUTH_FLOW"] == "1" { + ClaudeOAuthCredentialsStore.log.debug( + "Claude OAuth keychain freshness sync skipped (background)", + metadata: ["promptMode": mode.rawValue, "owner": String(describing: cached.owner)]) + } + return false + } + return true + case .always: + return true + } + } + + func syncWithClaudeKeychainIfChanged( + cached: ClaudeOAuthCredentialRecord, + respectKeychainPromptCooldown: Bool, + now: Date = Date()) -> ClaudeOAuthCredentialRecord? + { + #if os(macOS) + let mode = ClaudeOAuthKeychainPromptPreference.current() + guard ClaudeOAuthCredentialsStore.shouldAllowClaudeCodeKeychainAccess(mode: mode) else { return nil } + if ClaudeOAuthCredentialsStore.isPromptPolicyApplicable, + respectKeychainPromptCooldown, + !ClaudeOAuthKeychainAccessGate.shouldAllowPrompt(now: now) + { + return nil + } + + if ClaudeOAuthCredentialsStore.shouldShowClaudeKeychainPreAlert() { + return nil + } + + if !ClaudeOAuthCredentialsStore.shouldCheckClaudeKeychainChange(now: now) { + return nil + } + + guard let currentFingerprint = ClaudeOAuthCredentialsStore.currentClaudeKeychainFingerprintWithoutPrompt() + else { + return nil + } + let storedFingerprint = ClaudeOAuthCredentialsStore.loadClaudeKeychainFingerprint() + guard currentFingerprint != storedFingerprint else { return nil } + + do { + guard let data = try ClaudeOAuthCredentialsStore.loadFromClaudeKeychainNonInteractive() else { + return nil + } + guard let keychainCreds = try? ClaudeOAuthCredentials.parse(data: data) else { + ClaudeOAuthCredentialsStore.saveClaudeKeychainFingerprint(currentFingerprint) + return nil + } + ClaudeOAuthCredentialsStore.saveClaudeKeychainFingerprint(currentFingerprint) + + guard keychainCreds.accessToken != cached.credentials.accessToken else { return nil } + if keychainCreds.isExpired, !cached.credentials.isExpired { + return nil + } + + ClaudeOAuthCredentialsStore.log.info("Claude keychain credentials changed; syncing OAuth cache") + let synced = ClaudeOAuthCredentialRecord( + credentials: keychainCreds, + owner: .claudeCLI, + source: .claudeKeychain) + ClaudeOAuthCredentialsStore.writeMemoryCache( + record: ClaudeOAuthCredentialRecord( + credentials: keychainCreds, + owner: .claudeCLI, + source: .memoryCache), + timestamp: now) + ClaudeOAuthCredentialsStore.saveToCacheKeychain(data, owner: .claudeCLI) + return synced + } catch let error as ClaudeOAuthCredentialsError { + if case let .keychainError(status) = error, + status == Int(errSecUserCanceled) + || status == Int(errSecAuthFailed) + || status == Int(errSecInteractionNotAllowed) + || status == Int(errSecNoAccessForItem) + { + ClaudeOAuthKeychainAccessGate.recordDenied(now: now) + } + return nil + } catch { + return nil + } + #else + _ = cached + _ = respectKeychainPromptCooldown + _ = now + return nil + #endif + } + + func repairFromClaudeKeychainWithoutPromptIfAllowed( + now: Date, + respectKeychainPromptCooldown: Bool, + allowCacheKeychainWrite: Bool = true) -> ClaudeOAuthCredentialRecord? + { + #if os(macOS) + let mode = ClaudeOAuthKeychainPromptPreference.current() + guard ClaudeOAuthCredentialsStore.shouldAllowClaudeCodeKeychainAccess(mode: mode) else { return nil } + + if ClaudeOAuthCredentialsStore.shouldShowClaudeKeychainPreAlert() { + return nil + } + + if ClaudeOAuthCredentialsStore.isPromptPolicyApplicable, + respectKeychainPromptCooldown, + ProviderInteractionContext.current != .userInitiated, + !ClaudeOAuthKeychainAccessGate.shouldAllowPrompt(now: now) + { + return nil + } + + do { + if ClaudeOAuthCredentialsStore.shouldPreferSecurityCLIKeychainRead(), + let securityData = ClaudeOAuthCredentialsStore.loadFromClaudeKeychainViaSecurityCLIIfEnabled( + interaction: ProviderInteractionContext.current), + !securityData.isEmpty + { + guard let creds = try? ClaudeOAuthCredentials.parse(data: securityData) else { return nil } + if creds.isExpired { + return ClaudeOAuthCredentialRecord( + credentials: creds, + owner: .claudeCLI, + source: .claudeKeychain) + } + + ClaudeOAuthCredentialsStore.writeMemoryCache( + record: ClaudeOAuthCredentialRecord( + credentials: creds, + owner: .claudeCLI, + source: .memoryCache), + timestamp: now) + if allowCacheKeychainWrite { + ClaudeOAuthCredentialsStore.saveToCacheKeychain(securityData, owner: .claudeCLI) + } + + ClaudeOAuthCredentialsStore.log.info( + "Claude keychain credentials loaded without prompt; syncing OAuth cache", + metadata: ["interaction": ProviderInteractionContext.current == .userInitiated + ? "user" : "background"]) + return ClaudeOAuthCredentialRecord( + credentials: creds, + owner: .claudeCLI, + source: .claudeKeychain) + } + + guard let data = try ClaudeOAuthCredentialsStore.loadFromClaudeKeychainNonInteractive(), + !data.isEmpty + else { + return nil + } + let fingerprint = ClaudeOAuthCredentialsStore.currentClaudeKeychainFingerprintWithoutPrompt() + guard let creds = try? ClaudeOAuthCredentials.parse(data: data) else { + ClaudeOAuthCredentialsStore.saveClaudeKeychainFingerprint(fingerprint) + return nil + } + + if creds.isExpired { + ClaudeOAuthCredentialsStore.saveClaudeKeychainFingerprint(fingerprint) + return ClaudeOAuthCredentialRecord( + credentials: creds, + owner: .claudeCLI, + source: .claudeKeychain) + } + + ClaudeOAuthCredentialsStore.saveClaudeKeychainFingerprint(fingerprint) + ClaudeOAuthCredentialsStore.writeMemoryCache( + record: ClaudeOAuthCredentialRecord( + credentials: creds, + owner: .claudeCLI, + source: .memoryCache), + timestamp: now) + if allowCacheKeychainWrite { + ClaudeOAuthCredentialsStore.saveToCacheKeychain(data, owner: .claudeCLI) + } + + ClaudeOAuthCredentialsStore.log.info( + "Claude keychain credentials loaded without prompt; syncing OAuth cache", + metadata: ["interaction": ProviderInteractionContext.current == .userInitiated + ? "user" : "background"]) + return ClaudeOAuthCredentialRecord( + credentials: creds, + owner: .claudeCLI, + source: .claudeKeychain) + } catch let error as ClaudeOAuthCredentialsError { + if case let .keychainError(status) = error, + status == Int(errSecUserCanceled) + || status == Int(errSecAuthFailed) + || status == Int(errSecInteractionNotAllowed) + || status == Int(errSecNoAccessForItem) + { + ClaudeOAuthKeychainAccessGate.recordDenied(now: now) + } + return nil + } catch { + return nil + } + #else + _ = now + _ = respectKeychainPromptCooldown + return nil + #endif + } + + @discardableResult + func syncFromClaudeKeychainWithoutPrompt(now: Date = Date()) -> Bool { + self.context.run { + #if os(macOS) + let mode = ClaudeOAuthKeychainPromptPreference.current() + guard ClaudeOAuthCredentialsStore.shouldAllowClaudeCodeKeychainAccess(mode: mode) else { return false } + + if let data = ClaudeOAuthCredentialsStore.loadFromClaudeKeychainViaSecurityCLIIfEnabled( + interaction: ProviderInteractionContext.current), + !data.isEmpty + { + if let creds = try? ClaudeOAuthCredentials.parse(data: data), !creds.isExpired { + ClaudeOAuthCredentialsStore.writeMemoryCache( + record: ClaudeOAuthCredentialRecord( + credentials: creds, + owner: .claudeCLI, + source: .memoryCache), + timestamp: now) + ClaudeOAuthCredentialsStore.saveToCacheKeychain(data, owner: .claudeCLI) + return true + } + } + + let fallbackPromptMode = ClaudeOAuthKeychainPromptPreference.securityFrameworkFallbackMode() + guard ClaudeOAuthCredentialsStore.shouldAllowClaudeCodeKeychainAccess(mode: fallbackPromptMode) else { + return false + } + + if ProviderInteractionContext.current == .background, + !ClaudeOAuthKeychainAccessGate.shouldAllowPrompt(now: now) + { + return false + } + + #if DEBUG + let override = ClaudeOAuthCredentialsStore.taskClaudeKeychainOverrideStore?.data + ?? ClaudeOAuthCredentialsStore.taskClaudeKeychainDataOverride + ?? ClaudeOAuthCredentialsStore.claudeKeychainDataOverride + if let override, + !override.isEmpty, + let creds = try? ClaudeOAuthCredentials.parse(data: override), + !creds.isExpired + { + ClaudeOAuthCredentialsStore.saveClaudeKeychainFingerprint( + ClaudeOAuthCredentialsStore.currentClaudeKeychainFingerprintWithoutPrompt()) + ClaudeOAuthCredentialsStore.writeMemoryCache( + record: ClaudeOAuthCredentialRecord( + credentials: creds, + owner: .claudeCLI, + source: .memoryCache), + timestamp: now) + ClaudeOAuthCredentialsStore.saveToCacheKeychain(override, owner: .claudeCLI) + return true + } + #endif + + if ClaudeOAuthCredentialsStore.shouldShowClaudeKeychainPreAlert() { + return false + } + + if let candidate = ClaudeOAuthCredentialsStore.claudeKeychainCandidatesWithoutPrompt( + promptMode: fallbackPromptMode).first, + let data = try? ClaudeOAuthCredentialsStore.loadClaudeKeychainData( + candidate: candidate, + allowKeychainPrompt: false), + !data.isEmpty + { + let fingerprint = ClaudeKeychainFingerprint( + modifiedAt: candidate.modifiedAt.map { Int($0.timeIntervalSince1970) }, + createdAt: candidate.createdAt.map { Int($0.timeIntervalSince1970) }, + persistentRefHash: ClaudeOAuthCredentialsStore.sha256Prefix(candidate.persistentRef)) + + if let creds = try? ClaudeOAuthCredentials.parse(data: data), !creds.isExpired { + ClaudeOAuthCredentialsStore.saveClaudeKeychainFingerprint(fingerprint) + ClaudeOAuthCredentialsStore.writeMemoryCache( + record: ClaudeOAuthCredentialRecord( + credentials: creds, + owner: .claudeCLI, + source: .memoryCache), + timestamp: now) + ClaudeOAuthCredentialsStore.saveToCacheKeychain(data, owner: .claudeCLI) + return true + } + + ClaudeOAuthCredentialsStore.saveClaudeKeychainFingerprint(fingerprint) + } + + let legacyData = try? ClaudeOAuthCredentialsStore.loadClaudeKeychainLegacyData( + allowKeychainPrompt: false, + promptMode: fallbackPromptMode) + if let legacyData, + !legacyData.isEmpty, + let creds = try? ClaudeOAuthCredentials.parse(data: legacyData), + !creds.isExpired + { + ClaudeOAuthCredentialsStore.saveClaudeKeychainFingerprint( + ClaudeOAuthCredentialsStore.currentClaudeKeychainFingerprintWithoutPrompt()) + ClaudeOAuthCredentialsStore.writeMemoryCache( + record: ClaudeOAuthCredentialRecord( + credentials: creds, + owner: .claudeCLI, + source: .memoryCache), + timestamp: now) + ClaudeOAuthCredentialsStore.saveToCacheKeychain(legacyData, owner: .claudeCLI) + return true + } + + return false + #else + _ = now + return false + #endif + } + } + } + + private struct Refresher { + let context: CollaboratorContext + + func refreshAccessToken( + refreshToken: String, + existingScopes: [String], + existingRateLimitTier: String?, + existingSubscriptionType: String? = nil, + historyOwnerIdentifier: String?) async throws -> ClaudeOAuthCredentials + { + try await self.context.run { + let newCredentials = try await self.refreshAccessTokenCore( + refreshToken: refreshToken, + existingScopes: existingScopes, + existingRateLimitTier: existingRateLimitTier, + existingSubscriptionType: existingSubscriptionType) + + ClaudeOAuthCredentialsStore.saveRefreshedCredentialsToCache( + newCredentials, + historyOwnerIdentifier: historyOwnerIdentifier) + ClaudeOAuthCredentialsStore.writeMemoryCache( + record: ClaudeOAuthCredentialRecord( + credentials: newCredentials, + owner: .codexbar, + source: .memoryCache, + historyOwnerIdentifier: historyOwnerIdentifier), + timestamp: Date()) + ClaudeOAuthRefreshFailureGate.recordSuccess() + + return newCredentials + } + } + + private func refreshAccessTokenCore( + refreshToken: String, + existingScopes: [String], + existingRateLimitTier: String?, + existingSubscriptionType: String?) async throws -> ClaudeOAuthCredentials + { + guard ClaudeOAuthRefreshFailureGate.shouldAttempt() else { + let status = ClaudeOAuthRefreshFailureGate.currentBlockStatus() + let message = switch status { + case .terminal: + "Claude OAuth refresh blocked until auth changes. \(ClaudeOAuthCredentialsStore.reauthenticateHint)" + case .transient: + "Claude OAuth refresh temporarily backed off due to prior failures; will retry automatically." + case nil: + "Claude OAuth refresh temporarily suppressed due to prior failures; will retry automatically." + } + throw ClaudeOAuthCredentialsError.refreshFailed(message) + } + + guard let url = URL(string: ClaudeOAuthCredentialsStore.tokenRefreshEndpoint) else { + throw ClaudeOAuthCredentialsError.refreshFailed("Invalid token endpoint URL") + } + + var request = URLRequest(url: url) + request.httpMethod = "POST" + request.timeoutInterval = 30 + request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") + request.setValue("application/json", forHTTPHeaderField: "Accept") + + var components = URLComponents() + components.queryItems = [ + URLQueryItem(name: "grant_type", value: "refresh_token"), + URLQueryItem(name: "refresh_token", value: refreshToken), + URLQueryItem(name: "client_id", value: ClaudeOAuthCredentialsStore.oauthClientID), + ] + request.httpBody = (components.percentEncodedQuery ?? "").data(using: .utf8) + + let response = try await ProviderHTTPClient.shared.response(for: request) + let data = response.data + guard response.statusCode == 200 else { + if let disposition = ClaudeOAuthCredentialsStore.refreshFailureDisposition( + statusCode: response.statusCode, + data: data) + { + let oauthError = ClaudeOAuthCredentialsStore.extractOAuthErrorCode(from: data) + ClaudeOAuthCredentialsStore.log.info( + "Claude OAuth refresh rejected", + metadata: [ + "httpStatus": "\(response.statusCode)", + "oauthError": oauthError ?? "nil", + "disposition": disposition.rawValue, + ]) + + switch disposition { + case .terminalInvalidGrant: + ClaudeOAuthRefreshFailureGate.recordTerminalAuthFailure() + Repository(context: self.context).invalidateCache() + let message = "HTTP \(response.statusCode) invalid_grant. " + + ClaudeOAuthCredentialsStore.reauthenticateHint + throw ClaudeOAuthCredentialsError.refreshFailed( + message) + case .transientBackoff: + ClaudeOAuthRefreshFailureGate.recordTransientFailure() + let suffix = oauthError.map { " (\($0))" } ?? "" + throw ClaudeOAuthCredentialsError.refreshFailed("HTTP \(response.statusCode)\(suffix)") + } + } + throw ClaudeOAuthCredentialsError.refreshFailed("HTTP \(response.statusCode)") + } + + let tokenResponse = try JSONDecoder().decode(TokenRefreshResponse.self, from: data) + let expiresAt = Date(timeIntervalSinceNow: TimeInterval(tokenResponse.expiresIn)) + + return ClaudeOAuthCredentials( + accessToken: tokenResponse.accessToken, + refreshToken: tokenResponse.refreshToken ?? refreshToken, + expiresAt: expiresAt, + scopes: existingScopes, + rateLimitTier: existingRateLimitTier, + subscriptionType: existingSubscriptionType) + } + } + + public static func load( + environment: [String: String] = ProcessInfo.processInfo.environment, + allowKeychainPrompt: Bool = true, + respectKeychainPromptCooldown: Bool = false) throws -> ClaudeOAuthCredentials + { + let context = self.currentCollaboratorContext() + return try Repository(context: context).load( + environment: environment, + allowKeychainPrompt: allowKeychainPrompt, + respectKeychainPromptCooldown: respectKeychainPromptCooldown) + } + + public static func loadRecord( + environment: [String: String] = ProcessInfo.processInfo.environment, + allowKeychainPrompt: Bool = true, + respectKeychainPromptCooldown: Bool = false, + allowClaudeKeychainRepairWithoutPrompt: Bool = true) throws -> ClaudeOAuthCredentialRecord + { + let context = self.currentCollaboratorContext() + return try Repository(context: context).loadRecord( + environment: environment, + allowKeychainPrompt: allowKeychainPrompt, + respectKeychainPromptCooldown: respectKeychainPromptCooldown, + allowClaudeKeychainRepairWithoutPrompt: allowClaudeKeychainRepairWithoutPrompt) + } + + /// Async version of load that handles expired tokens based on credential ownership. + /// - Claude CLI-owned credentials delegate refresh to Claude CLI. + /// - CodexBar-owned credentials refresh directly via token endpoint. + public static func loadWithAutoRefresh( + environment: [String: String] = ProcessInfo.processInfo.environment, + allowKeychainPrompt: Bool = true, + respectKeychainPromptCooldown: Bool = false) async throws -> ClaudeOAuthCredentials + { + try await self.loadRecordWithAutoRefresh( + environment: environment, + allowKeychainPrompt: allowKeychainPrompt, + respectKeychainPromptCooldown: respectKeychainPromptCooldown).credentials + } + + /// Record-preserving variant used when callers must distinguish the credential that actually won routing. + public static func loadRecordWithAutoRefresh( + environment: [String: String] = ProcessInfo.processInfo.environment, + allowKeychainPrompt: Bool = true, + respectKeychainPromptCooldown: Bool = false) async throws -> ClaudeOAuthCredentialRecord + { + let context = self.currentCollaboratorContext() + let repository = Repository(context: context) + let refresher = Refresher(context: context) + let record = try repository.loadRecord( + environment: environment, + allowKeychainPrompt: allowKeychainPrompt, + respectKeychainPromptCooldown: respectKeychainPromptCooldown, + allowClaudeKeychainRepairWithoutPrompt: true) + let credentials = record.credentials + let now = Date() + var expiryMetadata = credentials.diagnosticsMetadata(now: now) + expiryMetadata["source"] = record.source.rawValue + expiryMetadata["owner"] = record.owner.rawValue + expiryMetadata["allowKeychainPrompt"] = "\(allowKeychainPrompt)" + expiryMetadata["respectPromptCooldown"] = "\(respectKeychainPromptCooldown)" + expiryMetadata["readStrategy"] = ClaudeOAuthKeychainReadStrategyPreference.current().rawValue + + let isExpired: Bool = if let expiresAt = credentials.expiresAt { + now >= expiresAt + } else { + true + } + + // If not expired, return as-is + guard isExpired else { + self.log.debug("Claude OAuth credentials loaded for usage", metadata: expiryMetadata) + return record + } + + self.log.info("Claude OAuth credentials considered expired", metadata: expiryMetadata) + + switch record.owner { + case .claudeCLI: + if ProviderInteractionContext.current != .userInitiated, + ClaudeOAuthCredentialsStore.isMcpOAuthOnlyClaudeKeychainPayloadPresent( + interaction: ProviderInteractionContext.current, + environment: environment) + { + self.log.warning( + "Claude OAuth credentials expired; Claude keychain has MCP OAuth state only", + metadata: expiryMetadata) + throw ClaudeOAuthCredentialsError.mcpOAuthOnlyKeychain + } + self.log.info( + "Claude OAuth credentials expired; delegating refresh to Claude CLI", + metadata: expiryMetadata) + throw ClaudeOAuthCredentialsError.refreshDelegatedToClaudeCLI + case .environment: + self.log.warning("Environment OAuth token expired and cannot be auto-refreshed") + throw ClaudeOAuthCredentialsError.noRefreshToken + case .codexbar: + break + } + + // Try to refresh if we have a refresh token. + guard let refreshToken = credentials.refreshToken, !refreshToken.isEmpty else { + self.log.warning("Token expired but no refresh token available") + throw ClaudeOAuthCredentialsError.noRefreshToken + } + self.log.info("Access token expired, attempting auto-refresh") + + do { + let refreshed = try await refresher.refreshAccessToken( + refreshToken: refreshToken, + existingScopes: credentials.scopes, + existingRateLimitTier: credentials.rateLimitTier, + existingSubscriptionType: credentials.subscriptionType, + historyOwnerIdentifier: record.historyOwnerIdentifier) + self.log.info("Token refresh successful, expires in \(refreshed.expiresIn ?? 0) seconds") + return ClaudeOAuthCredentialRecord( + credentials: refreshed, + owner: .codexbar, + source: .memoryCache, + historyOwnerIdentifier: record.historyOwnerIdentifier) + } catch { + self.log.error("Token refresh failed: \(error.localizedDescription)") + throw error + } + } + + /// Save refreshed credentials to CodexBar's keychain cache + private static func saveRefreshedCredentialsToCache( + _ credentials: ClaudeOAuthCredentials, + historyOwnerIdentifier: String?) + { + var oauth: [String: Any] = [ + "accessToken": credentials.accessToken, + "expiresAt": (credentials.expiresAt?.timeIntervalSince1970 ?? 0) * 1000, + "scopes": credentials.scopes, + ] + + if let refreshToken = credentials.refreshToken { + oauth["refreshToken"] = refreshToken + } + if let rateLimitTier = credentials.rateLimitTier { + oauth["rateLimitTier"] = rateLimitTier + } + if let subscriptionType = credentials.subscriptionType { + oauth["subscriptionType"] = subscriptionType + } + + let oauthData: [String: Any] = ["claudeAiOauth": oauth] + + guard let jsonData = try? JSONSerialization.data(withJSONObject: oauthData) else { + self.log.error("Failed to serialize refreshed credentials for cache") + return + } + + self.saveToCacheKeychain( + jsonData, + owner: .codexbar, + historyOwnerIdentifier: historyOwnerIdentifier) + self.log.debug("Saved refreshed credentials to CodexBar keychain cache") + } + + /// Response from the OAuth token refresh endpoint + private struct TokenRefreshResponse: Decodable { + let accessToken: String + let refreshToken: String? + let expiresIn: Int + let tokenType: String? + + enum CodingKeys: String, CodingKey { + case accessToken = "access_token" + case refreshToken = "refresh_token" + case expiresIn = "expires_in" + case tokenType = "token_type" + } + } + + public static func loadFromFile() throws -> Data { + let url = self.credentialsFileURL() + do { + return try Data(contentsOf: url) + } catch { + if (error as NSError).code == NSFileReadNoSuchFileError { + throw ClaudeOAuthCredentialsError.notFound + } + throw ClaudeOAuthCredentialsError.readFailed(error.localizedDescription) + } + } + + public static func credentialsFileFingerprintToken() -> String? { + guard let fingerprint = self.currentFileFingerprint() else { return nil } + let modifiedAt = fingerprint.modifiedAtMs.map(String.init) ?? "nil" + return "\(modifiedAt):\(fingerprint.size)" + } + + public static func authFingerprintToken() -> String { + let file = self.credentialsFileFingerprintToken() ?? "nil" + let keychain = self.claudeKeychainFingerprintToken() ?? "nil" + return "file=\(file)|keychain=\(keychain)" + } + + public static func consumeClaudeKeychainFingerprintChangeWithoutPrompt() -> Bool { + let current: ClaudeKeychainFingerprint? + switch self.probeClaudeKeychainFingerprintWithoutPrompt() { + case .unavailable: + return false + case let .value(fingerprint): + current = fingerprint + } + let stored = self.loadClaudeKeychainFingerprint() + guard current != stored else { return false } + self.saveClaudeKeychainFingerprint(current) + return true + } + + public static func claudeKeychainFingerprintChangedWithoutConsuming() -> Bool { + let current: ClaudeKeychainFingerprint? + switch self.probeClaudeKeychainFingerprintWithoutPrompt() { + case .unavailable: + return false + case let .value(fingerprint): + current = fingerprint + } + return current != self.loadClaudeKeychainFingerprint() + } + + public static func claudeKeychainFingerprintToken() -> String? { + let fingerprint: ClaudeKeychainFingerprint? = switch self.probeClaudeKeychainFingerprintWithoutPrompt() { + case .unavailable: + self.loadClaudeKeychainFingerprint() + case let .value(probed): + probed + } + guard let fingerprint else { return nil } + let modifiedAt = fingerprint.modifiedAt.map(String.init) ?? "nil" + let createdAt = fingerprint.createdAt.map(String.init) ?? "nil" + let persistentRefHash = fingerprint.persistentRefHash ?? "nil" + return "\(modifiedAt):\(createdAt):\(persistentRefHash)" + } + + /// Returns the current Claude Code Keychain item's opaque persistent-reference hash without + /// falling back to a stored fingerprint. History ownership must prefer no identity over a + /// potentially stale identity when a non-interactive Keychain probe is unavailable. + public static func claudeKeychainPersistentRefHashWithoutPrompt() -> String? { + switch self.probeClaudeKeychainFingerprintWithoutPrompt() { + case .unavailable: + nil + case let .value(fingerprint): + fingerprint?.persistentRefHash + } + } + + /// Returns the current Keychain item's persistent-reference hash only when it owns the credential + /// that actually won OAuth routing. Token material is compared in memory and is never hashed or persisted. + public static func matchingClaudeKeychainPersistentRefHashWithoutPrompt( + for record: ClaudeOAuthCredentialRecord) -> String? + { + self.claudeKeychainCredentialMatchWithoutPrompt(for: record).persistentRefHash + } + + static func claudeKeychainCredentialMatchWithoutPrompt( + for record: ClaudeOAuthCredentialRecord) -> ClaudeKeychainCredentialMatch + { + guard record.owner == .claudeCLI else { return .notApplicable } + let evidence: ClaudeKeychainCredentialEvidence + switch self.newestClaudeKeychainCredentialEvidenceWithoutPrompt() { + case .unavailable: + return .unavailable + case .value(nil): + return .absent + case let .value(value?): + evidence = value + } + guard evidence.credentials.accessToken == record.credentials.accessToken else { + return .mismatch + } + return .matched(persistentRefHash: evidence.persistentRefHash) + } + + private static func matchingClaudeKeychainPersistentRefHash( + for record: ClaudeOAuthCredentialRecord, + evidence: ClaudeKeychainCredentialEvidence?) -> String? + { + guard let evidence, + evidence.credentials.accessToken == record.credentials.accessToken + else { + return nil + } + return evidence.persistentRefHash + } + + private static func newestClaudeKeychainCredentialEvidenceWithoutPrompt() + -> ClaudeKeychainProbe + { + #if DEBUG + if let store = self.taskClaudeKeychainOverrideStore { + guard store.data != nil || store.fingerprint != nil else { return .value(nil) } + return self.makeClaudeKeychainCredentialEvidence( + data: store.data, + persistentRefHash: store.fingerprint?.persistentRefHash).map { .value($0) } ?? .unavailable + } + let overrideData = self.taskClaudeKeychainDataOverride ?? self.claudeKeychainDataOverride + let overrideFingerprint = self.taskClaudeKeychainFingerprintOverride ?? self.claudeKeychainFingerprintOverride + if overrideData != nil || overrideFingerprint != nil { + return self.makeClaudeKeychainCredentialEvidence( + data: overrideData, + persistentRefHash: overrideFingerprint?.persistentRefHash).map { .value($0) } ?? .unavailable + } + if self.taskSecurityCLIReadOverride != nil || self.securityCLIReadOverride != nil { + // A security(1) result cannot be bound to a persistent reference without an exact candidate read. + return .unavailable + } + #endif + + #if os(macOS) + let promptMode = ClaudeOAuthKeychainPromptPreference.current() + let newest: ClaudeKeychainCandidate? + switch self.claudeKeychainCandidatesProbeWithoutPrompt(promptMode: promptMode) { + case .unavailable: + return .unavailable + case let .value(candidates): + if let first = candidates.first { + newest = first + } else { + switch self.claudeKeychainLegacyCandidateProbeWithoutPrompt(promptMode: promptMode) { + case .unavailable: + return .unavailable + case let .value(candidate): + newest = candidate + } + } + } + guard let newest else { return .value(nil) } + guard let persistentRefHash = self.sha256Prefix(newest.persistentRef), + let data = try? self.loadClaudeKeychainData( + candidate: newest, + allowKeychainPrompt: false, + promptMode: promptMode) + else { + return .unavailable + } + guard let evidence = self.makeClaudeKeychainCredentialEvidence( + data: data, + persistentRefHash: persistentRefHash) + else { return .unavailable } + return .value(evidence) + #else + return .unavailable + #endif + } + + private static func makeClaudeKeychainCredentialEvidence( + data: Data?, + persistentRefHash: String?) -> ClaudeKeychainCredentialEvidence? + { + guard let data, + let persistentRefHash, + let credentials = try? ClaudeOAuthCredentials.parse(data: data) + else { + return nil + } + return ClaudeKeychainCredentialEvidence( + credentials: credentials, + persistentRefHash: persistentRefHash) + } + + #if DEBUG + static func _matchingClaudeKeychainPersistentRefHashForTesting( + record: ClaudeOAuthCredentialRecord, + candidateCredentials: ClaudeOAuthCredentials, + persistentRefHash: String) -> String? + { + self.matchingClaudeKeychainPersistentRefHash( + for: record, + evidence: ClaudeKeychainCredentialEvidence( + credentials: candidateCredentials, + persistentRefHash: persistentRefHash)) + } + #endif + + private enum ClaudeKeychainProbe { + case unavailable + case value(Value) + } + + @discardableResult + public static func invalidateCacheIfCredentialsFileChanged() -> Bool { + Repository(context: self.currentCollaboratorContext()).invalidateCacheIfCredentialsFileChanged() + } + + /// Invalidate the credentials cache (call after login/logout) + public static func invalidateCache() { + Repository(context: self.currentCollaboratorContext()).invalidateCache() + } + + /// Check if CodexBar has cached credentials (in memory or keychain cache) + public static func hasCachedCredentials(environment: [String: String] = ProcessInfo.processInfo + .environment) -> Bool + { + Repository(context: self.currentCollaboratorContext()).hasCachedCredentials(environment: environment) + } + + public static func hasClaudeKeychainCredentialsWithoutPrompt() -> Bool { + Repository(context: self.currentCollaboratorContext()).hasClaudeKeychainCredentialsWithoutPrompt() + } + + private static func hasClaudeKeychainItemWithoutPrompt() -> Bool { + #if DEBUG + if let store = self.taskClaudeKeychainOverrideStore { + if let data = store.data, !data.isEmpty { + return true + } + if store.fingerprint != nil { + return true + } + } + if let data = self.taskClaudeKeychainDataOverride ?? self.claudeKeychainDataOverride, + !data.isEmpty + { + return true + } + if self.taskClaudeKeychainFingerprintOverride ?? self.claudeKeychainFingerprintOverride != nil { + return true + } + #endif + + #if os(macOS) + switch self.claudeKeychainCandidatesProbeWithoutPrompt(enforcePromptPolicy: false) { + case let .value(candidates) where !candidates.isEmpty: + return true + case .value, .unavailable: + break + } + switch self.claudeKeychainLegacyCandidateProbeWithoutPrompt(enforcePromptPolicy: false) { + case let .value(candidate): + return candidate != nil + case .unavailable: + return false + } + #else + return false + #endif + } + + private static func shouldCheckClaudeKeychainChange(now: Date = Date()) -> Bool { + #if DEBUG + // Unit tests can supply TaskLocal overrides for the Claude keychain data/fingerprint. Those tests often run + // concurrently with other suites, so the global throttle becomes nondeterministic. When an override is + // present, bypass the throttle so test expectations don't depend on unrelated activity. + if self.taskClaudeKeychainOverrideStore != nil || self.taskClaudeKeychainFingerprintOverride != nil + || self.claudeKeychainFingerprintOverride != nil + { + return true + } + #endif + + self.claudeKeychainChangeCheckLock.lock() + defer { self.claudeKeychainChangeCheckLock.unlock() } + if let last = self.lastClaudeKeychainChangeCheckAt, + now.timeIntervalSince(last) < self.claudeKeychainChangeCheckMinimumInterval + { + return false + } + self.lastClaudeKeychainChangeCheckAt = now + return true + } + + private static func loadClaudeKeychainFingerprint() -> ClaudeKeychainFingerprint? { + #if DEBUG + if let store = taskClaudeKeychainFingerprintStoreOverride { + return store.fingerprint + } + #endif + // Proactively remove the legacy V1 key (it included the keychain account string, which can be identifying). + UserDefaults.standard.removeObject(forKey: self.claudeKeychainFingerprintLegacyKey) + + guard let data = UserDefaults.standard.data(forKey: self.claudeKeychainFingerprintKey) else { + return nil + } + return try? JSONDecoder().decode(ClaudeKeychainFingerprint.self, from: data) + } + + private static func saveClaudeKeychainFingerprint(_ fingerprint: ClaudeKeychainFingerprint?) { + #if DEBUG + if let store = taskClaudeKeychainFingerprintStoreOverride { + store.fingerprint = fingerprint + return + } + #endif + // Proactively remove the legacy V1 key (it included the keychain account string, which can be identifying). + UserDefaults.standard.removeObject(forKey: self.claudeKeychainFingerprintLegacyKey) + + guard let fingerprint else { + UserDefaults.standard.removeObject(forKey: self.claudeKeychainFingerprintKey) + return + } + if let data = try? JSONEncoder().encode(fingerprint) { + UserDefaults.standard.set(data, forKey: self.claudeKeychainFingerprintKey) + } + } + + private static func currentClaudeKeychainFingerprintWithoutPrompt() -> ClaudeKeychainFingerprint? { + switch self.probeClaudeKeychainFingerprintWithoutPrompt() { + case .unavailable: + nil + case let .value(fingerprint): + fingerprint + } + } + + private static func probeClaudeKeychainFingerprintWithoutPrompt() + -> ClaudeKeychainProbe { + let mode = ClaudeOAuthKeychainPromptPreference.current() + #if DEBUG + if let store = taskClaudeKeychainOverrideStore { + return .value(store.fingerprint) + } + if let override = taskClaudeKeychainFingerprintOverride ?? self + .claudeKeychainFingerprintOverride + { + return .value(override) + } + #endif + guard self.shouldAllowClaudeCodeKeychainAccess(mode: mode) else { return .unavailable } + if self.isPromptPolicyApplicable, + ProviderInteractionContext.current == .background, + !ClaudeOAuthKeychainAccessGate.shouldAllowPrompt() + { + return .unavailable + } + #if os(macOS) + let candidatesProbe = self.claudeKeychainCandidatesProbeWithoutPrompt(promptMode: mode) + let newest: ClaudeKeychainCandidate? + switch candidatesProbe { + case .unavailable: + return .unavailable + case let .value(candidates): + if let first = candidates.first { + newest = first + } else { + switch self.claudeKeychainLegacyCandidateProbeWithoutPrompt(promptMode: mode) { + case .unavailable: + return .unavailable + case let .value(candidate): + newest = candidate + } + } + } + guard let newest else { return .value(nil) } + + let modifiedAt = newest.modifiedAt.map { Int($0.timeIntervalSince1970) } + let createdAt = newest.createdAt.map { Int($0.timeIntervalSince1970) } + let persistentRefHash = Self.sha256Prefix(newest.persistentRef) + return .value(ClaudeKeychainFingerprint( + modifiedAt: modifiedAt, + createdAt: createdAt, + persistentRefHash: persistentRefHash)) + #else + return .unavailable + #endif + } + + static func currentClaudeKeychainFingerprintWithoutPromptForAuthGate() -> ClaudeKeychainFingerprint? { + self.currentClaudeKeychainFingerprintWithoutPrompt() + } + + static func currentCredentialsFileFingerprintWithoutPromptForAuthGate() -> String? { + guard let fingerprint = self.currentFileFingerprint() else { return nil } + let modifiedAt = fingerprint.modifiedAtMs ?? 0 + return "\(modifiedAt):\(fingerprint.size)" + } + + private static func loadFromClaudeKeychainNonInteractive( + readStrategy: ClaudeOAuthKeychainReadStrategy = ClaudeOAuthKeychainReadStrategyPreference.current()) + throws -> Data? + { + #if os(macOS) + let fallbackPromptMode = ClaudeOAuthKeychainPromptPreference.securityFrameworkFallbackMode( + readStrategy: readStrategy) + if let data = self.loadFromClaudeKeychainViaSecurityCLIIfEnabled( + interaction: ProviderInteractionContext.current, + readStrategy: readStrategy) + { + return data + } + + // For experimental strategy, enforce stored prompt policy before any Security.framework fallback probes. + guard self.shouldAllowClaudeCodeKeychainAccess(mode: fallbackPromptMode) else { return nil } + + #if DEBUG + if let store = taskClaudeKeychainOverrideStore { + return store.data + } + if let override = taskClaudeKeychainDataOverride ?? self.claudeKeychainDataOverride { + return override + } + #endif + + // Keep semantics aligned with fingerprinting: if there are multiple entries, we only ever consult the newest + // candidate (same as currentClaudeKeychainFingerprintWithoutPrompt()) to avoid syncing from a different item. + let candidates = self.claudeKeychainCandidatesWithoutPrompt(promptMode: fallbackPromptMode) + if let newest = candidates.first { + if let data = try self.loadClaudeKeychainData(candidate: newest, allowKeychainPrompt: false), + !data.isEmpty + { + return data + } + return nil + } + + let legacyData = try self.loadClaudeKeychainLegacyData( + allowKeychainPrompt: false, + promptMode: fallbackPromptMode) + if let legacyData, !legacyData.isEmpty { + return legacyData + } + return nil + #else + return nil + #endif + } + + static func readRawClaudeKeychainPayloadViaSecurityFrameworkWithoutPrompt() -> Data? { + #if os(macOS) + guard self.keychainAccessAllowed else { return nil } + #if DEBUG + if let store = self.taskClaudeKeychainOverrideStore { + return store.data + } + if let override = self.taskClaudeKeychainDataOverride ?? self.claudeKeychainDataOverride { + return override + } + #endif + + // This probe must work under the default `onlyOnUserAction` policy, but must never show Keychain UI. + // The candidate and data queries both use KeychainNoUIQuery; `.always` only bypasses the prompt-policy gate. + switch self.claudeKeychainCandidatesProbeWithoutPrompt( + promptMode: .always, + enforcePromptPolicy: false) + { + case .unavailable: + return nil + case let .value(candidates): + if let newest = candidates.first { + return try? self.loadClaudeKeychainData( + candidate: newest, + allowKeychainPrompt: false, + promptMode: .always) + } + } + return try? self.loadClaudeKeychainLegacyData( + allowKeychainPrompt: false, + promptMode: .always) + #else + return nil + #endif + } + + public static func loadFromClaudeKeychain() throws -> Data { + guard self.shouldAllowClaudeCodeKeychainAccess(mode: ClaudeOAuthKeychainPromptPreference.current()) else { + throw ClaudeOAuthCredentialsError.notFound + } + #if DEBUG + if let store = taskClaudeKeychainOverrideStore, let override = store.data { + return override + } + if let override = taskClaudeKeychainDataOverride ?? self.claudeKeychainDataOverride { + return override + } + #endif + if let data = self.loadFromClaudeKeychainViaSecurityCLIIfEnabled( + interaction: ProviderInteractionContext.current) + { + return data + } + if self.shouldPreferSecurityCLIKeychainRead() { + let fallbackPromptMode = ClaudeOAuthKeychainPromptPreference.securityFrameworkFallbackMode() + let fallbackDecision = self.securityFrameworkFallbackPromptDecision( + promptMode: fallbackPromptMode, + allowKeychainPrompt: true, + respectKeychainPromptCooldown: false) + self.log.debug( + "Claude keychain Security.framework fallback prompt policy evaluated", + metadata: [ + "reader": "securityFrameworkFallback", + "fallbackPromptMode": fallbackPromptMode.rawValue, + "fallbackPromptAllowed": "\(fallbackDecision.allowed)", + "fallbackBlockedReason": fallbackDecision.blockedReason ?? "none", + ]) + guard fallbackDecision.allowed else { + throw ClaudeOAuthCredentialsError.notFound + } + return try self.loadFromClaudeKeychainUsingSecurityFramework( + promptMode: fallbackPromptMode, + allowKeychainPrompt: true) + } + return try self.loadFromClaudeKeychainUsingSecurityFramework() + } + + /// Legacy alias for backward compatibility + public static func loadFromKeychain() throws -> Data { + try self.loadFromClaudeKeychain() + } + + private static func loadFromClaudeKeychainUsingSecurityFramework( + promptMode: ClaudeOAuthKeychainPromptMode = ClaudeOAuthKeychainPromptPreference.current(), + allowKeychainPrompt: Bool = true) throws -> Data + { + #if DEBUG + if let store = taskClaudeKeychainOverrideStore, let override = store.data { + return override + } + if let override = taskClaudeKeychainDataOverride ?? self.claudeKeychainDataOverride { + return override + } + #endif + #if os(macOS) + let candidates = self.claudeKeychainCandidatesWithoutPrompt(promptMode: promptMode) + if let newest = candidates.first { + do { + if let data = try self.loadClaudeKeychainData( + candidate: newest, + allowKeychainPrompt: allowKeychainPrompt, + promptMode: promptMode), + !data.isEmpty + { + // Store fingerprint after a successful interactive read so we don't immediately try to + // "sync" in the background (which can still show UI on some systems). + let modifiedAt = newest.modifiedAt.map { Int($0.timeIntervalSince1970) } + let createdAt = newest.createdAt.map { Int($0.timeIntervalSince1970) } + let persistentRefHash = Self.sha256Prefix(newest.persistentRef) + self.saveClaudeKeychainFingerprint( + ClaudeKeychainFingerprint( + modifiedAt: modifiedAt, + createdAt: createdAt, + persistentRefHash: persistentRefHash)) + return data + } + } catch let error as ClaudeOAuthCredentialsError { + if case .keychainError = error { + ClaudeOAuthKeychainAccessGate.recordDenied() + } + throw error + } + } + + // Fallback: legacy query (may pick an arbitrary duplicate). + do { + if let data = try self.loadClaudeKeychainLegacyData( + allowKeychainPrompt: allowKeychainPrompt, + promptMode: promptMode), + !data.isEmpty + { + // Same as above: store fingerprint after interactive read to avoid background "sync" reads. + self.saveClaudeKeychainFingerprint(self.currentClaudeKeychainFingerprintWithoutPrompt()) + return data + } + } catch let error as ClaudeOAuthCredentialsError { + if case .keychainError = error { + ClaudeOAuthKeychainAccessGate.recordDenied() + } + throw error + } + throw ClaudeOAuthCredentialsError.notFound + #else + throw ClaudeOAuthCredentialsError.notFound + #endif + } + + #if os(macOS) + private struct ClaudeKeychainCandidate { + let persistentRef: Data + let account: String? + let modifiedAt: Date? + let createdAt: Date? + } + + private static func claudeKeychainCandidatesProbeWithoutPrompt( + promptMode: ClaudeOAuthKeychainPromptMode = ClaudeOAuthKeychainPromptPreference + .current(), + enforcePromptPolicy: Bool = true) -> ClaudeKeychainProbe<[ClaudeKeychainCandidate]> + { + if enforcePromptPolicy { + guard self.shouldAllowClaudeCodeKeychainAccess(mode: promptMode) else { return .unavailable } + if self.isPromptPolicyApplicable, + ProviderInteractionContext.current == .background, + !ClaudeOAuthKeychainAccessGate.shouldAllowPrompt() + { + return .unavailable + } + } else { + guard self.keychainAccessAllowed else { return .unavailable } + } + var query: [String: Any] = [ + kSecClass as String: kSecClassGenericPassword, + kSecAttrService as String: self.claudeKeychainService, + kSecMatchLimit as String: kSecMatchLimitAll, + kSecReturnAttributes as String: true, + kSecReturnPersistentRef as String: true, + ] + KeychainNoUIQuery.apply(to: &query) + + let (status, result, durationMs) = ClaudeOAuthKeychainQueryTiming.copyMatching(query) + if ClaudeOAuthKeychainQueryTiming + .backoffIfSlowNoUIQuery(durationMs, self.claudeKeychainService, self.log) + { + return .unavailable + } + if status == errSecUserCanceled || status == errSecAuthFailed || status == errSecNoAccessForItem { + ClaudeOAuthKeychainAccessGate.recordDenied() + } + if status == errSecItemNotFound { + return .value([]) + } + guard status == errSecSuccess else { return .unavailable } + guard let rows = result as? [[String: Any]], !rows.isEmpty else { return .value([]) } + + let candidates: [ClaudeKeychainCandidate] = rows.compactMap { row in + guard let persistentRef = row[kSecValuePersistentRef as String] as? Data else { return nil } + return ClaudeKeychainCandidate( + persistentRef: persistentRef, + account: row[kSecAttrAccount as String] as? String, + modifiedAt: row[kSecAttrModificationDate as String] as? Date, + createdAt: row[kSecAttrCreationDate as String] as? Date) + } + + let sorted = candidates.sorted { lhs, rhs in + let lhsDate = lhs.modifiedAt ?? lhs.createdAt ?? Date.distantPast + let rhsDate = rhs.modifiedAt ?? rhs.createdAt ?? Date.distantPast + return lhsDate > rhsDate + } + return .value(sorted) + } + + private static func claudeKeychainCandidatesWithoutPrompt( + promptMode: ClaudeOAuthKeychainPromptMode = ClaudeOAuthKeychainPromptPreference + .current()) -> [ClaudeKeychainCandidate] + { + switch self.claudeKeychainCandidatesProbeWithoutPrompt(promptMode: promptMode) { + case .unavailable: + [] + case let .value(candidates): + candidates + } + } + + private static func claudeKeychainLegacyCandidateProbeWithoutPrompt( + promptMode: ClaudeOAuthKeychainPromptMode = ClaudeOAuthKeychainPromptPreference + .current(), + enforcePromptPolicy: Bool = true) -> ClaudeKeychainProbe + { + if enforcePromptPolicy { + guard self.shouldAllowClaudeCodeKeychainAccess(mode: promptMode) else { return .unavailable } + if self.isPromptPolicyApplicable, + ProviderInteractionContext.current == .background, + !ClaudeOAuthKeychainAccessGate.shouldAllowPrompt() + { + return .unavailable + } + } else { + guard self.keychainAccessAllowed else { return .unavailable } + } + var query: [String: Any] = [ + kSecClass as String: kSecClassGenericPassword, + kSecAttrService as String: self.claudeKeychainService, + kSecMatchLimit as String: kSecMatchLimitOne, + kSecReturnAttributes as String: true, + kSecReturnPersistentRef as String: true, + ] + KeychainNoUIQuery.apply(to: &query) + + let (status, result, durationMs) = ClaudeOAuthKeychainQueryTiming.copyMatching(query) + if ClaudeOAuthKeychainQueryTiming + .backoffIfSlowNoUIQuery(durationMs, self.claudeKeychainService, self.log) + { + return .unavailable + } + if status == errSecUserCanceled || status == errSecAuthFailed || status == errSecNoAccessForItem { + ClaudeOAuthKeychainAccessGate.recordDenied() + } + if status == errSecItemNotFound { + return .value(nil) + } + guard status == errSecSuccess else { return .unavailable } + guard let row = result as? [String: Any] else { return .value(nil) } + guard let persistentRef = row[kSecValuePersistentRef as String] as? Data else { return .value(nil) } + return .value(ClaudeKeychainCandidate( + persistentRef: persistentRef, + account: row[kSecAttrAccount as String] as? String, + modifiedAt: row[kSecAttrModificationDate as String] as? Date, + createdAt: row[kSecAttrCreationDate as String] as? Date)) + } + + private static func claudeKeychainLegacyCandidateWithoutPrompt( + promptMode: ClaudeOAuthKeychainPromptMode = ClaudeOAuthKeychainPromptPreference + .current()) -> ClaudeKeychainCandidate? + { + switch self.claudeKeychainLegacyCandidateProbeWithoutPrompt(promptMode: promptMode) { + case .unavailable: + nil + case let .value(candidate): + candidate + } + } + + private static func loadClaudeKeychainData( + candidate: ClaudeKeychainCandidate, + allowKeychainPrompt: Bool, + promptMode: ClaudeOAuthKeychainPromptMode = ClaudeOAuthKeychainPromptPreference.current()) throws -> Data? + { + guard self.shouldAllowClaudeCodeKeychainAccess(mode: promptMode) else { return nil } + self.log.debug( + "Claude keychain data read start", + metadata: [ + "service": self.claudeKeychainService, + "interactive": "\(allowKeychainPrompt)", + "process": ProcessInfo.processInfo.processName, + ]) + + var query: [String: Any] = [ + kSecClass as String: kSecClassGenericPassword, + kSecValuePersistentRef as String: candidate.persistentRef, + kSecMatchLimit as String: kSecMatchLimitOne, + kSecReturnData as String: true, + ] + + if !allowKeychainPrompt { + KeychainNoUIQuery.apply(to: &query) + } + + var result: AnyObject? + let startedAtNs = DispatchTime.now().uptimeNanoseconds + let status = KeychainSecurity.copyMatching(query as CFDictionary, &result) + let durationMs = Double(DispatchTime.now().uptimeNanoseconds - startedAtNs) / 1_000_000.0 + self.log.debug( + "Claude keychain data read result", + metadata: [ + "service": self.claudeKeychainService, + "interactive": "\(allowKeychainPrompt)", + "status": "\(status)", + "duration_ms": String(format: "%.2f", durationMs), + "process": ProcessInfo.processInfo.processName, + ]) + switch status { + case errSecSuccess: + if let data = result as? Data { + return data + } + return nil + case errSecItemNotFound: + return nil + case errSecInteractionNotAllowed: + if allowKeychainPrompt { + ClaudeOAuthKeychainAccessGate.recordDenied() + throw ClaudeOAuthCredentialsError.keychainError(Int(status)) + } + return nil + case errSecUserCanceled, errSecAuthFailed: + ClaudeOAuthKeychainAccessGate.recordDenied() + throw ClaudeOAuthCredentialsError.keychainError(Int(status)) + case errSecNoAccessForItem: + ClaudeOAuthKeychainAccessGate.recordDenied() + throw ClaudeOAuthCredentialsError.keychainError(Int(status)) + default: + throw ClaudeOAuthCredentialsError.keychainError(Int(status)) + } + } + + private static func loadClaudeKeychainLegacyData( + allowKeychainPrompt: Bool, + promptMode: ClaudeOAuthKeychainPromptMode = ClaudeOAuthKeychainPromptPreference.current()) throws -> Data? + { + guard self.shouldAllowClaudeCodeKeychainAccess(mode: promptMode) else { return nil } + self.log.debug( + "Claude keychain legacy data read start", + metadata: [ + "service": self.claudeKeychainService, + "interactive": "\(allowKeychainPrompt)", + "process": ProcessInfo.processInfo.processName, + ]) + + var query: [String: Any] = [ + kSecClass as String: kSecClassGenericPassword, + kSecAttrService as String: self.claudeKeychainService, + kSecMatchLimit as String: kSecMatchLimitOne, + kSecReturnData as String: true, + ] + + if !allowKeychainPrompt { + KeychainNoUIQuery.apply(to: &query) + } + + var result: AnyObject? + let startedAtNs = DispatchTime.now().uptimeNanoseconds + let status = KeychainSecurity.copyMatching(query as CFDictionary, &result) + let durationMs = Double(DispatchTime.now().uptimeNanoseconds - startedAtNs) / 1_000_000.0 + self.log.debug( + "Claude keychain legacy data read result", + metadata: [ + "service": self.claudeKeychainService, + "interactive": "\(allowKeychainPrompt)", + "status": "\(status)", + "duration_ms": String(format: "%.2f", durationMs), + "process": ProcessInfo.processInfo.processName, + ]) + switch status { + case errSecSuccess: + return result as? Data + case errSecItemNotFound: + return nil + case errSecInteractionNotAllowed: + if allowKeychainPrompt { + ClaudeOAuthKeychainAccessGate.recordDenied() + throw ClaudeOAuthCredentialsError.keychainError(Int(status)) + } + return nil + case errSecUserCanceled, errSecAuthFailed: + ClaudeOAuthKeychainAccessGate.recordDenied() + throw ClaudeOAuthCredentialsError.keychainError(Int(status)) + case errSecNoAccessForItem: + ClaudeOAuthKeychainAccessGate.recordDenied() + throw ClaudeOAuthCredentialsError.keychainError(Int(status)) + default: + throw ClaudeOAuthCredentialsError.keychainError(Int(status)) + } + } + #endif + + private static func loadFromEnvironment(_ environment: [String: String]) + -> ClaudeOAuthCredentials? + { + guard + let token = environment[self.environmentTokenKey]?.trimmingCharacters( + in: .whitespacesAndNewlines), + !token.isEmpty + else { + return nil + } + + let scopes: [String] = { + guard let raw = environment[self.environmentScopesKey] else { return ["user:profile"] } + let parsed = + raw + .split(separator: ",") + .map { $0.trimmingCharacters(in: .whitespacesAndNewlines) } + .filter { !$0.isEmpty } + return parsed.isEmpty ? ["user:profile"] : parsed + }() + + return ClaudeOAuthCredentials( + accessToken: token, + refreshToken: nil, + expiresAt: Date.distantFuture, + scopes: scopes, + rateLimitTier: nil) + } + + static func setCredentialsURLOverrideForTesting(_ url: URL?) { + self.credentialsURLOverride = url + } + + #if DEBUG + public static func withCredentialsURLOverrideForTesting(_ url: URL?, operation: () throws -> T) rethrows -> T { + try self.$taskCredentialsURLOverride.withValue(url) { + try operation() + } + } + + public static func withCredentialsURLOverrideForTesting(_ url: URL?, operation: () async throws -> T) + async rethrows -> T { + try await self.$taskCredentialsURLOverride.withValue(url) { + try await operation() + } + } + + public static var currentCredentialsURLOverrideForTesting: URL? { + self.taskCredentialsURLOverride + } + #endif + + private static func saveToCacheKeychain( + _ data: Data, + owner: ClaudeOAuthCredentialOwner? = nil, + historyOwnerIdentifier: String? = nil) + { + guard self.shouldUseCodexBarOAuthKeychainCache else { + self.markPendingCodexBarOAuthKeychainCacheClear() + return + } + let entry = CacheEntry( + data: data, + storedAt: Date(), + owner: owner, + historyOwnerIdentifier: historyOwnerIdentifier) + self.currentPendingCodexBarOAuthKeychainCacheClearStore.withCacheTransaction { pending in + if pending { + switch KeychainCacheStore.clearResult(key: self.cacheKey) { + case .removed, .missing: + pending = false + case .failed: + break + } + } + pending = !KeychainCacheStore.storeResult(key: self.cacheKey, entry: entry) + } + } + + private static func clearCacheKeychain() { + if self.shouldUseCodexBarOAuthKeychainCache { + self.currentPendingCodexBarOAuthKeychainCacheClearStore.withCacheTransaction { pending in + switch KeychainCacheStore.clearResult(key: self.cacheKey) { + case .removed, .missing: + pending = false + case .failed: + pending = true + } + } + } else { + self.markPendingCodexBarOAuthKeychainCacheClear() + } + } + + private static func loadCodexBarOAuthKeychainCache() -> KeychainCacheStore.LoadResult { + guard self.shouldUseCodexBarOAuthKeychainCache else { return .missing } + var result: KeychainCacheStore.LoadResult = .temporarilyUnavailable + self.currentPendingCodexBarOAuthKeychainCacheClearStore.withCacheTransaction { pending in + if pending { + switch KeychainCacheStore.clearResult(key: self.cacheKey) { + case .removed, .missing: + pending = false + case .failed: + return + } + } + result = KeychainCacheStore.load(key: self.cacheKey, as: CacheEntry.self) + } + return result + } + + private static var shouldUseCodexBarOAuthKeychainCache: Bool { + ClaudeOAuthKeychainPromptPreference.storedMode() != .never + } + + private static func markPendingCodexBarOAuthKeychainCacheClear() { + self.currentPendingCodexBarOAuthKeychainCacheClearStore.markPending() + } + + private static var hasPendingCodexBarOAuthKeychainCacheClear: Bool { + self.currentPendingCodexBarOAuthKeychainCacheClearStore.isPending + } + + private static var currentPendingCodexBarOAuthKeychainCacheClearStore: ClaudeOAuthPendingCacheClearStore { + #if DEBUG + if let store = self.taskPendingCacheClearStoreOverride { + return store + } + #endif + return self.pendingCodexBarOAuthKeychainCacheClearStore + } + + private static var keychainAccessAllowed: Bool { + #if DEBUG + if let override = self.taskKeychainAccessOverride { + return !override + } + if KeychainAccessGate.currentOverrideForTesting == true { + return false + } + if self.hasTaskKeychainTestingOverride { + return true + } + #endif + return !KeychainAccessGate.isDisabled + } + + #if DEBUG + private static var hasTaskKeychainTestingOverride: Bool { + self.taskClaudeKeychainOverrideStore != nil + || self.taskClaudeKeychainDataOverride != nil + || self.taskClaudeKeychainFingerprintOverride != nil + || self.taskSecurityCLIReadOverride != nil + || self.taskSecurityCLIReadAccountOverride != nil + } + #endif + + private static var isPromptPolicyApplicable: Bool { + ClaudeOAuthKeychainPromptPreference.isApplicable() + } + + private static func securityFrameworkFallbackPromptDecision( + promptMode: ClaudeOAuthKeychainPromptMode, + allowKeychainPrompt: Bool, + respectKeychainPromptCooldown: Bool) -> (allowed: Bool, blockedReason: String?) + { + guard allowKeychainPrompt else { + return (allowed: false, blockedReason: "allowKeychainPromptFalse") + } + guard self.shouldAllowClaudeCodeKeychainAccess(mode: promptMode) else { + return (allowed: false, blockedReason: self.fallbackBlockedReason(promptMode: promptMode)) + } + if respectKeychainPromptCooldown, + !ClaudeOAuthKeychainAccessGate.shouldAllowPrompt() + { + return (allowed: false, blockedReason: "cooldown") + } + return (allowed: true, blockedReason: nil) + } + + private static func fallbackBlockedReason(promptMode: ClaudeOAuthKeychainPromptMode) -> String { + if !self.keychainAccessAllowed { + return "keychainDisabled" + } + switch promptMode { + case .never: + return "never" + case .onlyOnUserAction: + return "onlyOnUserAction-background" + case .always: + return "disallowed" + } + } + + private static func shouldAllowClaudeCodeKeychainAccess( + mode: ClaudeOAuthKeychainPromptMode = ClaudeOAuthKeychainPromptPreference.current()) -> Bool + { + guard self.keychainAccessAllowed else { return false } + switch mode { + case .never: return false + case .onlyOnUserAction: + return ProviderInteractionContext.current == .userInitiated || self.allowBackgroundPromptBootstrap + case .always: return true + } + } + + static func preferredClaudeKeychainAccountForSecurityCLIRead( + interaction: ProviderInteraction = ProviderInteractionContext.current) -> String? + { + // Keep the experimental background path fully on /usr/bin/security by default. + // Account pinning requires Security.framework candidate probing, so only allow it on explicit user actions. + guard interaction == .userInitiated else { return nil } + #if DEBUG + if let override = self.taskSecurityCLIReadAccountOverride { + return override + } + #endif + #if os(macOS) + let mode = ClaudeOAuthKeychainPromptPreference.current() + guard self.shouldAllowClaudeCodeKeychainAccess(mode: mode) else { return nil } + // Keep experimental mode prompt-safe: avoid Security.framework candidate probes when preflight says + // interaction is likely. + if self.shouldShowClaudeKeychainPreAlert() { + return nil + } + guard let account = self.claudeKeychainCandidatesWithoutPrompt(promptMode: mode).first?.account, + !account.isEmpty + else { + return nil + } + return account + #else + return nil + #endif + } + + private static func credentialsFileURL() -> URL { + #if DEBUG + if let override = self.taskCredentialsURLOverride { + return override + } + #endif + return self.credentialsURLOverride ?? self.defaultCredentialsURL() + } + + private static func loadFileFingerprint() -> CredentialsFileFingerprint? { + #if DEBUG + if let store = self.taskCredentialsFileFingerprintStoreOverride { + return store.load() + } + #endif + guard let data = UserDefaults.standard.data(forKey: self.fileFingerprintKey) else { + return nil + } + return try? JSONDecoder().decode(CredentialsFileFingerprint.self, from: data) + } + + private static func saveFileFingerprint(_ fingerprint: CredentialsFileFingerprint?) { + #if DEBUG + if let store = self.taskCredentialsFileFingerprintStoreOverride { + store.save(fingerprint); return + } + #endif + guard let fingerprint else { + UserDefaults.standard.removeObject(forKey: self.fileFingerprintKey) + return + } + if let data = try? JSONEncoder().encode(fingerprint) { + UserDefaults.standard.set(data, forKey: self.fileFingerprintKey) + } + } + + private static func currentFileFingerprint() -> CredentialsFileFingerprint? { + let url = self.credentialsFileURL() + guard let attrs = try? FileManager.default.attributesOfItem(atPath: url.path) else { + return nil + } + let size = (attrs[.size] as? NSNumber)?.intValue ?? 0 + let modifiedAtMs = (attrs[.modificationDate] as? Date).map { Int($0.timeIntervalSince1970 * 1000) } + return CredentialsFileFingerprint(modifiedAtMs: modifiedAtMs, size: size) + } + + #if DEBUG + static func _resetCredentialsFileTrackingForTesting() { + if let store = self.taskCredentialsFileFingerprintStoreOverride { + store.save(nil) + } else { + UserDefaults.standard.removeObject(forKey: self.fileFingerprintKey) + } + if self.taskPendingCacheClearStoreOverride != nil { + self.currentPendingCodexBarOAuthKeychainCacheClearStore.withCacheTransaction { pending in + pending = false + } + } + } + + static func _resetClaudeKeychainChangeTrackingForTesting() { + UserDefaults.standard.removeObject(forKey: self.claudeKeychainFingerprintKey) + UserDefaults.standard.removeObject(forKey: self.claudeKeychainFingerprintLegacyKey) + self.setClaudeKeychainDataOverrideForTesting(nil) + self.setClaudeKeychainFingerprintOverrideForTesting(nil) + self.claudeKeychainChangeCheckLock.lock() + self.lastClaudeKeychainChangeCheckAt = nil + self.claudeKeychainChangeCheckLock.unlock() + } + + static func _resetClaudeKeychainChangeThrottleForTesting() { + self.claudeKeychainChangeCheckLock.lock() + self.lastClaudeKeychainChangeCheckAt = nil + self.claudeKeychainChangeCheckLock.unlock() + } + #endif + + private static func defaultCredentialsURL() -> URL { + let home = FileManager.default.homeDirectoryForCurrentUser + return home.appendingPathComponent(self.credentialsPath) + } +} + +// swiftlint:enable type_body_length + +extension ClaudeOAuthCredentialsStore { + /// After delegated Claude CLI refresh, re-load the Claude keychain entry without prompting and sync it into + /// CodexBar's caches. This is used to avoid triggering a second OS keychain dialog during the OAuth retry. + @discardableResult + static func syncFromClaudeKeychainWithoutPrompt(now: Date = Date()) -> Bool { + Recovery(context: self.currentCollaboratorContext()).syncFromClaudeKeychainWithoutPrompt(now: now) + } + + private static func shouldShowClaudeKeychainPreAlert() -> Bool { + #if DEBUG + // Synthetic Claude Keychain fixtures must not fall through to the real preflight. Tests that explicitly + // override the preflight still exercise its prompt-policy branches. + if self.hasTaskKeychainTestingOverride, + !KeychainAccessPreflight.hasCheckGenericPasswordOverrideForTesting + { + return false + } + #endif + let mode = ClaudeOAuthKeychainPromptPreference.current() + guard self.shouldAllowClaudeCodeKeychainAccess(mode: mode) else { return false } + return switch KeychainAccessPreflight.checkGenericPassword(service: self.claudeKeychainService, account: nil) { + case .interactionRequired: + true + case .failure: + // If preflight fails, we can't be sure whether interaction is required (or if the preflight itself + // is impacted by a misbehaving Keychain configuration). Be conservative and show the pre-alert. + true + case .allowed, .notFound: + false + } + } + + private static func shouldNotifyClaudeKeychainPreAlert() -> Bool { + let mode = ClaudeOAuthKeychainPromptPreference.current() + guard self.shouldAllowClaudeCodeKeychainAccess(mode: mode) else { return false } + // Attribute-only preflight can report success even when reading the secret will prompt. Explicit user + // actions are rare and intentional, so always explain the read before Security.framework can show UI. + return ProviderInteractionContext.current == .userInitiated || self.shouldShowClaudeKeychainPreAlert() + } + + /// Refresh the access token using a refresh token. + /// Updates CodexBar's keychain cache with the new credentials. + public static func refreshAccessToken( + refreshToken: String, + existingScopes: [String], + existingRateLimitTier: String?, + existingSubscriptionType: String? = nil) async throws -> ClaudeOAuthCredentials + { + let historyOwnerIdentifier = ClaudeOAuthCredentials.historyOwnerIdentifier(forRefreshToken: refreshToken) + return try await Refresher(context: self.currentCollaboratorContext()).refreshAccessToken( + refreshToken: refreshToken, + existingScopes: existingScopes, + existingRateLimitTier: existingRateLimitTier, + existingSubscriptionType: existingSubscriptionType, + historyOwnerIdentifier: historyOwnerIdentifier) + } + + private enum RefreshFailureDisposition: String { + case terminalInvalidGrant + case transientBackoff + } + + private static func extractOAuthErrorCode(from data: Data) -> String? { + guard let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else { + return nil + } + return json["error"] as? String + } + + private static func refreshFailureDisposition(statusCode: Int, data: Data) -> RefreshFailureDisposition? { + guard statusCode == 400 || statusCode == 401 else { return nil } + if let error = self.extractOAuthErrorCode(from: data)?.lowercased(), error == "invalid_grant" { + return .terminalInvalidGrant + } + return .transientBackoff + } + + #if DEBUG + static func extractOAuthErrorCodeForTesting(from data: Data) -> String? { + self.extractOAuthErrorCode(from: data) + } + + static func refreshFailureDispositionForTesting(statusCode: Int, data: Data) -> String? { + self.refreshFailureDisposition(statusCode: statusCode, data: data)?.rawValue + } + #endif +} diff --git a/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthDelegatedRefreshCoordinator.swift b/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthDelegatedRefreshCoordinator.swift new file mode 100644 index 0000000..15a5c42 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthDelegatedRefreshCoordinator.swift @@ -0,0 +1,580 @@ +import Foundation + +public enum ClaudeOAuthDelegatedRefreshCoordinator { + private final class AttemptStateStorage: @unchecked Sendable { + let lock = NSLock() + let persistsCooldown: Bool + var hasLoadedState = false + var lastAttemptAt: Date? + var lastCooldownInterval: TimeInterval? + var inFlightAttemptID: UInt64? + var inFlightInteraction: ProviderInteraction? + var inFlightTask: Task? + var nextAttemptID: UInt64 = 0 + + init(persistsCooldown: Bool) { + self.persistsCooldown = persistsCooldown + } + } + + public enum Outcome: Sendable, Equatable { + case skippedByCooldown + case cliUnavailable + case attemptedSucceeded + case attemptedFailed(String) + } + + private static let log = CodexBarLog.logger(LogCategories.claudeUsage) + private static let cooldownDefaultsKey = "claudeOAuthDelegatedRefreshLastAttemptAtV1" + private static let cooldownIntervalDefaultsKey = "claudeOAuthDelegatedRefreshCooldownIntervalSecondsV1" + private static let defaultCooldownInterval: TimeInterval = 60 * 5 + private static let shortCooldownInterval: TimeInterval = 20 + + private static let sharedState = AttemptStateStorage(persistsCooldown: true) + + public static func attempt( + now: Date = Date(), + timeout: TimeInterval = 8, + environment: [String: String] = ProcessInfo.processInfo.environment) async -> Outcome + { + if Task.isCancelled { + return .attemptedFailed("Cancelled.") + } + + let decision = self.inFlightDecision( + now: now, + timeout: timeout, + environment: environment, + interaction: ProviderInteractionContext.current) + #if DEBUG + if case .joinThenRetry = decision { + self.userInitiatedBackgroundJoinObserverForTesting?() + } + #endif + + switch decision { + case let .join(task): + return await task.value + case let .joinThenRetry(id, task, state): + let outcome = await task.value + self.clearInFlightTaskIfStillCurrent(id: id, state: state) + switch outcome { + case .attemptedFailed, .skippedByCooldown, .cliUnavailable: + return await self.attempt(now: now, timeout: timeout, environment: environment) + case .attemptedSucceeded: + return outcome + } + case let .start(id, task, state): + let outcome = await task.value + self.clearInFlightTaskIfStillCurrent(id: id, state: state) + return outcome + } + } + + private enum InFlightDecision { + case join(Task) + case joinThenRetry(UInt64, Task, AttemptStateStorage) + case start(UInt64, Task, AttemptStateStorage) + } + + private struct AttemptConfiguration { + let environment: [String: String] + let interaction: ProviderInteraction + let readStrategy: ClaudeOAuthKeychainReadStrategy + let keychainAccessDisabled: Bool + #if DEBUG + let cliAvailableOverride: Bool? + let touchAuthPathOverride: (@Sendable (TimeInterval, [String: String]) async throws -> Void)? + let keychainFingerprintOverride: (@Sendable () -> ClaudeOAuthCredentialsStore.ClaudeKeychainFingerprint?)? + #endif + } + + private static func inFlightDecision( + now: Date, + timeout: TimeInterval, + environment: [String: String], + interaction: ProviderInteraction) -> InFlightDecision + { + let state = self.currentStateStorage + state.lock.lock() + defer { state.lock.unlock() } + + if let existing = state.inFlightTask { + if interaction == .userInitiated, + state.inFlightInteraction != .userInitiated, + let existingID = state.inFlightAttemptID + { + return .joinThenRetry(existingID, existing, state) + } + return .join(existing) + } + + state.nextAttemptID += 1 + let attemptID = state.nextAttemptID + // Detached to avoid inheriting the caller's executor context (e.g. MainActor) and cancellation state. + #if DEBUG + let configuration = AttemptConfiguration( + environment: environment, + interaction: interaction, + readStrategy: ClaudeOAuthKeychainReadStrategyPreference.current(), + keychainAccessDisabled: KeychainAccessGate.isDisabled, + cliAvailableOverride: self.cliAvailableOverrideForTesting, + touchAuthPathOverride: self.touchAuthPathOverrideForTesting, + keychainFingerprintOverride: self.keychainFingerprintOverrideForTesting) + let securityCLIReadOverride = ClaudeOAuthCredentialsStore.currentSecurityCLIReadOverrideForTesting() + #else + let configuration = AttemptConfiguration( + environment: environment, + interaction: interaction, + readStrategy: ClaudeOAuthKeychainReadStrategyPreference.current(), + keychainAccessDisabled: KeychainAccessGate.isDisabled) + #endif + let task = Task.detached(priority: .utility) { + #if DEBUG + return await ClaudeOAuthCredentialsStore.withSecurityCLIReadOverrideForTesting(securityCLIReadOverride) { + await self.performAttempt( + now: now, + timeout: timeout, + configuration: configuration, + state: state) + } + #else + await self.performAttempt( + now: now, + timeout: timeout, + configuration: configuration, + state: state) + #endif + } + state.inFlightAttemptID = attemptID + state.inFlightInteraction = interaction + state.inFlightTask = task + return .start(attemptID, task, state) + } + + private static func performAttempt( + now: Date, + timeout: TimeInterval, + configuration: AttemptConfiguration, + state: AttemptStateStorage) async -> Outcome + { + guard self.isClaudeCLIAvailable(environment: configuration.environment, configuration: configuration) else { + self.log.info("Claude OAuth delegated refresh skipped: claude CLI unavailable") + return .cliUnavailable + } + + // Atomically reserve an attempt under the lock so concurrent callers don't race past isInCooldown() and start + // multiple touches/poll loops. + guard self.reserveAttemptIfNotInCooldown( + now: now, + bypassCooldown: configuration.interaction == .userInitiated, + state: state) + else { + self.log.debug("Claude OAuth delegated refresh skipped by cooldown") + return .skippedByCooldown + } + + if let mcpOAuthOnlyFailure = self.mcpOAuthOnlyKeychainFailureIfPresent( + interaction: configuration.interaction, + readStrategy: configuration.readStrategy, + keychainAccessDisabled: configuration.keychainAccessDisabled, + environment: configuration.environment) + { + self.recordAttempt(now: now, cooldown: self.defaultCooldownInterval, state: state) + self.log.warning( + "Claude OAuth delegated refresh skipped: Claude keychain has MCP OAuth state only", + metadata: ["readStrategy": configuration.readStrategy.rawValue]) + return .attemptedFailed(mcpOAuthOnlyFailure) + } + + let baseline = self.currentKeychainChangeObservationBaseline( + readStrategy: configuration.readStrategy, + keychainAccessDisabled: configuration.keychainAccessDisabled, + configuration: configuration) + var touchError: Error? + + do { + try await self.touchOAuthAuthPath( + timeout: timeout, + environment: configuration.environment, + configuration: configuration) + } catch { + touchError = error + } + + // "Touch succeeded" must mean we actually observed the Claude keychain entry change. + // Otherwise we end up in a long cooldown with still-expired credentials. + let changed = await self.waitForClaudeKeychainChange( + from: baseline, + readStrategy: configuration.readStrategy, + keychainAccessDisabled: configuration.keychainAccessDisabled, + configuration: configuration, + timeout: min(max(timeout, 1), 2)) + if changed { + self.recordAttempt(now: now, cooldown: self.defaultCooldownInterval, state: state) + self.log.info("Claude OAuth delegated refresh touch succeeded") + return .attemptedSucceeded + } + + self.recordAttempt(now: now, cooldown: self.shortCooldownInterval, state: state) + if let touchError { + let errorType = String(describing: type(of: touchError)) + self.log.warning( + "Claude OAuth delegated refresh touch failed", + metadata: ["errorType": errorType]) + self.log.debug("Claude OAuth delegated refresh touch error: \(touchError.localizedDescription)") + return .attemptedFailed(touchError.localizedDescription) + } + + self.log.warning("Claude OAuth delegated refresh touch did not update Claude keychain") + return .attemptedFailed("Claude keychain did not update after Claude CLI touch.") + } + + public static func isInCooldown(now: Date = Date()) -> Bool { + let state = self.currentStateStorage + state.lock.lock() + defer { state.lock.unlock() } + self.loadStateIfNeededLocked(state: state) + guard let lastAttemptAt = state.lastAttemptAt else { return false } + let cooldown = state.lastCooldownInterval ?? self.defaultCooldownInterval + return now.timeIntervalSince(lastAttemptAt) < cooldown + } + + public static func cooldownRemainingSeconds(now: Date = Date()) -> Int? { + let state = self.currentStateStorage + state.lock.lock() + defer { state.lock.unlock() } + self.loadStateIfNeededLocked(state: state) + guard let lastAttemptAt = state.lastAttemptAt else { return nil } + let cooldown = state.lastCooldownInterval ?? self.defaultCooldownInterval + let remaining = cooldown - now.timeIntervalSince(lastAttemptAt) + guard remaining > 0 else { return nil } + return Int(remaining.rounded(.up)) + } + + public static func isClaudeCLIAvailable( + environment: [String: String] = ProcessInfo.processInfo.environment) -> Bool + { + self.isClaudeCLIAvailable( + environment: environment, + configuration: nil) + } + + private static func isClaudeCLIAvailable( + environment: [String: String], + configuration: AttemptConfiguration?) -> Bool + { + #if DEBUG + if let override = configuration?.cliAvailableOverride ?? self.cliAvailableOverrideForTesting { + return override + } + #endif + return ClaudeCLIResolver.isAvailable(environment: environment) + } + + private static func touchOAuthAuthPath( + timeout: TimeInterval, + environment: [String: String], + configuration: AttemptConfiguration?) async throws + { + #if DEBUG + if let override = configuration?.touchAuthPathOverride ?? self.touchAuthPathOverrideForTesting { + try await override(timeout, environment) + return + } + #endif + try await ClaudeStatusProbe.touchOAuthAuthPath(timeout: timeout, environment: environment) + } + + private enum KeychainChangeObservationBaseline { + case securityFramework(fingerprint: ClaudeOAuthCredentialsStore.ClaudeKeychainFingerprint?) + case securityCLI(data: Data?) + } + + private static func currentKeychainChangeObservationBaseline( + readStrategy: ClaudeOAuthKeychainReadStrategy, + keychainAccessDisabled: Bool, + configuration: AttemptConfiguration?) -> KeychainChangeObservationBaseline + { + if readStrategy == .securityCLIExperimental { + return .securityCLI(data: self.currentClaudeKeychainDataViaSecurityCLIForObservation( + readStrategy: readStrategy, + keychainAccessDisabled: keychainAccessDisabled, + interaction: .background)) + } + return .securityFramework(fingerprint: self.currentClaudeKeychainFingerprint(configuration: configuration)) + } + + private static func waitForClaudeKeychainChange( + from baseline: KeychainChangeObservationBaseline, + readStrategy: ClaudeOAuthKeychainReadStrategy, + keychainAccessDisabled: Bool, + configuration: AttemptConfiguration?, + timeout: TimeInterval) async -> Bool + { + // Prefer correctness but bound the delay. Keychain writes can be slightly delayed after the CLI touch. + // Keep this short to avoid "prompt storms" on configurations where "no UI" queries can still surface UI. + let clampedTimeout = max(0, min(timeout, 2)) + if clampedTimeout == 0 { return false } + + let delays: [TimeInterval] = [0.2, 0.5, 0.8].filter { $0 <= clampedTimeout } + let deadline = Date().addingTimeInterval(clampedTimeout) + + func isObservedChange() -> Bool { + switch baseline { + case let .securityFramework(fingerprintBefore): + // Treat "no fingerprint" as "not observed"; we only succeed if we can read a fingerprint and it + // differs. + guard let current = self.currentClaudeKeychainFingerprintForObservation(configuration: configuration) + else { + return false + } + return current != fingerprintBefore + case let .securityCLI(dataBefore): + // In experimental mode, avoid Security.framework observation entirely and detect change from + // /usr/bin/security output only. + // If baseline capture failed (nil), treat observation as inconclusive and do not infer a change from + // a later successful read. + guard let dataBefore else { return false } + guard let current = self.currentClaudeKeychainDataViaSecurityCLIForObservation( + readStrategy: readStrategy, + keychainAccessDisabled: keychainAccessDisabled, + interaction: .background) + else { return false } + return current != dataBefore + } + } + + if isObservedChange() { + return true + } + + for delay in delays { + if Date() >= deadline { break } + do { + try Task.checkCancellation() + try await Task.sleep(nanoseconds: UInt64(delay * 1_000_000_000)) + } catch { + return false + } + + if isObservedChange() { + return true + } + } + + return false + } + + private static func currentClaudeKeychainFingerprint( + configuration: AttemptConfiguration?) -> ClaudeOAuthCredentialsStore.ClaudeKeychainFingerprint? + { + #if DEBUG + if let override = configuration?.keychainFingerprintOverride ?? self.keychainFingerprintOverrideForTesting { + return override() + } + #endif + return ClaudeOAuthCredentialsStore.currentClaudeKeychainFingerprintWithoutPromptForAuthGate() + } + + private static func currentClaudeKeychainFingerprintForObservation() -> ClaudeOAuthCredentialsStore + .ClaudeKeychainFingerprint? + { + self.currentClaudeKeychainFingerprintForObservation(configuration: nil) + } + + private static func currentClaudeKeychainFingerprintForObservation( + configuration: AttemptConfiguration?) -> ClaudeOAuthCredentialsStore.ClaudeKeychainFingerprint? + { + #if DEBUG + if let override = configuration?.keychainFingerprintOverride ?? self.keychainFingerprintOverrideForTesting { + return override() + } + #endif + + // Observation should not be blocked by the background cooldown gate; otherwise we can "false fail" even when + // the CLI refreshed successfully but we couldn't observe it due to a previous denied prompt/cooldown. + // + // This temporarily classifies the observation query as "user initiated" so it bypasses the gate that only + // applies to background probes. The query remains "no UI" and does not clear cooldown state itself. + return ProviderInteractionContext.$current.withValue(.userInitiated) { + ClaudeOAuthCredentialsStore.currentClaudeKeychainFingerprintWithoutPromptForAuthGate() + } + } + + private static func currentClaudeKeychainDataViaSecurityCLIForObservation( + readStrategy: ClaudeOAuthKeychainReadStrategy, + keychainAccessDisabled: Bool, + interaction: ProviderInteraction) -> Data? + { + guard !keychainAccessDisabled else { return nil } + return ClaudeOAuthCredentialsStore.readRawClaudeKeychainPayloadViaSecurityCLIIfEnabled( + interaction: interaction, + readStrategy: readStrategy) + } + + private static func mcpOAuthOnlyKeychainFailureIfPresent( + interaction: ProviderInteraction, + readStrategy: ClaudeOAuthKeychainReadStrategy, + keychainAccessDisabled: Bool, + environment: [String: String]) -> String? + { + guard interaction != .userInitiated else { return nil } + guard ClaudeOAuthCredentialsStore.isMcpOAuthOnlyClaudeKeychainPayloadPresent( + interaction: interaction, + readStrategy: readStrategy, + keychainAccessDisabled: keychainAccessDisabled, + environment: environment) + else { + return nil + } + return ClaudeOAuthCredentialsError.mcpOAuthOnlyKeychain.errorDescription + ?? "Claude keychain contains MCP OAuth state only." + } + + private static func clearInFlightTaskIfStillCurrent(id: UInt64, state: AttemptStateStorage) { + state.lock.lock() + if state.inFlightAttemptID == id { + state.inFlightAttemptID = nil + state.inFlightInteraction = nil + state.inFlightTask = nil + } + state.lock.unlock() + } + + private static func recordAttempt(now: Date, cooldown: TimeInterval, state: AttemptStateStorage) { + state.lock.lock() + defer { state.lock.unlock() } + self.loadStateIfNeededLocked(state: state) + state.lastAttemptAt = now + state.lastCooldownInterval = cooldown + guard state.persistsCooldown else { return } + UserDefaults.standard.set(now.timeIntervalSince1970, forKey: self.cooldownDefaultsKey) + UserDefaults.standard.set(cooldown, forKey: self.cooldownIntervalDefaultsKey) + } + + private static func reserveAttemptIfNotInCooldown( + now: Date, + bypassCooldown: Bool, + state: AttemptStateStorage) -> Bool + { + state.lock.lock() + defer { state.lock.unlock() } + self.loadStateIfNeededLocked(state: state) + + let cooldown = state.lastCooldownInterval ?? self.defaultCooldownInterval + if !bypassCooldown, + let lastAttemptAt = state.lastAttemptAt, + now.timeIntervalSince(lastAttemptAt) < cooldown + { + return false + } + + // Reserve with a short cooldown; the final outcome will extend or keep it short. + state.lastAttemptAt = now + state.lastCooldownInterval = self.shortCooldownInterval + guard state.persistsCooldown else { return true } + UserDefaults.standard.set(now.timeIntervalSince1970, forKey: self.cooldownDefaultsKey) + UserDefaults.standard.set(self.shortCooldownInterval, forKey: self.cooldownIntervalDefaultsKey) + return true + } + + private static func loadStateIfNeededLocked(state: AttemptStateStorage) { + guard !state.hasLoadedState else { return } + state.hasLoadedState = true + guard state.persistsCooldown else { + state.lastAttemptAt = nil + state.lastCooldownInterval = nil + return + } + guard let raw = UserDefaults.standard.object(forKey: self.cooldownDefaultsKey) as? Double else { + state.lastAttemptAt = nil + state.lastCooldownInterval = nil + return + } + state.lastAttemptAt = Date(timeIntervalSince1970: raw) + if let interval = UserDefaults.standard.object(forKey: self.cooldownIntervalDefaultsKey) as? Double { + state.lastCooldownInterval = interval + } else { + state.lastCooldownInterval = nil + } + } + + #if DEBUG + @TaskLocal private static var stateStorageForTesting: AttemptStateStorage? + @TaskLocal static var cliAvailableOverrideForTesting: Bool? + @TaskLocal static var touchAuthPathOverrideForTesting: (@Sendable ( + TimeInterval, + [String: String]) async throws -> Void)? + @TaskLocal static var keychainFingerprintOverrideForTesting: (@Sendable () -> ClaudeOAuthCredentialsStore + .ClaudeKeychainFingerprint?)? + @TaskLocal static var userInitiatedBackgroundJoinObserverForTesting: (@Sendable () -> Void)? + + static func withCLIAvailableOverrideForTesting( + _ override: Bool?, + operation: () async throws -> T) async rethrows -> T + { + try await self.$cliAvailableOverrideForTesting.withValue(override) { + try await operation() + } + } + + static func withTouchAuthPathOverrideForTesting( + _ override: (@Sendable (TimeInterval, [String: String]) async throws -> Void)?, + operation: () async throws -> T) async rethrows -> T + { + try await self.$touchAuthPathOverrideForTesting.withValue(override) { + try await operation() + } + } + + static func withKeychainFingerprintOverrideForTesting( + _ override: (@Sendable () -> ClaudeOAuthCredentialsStore.ClaudeKeychainFingerprint?)?, + operation: () async throws -> T) async rethrows -> T + { + try await self.$keychainFingerprintOverrideForTesting.withValue(override) { + try await operation() + } + } + + static func withUserInitiatedBackgroundJoinObserverForTesting( + _ observer: (@Sendable () -> Void)?, + operation: () async throws -> T) async rethrows -> T + { + try await self.$userInitiatedBackgroundJoinObserverForTesting.withValue(observer) { + try await operation() + } + } + + static func withIsolatedStateForTesting(operation: () async throws -> T) async rethrows -> T { + let state = AttemptStateStorage(persistsCooldown: false) + return try await self.$stateStorageForTesting.withValue(state) { + try await operation() + } + } + + static func resetForTesting() { + let state = self.currentStateStorage + state.lock.lock() + state.hasLoadedState = true + state.lastAttemptAt = nil + state.lastCooldownInterval = nil + state.inFlightAttemptID = nil + state.inFlightInteraction = nil + state.inFlightTask = nil + state.nextAttemptID = 0 + state.lock.unlock() + guard state.persistsCooldown else { return } + UserDefaults.standard.removeObject(forKey: self.cooldownDefaultsKey) + UserDefaults.standard.removeObject(forKey: self.cooldownIntervalDefaultsKey) + } + #endif + + private static var currentStateStorage: AttemptStateStorage { + #if DEBUG + self.stateStorageForTesting ?? self.sharedState + #else + self.sharedState + #endif + } +} diff --git a/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthKeychainAccessGate.swift b/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthKeychainAccessGate.swift new file mode 100644 index 0000000..6d43c45 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthKeychainAccessGate.swift @@ -0,0 +1,184 @@ +import Foundation + +#if os(macOS) +import os.lock + +public enum ClaudeOAuthKeychainAccessGate { + private struct State { + var loaded = false + var deniedUntil: Date? + } + + private static let lock = OSAllocatedUnfairLock(initialState: State()) + private static let defaultsKey = "claudeOAuthKeychainDeniedUntil" + private static let cooldownInterval: TimeInterval = 60 * 60 * 6 + @TaskLocal private static var taskOverrideShouldAllowPromptForTesting: Bool? + #if DEBUG + public final class DeniedUntilStore: @unchecked Sendable { + public var deniedUntil: Date? + + public init() {} + } + + @TaskLocal private static var taskDeniedUntilStoreOverrideForTesting: DeniedUntilStore? + #endif + + public static func shouldAllowPrompt(now: Date = Date()) -> Bool { + guard !KeychainAccessGate.isDisabled else { return false } + if let override = self.taskOverrideShouldAllowPromptForTesting { return override } + #if DEBUG + if let store = self.taskDeniedUntilStoreOverrideForTesting { + if let deniedUntil = store.deniedUntil, deniedUntil > now { + return false + } + store.deniedUntil = nil + return true + } + #endif + return self.lock.withLock { state in + self.loadIfNeeded(&state) + if let deniedUntil = state.deniedUntil { + if deniedUntil > now { + return false + } + state.deniedUntil = nil + self.persist(state) + } + return true + } + } + + public static func recordDenied(now: Date = Date()) { + let deniedUntil = now.addingTimeInterval(self.cooldownInterval) + #if DEBUG + if let store = self.taskDeniedUntilStoreOverrideForTesting { + store.deniedUntil = deniedUntil + return + } + #endif + self.lock.withLock { state in + self.loadIfNeeded(&state) + state.deniedUntil = deniedUntil + self.persist(state) + } + } + + /// Clears the cooldown so the next attempt can proceed. Intended for user-initiated repairs. + /// - Returns: true if a cooldown was present and cleared. + public static func clearDenied(now: Date = Date()) -> Bool { + #if DEBUG + if let store = self.taskDeniedUntilStoreOverrideForTesting { + guard let deniedUntil = store.deniedUntil, deniedUntil > now else { + store.deniedUntil = nil + return false + } + store.deniedUntil = nil + return true + } + #endif + return self.lock.withLock { state in + self.loadIfNeeded(&state) + guard let deniedUntil = state.deniedUntil, deniedUntil > now else { + state.deniedUntil = nil + self.persist(state) + return false + } + state.deniedUntil = nil + self.persist(state) + return true + } + } + + #if DEBUG + static func withShouldAllowPromptOverrideForTesting( + _ value: Bool?, + operation: () throws -> T) rethrows -> T + { + try self.$taskOverrideShouldAllowPromptForTesting.withValue(value) { + try operation() + } + } + + static func withShouldAllowPromptOverrideForTesting( + _ value: Bool?, + operation: () async throws -> T) async rethrows -> T + { + try await self.$taskOverrideShouldAllowPromptForTesting.withValue(value) { + try await operation() + } + } + + public static func withDeniedUntilStoreOverrideForTesting( + _ store: DeniedUntilStore?, + operation: () throws -> T) rethrows -> T + { + try self.$taskDeniedUntilStoreOverrideForTesting.withValue(store) { + try operation() + } + } + + public static func withDeniedUntilStoreOverrideForTesting( + _ store: DeniedUntilStore?, + operation: () async throws -> T) async rethrows -> T + { + try await self.$taskDeniedUntilStoreOverrideForTesting.withValue(store) { + try await operation() + } + } + + public static var currentDeniedUntilStoreOverrideForTesting: DeniedUntilStore? { + self.taskDeniedUntilStoreOverrideForTesting + } + + public static func resetForTesting() { + self.lock.withLock { state in + // Keep deterministic during tests: avoid re-loading UserDefaults written by unrelated code paths. + state.loaded = true + state.deniedUntil = nil + UserDefaults.standard.removeObject(forKey: self.defaultsKey) + } + } + + public static func resetInMemoryForTesting() { + self.lock.withLock { state in + state.loaded = false + state.deniedUntil = nil + } + } + #endif + + private static func loadIfNeeded(_ state: inout State) { + guard !state.loaded else { return } + state.loaded = true + if let raw = UserDefaults.standard.object(forKey: self.defaultsKey) as? Double { + state.deniedUntil = Date(timeIntervalSince1970: raw) + } + } + + private static func persist(_ state: State) { + if let deniedUntil = state.deniedUntil { + UserDefaults.standard.set(deniedUntil.timeIntervalSince1970, forKey: self.defaultsKey) + } else { + UserDefaults.standard.removeObject(forKey: self.defaultsKey) + } + } +} +#else +public enum ClaudeOAuthKeychainAccessGate { + public static func shouldAllowPrompt(now _: Date = Date()) -> Bool { + true + } + + public static func recordDenied(now _: Date = Date()) {} + + public static func clearDenied(now _: Date = Date()) -> Bool { + false + } + + #if DEBUG + public static func resetForTesting() {} + + public static func resetInMemoryForTesting() {} + #endif +} +#endif diff --git a/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthKeychainPreAlertGate.swift b/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthKeychainPreAlertGate.swift new file mode 100644 index 0000000..285947a --- /dev/null +++ b/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthKeychainPreAlertGate.swift @@ -0,0 +1,169 @@ +import Foundation + +#if os(macOS) +import os.lock + +enum ClaudeOAuthKeychainPreAlertGate { + fileprivate struct State { + var loaded = false + var acknowledgedUntil: Date? + var presentationInFlight = false + } + + private static let lock = OSAllocatedUnfairLock(initialState: State()) + private static let defaultsKey = "claudeOAuthKeychainPreAlertAcknowledgedUntilV1" + static let cooldownInterval: TimeInterval = 60 * 60 * 6 + + #if DEBUG + final class StateStore: @unchecked Sendable { + fileprivate let lock = OSAllocatedUnfairLock(initialState: State(loaded: true)) + } + + @TaskLocal private static var taskStateStoreOverrideForTesting: StateStore? + #endif + + /// Presents at most one explanatory alert and starts the cooldown only when it reaches a handler. + @discardableResult + static func presentIfNeeded( + now: Date = Date(), + completedAt: Date? = nil, + present: () -> Bool) -> Bool + { + guard self.beginPresentation(now: now) else { return false } + let wasPresented = present() + self.finishPresentation(wasPresented: wasPresented, now: completedAt ?? Date()) + return wasPresented + } + + private static func beginPresentation(now: Date) -> Bool { + #if DEBUG + if let store = self.taskStateStoreOverrideForTesting { + return store.lock.withLock { state in + self.reservePresentation(state: &state, now: now) + } + } + #endif + return self.lock.withLock { state in + self.loadIfNeeded(&state) + guard self.reservePresentation(state: &state, now: now) else { return false } + self.persist(state) + return true + } + } + + private static func finishPresentation(wasPresented: Bool, now: Date) { + #if DEBUG + if let store = self.taskStateStoreOverrideForTesting { + store.lock.withLock { state in + self.completePresentation(state: &state, wasPresented: wasPresented, now: now) + } + return + } + #endif + self.lock.withLock { state in + self.loadIfNeeded(&state) + self.completePresentation(state: &state, wasPresented: wasPresented, now: now) + self.persist(state) + } + } + + #if DEBUG + static func withStateStoreOverrideForTesting( + _ store: StateStore?, + operation: () throws -> T) rethrows -> T + { + try self.$taskStateStoreOverrideForTesting.withValue(store) { + try operation() + } + } + + static func withStateStoreOverrideForTesting( + _ store: StateStore?, + operation: () async throws -> T) async rethrows -> T + { + try await self.$taskStateStoreOverrideForTesting.withValue(store) { + try await operation() + } + } + + static func resetForTesting() { + self.lock.withLock { state in + state = State(loaded: true) + UserDefaults.standard.removeObject(forKey: self.defaultsKey) + } + } + + static func resetInMemoryForTesting() { + self.lock.withLock { state in + state = State() + } + } + #endif + + private static func loadIfNeeded(_ state: inout State) { + guard !state.loaded else { return } + state.loaded = true + if let raw = UserDefaults.standard.object(forKey: self.defaultsKey) as? Double { + state.acknowledgedUntil = Date(timeIntervalSince1970: raw) + } + } + + private static func reservePresentation(state: inout State, now: Date) -> Bool { + guard !state.presentationInFlight else { return false } + if let acknowledgedUntil = state.acknowledgedUntil, acknowledgedUntil > now { + return false + } + state.acknowledgedUntil = nil + state.presentationInFlight = true + return true + } + + private static func completePresentation(state: inout State, wasPresented: Bool, now: Date) { + state.presentationInFlight = false + if wasPresented { + state.acknowledgedUntil = now.addingTimeInterval(self.cooldownInterval) + } + } + + private static func persist(_ state: State) { + if let acknowledgedUntil = state.acknowledgedUntil { + UserDefaults.standard.set(acknowledgedUntil.timeIntervalSince1970, forKey: self.defaultsKey) + } else { + UserDefaults.standard.removeObject(forKey: self.defaultsKey) + } + } +} +#else +enum ClaudeOAuthKeychainPreAlertGate { + static let cooldownInterval: TimeInterval = 60 * 60 * 6 + + #if DEBUG + final class StateStore: @unchecked Sendable {} + #endif + + @discardableResult + static func presentIfNeeded( + now _: Date = Date(), + completedAt _: Date? = nil, + present _: () -> Bool) -> Bool + { + false + } + + #if DEBUG + static func withStateStoreOverrideForTesting( + _: StateStore?, + operation: () throws -> T) rethrows -> T + { + try operation() + } + + static func withStateStoreOverrideForTesting( + _: StateStore?, + operation: () async throws -> T) async rethrows -> T + { + try await operation() + } + #endif +} +#endif diff --git a/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthKeychainPromptMode.swift b/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthKeychainPromptMode.swift new file mode 100644 index 0000000..308684a --- /dev/null +++ b/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthKeychainPromptMode.swift @@ -0,0 +1,177 @@ +import Foundation + +public enum ClaudeOAuthKeychainPromptMode: String, Sendable, Codable, CaseIterable { + case never + case onlyOnUserAction + case always +} + +public enum ClaudeOAuthKeychainPromptPreference { + static let releaseApplicationDefaultsDomain = "com.steipete.codexbar" + static let debugApplicationDefaultsDomain = "com.steipete.codexbar.debug" + private static let userDefaultsKey = "claudeOAuthKeychainPromptMode" + + static var applicationDefaultsDomain: String { + self.resolveApplicationDefaultsDomain( + bundleIdentifier: Bundle.main.bundleIdentifier, + bundleURL: Bundle.main.bundleURL, + executableURL: Bundle.main.executableURL, + invocationURL: CommandLine.arguments.first.map(URL.init(fileURLWithPath:))) + } + + #if DEBUG + private final class UserDefaultsBox: @unchecked Sendable { + let value: UserDefaults + + init(_ value: UserDefaults) { + self.value = value + } + } + + @TaskLocal private static var taskOverride: ClaudeOAuthKeychainPromptMode? + @TaskLocal private static var taskApplicationUserDefaultsOverride: UserDefaultsBox? + #endif + + public static func current(userDefaults: UserDefaults? = nil) -> ClaudeOAuthKeychainPromptMode { + self.effectiveMode(userDefaults: userDefaults) + } + + public static func storedMode(userDefaults: UserDefaults? = nil) -> ClaudeOAuthKeychainPromptMode { + #if DEBUG + if let taskOverride { + return taskOverride + } + #endif + let userDefaults = userDefaults ?? self.applicationUserDefaults + if let raw = userDefaults.string(forKey: self.userDefaultsKey), + let mode = ClaudeOAuthKeychainPromptMode(rawValue: raw) + { + return mode + } + return .onlyOnUserAction + } + + public static func isApplicable( + readStrategy: ClaudeOAuthKeychainReadStrategy = ClaudeOAuthKeychainReadStrategyPreference.current()) -> Bool + { + readStrategy == .securityFramework + } + + public static func effectiveMode( + userDefaults: UserDefaults? = nil, + readStrategy: ClaudeOAuthKeychainReadStrategy = ClaudeOAuthKeychainReadStrategyPreference.current()) + -> ClaudeOAuthKeychainPromptMode + { + guard self.isApplicable(readStrategy: readStrategy) else { + return .always + } + return self.storedMode(userDefaults: userDefaults) + } + + public static func securityFrameworkFallbackMode( + userDefaults: UserDefaults? = nil, + readStrategy: ClaudeOAuthKeychainReadStrategy = ClaudeOAuthKeychainReadStrategyPreference.current()) + -> ClaudeOAuthKeychainPromptMode + { + if readStrategy == .securityCLIExperimental { + return self.storedMode(userDefaults: userDefaults) + } + return self.effectiveMode(userDefaults: userDefaults, readStrategy: readStrategy) + } + + static var applicationUserDefaults: UserDefaults { + #if DEBUG + if let taskApplicationUserDefaultsOverride { + return taskApplicationUserDefaultsOverride.value + } + #endif + return UserDefaults(suiteName: self.applicationDefaultsDomain) ?? .standard + } + + static func resolveApplicationDefaultsDomain( + bundleIdentifier: String?, + bundleURL: URL?, + executableURL: URL?, + invocationURL: URL?, + bundleIdentifierForApp: (URL) -> String? = { Bundle(url: $0)?.bundleIdentifier }) -> String + { + if let domain = self.defaultsDomain(forBundleIdentifier: bundleIdentifier) { + return domain + } + + let candidates = [bundleURL, executableURL, invocationURL].compactMap(\.self) + var visitedPaths = Set() + for candidate in candidates { + var current = candidate.standardizedFileURL.resolvingSymlinksInPath() + let ancestorCount = current.pathComponents.count + for _ in 0.. String? { + guard let bundleIdentifier else { return nil } + // Check debug first because its identifier is a child of the release identifier. + if bundleIdentifier == self.debugApplicationDefaultsDomain + || bundleIdentifier.hasPrefix("\(self.debugApplicationDefaultsDomain).") + { + return self.debugApplicationDefaultsDomain + } + if bundleIdentifier == self.releaseApplicationDefaultsDomain + || bundleIdentifier.hasPrefix("\(self.releaseApplicationDefaultsDomain).") + { + return self.releaseApplicationDefaultsDomain + } + return nil + } + + #if DEBUG + public static func withTaskOverrideForTesting( + _ mode: ClaudeOAuthKeychainPromptMode?, + operation: () throws -> T) rethrows -> T + { + try self.$taskOverride.withValue(mode) { + try operation() + } + } + + public static func withTaskOverrideForTesting( + _ mode: ClaudeOAuthKeychainPromptMode?, + operation: () async throws -> T) async rethrows -> T + { + try await self.$taskOverride.withValue(mode) { + try await operation() + } + } + + public static var currentTaskOverrideForTesting: ClaudeOAuthKeychainPromptMode? { + self.taskOverride + } + + static func withApplicationUserDefaultsOverrideForTesting( + _ userDefaults: UserDefaults?, + operation: () throws -> T) rethrows -> T + { + try self.$taskApplicationUserDefaultsOverride.withValue(userDefaults.map(UserDefaultsBox.init)) { + try operation() + } + } + + static func withApplicationUserDefaultsOverrideForTesting( + _ userDefaults: UserDefaults?, + operation: () async throws -> T) async rethrows -> T + { + try await self.$taskApplicationUserDefaultsOverride.withValue(userDefaults.map(UserDefaultsBox.init)) { + try await operation() + } + } + #endif +} diff --git a/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthKeychainQueryTiming.swift b/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthKeychainQueryTiming.swift new file mode 100644 index 0000000..eb49938 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthKeychainQueryTiming.swift @@ -0,0 +1,31 @@ +import Dispatch +import Foundation + +#if os(macOS) +import Security + +enum ClaudeOAuthKeychainQueryTiming { + static func copyMatching(_ query: [String: Any]) -> (status: OSStatus, result: AnyObject?, durationMs: Double) { + var result: AnyObject? + let startedAtNs = DispatchTime.now().uptimeNanoseconds + let status = KeychainSecurity.copyMatching(query as CFDictionary, &result) + let durationMs = Double(DispatchTime.now().uptimeNanoseconds - startedAtNs) / 1_000_000.0 + return (status, result, durationMs) + } + + static func backoffIfSlowNoUIQuery(_ durationMs: Double, _ service: String, _ log: CodexBarLogger) -> Bool { + // Intentionally no longer treats "slow" no-UI Keychain queries as a denial. Some systems can have + // non-deterministic timing characteristics that would make this backoff too aggressive and surprising. + // + // Keep this hook so call sites can cheaply log slow queries during debugging without changing behavior. + guard ProviderInteractionContext.current == .background, durationMs > 1000 else { return false } + log.debug( + "Claude keychain no-UI query was slow", + metadata: [ + "service": service, + "duration_ms": String(format: "%.2f", durationMs), + ]) + return false + } +} +#endif diff --git a/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthKeychainReadStrategy.swift b/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthKeychainReadStrategy.swift new file mode 100644 index 0000000..057f3ab --- /dev/null +++ b/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthKeychainReadStrategy.swift @@ -0,0 +1,49 @@ +import Foundation + +public enum ClaudeOAuthKeychainReadStrategy: String, Sendable, Codable, CaseIterable { + case securityFramework + case securityCLIExperimental +} + +public enum ClaudeOAuthKeychainReadStrategyPreference { + private static let userDefaultsKey = "claudeOAuthKeychainReadStrategy" + + #if DEBUG + @TaskLocal private static var taskOverride: ClaudeOAuthKeychainReadStrategy? + #endif + + public static func current(userDefaults: UserDefaults = .standard) -> ClaudeOAuthKeychainReadStrategy { + #if DEBUG + if let taskOverride { return taskOverride } + #endif + if let raw = userDefaults.string(forKey: self.userDefaultsKey) { + let strategy = ClaudeOAuthKeychainReadStrategy(rawValue: raw) ?? .securityFramework + return strategy == .securityCLIExperimental ? .securityFramework : strategy + } + return .securityFramework + } + + #if DEBUG + public static func withTaskOverrideForTesting( + _ strategy: ClaudeOAuthKeychainReadStrategy?, + operation: () throws -> T) rethrows -> T + { + try self.$taskOverride.withValue(strategy) { + try operation() + } + } + + public static func withTaskOverrideForTesting( + _ strategy: ClaudeOAuthKeychainReadStrategy?, + operation: () async throws -> T) async rethrows -> T + { + try await self.$taskOverride.withValue(strategy) { + try await operation() + } + } + + public static var currentTaskOverrideForTesting: ClaudeOAuthKeychainReadStrategy? { + self.taskOverride + } + #endif +} diff --git a/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthMutableKeychainOverrides.swift b/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthMutableKeychainOverrides.swift new file mode 100644 index 0000000..d1b53f9 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthMutableKeychainOverrides.swift @@ -0,0 +1,35 @@ +import Foundation + +#if DEBUG +extension ClaudeOAuthCredentialsStore { + final class ClaudeKeychainOverrideStore: @unchecked Sendable { + var data: Data? + var fingerprint: ClaudeKeychainFingerprint? + + init(data: Data? = nil, fingerprint: ClaudeKeychainFingerprint? = nil) { + self.data = data + self.fingerprint = fingerprint + } + } + + @TaskLocal static var taskClaudeKeychainOverrideStore: ClaudeKeychainOverrideStore? + + static func withMutableClaudeKeychainOverrideStoreForTesting( + _ store: ClaudeKeychainOverrideStore?, + operation: () throws -> T) rethrows -> T + { + try self.$taskClaudeKeychainOverrideStore.withValue(store) { + try operation() + } + } + + static func withMutableClaudeKeychainOverrideStoreForTesting( + _ store: ClaudeKeychainOverrideStore?, + operation: () async throws -> T) async rethrows -> T + { + try await self.$taskClaudeKeychainOverrideStore.withValue(store) { + try await operation() + } + } +} +#endif diff --git a/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthPendingCacheClearStore.swift b/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthPendingCacheClearStore.swift new file mode 100644 index 0000000..d9c84f8 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthPendingCacheClearStore.swift @@ -0,0 +1,142 @@ +#if canImport(Darwin) +import Darwin +#elseif canImport(Glibc) +import Glibc +#elseif canImport(Musl) +import Musl +#endif +import Foundation + +protocol ClaudeOAuthPendingCacheClearStore: Sendable { + var isPending: Bool { get } + + func markPending() + func withCacheTransaction(_ operation: (inout Bool) -> Void) +} + +final class ClaudeOAuthPendingCacheClearUserDefaultsStore: ClaudeOAuthPendingCacheClearStore, @unchecked Sendable { + private static let processLock = NSLock() + private static let log = CodexBarLog.logger(LogCategories.claudeUsage) + + private let domain: String + private let key: String + private let lockURL: URL + + init( + domain: String, + key: String, + lockURL: URL = URL(fileURLWithPath: NSHomeDirectory(), isDirectory: true) + .appendingPathComponent(".codexbar", isDirectory: true) + .appendingPathComponent("claude-oauth-cache.lock")) + { + self.domain = domain + self.key = key + self.lockURL = lockURL + } + + var isPending: Bool { + do { + return try self.withInterprocessLock { + self.currentGeneration() != nil + } + } catch { + Self.log.error("Claude OAuth cache tombstone lock failed: \(error.localizedDescription)") + return true + } + } + + func markPending() { + do { + try self.withInterprocessLock { + self.writeGeneration(UUID().uuidString) + } + } catch { + // A surviving tombstone is safer than allowing a stale cache read. If the lock itself is unavailable, + // write a fresh generation but never clear one through the unlocked fallback path. + Self.log.error("Claude OAuth cache tombstone lock failed: \(error.localizedDescription)") + self.writeGeneration(UUID().uuidString) + } + } + + func withCacheTransaction(_ operation: (inout Bool) -> Void) { + do { + try self.withInterprocessLock { + let initialGeneration = self.currentGeneration() + var pending = initialGeneration != nil + operation(&pending) + self.persist( + pending: pending, + initialGeneration: initialGeneration) + } + } catch { + Self.log.error("Claude OAuth cache transaction lock failed: \(error.localizedDescription)") + // Fail closed: without the shared lock, do not touch the cache and leave a fresh invalidation marker. + self.writeGeneration(UUID().uuidString) + } + } + + private func persist( + pending: Bool, + initialGeneration: String?) + { + let currentGeneration = self.currentGeneration() + if pending { + if currentGeneration == nil { + self.writeGeneration(UUID().uuidString) + } + return + } + + // Compare the observed generation before removal. This is defensive against writers that do not yet honor + // the lock, while the lock serializes all current app and bundled-CLI cache mutations. + guard currentGeneration == initialGeneration else { return } + self.writeGeneration(nil) + } + + private func currentGeneration() -> String? { + let userDefaults = UserDefaults(suiteName: self.domain) ?? .standard + userDefaults.synchronize() + if let generation = userDefaults.string(forKey: self.key), !generation.isEmpty { + return generation + } + // V1 stored a boolean. Preserve an outstanding invalidation across the generation-based upgrade. + if userDefaults.object(forKey: self.key) as? Bool == true { + return "legacy-boolean" + } + return nil + } + + private func writeGeneration(_ generation: String?) { + let userDefaults = UserDefaults(suiteName: self.domain) ?? .standard + if let generation { + userDefaults.set(generation, forKey: self.key) + } else { + userDefaults.removeObject(forKey: self.key) + } + userDefaults.synchronize() + } + + private func withInterprocessLock(_ operation: () throws -> T) throws -> T { + Self.processLock.lock() + defer { Self.processLock.unlock() } + + try FileManager.default.createDirectory( + at: self.lockURL.deletingLastPathComponent(), + withIntermediateDirectories: true) + let fd = open(self.lockURL.path, O_CREAT | O_RDWR | O_CLOEXEC, S_IRUSR | S_IWUSR) + guard fd >= 0 else { + throw POSIXError(POSIXErrorCode(rawValue: errno) ?? .EIO) + } + defer { + _ = flock(fd, LOCK_UN) + close(fd) + } + + while flock(fd, LOCK_EX) != 0 { + guard errno == EINTR else { + throw POSIXError(POSIXErrorCode(rawValue: errno) ?? .EIO) + } + } + return try operation() + } +} diff --git a/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthRefreshFailureGate.swift b/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthRefreshFailureGate.swift new file mode 100644 index 0000000..e9caa25 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthRefreshFailureGate.swift @@ -0,0 +1,371 @@ +import Foundation + +#if os(macOS) +import os.lock + +public enum ClaudeOAuthRefreshFailureGate { + public enum BlockStatus: Equatable, Sendable { + case terminal(reason: String?, failures: Int) + case transient(until: Date, failures: Int) + } + + struct AuthFingerprint: Codable, Equatable { + let keychain: ClaudeOAuthCredentialsStore.ClaudeKeychainFingerprint? + let credentialsFile: String? + } + + private struct State { + var loaded = false + var terminalFailureCount = 0 + var transientFailureCount = 0 + var isTerminalBlocked = false + var transientBlockedUntil: Date? + var fingerprintAtFailure: AuthFingerprint? + var lastCredentialsRecheckAt: Date? + var terminalReason: String? + } + + private static let lock = OSAllocatedUnfairLock(initialState: State()) + private static let blockedUntilKey = "claudeOAuthRefreshBackoffBlockedUntilV1" // legacy (migration) + private static let failureCountKey = "claudeOAuthRefreshBackoffFailureCountV1" // legacy + terminal count + private static let fingerprintKey = "claudeOAuthRefreshBackoffFingerprintV2" + private static let terminalBlockedKey = "claudeOAuthRefreshTerminalBlockedV1" + private static let terminalReasonKey = "claudeOAuthRefreshTerminalReasonV1" + private static let transientBlockedUntilKey = "claudeOAuthRefreshTransientBlockedUntilV1" + private static let transientFailureCountKey = "claudeOAuthRefreshTransientFailureCountV1" + + private static let log = CodexBarLog.logger(LogCategories.claudeUsage) + private static let minimumCredentialsRecheckInterval: TimeInterval = 15 + private static let unknownFingerprint = AuthFingerprint(keychain: nil, credentialsFile: nil) + private static let transientBaseInterval: TimeInterval = 60 * 5 + private static let transientMaxInterval: TimeInterval = 60 * 60 * 6 + + #if DEBUG + @TaskLocal static var shouldAttemptOverride: Bool? + private nonisolated(unsafe) static var fingerprintProviderOverride: (() -> AuthFingerprint?)? + + static func setFingerprintProviderOverrideForTesting(_ provider: (() -> AuthFingerprint?)?) { + self.fingerprintProviderOverride = provider + } + + public static func resetInMemoryStateForTesting() { + self.lock.withLock { state in + state.loaded = false + state.terminalFailureCount = 0 + state.transientFailureCount = 0 + state.isTerminalBlocked = false + state.transientBlockedUntil = nil + state.fingerprintAtFailure = nil + state.lastCredentialsRecheckAt = nil + state.terminalReason = nil + } + } + + public static func resetForTesting() { + self.lock.withLock { state in + state.loaded = false + state.terminalFailureCount = 0 + state.transientFailureCount = 0 + state.isTerminalBlocked = false + state.transientBlockedUntil = nil + state.fingerprintAtFailure = nil + state.lastCredentialsRecheckAt = nil + state.terminalReason = nil + UserDefaults.standard.removeObject(forKey: self.blockedUntilKey) + UserDefaults.standard.removeObject(forKey: self.failureCountKey) + UserDefaults.standard.removeObject(forKey: self.fingerprintKey) + UserDefaults.standard.removeObject(forKey: self.terminalBlockedKey) + UserDefaults.standard.removeObject(forKey: self.terminalReasonKey) + UserDefaults.standard.removeObject(forKey: self.transientBlockedUntilKey) + UserDefaults.standard.removeObject(forKey: self.transientFailureCountKey) + } + } + #endif + + public static func shouldAttempt(now: Date = Date()) -> Bool { + #if DEBUG + if let override = self.shouldAttemptOverride { return override } + #endif + + return self.lock.withLock { state in + let didMigrate = self.loadIfNeeded(&state, now: now) + if didMigrate { + self.persist(state) + } + + if state.isTerminalBlocked { + guard self.shouldRecheckCredentials(now: now, state: state) else { return false } + + state.lastCredentialsRecheckAt = now + if self.hasCredentialsChangedSinceFailure(state) { + self.resetState(&state) + self.persist(state) + return true + } + + self.log.debug( + "Claude OAuth refresh blocked until auth changes", + metadata: [ + "terminalFailures": "\(state.terminalFailureCount)", + "reason": state.terminalReason ?? "nil", + ]) + return false + } + + if let blockedUntil = state.transientBlockedUntil { + if blockedUntil <= now { + self.clearTransientState(&state) + // Once transient backoff expires, forget its auth baseline so future failures capture fresh + // fingerprints and so we don't ratchet backoff across unrelated intermittent failures. + state.fingerprintAtFailure = nil + state.lastCredentialsRecheckAt = nil + self.persist(state) + return true + } + + if self.shouldRecheckCredentials(now: now, state: state) { + state.lastCredentialsRecheckAt = now + if self.hasCredentialsChangedSinceFailure(state) { + self.resetState(&state) + self.persist(state) + return true + } + } + + self.log.debug( + "Claude OAuth refresh transient backoff active", + metadata: [ + "until": "\(blockedUntil.timeIntervalSince1970)", + "transientFailures": "\(state.transientFailureCount)", + ]) + return false + } + + return true + } + } + + public static func currentBlockStatus(now: Date = Date()) -> BlockStatus? { + self.lock.withLock { state in + _ = self.loadIfNeeded(&state, now: now) + if state.isTerminalBlocked { + return .terminal(reason: state.terminalReason, failures: state.terminalFailureCount) + } + if let blockedUntil = state.transientBlockedUntil, blockedUntil > now { + return .transient(until: blockedUntil, failures: state.transientFailureCount) + } + return nil + } + } + + public static func recordTerminalAuthFailure(now: Date = Date()) { + self.lock.withLock { state in + _ = self.loadIfNeeded(&state, now: now) + state.terminalFailureCount += 1 + state.isTerminalBlocked = true + state.terminalReason = "invalid_grant" + state.fingerprintAtFailure = self.currentFingerprint() ?? self.unknownFingerprint + state.lastCredentialsRecheckAt = now + self.clearTransientState(&state) + self.persist(state) + } + } + + public static func recordTransientFailure(now: Date = Date()) { + self.lock.withLock { state in + _ = self.loadIfNeeded(&state, now: now) + + // Keep terminal blocking monotonic: once we know auth is rejected (e.g. invalid_grant), + // do not downgrade it to time-based backoff unless auth changes (fingerprint) or we record success. + guard !state.isTerminalBlocked else { return } + + self.clearTerminalState(&state) + + state.transientFailureCount += 1 + let interval = self.transientCooldownInterval(failures: state.transientFailureCount) + state.transientBlockedUntil = now.addingTimeInterval(interval) + state.fingerprintAtFailure = self.currentFingerprint() ?? self.unknownFingerprint + state.lastCredentialsRecheckAt = now + self.persist(state) + } + } + + public static func recordAuthFailure(now: Date = Date()) { + // Legacy shim: treat as terminal auth failure. + self.recordTerminalAuthFailure(now: now) + } + + public static func recordSuccess() { + self.lock.withLock { state in + _ = self.loadIfNeeded(&state, now: Date()) + self.resetState(&state) + self.persist(state) + } + } + + private static func shouldRecheckCredentials(now: Date, state: State) -> Bool { + guard let last = state.lastCredentialsRecheckAt else { return true } + return now.timeIntervalSince(last) >= self.minimumCredentialsRecheckInterval + } + + private static func hasCredentialsChangedSinceFailure(_ state: State) -> Bool { + guard let current = self.currentFingerprint() else { return false } + guard let prior = state.fingerprintAtFailure else { return false } + return current != prior + } + + private static func currentFingerprint() -> AuthFingerprint? { + #if DEBUG + if let override = self.fingerprintProviderOverride { return override() } + #endif + return AuthFingerprint( + keychain: ClaudeOAuthCredentialsStore.currentClaudeKeychainFingerprintWithoutPromptForAuthGate(), + credentialsFile: ClaudeOAuthCredentialsStore.currentCredentialsFileFingerprintWithoutPromptForAuthGate()) + } + + private static func loadIfNeeded(_ state: inout State, now: Date) -> Bool { + state.loaded = true + var didMutate = false + + // Always refresh persisted fields from UserDefaults, even after first load. + // + // This avoids stale state when UserDefaults are modified while the app is running (or during tests), + // while still keeping ephemeral throttling state (like lastCredentialsRecheckAt) in memory. + state.terminalFailureCount = UserDefaults.standard.integer(forKey: self.failureCountKey) + state.transientFailureCount = UserDefaults.standard.integer(forKey: self.transientFailureCountKey) + + if let raw = UserDefaults.standard.object(forKey: self.transientBlockedUntilKey) as? Double { + state.transientBlockedUntil = Date(timeIntervalSince1970: raw) + } + + let legacyBlockedUntil = (UserDefaults.standard.object(forKey: self.blockedUntilKey) as? Double) + .map { Date(timeIntervalSince1970: $0) } + let legacyFailureCount = UserDefaults.standard.integer(forKey: self.failureCountKey) + + if let data = UserDefaults.standard.data(forKey: self.fingerprintKey) { + state.fingerprintAtFailure = (try? JSONDecoder().decode(AuthFingerprint.self, from: data)) + } else { + state.fingerprintAtFailure = nil + } + + if UserDefaults.standard.object(forKey: self.terminalBlockedKey) != nil { + state.isTerminalBlocked = UserDefaults.standard.bool(forKey: self.terminalBlockedKey) + state.terminalReason = UserDefaults.standard.string(forKey: self.terminalReasonKey) + if legacyBlockedUntil != nil { + didMutate = true + } + } else { + // Migration: legacy keys represented a time-based backoff. Migrate to transient backoff (never terminal) + // unless we already have new transient keys persisted. + if UserDefaults.standard.object(forKey: self.transientFailureCountKey) == nil, + UserDefaults.standard.object(forKey: self.transientBlockedUntilKey) == nil, + legacyBlockedUntil != nil || legacyFailureCount > 0 + { + state.isTerminalBlocked = false + state.terminalReason = nil + state.terminalFailureCount = 0 + + if let legacyBlockedUntil, legacyBlockedUntil > now { + state.transientFailureCount = max(legacyFailureCount, 0) + state.transientBlockedUntil = legacyBlockedUntil + } else { + state.transientFailureCount = 0 + state.transientBlockedUntil = nil + } + didMutate = true + } + } + + if state.isTerminalBlocked || state.transientBlockedUntil != nil, state.fingerprintAtFailure == nil { + state.fingerprintAtFailure = self.unknownFingerprint + didMutate = true + } + + if legacyBlockedUntil != nil { + didMutate = true + } + + return didMutate + } + + private static func persist(_ state: State) { + UserDefaults.standard.set(state.terminalFailureCount, forKey: self.failureCountKey) + UserDefaults.standard.set(state.isTerminalBlocked, forKey: self.terminalBlockedKey) + if let reason = state.terminalReason { + UserDefaults.standard.set(reason, forKey: self.terminalReasonKey) + } else { + UserDefaults.standard.removeObject(forKey: self.terminalReasonKey) + } + + UserDefaults.standard.set(state.transientFailureCount, forKey: self.transientFailureCountKey) + if let blockedUntil = state.transientBlockedUntil { + UserDefaults.standard.set(blockedUntil.timeIntervalSince1970, forKey: self.transientBlockedUntilKey) + } else { + UserDefaults.standard.removeObject(forKey: self.transientBlockedUntilKey) + } + + UserDefaults.standard.removeObject(forKey: self.blockedUntilKey) + + if let fingerprint = state.fingerprintAtFailure, + let data = try? JSONEncoder().encode(fingerprint) + { + UserDefaults.standard.set(data, forKey: self.fingerprintKey) + } else { + UserDefaults.standard.removeObject(forKey: self.fingerprintKey) + } + } + + private static func transientCooldownInterval(failures: Int) -> TimeInterval { + guard failures > 0 else { return 0 } + let factor = pow(2.0, Double(failures - 1)) + return min(self.transientBaseInterval * factor, self.transientMaxInterval) + } + + private static func clearTerminalState(_ state: inout State) { + state.terminalFailureCount = 0 + state.isTerminalBlocked = false + state.terminalReason = nil + } + + private static func clearTransientState(_ state: inout State) { + state.transientFailureCount = 0 + state.transientBlockedUntil = nil + } + + private static func resetState(_ state: inout State) { + self.clearTerminalState(&state) + self.clearTransientState(&state) + state.fingerprintAtFailure = nil + state.lastCredentialsRecheckAt = nil + } +} +#else +public enum ClaudeOAuthRefreshFailureGate { + public enum BlockStatus: Equatable, Sendable { + case terminal(reason: String?, failures: Int) + case transient(until: Date, failures: Int) + } + + public static func shouldAttempt(now _: Date = Date()) -> Bool { + true + } + + public static func currentBlockStatus(now _: Date = Date()) -> BlockStatus? { + nil + } + + public static func recordTerminalAuthFailure(now _: Date = Date()) {} + + public static func recordTransientFailure(now _: Date = Date()) {} + + public static func recordAuthFailure(now _: Date = Date()) {} + + public static func recordSuccess() {} + + #if DEBUG + static func setFingerprintProviderOverrideForTesting(_: (() -> Any?)?) {} + public static func resetInMemoryStateForTesting() {} + public static func resetForTesting() {} + #endif +} +#endif diff --git a/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthUsageFetcher.swift b/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthUsageFetcher.swift new file mode 100644 index 0000000..ca7e64d --- /dev/null +++ b/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthUsageFetcher.swift @@ -0,0 +1,324 @@ +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +public enum ClaudeOAuthFetchError: LocalizedError, Sendable { + case unauthorized + case rateLimited(retryAfter: Date?) + case invalidResponse + case serverError(Int, String?) + case networkError(Error) + + public var errorDescription: String? { + switch self { + case .unauthorized: + return "Claude OAuth request unauthorized. Run `claude` to re-authenticate." + case .rateLimited: + return "Claude OAuth usage endpoint is rate limited by Anthropic right now. Wait a few minutes, " + + "then click Refresh. If it keeps happening, run `claude logout && claude login`, then try again." + case .invalidResponse: + return "Claude OAuth response was invalid." + case let .serverError(code, body): + if let body, !body.isEmpty { + let cleaned = body + .replacingOccurrences(of: "\n", with: " ") + .trimmingCharacters(in: .whitespacesAndNewlines) + let shortened = cleaned.count > 400 ? String(cleaned.prefix(400)) + "…" : cleaned + return "Claude OAuth error: HTTP \(code) – \(shortened)" + } + return "Claude OAuth error: HTTP \(code)" + case let .networkError(error): + return "Claude OAuth network error: \(error.localizedDescription)" + } + } +} + +enum ClaudeOAuthUsageFetcher { + private static let baseURL = "https://api.anthropic.com" + private static let usagePath = "/api/oauth/usage" + private static let betaHeader = "oauth-2025-04-20" + private static let fallbackClaudeCodeVersion = "2.1.0" + + static func fetchUsage( + accessToken: String, + detectClaudeVersion: Bool = true) async throws -> OAuthUsageResponse + { + if let blockedUntil = ClaudeOAuthUsageRateLimitGate.blockedUntil() { + throw ClaudeOAuthFetchError.rateLimited(retryAfter: blockedUntil) + } + + guard let url = URL(string: baseURL + usagePath) else { + throw ClaudeOAuthFetchError.invalidResponse + } + + var request = URLRequest(url: url) + request.httpMethod = "GET" + request.timeoutInterval = 30 + request.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization") + request.setValue("application/json", forHTTPHeaderField: "Accept") + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + // OAuth usage endpoint currently requires the beta header. + request.setValue(Self.betaHeader, forHTTPHeaderField: "anthropic-beta") + request.setValue( + Self.claudeCodeUserAgent(detectClaudeVersion: detectClaudeVersion), + forHTTPHeaderField: "User-Agent") + + do { + let response = try await ProviderHTTPClient.shared.response(for: request) + let data = response.data + switch response.statusCode { + case 200: + let usage = try Self.decodeUsageResponse(data) + ClaudeOAuthUsageRateLimitGate.recordSuccess() + return usage + case 401: + throw ClaudeOAuthFetchError.unauthorized + case 429: + let retryAfter = Self.retryAfterDate(from: response.response) + ClaudeOAuthUsageRateLimitGate.recordRateLimit(retryAfter: retryAfter) + throw ClaudeOAuthFetchError.rateLimited( + retryAfter: ClaudeOAuthUsageRateLimitGate.currentBlockedUntil() ?? retryAfter) + case 403: + let body = String(data: data, encoding: .utf8) + throw ClaudeOAuthFetchError.serverError(response.statusCode, body) + default: + let body = String(data: data, encoding: .utf8) + throw ClaudeOAuthFetchError.serverError(response.statusCode, body) + } + } catch let error as ClaudeOAuthFetchError { + throw error + } catch { + throw ClaudeOAuthFetchError.networkError(error) + } + } + + static func decodeUsageResponse(_ data: Data) throws -> OAuthUsageResponse { + let decoder = JSONDecoder() + return try decoder.decode(OAuthUsageResponse.self, from: data) + } + + static func parseISO8601Date(_ string: String?) -> Date? { + guard let string, !string.isEmpty else { return nil } + let formatter = ISO8601DateFormatter() + formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds] + if let date = formatter.date(from: string) { return date } + formatter.formatOptions = [.withInternetDateTime] + return formatter.date(from: string) + } + + private static func retryAfterDate(from response: HTTPURLResponse, now: Date = Date()) -> Date? { + guard let raw = response.value(forHTTPHeaderField: "Retry-After")? + .trimmingCharacters(in: .whitespacesAndNewlines), + !raw.isEmpty + else { return nil } + + if let seconds = TimeInterval(raw), seconds >= 0 { + return now.addingTimeInterval(seconds) + } + + let formatter = DateFormatter() + formatter.locale = Locale(identifier: "en_US_POSIX") + formatter.timeZone = TimeZone(secondsFromGMT: 0) + formatter.dateFormat = "EEE',' dd MMM yyyy HH':'mm':'ss zzz" + return formatter.date(from: raw) + } + + private static func claudeCodeUserAgent( + detectClaudeVersion: Bool, + versionDetector: () -> String? = { ProviderVersionDetector.claudeVersion() }) -> String + { + self.claudeCodeUserAgent(versionString: detectClaudeVersion ? versionDetector() : nil) + } + + private static func claudeCodeUserAgent(versionString: String?) -> String { + let version = self.normalizedClaudeCodeVersion(versionString) ?? self.fallbackClaudeCodeVersion + return "claude-code/\(version)" + } + + private static func normalizedClaudeCodeVersion(_ versionString: String?) -> String? { + guard let raw = versionString?.trimmingCharacters(in: .whitespacesAndNewlines), !raw.isEmpty else { + return nil + } + let token = raw.split(whereSeparator: \.isWhitespace).first.map(String.init) ?? raw + let trimmed = token.trimmingCharacters(in: .whitespacesAndNewlines) + return trimmed.isEmpty ? nil : trimmed + } +} + +struct OAuthUsageResponse: Decodable { + let fiveHour: OAuthUsageWindow? + let sevenDay: OAuthUsageWindow? + let sevenDayOAuthApps: OAuthUsageWindow? + let sevenDayOpus: OAuthUsageWindow? + let sevenDaySonnet: OAuthUsageWindow? + let sevenDayRoutines: OAuthUsageWindow? + let sevenDayRoutinesSourceKey: String? + let iguanaNecktie: OAuthUsageWindow? + let extraUsage: OAuthExtraUsage? + /// Newer shape (superseding the flat `seven_day_*` fields above for scoped weekly + /// windows): a flat list of limit entries, each optionally naming the model it scopes + /// to via `scope.model.display_name` (e.g. "Fable" during a promotional access window). + let limits: [OAuthLimitEntry]? + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: DynamicCodingKey.self) + self.fiveHour = Self.decodeWindow(in: container, keys: ["five_hour"]) + self.sevenDay = Self.decodeWindow(in: container, keys: ["seven_day"]) + self.sevenDayOAuthApps = Self.decodeWindow(in: container, keys: ["seven_day_oauth_apps"]) + self.sevenDayOpus = Self.decodeWindow(in: container, keys: ["seven_day_opus"]) + self.sevenDaySonnet = Self.decodeWindow(in: container, keys: ["seven_day_sonnet"]) + let routines = Self.decodeWindowWithSource(in: container, keys: [ + "seven_day_routines", + "seven_day_claude_routines", + "claude_routines", + "routines", + "routine", + "seven_day_cowork", + "cowork", + ]) + self.sevenDayRoutines = routines.window + self.sevenDayRoutinesSourceKey = routines.sourceKey + self.iguanaNecktie = Self.decodeWindow(in: container, keys: ["iguana_necktie"]) + self.extraUsage = Self.decodeValue(in: container, keys: ["extra_usage"]) + self.limits = Self.decodeValue(in: container, keys: ["limits"]) + } + + private static func decodeWindow( + in container: KeyedDecodingContainer, + keys: [String]) -> OAuthUsageWindow? + { + self.decodeValue(in: container, keys: keys) + } + + private static func decodeWindowWithSource( + in container: KeyedDecodingContainer, + keys: [String]) -> (window: OAuthUsageWindow?, sourceKey: String?) + { + var firstNullKey: String? + for keyName in keys { + guard let key = DynamicCodingKey(stringValue: keyName) else { continue } + guard container.contains(key) else { continue } + if let value = try? container.decodeIfPresent(OAuthUsageWindow.self, forKey: key) { + return (value, keyName) + } + if firstNullKey == nil { + firstNullKey = keyName + } + } + return (nil, firstNullKey) + } + + private static func decodeValue( + in container: KeyedDecodingContainer, + keys: [String]) -> T? + { + for keyName in keys { + guard let key = DynamicCodingKey(stringValue: keyName) else { continue } + if let value = try? container.decodeIfPresent(T.self, forKey: key) { + return value + } + } + return nil + } +} + +private struct DynamicCodingKey: CodingKey { + let stringValue: String + let intValue: Int? + + init?(stringValue: String) { + self.stringValue = stringValue + self.intValue = nil + } + + init?(intValue: Int) { + nil + } +} + +struct OAuthUsageWindow: Decodable { + let utilization: Double? + let resetsAt: String? + + enum CodingKeys: String, CodingKey { + case utilization + case resetsAt = "resets_at" + } +} + +/// A single entry from the `limits` array. `kind`/`group` classify the limit +/// (e.g. `kind: "weekly_scoped"`, `group: "weekly"`); `scope.model.display_name` names the +/// model it applies to when the limit is scoped to one, rather than the whole account. +struct OAuthLimitEntry: Decodable { + let kind: String? + let group: String? + let percent: Double? + let resetsAt: String? + let scope: OAuthLimitScope? + let isActive: Bool? + + enum CodingKeys: String, CodingKey { + case kind + case group + case percent + case resetsAt = "resets_at" + case scope + case isActive = "is_active" + } +} + +struct OAuthLimitScope: Decodable { + let model: OAuthLimitScopeModel? +} + +struct OAuthLimitScopeModel: Decodable { + let id: String? + let displayName: String? + + enum CodingKeys: String, CodingKey { + case id + case displayName = "display_name" + } +} + +struct OAuthExtraUsage: Decodable { + let isEnabled: Bool? + let monthlyLimit: Double? + let usedCredits: Double? + let utilization: Double? + let currency: String? + + enum CodingKeys: String, CodingKey { + case isEnabled = "is_enabled" + case monthlyLimit = "monthly_limit" + case usedCredits = "used_credits" + case utilization + case currency + } +} + +#if DEBUG +extension ClaudeOAuthUsageFetcher { + static func _decodeUsageResponseForTesting(_ data: Data) throws -> OAuthUsageResponse { + try self.decodeUsageResponse(data) + } + + static func _userAgentForTesting(versionString: String?) -> String { + self.claudeCodeUserAgent(versionString: versionString) + } + + static func _userAgentForTesting( + detectClaudeVersion: Bool, + versionDetector: () -> String?) -> String + { + self.claudeCodeUserAgent( + detectClaudeVersion: detectClaudeVersion, + versionDetector: versionDetector) + } + + static func _retryAfterDateForTesting(from response: HTTPURLResponse, now: Date) -> Date? { + self.retryAfterDate(from: response, now: now) + } +} +#endif diff --git a/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthUsageRateLimitGate.swift b/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthUsageRateLimitGate.swift new file mode 100644 index 0000000..01ee9ec --- /dev/null +++ b/Sources/CodexBarCore/Providers/Claude/ClaudeOAuth/ClaudeOAuthUsageRateLimitGate.swift @@ -0,0 +1,46 @@ +import Foundation + +enum ClaudeOAuthUsageRateLimitGate { + private static let blockedUntilKey = "claudeOAuthUsageRateLimitBlockedUntilV1" + private static let defaultCooldown: TimeInterval = 60 * 5 + + static func blockedUntil( + interaction: ProviderInteraction = ProviderInteractionContext.current, + now: Date = Date()) -> Date? + { + guard interaction != .userInitiated else { return nil } + return self.currentBlockedUntil(now: now) + } + + static func currentBlockedUntil(now: Date = Date()) -> Date? { + guard let raw = UserDefaults.standard.object(forKey: self.blockedUntilKey) as? Double else { + return nil + } + + let blockedUntil = Date(timeIntervalSince1970: raw) + guard blockedUntil > now else { + UserDefaults.standard.removeObject(forKey: self.blockedUntilKey) + return nil + } + return blockedUntil + } + + static func recordRateLimit(retryAfter: Date?, now: Date = Date()) { + let blockedUntil = if let retryAfter, retryAfter > now { + retryAfter + } else { + now.addingTimeInterval(self.defaultCooldown) + } + UserDefaults.standard.set(blockedUntil.timeIntervalSince1970, forKey: self.blockedUntilKey) + } + + static func recordSuccess() { + UserDefaults.standard.removeObject(forKey: self.blockedUntilKey) + } + + #if DEBUG + static func resetForTesting() { + UserDefaults.standard.removeObject(forKey: self.blockedUntilKey) + } + #endif +} diff --git a/Sources/CodexBarCore/Providers/Claude/ClaudePlan.swift b/Sources/CodexBarCore/Providers/Claude/ClaudePlan.swift new file mode 100644 index 0000000..2f58530 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Claude/ClaudePlan.swift @@ -0,0 +1,179 @@ +import Foundation + +public enum ClaudePlan: String, CaseIterable, Sendable { + case max + case pro + case team + case enterprise + case ultra + + public var brandedLoginMethod: String { + switch self { + case .max: + "Claude Max" + case .pro: + "Claude Pro" + case .team: + "Claude Team" + case .enterprise: + "Claude Enterprise" + case .ultra: + "Claude Ultra" + } + } + + /// Branded label including the Max usage multiplier when the rate-limit tier carries one. + public func brandedLoginMethod(rateLimitTier: String?) -> String { + guard self == .max, let multiplier = Self.maxUsageMultiplier(rateLimitTier: rateLimitTier) else { + return self.brandedLoginMethod + } + return "\(self.brandedLoginMethod) \(multiplier)" + } + + public var compactLoginMethod: String { + switch self { + case .max: + "Max" + case .pro: + "Pro" + case .team: + "Team" + case .enterprise: + "Enterprise" + case .ultra: + "Ultra" + } + } + + public var countsAsSubscription: Bool { + switch self { + case .max, .pro, .team, .ultra: + true + case .enterprise: + false + } + } + + public static func fromOAuthRateLimitTier(_ rateLimitTier: String?) -> Self? { + self.fromRateLimitTier(rateLimitTier) + } + + public static func fromOAuthCredentials(subscriptionType: String?, rateLimitTier: String?) -> Self? { + self.fromCompatibilityLoginMethod(subscriptionType) + ?? self.fromOAuthRateLimitTier(rateLimitTier) + } + + public static func fromWebAccount(rateLimitTier: String?, billingType: String?) -> Self? { + if let plan = self.fromRateLimitTier(rateLimitTier) { + return plan + } + + let tier = Self.normalized(rateLimitTier) + let billing = Self.normalized(billingType) + if billing.contains("stripe"), tier.contains("claude") { + return .pro + } + return nil + } + + public static func fromCompatibilityLoginMethod(_ loginMethod: String?) -> Self? { + let words = Self.normalizedWords(loginMethod) + if words.isEmpty { + return nil + } + if words.contains("max") { + return .max + } + if words.contains("pro") { + return .pro + } + if words.contains("team") { + return .team + } + if words.contains("enterprise") { + return .enterprise + } + if words.contains("ultra") { + return .ultra + } + return nil + } + + public static func oauthLoginMethod(rateLimitTier: String?) -> String? { + self.fromOAuthRateLimitTier(rateLimitTier)?.brandedLoginMethod(rateLimitTier: rateLimitTier) + } + + public static func oauthLoginMethod(subscriptionType: String?, rateLimitTier: String?) -> String? { + self.fromOAuthCredentials( + subscriptionType: subscriptionType, + rateLimitTier: rateLimitTier)?.brandedLoginMethod(rateLimitTier: rateLimitTier) + } + + public static func webLoginMethod(rateLimitTier: String?, billingType: String?) -> String? { + self.fromWebAccount( + rateLimitTier: rateLimitTier, + billingType: billingType)?.brandedLoginMethod(rateLimitTier: rateLimitTier) + } + + public static func cliCompatibilityLoginMethod(_ loginMethod: String?) -> String? { + guard let loginMethod = loginMethod?.trimmingCharacters(in: .whitespacesAndNewlines), + !loginMethod.isEmpty + else { + return nil + } + + if let plan = self.fromCompatibilityLoginMethod(loginMethod) { + return plan.compactLoginMethod + } + + return loginMethod + } + + public static func isSubscriptionLoginMethod(_ loginMethod: String?) -> Bool { + self.fromCompatibilityLoginMethod(loginMethod)?.countsAsSubscription ?? false + } + + private static func fromRateLimitTier(_ rateLimitTier: String?) -> Self? { + let tier = Self.normalized(rateLimitTier) + if tier.contains("max") { + return .max + } + if tier.contains("pro") { + return .pro + } + if tier.contains("team") { + return .team + } + if tier.contains("enterprise") { + return .enterprise + } + return nil + } + + private static func maxUsageMultiplier(rateLimitTier: String?) -> String? { + let words = Self.normalizedWords(rateLimitTier) + guard let maxIndex = words.firstIndex(of: Self.max.rawValue), + words.indices.contains(maxIndex + 1) + else { + return nil + } + + let multiplier = words[maxIndex + 1] + guard multiplier.last == "x", Int(multiplier.dropLast()) != nil else { + return nil + } + return multiplier + } + + private static func normalized(_ text: String?) -> String { + text? + .trimmingCharacters(in: .whitespacesAndNewlines) + .lowercased() ?? "" + } + + private static func normalizedWords(_ text: String?) -> [String] { + self.normalized(text) + .split(whereSeparator: { !$0.isLetter && !$0.isNumber }) + .map(String.init) + } +} diff --git a/Sources/CodexBarCore/Providers/Claude/ClaudeProbeSessionArtifactCleaner.swift b/Sources/CodexBarCore/Providers/Claude/ClaudeProbeSessionArtifactCleaner.swift new file mode 100644 index 0000000..fa7cce3 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Claude/ClaudeProbeSessionArtifactCleaner.swift @@ -0,0 +1,105 @@ +import Foundation + +enum ClaudeProbeSessionArtifactCleaner { + private static let log = CodexBarLog.logger(LogCategories.claudeProbe) + private static let maxProjectDirectoryNameLength = 200 + + @discardableResult + static func cleanupProbeSessionArtifacts( + probeDirectory: URL = ClaudeStatusProbe.probeWorkingDirectoryURL(), + environment: [String: String] = ProcessInfo.processInfo.environment, + fileManager fm: FileManager = .default) -> [URL] + { + let projectDirectoryName = self.claudeProjectDirectoryName(for: probeDirectory) + var visitedDirectories = Set() + var removedFiles: [URL] = [] + + for root in self.claudeConfigRoots(environment: environment, fileManager: fm) { + let projectsRoot = root.appendingPathComponent("projects", isDirectory: true) + let directories = [projectsRoot.appendingPathComponent(projectDirectoryName, isDirectory: true)] + + for directory in directories where visitedDirectories.insert(directory.path).inserted { + guard let entries = try? fm.contentsOfDirectory( + at: directory, + includingPropertiesForKeys: [.isRegularFileKey], + options: [.skipsHiddenFiles]) + else { continue } + + for entry in entries where entry.pathExtension == "jsonl" { + let values = try? entry.resourceValues(forKeys: [.isRegularFileKey]) + guard values?.isRegularFile == true else { continue } + do { + try fm.removeItem(at: entry) + removedFiles.append(entry) + } catch { + Self.log.debug( + "Claude probe session artifact cleanup skipped file", + metadata: ["error": error.localizedDescription]) + } + } + + if (try? fm.contentsOfDirectory(atPath: directory.path).isEmpty) == true { + try? fm.removeItem(at: directory) + } + } + } + + return removedFiles + } + + static func claudeProjectDirectoryName(for directory: URL) -> String { + let path = directory.path.precomposedStringWithCanonicalMapping + let sanitized = String(path.utf16.map { codeUnit in + switch codeUnit { + case 48...57, 65...90, 97...122: + Character(UnicodeScalar(codeUnit)!) + default: + "-" + } + }) + + guard sanitized.count > self.maxProjectDirectoryNameLength else { return sanitized } + return "\(sanitized.prefix(self.maxProjectDirectoryNameLength))-\(self.javaScriptHashBase36(path))" + } + + private static func javaScriptHashBase36(_ string: String) -> String { + var hash: Int32 = 0 + for codeUnit in string.utf16 { + hash = hash &* 31 &+ Int32(truncatingIfNeeded: codeUnit) + } + + let magnitude = hash < 0 ? -Int64(hash) : Int64(hash) + return String(magnitude, radix: 36) + } + + private static func claudeConfigRoots( + environment: [String: String], + fileManager fm: FileManager) -> [URL] + { + var roots: [URL] = [] + var seen = Set() + + func append(_ url: URL) { + let standardized = url.standardizedFileURL + guard seen.insert(standardized.path).inserted else { return } + roots.append(standardized) + } + + if let raw = environment["CLAUDE_CONFIG_DIR"] { + for part in raw.split(separator: ",") { + let path = part.trimmingCharacters(in: .whitespacesAndNewlines) + guard !path.isEmpty else { continue } + append(URL(fileURLWithPath: path)) + } + } + + let home = environment["HOME"].flatMap { $0.isEmpty ? nil : $0 } ?? NSHomeDirectory() + append(URL(fileURLWithPath: home).appendingPathComponent(".claude", isDirectory: true)) + append(URL(fileURLWithPath: home).appendingPathComponent(".config/claude", isDirectory: true)) + + if roots.isEmpty { + append(fm.homeDirectoryForCurrentUser.appendingPathComponent(".claude", isDirectory: true)) + } + return roots + } +} diff --git a/Sources/CodexBarCore/Providers/Claude/ClaudeProviderDescriptor.swift b/Sources/CodexBarCore/Providers/Claude/ClaudeProviderDescriptor.swift new file mode 100644 index 0000000..1868f5c --- /dev/null +++ b/Sources/CodexBarCore/Providers/Claude/ClaudeProviderDescriptor.swift @@ -0,0 +1,679 @@ +import Foundation + +public enum ClaudeProviderDescriptor { + public static let descriptor: ProviderDescriptor = Self.makeDescriptor() + + static func makeDescriptor() -> ProviderDescriptor { + ProviderDescriptor( + id: .claude, + metadata: ProviderMetadata( + id: .claude, + displayName: "Claude", + sessionLabel: "Session", + weeklyLabel: "Weekly", + opusLabel: "Sonnet", + supportsOpus: true, + supportsCredits: false, + creditsHint: "", + toggleTitle: "Show Claude Code usage", + cliName: "claude", + defaultEnabled: false, + isPrimaryProvider: true, + usesAccountFallback: false, + browserCookieOrder: ProviderBrowserCookieDefaults.defaultImportOrder, + dashboardURL: "https://console.anthropic.com/settings/billing", + subscriptionDashboardURL: "https://claude.ai/settings/usage", + changelogURL: "https://github.com/anthropics/claude-code/releases", + statusPageURL: "https://status.claude.com/"), + branding: ProviderBranding( + iconStyle: .claude, + iconResourceName: "ProviderIcon-claude", + color: ProviderColor(red: 204 / 255, green: 124 / 255, blue: 94 / 255)), + tokenCost: ProviderTokenCostConfig( + supportsTokenCost: true, + noDataMessage: self.noDataMessage), + fetchPlan: ProviderFetchPlan( + sourceModes: [.auto, .api, .web, .cli, .oauth], + pipeline: ProviderFetchPipeline(resolveStrategies: self.resolveStrategies)), + cli: ProviderCLIConfig( + name: "claude", + versionDetector: { browserDetection in + ClaudeUsageFetcher(browserDetection: browserDetection).detectVersion() + })) + } + + private static func resolveStrategies(context: ProviderFetchContext) async -> [any ProviderFetchStrategy] { + if context.sourceMode == .api || self.hasAutoAdminAPIKey(context: context) { + return [ClaudeAdminAPIFetchStrategy()] + } + if ClaudeAdminAPIFetchStrategy.isSelectedAdminAPIAccount(context: context) { + return [ClaudeAdminAPIFetchStrategy()] + } + + let planningInput = Self.makePlanningInput(context: context) + let plan = ClaudeSourcePlanner.resolve(input: planningInput) + let manualCookieHeader = Self.manualCookieHeader(from: context) + + return plan.orderedSteps.map { step in + let strategy: any ProviderFetchStrategy = switch step.dataSource { + case .api: + ClaudeAdminAPIFetchStrategy() + case .oauth: + ClaudeOAuthFetchStrategy() + case .web: + ClaudeWebFetchStrategy(browserDetection: context.browserDetection) + case .cli: + ClaudeCLIFetchStrategy( + useWebExtras: context.runtime == .app + && planningInput.webExtrasEnabled, + manualCookieHeader: manualCookieHeader, + browserDetection: context.browserDetection, + hasWebFallback: planningInput.hasWebSession) + case .auto: + fatalError("Planner must not emit .auto as an executable step.") + } + return ClaudePlannedFetchStrategy(base: strategy, plannedStep: step) + } + } + + private static func hasAutoAdminAPIKey(context: ProviderFetchContext) -> Bool { + context.sourceMode == .auto && ClaudeAdminAPISettingsReader.apiKey(environment: context.env) != nil + } + + private static func makePlanningInput(context: ProviderFetchContext) -> ClaudeSourcePlanningInput { + let webExtrasEnabled = context.settings?.claude?.webExtrasEnabled ?? false + let needsOAuthAvailability = context.runtime == .app && context.sourceMode == .auto + let hasWebSession = Self.hasPlausibleWebSession(context: context) + + return ClaudeSourcePlanningInput( + runtime: context.runtime, + selectedDataSource: Self.sourceDataSource(from: context.sourceMode), + webExtrasEnabled: webExtrasEnabled, + hasWebSession: hasWebSession, + hasCLI: ClaudeCLIResolver.isAvailable(environment: context.env), + hasOAuthCredentials: needsOAuthAvailability && ClaudeOAuthPlanningAvailability.isAvailable( + runtime: context.runtime, + sourceMode: context.sourceMode, + environment: context.env)) + } + + private static func hasPlausibleWebSession(context: ProviderFetchContext) -> Bool { + switch context.sourceMode { + case .api, .oauth, .cli: + return false + case .web: + // Explicit web performs its cookie/session work inside the bounded fetch. + return context.settings?.claude?.cookieSource != .off + case .auto: + break + } + + guard ClaudeWebFetchStrategy.isSupportedOnCurrentPlatform else { return false } + + switch context.settings?.claude?.cookieSource { + case .off?: + return false + case .manual?: + return ClaudeWebFetchStrategy.hasManualSessionKey(context: context) + case .auto?, nil: + // Browser/Keychain inspection can block. Keep planning synchronous and let the web step + // perform the bounded availability check if app-auto actually reaches its last fallback. + // CLI auto continues to perform its real session import inside the bounded web fetch. + return true + } + } + + private static func manualCookieHeader(from context: ProviderFetchContext) -> String? { + guard context.settings?.claude?.cookieSource == .manual else { return nil } + return CookieHeaderNormalizer.normalize(context.settings?.claude?.manualCookieHeader) + } + + private static func noDataMessage() -> String { + "No Claude usage logs found in ~/.config/claude/projects, ~/.claude/projects, " + + "or Claude Desktop sessions." + } + + public static func resolveUsageStrategy( + selectedDataSource: ClaudeUsageDataSource, + webExtrasEnabled: Bool, + hasWebSession: Bool, + hasCLI: Bool, + hasOAuthCredentials: Bool) -> ClaudeUsageStrategy + { + let plan = ClaudeSourcePlanner.resolve(input: ClaudeSourcePlanningInput( + runtime: .app, + selectedDataSource: selectedDataSource, + webExtrasEnabled: webExtrasEnabled, + hasWebSession: hasWebSession, + hasCLI: hasCLI, + hasOAuthCredentials: hasOAuthCredentials)) + return plan.compatibilityStrategy ?? ClaudeUsageStrategy(dataSource: selectedDataSource, useWebExtras: false) + } + + private static func sourceDataSource(from mode: ProviderSourceMode) -> ClaudeUsageDataSource { + switch mode { + case .auto: + .auto + case .api: + .api + case .web: + .web + case .cli: + .cli + case .oauth: + .oauth + } + } +} + +public struct ClaudeUsageStrategy: Equatable, Sendable { + public let dataSource: ClaudeUsageDataSource + public let useWebExtras: Bool +} + +public enum ClaudeOAuthPlanningAvailability { + public static func isAvailable( + runtime: ProviderRuntime, + sourceMode: ProviderSourceMode, + environment: [String: String]) -> Bool + { + ClaudeOAuthFetchStrategy.isPlausiblyAvailable( + runtime: runtime, + sourceMode: sourceMode, + environment: environment) + } +} + +private struct ClaudePlannedFetchStrategy: ProviderFetchStrategy { + let base: any ProviderFetchStrategy + let plannedStep: ClaudeFetchPlanStep + + var id: String { + self.base.id + } + + var kind: ProviderFetchKind { + self.base.kind + } + + func isAvailable(_ context: ProviderFetchContext) async -> Bool { + guard context.sourceMode == .auto else { + return await self.base.isAvailable(context) + } + guard self.plannedStep.isPlausiblyAvailable else { return false } + if self.plannedStep.dataSource == .cli || + (context.runtime == .app && self.plannedStep.dataSource == .web) + { + return await self.base.isAvailable(context) + } + return true + } + + func fetch(_ context: ProviderFetchContext) async throws -> ProviderFetchResult { + try await self.base.fetch(context) + } + + func shouldFallback(on error: Error, context: ProviderFetchContext) -> Bool { + self.base.shouldFallback(on: error, context: context) + } +} + +struct ClaudeAdminAPIFetchStrategy: ProviderFetchStrategy { + let id: String = "claude.admin-api" + let kind: ProviderFetchKind = .apiToken + let usageFetcher: @Sendable (String) async throws -> ClaudeAdminAPIUsageSnapshot + + init( + usageFetcher: @escaping @Sendable (String) async throws -> ClaudeAdminAPIUsageSnapshot = { apiKey in + try await ClaudeAdminAPIUsageFetcher.fetchUsage(apiKey: apiKey) + }) + { + self.usageFetcher = usageFetcher + } + + static func isSelectedAdminAPIAccount(context: ProviderFetchContext) -> Bool { + guard context.selectedTokenAccountID != nil else { return false } + return self.resolveToken(environment: context.env) != nil + } + + func isAvailable(_ context: ProviderFetchContext) async -> Bool { + Self.resolveToken(environment: context.env) != nil + } + + func fetch(_ context: ProviderFetchContext) async throws -> ProviderFetchResult { + guard let apiKey = Self.resolveToken(environment: context.env) else { + throw ClaudeAdminAPISettingsError.missingToken + } + let usage = try await self.usageFetcher(apiKey) + return self.makeResult( + usage: usage.toUsageSnapshot(), + sourceLabel: "admin-api") + } + + func shouldFallback(on _: Error, context: ProviderFetchContext) -> Bool { + context.runtime == .app && + context.sourceMode == .auto && + !Self.isSelectedAdminAPIAccount(context: context) + } + + private static func resolveToken(environment: [String: String]) -> String? { + ProviderTokenResolver.claudeAdminAPIToken(environment: environment) + } +} + +struct ClaudeOAuthFetchStrategy: ProviderFetchStrategy { + let id: String = "claude.oauth" + let kind: ProviderFetchKind = .oauth + + #if DEBUG + @TaskLocal static var nonInteractiveCredentialRecordOverride: ClaudeOAuthCredentialRecord? + @TaskLocal static var claudeCLIAvailableOverride: Bool? + #endif + + private func loadNonInteractiveCredentialRecord(environment: [String: String]) -> ClaudeOAuthCredentialRecord? { + #if DEBUG + if let override = Self.nonInteractiveCredentialRecordOverride { + return override + } + #endif + + return try? ClaudeOAuthCredentialsStore.loadRecord( + environment: environment, + allowKeychainPrompt: false, + respectKeychainPromptCooldown: true, + allowClaudeKeychainRepairWithoutPrompt: false) + } + + private func isClaudeCLIAvailable(environment: [String: String]) -> Bool { + #if DEBUG + if let override = Self.claudeCLIAvailableOverride { + return override + } + #endif + return ClaudeCLIResolver.isAvailable(environment: environment) + } + + static func isPlausiblyAvailable( + runtime: ProviderRuntime, + sourceMode: ProviderSourceMode, + environment: [String: String]) -> Bool + { + let hasEnvironmentOAuthToken = !(environment[ClaudeOAuthCredentialsStore.environmentTokenKey]? + .trimmingCharacters(in: .whitespacesAndNewlines) + .isEmpty ?? true) + if hasEnvironmentOAuthToken { + return true + } + + let strategy = ClaudeOAuthFetchStrategy() + let nonInteractiveRecord = strategy.loadNonInteractiveCredentialRecord(environment: environment) + let nonInteractiveCredentials = nonInteractiveRecord?.credentials + let hasRequiredScopeWithoutPrompt = nonInteractiveCredentials?.scopes.contains("user:profile") == true + if hasRequiredScopeWithoutPrompt, nonInteractiveCredentials?.isExpired == false { + return true + } + + let claudeCLIAvailable = strategy.isClaudeCLIAvailable(environment: environment) + + if let nonInteractiveRecord, hasRequiredScopeWithoutPrompt, nonInteractiveRecord.credentials.isExpired { + switch nonInteractiveRecord.owner { + case .codexbar: + let refreshToken = nonInteractiveRecord.credentials.refreshToken? + .trimmingCharacters(in: .whitespacesAndNewlines) ?? "" + if sourceMode == .auto { + return !refreshToken.isEmpty + } + return true + case .claudeCLI: + guard sourceMode == .auto else { return true } + guard claudeCLIAvailable else { return false } + guard ProviderInteractionContext.current == .background else { return true } + return !Self.hasMcpOAuthOnlyClaudeKeychainPayload(environment: environment) + case .environment: + return sourceMode != .auto + } + } + + guard sourceMode == .auto else { return true } + + let fallbackPromptMode = ClaudeOAuthKeychainPromptPreference.securityFrameworkFallbackMode() + let promptPolicyApplicable = ClaudeOAuthKeychainPromptPreference.isApplicable() + if ProviderInteractionContext.current == .userInitiated { + _ = ClaudeOAuthKeychainAccessGate.clearDenied() + } + + let shouldAllowStartupBootstrap = runtime == .app && + ProviderRefreshContext.current == .startup && + ProviderInteractionContext.current == .background && + fallbackPromptMode == .onlyOnUserAction && + !ClaudeOAuthCredentialsStore.hasCachedCredentials(environment: environment) + if shouldAllowStartupBootstrap { + return ClaudeOAuthKeychainAccessGate.shouldAllowPrompt() + } + + if promptPolicyApplicable, + !ClaudeOAuthKeychainAccessGate.shouldAllowPrompt() + { + return false + } + return ClaudeOAuthCredentialsStore.hasClaudeKeychainCredentialsWithoutPrompt() + } + + private static func hasMcpOAuthOnlyClaudeKeychainPayload(environment: [String: String]) -> Bool { + ClaudeOAuthCredentialsStore.isMcpOAuthOnlyClaudeKeychainPayloadPresent( + interaction: ProviderInteractionContext.current, + environment: environment) + } + + func isAvailable(_ context: ProviderFetchContext) async -> Bool { + Self.isPlausiblyAvailable( + runtime: context.runtime, + sourceMode: context.sourceMode, + environment: context.env) + } + + func fetch(_ context: ProviderFetchContext) async throws -> ProviderFetchResult { + let fetcher = ClaudeUsageFetcher( + browserDetection: context.browserDetection, + environment: context.env, + runtime: context.runtime, + dataSource: .oauth, + oauthKeychainPromptCooldownEnabled: context.sourceMode == .auto, + allowBackgroundDelegatedRefresh: false, + allowStartupBootstrapPrompt: context.runtime == .app && + (context.sourceMode == .auto || context.sourceMode == .oauth), + useWebExtras: false) + let usage = try await fetcher.loadLatestUsage(model: "sonnet") + return ProviderFetchResult( + usage: Self.snapshot(from: usage), + credits: nil, + dashboard: nil, + sourceLabel: "oauth", + strategyID: self.id, + strategyKind: self.kind, + claudeOAuthKeychainPersistentRefHash: usage.oauthKeychainPersistentRefHash, + claudeOAuthHistoryOwnerIdentifier: usage.oauthHistoryOwnerIdentifier, + claudeOAuthKeychainCredentialMismatch: usage.oauthKeychainCredentialMismatch, + claudeOAuthKeychainCredentialAbsent: usage.oauthKeychainCredentialAbsent, + claudeOAuthKeychainCredentialUnavailable: usage.oauthKeychainCredentialUnavailable) + } + + func shouldFallback(on _: Error, context: ProviderFetchContext) -> Bool { + // In Auto mode, fall back to the next strategy (cli/web) if OAuth fails (e.g. user cancels keychain prompt + // or auth breaks). + context.runtime == .app && context.sourceMode == .auto + } + + fileprivate static func snapshot(from usage: ClaudeUsageSnapshot) -> UsageSnapshot { + let identity = ProviderIdentitySnapshot( + providerID: .claude, + accountEmail: usage.accountEmail, + accountOrganization: usage.accountOrganization, + loginMethod: usage.loginMethod) + let primary = usage.primaryWindowKind == .spendLimit ? nil : usage.primary + return UsageSnapshot( + primary: primary, + secondary: usage.secondary, + tertiary: usage.opus, + extraRateWindows: usage.extraRateWindows.isEmpty ? nil : usage.extraRateWindows, + providerCost: usage.providerCost, + updatedAt: usage.updatedAt, + identity: identity) + } + + static func _snapshotForTesting(from usage: ClaudeUsageSnapshot) -> UsageSnapshot { + self.snapshot(from: usage) + } +} + +private final class ClaudeWebFetchDeadlineState: @unchecked Sendable { + private let lock = NSLock() + private var deadline: ContinuousClock.Instant? + + func remainingBudget( + fullBudget: Duration, + now: ContinuousClock.Instant) -> Duration + { + self.lock.lock() + defer { self.lock.unlock() } + + let deadline: ContinuousClock.Instant + if let existingDeadline = self.deadline { + deadline = existingDeadline + } else { + deadline = now.advanced(by: fullBudget) + self.deadline = deadline + } + return max(.zero, now.duration(to: deadline)) + } +} + +struct ClaudeWebFetchStrategy: ProviderFetchStrategy { + typealias UsageLoader = @Sendable (ProviderFetchContext) async throws -> ClaudeUsageSnapshot + typealias DeadlineNow = @Sendable () -> ContinuousClock.Instant + + #if DEBUG + @TaskLocal static var availabilityProbeOverrideForTesting: + (@Sendable (ProviderFetchContext, BrowserDetection) -> Bool)? + @TaskLocal static var usageLoaderOverrideForTesting: UsageLoader? + #endif + + let id: String = "claude.web" + let kind: ProviderFetchKind = .web + let browserDetection: BrowserDetection + private let usageLoader: UsageLoader? + private let deadlineState: ClaudeWebFetchDeadlineState + private let deadlineNow: DeadlineNow + + init( + browserDetection: BrowserDetection, + usageLoader: UsageLoader? = nil, + deadlineNow: @escaping DeadlineNow = { ContinuousClock.now }) + { + self.browserDetection = browserDetection + self.usageLoader = usageLoader + self.deadlineState = ClaudeWebFetchDeadlineState() + self.deadlineNow = deadlineNow + } + + func isAvailable(_ context: ProviderFetchContext) async -> Bool { + let appAutoRemainingBudget: Duration? + if context.runtime == .app, context.sourceMode == .auto { + guard let fullBudget = Self.timeoutDuration(context.webTimeout) else { return false } + let remainingBudget = self.deadlineState.remainingBudget( + fullBudget: fullBudget, + now: self.deadlineNow()) + guard remainingBudget > .zero else { return false } + appAutoRemainingBudget = remainingBudget + } else { + appAutoRemainingBudget = nil + } + + return switch context.settings?.claude?.cookieSource { + case .off?: + false + case .manual?: + Self.hasManualSessionKey(context: context) + case .auto?, nil: + if let appAutoRemainingBudget { + await Self.hasBrowserSessionKey(context: context, before: appAutoRemainingBudget) + } else { + // Explicit web and CLI auto perform the real browser import inside the bounded fetch. + true + } + } + } + + func fetch(_ context: ProviderFetchContext) async throws -> ProviderFetchResult { + let usage = try await self.loadUsage(before: context.webTimeout, context: context) + return self.makeResult( + usage: ClaudeOAuthFetchStrategy.snapshot(from: usage), + sourceLabel: "web") + } + + func shouldFallback(on error: Error, context: ProviderFetchContext) -> Bool { + guard context.sourceMode == .auto else { return false } + guard !Task.isCancelled, + !(error is CancellationError), + (error as? URLError)?.code != .cancelled + else { + return false + } + // In CLI runtime auto mode, web comes before CLI so fallback is required. + // In app runtime auto mode, web is terminal and should surface its concrete error. + return context.runtime == .cli + } + + fileprivate static func hasManualSessionKey(context: ProviderFetchContext) -> Bool { + ClaudeWebAPIFetcher.hasSessionKey(cookieHeader: self.manualCookieHeader(from: context)) + } + + fileprivate static func hasBrowserSessionKey( + context: ProviderFetchContext, + before timeout: Duration) async -> Bool + { + let browserDetection = context.browserDetection + let sourceTask = Task { + #if DEBUG + if let override = Self.availabilityProbeOverrideForTesting { + return override(context, browserDetection) + } + #endif + return ClaudeWebAPIFetcher.hasSessionKey(browserDetection: browserDetection) + } + let race = BoundedTaskJoin(sourceTask: sourceTask) + switch await race.value(joinGrace: timeout) { + case let .value(isAvailable): + return isAvailable + case .failure, .timedOut: + return false + } + } + + private static func manualCookieHeader(from context: ProviderFetchContext) -> String? { + guard context.settings?.claude?.cookieSource == .manual else { return nil } + return CookieHeaderNormalizer.normalize(context.settings?.claude?.manualCookieHeader) + } + + private func loadUsage( + before timeout: TimeInterval, + context: ProviderFetchContext) async throws -> ClaudeUsageSnapshot + { + guard let timeoutDuration = Self.timeoutDuration(timeout) else { + throw ClaudeWebFetchStrategyError.invalidTimeout + } + let remainingBudget = self.deadlineState.remainingBudget( + fullBudget: timeoutDuration, + now: self.deadlineNow()) + guard remainingBudget > .zero else { + try Task.checkCancellation() + throw ClaudeWebFetchStrategyError.timedOut(seconds: timeout) + } + let sourceTask = Task { + if let usageLoader = self.usageLoader { + return try await usageLoader(context) + } + #if DEBUG + if let usageLoader = Self.usageLoaderOverrideForTesting { + return try await usageLoader(context) + } + #endif + let fetcher = ClaudeUsageFetcher( + browserDetection: self.browserDetection, + dataSource: .web, + useWebExtras: false, + manualCookieHeader: Self.manualCookieHeader(from: context), + webOrganizationID: context.settings?.claude?.organizationID) + return try await fetcher.loadLatestUsage(model: "sonnet") + } + let race = BoundedTaskJoin(sourceTask: sourceTask) + switch await race.value(joinGrace: remainingBudget) { + case let .value(usage): + try Task.checkCancellation() + return usage + case let .failure(error): + throw error + case .timedOut: + try Task.checkCancellation() + throw ClaudeWebFetchStrategyError.timedOut(seconds: timeout) + } + } + + private static func timeoutDuration(_ timeout: TimeInterval) -> Duration? { + guard timeout.isFinite, + timeout >= 0, + timeout <= TimeInterval(Int64.max) + else { + return nil + } + return .seconds(timeout) + } + + fileprivate static var isSupportedOnCurrentPlatform: Bool { + #if os(macOS) + true + #else + false + #endif + } +} + +public enum ClaudeWebFetchStrategyError: LocalizedError, Equatable, Sendable { + case invalidTimeout + case timedOut(seconds: TimeInterval) + + public var errorDescription: String? { + switch self { + case .invalidTimeout: + "Claude web usage fetch timeout must be a finite, nonnegative value within the supported range." + case let .timedOut(seconds): + "Claude web usage fetch timed out after \(seconds.formatted()) seconds." + } + } +} + +struct ClaudeCLIFetchStrategy: ProviderFetchStrategy { + let id: String = "claude.cli" + let kind: ProviderFetchKind = .cli + let useWebExtras: Bool + let manualCookieHeader: String? + let browserDetection: BrowserDetection + let hasWebFallback: Bool + + func isAvailable(_ context: ProviderFetchContext) async -> Bool { + // The interactive Claude REPL can open browser OAuth when it starts logged out. CLI runtime and background + // app Auto refreshes must establish authentication through the non-interactive status command first. + let requiresAuthPreflight = context.runtime == .cli || ( + context.runtime == .app && + context.sourceMode == .auto && + ProviderInteractionContext.current == .background) + guard requiresAuthPreflight else { return true } + guard let binary = ClaudeCLIResolver.resolvedBinaryPath(environment: context.env) else { return false } + return await ClaudeCLIAuthStatusProbe.isLoggedIn(binary: binary, environment: context.env) + } + + func fetch(_ context: ProviderFetchContext) async throws -> ProviderFetchResult { + let keepAlive = context.settings?.debugKeepCLISessionsAlive ?? false + let fetcher = ClaudeUsageFetcher( + browserDetection: browserDetection, + environment: context.env, + dataSource: .cli, + useWebExtras: self.useWebExtras, + manualCookieHeader: self.manualCookieHeader, + webOrganizationID: context.settings?.claude?.organizationID, + keepCLISessionsAlive: keepAlive) + let usage = try await fetcher.loadLatestUsage(model: "sonnet") + return self.makeResult( + usage: ClaudeOAuthFetchStrategy.snapshot(from: usage), + sourceLabel: "claude") + } + + func shouldFallback(on error: Error, context: ProviderFetchContext) -> Bool { + guard context.runtime == .app, context.sourceMode == .auto else { return false } + guard !ClaudeStatusProbe.isSubscriptionQuotaUnavailableDescription(error.localizedDescription) else { + return false + } + // Reuse the bounded planning result instead of repeating browser/Keychain work after CLI failure. + return self.hasWebFallback + } +} diff --git a/Sources/CodexBarCore/Providers/Claude/ClaudeScopedWeeklyLimitMapper.swift b/Sources/CodexBarCore/Providers/Claude/ClaudeScopedWeeklyLimitMapper.swift new file mode 100644 index 0000000..0abfbaa --- /dev/null +++ b/Sources/CodexBarCore/Providers/Claude/ClaudeScopedWeeklyLimitMapper.swift @@ -0,0 +1,62 @@ +import Foundation + +/// Shared mapping for the model-scoped weekly limits returned by both Claude usage APIs. +enum ClaudeScopedWeeklyLimitMapper { + struct Limit { + let kind: String? + let group: String? + let percent: Double? + let resetsAt: Date? + let modelID: String? + let modelName: String? + } + + static func extraRateWindows( + from limits: [Limit]?, + resetDescription: ((Date) -> String)? = nil) -> [NamedRateWindow] + { + guard let limits else { return [] } + var seenIDs: Set = [] + + return limits.compactMap { limit in + guard limit.group == "weekly", limit.kind == "weekly_scoped" else { return nil } + guard let percent = limit.percent, percent.isFinite else { return nil } + guard let modelName = self.nonEmpty(limit.modelName) else { return nil } + let identity = self.nonEmpty(limit.modelID) ?? modelName + let slug = self.slug(identity) + guard !slug.isEmpty else { return nil } + + let id = "claude-weekly-scoped-\(slug)" + guard seenIDs.insert(id).inserted else { return nil } + + return NamedRateWindow( + id: id, + title: "\(modelName) only", + window: RateWindow( + usedPercent: percent, + windowMinutes: 7 * 24 * 60, + resetsAt: limit.resetsAt, + resetDescription: limit.resetsAt.flatMap { resetDescription?($0) })) + } + } + + private static func nonEmpty(_ value: String?) -> String? { + let trimmed = value?.trimmingCharacters(in: .whitespacesAndNewlines) + return if let trimmed, !trimmed.isEmpty { trimmed } else { nil } + } + + private static func slug(_ value: String) -> String { + var result = "" + var lastWasDash = false + for scalar in value.lowercased().unicodeScalars { + if CharacterSet.alphanumerics.contains(scalar) { + result.unicodeScalars.append(scalar) + lastWasDash = false + } else if !lastWasDash { + result.append("-") + lastWasDash = true + } + } + return result.trimmingCharacters(in: CharacterSet(charactersIn: "-")) + } +} diff --git a/Sources/CodexBarCore/Providers/Claude/ClaudeSourcePlanner.swift b/Sources/CodexBarCore/Providers/Claude/ClaudeSourcePlanner.swift new file mode 100644 index 0000000..24ae2c0 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Claude/ClaudeSourcePlanner.swift @@ -0,0 +1,224 @@ +import Foundation + +public struct ClaudeSourcePlanningInput: Equatable, Sendable { + public let runtime: ProviderRuntime + public let selectedDataSource: ClaudeUsageDataSource + public let webExtrasEnabled: Bool + public let hasWebSession: Bool + public let hasCLI: Bool + public let hasOAuthCredentials: Bool + + public init( + runtime: ProviderRuntime, + selectedDataSource: ClaudeUsageDataSource, + webExtrasEnabled: Bool, + hasWebSession: Bool, + hasCLI: Bool, + hasOAuthCredentials: Bool) + { + self.runtime = runtime + self.selectedDataSource = selectedDataSource + self.webExtrasEnabled = webExtrasEnabled + self.hasWebSession = hasWebSession + self.hasCLI = hasCLI + self.hasOAuthCredentials = hasOAuthCredentials + } +} + +public enum ClaudeSourcePlanReason: String, Equatable, Sendable { + case explicitSourceSelection = "explicit-source-selection" + case appAutoPreferredOAuth = "app-auto-preferred-oauth" + case appAutoFallbackCLI = "app-auto-fallback-cli" + case appAutoFallbackWeb = "app-auto-fallback-web" + case cliAutoPreferredWeb = "cli-auto-preferred-web" + case cliAutoFallbackCLI = "cli-auto-fallback-cli" +} + +public struct ClaudeFetchPlanStep: Equatable, Sendable { + public let dataSource: ClaudeUsageDataSource + public let inclusionReason: ClaudeSourcePlanReason + public let isPlausiblyAvailable: Bool + + public init( + dataSource: ClaudeUsageDataSource, + inclusionReason: ClaudeSourcePlanReason, + isPlausiblyAvailable: Bool) + { + self.dataSource = dataSource + self.inclusionReason = inclusionReason + self.isPlausiblyAvailable = isPlausiblyAvailable + } +} + +public struct ClaudeFetchPlan: Equatable, Sendable { + public let input: ClaudeSourcePlanningInput + public let orderedSteps: [ClaudeFetchPlanStep] + + public init(input: ClaudeSourcePlanningInput, orderedSteps: [ClaudeFetchPlanStep]) { + self.input = input + self.orderedSteps = orderedSteps + } + + public var availableSteps: [ClaudeFetchPlanStep] { + self.orderedSteps.filter(\.isPlausiblyAvailable) + } + + public var isNoSourceAvailable: Bool { + self.availableSteps.isEmpty + } + + public var preferredStep: ClaudeFetchPlanStep? { + switch self.input.selectedDataSource { + case .auto: + self.availableSteps.first + case .api, .oauth, .web, .cli: + self.orderedSteps.first + } + } + + public var executionSteps: [ClaudeFetchPlanStep] { + switch self.input.selectedDataSource { + case .auto: + self.availableSteps + case .api, .oauth, .web, .cli: + self.orderedSteps + } + } + + public var compatibilityStrategy: ClaudeUsageStrategy? { + guard let preferredStep else { return nil } + let useWebExtras = self.input.runtime == .app + && preferredStep.dataSource == .cli + && self.input.webExtrasEnabled + return ClaudeUsageStrategy( + dataSource: preferredStep.dataSource, + useWebExtras: useWebExtras) + } + + public var orderLabel: String { + self.orderedSteps.map(\.dataSource.sourceLabel).joined(separator: "→") + } + + public func debugLines() -> [String] { + var lines = ["planner_order=\(self.orderLabel)"] + lines.append("planner_selected=\(self.preferredStep?.dataSource.rawValue ?? "none")") + lines.append("planner_no_source=\(self.isNoSourceAvailable)") + for step in self.orderedSteps { + let availability = step.isPlausiblyAvailable ? "available" : "unavailable" + lines.append( + "planner_step.\(step.dataSource.rawValue)=\(availability) reason=\(step.inclusionReason.rawValue)") + } + return lines + } +} + +public enum ClaudeCLIResolver { + #if DEBUG + @TaskLocal static var resolvedBinaryPathOverrideForTesting: String? + + public static var currentResolvedBinaryPathOverrideForTesting: String? { + self.resolvedBinaryPathOverrideForTesting + } + + public static func withResolvedBinaryPathOverrideForTesting( + _ path: String?, + operation: () async throws -> T) async rethrows -> T + { + try await self.$resolvedBinaryPathOverrideForTesting.withValue(path) { + try await operation() + } + } + #endif + + public static func resolvedBinaryPath( + environment: [String: String] = ProcessInfo.processInfo.environment, + loginPATH: [String]? = LoginShellPathCache.shared.current) + -> String? + { + #if DEBUG + if let override = self.resolvedBinaryPathOverrideForTesting { + return FileManager.default.isExecutableFile(atPath: override) ? override : nil + } + #endif + + var normalizedEnvironment = environment + if let override = environment["CLAUDE_CLI_PATH"]?.trimmingCharacters(in: .whitespacesAndNewlines) { + if override.isEmpty { + normalizedEnvironment.removeValue(forKey: "CLAUDE_CLI_PATH") + } else { + normalizedEnvironment["CLAUDE_CLI_PATH"] = override + if FileManager.default.isExecutableFile(atPath: override) { + return override + } + } + } + + return BinaryLocator.resolveClaudeBinary( + env: normalizedEnvironment, + loginPATH: loginPATH) + } + + public static func isAvailable(environment: [String: String] = ProcessInfo.processInfo.environment) -> Bool { + self.resolvedBinaryPath(environment: environment) != nil + } +} + +public enum ClaudeSourcePlanner { + public static func resolve(input: ClaudeSourcePlanningInput) -> ClaudeFetchPlan { + ClaudeFetchPlan(input: input, orderedSteps: self.makeSteps(input: input)) + } + + private static func makeSteps(input: ClaudeSourcePlanningInput) -> [ClaudeFetchPlanStep] { + switch input.selectedDataSource { + case .auto: + switch input.runtime { + case .app: + [ + self.step(.oauth, reason: .appAutoPreferredOAuth, input: input), + self.step(.cli, reason: .appAutoFallbackCLI, input: input), + self.step(.web, reason: .appAutoFallbackWeb, input: input), + ] + case .cli: + [ + self.step(.web, reason: .cliAutoPreferredWeb, input: input), + self.step(.cli, reason: .cliAutoFallbackCLI, input: input), + ] + } + case .api: + [self.step(.api, reason: .explicitSourceSelection, input: input)] + case .oauth: + [self.step(.oauth, reason: .explicitSourceSelection, input: input)] + case .web: + [self.step(.web, reason: .explicitSourceSelection, input: input)] + case .cli: + [self.step(.cli, reason: .explicitSourceSelection, input: input)] + } + } + + private static func step( + _ dataSource: ClaudeUsageDataSource, + reason: ClaudeSourcePlanReason, + input: ClaudeSourcePlanningInput) -> ClaudeFetchPlanStep + { + ClaudeFetchPlanStep( + dataSource: dataSource, + inclusionReason: reason, + isPlausiblyAvailable: self.isPlausiblyAvailable(dataSource, input: input)) + } + + private static func isPlausiblyAvailable( + _ dataSource: ClaudeUsageDataSource, + input: ClaudeSourcePlanningInput) -> Bool + { + switch dataSource { + case .auto, .api: + false + case .oauth: + input.hasOAuthCredentials + case .web: + input.hasWebSession + case .cli: + input.hasCLI + } + } +} diff --git a/Sources/CodexBarCore/Providers/Claude/ClaudeStatusProbe.swift b/Sources/CodexBarCore/Providers/Claude/ClaudeStatusProbe.swift new file mode 100644 index 0000000..9c255ee --- /dev/null +++ b/Sources/CodexBarCore/Providers/Claude/ClaudeStatusProbe.swift @@ -0,0 +1,1353 @@ +import Foundation + +public struct ClaudeStatusSnapshot: Sendable { + public let sessionPercentLeft: Int? + public let weeklyPercentLeft: Int? + public let opusPercentLeft: Int? + public let extraRateWindows: [NamedRateWindow] + public let accountEmail: String? + public let accountOrganization: String? + public let loginMethod: String? + public let primaryResetDescription: String? + public let secondaryResetDescription: String? + public let opusResetDescription: String? + public let rawText: String + + public init( + sessionPercentLeft: Int?, + weeklyPercentLeft: Int?, + opusPercentLeft: Int?, + accountEmail: String?, + accountOrganization: String?, + loginMethod: String?, + primaryResetDescription: String?, + secondaryResetDescription: String?, + opusResetDescription: String?, + rawText: String, + extraRateWindows: [NamedRateWindow] = []) + { + self.sessionPercentLeft = sessionPercentLeft + self.weeklyPercentLeft = weeklyPercentLeft + self.opusPercentLeft = opusPercentLeft + self.extraRateWindows = extraRateWindows + self.accountEmail = accountEmail + self.accountOrganization = accountOrganization + self.loginMethod = loginMethod + self.primaryResetDescription = primaryResetDescription + self.secondaryResetDescription = secondaryResetDescription + self.opusResetDescription = opusResetDescription + self.rawText = rawText + } +} + +public struct ClaudeAccountIdentity: Sendable { + public let accountEmail: String? + public let accountOrganization: String? + public let loginMethod: String? + + public init(accountEmail: String?, accountOrganization: String?, loginMethod: String?) { + self.accountEmail = accountEmail + self.accountOrganization = accountOrganization + self.loginMethod = loginMethod + } +} + +public enum ClaudeStatusProbeError: LocalizedError, Sendable { + case claudeNotInstalled + case parseFailed(String) + case timedOut + + public var errorDescription: String? { + switch self { + case .claudeNotInstalled: + "Claude CLI is not installed or not on PATH." + case let .parseFailed(msg): + "Could not parse Claude usage: \(msg)" + case .timedOut: + "Claude usage probe timed out." + } + } +} + +/// Runs `claude` inside a PTY, sends `/usage`, and parses the rendered text panel. +public struct ClaudeStatusProbe: Sendable { + public static let subscriptionQuotaUnavailableDescription = + "Claude CLI /usage returned a subscription notice without session quota data. " + + "Local cost and token history remain available." + + public var claudeBinary: String = "claude" + public var timeout: TimeInterval = 20.0 + public var keepCLISessionsAlive: Bool = false + private static let log = CodexBarLog.logger(LogCategories.claudeProbe) + #if DEBUG + public typealias FetchOverride = @Sendable (String, TimeInterval, Bool) async throws -> ClaudeStatusSnapshot + @TaskLocal static var fetchOverride: FetchOverride? + #endif + + public init(claudeBinary: String = "claude", timeout: TimeInterval = 20.0, keepCLISessionsAlive: Bool = false) { + self.claudeBinary = claudeBinary + self.timeout = timeout + self.keepCLISessionsAlive = keepCLISessionsAlive + } + + #if DEBUG + public static var currentFetchOverrideForTesting: FetchOverride? { + self.fetchOverride + } + + public static func withFetchOverrideForTesting( + _ override: FetchOverride?, + operation: () async throws -> T) async rethrows -> T + { + try await self.$fetchOverride.withValue(override) { + try await operation() + } + } + + public static func withFetchOverrideForTesting( + _ override: FetchOverride?, + operation: () async -> T) async -> T + { + await self.$fetchOverride.withValue(override) { + await operation() + } + } + #endif + + public func fetch() async throws -> ClaudeStatusSnapshot { + let resolved = Self.resolvedBinaryPath(binaryName: self.claudeBinary) + guard let resolved, Self.isBinaryAvailable(resolved) else { + throw ClaudeStatusProbeError.claudeNotInstalled + } + + // Run commands sequentially through a shared Claude session to avoid warm-up churn. + let timeout = self.timeout + let keepAlive = self.keepCLISessionsAlive + #if DEBUG + if let override = Self.fetchOverride { + return try await override(resolved, timeout, keepAlive) + } + #endif + do { + var usage = try await Self.capture(subcommand: "/usage", binary: resolved, timeout: timeout) + if !Self.usageOutputLooksRelevant(usage) { + Self.log.debug("Claude CLI /usage looked like startup output; retrying once") + usage = try await Self.capture(subcommand: "/usage", binary: resolved, timeout: max(timeout, 14)) + } + // `/status` only enriches a valid usage snapshot with identity. Terminal usage errors and loading stalls + // cannot be repaired by it, so fail now instead of paying for another interactive CLI round trip. + try Self.validateUsageBeforeStatusProbe(usage) + let status = try? await Self.capture(subcommand: "/status", binary: resolved, timeout: min(timeout, 12)) + let snap = try Self.parse(text: usage, statusText: status) + + Self.log.info("Claude CLI scrape ok", metadata: [ + "sessionPercentLeft": "\(snap.sessionPercentLeft ?? -1)", + "weeklyPercentLeft": "\(snap.weeklyPercentLeft ?? -1)", + "opusPercentLeft": "\(snap.opusPercentLeft ?? -1)", + ]) + if !keepAlive { + await Self.resetTransientCLISessionAndCleanupProbeArtifacts() + } + return snap + } catch { + if !keepAlive { + await Self.resetTransientCLISessionAndCleanupProbeArtifacts() + } + throw error + } + } + + private static func resetTransientCLISessionAndCleanupProbeArtifacts() async { + await ClaudeCLISession.current.reset() + let removed = ClaudeProbeSessionArtifactCleaner.cleanupProbeSessionArtifacts() + guard !removed.isEmpty else { return } + Self.log.debug("Claude probe session artifacts removed", metadata: ["count": "\(removed.count)"]) + } +} + +extension ClaudeStatusProbe { + // MARK: - Parsing helpers + + private struct LabelSearchContext { + let lines: [String] + let normalizedLines: [String] + let normalizedData: Data + + init(text: String) { + self.lines = text.components(separatedBy: .newlines) + self.normalizedLines = self.lines.map { ClaudeStatusProbe.normalizedForLabelSearch($0) } + let normalized = ClaudeStatusProbe.normalizedForLabelSearch(text) + self.normalizedData = Data(normalized.utf8) + } + + func contains(_ needle: String) -> Bool { + self.normalizedData.range(of: Data(needle.utf8)) != nil + } + } + + public static func parse(text: String, statusText: String? = nil) throws -> ClaudeStatusSnapshot { + let clean = TextParsing.stripANSICodes(text) + let statusClean = statusText.map(TextParsing.stripANSICodes) + guard !clean.isEmpty else { throw ClaudeStatusProbeError.timedOut } + + let shouldDump = ProcessInfo.processInfo.environment["DEBUG_CLAUDE_DUMP"] == "1" + + if let usageError = self.extractUsageError(text: clean) { + Self.dumpIfNeeded( + enabled: shouldDump, + reason: "usageError: \(usageError)", + usage: clean, + status: statusText) + throw ClaudeStatusProbeError.parseFailed(usageError) + } + + let latestUsagePanel = self.trimToLatestUsagePanel(clean) + if self.isUsageStillLoading(text: latestUsagePanel ?? clean) { + Self.dumpIfNeeded( + enabled: shouldDump, + reason: "usage still loading", + usage: clean, + status: statusText) + throw ClaudeStatusProbeError.parseFailed("Claude CLI /usage is still loading usage data.") + } + + // Claude CLI renders /usage as a TUI. Our PTY capture includes earlier screen fragments (including a status + // line + // with a "0%" context meter) before the usage panel is drawn. To keep parsing stable, trim to the last + // Settings/Usage panel when present. + let usagePanelText = latestUsagePanel ?? clean + let labelContext = LabelSearchContext(text: usagePanelText) + + var sessionPct = self.extractPercent(labelSubstring: "Current session", context: labelContext) + let weeklyPct = self.extractPercent(labelSubstring: "Current week (all models)", context: labelContext) + let opusLabels = [ + "Current week (Opus)", + "Current week (Sonnet only)", + "Current week (Sonnet)", + ] + let opusPct = self.extractPercent(labelSubstrings: opusLabels, context: labelContext) + + // Fallback: order-based percent scraping when labels are present but the surrounding layout moved. + // Only apply the fallback when the corresponding label exists in the rendered panel; enterprise accounts + // may omit the weekly panel entirely, and we should treat that as "unavailable" rather than guessing. + let weeklyModels = Set(labelContext.lines.compactMap(self.weeklyModelName).map(self.normalizedForLabelSearch)) + let hasAllModelsWeeklyLabel = weeklyModels.contains("allmodels") + let opusModels = Set(opusLabels.compactMap(self.weeklyModelName).map(self.normalizedForLabelSearch)) + let hasOpusLabel = !weeklyModels.isDisjoint(with: opusModels) + + if sessionPct == nil { + let ordered = self.allPercents(usagePanelText) + if sessionPct == nil, ordered.indices.contains(0) { + sessionPct = ordered[0] + } + } + + let identity = Self.parseIdentity(usageText: clean, statusText: statusClean) + + guard let sessionPct else { + Self.dumpIfNeeded( + enabled: shouldDump, + reason: "missing session label", + usage: clean, + status: statusText) + if shouldDump { + let tail = usagePanelText.suffix(1800) + let snippet = tail.isEmpty ? "(empty)" : String(tail) + throw ClaudeStatusProbeError.parseFailed( + "Missing Current session.\n\n--- Clean usage tail ---\n\(snippet)") + } + throw ClaudeStatusProbeError.parseFailed("Missing Current session.") + } + + let sessionReset = self.extractReset(labelSubstring: "Current session", context: labelContext) + let weeklyReset = hasAllModelsWeeklyLabel + ? self.extractReset(labelSubstring: "Current week (all models)", context: labelContext) + : nil + let opusReset = hasOpusLabel + ? self.extractReset(labelSubstrings: opusLabels, context: labelContext) + : nil + let scopedWeeklyUsages = self.extractScopedWeeklyUsages(context: labelContext) + let extraRateWindows = self.extraRateWindows( + fromScopedWeeklyUsages: scopedWeeklyUsages, + fallbackResetDescription: weeklyReset) + + return ClaudeStatusSnapshot( + sessionPercentLeft: sessionPct, + weeklyPercentLeft: weeklyPct, + opusPercentLeft: opusPct, + accountEmail: identity.accountEmail, + accountOrganization: identity.accountOrganization, + loginMethod: identity.loginMethod, + primaryResetDescription: sessionReset, + secondaryResetDescription: weeklyReset, + opusResetDescription: opusReset, + rawText: text + (statusText ?? ""), + extraRateWindows: extraRateWindows) + } + + public static func parseIdentity(usageText: String?, statusText: String?) -> ClaudeAccountIdentity { + let usageClean = usageText.map(TextParsing.stripANSICodes) ?? "" + let statusClean = statusText.map(TextParsing.stripANSICodes) + return self.extractIdentity(usageText: usageClean, statusText: statusClean) + } + + public static func fetchIdentity( + timeout: TimeInterval = 12.0, + environment: [String: String] = ProcessInfo.processInfo.environment) async throws -> ClaudeAccountIdentity + { + let resolved = self.resolvedBinaryPath(binaryName: "claude", environment: environment) + guard let resolved, self.isBinaryAvailable(resolved) else { + throw ClaudeStatusProbeError.claudeNotInstalled + } + let statusText = try await Self.capture(subcommand: "/status", binary: resolved, timeout: timeout) + return Self.parseIdentity(usageText: nil, statusText: statusText) + } + + public static func touchOAuthAuthPath( + timeout: TimeInterval = 8, + environment: [String: String] = ProcessInfo.processInfo.environment) async throws + { + let resolved = self.resolvedBinaryPath(binaryName: "claude", environment: environment) + guard let resolved, self.isBinaryAvailable(resolved) else { + throw ClaudeStatusProbeError.claudeNotInstalled + } + do { + // Use a more robust capture configuration than the standard `/status` scrape: + // - Avoid the short idle-timeout which can terminate the session while CLI auth checks are still running. + // - We intentionally do not parse output here; success is "the command ran without timing out". + _ = try await ClaudeCLISession.shared.capture( + subcommand: "/status", + binary: resolved, + timeout: timeout, + idleTimeout: nil, + stopOnSubstrings: [], + settleAfterStop: 0.8, + sendEnterEvery: 0.8) + await ClaudeCLISession.shared.reset() + } catch { + await ClaudeCLISession.shared.reset() + throw error + } + } + + public static func isClaudeBinaryAvailable( + environment: [String: String] = ProcessInfo.processInfo.environment) -> Bool + { + let resolved = self.resolvedBinaryPath(binaryName: "claude", environment: environment) + return self.isBinaryAvailable(resolved) + } + + private static func extractPercent(labelSubstring: String, context: LabelSearchContext) -> Int? { + let lines = context.lines + let label = self.normalizedForLabelSearch(labelSubstring) + for (idx, line) in lines.enumerated() { + let normalizedLine = context.normalizedLines[idx] + guard self.matchesLabel( + line: line, + normalizedLine: normalizedLine, + labelSubstring: labelSubstring, + normalizedLabel: label) + else { continue } + + // Claude's usage panel can take a moment to render percentages (especially on enterprise accounts), + // so scan a larger window than the original 3–4 lines. + let window = lines.dropFirst(idx).prefix(12) + for candidate in window { + if self.crossesLabelBoundary( + line: candidate, + labelSubstring: labelSubstring, + normalizedLabel: label) + { + break + } + if let pct = self.percentFromLine(candidate) { + return pct + } + } + } + return nil + } + + private static func usageOutputLooksRelevant(_ text: String) -> Bool { + let normalized = TextParsing.stripANSICodes(text).lowercased().filter { !$0.isWhitespace } + return normalized.contains("currentsession") + || normalized.contains("currentweek") + || normalized.contains("loadingusage") + || normalized.contains("failedtoloadusagedata") + || self.usageCaptureHasSubscriptionNotice(normalized) + } + + private static func validateUsageBeforeStatusProbe(_ text: String) throws { + let clean = TextParsing.stripANSICodes(text) + if let usageError = self.extractUsageError(text: clean) { + throw ClaudeStatusProbeError.parseFailed(usageError) + } + + let latestUsagePanel = self.trimToLatestUsagePanel(clean) + if self.isUsageStillLoading(text: latestUsagePanel ?? clean) { + throw ClaudeStatusProbeError.parseFailed("Claude CLI /usage is still loading usage data.") + } + } + + private static func extractPercent(labelSubstrings: [String], context: LabelSearchContext) -> Int? { + for label in labelSubstrings { + if let value = self.extractPercent(labelSubstring: label, context: context) { + return value + } + } + return nil + } + + private struct ScopedWeeklyUsage { + let modelName: String + let percentLeft: Int + let resetDescription: String? + } + + private static func extractScopedWeeklyUsages(context: LabelSearchContext) -> [ScopedWeeklyUsage] { + var usageIndexByModel: [String: Int] = [:] + var usages: [ScopedWeeklyUsage] = [] + for (index, line) in context.lines.enumerated() { + guard let modelName = self.weeklyModelName(from: line) else { continue } + let normalizedModel = self.normalizedForLabelSearch(modelName) + guard normalizedModel != "allmodels", !normalizedModel.isEmpty else { continue } + + let window = context.lines.dropFirst(index).prefix(14) + var percentLeft: Int? + var resetDescription: String? + for candidate in window { + if self.crossesLabelBoundary( + line: candidate, + labelSubstring: line, + normalizedLabel: self.normalizedForLabelSearch(line)) + { + break + } + if percentLeft == nil { + percentLeft = self.percentFromLine(candidate) + } + if resetDescription == nil { + resetDescription = self.resetFromLine(candidate) + } + } + guard let percentLeft else { continue } + let usage = ScopedWeeklyUsage( + modelName: modelName, + percentLeft: percentLeft, + resetDescription: resetDescription) + if let existingIndex = usageIndexByModel[normalizedModel] { + usages[existingIndex] = usage + } else { + usageIndexByModel[normalizedModel] = usages.endIndex + usages.append(usage) + } + } + return usages + } + + private static func extraRateWindows( + fromScopedWeeklyUsages usages: [ScopedWeeklyUsage], + fallbackResetDescription: String?) -> [NamedRateWindow] + { + usages.compactMap { usage in + let normalizedModel = self.normalizedForLabelSearch(usage.modelName) + guard normalizedModel != "opus", + normalizedModel != "sonnet", + normalizedModel != "sonnetonly" + else { return nil } + + let usedPercent = max(0, min(100, 100 - Double(usage.percentLeft))) + let modelTitle = normalizedModel.hasSuffix("only") + ? usage.modelName + : "\(usage.modelName) only" + let resetDescription = usage.resetDescription ?? fallbackResetDescription + return NamedRateWindow( + id: "claude-weekly-scoped-\(self.slug(usage.modelName))", + title: modelTitle, + window: RateWindow( + usedPercent: usedPercent, + windowMinutes: 7 * 24 * 60, + resetsAt: self.parseResetDate( + from: resetDescription, + expectedWindow: 7 * 24 * 60 * 60), + resetDescription: resetDescription)) + } + } + + private static func slug(_ value: String) -> String { + var result = "" + var lastWasDash = false + for scalar in value.lowercased().unicodeScalars { + if CharacterSet.alphanumerics.contains(scalar) { + result.unicodeScalars.append(scalar) + lastWasDash = false + } else if !lastWasDash { + result.append("-") + lastWasDash = true + } + } + return result.trimmingCharacters(in: CharacterSet(charactersIn: "-")) + } + + private static func percentFromLine(_ line: String, assumeRemainingWhenUnclear: Bool = false) -> Int? { + if self.isLikelyStatusContextLine(line) { + return nil + } + + // Allow optional Unicode whitespace before % to handle CLI formatting changes. + let pattern = #"([0-9]{1,3}(?:\.[0-9]+)?)\p{Zs}*%"# + guard let regex = try? NSRegularExpression(pattern: pattern, options: [.caseInsensitive]) else { return nil } + let range = NSRange(line.startIndex..= 2, + let valRange = Range(match.range(at: 1), in: line) + else { return nil } + let rawVal = Double(line[valRange]) ?? 0 + let clamped = max(0, min(100, rawVal)) + let lower = line.lowercased() + let usedKeywords = ["used", "spent", "consumed"] + let remainingKeywords = ["left", "remaining", "available"] + if usedKeywords.contains(where: lower.contains) { + return Int(max(0, min(100, 100 - clamped)).rounded()) + } + if remainingKeywords.contains(where: lower.contains) { + return Int(clamped.rounded()) + } + return assumeRemainingWhenUnclear ? Int(clamped.rounded()) : nil + } + + private static func isLikelyStatusContextLine(_ line: String) -> Bool { + guard line.contains("|") else { return false } + let lower = line.lowercased() + let modelTokens = ["opus", "sonnet", "haiku", "default"] + return modelTokens.contains(where: lower.contains) + } + + private static func extractFirst(pattern: String, text: String) -> String? { + guard let regex = try? NSRegularExpression(pattern: pattern, options: [.caseInsensitive]) else { return nil } + let range = NSRange(text.startIndex..= 2, + let r = Range(match.range(at: 1), in: text) else { return nil } + return String(text[r]).trimmingCharacters(in: .whitespacesAndNewlines) + } + + private static func extractIdentity(usageText: String, statusText: String?) -> ClaudeAccountIdentity { + let emailPatterns = [ + #"(?i)Account:\s+([^\s@]+@[^\s@]+)"#, + #"(?i)Email:\s+([^\s@]+@[^\s@]+)"#, + ] + let looseEmailPatterns = [ + #"(?i)Account:\s+(\S+)"#, + #"(?i)Email:\s+(\S+)"#, + ] + let email = emailPatterns + .compactMap { self.extractFirst(pattern: $0, text: usageText) } + .first + ?? emailPatterns + .compactMap { self.extractFirst(pattern: $0, text: statusText ?? "") } + .first + ?? looseEmailPatterns + .compactMap { self.extractFirst(pattern: $0, text: usageText) } + .first + ?? looseEmailPatterns + .compactMap { self.extractFirst(pattern: $0, text: statusText ?? "") } + .first + ?? self.extractFirst( + pattern: #"(?i)[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}"#, + text: usageText) + ?? self.extractFirst( + pattern: #"(?i)[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}"#, + text: statusText ?? "") + let orgPatterns = [ + #"(?i)Org:\s*(.+)"#, + #"(?i)Organization:\s*(.+)"#, + ] + let orgRaw = orgPatterns + .compactMap { self.extractFirst(pattern: $0, text: usageText) } + .first + ?? orgPatterns + .compactMap { self.extractFirst(pattern: $0, text: statusText ?? "") } + .first + let org: String? = { + guard let orgText = orgRaw?.trimmingCharacters(in: .whitespacesAndNewlines), !orgText.isEmpty else { + return nil + } + // Suppress org if it’s just the email prefix (common in CLI panels). + if let email, orgText.lowercased().hasPrefix(email.lowercased()) { + return nil + } + return orgText + }() + // Prefer explicit login method from /status, then fall back to /usage header heuristics. + let login = self.extractLoginMethod(text: statusText ?? "") ?? self.extractLoginMethod(text: usageText) + return ClaudeAccountIdentity(accountEmail: email, accountOrganization: org, loginMethod: login) + } + + private static func extractUsageError(text: String) -> String? { + if let jsonHint = self.extractUsageErrorJSON(text: text) { + return jsonHint + } + + let lower = text.lowercased() + let compact = lower.filter { !$0.isWhitespace } + if lower.contains("do you trust the files in this folder?"), !lower.contains("current session") { + let folder = self.extractFirst( + pattern: #"Do you trust the files in this folder\?\s*(?:\r?\n)+\s*([^\r\n]+)"#, + text: text) + let folderHint = folder.flatMap { value in + let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines) + return trimmed.isEmpty ? nil : trimmed + } + if let folderHint { + return """ + Claude CLI is waiting for a folder trust prompt (\(folderHint)). CodexBar tries to auto-accept this, \ + but if it keeps appearing run: `cd "\(folderHint)" && claude` and choose “Yes, proceed”, then retry. + """ + } + return """ + Claude CLI is waiting for a folder trust prompt. CodexBar tries to auto-accept this, but if it keeps \ + appearing open `claude` once, choose “Yes, proceed”, then retry. + """ + } + if lower.contains("token_expired") || lower.contains("token has expired") { + return "Claude CLI token expired. Run `claude login` to refresh." + } + if lower.contains("authentication_error") { + return "Claude CLI authentication error. Run `claude login`." + } + if lower.contains("rate_limit_error") + || lower.contains("rate limited") + || compact.contains("ratelimited") + { + return "Claude CLI usage endpoint is rate limited right now. Please try again later." + } + if self.isSubscriptionNoticeOnly(text: text) { + return self.subscriptionQuotaUnavailableDescription + } + if lower.contains("failed to load usage data") { + return "Claude CLI could not load usage data. Open the CLI and retry `/usage`." + } + if compact.contains("failedtoloadusagedata") { + return "Claude CLI could not load usage data. Open the CLI and retry `/usage`." + } + return nil + } + + private static func isUsageStillLoading(text: String) -> Bool { + let normalized = TextParsing.stripANSICodes(text).lowercased().filter { !$0.isWhitespace } + guard normalized.contains("loadingusage") else { return false } + return !self.usageCaptureHasSessionValue(normalized) && self.allPercents(text).isEmpty + } + + /// Returns true when the text contains only a subscription notice with no session/weekly quota data. + /// CLI 2.1+ can return "You are currently using your subscription to power your Claude Code usage" + /// which lacks the "Current session" / "Current week" labels and percentage values needed for quota display. + /// A PTY capture may contain both an intermediate "Loading usage data…" panel and the final subscription + /// notice; `loadingusage` is not treated as quota data in this check so mixed captures surface correctly. + private static func isSubscriptionNoticeOnly(text: String) -> Bool { + let normalized = text.lowercased().filter { !$0.isWhitespace } + guard normalized.contains("currentlyusingyoursubscription") else { return false } + guard normalized.contains("claudecodeusage") else { return false } + // Only real session/week labels and actual percentage values count as quota data. + // `loadingusage` is not quota data — a mixed loading+subscription PTY capture should + // surface the subscription error, not a still-loading stall. + let hasQuotaData = normalized.contains("currentsession") || normalized.contains("currentweek") + || normalized.contains("%used") || normalized.contains("%left") || normalized.contains("%remaining") + || normalized.contains("%available") + return !hasQuotaData + } + + public static func isSubscriptionQuotaUnavailableDescription(_ text: String?) -> Bool { + text?.localizedCaseInsensitiveContains("subscription notice without session quota data") == true + } + + /// Collect remaining percentages in the order they appear; used as a backup when labels move/rename. + private static func allPercents(_ text: String) -> [Int] { + let lines = text.components(separatedBy: .newlines) + let normalized = text.lowercased().filter { !$0.isWhitespace } + let hasUsageWindows = normalized.contains("currentsession") || normalized.contains("currentweek") + let hasLoading = normalized.contains("loadingusage") + let hasUsagePercentKeywords = normalized.contains("used") || normalized.contains("left") + || normalized.contains("remaining") || normalized.contains("available") + let loadingOnly = hasLoading && !hasUsageWindows + guard hasUsageWindows || hasLoading else { return [] } + if loadingOnly { + return [] + } + guard hasUsagePercentKeywords else { return [] } + + // Keep this strict to avoid matching Claude's status-line context meter (e.g. "0%") as session usage when the + // /usage panel is still rendering. + return lines.compactMap { self.percentFromLine($0, assumeRemainingWhenUnclear: false) } + } + + /// Attempts to isolate the most recent /usage panel output from a PTY capture. + /// The Claude TUI draws a "Settings: … Usage …" header; we slice from its last occurrence to avoid earlier screen + /// fragments (like the status bar) contaminating percent scraping. + private static func trimToLatestUsagePanel(_ text: String) -> String? { + guard let settingsRange = text.range(of: "Settings:", options: [.caseInsensitive, .backwards]) else { + return nil + } + let tail = text[settingsRange.lowerBound...] + guard tail.range(of: "Usage", options: .caseInsensitive) != nil else { return nil } + let lower = tail.lowercased() + let hasPercent = lower.contains("%") + let hasUsageWords = lower.contains("used") || lower.contains("left") || lower.contains("remaining") + || lower.contains("available") + let hasLoading = lower.contains("loading usage") + guard (hasPercent && hasUsageWords) || hasLoading else { return nil } + return String(tail) + } + + private static func extractReset(labelSubstring: String, context: LabelSearchContext) -> String? { + let lines = context.lines + let label = self.normalizedForLabelSearch(labelSubstring) + for (idx, line) in lines.enumerated() { + let normalizedLine = context.normalizedLines[idx] + guard self.matchesLabel( + line: line, + normalizedLine: normalizedLine, + labelSubstring: labelSubstring, + normalizedLabel: label) + else { continue } + + let window = lines.dropFirst(idx).prefix(14) + for candidate in window { + if self.crossesLabelBoundary( + line: candidate, + labelSubstring: labelSubstring, + normalizedLabel: label) + { + break + } + if let reset = self.resetFromLine(candidate) { + return reset + } + } + } + return nil + } + + private static func matchesLabel( + line: String, + normalizedLine: String, + labelSubstring: String, + normalizedLabel: String) -> Bool + { + guard let expectedModel = self.weeklyModelName(from: labelSubstring) else { + return normalizedLine.contains(normalizedLabel) + } + guard let actualModel = self.weeklyModelName(from: line) else { return false } + return self.normalizedForLabelSearch(actualModel) == self.normalizedForLabelSearch(expectedModel) + } + + private static func crossesLabelBoundary( + line: String, + labelSubstring: String, + normalizedLabel: String) -> Bool + { + let normalizedLine = self.normalizedForLabelSearch(line) + guard normalizedLine.hasPrefix("current") else { return false } + guard let expectedModel = self.weeklyModelName(from: labelSubstring) else { + return !normalizedLine.contains(normalizedLabel) + } + guard let actualModel = self.weeklyModelName(from: line) else { return true } + return self.normalizedForLabelSearch(actualModel) != self.normalizedForLabelSearch(expectedModel) + } + + private static func weeklyModelName(from line: String) -> String? { + guard let regex = try? NSRegularExpression( + pattern: #"current\s*week\s*\(([^)]+)\)"#, + options: [.caseInsensitive]) + else { return nil } + let range = NSRange(line.startIndex..= 2, + let modelRange = Range(match.range(at: 1), in: line) + else { return nil } + return String(line[modelRange]).trimmingCharacters(in: .whitespacesAndNewlines) + } + + private static func extractReset(labelSubstrings: [String], context: LabelSearchContext) -> String? { + for label in labelSubstrings { + if let value = self.extractReset(labelSubstring: label, context: context) { + return value + } + } + return nil + } + + private static func resetFromLine(_ line: String) -> String? { + let range = line.range(of: #"(?i)\bresets?\b"#, options: .regularExpression) + ?? line.range(of: #"\b(?:Reset|Resets)(?=[A-Z0-9])"#, options: .regularExpression) + guard let range else { return nil } + let raw = String(line[range.lowerBound...]).trimmingCharacters(in: .whitespacesAndNewlines) + return self.cleanResetLine(raw) + } + + private static func normalizedForLabelSearch(_ text: String) -> String { + String(text.lowercased().unicodeScalars.filter(CharacterSet.alphanumerics.contains)) + } + + /// Capture all "Reset"/"Resets" strings to surface in the menu. + private static func allResets(_ text: String) -> [String] { + let pat = #"\bResets?\b[^\r\n]*"# + guard let regex = try? NSRegularExpression(pattern: pat, options: [.caseInsensitive]) else { return [] } + let nsrange = NSRange(text.startIndex.. String { + // TTY capture sometimes appends a stray ")" at line ends; trim it to keep snapshots stable. + var cleaned = raw.trimmingCharacters(in: .whitespacesAndNewlines) + cleaned = cleaned.trimmingCharacters(in: CharacterSet(charactersIn: " )")) + cleaned = cleaned.replacingOccurrences( + of: #"(?i)\b([A-Za-z]{3}\s+\d{1,2})\s+t\s+(\d)"#, + with: "$1 at $2", + options: .regularExpression) + let openCount = cleaned.count(where: { $0 == "(" }) + let closeCount = cleaned.count(where: { $0 == ")" }) + if openCount > closeCount { + cleaned.append(")") + } + return cleaned + } + + /// Parses explicit-year resets at their stated occurrence; recurring forms resolve forward in any explicit + /// timezone. + public static func parseResetDate(from text: String?, now: Date = .init()) -> Date? { + self.parseResetDate(from: text, now: now, expectedWindow: nil) + } + + /// Quota surfaces may accept a recently stale occurrence when the next occurrence cannot belong to that window. + package static func parseResetDate( + from text: String?, + now: Date = .init(), + expectedWindow: TimeInterval?) -> Date? + { + guard let normalized = self.normalizeResetInput(text) else { return nil } + let (raw, timeZone) = normalized + + let formatter = DateFormatter() + formatter.locale = Locale(identifier: "en_US_POSIX") + formatter.timeZone = timeZone ?? TimeZone.current + var calendar = Calendar(identifier: .gregorian) + calendar.timeZone = formatter.timeZone + // Parse yearless Feb 29 independently of the current year, then resolve validated calendar occurrences. + formatter.defaultDate = calendar.date(from: DateComponents(year: 2000, month: 1, day: 1)) + + if let date = self.parseDate(raw, formats: Self.resetDateTimeWithExplicitYear, formatter: formatter) { + return self.resolveOccurrence( + self.explicitOccurrences(for: date, calendar: calendar), + now: now, + expectedWindow: expectedWindow) + } + if let date = self.parseDate(raw, formats: Self.resetDateTimeWithMinutes, formatter: formatter) { + let comps = calendar.dateComponents([.month, .day, .hour, .minute], from: date) + return self.resolveOccurrence( + self.yearlyOccurrences(for: comps, now: now, calendar: calendar), + now: now, + expectedWindow: expectedWindow) + } + if let date = self.parseDate(raw, formats: Self.resetDateTimeHourOnly, formatter: formatter) { + let comps = calendar.dateComponents([.month, .day, .hour], from: date) + return self.resolveOccurrence( + self.yearlyOccurrences(for: comps, now: now, calendar: calendar), + now: now, + expectedWindow: expectedWindow) + } + + if let time = self.parseDate(raw, formats: Self.resetTimeWithMinutes, formatter: formatter) { + let comps = calendar.dateComponents([.hour, .minute], from: time) + return self.resolveOccurrence( + self.dailyOccurrences(for: comps, now: now, calendar: calendar), + now: now, + expectedWindow: expectedWindow) + } + + guard let time = self.parseDate(raw, formats: Self.resetTimeHourOnly, formatter: formatter) else { return nil } + let comps = calendar.dateComponents([.hour], from: time) + return self.resolveOccurrence( + self.dailyOccurrences(for: comps, now: now, calendar: calendar), + now: now, + expectedWindow: expectedWindow) + } + + private static func explicitOccurrences(for date: Date, calendar: Calendar) -> [Date] { + let components = calendar.dateComponents([.year, .month, .day, .hour, .minute], from: date) + guard let year = components.year, + let month = components.month, + let day = components.day, + let hour = components.hour, + let minute = components.minute + else { return [] } + return self.exactLocalOccurrences( + DateComponents( + timeZone: calendar.timeZone, + year: year, + month: month, + day: day, + hour: hour, + minute: minute, + second: 0), + calendar: calendar) + } + + private static func resolveOccurrence( + _ candidates: [Date], + now: Date, + expectedWindow: TimeInterval?) -> Date? + { + let sortedCandidates = candidates.sorted() + guard let future = sortedCandidates.first(where: { $0 >= now }) else { return sortedCandidates.last } + guard let expectedWindow else { return future } + + let horizon = max(0, expectedWindow) + let past = sortedCandidates.last(where: { $0 < now }) + let pastIsPlausible = past.map { now.timeIntervalSince($0) <= horizon } ?? false + let futureIsPlausible = future.timeIntervalSince(now) <= horizon + return pastIsPlausible && !futureIsPlausible ? past : future + } + + private static func yearlyOccurrences( + for components: DateComponents, + now: Date, + calendar: Calendar) -> [Date] + { + guard let month = components.month, + let day = components.day, + let hour = components.hour + else { return [] } + let currentYear = calendar.component(.year, from: now) + // Eight years covers the Gregorian century gap between leap days (for example, 2096 to 2104). + return ((currentYear - 8)...(currentYear + 8)).flatMap { year in + self.exactLocalOccurrences( + DateComponents( + timeZone: calendar.timeZone, + year: year, + month: month, + day: day, + hour: hour, + minute: components.minute ?? 0, + second: 0), + calendar: calendar) + } + } + + private static func dailyOccurrences( + for components: DateComponents, + now: Date, + calendar: Calendar) -> [Date] + { + guard let hour = components.hour else { return [] } + let startOfToday = calendar.startOfDay(for: now) + return (-1...1).flatMap { offset -> [Date] in + guard let day = calendar.date(byAdding: .day, value: offset, to: startOfToday) else { return [] } + let dayComponents = calendar.dateComponents([.year, .month, .day], from: day) + guard let year = dayComponents.year, + let month = dayComponents.month, + let dayOfMonth = dayComponents.day + else { return [] } + return self.exactLocalOccurrences( + DateComponents( + timeZone: calendar.timeZone, + year: year, + month: month, + day: dayOfMonth, + hour: hour, + minute: components.minute ?? 0, + second: 0), + calendar: calendar) + } + } + + /// Returns both instants when a local wall time repeats during a daylight-saving transition. + private static func exactLocalOccurrences( + _ target: DateComponents, + calendar: Calendar) -> [Date] + { + guard let year = target.year, + let month = target.month, + let day = target.day, + let hour = target.hour, + let minute = target.minute + else { return [] } + guard let firstApproximation = calendar.date(from: target) else { return [] } + let approximationComponents = calendar.dateComponents( + [.year, .month, .day, .hour, .minute, .second], + from: firstApproximation) + guard approximationComponents.year == year, + approximationComponents.month == month, + approximationComponents.day == day, + approximationComponents.hour == hour, + approximationComponents.minute == minute, + approximationComponents.second == 0 + else { return [] } + let startOfDay = calendar.startOfDay(for: firstApproximation) + guard let searchStart = calendar.date(byAdding: .second, value: -1, to: startOfDay) else { return [] } + + var results: [Date] = [] + for policy in [Calendar.RepeatedTimePolicy.first, .last] { + guard let date = calendar.nextDate( + after: searchStart, + matching: target, + matchingPolicy: .strict, + repeatedTimePolicy: policy, + direction: .forward) + else { continue } + let resolved = calendar.dateComponents([.year, .month, .day, .hour, .minute, .second], from: date) + guard resolved.year == year, + resolved.month == month, + resolved.day == day, + resolved.hour == hour, + resolved.minute == minute, + resolved.second == 0, + !results.contains(date) + else { continue } + results.append(date) + } + return results + } + + private static let resetTimeWithMinutes = ["h:mma", "h:mm a", "HH:mm", "H:mm"] + private static let resetTimeHourOnly = ["ha", "h a"] + + private static let resetDateTimeWithExplicitYear = [ + "MMM d, yyyy, h:mma", + "MMM d, yyyy, h:mm a", + "MMM d, yyyy, HH:mm", + "MMM d, yyyy h:mma", + "MMM d, yyyy h:mm a", + "MMM d, yyyy HH:mm", + "MMM d yyyy h:mma", + "MMM d yyyy h:mm a", + "MMM d yyyy HH:mm", + "MMM d, yyyy, ha", + "MMM d, yyyy, h a", + "MMM d, yyyy, HH", + "MMM d, yyyy ha", + "MMM d, yyyy h a", + "MMM d, yyyy HH", + "MMM d yyyy ha", + "MMM d yyyy h a", + "MMM d yyyy HH", + ] + + private static let resetDateTimeWithMinutes = [ + "MMM d, h:mma", + "MMM d, h:mm a", + "MMM d h:mma", + "MMM d h:mm a", + "MMM d, HH:mm", + "MMM d HH:mm", + ] + + private static let resetDateTimeHourOnly = [ + "MMM d, ha", + "MMM d, h a", + "MMM d ha", + "MMM d h a", + ] + + private static func normalizeResetInput(_ text: String?) -> (String, TimeZone?)? { + guard var raw = text?.trimmingCharacters(in: .whitespacesAndNewlines), !raw.isEmpty else { return nil } + raw = raw.replacingOccurrences(of: #"(?i)^resets?:?\s*"#, with: "", options: .regularExpression) + raw = raw.replacingOccurrences(of: " at ", with: " ", options: .caseInsensitive) + raw = raw.replacingOccurrences(of: #"(?i)\b([A-Za-z]{3})(\d)"#, with: "$1 $2", options: .regularExpression) + raw = raw.replacingOccurrences(of: #",(\d)"#, with: ", $1", options: .regularExpression) + raw = raw.replacingOccurrences(of: #"(?i)(\d)at(?=\d)"#, with: "$1 ", options: .regularExpression) + raw = raw.replacingOccurrences( + of: #"(?<=\d)\.(\d{2})\b"#, + with: ":$1", + options: .regularExpression) + + let timeZone = self.extractTimeZone(from: &raw) + raw = raw.replacingOccurrences(of: #"\s+"#, with: " ", options: .regularExpression) + .trimmingCharacters(in: .whitespacesAndNewlines) + return raw.isEmpty ? nil : (raw, timeZone) + } + + private static func extractTimeZone(from text: inout String) -> TimeZone? { + guard let tzRange = text.range(of: #"\(([^)]+)\)"#, options: .regularExpression) else { return nil } + let tzID = String(text[tzRange]).trimmingCharacters(in: CharacterSet(charactersIn: "() ")) + text.removeSubrange(tzRange) + text = text.trimmingCharacters(in: .whitespacesAndNewlines) + return TimeZone(identifier: tzID) + } + + private static func parseDate(_ text: String, formats: [String], formatter: DateFormatter) -> Date? { + for pattern in formats { + formatter.dateFormat = pattern + if let date = formatter.date(from: text) { + return date + } + } + return nil + } + + /// Extract login/plan string from CLI output. + private static func extractLoginMethod(text: String) -> String? { + guard !text.isEmpty else { return nil } + if let explicit = self.extractFirst(pattern: #"(?i)login\s+method:\s*(.+)"#, text: text) { + return ClaudePlan.cliCompatibilityLoginMethod(self.cleanPlan(explicit)) + } + // Capture any "Claude <...>" phrase (e.g., Max/Pro/Ultra/Team) to avoid future plan-name churn. + // Strip any leading ANSI that may have survived (rare) before matching. + // Use horizontal whitespace ([ \t]) rather than \s so the match stays on a single rendered line: + // \s spans newlines, which let "…use Claude" bridge into the /usage panel's "d → today" hint and + // produced a bogus "Dtoday" plan label after ANSI stripping glued the lines together. + let planPattern = #"(?i)(claude[ \t]+[a-z0-9][a-z0-9 \t._-]{0,24})"# + var candidates: [String] = [] + if let regex = try? NSRegularExpression(pattern: planPattern, options: []) { + let nsrange = NSRange(text.startIndex..= 2, + let r = Range(match.range(at: 1), in: text) else { return } + let raw = String(text[r]) + let val = ClaudePlan.cliCompatibilityLoginMethod(Self.cleanPlan(raw)) ?? Self.cleanPlan(raw) + candidates.append(val) + } + } + if let plan = candidates.first(where: { cand in + let lower = cand.lowercased() + return !lower.contains("code v") && !lower.contains("code version") && !lower.contains("code") + }) { + return plan + } + return nil + } + + /// Strips ANSI and stray bracketed codes like "[22m" that can survive CLI output. + private static func cleanPlan(_ text: String) -> String { + UsageFormatter.cleanPlanName(text) + } + + private static func dumpIfNeeded(enabled: Bool, reason: String, usage: String, status: String?) { + guard enabled else { return } + let stamp = ISO8601DateFormatter().string(from: Date()) + var parts = [ + "=== Claude parse dump @ \(stamp) ===", + "Reason: \(reason)", + "", + "--- usage (clean) ---", + usage, + "", + ] + if let status { + parts.append(contentsOf: [ + "--- status (raw/optional) ---", + status, + "", + ]) + } + let body = parts.joined(separator: "\n") + Task { @MainActor in self.recordDump(body) } + } + + // MARK: - Dump storage (in-memory ring buffer) + + @MainActor private static var recentDumps: [String] = [] + + @MainActor private static func recordDump(_ text: String) { + if self.recentDumps.count >= 5 { + self.recentDumps.removeFirst() + } + self.recentDumps.append(text) + } + + public static func latestDumps() async -> String { + await MainActor.run { + let result = Self.recentDumps.joined(separator: "\n\n---\n\n") + return result.isEmpty ? "No Claude parse dumps captured yet." : result + } + } + + #if DEBUG + public static func _replaceDumpsForTesting(_ dumps: [String]) async { + await MainActor.run { + self.recentDumps = dumps + } + } + #endif + + private static func extractUsageErrorJSON(text: String) -> String? { + let pattern = #"Failed\s*to\s*load\s*usage\s*data:\s*(\{.*\})"# + guard let regex = try? NSRegularExpression(pattern: pattern, options: [.dotMatchesLineSeparators]) else { + return nil + } + let range = NSRange(text.startIndex..= 2, + let jsonRange = Range(match.range(at: 1), in: text) + else { + return nil + } + + let jsonString = String(text[jsonRange]) + let compactJSON = jsonString.replacingOccurrences(of: "\r", with: "").replacingOccurrences(of: "\n", with: "") + let data = (compactJSON.isEmpty ? jsonString : compactJSON).data(using: .utf8) + guard let data, + let payload = try? JSONSerialization.jsonObject(with: data) as? [String: Any], + let error = payload["error"] as? [String: Any] + else { + return nil + } + + let message = (error["message"] as? String)?.trimmingCharacters(in: .whitespacesAndNewlines) + let details = error["details"] as? [String: Any] + let code = (details?["error_code"] as? String)?.trimmingCharacters(in: .whitespacesAndNewlines) + let type = (error["type"] as? String)?.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() + + if type == "rate_limit_error" { + return "Claude CLI usage endpoint is rate limited right now. Please try again later." + } + + var parts: [String] = [] + if let message, !message.isEmpty { + parts.append(message) + } + if let code, !code.isEmpty { + parts.append("(\(code))") + } + + guard !parts.isEmpty else { return nil } + let hint = parts.joined(separator: " ") + + if let code, code.lowercased().contains("token") { + return "\(hint). Run `claude login` to refresh." + } + return "Claude CLI error: \(hint)" + } + + // MARK: - Process helpers + + private static func resolvedBinaryPath( + binaryName: String, + environment: [String: String] = ProcessInfo.processInfo.environment) -> String? + { + if binaryName.contains("/") { + return binaryName + } + return ClaudeCLIResolver.resolvedBinaryPath(environment: environment) + } + + private static func isBinaryAvailable(_ binaryPathOrName: String?) -> Bool { + guard let binaryPathOrName else { return false } + return FileManager.default.isExecutableFile(atPath: binaryPathOrName) + || TTYCommandRunner.which(binaryPathOrName) != nil + } + + static func probeWorkingDirectoryURL() -> URL { + let fm = FileManager.default + let base = fm.urls(for: .applicationSupportDirectory, in: .userDomainMask).first ?? fm.temporaryDirectory + let dir = base + .appendingPathComponent("CodexBar", isDirectory: true) + .appendingPathComponent("ClaudeProbe", isDirectory: true) + do { + try fm.createDirectory(at: dir, withIntermediateDirectories: true) + return dir + } catch { + return fm.temporaryDirectory + } + } + + static func preparedProbeWorkingDirectoryURL() -> URL { + let directory = self.probeWorkingDirectoryURL() + do { + try self.prepareProbeWorkingDirectory(at: directory) + } catch { + Self.log.warning( + "Claude probe local settings unavailable", + metadata: ["error": error.localizedDescription]) + } + return directory + } + + static func prepareProbeWorkingDirectory(at directory: URL, fileManager fm: FileManager = .default) throws { + try fm.createDirectory(at: directory, withIntermediateDirectories: true) + let claudeDirectory = directory.appendingPathComponent(".claude", isDirectory: true) + try fm.createDirectory(at: claudeDirectory, withIntermediateDirectories: true) + + let settingsURL = claudeDirectory.appendingPathComponent("settings.local.json") + var settings = (try? self.readSettingsObject(from: settingsURL, fileManager: fm)) ?? [:] + settings["disableDeepLinkRegistration"] = "disable" + let data = try JSONSerialization.data( + withJSONObject: settings, + options: [.prettyPrinted, .sortedKeys]) + try data.write(to: settingsURL, options: .atomic) + } + + private static func readSettingsObject(from url: URL, fileManager fm: FileManager) throws -> [String: Any] { + guard fm.fileExists(atPath: url.path) else { + return [:] + } + let data = try Data(contentsOf: url) + guard !data.isEmpty else { + return [:] + } + let object = try JSONSerialization.jsonObject(with: data) + return object as? [String: Any] ?? [:] + } + + /// Run claude CLI inside a PTY so we can respond to interactive permission prompts. + private static func capture(subcommand: String, binary: String, timeout: TimeInterval) async throws -> String { + let stopOnSubstrings = subcommand == "/usage" + ? [ + "Failed to load usage data", + "failed to load usage data", + "Failedto loadusagedata", + "failedtoloadusagedata", + ] + : [] + let idleTimeout: TimeInterval? = subcommand == "/usage" ? nil : 3.0 + let sendEnterEvery: TimeInterval? = subcommand == "/usage" ? 0.8 : nil + let stopWhenNormalized: (@Sendable (String) -> Bool)? = subcommand == "/usage" + ? { @Sendable normalizedScan in + Self.usageCaptureHasSessionValue(normalizedScan) + || Self.usageCaptureHasSubscriptionNotice(normalizedScan) + } + : nil + do { + return try await ClaudeCLISession.current.capture( + subcommand: subcommand, + binary: binary, + timeout: timeout, + idleTimeout: idleTimeout, + stopOnSubstrings: stopOnSubstrings, + stopWhenNormalized: stopWhenNormalized, + settleAfterStop: subcommand == "/usage" ? 2.0 : 0.25, + sendEnterEvery: sendEnterEvery) + } catch ClaudeCLISession.SessionError.processExited { + await ClaudeCLISession.current.reset() + throw ClaudeStatusProbeError.timedOut + } catch ClaudeCLISession.SessionError.timedOut { + await ClaudeCLISession.current.reset() + throw ClaudeStatusProbeError.timedOut + } catch ClaudeCLISession.SessionError.launchFailed(_) { + throw ClaudeStatusProbeError.claudeNotInstalled + } catch { + await ClaudeCLISession.current.reset() + throw error + } + } + + private static func usageCaptureHasSessionValue(_ normalizedText: String) -> Bool { + guard let labelRange = normalizedText.range(of: "currentsession") else { return false } + let tail = normalizedText[labelRange.upperBound...] + return tail.range(of: #"[0-9]{1,3}(?:\.[0-9]+)?%"#, options: .regularExpression) != nil + } + + private static func usageCaptureHasSubscriptionNotice(_ normalizedText: String) -> Bool { + normalizedText.contains("currentlyusingyoursubscription") + && normalizedText.contains("claudecodeusage") + } +} diff --git a/Sources/CodexBarCore/Providers/Claude/ClaudeSwap/ClaudeSwapAccountList.swift b/Sources/CodexBarCore/Providers/Claude/ClaudeSwap/ClaudeSwapAccountList.swift new file mode 100644 index 0000000..097b118 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Claude/ClaudeSwap/ClaudeSwapAccountList.swift @@ -0,0 +1,216 @@ +import CoreFoundation +import Foundation + +/// Strictly parsed result of `cswap --list --json` (schema v1). +/// +/// Only the fields allow-listed in `docs/claude-multi-account-and-status-items.md` +/// are decoded: slot number, display email, active state, usage status, and the +/// 5-hour/7-day windows (percent + reset timestamp). Everything else in the +/// payload is ignored; unknown schema versions and partial top-level shapes are +/// rejected. +public struct ClaudeSwapAccountList: Equatable, Sendable { + public let activeAccountNumber: Int? + public let accounts: [ClaudeSwapAccountRow] + + public init(activeAccountNumber: Int?, accounts: [ClaudeSwapAccountRow]) { + self.activeAccountNumber = activeAccountNumber + self.accounts = accounts + } +} + +public struct ClaudeSwapAccountRow: Equatable, Sendable { + public let number: Int + /// Display-only sensitive value; never logged or persisted. + public let email: String + public let isActive: Bool + public let usageStatus: ClaudeSwapUsageStatus + public let fiveHour: ClaudeSwapUsageWindow? + public let sevenDay: ClaudeSwapUsageWindow? + + public init( + number: Int, + email: String, + isActive: Bool, + usageStatus: ClaudeSwapUsageStatus, + fiveHour: ClaudeSwapUsageWindow?, + sevenDay: ClaudeSwapUsageWindow?) + { + self.number = number + self.email = email + self.isActive = isActive + self.usageStatus = usageStatus + self.fiveHour = fiveHour + self.sevenDay = sevenDay + } +} + +public struct ClaudeSwapUsageWindow: Equatable, Sendable { + public let usedPercent: Double + public let resetsAt: Date? + + public init(usedPercent: Double, resetsAt: Date?) { + self.usedPercent = usedPercent + self.resetsAt = resetsAt + } +} + +/// The sentinel statuses `cswap` emits per account. Unknown values from newer +/// claude-swap releases are preserved rather than failing the whole payload. +public enum ClaudeSwapUsageStatus: Equatable, Sendable { + case ok + case tokenExpired + case apiKey + case keychainUnavailable + case noCredentials + case unavailable + case unknown(String) + + init(rawValue: String) { + switch rawValue { + case "ok": self = .ok + case "token_expired": self = .tokenExpired + case "api_key": self = .apiKey + case "keychain_unavailable": self = .keychainUnavailable + case "no_credentials": self = .noCredentials + case "unavailable": self = .unavailable + default: self = .unknown(rawValue) + } + } +} + +public enum ClaudeSwapListParserError: LocalizedError, Equatable, Sendable { + case notJSONObject + case missingSchemaVersion + case unsupportedSchemaVersion(Int) + case reportedError(type: String, message: String) + case malformedShape(String) + + public var errorDescription: String? { + switch self { + case .notJSONObject: + "claude-swap returned output that is not a JSON object." + case .missingSchemaVersion: + "claude-swap output has no schemaVersion field." + case let .unsupportedSchemaVersion(version): + "claude-swap output uses unsupported schema version \(version); CodexBar supports version 1." + case let .reportedError(type, message): + "claude-swap reported \(type): \(message)" + case let .malformedShape(details): + "claude-swap output is malformed: \(details)" + } + } +} + +public enum ClaudeSwapListParser { + public static let supportedSchemaVersion = 1 + + public static func parse(_ data: Data) throws -> ClaudeSwapAccountList { + let raw: Any + do { + raw = try JSONSerialization.jsonObject(with: data) + } catch { + throw ClaudeSwapListParserError.notJSONObject + } + guard let object = raw as? [String: Any] else { + throw ClaudeSwapListParserError.notJSONObject + } + guard let schemaVersion = object["schemaVersion"] as? Int else { + throw ClaudeSwapListParserError.missingSchemaVersion + } + guard schemaVersion == self.supportedSchemaVersion else { + throw ClaudeSwapListParserError.unsupportedSchemaVersion(schemaVersion) + } + if let errorObject = object["error"] as? [String: Any] { + throw ClaudeSwapListParserError.reportedError( + type: errorObject["type"] as? String ?? "Error", + message: errorObject["message"] as? String ?? "unknown error") + } + guard let rawAccounts = object["accounts"] as? [Any] else { + throw ClaudeSwapListParserError.malformedShape("missing accounts array") + } + guard let rawActiveAccountNumber = object["activeAccountNumber"] else { + throw ClaudeSwapListParserError.malformedShape("missing activeAccountNumber") + } + let activeAccountNumber: Int? = switch rawActiveAccountNumber { + case is NSNull: nil + case let number as Int where number > 0: number + default: + throw ClaudeSwapListParserError.malformedShape("activeAccountNumber is not a numeric slot or null") + } + var seenSlots: Set = [] + let accounts = try rawAccounts.map { rawRow -> ClaudeSwapAccountRow in + guard let row = rawRow as? [String: Any] else { + throw ClaudeSwapListParserError.malformedShape("account row is not an object") + } + let account = try self.parseRow(row) + guard seenSlots.insert(account.number).inserted else { + throw ClaudeSwapListParserError.malformedShape("duplicate account slot \(account.number)") + } + return account + } + let activeSlots = accounts.filter(\.isActive).map(\.number) + guard activeSlots == (activeAccountNumber.map { [$0] } ?? []) else { + throw ClaudeSwapListParserError.malformedShape("active account fields disagree") + } + return ClaudeSwapAccountList(activeAccountNumber: activeAccountNumber, accounts: accounts) + } + + private static func parseRow(_ row: [String: Any]) throws -> ClaudeSwapAccountRow { + guard let number = row["number"] as? Int else { + throw ClaudeSwapListParserError.malformedShape("account row has no numeric slot") + } + guard number > 0 else { + throw ClaudeSwapListParserError.malformedShape("account slot must be positive") + } + guard let isActive = row["active"] as? Bool else { + throw ClaudeSwapListParserError.malformedShape("slot \(number) has no active flag") + } + guard let rawStatus = row["usageStatus"] as? String else { + throw ClaudeSwapListParserError.malformedShape("slot \(number) has no usageStatus") + } + let email = (row["email"] as? String ?? "").trimmingCharacters(in: .whitespacesAndNewlines) + let usage = row["usage"] as? [String: Any] + return try ClaudeSwapAccountRow( + number: number, + email: email, + isActive: isActive, + usageStatus: ClaudeSwapUsageStatus(rawValue: rawStatus), + fiveHour: self.parseWindow(usage?["fiveHour"], slot: number, name: "fiveHour"), + sevenDay: self.parseWindow(usage?["sevenDay"], slot: number, name: "sevenDay")) + } + + private static func parseWindow(_ raw: Any?, slot: Int, name: String) throws -> ClaudeSwapUsageWindow? { + guard let raw else { return nil } + guard let window = raw as? [String: Any] else { + throw ClaudeSwapListParserError.malformedShape("slot \(slot) \(name) window is not an object") + } + guard let pct = Self.finiteDouble(window["pct"]) else { + throw ClaudeSwapListParserError.malformedShape("slot \(slot) \(name) percent is not a finite number") + } + var resetsAt: Date? + if let rawResetsAt = window["resetsAt"] { + guard let text = rawResetsAt as? String, let date = Self.parseTimestamp(text) else { + throw ClaudeSwapListParserError.malformedShape("slot \(slot) \(name) resetsAt is not a timestamp") + } + resetsAt = date + } + return ClaudeSwapUsageWindow(usedPercent: min(max(pct, 0), 100), resetsAt: resetsAt) + } + + private static func finiteDouble(_ raw: Any?) -> Double? { + guard let number = raw as? NSNumber else { return nil } + // JSON booleans bridge to NSNumber too; only accept genuine numbers. + guard CFGetTypeID(number) != CFBooleanGetTypeID() else { return nil } + let value = number.doubleValue + return value.isFinite ? value : nil + } + + private static func parseTimestamp(_ text: String) -> Date? { + let withFraction = ISO8601DateFormatter() + withFraction.formatOptions = [.withInternetDateTime, .withFractionalSeconds] + if let date = withFraction.date(from: text) { return date } + let plain = ISO8601DateFormatter() + plain.formatOptions = [.withInternetDateTime] + return plain.date(from: text) + } +} diff --git a/Sources/CodexBarCore/Providers/Claude/ClaudeSwap/ClaudeSwapAccountProjection.swift b/Sources/CodexBarCore/Providers/Claude/ClaudeSwap/ClaudeSwapAccountProjection.swift new file mode 100644 index 0000000..6fa1366 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Claude/ClaudeSwap/ClaudeSwapAccountProjection.swift @@ -0,0 +1,102 @@ +import Foundation + +/// Projects parsed `cswap --list --json` rows into the provider-neutral +/// account snapshot consumed by menus. Identity uses the source-issued numeric +/// slot (`claude-swap:`), never email or credential-derived values. +public enum ClaudeSwapAccountProjection { + public static let sourceName = "claude-swap" + public static let sourceLabel = "claude-swap" + static let fiveHourWindowMinutes = 5 * 60 + static let sevenDayWindowMinutes = 7 * 24 * 60 + + public static func accountSnapshots( + from list: ClaudeSwapAccountList, + now: Date = Date()) -> [ProviderAccountUsageSnapshot] + { + let ordered = list.accounts.sorted { lhs, rhs in + if lhs.isActive != rhs.isActive { return lhs.isActive } + return lhs.number < rhs.number + } + return ordered.map { row in + ProviderAccountUsageSnapshot( + id: ProviderAccountIdentity(source: self.sourceName, opaqueID: String(row.number)), + provider: .claude, + displayLabel: self.displayLabel(for: row), + isActive: row.isActive, + canActivate: !row.isActive && self.canActivate(row), + snapshot: self.usageSnapshot(for: row, now: now), + error: self.errorText(for: row), + sourceLabel: self.sourceLabel) + } + } + + public static func displayError( + accountError: String?, + adapterError: String?, + switchError: String? = nil) -> String? + { + switchError.map { "Account switch failed: \($0)" } + ?? accountError + ?? adapterError.map { "Showing the last successful update: \($0)" } + } + + static func displayLabel(for row: ClaudeSwapAccountRow) -> String { + row.email.isEmpty ? "Account \(row.number)" : row.email + } + + private static func usageSnapshot(for row: ClaudeSwapAccountRow, now: Date) -> UsageSnapshot? { + guard row.usageStatus == .ok else { return nil } + let primary = row.fiveHour.map { window in + RateWindow( + usedPercent: window.usedPercent, + windowMinutes: self.fiveHourWindowMinutes, + resetsAt: window.resetsAt, + resetDescription: nil) + } + let secondary = row.sevenDay.map { window in + RateWindow( + usedPercent: window.usedPercent, + windowMinutes: self.sevenDayWindowMinutes, + resetsAt: window.resetsAt, + resetDescription: nil) + } + guard primary != nil || secondary != nil else { return nil } + return UsageSnapshot( + primary: primary, + secondary: secondary, + updatedAt: now, + identity: ProviderIdentitySnapshot( + providerID: .claude, + accountEmail: self.displayLabel(for: row), + accountOrganization: nil, + loginMethod: self.sourceLabel)) + } + + private static func errorText(for row: ClaudeSwapAccountRow) -> String? { + switch row.usageStatus { + case .ok: + row.fiveHour == nil && row.sevenDay == nil ? "No usage windows reported." : nil + case .tokenExpired: + "Token expired. Switch to this account in claude-swap to refresh it." + case .apiKey: + "API-key account; subscription usage is unavailable." + case .keychainUnavailable: + "claude-swap could not read the active account's Keychain entry." + case .noCredentials: + "No stored credentials for this account slot." + case .unavailable: + "Usage fetch failed." + case let .unknown(raw): + "Unrecognized claude-swap status: \(raw)" + } + } + + private static func canActivate(_ row: ClaudeSwapAccountRow) -> Bool { + switch row.usageStatus { + case .ok, .apiKey, .unavailable: + true + case .tokenExpired, .keychainUnavailable, .noCredentials, .unknown: + false + } + } +} diff --git a/Sources/CodexBarCore/Providers/Claude/ClaudeSwap/ClaudeSwapAccountReader.swift b/Sources/CodexBarCore/Providers/Claude/ClaudeSwap/ClaudeSwapAccountReader.swift new file mode 100644 index 0000000..5896400 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Claude/ClaudeSwap/ClaudeSwapAccountReader.swift @@ -0,0 +1,141 @@ +import Foundation + +public enum ClaudeSwapAccountReaderError: LocalizedError, Sendable { + case executablePathNotConfigured + case outputTooLarge(byteCount: Int) + + public var errorDescription: String? { + switch self { + case .executablePathNotConfigured: + "No claude-swap executable path is configured." + case let .outputTooLarge(byteCount): + "claude-swap produced \(byteCount) bytes of output; refusing to parse more than " + + "\(ClaudeSwapAccountReader.maxOutputBytes)." + } + } +} + +/// Bounded adapter over the external `claude-swap` executable. +/// +/// Executes only the fixed list and explicit switch argument arrays (never a +/// shell or config-defined passthrough arguments), per the contracts in +/// `docs/claude-multi-account-and-status-items.md`. CodexBar never reads +/// claude-swap or Claude Code credential storage; the subprocess is solely +/// responsible for its own credential access. +public enum ClaudeSwapAccountReader { + public static let maxOutputBytes = 262_144 + public static let defaultTimeout: TimeInterval = 30 + + public static func readAccountList( + executablePath: String, + timeout: TimeInterval = ClaudeSwapAccountReader.defaultTimeout) async throws -> ClaudeSwapAccountList + { + // Handled claude-swap failures print a schema-v1 error envelope to stdout + // and exit non-zero, so non-zero exits still parse; the parser surfaces + // the envelope as `ClaudeSwapListParserError.reportedError`. + let result = try await self.run( + executablePath: executablePath, + arguments: ["--list", "--json"], + timeout: timeout, + acceptsNonZeroExit: true, + label: "claude-swap list") + return try ClaudeSwapListParser.parse(Data(result.utf8)) + } + + /// Activates one source-issued numeric slot through claude-swap. + /// + /// The external tool owns the credential transaction. CodexBar supplies no + /// credentials and accepts no config-defined arguments. + public static func switchAccount( + executablePath: String, + accountNumber: Int) async throws + -> ClaudeSwapAccountSwitchResult + { + guard accountNumber > 0 else { + throw ClaudeSwapSwitchParserError.malformedShape("requested account slot must be positive") + } + let result = try await self.runCredentialTransaction( + executablePath: executablePath, + arguments: ["--switch-to", String(accountNumber), "--json"], + acceptsNonZeroExit: true, + label: "claude-swap switch") + let parsed = try ClaudeSwapSwitchParser.parse(Data(result.utf8)) + guard parsed.toAccountNumber == accountNumber else { + throw ClaudeSwapSwitchParserError.mismatchedTarget( + expected: accountNumber, + actual: parsed.toAccountNumber) + } + return parsed + } + + /// Best-effort version probe (`cswap --version` prints `cswap `). + public static func readVersion( + executablePath: String, + timeout: TimeInterval = 10) async -> String? + { + guard let output = try? await self.run( + executablePath: executablePath, + arguments: ["--version"], + timeout: timeout, + label: "claude-swap version") + else { + return nil + } + let trimmed = output.trimmingCharacters(in: .whitespacesAndNewlines) + guard let version = trimmed.split(whereSeparator: \.isWhitespace).last, !version.isEmpty else { + return nil + } + return String(version) + } + + public static func resolvedExecutablePath(_ configuredPath: String) throws -> String { + let trimmed = configuredPath.trimmingCharacters(in: .whitespacesAndNewlines) + guard !trimmed.isEmpty else { + throw ClaudeSwapAccountReaderError.executablePathNotConfigured + } + return (trimmed as NSString).expandingTildeInPath + } + + private static func run( + executablePath: String, + arguments: [String], + timeout: TimeInterval, + acceptsNonZeroExit: Bool = false, + label: String) async throws -> String + { + try Task.checkCancellation() + let binary = try self.resolvedExecutablePath(executablePath) + let result = try await SubprocessRunner.run( + binary: binary, + arguments: arguments, + environment: ProcessInfo.processInfo.environment, + timeout: timeout, + acceptsNonZeroExit: acceptsNonZeroExit, + label: label) + guard result.stdout.utf8.count <= self.maxOutputBytes else { + throw ClaudeSwapAccountReaderError.outputTooLarge(byteCount: result.stdout.utf8.count) + } + return result.stdout + } + + /// Once launched, a credential mutation must reach the external tool's + /// natural exit; caller cancellation and read-probe timeouts must not kill it. + private static func runCredentialTransaction( + executablePath: String, + arguments: [String], + acceptsNonZeroExit: Bool, + label: String) async throws -> String + { + let binary = try self.resolvedExecutablePath(executablePath) + let result = try await SubprocessRunner.runToCompletion( + binary: binary, + arguments: arguments, + environment: ProcessInfo.processInfo.environment, + acceptsNonZeroExit: acceptsNonZeroExit, + label: label) + guard result.stdout.utf8.count <= self.maxOutputBytes else { + throw ClaudeSwapAccountReaderError.outputTooLarge(byteCount: result.stdout.utf8.count) + } + return result.stdout + } +} diff --git a/Sources/CodexBarCore/Providers/Claude/ClaudeSwap/ClaudeSwapAccountSwitch.swift b/Sources/CodexBarCore/Providers/Claude/ClaudeSwap/ClaudeSwapAccountSwitch.swift new file mode 100644 index 0000000..de539ed --- /dev/null +++ b/Sources/CodexBarCore/Providers/Claude/ClaudeSwap/ClaudeSwapAccountSwitch.swift @@ -0,0 +1,117 @@ +import CoreFoundation +import Foundation + +/// Allow-listed result of `cswap --switch-to --json` (schema v1). +public struct ClaudeSwapAccountSwitchResult: Equatable, Sendable { + public let switched: Bool + public let fromAccountNumber: Int? + public let toAccountNumber: Int + public let reason: String + + public init(switched: Bool, fromAccountNumber: Int?, toAccountNumber: Int, reason: String) { + self.switched = switched + self.fromAccountNumber = fromAccountNumber + self.toAccountNumber = toAccountNumber + self.reason = reason + } +} + +public enum ClaudeSwapSwitchParserError: LocalizedError, Equatable, Sendable { + case notJSONObject + case missingSchemaVersion + case unsupportedSchemaVersion(Int) + case reportedError(type: String, message: String) + case malformedShape(String) + case mismatchedTarget(expected: Int, actual: Int) + + public var errorDescription: String? { + switch self { + case .notJSONObject: + "claude-swap returned switch output that is not a JSON object." + case .missingSchemaVersion: + "claude-swap switch output has no schemaVersion field." + case let .unsupportedSchemaVersion(version): + "claude-swap switch output uses unsupported schema version \(version); CodexBar supports version 1." + case let .reportedError(type, message): + "claude-swap reported \(type): \(message)" + case let .malformedShape(details): + "claude-swap switch output is malformed: \(details)" + case let .mismatchedTarget(expected, actual): + "claude-swap reported account slot \(actual) after CodexBar requested slot \(expected)." + } + } +} + +public enum ClaudeSwapSwitchParser { + public static func parse(_ data: Data) throws -> ClaudeSwapAccountSwitchResult { + let raw: Any + do { + raw = try JSONSerialization.jsonObject(with: data) + } catch { + throw ClaudeSwapSwitchParserError.notJSONObject + } + guard let object = raw as? [String: Any] else { + throw ClaudeSwapSwitchParserError.notJSONObject + } + guard let schemaVersion = self.integer(object["schemaVersion"]) else { + throw ClaudeSwapSwitchParserError.missingSchemaVersion + } + guard schemaVersion == ClaudeSwapListParser.supportedSchemaVersion else { + throw ClaudeSwapSwitchParserError.unsupportedSchemaVersion(schemaVersion) + } + if let errorObject = object["error"] as? [String: Any] { + throw ClaudeSwapSwitchParserError.reportedError( + type: errorObject["type"] as? String ?? "Error", + message: errorObject["message"] as? String ?? "unknown error") + } + guard let switched = object["switched"] as? Bool else { + throw ClaudeSwapSwitchParserError.malformedShape("missing switched flag") + } + guard let reason = (object["reason"] as? String)?.trimmingCharacters(in: .whitespacesAndNewlines), + !reason.isEmpty + else { + throw ClaudeSwapSwitchParserError.malformedShape("missing reason") + } + let fromAccountNumber = try self.accountNumber( + in: object["from"], + field: "from", + allowsNull: true) + guard let toAccountNumber = try self.accountNumber( + in: object["to"], + field: "to", + allowsNull: false) + else { + throw ClaudeSwapSwitchParserError.malformedShape("to account has no numeric slot") + } + return ClaudeSwapAccountSwitchResult( + switched: switched, + fromAccountNumber: fromAccountNumber, + toAccountNumber: toAccountNumber, + reason: reason) + } + + private static func accountNumber(in raw: Any?, field: String, allowsNull: Bool) throws -> Int? { + if raw is NSNull, allowsNull { return nil } + guard let account = raw as? [String: Any] else { + throw ClaudeSwapSwitchParserError.malformedShape("missing \(field) account") + } + guard let rawNumber = account["number"] else { + throw ClaudeSwapSwitchParserError.malformedShape("\(field) account has no number") + } + if rawNumber is NSNull, allowsNull { return nil } + guard let number = self.integer(rawNumber), number > 0 + else { + throw ClaudeSwapSwitchParserError.malformedShape("\(field) account number is not a positive slot") + } + return number + } + + private static func integer(_ raw: Any?) -> Int? { + guard let number = raw as? NSNumber, + CFGetTypeID(number) != CFBooleanGetTypeID() + else { + return nil + } + return raw as? Int + } +} diff --git a/Sources/CodexBarCore/Providers/Claude/ClaudeUsageDataSource.swift b/Sources/CodexBarCore/Providers/Claude/ClaudeUsageDataSource.swift new file mode 100644 index 0000000..063de7f --- /dev/null +++ b/Sources/CodexBarCore/Providers/Claude/ClaudeUsageDataSource.swift @@ -0,0 +1,38 @@ +import Foundation + +public enum ClaudeUsageDataSource: String, CaseIterable, Identifiable, Sendable { + case auto + case api + case oauth + case web + case cli + + public var id: String { + self.rawValue + } + + public var displayName: String { + switch self { + case .auto: "Auto" + case .api: "API (Admin key)" + case .oauth: "OAuth API" + case .web: "Web API (cookies)" + case .cli: "CLI (PTY)" + } + } + + public var sourceLabel: String { + switch self { + case .auto: + "auto" + case .api: + "api" + case .oauth: + "oauth" + case .web: + "web" + case .cli: + "cli" + } + } +} diff --git a/Sources/CodexBarCore/Providers/Claude/ClaudeUsageFetcher.swift b/Sources/CodexBarCore/Providers/Claude/ClaudeUsageFetcher.swift new file mode 100644 index 0000000..1bfd3aa --- /dev/null +++ b/Sources/CodexBarCore/Providers/Claude/ClaudeUsageFetcher.swift @@ -0,0 +1,1533 @@ +import Foundation + +public protocol ClaudeUsageFetching: Sendable { + func loadLatestUsage(model: String) async throws -> ClaudeUsageSnapshot + func debugRawProbe(model: String) async -> String + func detectVersion() -> String? +} + +public struct ClaudeUsageSnapshot: Sendable { + public enum PrimaryWindowKind: Equatable, Sendable { + case usage + case spendLimit + } + + public let primary: RateWindow + public let primaryWindowKind: PrimaryWindowKind + public let secondary: RateWindow? + public let opus: RateWindow? + public let extraRateWindows: [NamedRateWindow] + public let providerCost: ProviderCostSnapshot? + public let updatedAt: Date + public let accountEmail: String? + public let accountOrganization: String? + public let loginMethod: String? + public let rawText: String? + /// Present only when the credential used for this OAuth fetch matches the current Claude Keychain item. + public let oauthKeychainPersistentRefHash: String? + /// One-way, high-entropy ownership evidence derived from the exact credential used for this OAuth fetch. + public let oauthHistoryOwnerIdentifier: String? + /// True when a prompt-free comparison proved this credential differs from Claude Code's Keychain entry. + public let oauthKeychainCredentialMismatch: Bool + /// True when a prompt-free probe proved Claude Code has no Keychain credential. + public let oauthKeychainCredentialAbsent: Bool + /// True when a Claude CLI credential won routing but the prompt-free Keychain comparison was unavailable. + public let oauthKeychainCredentialUnavailable: Bool + + public init( + primary: RateWindow, + primaryWindowKind: PrimaryWindowKind = .usage, + secondary: RateWindow?, + opus: RateWindow?, + extraRateWindows: [NamedRateWindow] = [], + providerCost: ProviderCostSnapshot? = nil, + updatedAt: Date, + accountEmail: String?, + accountOrganization: String?, + loginMethod: String?, + rawText: String?, + oauthKeychainPersistentRefHash: String? = nil, + oauthHistoryOwnerIdentifier: String? = nil, + oauthKeychainCredentialMismatch: Bool = false, + oauthKeychainCredentialAbsent: Bool = false, + oauthKeychainCredentialUnavailable: Bool = false) + { + self.primary = primary + self.primaryWindowKind = primaryWindowKind + self.secondary = secondary + self.opus = opus + self.extraRateWindows = extraRateWindows + self.providerCost = providerCost + self.updatedAt = updatedAt + self.accountEmail = accountEmail + self.accountOrganization = accountOrganization + self.loginMethod = loginMethod + self.rawText = rawText + self.oauthKeychainPersistentRefHash = oauthKeychainPersistentRefHash + self.oauthHistoryOwnerIdentifier = oauthHistoryOwnerIdentifier + self.oauthKeychainCredentialMismatch = oauthKeychainCredentialMismatch + self.oauthKeychainCredentialAbsent = oauthKeychainCredentialAbsent + self.oauthKeychainCredentialUnavailable = oauthKeychainCredentialUnavailable + } +} + +public enum ClaudeUsageError: LocalizedError, Sendable { + case claudeNotInstalled + case parseFailed(String) + case oauthFailed(String) + + public var errorDescription: String? { + switch self { + case .claudeNotInstalled: + "Claude CLI is not installed. Install it from https://code.claude.com/docs/en/overview." + case let .parseFailed(details): + "Could not parse Claude usage: \(details)" + case let .oauthFailed(details): + details + } + } +} + +public struct ClaudeUsageFetcher: ClaudeUsageFetching, Sendable { + private static let sessionWindowMinutes = 5 * 60 + private static let weeklyWindowMinutes = 7 * 24 * 60 + private static let cliAutoProbeTimeout: TimeInterval = 12 + private static let cliProbeTimeout: TimeInterval = 24 + private static let cliRetryProbeTimeout: TimeInterval = 60 + private struct Configuration { + let environment: [String: String] + let runtime: ProviderRuntime + let dataSource: ClaudeUsageDataSource + let oauthKeychainPromptCooldownEnabled: Bool + let allowBackgroundDelegatedRefresh: Bool + let allowStartupBootstrapPrompt: Bool + let useWebExtras: Bool + let manualCookieHeader: String? + let webOrganizationID: String? + let keepCLISessionsAlive: Bool + let browserDetection: BrowserDetection + } + + private let configuration: Configuration + private static let log = CodexBarLog.logger(LogCategories.claudeUsage) + private static var isClaudeOAuthFlowDebugEnabled: Bool { + ProcessInfo.processInfo.environment["CODEXBAR_DEBUG_CLAUDE_OAUTH_FLOW"] == "1" + } + + private var environment: [String: String] { + self.configuration.environment + } + + private var runtime: ProviderRuntime { + self.configuration.runtime + } + + private var dataSource: ClaudeUsageDataSource { + self.configuration.dataSource + } + + private var oauthKeychainPromptCooldownEnabled: Bool { + self.configuration.oauthKeychainPromptCooldownEnabled + } + + private var allowsDelegatedOAuthRefresh: Bool { + self.runtime == .app + } + + private var allowsOAuthClaudeVersionDetection: Bool { + self.runtime == .app + } + + private var allowBackgroundDelegatedRefresh: Bool { + self.configuration.allowBackgroundDelegatedRefresh + } + + private var allowStartupBootstrapPrompt: Bool { + self.configuration.allowStartupBootstrapPrompt + } + + private var useWebExtras: Bool { + self.configuration.useWebExtras + } + + private var manualCookieHeader: String? { + self.configuration.manualCookieHeader + } + + private var webOrganizationID: String? { + self.configuration.webOrganizationID + } + + private var keepCLISessionsAlive: Bool { + self.configuration.keepCLISessionsAlive + } + + private var browserDetection: BrowserDetection { + self.configuration.browserDetection + } + + private struct ClaudeOAuthKeychainPromptPolicy { + let mode: ClaudeOAuthKeychainPromptMode + let isApplicable: Bool + let interaction: ProviderInteraction + + var canPromptNow: Bool { + switch self.mode { + case .never: + false + case .onlyOnUserAction: + self.interaction == .userInitiated + case .always: + true + } + } + + /// Respect the Keychain prompt cooldown for background operations to avoid spamming system dialogs. + /// User actions (menu open / refresh / settings) are allowed to bypass the cooldown. + var shouldRespectKeychainPromptCooldown: Bool { + self.interaction != .userInitiated + } + + var interactionLabel: String { + self.interaction == .userInitiated ? "user" : "background" + } + } + + private static func currentClaudeOAuthInteractivePromptPolicy() -> ClaudeOAuthKeychainPromptPolicy { + let policy = ClaudeOAuthKeychainPromptPolicy( + mode: ClaudeOAuthKeychainPromptPreference.securityFrameworkFallbackMode(), + isApplicable: true, + interaction: ProviderInteractionContext.current) + + // User actions should be able to immediately retry a Security.framework fallback repair after a background + // cooldown was recorded, even when /usr/bin/security is the primary reader. + if policy.interaction == .userInitiated { + if ClaudeOAuthKeychainAccessGate.clearDenied() { + Self.log.info("Claude OAuth keychain cooldown cleared by user action") + } + } + return policy + } + + private static func currentClaudeOAuthDelegatedRefreshPolicy() -> ClaudeOAuthKeychainPromptPolicy { + // Delegated refresh must honor the stored prompt mode for every keychain read strategy. + // securityCLIExperimental is not "prompt policy N/A" for CLI touch repair. + ClaudeOAuthKeychainPromptPolicy( + mode: ClaudeOAuthKeychainPromptPreference.storedMode(), + isApplicable: true, + interaction: ProviderInteractionContext.current) + } + + private static func assertDelegatedRefreshAllowedInCurrentInteraction( + policy: ClaudeOAuthKeychainPromptPolicy, + allowBackgroundDelegatedRefresh: Bool) throws + { + if policy.mode == .never { + throw ClaudeUsageError.oauthFailed("Delegated refresh is disabled by 'never' keychain policy.") + } + if policy.mode == .onlyOnUserAction, + policy.interaction != .userInitiated, + !allowBackgroundDelegatedRefresh + { + throw ClaudeUsageError.oauthFailed( + "Claude OAuth token expired, but background repair is suppressed when Keychain prompt policy " + + "is set to only prompt on user action. Open the CodexBar menu or click Refresh to retry.") + } + } + + #if DEBUG + @TaskLocal static var loadOAuthCredentialsOverride: (@Sendable ( + [String: String], + Bool, + Bool) async throws -> ClaudeOAuthCredentials)? + @TaskLocal static var fetchOAuthUsageOverride: (@Sendable ( + String, + Bool) async throws -> OAuthUsageResponse)? + @TaskLocal static var delegatedRefreshAttemptOverride: (@Sendable ( + Date, + TimeInterval, + [String: String]) async -> ClaudeOAuthDelegatedRefreshCoordinator.Outcome)? + @TaskLocal static var hasCachedCredentialsOverride: Bool? + #endif + + /// Creates a new ClaudeUsageFetcher. + /// - Parameters: + /// - environment: Process environment (default: current process environment) + /// - dataSource: Usage data source (default: OAuth API). + /// - useWebExtras: If true, attempts to enrich usage with Claude web data (cookies). + public init( + browserDetection: BrowserDetection, + environment: [String: String] = ProcessInfo.processInfo.environment, + runtime: ProviderRuntime = .app, + dataSource: ClaudeUsageDataSource = .oauth, + oauthKeychainPromptCooldownEnabled: Bool = false, + allowBackgroundDelegatedRefresh: Bool = false, + allowStartupBootstrapPrompt: Bool = false, + useWebExtras: Bool = false, + manualCookieHeader: String? = nil, + webOrganizationID: String? = nil, + keepCLISessionsAlive: Bool = false) + { + self.configuration = Configuration( + environment: environment, + runtime: runtime, + dataSource: dataSource, + oauthKeychainPromptCooldownEnabled: oauthKeychainPromptCooldownEnabled, + allowBackgroundDelegatedRefresh: allowBackgroundDelegatedRefresh, + allowStartupBootstrapPrompt: allowStartupBootstrapPrompt, + useWebExtras: useWebExtras, + manualCookieHeader: manualCookieHeader, + webOrganizationID: webOrganizationID, + keepCLISessionsAlive: keepCLISessionsAlive, + browserDetection: browserDetection) + } + + private struct OAuthExecutor { + let fetcher: ClaudeUsageFetcher + + func load(allowDelegatedRetry: Bool) async throws -> ClaudeUsageSnapshot { + do { + let promptPolicy = ClaudeUsageFetcher.currentClaudeOAuthInteractivePromptPolicy() + + #if DEBUG + let hasCache = if let hasCachedCredentialsOverride = ClaudeUsageFetcher.hasCachedCredentialsOverride { + hasCachedCredentialsOverride + } else if ClaudeUsageFetcher.loadOAuthCredentialsOverride != nil { + false + } else { + ClaudeOAuthCredentialsStore.hasCachedCredentials(environment: self.fetcher.environment) + } + #else + let hasCache = ClaudeOAuthCredentialsStore.hasCachedCredentials(environment: self.fetcher.environment) + #endif + + let startupBootstrapOverride = self.shouldAllowStartupBootstrapPrompt( + policy: promptPolicy, + hasCache: hasCache) + let allowKeychainPrompt = (promptPolicy.canPromptNow || startupBootstrapOverride) && !hasCache + ClaudeUsageFetcher.logOAuthBootstrapPromptDecision( + allowKeychainPrompt: allowKeychainPrompt, + policy: promptPolicy, + hasCache: hasCache, + startupBootstrapOverride: startupBootstrapOverride) + + let credentialRecord = try await ClaudeOAuthCredentialsStore.$allowBackgroundPromptBootstrap + .withValue(startupBootstrapOverride) { + try await ClaudeUsageFetcher.loadOAuthCredentialRecord( + environment: self.fetcher.environment, + allowKeychainPrompt: allowKeychainPrompt, + respectKeychainPromptCooldown: promptPolicy.shouldRespectKeychainPromptCooldown) + } + let credentials = credentialRecord.credentials + + try self.validateRequiredOAuthScope(credentials) + let usage = try await ClaudeUsageFetcher.fetchOAuthUsage( + accessToken: credentials.accessToken, + detectClaudeVersion: self.fetcher.allowsOAuthClaudeVersionDetection) + let keychainMatch = ClaudeOAuthCredentialsStore + .claudeKeychainCredentialMatchWithoutPrompt(for: credentialRecord) + return try ClaudeUsageFetcher.mapOAuthUsage( + usage, + credentials: credentials, + oauthKeychainPersistentRefHash: keychainMatch.persistentRefHash, + oauthHistoryOwnerIdentifier: credentialRecord.historyOwnerIdentifier, + oauthKeychainCredentialMismatch: keychainMatch.isMismatch, + oauthKeychainCredentialAbsent: keychainMatch.isAbsent, + oauthKeychainCredentialUnavailable: keychainMatch.isUnavailable) + } catch let error as CancellationError { + throw error + } catch let error as ClaudeUsageError { + throw error + } catch let error as ClaudeOAuthCredentialsError { + if case .refreshDelegatedToClaudeCLI = error { + return try await self.loadAfterDelegatedRefresh(allowDelegatedRetry: allowDelegatedRetry) + } + throw ClaudeUsageError.oauthFailed(error.localizedDescription) + } catch let error as ClaudeOAuthFetchError { + if case .rateLimited = error { + throw ClaudeUsageError.oauthFailed(error.localizedDescription) + } + ClaudeOAuthCredentialsStore.invalidateCache() + if case let .serverError(statusCode, body) = error, + statusCode == 403, + body?.contains("user:profile") ?? false + { + throw ClaudeUsageError.oauthFailed( + "Claude OAuth token does not meet scope requirement 'user:profile'. " + + "Run `claude setup-token` to re-generate credentials, or switch Claude Source to " + + "Web/CLI.") + } + throw ClaudeUsageError.oauthFailed(error.localizedDescription) + } catch { + throw ClaudeUsageError.oauthFailed(error.localizedDescription) + } + } + + private func shouldAllowStartupBootstrapPrompt( + policy: ClaudeOAuthKeychainPromptPolicy, + hasCache: Bool) -> Bool + { + guard self.fetcher.allowStartupBootstrapPrompt else { return false } + guard !hasCache else { return false } + guard ClaudeOAuthKeychainPromptPreference.securityFrameworkFallbackMode() == .onlyOnUserAction else { + return false + } + guard policy.interaction == .background else { return false } + return ProviderRefreshContext.current == .startup + } + + private func loadAfterDelegatedRefresh(allowDelegatedRetry: Bool) async throws -> ClaudeUsageSnapshot { + guard allowDelegatedRetry else { + throw ClaudeUsageError.oauthFailed( + "Claude OAuth token expired. CodexBar CLI does not launch Claude to refresh credentials. " + + "Run `claude login`, then retry.") + } + + try Task.checkCancellation() + + let delegatedPromptPolicy = ClaudeUsageFetcher.currentClaudeOAuthDelegatedRefreshPolicy() + try ClaudeUsageFetcher.assertDelegatedRefreshAllowedInCurrentInteraction( + policy: delegatedPromptPolicy, + allowBackgroundDelegatedRefresh: self.fetcher.allowBackgroundDelegatedRefresh) + + let delegatedOutcome = await ClaudeUsageFetcher.attemptDelegatedRefresh( + environment: self.fetcher.environment) + ClaudeUsageFetcher.log.info( + "Claude OAuth delegated refresh attempted", + metadata: [ + "outcome": ClaudeUsageFetcher.delegatedRefreshOutcomeLabel(delegatedOutcome), + ]) + + do { + if self.fetcher.oauthKeychainPromptCooldownEnabled { + switch delegatedOutcome { + case .skippedByCooldown, .cliUnavailable: + throw ClaudeUsageError.oauthFailed( + "Claude OAuth token expired; delegated refresh is unavailable (outcome=" + + "\(ClaudeUsageFetcher.delegatedRefreshOutcomeLabel(delegatedOutcome))).") + case .attemptedSucceeded, .attemptedFailed: + break + } + } + + try Task.checkCancellation() + + _ = ClaudeOAuthCredentialsStore.invalidateCacheIfCredentialsFileChanged() + + let didSyncSilently = delegatedOutcome == .attemptedSucceeded + && ClaudeOAuthCredentialsStore.syncFromClaudeKeychainWithoutPrompt(now: Date()) + + let promptPolicy = ClaudeUsageFetcher.currentClaudeOAuthInteractivePromptPolicy() + ClaudeUsageFetcher.logDeferredBackgroundDelegatedRecoveryIfNeeded( + delegatedOutcome: delegatedOutcome, + didSyncSilently: didSyncSilently, + policy: promptPolicy) + let retryAllowKeychainPrompt = promptPolicy.canPromptNow && !didSyncSilently + if retryAllowKeychainPrompt { + ClaudeUsageFetcher.log.info( + "Claude OAuth keychain prompt allowed (post-delegation retry)", + metadata: [ + "interaction": promptPolicy.interactionLabel, + "promptMode": promptPolicy.mode.rawValue, + "promptPolicyApplicable": "\(promptPolicy.isApplicable)", + "delegatedOutcome": ClaudeUsageFetcher.delegatedRefreshOutcomeLabel(delegatedOutcome), + "didSyncSilently": "\(didSyncSilently)", + ]) + } + if ClaudeUsageFetcher.isClaudeOAuthFlowDebugEnabled { + ClaudeUsageFetcher.log.debug( + "Claude OAuth credential load (post-delegation retry start)", + metadata: [ + "cooldownEnabled": "\(self.fetcher.oauthKeychainPromptCooldownEnabled)", + "didSyncSilently": "\(didSyncSilently)", + "allowKeychainPrompt": "\(retryAllowKeychainPrompt)", + "delegatedOutcome": ClaudeUsageFetcher.delegatedRefreshOutcomeLabel(delegatedOutcome), + "interaction": promptPolicy.interactionLabel, + "promptMode": promptPolicy.mode.rawValue, + "promptPolicyApplicable": "\(promptPolicy.isApplicable)", + ]) + } + + let refreshedRecord = try await ClaudeUsageFetcher.loadOAuthCredentialRecord( + environment: self.fetcher.environment, + allowKeychainPrompt: retryAllowKeychainPrompt, + respectKeychainPromptCooldown: promptPolicy.shouldRespectKeychainPromptCooldown) + let refreshedCredentials = refreshedRecord.credentials + if ClaudeUsageFetcher.isClaudeOAuthFlowDebugEnabled { + ClaudeUsageFetcher.log.debug( + "Claude OAuth credential load (post-delegation retry)", + metadata: [ + "cooldownEnabled": "\(self.fetcher.oauthKeychainPromptCooldownEnabled)", + "didSyncSilently": "\(didSyncSilently)", + "allowKeychainPrompt": "\(retryAllowKeychainPrompt)", + "delegatedOutcome": ClaudeUsageFetcher.delegatedRefreshOutcomeLabel(delegatedOutcome), + "interaction": promptPolicy.interactionLabel, + "promptMode": promptPolicy.mode.rawValue, + "promptPolicyApplicable": "\(promptPolicy.isApplicable)", + ]) + } + + try self.validateRequiredOAuthScope(refreshedCredentials) + let usage = try await ClaudeUsageFetcher.fetchOAuthUsage( + accessToken: refreshedCredentials.accessToken, + detectClaudeVersion: self.fetcher.allowsOAuthClaudeVersionDetection) + let keychainMatch = ClaudeOAuthCredentialsStore + .claudeKeychainCredentialMatchWithoutPrompt(for: refreshedRecord) + return try ClaudeUsageFetcher.mapOAuthUsage( + usage, + credentials: refreshedCredentials, + oauthKeychainPersistentRefHash: keychainMatch.persistentRefHash, + oauthHistoryOwnerIdentifier: refreshedRecord.historyOwnerIdentifier, + oauthKeychainCredentialMismatch: keychainMatch.isMismatch, + oauthKeychainCredentialAbsent: keychainMatch.isAbsent, + oauthKeychainCredentialUnavailable: keychainMatch.isUnavailable) + } catch { + ClaudeUsageFetcher.log.debug( + "Claude OAuth post-delegation retry failed", + metadata: ClaudeUsageFetcher.delegatedRetryFailureMetadata( + error: error, + oauthKeychainPromptCooldownEnabled: self.fetcher.oauthKeychainPromptCooldownEnabled, + delegatedOutcome: delegatedOutcome)) + throw ClaudeUsageError.oauthFailed( + ClaudeUsageFetcher.delegatedRefreshFailureMessage( + for: delegatedOutcome, + retryError: error)) + } + } + + private func validateRequiredOAuthScope(_ credentials: ClaudeOAuthCredentials) throws { + guard credentials.scopes.contains("user:profile") else { + let scopes = credentials.scopes.joined(separator: ", ") + let detail = scopes.isEmpty + ? "Claude OAuth token missing 'user:profile' scope." + : "Claude OAuth token missing 'user:profile' scope (has: \(scopes))." + throw ClaudeUsageError.oauthFailed( + detail + " Run `claude setup-token` to re-generate credentials, or switch Claude Source to " + + "Web/CLI.") + } + } + } + + private struct StepExecutor { + let fetcher: ClaudeUsageFetcher + + func loadLatestUsage(model: String) async throws -> ClaudeUsageSnapshot { + switch self.fetcher.dataSource { + case .auto: + return try await self.executeAuto(model: model) + case .api: + throw ClaudeUsageError.parseFailed("Claude Admin API usage is handled by the provider descriptor.") + case .oauth: + var snapshot = try await self.fetcher.loadViaOAuth( + allowDelegatedRetry: self.fetcher.allowsDelegatedOAuthRefresh) + snapshot = await self.fetcher.applyWebExtrasIfNeeded(to: snapshot) + return snapshot + case .web: + return try await self.fetcher.loadViaWebAPI() + case .cli: + return try await self.loadViaCLIWithRetry(model: model) + } + } + + private func executeAuto(model: String) async throws -> ClaudeUsageSnapshot { + let plan = await self.makeAutoFetchPlan() + self.logAutoPlan(plan) + + let executionSteps = plan.executionSteps + for (index, step) in executionSteps.enumerated() { + do { + return try await self.execute(step: step, model: model) + } catch { + if index < executionSteps.count - 1 { + ClaudeUsageFetcher.log.debug( + "Claude planner step failed; falling back to next step", + metadata: [ + "step": step.dataSource.rawValue, + "reason": step.inclusionReason.rawValue, + "errorType": String(describing: type(of: error)), + ]) + continue + } + throw error + } + } + throw ClaudeUsageError.parseFailed("Claude planner produced no executable steps.") + } + + private func makeAutoFetchPlan() async -> ClaudeFetchPlan { + let hasWebSession = + if let header = self.fetcher.manualCookieHeader { + ClaudeWebAPIFetcher.hasSessionKey(cookieHeader: header) + } else { + ClaudeWebAPIFetcher.hasSessionKey(browserDetection: self.fetcher.browserDetection) + } + let hasCLI = ClaudeCLIResolver.isAvailable(environment: self.fetcher.environment) + return ClaudeSourcePlanner.resolve(input: ClaudeSourcePlanningInput( + runtime: self.fetcher.runtime, + selectedDataSource: .auto, + webExtrasEnabled: self.fetcher.useWebExtras, + hasWebSession: hasWebSession, + hasCLI: hasCLI, + hasOAuthCredentials: ClaudeOAuthPlanningAvailability.isAvailable( + runtime: self.fetcher.runtime, + sourceMode: .auto, + environment: self.fetcher.environment))) + } + + private func logAutoPlan(_ plan: ClaudeFetchPlan) { + var metadata: [String: String] = [ + "plannerOrder": plan.orderLabel, + "selected": plan.preferredStep?.dataSource.rawValue ?? "none", + "noSourceAvailable": "\(plan.isNoSourceAvailable)", + "webExtrasEnabled": "\(self.fetcher.useWebExtras)", + "oauthReadStrategy": ClaudeOAuthKeychainReadStrategyPreference.current().rawValue, + ] + for (index, step) in plan.orderedSteps.enumerated() { + metadata["step\(index)"] = + "\(step.dataSource.rawValue):\(step.inclusionReason.rawValue):\(step.isPlausiblyAvailable)" + } + ClaudeUsageFetcher.log.debug("Claude auto source planner", metadata: metadata) + } + + private func execute(step: ClaudeFetchPlanStep, model: String) async throws -> ClaudeUsageSnapshot { + switch step.dataSource { + case .api: + throw ClaudeUsageError.parseFailed("Planner emitted invalid api execution step.") + case .oauth: + var snapshot = try await self.fetcher.loadViaOAuth( + allowDelegatedRetry: self.fetcher.allowsDelegatedOAuthRefresh) + snapshot = await self.fetcher.applyWebExtrasIfNeeded(to: snapshot) + return snapshot + case .web: + return try await self.fetcher.loadViaWebAPI() + case .cli: + return try await self.loadViaAutoCLI(model: model) + case .auto: + throw ClaudeUsageError.parseFailed("Planner emitted invalid auto execution step.") + } + } + + private func loadViaAutoCLI(model: String) async throws -> ClaudeUsageSnapshot { + do { + return try await self.loadViaCLI(model: model, timeout: ClaudeUsageFetcher.cliAutoProbeTimeout) + } catch { + if error is CancellationError { + throw error + } + guard Self.shouldRetryCLIProbe(after: error) else { throw error } + return try await self.loadViaCLI(model: model, timeout: ClaudeUsageFetcher.cliRetryProbeTimeout) + } + } + + private func loadViaCLIWithRetry(model: String) async throws -> ClaudeUsageSnapshot { + do { + return try await self.loadViaCLI(model: model, timeout: ClaudeUsageFetcher.cliProbeTimeout) + } catch { + if error is CancellationError { + throw error + } + guard Self.shouldRetryCLIProbe(after: error) else { throw error } + return try await self.loadViaCLI(model: model, timeout: ClaudeUsageFetcher.cliRetryProbeTimeout) + } + } + + private func loadViaCLI(model: String, timeout: TimeInterval) async throws -> ClaudeUsageSnapshot { + if ClaudeCLIRateLimitGate.blockedUntil() != nil { + throw ClaudeUsageError.parseFailed(ClaudeCLIRateLimitGate.message) + } + + var snapshot: ClaudeUsageSnapshot + do { + snapshot = try await self.fetcher.loadViaPTY(model: model, timeout: timeout) + } catch { + if error is CancellationError { + throw error + } + if ClaudeUsageFetcher.isCLIRateLimitError(error) { + ClaudeCLIRateLimitGate.recordRateLimit() + throw error + } + guard Self.shouldTryDirectCLIUsage(after: error) else { throw error } + let ptyError = error + do { + snapshot = try await self.fetcher.loadViaDirectCLI( + timeout: Self.directCLIUsageTimeout(for: timeout)) + } catch let directError { + if directError is CancellationError { + throw directError + } + if ClaudeUsageFetcher.isCLIRateLimitError(directError) { + ClaudeCLIRateLimitGate.recordRateLimit() + throw directError + } + guard Self.directCLIErrorShouldReplacePTYError(directError) else { throw ptyError } + throw directError + } + } + ClaudeCLIRateLimitGate.recordSuccess() + snapshot = await self.fetcher.applyWebExtrasIfNeeded(to: snapshot) + return snapshot + } + + private static func directCLIUsageTimeout(for ptyTimeout: TimeInterval) -> TimeInterval { + min(max(ptyTimeout / 3, 6), 8) + } + + private static func directCLIErrorShouldReplacePTYError(_ error: Error) -> Bool { + if case let ClaudeStatusProbeError.parseFailed(message) = error { + return message.lowercased().contains("subscription") + } + if case let ClaudeUsageError.parseFailed(message) = error { + return message.lowercased().contains("subscription") + } + return false + } + + private static func shouldTryDirectCLIUsage(after error: Error) -> Bool { + if case ClaudeStatusProbeError.timedOut = error { + return true + } + if case let ClaudeStatusProbeError.parseFailed(message) = error { + let lower = message.lowercased() + return lower.contains("still loading usage") || lower.contains("could not load usage data") + } + let message = error.localizedDescription.lowercased() + return message.contains("timed out") || message.contains("timeout") + } + + private static func shouldRetryCLIProbe(after error: Error) -> Bool { + if case ClaudeStatusProbeError.timedOut = error { + return true + } + if case let ClaudeStatusProbeError.parseFailed(message) = error { + return message.lowercased().contains("still loading usage") + } + let message = error.localizedDescription.lowercased() + return message.contains("timed out") || message.contains("timeout") + } + } +} + +extension ClaudeUsageFetcher { + // MARK: - Parsing helpers + + public static func parse(json: Data) -> ClaudeUsageSnapshot? { + self.parse(json: json, now: .init()) + } + + package static func parse(json: Data, now: Date) -> ClaudeUsageSnapshot? { + guard let output = String(data: json, encoding: .utf8) else { return nil } + return try? Self.parse(output: output, now: now) + } + + private static func parse(output: String, now: Date) throws -> ClaudeUsageSnapshot { + guard + let data = output.data(using: .utf8), + let obj = try? JSONSerialization.jsonObject(with: data) as? [String: Any] + else { + throw ClaudeUsageError.parseFailed(output.prefix(500).description) + } + + if let ok = obj["ok"] as? Bool, !ok { + let hint = obj["hint"] as? String ?? (obj["pane_preview"] as? String ?? "") + throw ClaudeUsageError.parseFailed(hint) + } + + func firstWindowDict(_ keys: [String]) -> [String: Any]? { + for key in keys { + if let dict = obj[key] as? [String: Any] { + return dict + } + } + return nil + } + + func makeWindow(_ dict: [String: Any]?, windowMinutes: Int) -> RateWindow? { + guard let dict else { return nil } + let pct = (dict["pct_used"] as? NSNumber)?.doubleValue ?? 0 + let resetText = dict["resets"] as? String + return RateWindow( + usedPercent: pct, + windowMinutes: windowMinutes, + resetsAt: ClaudeStatusProbe.parseResetDate( + from: resetText, + now: now, + expectedWindow: TimeInterval(windowMinutes * 60)), + resetDescription: resetText) + } + + guard let session = makeWindow( + firstWindowDict(["session_5h"]), + windowMinutes: Self.sessionWindowMinutes) + else { + throw ClaudeUsageError.parseFailed("missing session data") + } + let weekAll = makeWindow( + firstWindowDict(["week_all_models", "week_all"]), + windowMinutes: Self.weeklyWindowMinutes) + + let rawEmail = (obj["account_email"] as? String)?.trimmingCharacters( + in: .whitespacesAndNewlines) + let email = (rawEmail?.isEmpty ?? true) ? nil : rawEmail + let rawOrg = (obj["account_org"] as? String)?.trimmingCharacters( + in: .whitespacesAndNewlines) + let org = (rawOrg?.isEmpty ?? true) ? nil : rawOrg + let loginMethod = (obj["login_method"] as? String)?.trimmingCharacters( + in: .whitespacesAndNewlines) + let opusWindow = makeWindow( + firstWindowDict([ + "week_sonnet", + "week_sonnet_only", + "week_opus", + ]), + windowMinutes: Self.weeklyWindowMinutes) + return ClaudeUsageSnapshot( + primary: session, + secondary: weekAll, + opus: opusWindow, + providerCost: nil, + updatedAt: now, + accountEmail: email, + accountOrganization: org, + loginMethod: loginMethod, + rawText: output) + } + + // MARK: - Public API + + public func detectVersion() -> String? { + ProviderVersionDetector.claudeVersion() + } + + public func debugRawProbe(model: String = "sonnet") async -> String { + do { + let snap = try await self.loadViaPTY(model: model, timeout: Self.cliProbeTimeout) + let opus = snap.opus?.remainingPercent ?? -1 + let email = snap.accountEmail ?? "nil" + let org = snap.accountOrganization ?? "nil" + let weekly = snap.secondary?.remainingPercent ?? -1 + let primary = snap.primary.remainingPercent + return """ + session_left=\(primary) weekly_left=\(weekly) + opus_left=\(opus) email \(email) org \(org) + \(snap) + """ + } catch { + return "Probe failed: \(error)" + } + } + + public func loadLatestUsage(model: String = "sonnet") async throws -> ClaudeUsageSnapshot { + try await StepExecutor(fetcher: self).loadLatestUsage(model: model) + } + + public static func isCLIRateLimitError(_ error: Error) -> Bool { + ClaudeCLIRateLimitGate.isRateLimitError(error) + } +} + +extension ClaudeUsageFetcher { + // MARK: - OAuth API path + + private static func logOAuthBootstrapPromptDecision( + allowKeychainPrompt: Bool, + policy: ClaudeOAuthKeychainPromptPolicy, + hasCache: Bool, + startupBootstrapOverride: Bool) + { + guard allowKeychainPrompt else { return } + self.log.info( + "Claude OAuth keychain prompt allowed (bootstrap)", + metadata: [ + "interaction": policy.interactionLabel, + "promptMode": policy.mode.rawValue, + "promptPolicyApplicable": "\(policy.isApplicable)", + "hasCache": "\(hasCache)", + "startupBootstrapOverride": "\(startupBootstrapOverride)", + ]) + } + + private static func logDeferredBackgroundDelegatedRecoveryIfNeeded( + delegatedOutcome: ClaudeOAuthDelegatedRefreshCoordinator.Outcome, + didSyncSilently: Bool, + policy: ClaudeOAuthKeychainPromptPolicy) + { + guard delegatedOutcome == .attemptedSucceeded else { return } + guard !didSyncSilently else { return } + guard policy.mode == .onlyOnUserAction else { return } + guard policy.interaction == .background else { return } + self.log.info( + "Claude OAuth delegated refresh completed; background recovery deferred until user action", + metadata: [ + "interaction": policy.interactionLabel, + "promptMode": policy.mode.rawValue, + "delegatedOutcome": self.delegatedRefreshOutcomeLabel(delegatedOutcome), + ]) + } + + private func loadViaOAuth(allowDelegatedRetry: Bool) async throws -> ClaudeUsageSnapshot { + try await OAuthExecutor(fetcher: self).load(allowDelegatedRetry: allowDelegatedRetry) + } + + private static func loadOAuthCredentialRecord( + environment: [String: String], + allowKeychainPrompt: Bool, + respectKeychainPromptCooldown: Bool) async throws -> ClaudeOAuthCredentialRecord + { + #if DEBUG + if let override = loadOAuthCredentialsOverride { + return try await ClaudeOAuthCredentialRecord( + credentials: override(environment, allowKeychainPrompt, respectKeychainPromptCooldown), + owner: .environment, + source: .environment) + } + #endif + return try await ClaudeOAuthCredentialsStore.loadRecordWithAutoRefresh( + environment: environment, + allowKeychainPrompt: allowKeychainPrompt, + respectKeychainPromptCooldown: respectKeychainPromptCooldown) + } + + private static func fetchOAuthUsage( + accessToken: String, + detectClaudeVersion: Bool) async throws -> OAuthUsageResponse + { + #if DEBUG + if let override = fetchOAuthUsageOverride { + return try await override(accessToken, detectClaudeVersion) + } + #endif + return try await ClaudeOAuthUsageFetcher.fetchUsage( + accessToken: accessToken, + detectClaudeVersion: detectClaudeVersion) + } + + private static func attemptDelegatedRefresh( + now: Date = Date(), + timeout: TimeInterval = 15, + environment: [String: String] = ProcessInfo.processInfo.environment) + async -> ClaudeOAuthDelegatedRefreshCoordinator.Outcome + { + #if DEBUG + if let override = delegatedRefreshAttemptOverride { + return await override(now, timeout, environment) + } + #endif + return await ClaudeOAuthDelegatedRefreshCoordinator.attempt( + now: now, + timeout: timeout, + environment: environment) + } + + private static func delegatedRefreshOutcomeLabel( + _ outcome: ClaudeOAuthDelegatedRefreshCoordinator.Outcome) -> String + { + switch outcome { + case .skippedByCooldown: + "skippedByCooldown" + case .cliUnavailable: + "cliUnavailable" + case .attemptedSucceeded: + "attemptedSucceeded" + case .attemptedFailed: + "attemptedFailed" + } + } + + private static func delegatedRefreshFailureMessage( + for outcome: ClaudeOAuthDelegatedRefreshCoordinator.Outcome, + retryError: Error) -> String + { + if let oauthError = retryError as? ClaudeOAuthFetchError, + case .rateLimited = oauthError + { + return oauthError.localizedDescription + } + + switch outcome { + case .skippedByCooldown: + return "Claude OAuth token expired and delegated refresh is cooling down. " + + "Please retry shortly, or run `claude login`." + case .cliUnavailable: + return "Claude OAuth token expired and Claude CLI is not available for delegated refresh. " + + "Install/configure `claude`, or run `claude login`." + case .attemptedSucceeded: + return "Claude OAuth token is still unavailable after delegated Claude CLI refresh. " + + "Run `claude login`, then retry." + case let .attemptedFailed(message): + return "Claude OAuth token expired and delegated Claude CLI refresh failed: \(message). " + + "Run `claude login`, then retry." + } + } + + private static func delegatedRetryFailureMetadata( + error: Error, + oauthKeychainPromptCooldownEnabled: Bool, + delegatedOutcome: ClaudeOAuthDelegatedRefreshCoordinator.Outcome) -> [String: String] + { + var metadata: [String: String] = [ + "errorType": String(describing: type(of: error)), + "cooldownEnabled": "\(oauthKeychainPromptCooldownEnabled)", + "delegatedOutcome": Self.delegatedRefreshOutcomeLabel(delegatedOutcome), + ] + + // Avoid `localizedDescription` here: some error types include server response bodies in their + // `errorDescription`, which can leak potentially identifying information into logs. + if let oauthError = error as? ClaudeOAuthFetchError { + switch oauthError { + case .unauthorized: + metadata["oauthError"] = "unauthorized" + case let .rateLimited(retryAfter): + metadata["oauthError"] = "rateLimited" + metadata["retryAfter"] = retryAfter.map { "\($0.timeIntervalSince1970)" } ?? "nil" + case .invalidResponse: + metadata["oauthError"] = "invalidResponse" + case let .serverError(statusCode, body): + metadata["oauthError"] = "serverError" + metadata["httpStatus"] = "\(statusCode)" + metadata["bodyLength"] = "\(body?.utf8.count ?? 0)" + case let .networkError(underlying): + metadata["oauthError"] = "networkError" + metadata["underlyingType"] = String(describing: type(of: underlying)) + } + } + + return metadata + } + + private static func mapOAuthUsage( + _ usage: OAuthUsageResponse, + credentials: ClaudeOAuthCredentials, + oauthKeychainPersistentRefHash: String? = nil, + oauthHistoryOwnerIdentifier: String? = nil, + oauthKeychainCredentialMismatch: Bool = false, + oauthKeychainCredentialAbsent: Bool = false, + oauthKeychainCredentialUnavailable: Bool = false) throws -> ClaudeUsageSnapshot + { + let oauthHistoryOwnerIdentifier = ClaudeOAuthCredentials.normalizedHistoryOwnerIdentifier( + oauthHistoryOwnerIdentifier) ?? credentials.historyOwnerIdentifier + + func makeWindow(_ window: OAuthUsageWindow?, windowMinutes: Int?) -> RateWindow? { + guard let window, + let utilization = window.utilization + else { return nil } + let resetDate = ClaudeOAuthUsageFetcher.parseISO8601Date(window.resetsAt) + let resetDescription = resetDate.map(Self.formatResetDate) + return RateWindow( + usedPercent: utilization, + windowMinutes: windowMinutes, + resetsAt: resetDate, + resetDescription: resetDescription) + } + + let loginMethod = ClaudePlan.oauthLoginMethod( + subscriptionType: credentials.subscriptionType, + rateLimitTier: credentials.rateLimitTier) + let primary = makeWindow(usage.fiveHour, windowMinutes: 5 * 60) + ?? makeWindow(usage.sevenDay, windowMinutes: 7 * 24 * 60) + ?? makeWindow(usage.sevenDayOAuthApps, windowMinutes: 7 * 24 * 60) + ?? makeWindow(usage.sevenDaySonnet, windowMinutes: 7 * 24 * 60) + ?? makeWindow(usage.sevenDayOpus, windowMinutes: 7 * 24 * 60) + let treatAsSpendLimit = primary == nil && usage.extraUsage?.isEnabled == true + let providerCost = Self.oauthExtraUsageCost( + usage.extraUsage, + loginMethod: loginMethod, + treatAsSpendLimit: treatAsSpendLimit) + + guard let primary else { + if let spendLimit = Self.oauthSpendLimitWindow(from: providerCost, extraUsage: usage.extraUsage) { + return ClaudeUsageSnapshot( + primary: spendLimit, + primaryWindowKind: .spendLimit, + secondary: nil, + opus: nil, + extraRateWindows: Self.oauthExtraRateWindows(from: usage), + providerCost: providerCost, + updatedAt: Date(), + accountEmail: nil, + accountOrganization: nil, + loginMethod: loginMethod, + rawText: nil, + oauthKeychainPersistentRefHash: oauthKeychainPersistentRefHash, + oauthHistoryOwnerIdentifier: oauthHistoryOwnerIdentifier, + oauthKeychainCredentialMismatch: oauthKeychainCredentialMismatch, + oauthKeychainCredentialAbsent: oauthKeychainCredentialAbsent, + oauthKeychainCredentialUnavailable: oauthKeychainCredentialUnavailable) + } + throw ClaudeUsageError.parseFailed("missing session data") + } + + let weekly = makeWindow(usage.sevenDay, windowMinutes: 7 * 24 * 60) + let modelSpecific = makeWindow( + usage.sevenDaySonnet ?? usage.sevenDayOpus, + windowMinutes: 7 * 24 * 60) + let extraRateWindows = Self.oauthExtraRateWindows(from: usage) + + return ClaudeUsageSnapshot( + primary: primary, + secondary: weekly, + opus: modelSpecific, + extraRateWindows: extraRateWindows, + providerCost: providerCost, + updatedAt: Date(), + accountEmail: nil, + accountOrganization: nil, + loginMethod: loginMethod, + rawText: nil, + oauthKeychainPersistentRefHash: oauthKeychainPersistentRefHash, + oauthHistoryOwnerIdentifier: oauthHistoryOwnerIdentifier, + oauthKeychainCredentialMismatch: oauthKeychainCredentialMismatch, + oauthKeychainCredentialAbsent: oauthKeychainCredentialAbsent, + oauthKeychainCredentialUnavailable: oauthKeychainCredentialUnavailable) + } + + private static func oauthExtraUsageCost( + _ extra: OAuthExtraUsage?, + loginMethod: String?, + treatAsSpendLimit: Bool = false) -> ProviderCostSnapshot? + { + guard let extra, extra.isEnabled == true else { return nil } + guard let used = extra.usedCredits, + let limit = extra.monthlyLimit + else { return nil } + let currency = extra.currency?.trimmingCharacters(in: .whitespacesAndNewlines) + let code = (currency?.isEmpty ?? true) ? "USD" : currency! + let isSpendLimit = treatAsSpendLimit || ClaudePlan.fromCompatibilityLoginMethod(loginMethod) == .enterprise + let normalized = Self.normalizeClaudeExtraUsageAmounts( + used: used, + limit: limit, + treatAsMajorUnits: false) + return ProviderCostSnapshot( + used: normalized.used, + limit: normalized.limit, + currencyCode: code, + period: isSpendLimit ? "Spend limit" : "Monthly cap", + resetsAt: nil, + updatedAt: Date()) + } + + private static func oauthSpendLimitWindow( + from providerCost: ProviderCostSnapshot?, + extraUsage: OAuthExtraUsage?) -> RateWindow? + { + guard let providerCost, + providerCost.limit > 0 + else { return nil } + let usedPercent = extraUsage?.utilization ?? (providerCost.used / providerCost.limit) * 100 + let used = UsageFormatter.currencyString(providerCost.used, currencyCode: providerCost.currencyCode) + let limit = UsageFormatter.currencyString(providerCost.limit, currencyCode: providerCost.currencyCode) + return RateWindow( + usedPercent: min(100, max(0, usedPercent)), + windowMinutes: nil, + resetsAt: providerCost.resetsAt, + resetDescription: "\(providerCost.period ?? "Spend limit"): \(used) / \(limit)") + } + + private static func normalizeClaudeExtraUsageAmounts( + used: Double, + limit: Double, + treatAsMajorUnits: Bool) -> (used: Double, limit: Double) + { + if treatAsMajorUnits { + return (used: used, limit: limit) + } + + // Claude's OAuth API returns values in cents (minor units), same as the Web API. + // Always convert to dollars (major units) for display consistency. + // See: ClaudeWebAPIFetcher.swift which always divides by 100. + return (used: used / 100.0, limit: limit / 100.0) + } + + private static func oauthExtraRateWindows(from usage: OAuthUsageResponse) -> [NamedRateWindow] { + let definitions: [(id: String, title: String, window: OAuthUsageWindow?, sourceKey: String?)] = [ + ( + id: "claude-routines", + title: "Daily Routines", + window: usage.sevenDayRoutines, + sourceKey: usage.sevenDayRoutinesSourceKey), + ] + if let routinesKey = usage.sevenDayRoutinesSourceKey { + Self.log.debug("Claude OAuth extra usage key matched: routines=\(routinesKey)") + } + let routineWindows: [NamedRateWindow] = definitions.compactMap { definition in + let utilization: Double + let resetDate: Date? + if let window = definition.window, let parsedUtilization = window.utilization { + utilization = parsedUtilization + resetDate = ClaudeOAuthUsageFetcher.parseISO8601Date(window.resetsAt) + } else if definition.sourceKey != nil { + // Keep product bars visible when the API returns a known key with null payload. + utilization = 0 + resetDate = nil + } else { + return nil + } + let resetDescription = resetDate.map(Self.formatResetDate) + return NamedRateWindow( + id: definition.id, + title: definition.title, + window: RateWindow( + usedPercent: utilization, + windowMinutes: Self.weeklyWindowMinutes, + resetsAt: resetDate, + resetDescription: resetDescription)) + } + return routineWindows + Self.oauthScopedWeeklyLimitWindows(from: usage) + } + + private static func oauthScopedWeeklyLimitWindows(from usage: OAuthUsageResponse) -> [NamedRateWindow] { + let limits = usage.limits?.map { entry in + ClaudeScopedWeeklyLimitMapper.Limit( + kind: entry.kind, + group: entry.group, + percent: entry.percent, + resetsAt: ClaudeOAuthUsageFetcher.parseISO8601Date(entry.resetsAt), + modelID: entry.scope?.model?.id, + modelName: entry.scope?.model?.displayName) + } + // `is_active` is intentionally not a filter: observed enforceable scoped limits report false. + return ClaudeScopedWeeklyLimitMapper.extraRateWindows( + from: limits, + resetDescription: Self.formatResetDate) + } + + // MARK: - Web API path (uses browser cookies) + + /// The 5-hour session (`primary`) window for a Claude web usage payload. + /// + /// When `five_hour` is null the web fetcher reports a synthesized 0% session (an account with no live + /// session window). Flag that placeholder so lane classifiers — e.g. the combined Session + Weekly + /// menu-bar metric — surface the weekly lane instead of a phantom 5h session. The flag keys off the + /// reported presence of the session object, so a real session that is merely idle (0% used, possibly + /// with no reset) stays unflagged and keeps rendering. + static func webPrimaryWindow(from webData: ClaudeWebAPIFetcher.WebUsageData) -> RateWindow { + RateWindow( + usedPercent: webData.sessionPercentUsed, + windowMinutes: 5 * 60, + resetsAt: webData.sessionResetsAt, + resetDescription: webData.sessionResetsAt.map { Self.formatResetDate($0) }, + isSyntheticPlaceholder: !webData.hasLiveSessionWindow) + } + + private func loadViaWebAPI() async throws -> ClaudeUsageSnapshot { + let webData: ClaudeWebAPIFetcher.WebUsageData = + if let header = self.manualCookieHeader { + try await ClaudeWebAPIFetcher.fetchUsage( + cookieHeader: header, + targetOrganizationID: self.webOrganizationID) + { msg in + Self.log.debug(msg) + } + } else { + try await ClaudeWebAPIFetcher.fetchUsage( + browserDetection: self.browserDetection, + targetOrganizationID: self.webOrganizationID) + { msg in + Self.log.debug(msg) + } + } + // Convert web API data to ClaudeUsageSnapshot format + let primary = Self.webPrimaryWindow(from: webData) + + let secondary: RateWindow? = webData.weeklyPercentUsed.map { pct in + RateWindow( + usedPercent: pct, + windowMinutes: 7 * 24 * 60, + resetsAt: webData.weeklyResetsAt, + resetDescription: webData.weeklyResetsAt.map { Self.formatResetDate($0) }) + } + + let opus: RateWindow? = webData.opusPercentUsed.map { opusPct in + RateWindow( + usedPercent: opusPct, + windowMinutes: 7 * 24 * 60, + resetsAt: webData.weeklyResetsAt, + resetDescription: webData.weeklyResetsAt.map { Self.formatResetDate($0) }) + } + + return ClaudeUsageSnapshot( + primary: primary, + secondary: secondary, + opus: opus, + extraRateWindows: webData.extraRateWindows, + providerCost: webData.extraUsageCost, + updatedAt: Date(), + accountEmail: webData.accountEmail, + accountOrganization: webData.accountOrganization, + loginMethod: webData.loginMethod, + rawText: nil) + } + + private static func formatResetDate(_ date: Date) -> String { + let formatter = DateFormatter() + formatter.dateFormat = "MMM d 'at' h:mma" + formatter.locale = Locale(identifier: "en_US_POSIX") + return formatter.string(from: date) + } + + // MARK: - PTY-based probe (no tmux) + + private func loadViaPTY(model: String, timeout: TimeInterval = 10) async throws -> ClaudeUsageSnapshot { + guard let claudeBinary = ClaudeCLIResolver.resolvedBinaryPath(environment: self.environment) else { + throw ClaudeUsageError.claudeNotInstalled + } + let probe = ClaudeStatusProbe( + claudeBinary: claudeBinary, + timeout: timeout, + keepCLISessionsAlive: self.keepCLISessionsAlive) + let snap = try await probe.fetch() + + return try Self.makeSnapshot(from: snap) + } + + private func loadViaDirectCLI(timeout: TimeInterval) async throws -> ClaudeUsageSnapshot { + guard let claudeBinary = ClaudeCLIResolver.resolvedBinaryPath(environment: self.environment) else { + throw ClaudeUsageError.claudeNotInstalled + } + + let workingDirectory = ClaudeStatusProbe.preparedProbeWorkingDirectoryURL() + var environment = ClaudeCLISession.launchEnvironment(baseEnv: self.environment) + environment["PWD"] = workingDirectory.path + defer { + ClaudeProbeSessionArtifactCleaner.cleanupProbeSessionArtifacts( + probeDirectory: workingDirectory, + environment: environment) + } + + let result = try await SubprocessRunner.run( + binary: claudeBinary, + arguments: ["/usage"], + environment: environment, + timeout: timeout, + standardInput: FileHandle.nullDevice, + currentDirectoryURL: workingDirectory, + label: "claude-direct-usage") + let snap = try ClaudeStatusProbe.parse(text: result.stdout) + return try Self.makeSnapshot(from: snap) + } + + private static func makeSnapshot( + from snap: ClaudeStatusSnapshot, + now: Date = .init()) throws -> ClaudeUsageSnapshot + { + guard let sessionPctLeft = snap.sessionPercentLeft else { + throw ClaudeUsageError.parseFailed("missing session data") + } + + func makeWindow(pctLeft: Int?, reset: String?, windowMinutes: Int) -> RateWindow? { + guard let left = pctLeft else { return nil } + let used = max(0, min(100, 100 - Double(left))) + let resetClean = reset?.trimmingCharacters(in: .whitespacesAndNewlines) + return RateWindow( + usedPercent: used, + windowMinutes: windowMinutes, + resetsAt: ClaudeStatusProbe.parseResetDate( + from: resetClean, + now: now, + expectedWindow: TimeInterval(windowMinutes * 60)), + resetDescription: resetClean) + } + + let primary = makeWindow( + pctLeft: sessionPctLeft, + reset: snap.primaryResetDescription, + windowMinutes: Self.sessionWindowMinutes)! + let weekly = makeWindow( + pctLeft: snap.weeklyPercentLeft, + reset: snap.secondaryResetDescription, + windowMinutes: Self.weeklyWindowMinutes) + let opus = makeWindow( + pctLeft: snap.opusPercentLeft, + reset: snap.opusResetDescription, + windowMinutes: Self.weeklyWindowMinutes) + + return ClaudeUsageSnapshot( + primary: primary, + secondary: weekly, + opus: opus, + extraRateWindows: snap.extraRateWindows, + providerCost: nil, + updatedAt: now, + accountEmail: snap.accountEmail, + accountOrganization: snap.accountOrganization, + loginMethod: snap.loginMethod, + rawText: snap.rawText) + } + + private func applyWebExtrasIfNeeded(to snapshot: ClaudeUsageSnapshot) async -> ClaudeUsageSnapshot { + guard self.useWebExtras, self.dataSource != .web else { return snapshot } + do { + let webData: ClaudeWebAPIFetcher.WebUsageData = + if let header = self.manualCookieHeader { + try await ClaudeWebAPIFetcher.fetchUsage( + cookieHeader: header, + targetOrganizationID: self.webOrganizationID) + { msg in + Self.log.debug(msg) + } + } else { + try await ClaudeWebAPIFetcher.fetchUsage( + browserDetection: self.browserDetection, + targetOrganizationID: self.webOrganizationID) + { msg in + Self.log.debug(msg) + } + } + // Only merge usage/cost extras; keep identity fields from the primary data source. + let mergedExtraRateWindows = Self.mergeExtraRateWindows( + primary: snapshot.extraRateWindows, + web: webData.extraRateWindows) + let mergedProviderCost = snapshot.providerCost ?? webData.extraUsageCost + if mergedProviderCost != snapshot.providerCost || mergedExtraRateWindows != snapshot.extraRateWindows { + return ClaudeUsageSnapshot( + primary: snapshot.primary, + primaryWindowKind: snapshot.primaryWindowKind, + secondary: snapshot.secondary, + opus: snapshot.opus, + extraRateWindows: mergedExtraRateWindows, + providerCost: mergedProviderCost, + updatedAt: snapshot.updatedAt, + accountEmail: snapshot.accountEmail, + accountOrganization: snapshot.accountOrganization, + loginMethod: snapshot.loginMethod, + rawText: snapshot.rawText, + oauthKeychainPersistentRefHash: snapshot.oauthKeychainPersistentRefHash, + oauthHistoryOwnerIdentifier: snapshot.oauthHistoryOwnerIdentifier, + oauthKeychainCredentialMismatch: snapshot.oauthKeychainCredentialMismatch, + oauthKeychainCredentialAbsent: snapshot.oauthKeychainCredentialAbsent, + oauthKeychainCredentialUnavailable: snapshot.oauthKeychainCredentialUnavailable) + } + } catch { + Self.log.debug("Claude web extras fetch failed: \(error.localizedDescription)") + } + return snapshot + } + + private static func mergeExtraRateWindows( + primary: [NamedRateWindow], + web: [NamedRateWindow]) -> [NamedRateWindow] + { + guard !primary.isEmpty else { return web } + guard !web.isEmpty else { return primary } + + let primaryScopedKeys = Set(primary.compactMap(self.scopedExtraRateWindowMergeKey)) + var webScopedIDsByKey: [String: Set] = [:] + for window in web { + guard let scopedKey = self.scopedExtraRateWindowMergeKey(window) else { continue } + webScopedIDsByKey[scopedKey, default: []].insert(window.id) + } + var seenIDs = Set(primary.map(\.id)) + var merged = primary + for window in web where seenIDs.insert(window.id).inserted { + if let scopedKey = self.scopedExtraRateWindowMergeKey(window), + primaryScopedKeys.contains(scopedKey), + webScopedIDsByKey[scopedKey]?.count == 1 + { + continue + } + merged.append(window) + } + return merged + } + + private static func scopedExtraRateWindowMergeKey(_ window: NamedRateWindow) -> String? { + guard window.id.hasPrefix("claude-weekly-scoped-") else { return nil } + + let modelName = window.title.replacingOccurrences( + of: #"\s+only\s*$"#, + with: "", + options: [.regularExpression, .caseInsensitive]) + let normalizedName = String(modelName.lowercased().unicodeScalars.filter(CharacterSet.alphanumerics.contains)) + guard !normalizedName.isEmpty else { return nil } + return normalizedName + } + + // MARK: - Process helpers + + private static func which(_ tool: String) -> String? { + let process = Process() + process.executableURL = URL(fileURLWithPath: "/usr/bin/which") + process.arguments = [tool] + let pipe = Pipe() + process.standardOutput = pipe + try? process.run() + process.waitUntilExit() + guard process.terminationStatus == 0 else { return nil } + let data = pipe.fileHandleForReading.readDataToEndOfFile() + guard + let path = String(data: data, encoding: .utf8)? + .trimmingCharacters(in: .whitespacesAndNewlines), + !path.isEmpty + else { return nil } + return path + } + + private static func readString(cmd: String, args: [String]) -> String? { + let task = Process() + task.executableURL = URL(fileURLWithPath: cmd) + task.arguments = args + let pipe = Pipe() + task.standardOutput = pipe + try? task.run() + task.waitUntilExit() + guard task.terminationStatus == 0 else { return nil } + let data = pipe.fileHandleForReading.readDataToEndOfFile() + return String(data: data, encoding: .utf8) + } + + private static func oauthCredentialProbeErrorLabel(_ error: Error) -> String { + guard let oauthError = error as? ClaudeOAuthCredentialsError else { + return String(describing: type(of: error)) + } + + return switch oauthError { + case .decodeFailed: + "decodeFailed" + case .missingOAuth: + "missingOAuth" + case .mcpOAuthOnlyKeychain: + "mcpOAuthOnlyKeychain" + case .missingAccessToken: + "missingAccessToken" + case .notFound: + "notFound" + case let .keychainError(status): + "keychainError:\(status)" + case .readFailed: + "readFailed" + case .refreshFailed: + "refreshFailed" + case .noRefreshToken: + "noRefreshToken" + case .refreshDelegatedToClaudeCLI: + "refreshDelegatedToClaudeCLI" + } + } +} + +#if DEBUG +extension ClaudeUsageFetcher { + public static func _mergeExtraRateWindowsForTesting( + primary: [NamedRateWindow], + web: [NamedRateWindow]) -> [NamedRateWindow] + { + self.mergeExtraRateWindows(primary: primary, web: web) + } + + public static func _mapOAuthUsageForTesting( + _ data: Data, + rateLimitTier: String? = nil, + subscriptionType: String? = nil) throws -> ClaudeUsageSnapshot + { + let usage = try ClaudeOAuthUsageFetcher.decodeUsageResponse(data) + let creds = ClaudeOAuthCredentials( + accessToken: "test", + refreshToken: nil, + expiresAt: Date().addingTimeInterval(3600), + scopes: [], + rateLimitTier: rateLimitTier, + subscriptionType: subscriptionType) + return try Self.mapOAuthUsage(usage, credentials: creds) + } +} +#endif diff --git a/Sources/CodexBarCore/Providers/Claude/ClaudeWeb/ClaudeWebAPIFetcher.swift b/Sources/CodexBarCore/Providers/Claude/ClaudeWeb/ClaudeWebAPIFetcher.swift new file mode 100644 index 0000000..59fac13 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Claude/ClaudeWeb/ClaudeWebAPIFetcher.swift @@ -0,0 +1,1270 @@ +import Foundation +import SweetCookieKit +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +enum ClaudeWebHTTPTransport { + #if DEBUG + @TaskLocal static var overrideForTesting: (any ProviderHTTPTransport)? + #endif + + static var current: any ProviderHTTPTransport { + #if DEBUG + if let override = self.overrideForTesting { + return override + } + #endif + return ProviderHTTPClient.shared + } +} + +enum ClaudeWebSessionKeyImport { + #if DEBUG + @TaskLocal static var overrideForTesting: ClaudeWebAPIFetcher.SessionKeyInfo? + #endif + + static var currentOverride: ClaudeWebAPIFetcher.SessionKeyInfo? { + #if DEBUG + self.overrideForTesting + #else + nil + #endif + } +} + +private actor ClaudeWebBrowserFetchGate { + private struct Waiter { + let id: UUID + let continuation: CheckedContinuation + } + + private var ownerID: UUID? + private var waiters: [Waiter] = [] + + func acquire(id: UUID) async -> Bool { + if Task.isCancelled { return false } + guard self.ownerID != nil else { + self.ownerID = id + return true + } + return await withCheckedContinuation { continuation in + self.waiters.append(Waiter(id: id, continuation: continuation)) + } + } + + func cancel(id: UUID) { + if self.ownerID == id { return } + guard let index = self.waiters.firstIndex(where: { $0.id == id }) else { return } + let waiter = self.waiters.remove(at: index) + waiter.continuation.resume(returning: false) + } + + func release(id: UUID) { + guard self.ownerID == id else { return } + guard !self.waiters.isEmpty else { + self.ownerID = nil + return + } + let waiter = self.waiters.removeFirst() + self.ownerID = waiter.id + waiter.continuation.resume(returning: true) + } +} + +private enum ClaudeWebBrowserFetchSerialization { + private static let gate = ClaudeWebBrowserFetchGate() + + static func run(_ operation: () async throws -> T) async throws -> T { + let id = UUID() + let acquired = await withTaskCancellationHandler { + await self.gate.acquire(id: id) + } onCancel: { + Task { await self.gate.cancel(id: id) } + } + guard acquired else { throw CancellationError() } + do { + try Task.checkCancellation() + let value = try await operation() + await self.gate.release(id: id) + return value + } catch { + await self.gate.release(id: id) + throw error + } + } +} + +/// Fetches Claude usage data directly from the claude.ai API using browser session cookies. +/// +/// This approach mirrors what Claude Usage Tracker does, but automatically extracts the session key +/// from browser cookies instead of requiring manual setup. +/// +/// API endpoints used: +/// - `GET https://claude.ai/api/organizations` → get org UUID +/// - `GET https://claude.ai/api/organizations/{org_id}/usage` → usage percentages + reset times +public enum ClaudeWebAPIFetcher { + private static let baseURL = "https://claude.ai/api" + private static let maxProbeBytes = 200_000 + #if os(macOS) + private static let cookieClient = BrowserCookieClient() + private static let cookieImportOrder: BrowserCookieImportOrder = + ProviderDefaults.metadata[.claude]?.browserCookieOrder ?? Browser.defaultImportOrder + #else + private static let cookieImportOrder: BrowserCookieImportOrder = [] + #endif + + public struct OrganizationInfo: Sendable { + public let id: String + public let name: String? + + public init(id: String, name: String?) { + self.id = id + self.name = name + } + } + + public struct SessionKeyInfo: Sendable { + public let key: String + public let sourceLabel: String + public let cookieCount: Int + + public init(key: String, sourceLabel: String, cookieCount: Int) { + self.key = key + self.sourceLabel = sourceLabel + self.cookieCount = cookieCount + } + } + + public enum FetchError: LocalizedError, Sendable { + case noSessionKeyFound + case invalidSessionKey + case notSupportedOnThisPlatform + case networkError(Error) + case invalidResponse + case unauthorized + case serverError(statusCode: Int) + case noOrganization + case organizationNotFound(String) + + public var errorDescription: String? { + switch self { + case .noSessionKeyFound: + "No Claude session key found in browser cookies." + case .invalidSessionKey: + "Invalid Claude session key format." + case .notSupportedOnThisPlatform: + "Claude web fetching is only supported on macOS." + case let .networkError(error): + "Network error: \(error.localizedDescription)" + case .invalidResponse: + "Invalid response from Claude API." + case .unauthorized: + "Sign in to claude.ai (or refresh Claude cookies) to load usage data." + case let .serverError(code): + "Claude API error: HTTP \(code)" + case .noOrganization: + "No Claude organization found for this account." + case let .organizationNotFound(id): + "Claude organization '\(id)' was not found for this session." + } + } + } + + /// Claude usage data from the API + public struct WebUsageData: Sendable { + public let sessionPercentUsed: Double + public let sessionResetsAt: Date? + public let weeklyPercentUsed: Double? + public let weeklyResetsAt: Date? + public let opusPercentUsed: Double? + public let extraRateWindows: [NamedRateWindow] + public let extraUsageCost: ProviderCostSnapshot? + public let accountOrganization: String? + public let accountEmail: String? + public let loginMethod: String? + /// Whether the API reported a `five_hour` session object. When `false` (the API sent + /// `five_hour: null`, as enterprise/credit accounts with no live session do), `sessionPercentUsed` + /// is the synthesized `0` placeholder rather than a real reading. Distinguishing this from a real + /// session that happens to be at `0%` (with or without a reset) lets lane classifiers drop the + /// placeholder without hiding a genuine empty session. + public let hasLiveSessionWindow: Bool + + public init( + sessionPercentUsed: Double, + sessionResetsAt: Date?, + weeklyPercentUsed: Double?, + weeklyResetsAt: Date?, + opusPercentUsed: Double?, + extraRateWindows: [NamedRateWindow], + extraUsageCost: ProviderCostSnapshot?, + accountOrganization: String?, + accountEmail: String?, + loginMethod: String?, + hasLiveSessionWindow: Bool = true) + { + self.sessionPercentUsed = sessionPercentUsed + self.sessionResetsAt = sessionResetsAt + self.weeklyPercentUsed = weeklyPercentUsed + self.weeklyResetsAt = weeklyResetsAt + self.opusPercentUsed = opusPercentUsed + self.extraRateWindows = extraRateWindows + self.extraUsageCost = extraUsageCost + self.accountOrganization = accountOrganization + self.accountEmail = accountEmail + self.loginMethod = loginMethod + self.hasLiveSessionWindow = hasLiveSessionWindow + } + } + + public struct ProbeResult: Sendable { + public let url: String + public let statusCode: Int? + public let contentType: String? + public let topLevelKeys: [String] + public let emails: [String] + public let planHints: [String] + public let notableFields: [String] + public let bodyPreview: String? + } + + // MARK: - Public API + + #if os(macOS) + + /// Attempts to fetch Claude usage data using cookies extracted from browsers. + /// Tries browser cookies using the standard import order. + public static func fetchUsage( + browserDetection: BrowserDetection, + targetOrganizationID: String? = nil, + logger: ((String) -> Void)? = nil) async throws -> WebUsageData + { + try await ClaudeWebBrowserFetchSerialization.run { + try await self.fetchUsageSerialized( + browserDetection: browserDetection, + targetOrganizationID: targetOrganizationID, + logger: logger) + } + } + + public static func fetchUsage( + cookieHeader: String, + targetOrganizationID: String? = nil, + logger: ((String) -> Void)? = nil) async throws -> WebUsageData + { + let log: (String) -> Void = { msg in logger?("[claude-web] \(msg)") } + let sessionInfo = try self.sessionKeyInfo(cookieHeader: cookieHeader) + log("Using manual session key (\(sessionInfo.cookieCount) cookies)") + return try await self.fetchUsage( + using: sessionInfo, + targetOrganizationID: targetOrganizationID, + logger: log) + } + + public static func fetchUsage( + using sessionKeyInfo: SessionKeyInfo, + targetOrganizationID: String? = nil, + logger: ((String) -> Void)? = nil) async throws -> WebUsageData + { + try await self.fetchUsage( + using: sessionKeyInfo, + targetOrganizationID: targetOrganizationID, + logger: logger, + cacheSourceLabel: nil, + expectedCacheObservation: .authoritative(nil)) + } + + private static func fetchUsageAndRenewCache( + cachedEntry: CookieHeaderCache.Entry, + targetOrganizationID: String?, + logger: ((String) -> Void)? = nil) async throws -> WebUsageData + { + let sessionInfo = try self.sessionKeyInfo(cookieHeader: cachedEntry.cookieHeader) + return try await self.fetchUsage( + using: sessionInfo, + targetOrganizationID: targetOrganizationID, + logger: logger, + cacheSourceLabel: cachedEntry.sourceLabel, + expectedCacheObservation: .authoritative(cachedEntry)) + } + + private static func fetchUsage( + using sessionKeyInfo: SessionKeyInfo, + targetOrganizationID: String?, + logger: ((String) -> Void)?, + cacheSourceLabel: String?, + expectedCacheObservation: CookieHeaderCache.ConditionalMutationObservation, + persistInitialSessionKey: Bool = false) async throws -> WebUsageData + { + let log: (String) -> Void = { msg in logger?(msg) } + let sessionKey = sessionKeyInfo.key + let renewalTracker = ClaudeWebSessionKeyRenewalTracker(initialSessionKey: sessionKey) + + // Fetch organization info + let organization = try await fetchOrganizationInfo( + sessionKey: sessionKey, + targetOrganizationID: targetOrganizationID, + logger: log, + renewalTracker: renewalTracker) + log("Organization resolved") + + var usage = try await fetchUsageData( + orgId: organization.id, + sessionKey: renewalTracker.sessionKey, + logger: log, + renewalTracker: renewalTracker) + if usage.extraUsageCost == nil, + let extra = await ClaudeWebExtraUsageCost.fetch( + baseURL: Self.baseURL, + orgId: organization.id, + sessionKey: renewalTracker.sessionKey, + logger: log, + renewalTracker: renewalTracker) + { + usage = WebUsageData( + sessionPercentUsed: usage.sessionPercentUsed, + sessionResetsAt: usage.sessionResetsAt, + weeklyPercentUsed: usage.weeklyPercentUsed, + weeklyResetsAt: usage.weeklyResetsAt, + opusPercentUsed: usage.opusPercentUsed, + extraRateWindows: usage.extraRateWindows, + extraUsageCost: extra, + accountOrganization: usage.accountOrganization, + accountEmail: usage.accountEmail, + loginMethod: usage.loginMethod, + hasLiveSessionWindow: usage.hasLiveSessionWindow) + } + if let account = await fetchAccountInfo( + sessionKey: renewalTracker.sessionKey, + orgId: organization.id, + logger: log, + renewalTracker: renewalTracker) + { + usage = WebUsageData( + sessionPercentUsed: usage.sessionPercentUsed, + sessionResetsAt: usage.sessionResetsAt, + weeklyPercentUsed: usage.weeklyPercentUsed, + weeklyResetsAt: usage.weeklyResetsAt, + opusPercentUsed: usage.opusPercentUsed, + extraRateWindows: usage.extraRateWindows, + extraUsageCost: usage.extraUsageCost, + accountOrganization: usage.accountOrganization, + accountEmail: account.email, + loginMethod: account.loginMethod, + hasLiveSessionWindow: usage.hasLiveSessionWindow) + } + if usage.accountOrganization == nil, let name = organization.name { + usage = WebUsageData( + sessionPercentUsed: usage.sessionPercentUsed, + sessionResetsAt: usage.sessionResetsAt, + weeklyPercentUsed: usage.weeklyPercentUsed, + weeklyResetsAt: usage.weeklyResetsAt, + opusPercentUsed: usage.opusPercentUsed, + extraRateWindows: usage.extraRateWindows, + extraUsageCost: usage.extraUsageCost, + accountOrganization: name, + accountEmail: usage.accountEmail, + loginMethod: usage.loginMethod, + hasLiveSessionWindow: usage.hasLiveSessionWindow) + } + if let cacheSourceLabel { + self.persistSessionKeyIfNeeded( + source: (sessionKey, cacheSourceLabel), + renewedCookieHeader: renewalTracker.renewedCookieHeader, + expectedCacheObservation: expectedCacheObservation, + persistInitialSessionKey: persistInitialSessionKey, + logger: log) + } + return usage + } + + /// Probes a list of endpoints using the current claude.ai session cookies. + /// - Parameters: + /// - endpoints: Absolute URLs or "/api/..." paths. Supports "{orgId}" placeholder. + /// - includePreview: When true, includes a truncated response preview in results. + public static func probeEndpoints( + _ endpoints: [String], + browserDetection: BrowserDetection, + includePreview: Bool = false, + logger: ((String) -> Void)? = nil) async throws -> [ProbeResult] + { + let log: (String) -> Void = { msg in logger?("[claude-probe] \(msg)") } + let sessionInfo = try extractSessionKeyInfo(browserDetection: browserDetection, logger: log) + let sessionKey = sessionInfo.key + let organization = try? await fetchOrganizationInfo(sessionKey: sessionKey, logger: log) + let expanded = endpoints.map { endpoint -> String in + var url = endpoint + if let orgId = organization?.id { + url = url.replacingOccurrences(of: "{orgId}", with: orgId) + } + if url.hasPrefix("/") { + url = "https://claude.ai\(url)" + } + return url + } + + var results: [ProbeResult] = [] + results.reserveCapacity(expanded.count) + + for endpoint in expanded { + guard let url = URL(string: endpoint) else { continue } + var request = URLRequest(url: url) + request.setValue("sessionKey=\(sessionKey)", forHTTPHeaderField: "Cookie") + request.setValue("application/json, text/html;q=0.9, */*;q=0.8", forHTTPHeaderField: "Accept") + request.httpMethod = "GET" + request.timeoutInterval = 20 + + do { + let (data, response) = try await ClaudeWebHTTPTransport.current.data(for: request) + let http = response as? HTTPURLResponse + let contentType = http?.allHeaderFields["Content-Type"] as? String + let truncated = data.prefix(Self.maxProbeBytes) + let body = String(data: truncated, encoding: .utf8) ?? "" + + let parsed = Self.parseProbeBody(data: data, fallbackText: body, contentType: contentType) + let preview = includePreview ? parsed.preview : nil + + results.append(ProbeResult( + url: endpoint, + statusCode: http?.statusCode, + contentType: contentType, + topLevelKeys: parsed.keys, + emails: parsed.emails, + planHints: parsed.planHints, + notableFields: parsed.notableFields, + bodyPreview: preview)) + } catch { + results.append(ProbeResult( + url: endpoint, + statusCode: nil, + contentType: nil, + topLevelKeys: [], + emails: [], + planHints: [], + notableFields: [], + bodyPreview: "Error: \(error.localizedDescription)")) + } + } + + return results + } + + /// Checks if we can find a Claude session key in browser cookies without making API calls. + public static func hasSessionKey(browserDetection: BrowserDetection, logger: ((String) -> Void)? = nil) -> Bool { + if let cached = CookieHeaderCache.load(provider: .claude), + self.hasSessionKey(cookieHeader: cached.cookieHeader) + { + return true + } + do { + _ = try self.sessionKeyInfo(browserDetection: browserDetection, logger: logger) + return true + } catch { + return false + } + } + + public static func hasSessionKey(cookieHeader: String?) -> Bool { + guard let cookieHeader else { return false } + return (try? self.sessionKeyInfo(cookieHeader: cookieHeader)) != nil + } + + public static func sessionKeyInfo( + browserDetection: BrowserDetection, + logger: ((String) -> Void)? = nil) throws -> SessionKeyInfo + { + try self.extractSessionKeyInfo(browserDetection: browserDetection, logger: logger) + } + + public static func sessionKeyInfo(cookieHeader: String) throws -> SessionKeyInfo { + let pairs = CookieHeaderNormalizer.pairs(from: cookieHeader) + if let sessionKey = self.findSessionKey(in: pairs) { + return SessionKeyInfo( + key: sessionKey, + sourceLabel: "Manual", + cookieCount: pairs.count) + } + throw FetchError.noSessionKeyFound + } + + // MARK: - Session Key Extraction + + private static func extractSessionKeyInfo( + browserDetection: BrowserDetection, + logger: ((String) -> Void)? = nil) throws -> SessionKeyInfo + { + if let override = ClaudeWebSessionKeyImport.currentOverride { return override } + let log: (String) -> Void = { msg in logger?(msg) } + + let cookieDomains = ["claude.ai"] + + // Filter to cookie-eligible browsers to avoid unnecessary keychain prompts + let installedBrowsers = Self.cookieImportOrder.cookieImportCandidates(using: browserDetection) + for browserSource in installedBrowsers { + do { + let query = BrowserCookieQuery(domains: cookieDomains) + let sources = try Self.cookieClient.codexBarRecords( + matching: query, + in: browserSource, + logger: log) + for source in sources { + if let sessionKey = findSessionKey(in: source.records.map { record in + (name: record.name, value: record.value) + }) { + log("Found sessionKey in \(source.label)") + return SessionKeyInfo( + key: sessionKey, + sourceLabel: source.label, + cookieCount: source.records.count) + } + } + } catch { + BrowserCookieAccessGate.recordIfNeeded(error) + log("\(browserSource.displayName) cookie load failed: \(error.localizedDescription)") + } + } + + throw FetchError.noSessionKeyFound + } + + private static func findSessionKey(in cookies: [(name: String, value: String)]) -> String? { + for cookie in cookies where cookie.name == "sessionKey" { + let value = cookie.value.trimmingCharacters(in: .whitespacesAndNewlines) + // Validate it looks like a Claude session key + if value.hasPrefix("sk-ant-") { + return value + } + } + return nil + } + + // MARK: - API Calls + + private static func fetchOrganizationInfo( + sessionKey: String, + targetOrganizationID: String? = nil, + logger: ((String) -> Void)? = nil, + renewalTracker: ClaudeWebSessionKeyRenewalTracker? = nil) async throws -> OrganizationInfo + { + let url = URL(string: "\(baseURL)/organizations")! + var request = URLRequest(url: url) + request.setValue("sessionKey=\(sessionKey)", forHTTPHeaderField: "Cookie") + request.setValue("application/json", forHTTPHeaderField: "Accept") + request.httpMethod = "GET" + request.timeoutInterval = 15 + + let (data, response) = try await ClaudeWebHTTPTransport.current.data(for: request) + + guard let httpResponse = response as? HTTPURLResponse else { + throw FetchError.invalidResponse + } + renewalTracker?.observe(response: httpResponse) + + logger?("Organizations API status: \(httpResponse.statusCode)") + + switch httpResponse.statusCode { + case 200: + return try self.parseOrganizationResponse(data, targetOrganizationID: targetOrganizationID) + case 401, 403: + throw FetchError.unauthorized + default: + throw FetchError.serverError(statusCode: httpResponse.statusCode) + } + } + + private static func fetchUsageData( + orgId: String, + sessionKey: String, + logger: ((String) -> Void)? = nil, + renewalTracker: ClaudeWebSessionKeyRenewalTracker? = nil) async throws -> WebUsageData + { + let url = URL(string: "\(baseURL)/organizations/\(orgId)/usage")! + var request = URLRequest(url: url) + request.setValue("sessionKey=\(sessionKey)", forHTTPHeaderField: "Cookie") + request.setValue("application/json", forHTTPHeaderField: "Accept") + request.httpMethod = "GET" + request.timeoutInterval = 15 + + let (data, response) = try await ClaudeWebHTTPTransport.current.data(for: request) + + guard let httpResponse = response as? HTTPURLResponse else { + throw FetchError.invalidResponse + } + renewalTracker?.observe(response: httpResponse) + + logger?("Usage API status: \(httpResponse.statusCode)") + + switch httpResponse.statusCode { + case 200: + return try self.parseUsageResponse(data, logger: logger) + case 401, 403: + throw FetchError.unauthorized + default: + throw FetchError.serverError(statusCode: httpResponse.statusCode) + } + } + + private static func parseUsageResponse(_ data: Data, logger: ((String) -> Void)? = nil) throws -> WebUsageData { + guard let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else { + throw FetchError.invalidResponse + } + + // Parse five_hour (session) usage + var sessionPercent: Double? + var sessionResets: Date? + let fiveHour = json["five_hour"] as? [String: Any] + if let fiveHour { + sessionPercent = Self.percentValue(from: fiveHour["utilization"]) + if let resetsAt = fiveHour["resets_at"] as? String { + sessionResets = self.parseISO8601Date(resetsAt) + } + } + // Enterprise/credit-based accounts return null for five_hour; treat as 0% rather than an error. + // Track the object's presence so a real 0% session (with or without a reset) is not mistaken for + // the synthesized null-session placeholder downstream. + let resolvedSessionPercent = sessionPercent ?? 0.0 + let hasLiveSessionWindow = fiveHour != nil + + // Parse seven_day (weekly) usage + var weeklyPercent: Double? + var weeklyResets: Date? + if let sevenDay = json["seven_day"] as? [String: Any] { + weeklyPercent = Self.percentValue(from: sevenDay["utilization"]) + if let resetsAt = sevenDay["resets_at"] as? String { + weeklyResets = self.parseISO8601Date(resetsAt) + } + } + + // Parse seven_day_sonnet (preferred) / seven_day_opus usage + var opusPercent: Double? + if let sevenDaySonnet = json["seven_day_sonnet"] as? [String: Any] { + opusPercent = Self.percentValue(from: sevenDaySonnet["utilization"]) + } else if let sevenDayOpus = json["seven_day_opus"] as? [String: Any] { + opusPercent = Self.percentValue(from: sevenDayOpus["utilization"]) + } + let extraRateParse = ClaudeWebExtraRateWindowParser.parse(from: json) + if let sourceKey = extraRateParse.sourceKeys["claude-routines"] { + logger?("Usage API extra window key matched: routines=\(sourceKey)") + } + let extraUsageCost = ClaudeWebExtraUsageCost.parse(from: json["extra_usage"]) + + return WebUsageData( + sessionPercentUsed: resolvedSessionPercent, + sessionResetsAt: sessionResets, + weeklyPercentUsed: weeklyPercent, + weeklyResetsAt: weeklyResets, + opusPercentUsed: opusPercent, + extraRateWindows: extraRateParse.windows, + extraUsageCost: extraUsageCost, + accountOrganization: nil, + accountEmail: nil, + loginMethod: nil, + hasLiveSessionWindow: hasLiveSessionWindow) + } + + private static func percentValue(from value: Any?) -> Double? { + if let intValue = value as? Int { + return Double(intValue) + } + if let doubleValue = value as? Double { + return doubleValue + } + return nil + } + + #if DEBUG + + // MARK: - Test hooks (DEBUG-only) + + public static func _parseUsageResponseForTesting(_ data: Data) throws -> WebUsageData { + try self.parseUsageResponse(data) + } + + public static func _parseOrganizationsResponseForTesting( + _ data: Data, + targetOrganizationID: String? = nil) throws -> OrganizationInfo + { + try self.parseOrganizationResponse(data, targetOrganizationID: targetOrganizationID) + } + + public static func _parseOverageSpendLimitForTesting(_ data: Data) -> ProviderCostSnapshot? { + ClaudeWebExtraUsageCost.parseOverageSpendLimit(data) + } + + public static func _parseAccountInfoForTesting(_ data: Data, orgId: String?) -> WebAccountInfo? { + self.parseAccountInfo(data, orgId: orgId) + } + #endif + + private static func parseISO8601Date(_ string: String) -> Date? { + let formatter = ISO8601DateFormatter() + formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds] + if let date = formatter.date(from: string) { + return date + } + // Try without fractional seconds + formatter.formatOptions = [.withInternetDateTime] + return formatter.date(from: string) + } + + private static func parseOrganizationResponse( + _ data: Data, + targetOrganizationID: String? = nil) throws -> OrganizationInfo + { + guard let organizations = try? JSONDecoder().decode([ClaudeWebOrganizationResponse].self, from: data) else { + throw FetchError.invalidResponse + } + if let targetOrganizationID = targetOrganizationID?.trimmingCharacters(in: .whitespacesAndNewlines), + !targetOrganizationID.isEmpty + { + guard let selected = organizations.first(where: { $0.uuid == targetOrganizationID }) else { + throw FetchError.organizationNotFound(targetOrganizationID) + } + return self.organizationInfo(from: selected) + } + guard let selected = organizations.first(where: { $0.hasChatCapability }) + ?? organizations.first(where: { !$0.isApiOnly }) + ?? organizations.first + else { + throw FetchError.noOrganization + } + return self.organizationInfo(from: selected) + } + + private static func organizationInfo(from selected: ClaudeWebOrganizationResponse) -> OrganizationInfo { + let name = selected.name?.trimmingCharacters(in: .whitespacesAndNewlines) + let sanitized = (name?.isEmpty ?? true) ? nil : name + return OrganizationInfo(id: selected.uuid, name: sanitized) + } + + public struct WebAccountInfo: Sendable { + public let email: String? + public let loginMethod: String? + + public init(email: String?, loginMethod: String?) { + self.email = email + self.loginMethod = loginMethod + } + } + + private struct AccountResponse: Decodable { + let emailAddress: String? + let memberships: [Membership]? + + enum CodingKeys: String, CodingKey { + case emailAddress = "email_address" + case memberships + } + + struct Membership: Decodable { + let organization: Organization + + struct Organization: Decodable { + let uuid: String? + let name: String? + let rateLimitTier: String? + let billingType: String? + + enum CodingKeys: String, CodingKey { + case uuid + case name + case rateLimitTier = "rate_limit_tier" + case billingType = "billing_type" + } + } + } + } + + private static func fetchAccountInfo( + sessionKey: String, + orgId: String?, + logger: ((String) -> Void)? = nil, + renewalTracker: ClaudeWebSessionKeyRenewalTracker? = nil) async -> WebAccountInfo? + { + let url = URL(string: "\(baseURL)/account")! + var request = URLRequest(url: url) + request.setValue("sessionKey=\(sessionKey)", forHTTPHeaderField: "Cookie") + request.setValue("application/json", forHTTPHeaderField: "Accept") + request.httpMethod = "GET" + request.timeoutInterval = 15 + + do { + let (data, response) = try await ClaudeWebHTTPTransport.current.data(for: request) + guard let httpResponse = response as? HTTPURLResponse else { return nil } + renewalTracker?.observe(response: httpResponse) + logger?("Account API status: \(httpResponse.statusCode)") + guard httpResponse.statusCode == 200 else { return nil } + return Self.parseAccountInfo(data, orgId: orgId) + } catch { + return nil + } + } + + private static func parseAccountInfo(_ data: Data, orgId: String?) -> WebAccountInfo? { + guard let response = try? JSONDecoder().decode(AccountResponse.self, from: data) else { return nil } + let email = response.emailAddress?.trimmingCharacters(in: .whitespacesAndNewlines) + let membership = Self.selectMembership(response.memberships, orgId: orgId) + let plan = ClaudePlan.webLoginMethod( + rateLimitTier: membership?.organization.rateLimitTier, + billingType: membership?.organization.billingType) + return WebAccountInfo(email: email, loginMethod: plan) + } + + private static func selectMembership( + _ memberships: [AccountResponse.Membership]?, + orgId: String?) -> AccountResponse.Membership? + { + guard let memberships, !memberships.isEmpty else { return nil } + if let orgId { + if let match = memberships.first(where: { $0.organization.uuid == orgId }) { return match } + } + return memberships.first + } + + private struct ProbeParseResult { + let keys: [String] + let emails: [String] + let planHints: [String] + let notableFields: [String] + let preview: String? + } + + private static func parseProbeBody( + data: Data, + fallbackText: String, + contentType: String?) -> ProbeParseResult + { + let trimmed = fallbackText.trimmingCharacters(in: .whitespacesAndNewlines) + let looksJSON = (contentType?.lowercased().contains("application/json") ?? false) || + trimmed.hasPrefix("{") || trimmed.hasPrefix("[") + + var keys: [String] = [] + var notableFields: [String] = [] + if looksJSON, let json = try? JSONSerialization.jsonObject(with: data) { + if let dict = json as? [String: Any] { + keys = dict.keys.sorted() + } else if let array = json as? [[String: Any]], let first = array.first { + keys = first.keys.sorted() + } + notableFields = Self.extractNotableFields(from: json) + } + + let emails = Self.extractEmails(from: trimmed) + let planHints = Self.extractPlanHints(from: trimmed) + let preview = trimmed.isEmpty ? nil : String(trimmed.prefix(500)) + return ProbeParseResult( + keys: keys, + emails: emails, + planHints: planHints, + notableFields: notableFields, + preview: preview) + } + + private static func extractEmails(from text: String) -> [String] { + let pattern = #"(?i)[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}"# + guard let regex = try? NSRegularExpression(pattern: pattern, options: []) else { return [] } + let range = NSRange(text.startIndex.. [String] { + let pattern = #"(?i)\b(max|pro|team|ultra|enterprise)\b"# + guard let regex = try? NSRegularExpression(pattern: pattern, options: []) else { return [] } + let range = NSRange(text.startIndex.. [String] { + let pattern = #"(?i)(plan|tier|subscription|seat|billing|product)"# + guard let regex = try? NSRegularExpression(pattern: pattern, options: []) else { return [] } + var results: [String] = [] + + func keyMatches(_ key: String) -> Bool { + let range = NSRange(key.startIndex..= 40 { return } + let rendered: String + switch value { + case let str as String: + rendered = str + case let num as NSNumber: + rendered = num.stringValue + case let bool as Bool: + rendered = bool ? "true" : "false" + default: + return + } + let trimmed = rendered.trimmingCharacters(in: .whitespacesAndNewlines) + guard !trimmed.isEmpty else { return } + results.append("\(keyPath)=\(trimmed)") + } + + func walk(_ value: Any, path: String) { + if let dict = value as? [String: Any] { + for (key, nested) in dict { + let nextPath = path.isEmpty ? key : "\(path).\(key)" + if keyMatches(key) { + appendValue(nextPath, value: nested) + } + walk(nested, path: nextPath) + } + } else if let array = value as? [Any] { + for (idx, nested) in array.enumerated() { + let nextPath = "\(path)[\(idx)]" + walk(nested, path: nextPath) + } + } + } + + walk(json, path: "") + return results + } + + #else + + public static func fetchUsage(logger: ((String) -> Void)? = nil) async throws -> WebUsageData { + throw FetchError.notSupportedOnThisPlatform + } + + public static func fetchUsage( + browserDetection: BrowserDetection, + targetOrganizationID: String? = nil, + logger: ((String) -> Void)? = nil) async throws -> WebUsageData + { + _ = browserDetection + _ = targetOrganizationID + _ = logger + throw FetchError.notSupportedOnThisPlatform + } + + public static func fetchUsage( + cookieHeader: String, + targetOrganizationID: String? = nil, + logger: ((String) -> Void)? = nil) async throws -> WebUsageData + { + _ = cookieHeader + _ = targetOrganizationID + _ = logger + throw FetchError.notSupportedOnThisPlatform + } + + public static func fetchUsage( + using sessionKeyInfo: SessionKeyInfo, + targetOrganizationID: String? = nil, + logger: ((String) -> Void)? = nil) async throws -> WebUsageData + { + _ = targetOrganizationID + throw FetchError.notSupportedOnThisPlatform + } + + public static func probeEndpoints( + _ endpoints: [String], + includePreview: Bool = false, + logger: ((String) -> Void)? = nil) async throws -> [ProbeResult] + { + throw FetchError.notSupportedOnThisPlatform + } + + public static func hasSessionKey(browserDetection: BrowserDetection, logger: ((String) -> Void)? = nil) -> Bool { + _ = browserDetection + _ = logger + return false + } + + public static func hasSessionKey(cookieHeader: String?) -> Bool { + guard let cookieHeader else { return false } + for pair in CookieHeaderNormalizer.pairs(from: cookieHeader) where pair.name == "sessionKey" { + let value = pair.value.trimmingCharacters(in: .whitespacesAndNewlines) + if value.hasPrefix("sk-ant-") { + return true + } + } + return false + } + + public static func sessionKeyInfo(logger: ((String) -> Void)? = nil) throws -> SessionKeyInfo { + throw FetchError.notSupportedOnThisPlatform + } + + #endif +} + +extension ClaudeWebAPIFetcher { + private static func persistSessionKeyIfNeeded( + source: (initialSessionKey: String, label: String), + renewedCookieHeader: String?, + expectedCacheObservation: CookieHeaderCache.ConditionalMutationObservation, + persistInitialSessionKey: Bool, + logger: (String) -> Void) + { + let importedCookieHeader = persistInitialSessionKey ? "sessionKey=\(source.initialSessionKey)" : nil + guard let cookieHeader = renewedCookieHeader ?? importedCookieHeader else { return } + let stored = CookieHeaderCache.storeIfObservationCurrent( + provider: .claude, + expected: expectedCacheObservation, + cookieHeader: cookieHeader, + sourceLabel: source.label) + if renewedCookieHeader != nil { + logger(stored ? "Stored renewed Claude session key" : "Skipped renewal because the cache changed") + } + } +} + +private final class ClaudeWebSessionKeyRenewalTracker: @unchecked Sendable { + private let initialSessionKey: String + private let lock = NSLock() + private var currentSessionKey: String + + init(initialSessionKey: String) { + self.initialSessionKey = initialSessionKey + self.currentSessionKey = initialSessionKey + } + + var sessionKey: String { + self.lock.lock() + defer { self.lock.unlock() } + return self.currentSessionKey + } + + var renewedCookieHeader: String? { + self.lock.lock() + defer { self.lock.unlock() } + guard self.currentSessionKey != self.initialSessionKey else { return nil } + return "sessionKey=\(self.currentSessionKey)" + } + + func observe(response: HTTPURLResponse) { + guard response.statusCode == 200, + let sessionKey = Self.sessionKey(fromSetCookieHeaders: response.allHeaderFields) + else { + return + } + self.lock.lock() + self.currentSessionKey = sessionKey + self.lock.unlock() + } + + private static func sessionKey(fromSetCookieHeaders fields: [AnyHashable: Any]) -> String? { + guard let value = fields.first(where: { + String(describing: $0.key).caseInsensitiveCompare("Set-Cookie") == .orderedSame + })?.value else { + return nil + } + var latestSessionKey: String? + for header in self.setCookieHeaderValues(from: value) { + latestSessionKey = self.sessionKey(fromSetCookieHeader: header) ?? latestSessionKey + } + return latestSessionKey + } + + private static func setCookieHeaderValues(from value: Any) -> [String] { + if let values = value as? [String] { + return values + } + if let values = value as? [Any] { + return values.map { String(describing: $0) } + } + return [String(describing: value)] + } + + private static func sessionKey(fromSetCookieHeader header: String) -> String? { + let pattern = #"(?i)(?:^|[,\r\n])\s*sessionKey=([^;,\r\n]+)"# + guard let regex = try? NSRegularExpression(pattern: pattern) else { return nil } + let range = NSRange(header.startIndex..= 2, + let valueRange = Range(match.range(at: 1), in: header) + else { + continue + } + let value = String(header[valueRange]).trimmingCharacters(in: .whitespacesAndNewlines) + if value.hasPrefix("sk-ant-") { + latestSessionKey = value + } + } + return latestSessionKey + } +} + +private enum ClaudeWebExtraUsageCost { + // MARK: - Extra usage cost (Claude "Extra") + + static func parse(from value: Any?) -> ProviderCostSnapshot? { + guard let extraUsage = value as? [String: Any] else { return nil } + guard let used = Self.doubleValue(extraUsage["used_credits"]), + let limit = Self.doubleValue(extraUsage["monthly_limit"] ?? extraUsage["monthly_credit_limit"]), + limit > 0 else { return nil } + let currency = (extraUsage["currency"] as? String)?.trimmingCharacters(in: .whitespacesAndNewlines) + let currencyCode = currency?.isEmpty == false ? currency ?? "USD" : "USD" + return Self.makeExtraUsageCost( + usedCredits: used, + monthlyCreditLimit: limit, + currencyCode: currencyCode) + } + + struct OverageSpendLimitResponse: Decodable { + let monthlyCreditLimit: Double? + let currency: String? + let usedCredits: Double? + let isEnabled: Bool? + + enum CodingKeys: String, CodingKey { + case monthlyCreditLimit = "monthly_credit_limit" + case currency + case usedCredits = "used_credits" + case isEnabled = "is_enabled" + } + } + + /// Best-effort fetch of Claude Extra spend/limit (does not fail the main usage fetch). + static func fetch( + baseURL: String, + orgId: String, + sessionKey: String, + logger: ((String) -> Void)? = nil, + renewalTracker: ClaudeWebSessionKeyRenewalTracker? = nil) async -> ProviderCostSnapshot? + { + let url = URL(string: "\(baseURL)/organizations/\(orgId)/overage_spend_limit")! + var request = URLRequest(url: url) + request.setValue("sessionKey=\(sessionKey)", forHTTPHeaderField: "Cookie") + request.setValue("application/json", forHTTPHeaderField: "Accept") + request.httpMethod = "GET" + request.timeoutInterval = 15 + + do { + let (data, response) = try await ClaudeWebHTTPTransport.current.data(for: request) + guard let httpResponse = response as? HTTPURLResponse else { return nil } + renewalTracker?.observe(response: httpResponse) + logger?("Overage API status: \(httpResponse.statusCode)") + guard httpResponse.statusCode == 200 else { return nil } + return Self.parseOverageSpendLimit(data) + } catch { + return nil + } + } + + static func parseOverageSpendLimit(_ data: Data) -> ProviderCostSnapshot? { + guard let decoded = try? JSONDecoder().decode(OverageSpendLimitResponse.self, from: data) else { return nil } + guard decoded.isEnabled == true else { return nil } + guard let used = decoded.usedCredits, + let limit = decoded.monthlyCreditLimit, + let currency = decoded.currency, + !currency.isEmpty else { return nil } + + return Self.makeExtraUsageCost( + usedCredits: used, + monthlyCreditLimit: limit, + currencyCode: currency) + } + + static func makeExtraUsageCost( + usedCredits: Double, + monthlyCreditLimit: Double, + currencyCode: String) -> ProviderCostSnapshot + { + let usedAmount = usedCredits / 100.0 + let limitAmount = monthlyCreditLimit / 100.0 + + return ProviderCostSnapshot( + used: usedAmount, + limit: limitAmount, + currencyCode: currencyCode, + period: "Monthly cap", + resetsAt: nil, + updatedAt: Date()) + } + + static func doubleValue(_ value: Any?) -> Double? { + switch value { + case let int as Int: + Double(int) + case let double as Double: + double + case let string as String: + Double(string) + default: + nil + } + } +} + +#if os(macOS) +extension ClaudeWebAPIFetcher { + fileprivate static func fetchUsageSerialized( + browserDetection: BrowserDetection, + targetOrganizationID: String?, + logger: ((String) -> Void)?) async throws -> WebUsageData + { + let log: (String) -> Void = { msg in logger?("[claude-web] \(msg)") } + var cacheObservation = CookieHeaderCache.observeForConditionalMutation(provider: .claude) + + if let cached = cacheObservation.entry, + !cached.cookieHeader.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty + { + log("Using cached cookie header from \(cached.sourceLabel)") + do { + return try await self.fetchUsageAndRenewCache( + cachedEntry: cached, + targetOrganizationID: targetOrganizationID, + logger: log) + } catch let error as FetchError { + switch error { + case .unauthorized, .noSessionKeyFound, .invalidSessionKey: + let cleared = CookieHeaderCache.clearIfCurrent(provider: .claude, expected: cached) + cacheObservation = .authoritative(cleared ? nil : cached) + default: + throw error + } + } catch { + throw error + } + } + + let sessionInfo = try extractSessionKeyInfo(browserDetection: browserDetection, logger: log) + log("Found session key (\(sessionInfo.cookieCount) cookies)") + + return try await self.fetchUsage( + using: sessionInfo, + targetOrganizationID: targetOrganizationID, + logger: log, + cacheSourceLabel: sessionInfo.sourceLabel, + expectedCacheObservation: cacheObservation, + persistInitialSessionKey: true) + } +} +#endif + +private struct ClaudeWebOrganizationResponse: Decodable { + let uuid: String + let name: String? + let capabilities: [String]? + + var normalizedCapabilities: Set { + Set((self.capabilities ?? []).map { $0.lowercased() }) + } + + var hasChatCapability: Bool { + self.normalizedCapabilities.contains("chat") + } + + var isApiOnly: Bool { + let normalized = self.normalizedCapabilities + return !normalized.isEmpty && normalized == ["api"] + } +} diff --git a/Sources/CodexBarCore/Providers/Claude/ClaudeWeb/ClaudeWebExtraRateWindowParser.swift b/Sources/CodexBarCore/Providers/Claude/ClaudeWeb/ClaudeWebExtraRateWindowParser.swift new file mode 100644 index 0000000..4090cf3 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Claude/ClaudeWeb/ClaudeWebExtraRateWindowParser.swift @@ -0,0 +1,123 @@ +import Foundation + +enum ClaudeWebExtraRateWindowParser { + private static let definitions: [(id: String, title: String, keys: [String])] = [ + ( + id: "claude-routines", + title: "Daily Routines", + keys: [ + "seven_day_routines", + "seven_day_claude_routines", + "claude_routines", + "routines", + "routine", + "seven_day_cowork", + "cowork", + ]), + ] + + static func parse(from json: [String: Any]) -> (windows: [NamedRateWindow], sourceKeys: [String: String]) { + var windows: [NamedRateWindow] = [] + var sourceKeys: [String: String] = [:] + windows.reserveCapacity(Self.definitions.count) + + for definition in Self.definitions { + if let foundWindow = Self.firstUsageWindow(in: json, keys: definition.keys) { + let rawWindow = foundWindow.window + guard let utilization = Self.percentValue(from: rawWindow["utilization"]) else { continue } + let resetsAt = (rawWindow["resets_at"] as? String).flatMap(Self.parseISO8601Date) + windows.append(Self.namedWindow( + id: definition.id, + title: definition.title, + usedPercent: utilization, + resetsAt: resetsAt)) + sourceKeys[definition.id] = foundWindow.sourceKey + continue + } + + // Some accounts expose the key with null payloads (for example `seven_day_cowork: null`). + // Preserve the bar in that case with a 0% window so the product section remains visible. + if let key = Self.firstUsageKey(in: json, keys: definition.keys) { + windows.append(Self.namedWindow( + id: definition.id, + title: definition.title, + usedPercent: 0, + resetsAt: nil)) + sourceKeys[definition.id] = key + } + } + windows.append(contentsOf: Self.scopedWeeklyLimitWindows(from: json)) + return (windows, sourceKeys) + } + + private static func scopedWeeklyLimitWindows(from json: [String: Any]) -> [NamedRateWindow] { + guard let limits = json["limits"] as? [[String: Any]] else { return [] } + let mappedLimits = limits.map { entry in + let scope = entry["scope"] as? [String: Any] + let model = scope?["model"] as? [String: Any] + return ClaudeScopedWeeklyLimitMapper.Limit( + kind: entry["kind"] as? String, + group: entry["group"] as? String, + percent: Self.percentValue(from: entry["percent"]), + resetsAt: (entry["resets_at"] as? String).flatMap(Self.parseISO8601Date), + modelID: model?["id"] as? String, + modelName: model?["display_name"] as? String) + } + return ClaudeScopedWeeklyLimitMapper.extraRateWindows(from: mappedLimits) + } + + private static func namedWindow( + id: String, + title: String, + usedPercent: Double, + resetsAt: Date?) -> NamedRateWindow + { + NamedRateWindow( + id: id, + title: title, + window: RateWindow( + usedPercent: usedPercent, + windowMinutes: 7 * 24 * 60, + resetsAt: resetsAt, + resetDescription: nil)) + } + + private static func firstUsageWindow( + in json: [String: Any], + keys: [String]) -> (window: [String: Any], sourceKey: String)? + { + for key in keys { + if let window = json[key] as? [String: Any] { + return (window, key) + } + } + return nil + } + + private static func firstUsageKey(in json: [String: Any], keys: [String]) -> String? { + for key in keys where json.keys.contains(key) { + return key + } + return nil + } + + private static func percentValue(from value: Any?) -> Double? { + if let intValue = value as? Int { + return Double(intValue) + } + if let doubleValue = value as? Double { + return doubleValue + } + return nil + } + + private static func parseISO8601Date(_ string: String) -> Date? { + let formatter = ISO8601DateFormatter() + formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds] + if let date = formatter.date(from: string) { + return date + } + formatter.formatOptions = [.withInternetDateTime] + return formatter.date(from: string) + } +} diff --git a/Sources/CodexBarCore/Providers/ClawRouter/ClawRouterProviderDescriptor.swift b/Sources/CodexBarCore/Providers/ClawRouter/ClawRouterProviderDescriptor.swift new file mode 100644 index 0000000..2b52905 --- /dev/null +++ b/Sources/CodexBarCore/Providers/ClawRouter/ClawRouterProviderDescriptor.swift @@ -0,0 +1,62 @@ +import Foundation + +public enum ClawRouterProviderDescriptor { + public static let descriptor: ProviderDescriptor = Self.makeDescriptor() + + static func makeDescriptor() -> ProviderDescriptor { + ProviderDescriptor( + id: .clawrouter, + metadata: ProviderMetadata( + id: .clawrouter, + displayName: "ClawRouter", + sessionLabel: "Monthly budget", + weeklyLabel: "Requests", + opusLabel: nil, + supportsOpus: false, + supportsCredits: false, + creditsHint: "", + toggleTitle: "Show ClawRouter usage", + cliName: "clawrouter", + defaultEnabled: false, + dashboardURL: "https://clawrouter.openclaw.ai/dashboard/access", + statusPageURL: nil), + branding: ProviderBranding( + iconStyle: .clawrouter, + iconResourceName: "ProviderIcon-clawrouter", + color: ProviderColor(red: 89 / 255, green: 110 / 255, blue: 246 / 255)), + tokenCost: ProviderTokenCostConfig( + supportsTokenCost: false, + noDataMessage: { "ClawRouter spend is reported by its usage API." }), + fetchPlan: ProviderFetchPlan( + sourceModes: [.auto, .api], + pipeline: ProviderFetchPipeline(resolveStrategies: { _ in [ClawRouterAPIFetchStrategy()] })), + cli: ProviderCLIConfig( + name: "clawrouter", + aliases: ["claw-router"], + versionDetector: nil)) + } +} + +struct ClawRouterAPIFetchStrategy: ProviderFetchStrategy { + let id = "clawrouter.api" + let kind: ProviderFetchKind = .apiToken + + func isAvailable(_ context: ProviderFetchContext) async -> Bool { + ProviderTokenResolver.clawRouterToken(environment: context.env) != nil + } + + func fetch(_ context: ProviderFetchContext) async throws -> ProviderFetchResult { + guard let apiKey = ProviderTokenResolver.clawRouterToken(environment: context.env) else { + throw ClawRouterUsageError.missingCredentials + } + try ClawRouterSettingsReader.validateEndpointOverride(environment: context.env) + let usage = try await ClawRouterUsageFetcher.fetchUsage( + apiKey: apiKey, + baseURL: ClawRouterSettingsReader.baseURL(environment: context.env)) + return self.makeResult(usage: usage.toUsageSnapshot(), sourceLabel: "api") + } + + func shouldFallback(on _: Error, context _: ProviderFetchContext) -> Bool { + false + } +} diff --git a/Sources/CodexBarCore/Providers/ClawRouter/ClawRouterSettingsReader.swift b/Sources/CodexBarCore/Providers/ClawRouter/ClawRouterSettingsReader.swift new file mode 100644 index 0000000..4504b07 --- /dev/null +++ b/Sources/CodexBarCore/Providers/ClawRouter/ClawRouterSettingsReader.swift @@ -0,0 +1,55 @@ +import Foundation + +public enum ClawRouterSettingsError: LocalizedError, Equatable, Sendable { + case invalidEndpointOverride(String) + + public var errorDescription: String? { + switch self { + case let .invalidEndpointOverride(key): + "ClawRouter endpoint override \(key) is invalid. Use an HTTPS URL without embedded credentials." + } + } +} + +public enum ClawRouterSettingsReader { + public static let apiKeyEnvironmentKey = "CLAWROUTER_API_KEY" + public static let baseURLEnvironmentKey = "CLAWROUTER_BASE_URL" + public static let defaultBaseURL = URL(string: "https://clawrouter.openclaw.ai")! + + public static func apiKey( + environment: [String: String] = ProcessInfo.processInfo.environment) -> String? + { + self.cleaned(environment[self.apiKeyEnvironmentKey]) + } + + public static func baseURL( + environment: [String: String] = ProcessInfo.processInfo.environment) -> URL + { + guard let raw = self.cleaned(environment[self.baseURLEnvironmentKey]) else { + return self.defaultBaseURL + } + return ProviderEndpointOverrideValidator.normalizedHTTPSURL(from: raw) ?? self.defaultBaseURL + } + + public static func validateEndpointOverride( + environment: [String: String] = ProcessInfo.processInfo.environment) throws + { + guard let raw = self.cleaned(environment[self.baseURLEnvironmentKey]) else { return } + guard ProviderEndpointOverrideValidator.normalizedHTTPSURL(from: raw) != nil else { + throw ClawRouterSettingsError.invalidEndpointOverride(self.baseURLEnvironmentKey) + } + } + + static func cleaned(_ raw: String?) -> String? { + guard var value = raw?.trimmingCharacters(in: .whitespacesAndNewlines), !value.isEmpty else { + return nil + } + if (value.hasPrefix("\"") && value.hasSuffix("\"")) || + (value.hasPrefix("'") && value.hasSuffix("'")) + { + value = String(value.dropFirst().dropLast()) + } + value = value.trimmingCharacters(in: .whitespacesAndNewlines) + return value.isEmpty ? nil : value + } +} diff --git a/Sources/CodexBarCore/Providers/ClawRouter/ClawRouterUsageFetcher.swift b/Sources/CodexBarCore/Providers/ClawRouter/ClawRouterUsageFetcher.swift new file mode 100644 index 0000000..609a790 --- /dev/null +++ b/Sources/CodexBarCore/Providers/ClawRouter/ClawRouterUsageFetcher.swift @@ -0,0 +1,255 @@ +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +public enum ClawRouterUsageError: LocalizedError, Equatable, Sendable { + case missingCredentials + case invalidCredentials + case apiError(Int) + case parseFailed(String) + + public var errorDescription: String? { + switch self { + case .missingCredentials: + "Missing ClawRouter API key. Add one in Settings or set CLAWROUTER_API_KEY." + case .invalidCredentials: + "ClawRouter rejected the API key. Check the key and its policy status." + case let .apiError(statusCode): + "ClawRouter API returned HTTP \(statusCode)." + case let .parseFailed(message): + "Could not parse ClawRouter usage: \(message)" + } + } +} + +public struct ClawRouterUsageSnapshot: Codable, Sendable, Equatable { + public struct ProviderSummary: Codable, Sendable, Equatable { + public let provider: String + public let requestCount: Int + public let successCount: Int + public let errorCount: Int + public let totalTokens: Int + public let actualCostUSD: Double + } + + public let budgetConfigured: Bool + public let budgetLedger: String + public let budgetLimitUSD: Double? + public let budgetSpentUSD: Double? + public let budgetRemainingUSD: Double? + public let budgetResetsAt: Date? + public let requestCount: Int + public let successCount: Int + public let errorCount: Int + public let inputTokens: Int + public let outputTokens: Int + public let totalTokens: Int + public let actualCostUSD: Double + public let providers: [ProviderSummary] + public let updatedAt: Date + + public func toUsageSnapshot() -> UsageSnapshot { + let usedPercent: Double? = if let spent = self.budgetSpentUSD, + let limit = self.budgetLimitUSD, + limit > 0 + { + min(100, max(0, spent / limit * 100)) + } else { + nil + } + let providerCost: ProviderCostSnapshot? = if let spent = self.budgetSpentUSD, + let limit = self.budgetLimitUSD + { + ProviderCostSnapshot( + used: spent, + limit: limit, + currencyCode: "USD", + period: "This month", + resetsAt: self.budgetResetsAt, + updatedAt: self.updatedAt) + } else if self.actualCostUSD > 0 { + ProviderCostSnapshot( + used: self.actualCostUSD, + limit: 0, + currencyCode: "USD", + period: "This month", + resetsAt: self.budgetResetsAt, + updatedAt: self.updatedAt) + } else { + nil + } + + return UsageSnapshot( + primary: usedPercent.map { + RateWindow( + usedPercent: $0, + windowMinutes: nil, + resetsAt: self.budgetResetsAt, + resetDescription: nil) + }, + secondary: nil, + providerCost: providerCost, + clawRouterUsage: self, + updatedAt: self.updatedAt, + identity: ProviderIdentitySnapshot( + providerID: .clawrouter, + accountEmail: nil, + accountOrganization: "\(self.providers.count) routed providers", + loginMethod: self.budgetConfigured ? "Managed monthly budget" : "Unmetered"), + dataConfidence: .exact) + } +} + +private struct ClawRouterUsageResponse: Decodable { + struct Budget: Decodable { + let configured: Bool + let ledger: String + let windowKey: String? + let limitMicros: Int64? + let spentMicros: Int64? + let remainingMicros: Int64? + } + + struct Usage: Decodable { + struct Summary: Decodable { + let requestCount: Int + let successCount: Int + let errorCount: Int + let inputTokens: Int + let outputTokens: Int + let totalTokens: Int + let actualCostMicros: Int64 + } + + struct Provider: Decodable { + let provider: String + let requestCount: Int + let successCount: Int + let errorCount: Int + let totalTokens: Int + let actualCostMicros: Int64 + } + + let summary: Summary + let providers: [Provider] + } + + let budget: Budget + let usage: Usage +} + +public enum ClawRouterUsageFetcher { + public static func fetchUsage( + apiKey: String, + baseURL: URL, + transport: any ProviderHTTPTransport = ProviderHTTPClient.shared, + updatedAt: Date = Date()) async throws -> ClawRouterUsageSnapshot + { + guard !apiKey.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else { + throw ClawRouterUsageError.missingCredentials + } + var request = URLRequest(url: self.usageURL(baseURL: baseURL)) + request.httpMethod = "GET" + request.timeoutInterval = 15 + request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization") + request.setValue("application/json", forHTTPHeaderField: "Accept") + + let response = try await transport.response(for: request) + if response.statusCode == 401 || response.statusCode == 403 { + throw ClawRouterUsageError.invalidCredentials + } + guard (200..<300).contains(response.statusCode) else { + throw ClawRouterUsageError.apiError(response.statusCode) + } + return try self.parseSnapshot(data: response.data, updatedAt: updatedAt) + } + + public static func _parseSnapshotForTesting( + _ data: Data, + updatedAt: Date) throws -> ClawRouterUsageSnapshot + { + try self.parseSnapshot(data: data, updatedAt: updatedAt) + } + + public static func _usageURLForTesting(baseURL: URL) -> URL { + self.usageURL(baseURL: baseURL) + } + + private static func usageURL(baseURL: URL) -> URL { + let path = baseURL.path.trimmingCharacters(in: CharacterSet(charactersIn: "/")) + let versionedBaseURL = path.split(separator: "/").last == "v1" + ? baseURL + : baseURL.appendingPathComponent("v1") + return versionedBaseURL.appendingPathComponent("usage") + } + + private static func parseSnapshot(data: Data, updatedAt: Date) throws -> ClawRouterUsageSnapshot { + do { + let response = try JSONDecoder().decode(ClawRouterUsageResponse.self, from: data) + return ClawRouterUsageSnapshot( + budgetConfigured: response.budget.configured, + budgetLedger: response.budget.ledger, + budgetLimitUSD: self.dollars(response.budget.limitMicros), + budgetSpentUSD: self.dollars(response.budget.spentMicros), + budgetRemainingUSD: self.dollars(response.budget.remainingMicros), + budgetResetsAt: self.nextMonthlyReset(windowKey: response.budget.windowKey), + requestCount: response.usage.summary.requestCount, + successCount: response.usage.summary.successCount, + errorCount: response.usage.summary.errorCount, + inputTokens: response.usage.summary.inputTokens, + outputTokens: response.usage.summary.outputTokens, + totalTokens: response.usage.summary.totalTokens, + actualCostUSD: self.dollars(response.usage.summary.actualCostMicros), + providers: response.usage.providers.map { + ClawRouterUsageSnapshot.ProviderSummary( + provider: $0.provider, + requestCount: $0.requestCount, + successCount: $0.successCount, + errorCount: $0.errorCount, + totalTokens: $0.totalTokens, + actualCostUSD: self.dollars($0.actualCostMicros)) + }.sorted { + if $0.actualCostUSD != $1.actualCostUSD { return $0.actualCostUSD > $1.actualCostUSD } + if $0.requestCount != $1.requestCount { return $0.requestCount > $1.requestCount } + return $0.provider < $1.provider + }, + updatedAt: updatedAt) + } catch let error as ClawRouterUsageError { + throw error + } catch { + throw ClawRouterUsageError.parseFailed(error.localizedDescription) + } + } + + private static func dollars(_ micros: Int64?) -> Double? { + micros.map(self.dollars) + } + + private static func dollars(_ micros: Int64) -> Double { + Double(micros) / 1_000_000 + } + + private static func nextMonthlyReset(windowKey: String?) -> Date? { + guard let suffix = windowKey?.split(separator: "/").last else { return nil } + let components = suffix.split(separator: "-") + guard components.count == 2, + let year = Int(components[0]), + let month = Int(components[1]), + (1...12).contains(month) + else { return nil } + + var nextYear = year + var nextMonth = month + 1 + if nextMonth == 13 { + nextMonth = 1 + nextYear += 1 + } + return DateComponents( + calendar: Calendar(identifier: .gregorian), + timeZone: TimeZone(secondsFromGMT: 0), + year: nextYear, + month: nextMonth, + day: 1).date + } +} diff --git a/Sources/CodexBarCore/Providers/Codebuff/CodebuffProviderDescriptor.swift b/Sources/CodexBarCore/Providers/Codebuff/CodebuffProviderDescriptor.swift new file mode 100644 index 0000000..6ea5634 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Codebuff/CodebuffProviderDescriptor.swift @@ -0,0 +1,95 @@ +import Foundation + +public enum CodebuffProviderDescriptor { + public static let descriptor: ProviderDescriptor = Self.makeDescriptor() + + static func makeDescriptor() -> ProviderDescriptor { + ProviderDescriptor( + id: .codebuff, + metadata: ProviderMetadata( + id: .codebuff, + displayName: "Codebuff", + sessionLabel: "Credits", + weeklyLabel: "Weekly", + opusLabel: nil, + supportsOpus: false, + supportsCredits: true, + creditsHint: "Credit balance from the Codebuff API", + toggleTitle: "Show Codebuff usage", + cliName: "codebuff", + defaultEnabled: false, + isPrimaryProvider: false, + usesAccountFallback: false, + browserCookieOrder: nil, + dashboardURL: "https://www.codebuff.com/usage", + statusPageURL: nil, + statusLinkURL: nil), + branding: ProviderBranding( + iconStyle: .codebuff, + iconResourceName: "ProviderIcon-codebuff", + color: ProviderColor(red: 68 / 255, green: 255 / 255, blue: 0 / 255)), + tokenCost: ProviderTokenCostConfig( + supportsTokenCost: false, + noDataMessage: { "Codebuff cost summary is not yet supported." }), + fetchPlan: ProviderFetchPlan( + sourceModes: [.auto, .api], + pipeline: ProviderFetchPipeline(resolveStrategies: { _ in [CodebuffAPIFetchStrategy()] })), + cli: ProviderCLIConfig( + name: "codebuff", + aliases: ["manicode"], + versionDetector: nil)) + } +} + +struct CodebuffAPIFetchStrategy: ProviderFetchStrategy { + let id: String = "codebuff.api" + let kind: ProviderFetchKind = .apiToken + + func isAvailable(_ context: ProviderFetchContext) async -> Bool { + _ = context + // Keep the strategy available so missing-token surfaces as a user-friendly error + // instead of a generic "no strategy" outcome. + return true + } + + func fetch(_ context: ProviderFetchContext) async throws -> ProviderFetchResult { + guard let resolution = Self.resolveToken(environment: context.env) else { + throw CodebuffUsageError.missingCredentials + } + let usage = try await CodebuffUsageFetcher.fetchUsage( + apiKey: resolution.token, + environment: context.env, + includeSubscription: Self.shouldFetchSubscription(for: resolution)) + return self.makeResult( + usage: usage.toUsageSnapshot(), + sourceLabel: "api") + } + + func shouldFallback(on _: Error, context _: ProviderFetchContext) -> Bool { + false + } + + static func shouldFetchSubscription(for resolution: ProviderTokenResolution) -> Bool { + resolution.source == .authFile + } + + private static func resolveToken(environment: [String: String]) -> ProviderTokenResolution? { + ProviderTokenResolver.codebuffResolution(environment: environment) + } +} + +/// Errors related to Codebuff settings. +public enum CodebuffSettingsError: LocalizedError, Sendable, Equatable { + case missingToken + case invalidEndpointOverride(String) + + public var errorDescription: String? { + switch self { + case .missingToken: + "Codebuff API token not configured. Set CODEBUFF_API_KEY or run `codebuff login` to " + + "populate ~/.config/manicode/credentials.json." + case let .invalidEndpointOverride(key): + "Codebuff endpoint override \(key) must use HTTPS or a bare host." + } + } +} diff --git a/Sources/CodexBarCore/Providers/Codebuff/CodebuffSettingsReader.swift b/Sources/CodexBarCore/Providers/Codebuff/CodebuffSettingsReader.swift new file mode 100644 index 0000000..633bf00 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Codebuff/CodebuffSettingsReader.swift @@ -0,0 +1,86 @@ +import Foundation + +/// Reads Codebuff settings from the environment or the local credentials file +/// that the `codebuff` CLI (formerly `manicode`) writes when the user logs in. +public enum CodebuffSettingsReader { + /// Environment variable key for the Codebuff API token. + public static let apiTokenKey = "CODEBUFF_API_KEY" + + /// Returns the API token from environment if present and non-empty. + public static func apiKey(environment: [String: String] = ProcessInfo.processInfo.environment) -> String? { + self.cleaned(environment[self.apiTokenKey]) + } + + /// Returns the API base URL, defaulting to the production endpoint. + public static func apiURL(environment: [String: String] = ProcessInfo.processInfo.environment) -> URL { + if let override = self.validAPIURL(environment: environment) { + return override + } + return URL(string: "https://www.codebuff.com")! + } + + public static func validateEndpointOverrides( + environment: [String: String] = ProcessInfo.processInfo.environment) throws + { + guard let raw = self.cleaned(environment["CODEBUFF_API_URL"]) else { return } + guard ProviderEndpointOverrideValidator.normalizedHTTPSURL(from: raw) == nil else { return } + throw CodebuffSettingsError.invalidEndpointOverride("CODEBUFF_API_URL") + } + + /// Returns the auth token from the local credentials file if present. + public static func authToken( + authFileURL: URL? = nil, + homeDirectory: URL = FileManager.default.homeDirectoryForCurrentUser) -> String? + { + let fileURL = authFileURL ?? self.defaultAuthFileURL(homeDirectory: homeDirectory) + guard let data = try? Data(contentsOf: fileURL) else { return nil } + return self.parseAuthToken(data: data) + } + + /// Default on-disk credentials path: `~/.config/manicode/credentials.json`. + static func defaultAuthFileURL(homeDirectory: URL) -> URL { + homeDirectory + .appendingPathComponent(".config", isDirectory: true) + .appendingPathComponent("manicode", isDirectory: true) + .appendingPathComponent("credentials.json", isDirectory: false) + } + + static func parseAuthToken(data: Data) -> String? { + guard let payload = try? JSONDecoder().decode(CredentialsFile.self, from: data) else { + return nil + } + return self.cleaned(payload.default?.authToken) ?? self.cleaned(payload.authToken) + } + + static func cleaned(_ raw: String?) -> String? { + guard var value = raw?.trimmingCharacters(in: .whitespacesAndNewlines), !value.isEmpty else { + return nil + } + + if (value.hasPrefix("\"") && value.hasSuffix("\"")) || + (value.hasPrefix("'") && value.hasSuffix("'")) + { + value = String(value.dropFirst().dropLast()) + } + + value = value.trimmingCharacters(in: .whitespacesAndNewlines) + return value.isEmpty ? nil : value + } + + private static func validAPIURL(environment: [String: String]) -> URL? { + guard let raw = self.cleaned(environment["CODEBUFF_API_URL"]) else { return nil } + return ProviderEndpointOverrideValidator.normalizedHTTPSURL(from: raw) + } +} + +private struct CredentialsFile: Decodable { + let `default`: CredentialsProfile? + let authToken: String? +} + +private struct CredentialsProfile: Decodable { + let authToken: String? + let fingerprintId: String? + let email: String? + let name: String? +} diff --git a/Sources/CodexBarCore/Providers/Codebuff/CodebuffUsageError.swift b/Sources/CodexBarCore/Providers/Codebuff/CodebuffUsageError.swift new file mode 100644 index 0000000..729d17f --- /dev/null +++ b/Sources/CodexBarCore/Providers/Codebuff/CodebuffUsageError.swift @@ -0,0 +1,40 @@ +import Foundation + +public enum CodebuffUsageError: LocalizedError, Sendable, Equatable { + case missingCredentials + case unauthorized + case endpointNotFound + case serviceUnavailable(Int) + case apiError(Int) + case networkError(String) + case parseFailed(String) + + public static let missingToken: CodebuffUsageError = .missingCredentials + + public var errorDescription: String? { + switch self { + case .missingCredentials: + "Codebuff API token not configured. Set CODEBUFF_API_KEY or run `codebuff login` to " + + "populate ~/.config/manicode/credentials.json." + case .unauthorized: + "Unauthorized. Please sign in to Codebuff again." + case .endpointNotFound: + "Codebuff usage endpoint not found." + case let .serviceUnavailable(status): + "Codebuff API is temporarily unavailable (status \(status))." + case let .apiError(status): + "Codebuff API returned an unexpected status (\(status))." + case let .networkError(message): + "Codebuff API error: \(message)" + case let .parseFailed(message): + "Could not parse Codebuff usage: \(message)" + } + } + + public var isAuthRelated: Bool { + switch self { + case .unauthorized, .missingCredentials: true + default: false + } + } +} diff --git a/Sources/CodexBarCore/Providers/Codebuff/CodebuffUsageFetcher.swift b/Sources/CodexBarCore/Providers/Codebuff/CodebuffUsageFetcher.swift new file mode 100644 index 0000000..830fa9b --- /dev/null +++ b/Sources/CodexBarCore/Providers/Codebuff/CodebuffUsageFetcher.swift @@ -0,0 +1,365 @@ +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +/// Fetches live credit balance and subscription details from the Codebuff API. +/// Uses Bearer token auth against the public www.codebuff.com endpoints used by +/// the dashboard + the `codebuff` CLI. +public enum CodebuffUsageFetcher { + private static let requestTimeoutSeconds: TimeInterval = 15 + /// Extra grace period to wait for the optional subscription endpoint after the + /// primary usage call returns. Keeps the menu responsive when `/api/user/subscription` + /// is slow or hangs while `/api/v1/usage` succeeds quickly. + private static let subscriptionGraceSeconds: TimeInterval = 2 + + public static func fetchUsage( + apiKey: String, + environment: [String: String] = ProcessInfo.processInfo.environment, + includeSubscription: Bool = true, + session transport: any ProviderHTTPTransport = ProviderHTTPClient.shared) async throws -> CodebuffUsageSnapshot + { + try await self.fetchUsage( + apiKey: apiKey, + environment: environment, + includeSubscription: includeSubscription, + transport: transport, + subscriptionGrace: .seconds(self.subscriptionGraceSeconds)) + } + + static func _fetchUsageForTesting( + apiKey: String, + environment: [String: String] = ProcessInfo.processInfo.environment, + includeSubscription: Bool = true, + transport: any ProviderHTTPTransport, + subscriptionGrace: Duration) async throws -> CodebuffUsageSnapshot + { + try await self.fetchUsage( + apiKey: apiKey, + environment: environment, + includeSubscription: includeSubscription, + transport: transport, + subscriptionGrace: subscriptionGrace) + } + + private static func fetchUsage( + apiKey: String, + environment: [String: String], + includeSubscription: Bool, + transport: any ProviderHTTPTransport, + subscriptionGrace: Duration) async throws -> CodebuffUsageSnapshot + { + let trimmed = apiKey.trimmingCharacters(in: .whitespacesAndNewlines) + guard !trimmed.isEmpty else { + throw CodebuffUsageError.missingCredentials + } + try CodebuffSettingsReader.validateEndpointOverrides(environment: environment) + + let baseURL = CodebuffSettingsReader.apiURL(environment: environment) + + let (usageValues, subscriptionValues) = try await self.fetchPayloads( + apiKey: trimmed, + baseURL: baseURL, + includeSubscription: includeSubscription, + transport: transport, + subscriptionGrace: subscriptionGrace) + + return CodebuffUsageSnapshot( + creditsUsed: usageValues.used, + creditsTotal: usageValues.total, + creditsRemaining: usageValues.remaining, + weeklyUsed: subscriptionValues?.weeklyUsed, + weeklyLimit: subscriptionValues?.weeklyLimit, + weeklyResetsAt: subscriptionValues?.weeklyResetsAt, + billingPeriodEnd: subscriptionValues?.billingPeriodEnd, + nextQuotaReset: usageValues.nextQuotaReset, + tier: subscriptionValues?.tier, + subscriptionStatus: subscriptionValues?.status, + autoTopUpEnabled: usageValues.autoTopupEnabled, + accountEmail: subscriptionValues?.email, + updatedAt: Date()) + } + + private static func fetchPayloads( + apiKey: String, + baseURL: URL, + includeSubscription: Bool, + transport: any ProviderHTTPTransport, + subscriptionGrace: Duration) async throws -> (UsagePayload, SubscriptionPayload?) + { + guard includeSubscription else { + return try await ( + self.fetchUsagePayload(apiKey: apiKey, baseURL: baseURL, transport: transport), + nil) + } + + let subscriptionTask = Task { + try await self.fetchSubscriptionPayload( + apiKey: apiKey, + baseURL: baseURL, + transport: transport) + } + let usageValues: UsagePayload + do { + usageValues = try await withTaskCancellationHandler { + try await self.fetchUsagePayload( + apiKey: apiKey, + baseURL: baseURL, + transport: transport) + } onCancel: { + subscriptionTask.cancel() + } + } catch { + subscriptionTask.cancel() + throw error + } + + do { + try Task.checkCancellation() + } catch { + subscriptionTask.cancel() + throw error + } + let race = BoundedTaskJoin(sourceTask: subscriptionTask) + switch await race.value(joinGrace: subscriptionGrace) { + case let .value(subscriptionValues): + try Task.checkCancellation() + return (usageValues, subscriptionValues) + case .timedOut: + try Task.checkCancellation() + return (usageValues, nil) + case .failure: + subscriptionTask.cancel() + try Task.checkCancellation() + return (usageValues, nil) + } + } + + // MARK: - Endpoint helpers + + struct UsagePayload { + let used: Double? + let total: Double? + let remaining: Double? + let nextQuotaReset: Date? + let autoTopupEnabled: Bool? + } + + struct SubscriptionPayload { + let status: String? + let tier: String? + let billingPeriodEnd: Date? + let weeklyUsed: Double? + let weeklyLimit: Double? + let weeklyResetsAt: Date? + let email: String? + } + + static func usageURL(baseURL: URL) -> URL { + baseURL.appendingPathComponent("/api/v1/usage") + } + + static func subscriptionURL(baseURL: URL) -> URL { + baseURL.appendingPathComponent("/api/user/subscription") + } + + static func statusError(for statusCode: Int) -> CodebuffUsageError? { + switch statusCode { + case 401, 403: .unauthorized + case 404: .endpointNotFound + case 500...599: .serviceUnavailable(statusCode) + default: nil + } + } + + static func parseUsagePayload(_ data: Data) throws -> UsagePayload { + guard let root = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else { + throw CodebuffUsageError.parseFailed("Invalid JSON") + } + + let used = self.double(from: root["usage"]) ?? self.double(from: root["used"]) + let total = self.double(from: root["quota"]) ?? self.double(from: root["limit"]) + let remaining = self.double(from: root["remainingBalance"]) ?? self.double(from: root["remaining"]) + let reset = self.date(from: root["next_quota_reset"]) + let autoTopUp = root["autoTopupEnabled"] as? Bool ?? root["auto_topup_enabled"] as? Bool + + return UsagePayload( + used: used, + total: total, + remaining: remaining, + nextQuotaReset: reset, + autoTopupEnabled: autoTopUp) + } + + static func parseSubscriptionPayload(_ data: Data) throws -> SubscriptionPayload { + guard let root = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else { + throw CodebuffUsageError.parseFailed("Invalid JSON") + } + + let subscription = root["subscription"] as? [String: Any] + let rateLimit = root["rateLimit"] as? [String: Any] + + let tier = self.string(from: subscription?["displayName"]) + ?? self.string(from: root["displayName"]) + ?? self.string(from: subscription?["tier"]) + ?? self.string(from: root["tier"]) + ?? self.string(from: subscription?["scheduledTier"]) + let status = subscription?["status"] as? String + let email = root["email"] as? String ?? (root["user"] as? [String: Any])?["email"] as? String + let billingPeriodEnd = self.date(from: subscription?["billingPeriodEnd"]) + ?? self.date(from: subscription?["currentPeriodEnd"]) + let weeklyUsed = self.double(from: rateLimit?["weeklyUsed"]) + ?? self.double(from: rateLimit?["used"]) + let weeklyLimit = self.double(from: rateLimit?["weeklyLimit"]) + ?? self.double(from: rateLimit?["limit"]) + let weeklyResetsAt = self.date(from: rateLimit?["weeklyResetsAt"]) + + return SubscriptionPayload( + status: status, + tier: tier, + billingPeriodEnd: billingPeriodEnd, + weeklyUsed: weeklyUsed, + weeklyLimit: weeklyLimit, + weeklyResetsAt: weeklyResetsAt, + email: email) + } + + // MARK: - Test hooks + + static func _parseUsagePayloadForTesting(_ data: Data) throws -> UsagePayload { + try self.parseUsagePayload(data) + } + + static func _parseSubscriptionPayloadForTesting(_ data: Data) throws -> SubscriptionPayload { + try self.parseSubscriptionPayload(data) + } + + static func _statusErrorForTesting(_ statusCode: Int) -> CodebuffUsageError? { + self.statusError(for: statusCode) + } + + // MARK: - Networking + + private static func fetchUsagePayload( + apiKey: String, + baseURL: URL, + transport: any ProviderHTTPTransport) async throws -> UsagePayload + { + var request = URLRequest(url: self.usageURL(baseURL: baseURL)) + request.httpMethod = "POST" + request.timeoutInterval = self.requestTimeoutSeconds + request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization") + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + request.setValue("application/json", forHTTPHeaderField: "Accept") + request.httpBody = try? JSONSerialization.data(withJSONObject: ["fingerprintId": "codexbar-usage"]) + + let response = try await self.send(request: request, transport: transport) + if let err = self.statusError(for: response.statusCode) { + throw err + } + guard response.statusCode == 200 else { + throw CodebuffUsageError.apiError(response.statusCode) + } + return try self.parseUsagePayload(response.data) + } + + private static func fetchSubscriptionPayload( + apiKey: String, + baseURL: URL, + transport: any ProviderHTTPTransport) async throws -> SubscriptionPayload + { + var request = URLRequest(url: self.subscriptionURL(baseURL: baseURL)) + request.httpMethod = "GET" + request.timeoutInterval = self.requestTimeoutSeconds + request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization") + request.setValue("application/json", forHTTPHeaderField: "Accept") + + let response = try await self.send(request: request, transport: transport) + if let err = self.statusError(for: response.statusCode) { + throw err + } + guard response.statusCode == 200 else { + throw CodebuffUsageError.apiError(response.statusCode) + } + return try self.parseSubscriptionPayload(response.data) + } + + private static func send( + request: URLRequest, + transport: any ProviderHTTPTransport) async throws -> ProviderHTTPResponse + { + do { + return try await transport.response(for: request) + } catch let error as CodebuffUsageError { + throw error + } catch let error as URLError where error.code == .badServerResponse { + throw CodebuffUsageError.networkError("Invalid response") + } catch { + throw CodebuffUsageError.networkError(error.localizedDescription) + } + } + + // MARK: - Value parsing + + private static func double(from value: Any?) -> Double? { + switch value { + case let number as NSNumber: + let raw = number.doubleValue + return raw.isFinite ? raw : nil + case let string as String: + let trimmed = string.trimmingCharacters(in: .whitespacesAndNewlines) + guard !trimmed.isEmpty, let raw = Double(trimmed), raw.isFinite else { return nil } + return raw + default: + return nil + } + } + + private static func string(from value: Any?) -> String? { + switch value { + case let string as String: + let trimmed = string.trimmingCharacters(in: .whitespacesAndNewlines) + return trimmed.isEmpty ? nil : trimmed + case let number as NSNumber: + let raw = number.doubleValue + guard raw.isFinite else { return nil } + return number.stringValue + default: + return nil + } + } + + private static func date(from value: Any?) -> Date? { + switch value { + case let string as String: + let trimmed = string.trimmingCharacters(in: .whitespacesAndNewlines) + guard !trimmed.isEmpty else { return nil } + let fractional = ISO8601DateFormatter() + fractional.formatOptions = [.withInternetDateTime, .withFractionalSeconds] + if let date = fractional.date(from: trimmed) { + return date + } + let plain = ISO8601DateFormatter() + plain.formatOptions = [.withInternetDateTime] + if let date = plain.date(from: trimmed) { + return date + } + if let interval = Double(trimmed), interval.isFinite { + return Self.dateFromNumeric(interval) + } + return nil + case let number as NSNumber: + let raw = number.doubleValue + return raw.isFinite ? Self.dateFromNumeric(raw) : nil + default: + return nil + } + } + + private static func dateFromNumeric(_ value: Double) -> Date? { + if value > 10_000_000_000 { + return Date(timeIntervalSince1970: value / 1000) + } + return Date(timeIntervalSince1970: value) + } +} diff --git a/Sources/CodexBarCore/Providers/Codebuff/CodebuffUsageSnapshot.swift b/Sources/CodexBarCore/Providers/Codebuff/CodebuffUsageSnapshot.swift new file mode 100644 index 0000000..478cc8e --- /dev/null +++ b/Sources/CodexBarCore/Providers/Codebuff/CodebuffUsageSnapshot.swift @@ -0,0 +1,147 @@ +import Foundation + +/// Parsed view of a Codebuff usage + subscription response pair. +public struct CodebuffUsageSnapshot: Sendable { + public let creditsUsed: Double? + public let creditsTotal: Double? + public let creditsRemaining: Double? + public let weeklyUsed: Double? + public let weeklyLimit: Double? + public let weeklyResetsAt: Date? + public let billingPeriodEnd: Date? + public let nextQuotaReset: Date? + public let tier: String? + public let subscriptionStatus: String? + public let autoTopUpEnabled: Bool? + public let accountEmail: String? + public let updatedAt: Date + + public init( + creditsUsed: Double? = nil, + creditsTotal: Double? = nil, + creditsRemaining: Double? = nil, + weeklyUsed: Double? = nil, + weeklyLimit: Double? = nil, + weeklyResetsAt: Date? = nil, + billingPeriodEnd: Date? = nil, + nextQuotaReset: Date? = nil, + tier: String? = nil, + subscriptionStatus: String? = nil, + autoTopUpEnabled: Bool? = nil, + accountEmail: String? = nil, + updatedAt: Date = Date()) + { + self.creditsUsed = creditsUsed + self.creditsTotal = creditsTotal + self.creditsRemaining = creditsRemaining + self.weeklyUsed = weeklyUsed + self.weeklyLimit = weeklyLimit + self.weeklyResetsAt = weeklyResetsAt + self.billingPeriodEnd = billingPeriodEnd + self.nextQuotaReset = nextQuotaReset + self.tier = tier + self.subscriptionStatus = subscriptionStatus + self.autoTopUpEnabled = autoTopUpEnabled + self.accountEmail = accountEmail + self.updatedAt = updatedAt + } + + public func toUsageSnapshot() -> UsageSnapshot { + let primary = self.makeCreditsWindow() + let secondary = self.makeWeeklyWindow() + + let identity = ProviderIdentitySnapshot( + providerID: .codebuff, + accountEmail: self.accountEmail, + accountOrganization: nil, + loginMethod: self.makeLoginMethod()) + + return UsageSnapshot( + primary: primary, + secondary: secondary, + tertiary: nil, + providerCost: nil, + updatedAt: self.updatedAt, + identity: identity) + } + + private func makeCreditsWindow() -> RateWindow? { + let total = self.resolvedTotal + guard let total, total > 0 else { + if self.creditsRemaining != nil || self.creditsUsed != nil { + // Degenerate case: no usable quota in the payload. Surface the row as fully + // exhausted so missing quota data is visibly surfaced (matches Kilo's behaviour + // for zero/unknown totals) rather than rendering a misleading healthy bar. + return RateWindow( + usedPercent: 100, + windowMinutes: nil, + resetsAt: self.nextQuotaReset, + resetDescription: nil) + } + return nil + } + let used = self.resolvedUsed + let percent = min(100, max(0, (used / total) * 100)) + // Note: do not stuff the credit balance ("X/Y credits") into `resetDescription` — + // generic renderers (UsageFormatter.resetLine) prepend "Resets " when `resetsAt` + // is absent, which would surface misleading text like "Resets 250/1,000 credits". + // The credits detail is shown via the dedicated Codebuff account panel instead. + return RateWindow( + usedPercent: percent, + windowMinutes: nil, + resetsAt: self.nextQuotaReset, + resetDescription: nil) + } + + private func makeWeeklyWindow() -> RateWindow? { + guard let limit = self.weeklyLimit, limit > 0 else { return nil } + let used = max(0, self.weeklyUsed ?? 0) + let percent = min(100, max(0, (used / limit) * 100)) + // Same reasoning as above: avoid encoding non-reset detail in `resetDescription`. + return RateWindow( + usedPercent: percent, + windowMinutes: 7 * 24 * 60, + resetsAt: self.weeklyResetsAt, + resetDescription: nil) + } + + private var resolvedTotal: Double? { + if let creditsTotal { return max(0, creditsTotal) } + if let creditsUsed, let creditsRemaining { + return max(0, creditsUsed + creditsRemaining) + } + return nil + } + + private var resolvedUsed: Double { + if let creditsUsed { + return max(0, creditsUsed) + } + if let total = self.resolvedTotal, let creditsRemaining { + return max(0, total - creditsRemaining) + } + return 0 + } + + private func makeLoginMethod() -> String? { + var parts: [String] = [] + if let tier = self.tier?.trimmingCharacters(in: .whitespacesAndNewlines), !tier.isEmpty { + parts.append(tier.capitalized) + } + if let remaining = self.creditsRemaining { + parts.append("\(Self.compactNumber(remaining)) remaining") + } + if self.autoTopUpEnabled == true { + parts.append("auto top-up") + } + return parts.isEmpty ? nil : parts.joined(separator: " · ") + } + + static func compactNumber(_ value: Double) -> String { + let formatter = NumberFormatter() + formatter.numberStyle = .decimal + formatter.locale = Locale(identifier: "en_US") + formatter.maximumFractionDigits = value >= 1000 ? 0 : 1 + return formatter.string(from: NSNumber(value: value)) ?? String(format: "%.0f", value) + } +} diff --git a/Sources/CodexBarCore/Providers/Codex/CodexAccountReconciliation.swift b/Sources/CodexBarCore/Providers/Codex/CodexAccountReconciliation.swift new file mode 100644 index 0000000..d157767 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Codex/CodexAccountReconciliation.swift @@ -0,0 +1,474 @@ +import Foundation + +public struct CodexResolvedActiveSource: Equatable, Sendable { + public let persistedSource: CodexActiveSource + public let resolvedSource: CodexActiveSource + + public init(persistedSource: CodexActiveSource, resolvedSource: CodexActiveSource) { + self.persistedSource = persistedSource + self.resolvedSource = resolvedSource + } + + public var requiresPersistenceCorrection: Bool { + self.persistedSource != self.resolvedSource + } +} + +public enum CodexActiveSourceResolver { + public static func resolve(from snapshot: CodexAccountReconciliationSnapshot) -> CodexResolvedActiveSource { + let persistedSource = snapshot.activeSource + let resolvedSource: CodexActiveSource = switch persistedSource { + case .liveSystem: + .liveSystem + case let .managedAccount(id): + if let activeStoredAccount = snapshot.activeStoredAccount { + self.resolvedSource(for: activeStoredAccount, snapshot: snapshot) + } else { + snapshot.liveSystemAccount != nil ? .liveSystem : .managedAccount(id: id) + } + case let .profileHome(path): + if let normalizedPath = snapshot.configuredProfileHomePath(path: path) { + self.resolvedProfileSource(path: normalizedPath, snapshot: snapshot) + } else { + .liveSystem + } + } + + return CodexResolvedActiveSource( + persistedSource: persistedSource, + resolvedSource: resolvedSource) + } + + private static func resolvedProfileSource( + path: String, + snapshot: CodexAccountReconciliationSnapshot) -> CodexActiveSource + { + if let livePath = snapshot.liveSystemAccount.flatMap({ + CodexHomeScope.normalizedHomePath($0.codexHomePath) + }), livePath == path { + return .liveSystem + } + + if let storedAccount = snapshot.storedAccounts.first(where: { + CodexHomeScope.normalizedHomePath($0.managedHomePath) == path + }) { + return self.resolvedSource(for: storedAccount, snapshot: snapshot) + } + + return .profileHome(path: path) + } + + private static func resolvedSource( + for storedAccount: ManagedCodexAccount, + snapshot: CodexAccountReconciliationSnapshot) -> CodexActiveSource + { + self.matchesLiveSystemAccount( + storedAccount: storedAccount, + snapshot: snapshot, + liveSystemAccount: snapshot.liveSystemAccount) ? .liveSystem : .managedAccount(id: storedAccount.id) + } + + private static func matchesLiveSystemAccount( + storedAccount: ManagedCodexAccount, + snapshot: CodexAccountReconciliationSnapshot, + liveSystemAccount: ObservedSystemCodexAccount?) -> Bool + { + guard let liveSystemAccount else { return false } + if let storedFingerprint = storedAccount.authFingerprint, + let liveFingerprint = liveSystemAccount.authFingerprint, + storedFingerprint == liveFingerprint + { + return true + } + return CodexIdentityMatcher.matches( + snapshot.runtimeIdentity(for: storedAccount), + lhsEmail: snapshot.runtimeEmail(for: storedAccount), + snapshot.runtimeIdentity(for: liveSystemAccount), + rhsEmail: liveSystemAccount.email) + } +} + +public struct CodexAccountReconciliationSnapshot: Equatable, Sendable { + public let storedAccounts: [ManagedCodexAccount] + public let activeStoredAccount: ManagedCodexAccount? + public let liveSystemAccount: ObservedSystemCodexAccount? + public let profileHomeAccounts: [ObservedSystemCodexAccount] + public let profileHomePaths: [String] + public let matchingStoredAccountForLiveSystemAccount: ManagedCodexAccount? + public let activeSource: CodexActiveSource + public let hasUnreadableAddedAccountStore: Bool + public let storedAccountRuntimeIdentities: [UUID: CodexIdentity] + public let storedAccountRuntimeEmails: [UUID: String] + + public init( + storedAccounts: [ManagedCodexAccount], + activeStoredAccount: ManagedCodexAccount?, + liveSystemAccount: ObservedSystemCodexAccount?, + profileHomeAccounts: [ObservedSystemCodexAccount] = [], + profileHomePaths: [String]? = nil, + matchingStoredAccountForLiveSystemAccount: ManagedCodexAccount?, + activeSource: CodexActiveSource, + hasUnreadableAddedAccountStore: Bool, + storedAccountRuntimeIdentities: [UUID: CodexIdentity] = [:], + storedAccountRuntimeEmails: [UUID: String] = [:]) + { + self.storedAccounts = storedAccounts + self.activeStoredAccount = activeStoredAccount + self.liveSystemAccount = liveSystemAccount + self.profileHomeAccounts = Self.uniqueProfileHomeAccounts(profileHomeAccounts) + self.profileHomePaths = Self.uniqueNormalizedPaths( + profileHomePaths ?? profileHomeAccounts.map(\.codexHomePath)) + self.matchingStoredAccountForLiveSystemAccount = matchingStoredAccountForLiveSystemAccount + self.activeSource = activeSource + self.hasUnreadableAddedAccountStore = hasUnreadableAddedAccountStore + self.storedAccountRuntimeIdentities = storedAccountRuntimeIdentities + self.storedAccountRuntimeEmails = storedAccountRuntimeEmails + } + + public static func == (lhs: CodexAccountReconciliationSnapshot, rhs: CodexAccountReconciliationSnapshot) -> Bool { + lhs.storedAccounts.map(AccountIdentity.init) == rhs.storedAccounts.map(AccountIdentity.init) + && lhs.activeStoredAccount.map(AccountIdentity.init) == rhs.activeStoredAccount.map(AccountIdentity.init) + && lhs.liveSystemAccount == rhs.liveSystemAccount + && lhs.profileHomeAccounts == rhs.profileHomeAccounts + && lhs.profileHomePaths == rhs.profileHomePaths + && lhs.matchingStoredAccountForLiveSystemAccount.map(AccountIdentity.init) + == rhs.matchingStoredAccountForLiveSystemAccount.map(AccountIdentity.init) + && lhs.activeSource == rhs.activeSource + && lhs.hasUnreadableAddedAccountStore == rhs.hasUnreadableAddedAccountStore + && lhs.storedAccountRuntimeIdentities == rhs.storedAccountRuntimeIdentities + && lhs.storedAccountRuntimeEmails == rhs.storedAccountRuntimeEmails + } + + public func runtimeIdentity(for storedAccount: ManagedCodexAccount) -> CodexIdentity { + self.storedAccountRuntimeIdentities[storedAccount.id] + ?? CodexIdentityResolver.resolve(accountId: nil, email: storedAccount.email) + } + + public func runtimeEmail(for storedAccount: ManagedCodexAccount) -> String { + self.storedAccountRuntimeEmails[storedAccount.id] + ?? Self.normalizeEmail(storedAccount.email) + } + + public func runtimeIdentity(for liveSystemAccount: ObservedSystemCodexAccount) -> CodexIdentity { + CodexIdentityMatcher.normalized( + liveSystemAccount.identity, + fallbackEmail: liveSystemAccount.email) + } + + public func profileHomeAccount(path: String) -> ObservedSystemCodexAccount? { + guard let normalizedPath = CodexHomeScope.normalizedHomePath(path) else { return nil } + return self.profileHomeAccounts.first { + CodexHomeScope.normalizedHomePath($0.codexHomePath) == normalizedPath + } + } + + public func configuredProfileHomePath(path: String) -> String? { + guard let normalizedPath = CodexHomeScope.normalizedHomePath(path), + self.profileHomePaths.contains(normalizedPath) + else { + return nil + } + return normalizedPath + } + + private static func normalizeEmail(_ email: String) -> String { + email.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() + } + + private static func uniqueProfileHomeAccounts( + _ accounts: [ObservedSystemCodexAccount]) -> [ObservedSystemCodexAccount] + { + var seenPaths: Set = [] + var result: [ObservedSystemCodexAccount] = [] + for account in accounts { + let path = CodexHomeScope.normalizedHomePath(account.codexHomePath) ?? account.codexHomePath + guard seenPaths.insert(path).inserted else { continue } + result.append(account) + } + return result + } + + private static func uniqueNormalizedPaths(_ paths: [String]) -> [String] { + var seen: Set = [] + return paths.compactMap { path in + guard let normalizedPath = CodexHomeScope.normalizedHomePath(path), + seen.insert(normalizedPath).inserted + else { + return nil + } + return normalizedPath + } + } +} + +public struct DefaultCodexAccountReconciler: Sendable { + public let storeLoader: @Sendable () throws -> ManagedCodexAccountSet + public let systemObserver: any CodexSystemAccountObserving + public let activeSource: CodexActiveSource + public let baseEnvironment: [String: String] + public let profileHomePaths: [String] + public let managedEnvironmentBuilder: @Sendable ([String: String], ManagedCodexAccount) -> [String: String] + + public init( + storeLoader: @escaping @Sendable () throws -> ManagedCodexAccountSet = { + try FileManagedCodexAccountStore().loadAccounts() + }, + systemObserver: any CodexSystemAccountObserving = DefaultCodexSystemAccountObserver(), + activeSource: CodexActiveSource = .liveSystem, + baseEnvironment: [String: String], + profileHomePaths: [String] = [], + managedEnvironmentBuilder: @escaping @Sendable ([String: String], ManagedCodexAccount) + -> [String: String] = { baseEnvironment, account in + CodexHomeScope.scopedEnvironment(base: baseEnvironment, codexHome: account.managedHomePath) + }) + { + self.storeLoader = storeLoader + self.systemObserver = systemObserver + self.activeSource = activeSource + self.baseEnvironment = baseEnvironment + self.profileHomePaths = Self.uniqueNormalizedPaths(profileHomePaths) + self.managedEnvironmentBuilder = managedEnvironmentBuilder + } + + public func loadSnapshot() -> CodexAccountReconciliationSnapshot { + let liveSystemAccount = self.loadLiveSystemAccount() + let profileHomeAccounts = self.loadProfileHomeAccounts(liveSystemAccount: liveSystemAccount) + + do { + let accounts = try self.storeLoader() + let runtimeAccounts = Dictionary(uniqueKeysWithValues: accounts.accounts.map { account in + let runtimeAccount = self.loadRuntimeAccount(for: account) + return (account.id, runtimeAccount) + }) + let activeStoredAccount: ManagedCodexAccount? = switch self.activeSource { + case let .managedAccount(id): + accounts.account(id: id) + case .liveSystem, .profileHome: + nil + } + let matchingStoredAccountForLiveSystemAccount = liveSystemAccount.flatMap { liveAccount in + if let liveFingerprint = liveAccount.authFingerprint, + let exactFingerprintMatch = accounts.accounts.first(where: { + $0.authFingerprint == liveFingerprint + }) + { + return exactFingerprintMatch + } + return accounts.accounts.first { account in + guard let runtimeAccount = runtimeAccounts[account.id] else { return false } + return CodexIdentityMatcher.matches( + runtimeAccount.identity, + lhsEmail: runtimeAccount.email, + self.runtimeIdentity(for: liveAccount), + rhsEmail: liveAccount.email) + } + } + + return CodexAccountReconciliationSnapshot( + storedAccounts: accounts.accounts, + activeStoredAccount: activeStoredAccount, + liveSystemAccount: liveSystemAccount, + profileHomeAccounts: self.profileHomeAccounts( + profileHomeAccounts, + excludingManagedAccounts: accounts.accounts), + profileHomePaths: self.profileHomePaths, + matchingStoredAccountForLiveSystemAccount: matchingStoredAccountForLiveSystemAccount, + activeSource: self.activeSource, + hasUnreadableAddedAccountStore: false, + storedAccountRuntimeIdentities: runtimeAccounts.mapValues(\.identity), + storedAccountRuntimeEmails: runtimeAccounts.mapValues(\.email)) + } catch { + return CodexAccountReconciliationSnapshot( + storedAccounts: [], + activeStoredAccount: nil, + liveSystemAccount: liveSystemAccount, + profileHomeAccounts: profileHomeAccounts, + profileHomePaths: self.profileHomePaths, + matchingStoredAccountForLiveSystemAccount: nil, + activeSource: self.activeSource, + hasUnreadableAddedAccountStore: true) + } + } + + private func loadProfileHomeAccounts( + liveSystemAccount: ObservedSystemCodexAccount?) -> [ObservedSystemCodexAccount] + { + let livePath = liveSystemAccount.flatMap { CodexHomeScope.normalizedHomePath($0.codexHomePath) } + return self.profileHomePaths.compactMap { path in + guard path != livePath else { return nil } + return self.loadProfileHomeAccount(homePath: path) + } + } + + private func loadProfileHomeAccount(homePath: String) -> ObservedSystemCodexAccount? { + let environment = CodexHomeScope.scopedEnvironment(base: self.baseEnvironment, codexHome: homePath) + let account = UsageFetcher(environment: environment).loadAuthBackedCodexAccount() + + guard let rawEmail = account.email?.trimmingCharacters(in: .whitespacesAndNewlines), + !rawEmail.isEmpty + else { + return nil + } + + let providerAccountID: String? = switch account.identity { + case let .providerAccount(id): + ManagedCodexAccount.normalizeProviderAccountID(id) + case .emailOnly, .unresolved: + nil + } + + return ObservedSystemCodexAccount( + email: rawEmail.lowercased(), + workspaceAccountID: providerAccountID, + authFingerprint: CodexAuthFingerprint.fingerprint(homePath: homePath), + codexHomePath: homePath, + observedAt: Date(), + identity: account.identity) + } + + private func loadLiveSystemAccount() -> ObservedSystemCodexAccount? { + do { + guard let account = try self.systemObserver.loadSystemAccount(environment: self.baseEnvironment) else { + return nil + } + let normalizedEmail = Self.normalizeEmail(account.email) + guard !normalizedEmail.isEmpty else { + return nil + } + return ObservedSystemCodexAccount( + email: normalizedEmail, + workspaceLabel: account.workspaceLabel, + workspaceAccountID: account.workspaceAccountID, + authFingerprint: account.authFingerprint, + codexHomePath: account.codexHomePath, + observedAt: account.observedAt, + identity: self.runtimeIdentity(for: account)) + } catch { + return nil + } + } + + private static func normalizeEmail(_ email: String) -> String { + email.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() + } + + private func loadRuntimeAccount(for account: ManagedCodexAccount) -> RuntimeManagedCodexAccount { + let scopedEnvironment = self.managedEnvironmentBuilder(self.baseEnvironment, account) + let authBackedAccount = UsageFetcher(environment: scopedEnvironment).loadAuthBackedCodexAccount() + let email = Self.normalizeEmail(authBackedAccount.email ?? account.email) + let identity = CodexIdentityMatcher.normalized(authBackedAccount.identity, fallbackEmail: email) + + return RuntimeManagedCodexAccount( + email: email, + identity: identity) + } + + private func profileHomeAccounts( + _ profileHomeAccounts: [ObservedSystemCodexAccount], + excludingManagedAccounts managedAccounts: [ManagedCodexAccount]) -> [ObservedSystemCodexAccount] + { + let managedPaths = Set(managedAccounts.compactMap { CodexHomeScope.normalizedHomePath($0.managedHomePath) }) + return profileHomeAccounts.filter { account in + guard let path = CodexHomeScope.normalizedHomePath(account.codexHomePath) else { return false } + return !managedPaths.contains(path) + } + } + + private func runtimeIdentity(for liveSystemAccount: ObservedSystemCodexAccount) -> CodexIdentity { + CodexIdentityMatcher.normalized( + liveSystemAccount.identity, + fallbackEmail: liveSystemAccount.email) + } + + private static func uniqueNormalizedPaths(_ paths: [String]) -> [String] { + var seen: Set = [] + var result: [String] = [] + for path in paths.compactMap({ CodexHomeScope.normalizedHomePath($0) }) { + guard seen.insert(path).inserted else { continue } + result.append(path) + } + return result + } +} + +public enum CodexIdentityMatcher { + public static func matches(_ lhs: CodexIdentity, _ rhs: CodexIdentity) -> Bool { + switch (lhs, rhs) { + case let (.providerAccount(leftID), .providerAccount(rightID)): + leftID == rightID + case let (.emailOnly(leftEmail), .emailOnly(rightEmail)): + leftEmail == rightEmail + default: + false + } + } + + public static func matches( + _ lhs: CodexIdentity, + lhsEmail: String?, + _ rhs: CodexIdentity, + rhsEmail: String?) -> Bool + { + guard self.matches(lhs, rhs) else { return false } + guard case .providerAccount = lhs, case .providerAccount = rhs else { return true } + guard let normalizedLeftEmail = CodexIdentityResolver.normalizeEmail(lhsEmail), + let normalizedRightEmail = CodexIdentityResolver.normalizeEmail(rhsEmail) + else { + return true + } + return normalizedLeftEmail == normalizedRightEmail + } + + public static func normalized(_ identity: CodexIdentity, fallbackEmail: String) -> CodexIdentity { + switch identity { + case .providerAccount: + identity + case let .emailOnly(normalizedEmail): + CodexIdentityResolver.resolve(accountId: nil, email: normalizedEmail) + case .unresolved: + CodexIdentityResolver.resolve(accountId: nil, email: fallbackEmail) + } + } + + public static func selectionKey(for identity: CodexIdentity, fallbackEmail: String) -> String { + switch self.normalized(identity, fallbackEmail: fallbackEmail) { + case let .providerAccount(id): + "provider:\(id)" + case let .emailOnly(normalizedEmail): + "email:\(normalizedEmail)" + case .unresolved: + "unresolved:\(fallbackEmail)" + } + } +} + +private struct RuntimeManagedCodexAccount { + let email: String + let identity: CodexIdentity +} + +private struct AccountIdentity: Equatable { + let id: UUID + let email: String + let providerAccountID: String? + let workspaceLabel: String? + let workspaceAccountID: String? + let managedHomePath: String + let createdAt: TimeInterval + let updatedAt: TimeInterval + let lastAuthenticatedAt: TimeInterval? + let authFingerprint: String? + + init(_ account: ManagedCodexAccount) { + self.id = account.id + self.email = account.email + self.providerAccountID = account.providerAccountID + self.workspaceLabel = account.workspaceLabel + self.workspaceAccountID = account.workspaceAccountID + self.managedHomePath = account.managedHomePath + self.createdAt = account.createdAt + self.updatedAt = account.updatedAt + self.lastAuthenticatedAt = account.lastAuthenticatedAt + self.authFingerprint = account.authFingerprint + } +} diff --git a/Sources/CodexBarCore/Providers/Codex/CodexAdditionalRateLimitMapper.swift b/Sources/CodexBarCore/Providers/Codex/CodexAdditionalRateLimitMapper.swift new file mode 100644 index 0000000..c37f28c --- /dev/null +++ b/Sources/CodexBarCore/Providers/Codex/CodexAdditionalRateLimitMapper.swift @@ -0,0 +1,153 @@ +import Foundation + +/// Maps Codex `additional_rate_limits` entries (model-specific limits such as GPT-5.3-Codex-Spark) +/// into named extra rate windows. +/// +/// These limits are reported by the `wham/usage` API alongside, but separately from, the primary and +/// weekly Codex windows, so we surface them through `UsageSnapshot.extraRateWindows` rather than the core +/// primary/secondary lanes. When the field is absent the mapper returns an empty list and the snapshot is +/// unchanged. +package enum CodexAdditionalRateLimitMapper { + /// Stable ids/titles for GPT-5.3-Codex-Spark limits so SwiftUI identity stays constant even if the API + /// label wording shifts. Keep the original 5-hour id for compatibility with the first Spark implementation. + package static let sparkWindowID = "codex-spark" + package static let sparkWeeklyWindowID = "codex-spark-weekly" + static let sparkWindowTitle = "Codex Spark 5-hour" + static let sparkWeeklyWindowTitle = "Codex Spark Weekly" + + static func extraRateWindows( + from additionalRateLimits: [CodexUsageResponse.AdditionalRateLimit]?, + now: Date = Date()) -> [NamedRateWindow] + { + guard let additionalRateLimits, !additionalRateLimits.isEmpty else { return [] } + var usedIDs = Set() + return additionalRateLimits.flatMap { entry in + self.namedWindows(from: entry, usedIDs: &usedIDs, now: now) + } + } + + private static func namedWindows( + from entry: CodexUsageResponse.AdditionalRateLimit, + usedIDs: inout Set, + now: Date) -> [NamedRateWindow] + { + if self.isSpark(entry) { + return self.sparkWindows(from: entry, usedIDs: &usedIDs, now: now) + } + + // Model-specific limits report utilization in the primary window; fall back to the secondary + // window only when a primary one is not present. + guard let snapshot = entry.rateLimit?.primaryWindow ?? entry.rateLimit?.secondaryWindow else { + return [] + } + guard let id = self.windowID(for: entry), usedIDs.insert(id).inserted else { return [] } + return [self.namedWindow( + id: id, + title: self.windowTitle(for: entry), + snapshot: snapshot, + now: now)] + } + + private static func sparkWindows( + from entry: CodexUsageResponse.AdditionalRateLimit, + usedIDs: inout Set, + now: Date) -> [NamedRateWindow] + { + let candidates: [(CodexUsageResponse.WindowSnapshot?, SparkWindowKind)] = [ + (entry.rateLimit?.primaryWindow, .fiveHour), + (entry.rateLimit?.secondaryWindow, .weekly), + ] + + return candidates.compactMap { snapshot, fallbackKind in + guard let snapshot else { return nil } + let kind = self.sparkWindowKind(for: snapshot, fallback: fallbackKind) + guard usedIDs.insert(kind.id).inserted else { return nil } + return self.namedWindow(id: kind.id, title: kind.title, snapshot: snapshot, now: now) + } + } + + private static func namedWindow( + id: String, + title: String, + snapshot: CodexUsageResponse.WindowSnapshot, + now: Date) -> NamedRateWindow + { + let resetDate: Date? = snapshot.resetAt > 0 + ? Date(timeIntervalSince1970: TimeInterval(snapshot.resetAt)) + : nil + let window = RateWindow( + usedPercent: Double(snapshot.usedPercent), + windowMinutes: snapshot.limitWindowSeconds > 0 ? snapshot.limitWindowSeconds / 60 : nil, + resetsAt: resetDate, + resetDescription: resetDate.map { UsageFormatter.resetDescription(from: $0, now: now) }) + return NamedRateWindow(id: id, title: title, window: window) + } + + private enum SparkWindowKind { + case fiveHour + case weekly + + var id: String { + switch self { + case .fiveHour: CodexAdditionalRateLimitMapper.sparkWindowID + case .weekly: CodexAdditionalRateLimitMapper.sparkWeeklyWindowID + } + } + + var title: String { + switch self { + case .fiveHour: CodexAdditionalRateLimitMapper.sparkWindowTitle + case .weekly: CodexAdditionalRateLimitMapper.sparkWeeklyWindowTitle + } + } + } + + private static func sparkWindowKind( + for snapshot: CodexUsageResponse.WindowSnapshot, + fallback: SparkWindowKind) -> SparkWindowKind + { + let minutes = snapshot.limitWindowSeconds > 0 ? snapshot.limitWindowSeconds / 60 : 0 + if minutes > 0, minutes <= 6 * 60 { return .fiveHour } + if minutes >= 6 * 24 * 60 { return .weekly } + return fallback + } + + private static func windowID(for entry: CodexUsageResponse.AdditionalRateLimit) -> String? { + guard let source = self.firstNonEmpty(entry.meteredFeature, entry.limitName) else { return nil } + let slug = self.slug(source) + return slug.isEmpty ? nil : "codex-\(slug)" + } + + private static func windowTitle(for entry: CodexUsageResponse.AdditionalRateLimit) -> String { + self.firstNonEmpty(entry.limitName, entry.meteredFeature) ?? "Codex extra limit" + } + + private static func isSpark(_ entry: CodexUsageResponse.AdditionalRateLimit) -> Bool { + [entry.limitName, entry.meteredFeature] + .compactMap { $0?.lowercased() } + .contains { $0.contains("spark") } + } + + private static func firstNonEmpty(_ values: String?...) -> String? { + for value in values { + let trimmed = value?.trimmingCharacters(in: .whitespacesAndNewlines) + if let trimmed, !trimmed.isEmpty { return trimmed } + } + return nil + } + + private static func slug(_ value: String) -> String { + var result = "" + var lastWasDash = false + for scalar in value.lowercased().unicodeScalars { + if CharacterSet.alphanumerics.contains(scalar) { + result.unicodeScalars.append(scalar) + lastWasDash = false + } else if !lastWasDash { + result.append("-") + lastWasDash = true + } + } + return result.trimmingCharacters(in: CharacterSet(charactersIn: "-")) + } +} diff --git a/Sources/CodexBarCore/Providers/Codex/CodexAuthenticatedHTTPTransport.swift b/Sources/CodexBarCore/Providers/Codex/CodexAuthenticatedHTTPTransport.swift new file mode 100644 index 0000000..12c17a2 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Codex/CodexAuthenticatedHTTPTransport.swift @@ -0,0 +1,33 @@ +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +enum CodexAuthenticatedHTTPTransport { + static let shared = Self.makeClient() + + @TaskLocal static var overrideForTesting: (any ProviderHTTPTransport)? + + static var current: any ProviderHTTPTransport { + if let override = self.overrideForTesting { + return override + } + return self.shared + } + + static func makeConfiguration() -> URLSessionConfiguration { + let configuration = URLSessionConfiguration.ephemeral + configuration.urlCache = nil + configuration.requestCachePolicy = .reloadIgnoringLocalCacheData + configuration.httpCookieStorage = nil + configuration.httpShouldSetCookies = false + configuration.urlCredentialStorage = nil + return configuration + } + + static func makeClient(configuration: URLSessionConfiguration? = nil) -> ProviderHTTPClient { + let configuration = configuration ?? self.makeConfiguration() + let session = ProviderHTTPClient.redirectGuardedSession(configuration: configuration) + return ProviderHTTPClient(session: session) + } +} diff --git a/Sources/CodexBarCore/Providers/Codex/CodexCLIDashboardAuthorityContext.swift b/Sources/CodexBarCore/Providers/Codex/CodexCLIDashboardAuthorityContext.swift new file mode 100644 index 0000000..ce34806 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Codex/CodexCLIDashboardAuthorityContext.swift @@ -0,0 +1,62 @@ +import Foundation + +public enum CodexCLIDashboardAuthorityContext { + public static func makeLiveWebInput( + dashboard: OpenAIDashboardSnapshot, + context: ProviderFetchContext, + routingTargetEmail: String?) -> CodexDashboardAuthorityInput + { + let auth = context.fetcher.loadAuthBackedCodexAccount() + return CodexDashboardAuthorityInput( + sourceKind: .liveWeb, + proof: CodexDashboardOwnershipProofContext( + currentIdentity: auth.identity, + expectedScopedEmail: auth.email, + trustedCurrentUsageEmail: nil, + dashboardSignedInEmail: dashboard.signedInEmail, + knownOwners: context.settings?.codex?.dashboardAuthorityKnownOwners ?? []), + routing: CodexDashboardRoutingHints( + targetEmail: CodexIdentityResolver.normalizeEmail(routingTargetEmail), + lastKnownDashboardRoutingEmail: nil)) + } + + public static func makeCachedDashboardInput( + dashboard: OpenAIDashboardSnapshot, + cachedAccountEmail: String, + usage: UsageSnapshot, + sourceLabel: String, + context: ProviderFetchContext) -> CodexDashboardAuthorityInput + { + let auth = context.fetcher.loadAuthBackedCodexAccount() + let trustedCurrentUsageEmail = Self.shouldTrustUsageEmail(sourceLabel: sourceLabel) + ? usage.accountEmail(for: .codex) + : nil + return CodexDashboardAuthorityInput( + sourceKind: .cachedDashboard, + proof: CodexDashboardOwnershipProofContext( + currentIdentity: auth.identity, + expectedScopedEmail: auth.email, + trustedCurrentUsageEmail: trustedCurrentUsageEmail, + dashboardSignedInEmail: dashboard.signedInEmail, + knownOwners: context.settings?.codex?.dashboardAuthorityKnownOwners ?? []), + routing: CodexDashboardRoutingHints( + targetEmail: auth.email, + lastKnownDashboardRoutingEmail: cachedAccountEmail)) + } + + public static func attachmentEmail(from input: CodexDashboardAuthorityInput) -> String? { + CodexIdentityResolver.normalizeEmail( + input.proof.expectedScopedEmail ?? + input.proof.trustedCurrentUsageEmail ?? + input.proof.dashboardSignedInEmail) + } + + public static func shouldTrustUsageEmail(sourceLabel: String) -> Bool { + switch sourceLabel.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() { + case "codex-cli", "oauth": + true + default: + false + } + } +} diff --git a/Sources/CodexBarCore/Providers/Codex/CodexCLILaunchGate.swift b/Sources/CodexBarCore/Providers/Codex/CodexCLILaunchGate.swift new file mode 100644 index 0000000..78ffa8a --- /dev/null +++ b/Sources/CodexBarCore/Providers/Codex/CodexCLILaunchGate.swift @@ -0,0 +1,70 @@ +import Foundation + +final class CodexCLILaunchGate: @unchecked Sendable { + static let shared = CodexCLILaunchGate() + static let cooldown: TimeInterval = 30 * 60 + + private struct Entry { + let message: String + let expiresAt: Date + } + + private let lock = NSLock() + private var entries: [String: Entry] = [:] + + func backgroundSkipMessage( + binary: String, + now: Date = Date(), + interaction: ProviderInteraction = ProviderInteractionContext.current) -> String? + { + guard interaction == .background else { return nil } + + self.lock.lock() + defer { self.lock.unlock() } + + guard let entry = self.entries[binary] else { return nil } + guard entry.expiresAt > now else { + self.entries.removeValue(forKey: binary) + return nil + } + return entry.message + } + + @discardableResult + func recordLaunchFailure(binary: String, message: String, now: Date = Date()) -> String? { + guard Self.shouldThrottleLaunchFailure(message) else { return nil } + let throttled = Self.throttledMessage(binary: binary, originalMessage: message) + let entry = Entry( + message: throttled, + expiresAt: now.addingTimeInterval(Self.cooldown)) + + self.lock.lock() + self.entries[binary] = entry + self.lock.unlock() + + return throttled + } + + func resetForTesting() { + self.lock.lock() + self.entries.removeAll() + self.lock.unlock() + } + + static func shouldThrottleLaunchFailure(_ message: String) -> Bool { + let lower = message.lowercased() + if lower.contains("openpty") || + lower.contains("write to pty") || + lower.contains("app shutdown") + { + return false + } + return true + } + + private static func throttledMessage(binary: String, originalMessage: String) -> String { + "Codex CLI launch failed; background refresh is paused for 30 minutes. " + + "Reinstall or unblock `\(binary)` in macOS security settings, then refresh manually. " + + "Last error: \(originalMessage)" + } +} diff --git a/Sources/CodexBarCore/Providers/Codex/CodexCLISession.swift b/Sources/CodexBarCore/Providers/Codex/CodexCLISession.swift new file mode 100644 index 0000000..2c88db3 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Codex/CodexCLISession.swift @@ -0,0 +1,427 @@ +#if canImport(Darwin) +import Darwin +#elseif canImport(Glibc) +import Glibc +#elseif canImport(Musl) +import Musl +#endif +import Foundation + +actor CodexCLISession { + static let shared = CodexCLISession() + + enum SessionError: LocalizedError { + case launchFailed(String) + case timedOut + case processExited + + var errorDescription: String? { + switch self { + case let .launchFailed(msg): "Failed to launch Codex CLI session: \(msg)" + case .timedOut: "Codex CLI session timed out." + case .processExited: "Codex CLI session exited." + } + } + } + + private var process: Process? + private var primaryFD: Int32 = -1 + private var primaryHandle: FileHandle? + private var secondaryHandle: FileHandle? + private var processGroup: pid_t? + private var binaryPath: String? + private var startedAt: Date? + private var ptyRows: UInt16 = 0 + private var ptyCols: UInt16 = 0 + private var sessionEnvironment: [String: String]? + private var sessionArguments: [String] = [] + private var sessionWorkingDirectory: URL? + + struct CaptureOptions { + let timeout: TimeInterval + let rows: UInt16 + let cols: UInt16 + let environment: [String: String] + let extraArgs: [String] + let workingDirectory: URL? + } + + private struct RollingBuffer { + private let maxNeedle: Int + private var tail = Data() + + init(maxNeedle: Int) { + self.maxNeedle = max(0, maxNeedle) + } + + mutating func append(_ data: Data) -> Data { + guard !data.isEmpty else { return Data() } + var combined = Data() + combined.reserveCapacity(self.tail.count + data.count) + combined.append(self.tail) + combined.append(data) + if self.maxNeedle > 1 { + if combined.count >= self.maxNeedle - 1 { + self.tail = combined.suffix(self.maxNeedle - 1) + } else { + self.tail = combined + } + } else { + self.tail.removeAll(keepingCapacity: true) + } + return combined + } + + mutating func reset() { + self.tail.removeAll(keepingCapacity: true) + } + } + + static func lowercasedASCII(_ data: Data) -> Data { + guard !data.isEmpty else { return data } + var out = Data(count: data.count) + out.withUnsafeMutableBytes { dest in + data.withUnsafeBytes { source in + let src = source.bindMemory(to: UInt8.self) + let dst = dest.bindMemory(to: UInt8.self) + for idx in 0..= 65, byte <= 90 { byte += 32 } + dst[idx] = byte + } + } + } + return out + } + + // swiftlint:disable cyclomatic_complexity + func captureStatus( + binary: String, + options: CaptureOptions) async throws -> String + { + try self.ensureStarted(binary: binary, options: options) + if let startedAt { + let sinceStart = Date().timeIntervalSince(startedAt) + if sinceStart < 0.4 { + let delay = UInt64((0.4 - sinceStart) * 1_000_000_000) + try await Task.sleep(nanoseconds: delay) + } + } + self.drainOutput() + + let script = "/status" + let cursorQuery = Data([0x1B, 0x5B, 0x36, 0x6E]) + let statusMarkers = [ + "Credits:", + "5h limit", + "5-hour limit", + "Weekly limit", + ].map { Data($0.utf8) } + let updateNeedles = ["Update available!", "Run bun install -g @openai/codex", "0.60.1 ->"] + let updateNeedlesLower = updateNeedles.map { Data($0.lowercased().utf8) } + let statusNeedleLengths = statusMarkers.map(\.count) + let updateNeedleLengths = updateNeedlesLower.map(\.count) + let statusMaxNeedle = ([cursorQuery.count] + statusNeedleLengths).max() ?? cursorQuery.count + let updateMaxNeedle = updateNeedleLengths.max() ?? 0 + var statusScanBuffer = RollingBuffer(maxNeedle: statusMaxNeedle) + var updateScanBuffer = RollingBuffer(maxNeedle: updateMaxNeedle) + + var buffer = Data() + let deadline = Date().addingTimeInterval(options.timeout) + var nextCursorCheckAt = Date(timeIntervalSince1970: 0) + + var skippedCodexUpdate = false + var sentScript = false + var updateSkipAttempts = 0 + var lastEnter = Date(timeIntervalSince1970: 0) + var scriptSentAt: Date? + var resendStatusRetries = 0 + var enterRetries = 0 + var sawCodexStatus = false + var sawCodexUpdatePrompt = false + + while Date() < deadline { + let newData = self.readChunk() + if !newData.isEmpty { + buffer.append(newData) + } + let scanData = statusScanBuffer.append(newData) + if Date() >= nextCursorCheckAt, + !scanData.isEmpty, + scanData.range(of: cursorQuery) != nil + { + try? self.send("\u{1b}[1;1R") + nextCursorCheckAt = Date().addingTimeInterval(1.0) + } + if !scanData.isEmpty, !sawCodexStatus { + if statusMarkers.contains(where: { scanData.range(of: $0) != nil }) { + sawCodexStatus = true + } + } + + if !skippedCodexUpdate, !sawCodexUpdatePrompt, !newData.isEmpty { + let lowerData = Self.lowercasedASCII(newData) + let lowerScan = updateScanBuffer.append(lowerData) + if updateNeedlesLower.contains(where: { lowerScan.range(of: $0) != nil }) { + sawCodexUpdatePrompt = true + } + } + + if !skippedCodexUpdate, sawCodexUpdatePrompt { + try? self.send("\u{1b}[B") + try await Task.sleep(nanoseconds: 120_000_000) + try? self.send("\r") + try await Task.sleep(nanoseconds: 150_000_000) + try? self.send("\r") + try? self.send(script) + try? self.send("\r") + updateSkipAttempts += 1 + if updateSkipAttempts >= 1 { + skippedCodexUpdate = true + sentScript = false + scriptSentAt = nil + buffer.removeAll() + statusScanBuffer.reset() + updateScanBuffer.reset() + sawCodexStatus = false + } + try await Task.sleep(nanoseconds: 300_000_000) + } + + if !sentScript, !sawCodexUpdatePrompt || skippedCodexUpdate { + try? self.send(script) + try? self.send("\r") + sentScript = true + scriptSentAt = Date() + lastEnter = Date() + try await Task.sleep(nanoseconds: 200_000_000) + continue + } + if sentScript, !sawCodexStatus { + if Date().timeIntervalSince(lastEnter) >= 1.2, enterRetries < 6 { + try? self.send("\r") + enterRetries += 1 + lastEnter = Date() + try await Task.sleep(nanoseconds: 120_000_000) + continue + } + if let sentAt = scriptSentAt, + Date().timeIntervalSince(sentAt) >= 3.0, + resendStatusRetries < 2 + { + try? self.send(script) + try? self.send("\r") + resendStatusRetries += 1 + buffer.removeAll() + statusScanBuffer.reset() + updateScanBuffer.reset() + sawCodexStatus = false + scriptSentAt = Date() + lastEnter = Date() + try await Task.sleep(nanoseconds: 220_000_000) + continue + } + } + if sawCodexStatus { break } + if let proc = self.process, !proc.isRunning { + throw SessionError.processExited + } + try await Task.sleep(nanoseconds: 120_000_000) + } + + if sawCodexStatus { + let settleDeadline = Date().addingTimeInterval(2.0) + while Date() < settleDeadline { + let newData = self.readChunk() + if !newData.isEmpty { + buffer.append(newData) + } + let scanData = statusScanBuffer.append(newData) + if Date() >= nextCursorCheckAt, + !scanData.isEmpty, + scanData.range(of: cursorQuery) != nil + { + try? self.send("\u{1b}[1;1R") + nextCursorCheckAt = Date().addingTimeInterval(1.0) + } + try await Task.sleep(nanoseconds: 100_000_000) + } + } + + guard !buffer.isEmpty, let text = String(data: buffer, encoding: .utf8) else { + throw SessionError.timedOut + } + return text + } + + // swiftlint:enable cyclomatic_complexity + + func reset() { + self.cleanup() + } + + private func ensureStarted( + binary: String, + options: CaptureOptions) throws + { + if let proc = self.process, + proc.isRunning, + self.binaryPath == binary, + self.ptyRows == options.rows, + self.ptyCols == options.cols, + self.sessionEnvironment == options.environment, + self.sessionArguments == options.extraArgs, + self.sessionWorkingDirectory == options.workingDirectory + { + return + } + self.cleanup() + + var primaryFD: Int32 = -1 + var secondaryFD: Int32 = -1 + var win = winsize(ws_row: options.rows, ws_col: options.cols, ws_xpixel: 0, ws_ypixel: 0) + guard openpty(&primaryFD, &secondaryFD, nil, nil, &win) == 0 else { + throw SessionError.launchFailed("openpty failed") + } + _ = fcntl(primaryFD, F_SETFL, O_NONBLOCK) + + let primaryHandle = FileHandle(fileDescriptor: primaryFD, closeOnDealloc: true) + let secondaryHandle = FileHandle(fileDescriptor: secondaryFD, closeOnDealloc: true) + + let proc = Process() + let resolvedURL = URL(fileURLWithPath: binary) + proc.executableURL = resolvedURL + proc.arguments = options.extraArgs + proc.standardInput = secondaryHandle + proc.standardOutput = secondaryHandle + proc.standardError = secondaryHandle + proc.currentDirectoryURL = options.workingDirectory + + let env = TTYCommandRunner.enrichedEnvironment( + baseEnv: options.environment, + home: options.environment["HOME"] ?? NSHomeDirectory()) + proc.environment = env + + guard TTYCommandRunner.beginActiveProcessLaunchForAppShutdown() else { + try? primaryHandle.close() + try? secondaryHandle.close() + throw SessionError.launchFailed("App shutdown in progress") + } + defer { TTYCommandRunner.endActiveProcessLaunchForAppShutdown() } + + do { + try proc.run() + } catch { + try? primaryHandle.close() + try? secondaryHandle.close() + throw SessionError.launchFailed(error.localizedDescription) + } + + let pid = proc.processIdentifier + guard TTYCommandRunner.registerActiveProcessForAppShutdown( + pid: pid, + binary: resolvedURL.lastPathComponent) + else { + proc.terminate() + kill(pid, SIGKILL) + try? primaryHandle.close() + try? secondaryHandle.close() + throw SessionError.launchFailed("App shutdown in progress") + } + + var processGroup: pid_t? + if setpgid(pid, pid) == 0 { + processGroup = pid + TTYCommandRunner.updateActiveProcessGroupForAppShutdown(pid: pid, processGroup: processGroup) + } + + self.process = proc + self.primaryFD = primaryFD + self.primaryHandle = primaryHandle + self.secondaryHandle = secondaryHandle + self.processGroup = processGroup + self.binaryPath = binary + self.startedAt = Date() + self.ptyRows = options.rows + self.ptyCols = options.cols + self.sessionEnvironment = options.environment + self.sessionArguments = options.extraArgs + self.sessionWorkingDirectory = options.workingDirectory + } + + private func cleanup() { + if let proc = self.process, proc.isRunning, let handle = self.primaryHandle { + try? handle.write(contentsOf: Data("/exit\n".utf8)) + } + try? self.primaryHandle?.close() + try? self.secondaryHandle?.close() + + let descendants = self.process.map { TTYProcessTreeTerminator.descendantPIDs(of: $0.processIdentifier) } ?? [] + if let proc = self.process, proc.isRunning { + proc.terminate() + } + if let proc = self.process { + TTYProcessTreeTerminator.terminateProcessTree( + rootPID: proc.processIdentifier, + processGroup: self.processGroup, + signal: SIGTERM, + knownDescendants: descendants) + } + let waitDeadline = Date().addingTimeInterval(1.0) + if let proc = self.process { + while proc.isRunning, Date() < waitDeadline { + usleep(100_000) + } + if proc.isRunning { + TTYProcessTreeTerminator.terminateProcessTree( + rootPID: proc.processIdentifier, + processGroup: self.processGroup, + signal: SIGKILL, + knownDescendants: descendants) + } else { + for pid in descendants where pid > 0 { + kill(pid, SIGKILL) + } + } + TTYCommandRunner.unregisterActiveProcessForAppShutdown(pid: proc.processIdentifier) + } + + self.process = nil + self.primaryHandle = nil + self.secondaryHandle = nil + self.primaryFD = -1 + self.processGroup = nil + self.binaryPath = nil + self.startedAt = nil + self.ptyRows = 0 + self.ptyCols = 0 + self.sessionEnvironment = nil + self.sessionArguments = [] + self.sessionWorkingDirectory = nil + } + + private func readChunk() -> Data { + guard self.primaryFD >= 0 else { return Data() } + var appended = Data() + while true { + var tmp = [UInt8](repeating: 0, count: 8192) + let n = read(self.primaryFD, &tmp, tmp.count) + if n > 0 { + appended.append(contentsOf: tmp.prefix(n)) + continue + } + break + } + return appended + } + + private func drainOutput() { + _ = self.readChunk() + } + + private func send(_ text: String) throws { + guard let data = text.data(using: .utf8) else { return } + guard let handle = self.primaryHandle else { throw SessionError.processExited } + try handle.write(contentsOf: data) + } +} diff --git a/Sources/CodexBarCore/Providers/Codex/CodexDashboardAuthority.swift b/Sources/CodexBarCore/Providers/Codex/CodexDashboardAuthority.swift new file mode 100644 index 0000000..8d40ccc --- /dev/null +++ b/Sources/CodexBarCore/Providers/Codex/CodexDashboardAuthority.swift @@ -0,0 +1,332 @@ +import Foundation + +public enum CodexDashboardSourceKind: String, Codable, Sendable { + case liveWeb + case cachedDashboard +} + +public enum CodexDashboardDisposition: String, Codable, Sendable { + case attach + case displayOnly + case failClosed +} + +public enum CodexDashboardAllowedEffect: String, Codable, CaseIterable, Hashable, Sendable { + case usageBackfill + case creditsAttachment + case refreshGuardSeed + case historicalBackfill + case cachedDashboardReuse +} + +public enum CodexDashboardCleanup: String, Codable, CaseIterable, Hashable, Sendable { + case dashboardSnapshot + case dashboardDerivedUsage + case dashboardDerivedCredits + case dashboardRefreshGuardSeed + case dashboardCache +} + +public struct CodexDashboardKnownOwnerCandidate: Equatable, Hashable, Sendable { + public let identity: CodexIdentity + public let normalizedEmail: String? + public let sourceIsolationIdentifier: String? + + public init( + identity: CodexIdentity, + normalizedEmail: String?, + sourceIsolationIdentifier: String? = nil) + { + self.identity = identity + self.normalizedEmail = normalizedEmail + self.sourceIsolationIdentifier = sourceIsolationIdentifier + } + + public func hash(into hasher: inout Hasher) { + switch self.identity { + case let .providerAccount(id): + hasher.combine("providerAccount") + hasher.combine(id) + case let .emailOnly(normalizedEmail): + hasher.combine("emailOnly") + hasher.combine(normalizedEmail) + case .unresolved: + hasher.combine("unresolved") + } + hasher.combine(self.normalizedEmail) + hasher.combine(self.sourceIsolationIdentifier) + } +} + +public struct CodexDashboardOwnershipProofContext: Equatable, Sendable { + public let currentIdentity: CodexIdentity + public let expectedScopedEmail: String? + public let trustedCurrentUsageEmail: String? + public let dashboardSignedInEmail: String? + public let knownOwners: [CodexDashboardKnownOwnerCandidate] + + public init( + currentIdentity: CodexIdentity, + expectedScopedEmail: String?, + trustedCurrentUsageEmail: String?, + dashboardSignedInEmail: String?, + knownOwners: [CodexDashboardKnownOwnerCandidate]) + { + self.currentIdentity = currentIdentity + self.expectedScopedEmail = expectedScopedEmail + self.trustedCurrentUsageEmail = trustedCurrentUsageEmail + self.dashboardSignedInEmail = dashboardSignedInEmail + self.knownOwners = knownOwners + } +} + +public struct CodexDashboardRoutingHints: Equatable, Sendable { + public let targetEmail: String? + public let lastKnownDashboardRoutingEmail: String? + + public init(targetEmail: String?, lastKnownDashboardRoutingEmail: String?) { + self.targetEmail = targetEmail + self.lastKnownDashboardRoutingEmail = lastKnownDashboardRoutingEmail + } +} + +public struct CodexDashboardAuthorityInput: Equatable, Sendable { + public let sourceKind: CodexDashboardSourceKind + public let proof: CodexDashboardOwnershipProofContext + public let routing: CodexDashboardRoutingHints + + public init( + sourceKind: CodexDashboardSourceKind, + proof: CodexDashboardOwnershipProofContext, + routing: CodexDashboardRoutingHints) + { + self.sourceKind = sourceKind + self.proof = proof + self.routing = routing + } +} + +public enum CodexDashboardDecisionReason: Equatable, Sendable { + case exactProviderAccountMatch + case trustedEmailMatchNoCompetingOwner + case trustedContinuityNoCompetingOwner + case wrongEmail(expected: String?, actual: String?) + case sameEmailAmbiguity(email: String) + case unresolvedWithoutTrustedEvidence + case providerAccountMissingScopedEmail + case providerAccountLacksExactOwnershipProof + case missingDashboardSignedInEmail +} + +public struct CodexDashboardAuthorityDecision: Equatable, Sendable { + public let disposition: CodexDashboardDisposition + public let reason: CodexDashboardDecisionReason + public let allowedEffects: Set + public let cleanup: Set + + public init( + disposition: CodexDashboardDisposition, + reason: CodexDashboardDecisionReason, + allowedEffects: Set, + cleanup: Set) + { + self.disposition = disposition + self.reason = reason + self.allowedEffects = allowedEffects + self.cleanup = cleanup + } +} + +public enum CodexDashboardPolicyError: LocalizedError, Equatable, Sendable { + case displayOnly(CodexDashboardAuthorityDecision) + + public var errorDescription: String? { + switch self { + case .displayOnly: + "Codex dashboard may be displayed, but it cannot be attached to the active account." + } + } +} + +public enum CodexDashboardAuthority { + /// Evaluates whether a Codex dashboard snapshot may attach to the active account. + /// + /// App callers may keep `.displayOnly` dashboard data visible, but must not attach usage, + /// credits, refresh guards, or historical backfill. + /// + /// CLI callers should surface `.displayOnly` as `CodexDashboardPolicyError.displayOnly` + /// instead of treating it as a generic failure. + /// + /// Cached dashboard callers may restore data only when the decision includes + /// `.cachedDashboardReuse` in `allowedEffects`. + public static func evaluate(_ input: CodexDashboardAuthorityInput) -> CodexDashboardAuthorityDecision { + let proof = input.proof + let currentIdentity = Self.normalizeIdentity(proof.currentIdentity) + let expectedScopedEmail = CodexIdentityResolver.normalizeEmail(proof.expectedScopedEmail) + let trustedCurrentUsageEmail = CodexIdentityResolver.normalizeEmail(proof.trustedCurrentUsageEmail) + let dashboardSignedInEmail = CodexIdentityResolver.normalizeEmail(proof.dashboardSignedInEmail) + let knownOwners = Self.normalizeKnownOwners(proof.knownOwners) + + // Routing hints are intentionally excluded from ownership proof. They may help fetch or route + // dashboard requests, but they must never influence attach/display/fail-closed policy. + + guard let dashboardSignedInEmail else { + return Self.makeDecision( + disposition: .failClosed, + reason: .missingDashboardSignedInEmail, + sourceKind: input.sourceKind) + } + + if let expectedScopedEmail, dashboardSignedInEmail != expectedScopedEmail { + return Self.makeDecision( + disposition: .failClosed, + reason: .wrongEmail(expected: expectedScopedEmail, actual: dashboardSignedInEmail), + sourceKind: input.sourceKind) + } + + switch currentIdentity { + case let .providerAccount(id): + guard expectedScopedEmail != nil else { + return Self.makeDecision( + disposition: .failClosed, + reason: .providerAccountMissingScopedEmail, + sourceKind: input.sourceKind) + } + if Self.knownOwnerCount(for: dashboardSignedInEmail, in: knownOwners) > 1 { + return Self.makeDecision( + disposition: .displayOnly, + reason: .sameEmailAmbiguity(email: dashboardSignedInEmail), + sourceKind: input.sourceKind) + } + let exactMatch = knownOwners.contains { candidate in + candidate.identity == .providerAccount(id: id) && candidate.normalizedEmail == dashboardSignedInEmail + } + if exactMatch { + return Self.makeDecision( + disposition: .attach, + reason: .exactProviderAccountMatch, + sourceKind: input.sourceKind) + } + return Self.makeDecision( + disposition: .failClosed, + reason: .providerAccountLacksExactOwnershipProof, + sourceKind: input.sourceKind) + + case let .emailOnly(normalizedEmail): + guard dashboardSignedInEmail == normalizedEmail else { + return Self.makeDecision( + disposition: .failClosed, + reason: .wrongEmail(expected: normalizedEmail, actual: dashboardSignedInEmail), + sourceKind: input.sourceKind) + } + if Self.knownOwnerCount(for: normalizedEmail, in: knownOwners) > 1 { + return Self.makeDecision( + disposition: .displayOnly, + reason: .sameEmailAmbiguity(email: normalizedEmail), + sourceKind: input.sourceKind) + } + return Self.makeDecision( + disposition: .attach, + reason: .trustedEmailMatchNoCompetingOwner, + sourceKind: input.sourceKind) + + case .unresolved: + guard let trustedCurrentUsageEmail else { + return Self.makeDecision( + disposition: .failClosed, + reason: .unresolvedWithoutTrustedEvidence, + sourceKind: input.sourceKind) + } + guard dashboardSignedInEmail == trustedCurrentUsageEmail else { + return Self.makeDecision( + disposition: .failClosed, + reason: .wrongEmail(expected: trustedCurrentUsageEmail, actual: dashboardSignedInEmail), + sourceKind: input.sourceKind) + } + if Self.knownOwnerCount(for: trustedCurrentUsageEmail, in: knownOwners) > 1 { + return Self.makeDecision( + disposition: .displayOnly, + reason: .sameEmailAmbiguity(email: trustedCurrentUsageEmail), + sourceKind: input.sourceKind) + } + return Self.makeDecision( + disposition: .attach, + reason: .trustedContinuityNoCompetingOwner, + sourceKind: input.sourceKind) + } + } + + private static func normalizeIdentity(_ identity: CodexIdentity) -> CodexIdentity { + switch identity { + case let .providerAccount(id): + if let normalizedID = CodexIdentityResolver.normalizeAccountID(id) { + return .providerAccount(id: normalizedID) + } + return .unresolved + case let .emailOnly(normalizedEmail): + if let normalizedEmail = CodexIdentityResolver.normalizeEmail(normalizedEmail) { + return .emailOnly(normalizedEmail: normalizedEmail) + } + return .unresolved + case .unresolved: + return .unresolved + } + } + + private static func normalizeKnownOwners( + _ candidates: [CodexDashboardKnownOwnerCandidate]) + -> Set + { + Set(candidates.map { candidate in + let identity = self.normalizeIdentity(candidate.identity) + let sourceIsolationIdentifier: String? = switch identity { + case .providerAccount: + nil + case .emailOnly, .unresolved: + candidate.sourceIsolationIdentifier + } + return CodexDashboardKnownOwnerCandidate( + identity: identity, + normalizedEmail: CodexIdentityResolver.normalizeEmail(candidate.normalizedEmail), + sourceIsolationIdentifier: sourceIsolationIdentifier) + }) + } + + private static func knownOwnerCount( + for email: String, + in candidates: Set) -> Int + { + candidates.count { $0.normalizedEmail == email } + } + + private static func makeDecision( + disposition: CodexDashboardDisposition, + reason: CodexDashboardDecisionReason, + sourceKind: CodexDashboardSourceKind) -> CodexDashboardAuthorityDecision + { + CodexDashboardAuthorityDecision( + disposition: disposition, + reason: reason, + allowedEffects: self.allowedEffects(disposition: disposition, sourceKind: sourceKind), + cleanup: disposition == .attach ? [] : Set(CodexDashboardCleanup.allCases)) + } + + private static func allowedEffects( + disposition: CodexDashboardDisposition, + sourceKind: CodexDashboardSourceKind) -> Set + { + guard disposition == .attach else { return [] } + + switch sourceKind { + case .liveWeb: + return [ + .usageBackfill, + .creditsAttachment, + .refreshGuardSeed, + .historicalBackfill, + ] + case .cachedDashboard: + return [.cachedDashboardReuse] + } + } +} diff --git a/Sources/CodexBarCore/Providers/Codex/CodexIdentity.swift b/Sources/CodexBarCore/Providers/Codex/CodexIdentity.swift new file mode 100644 index 0000000..f83cb19 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Codex/CodexIdentity.swift @@ -0,0 +1,47 @@ +import Foundation + +public enum CodexIdentity: Codable, Equatable, Sendable { + case providerAccount(id: String) + // Normal OAuth auth should resolve to a provider account ID. Email-only identity is kept as a + // migration/hardening fallback for partial auth payloads, not as the primary steady-state path. + case emailOnly(normalizedEmail: String) + case unresolved +} + +public enum CodexIdentityResolver { + public static func resolve(accountId: String?, email: String?) -> CodexIdentity { + if let accountId = normalizeAccountID(accountId) { + return .providerAccount(id: accountId) + } + if let email = Self.normalizeEmail(email) { + return .emailOnly(normalizedEmail: email) + } + return .unresolved + } + + public static func normalizeEmail(_ email: String?) -> String? { + guard let email = email?.trimmingCharacters(in: .whitespacesAndNewlines), !email.isEmpty else { + return nil + } + return email.lowercased() + } + + public static func normalizeAccountID(_ accountId: String?) -> String? { + guard let accountId = accountId?.trimmingCharacters(in: .whitespacesAndNewlines), !accountId.isEmpty else { + return nil + } + return accountId + } +} + +public struct CodexAuthBackedAccount: Equatable, Sendable { + public let identity: CodexIdentity + public let email: String? + public let plan: String? + + public init(identity: CodexIdentity, email: String?, plan: String?) { + self.identity = identity + self.email = email + self.plan = plan + } +} diff --git a/Sources/CodexBarCore/Providers/Codex/CodexOAuth/CodexOAuthCredentials.swift b/Sources/CodexBarCore/Providers/Codex/CodexOAuth/CodexOAuthCredentials.swift new file mode 100644 index 0000000..7c180da --- /dev/null +++ b/Sources/CodexBarCore/Providers/Codex/CodexOAuth/CodexOAuthCredentials.swift @@ -0,0 +1,285 @@ +#if canImport(Darwin) +import Darwin +#elseif canImport(Glibc) +import Glibc +#elseif canImport(Musl) +import Musl +#endif +import Foundation + +public struct CodexOAuthCredentials: Sendable { + public let accessToken: String + public let refreshToken: String + public let idToken: String? + public let accountId: String? + public let lastRefresh: Date? + + public init( + accessToken: String, + refreshToken: String, + idToken: String?, + accountId: String?, + lastRefresh: Date?) + { + self.accessToken = accessToken + self.refreshToken = refreshToken + self.idToken = idToken + self.accountId = accountId + self.lastRefresh = lastRefresh + } + + public var needsRefresh: Bool { + guard let lastRefresh else { return true } + let eightDays: TimeInterval = 8 * 24 * 60 * 60 + return Date().timeIntervalSince(lastRefresh) > eightDays + } +} + +public enum CodexOAuthCredentialsError: LocalizedError, Sendable { + case notFound + case decodeFailed(String) + case missingTokens + + public var errorDescription: String? { + switch self { + case .notFound: + "Codex auth.json not found. Run `codex` to log in." + case let .decodeFailed(message): + "Failed to decode Codex credentials: \(message)" + case .missingTokens: + "Codex auth.json exists but contains no tokens." + } + } +} + +public enum CodexOAuthCredentialsStore { + private static func authFilePath( + env: [String: String] = ProcessInfo.processInfo.environment, + fileManager: FileManager = .default) -> URL + { + CodexHomeScope + .ambientHomeURL(env: env, fileManager: fileManager) + .appendingPathComponent("auth.json") + } + + public static func load(env: [String: String] = ProcessInfo.processInfo + .environment) throws -> CodexOAuthCredentials + { + let url = self.authFilePath(env: env) + guard FileManager.default.fileExists(atPath: url.path) else { + throw CodexOAuthCredentialsError.notFound + } + + let data = try Data(contentsOf: url) + return try self.parse(data: data) + } + + public static func loadOAuthTokens(env: [String: String] = ProcessInfo.processInfo + .environment) throws -> CodexOAuthCredentials + { + let url = self.authFilePath(env: env) + guard FileManager.default.fileExists(atPath: url.path) else { + throw CodexOAuthCredentialsError.notFound + } + + let data = try Data(contentsOf: url) + guard let credentials = try self.tokenCredentials(data: data) else { + throw CodexOAuthCredentialsError.missingTokens + } + return credentials + } + + public static func parse(data: Data) throws -> CodexOAuthCredentials { + guard let json = try JSONSerialization.jsonObject(with: data) as? [String: Any] else { + throw CodexOAuthCredentialsError.decodeFailed("Invalid JSON") + } + + if let apiKeyCredentials = Self.apiKeyCredentials(in: json) { + return apiKeyCredentials + } + + if let tokenCredentials = Self.tokenCredentials(in: json) { + return tokenCredentials + } + + throw CodexOAuthCredentialsError.missingTokens + } + + private static func tokenCredentials(data: Data) throws -> CodexOAuthCredentials? { + guard let json = try JSONSerialization.jsonObject(with: data) as? [String: Any] else { + throw CodexOAuthCredentialsError.decodeFailed("Invalid JSON") + } + return self.tokenCredentials(in: json) + } + + private static func tokenCredentials(in json: [String: Any]) -> CodexOAuthCredentials? { + guard let tokens = json["tokens"] as? [String: Any], + let accessToken = stringValue( + in: tokens, + snakeCaseKey: "access_token", + camelCaseKey: "accessToken"), + let refreshToken = stringValue( + in: tokens, + snakeCaseKey: "refresh_token", + camelCaseKey: "refreshToken"), + !accessToken.isEmpty + else { + return nil + } + + let idToken = Self.stringValue(in: tokens, snakeCaseKey: "id_token", camelCaseKey: "idToken") + let accountId = Self.stringValue(in: tokens, snakeCaseKey: "account_id", camelCaseKey: "accountId") + let lastRefresh = Self.parseLastRefresh(from: json["last_refresh"]) + + return CodexOAuthCredentials( + accessToken: accessToken, + refreshToken: refreshToken, + idToken: idToken, + accountId: accountId, + lastRefresh: lastRefresh) + } + + private static func apiKeyCredentials(in json: [String: Any]) -> CodexOAuthCredentials? { + guard let apiKey = json["OPENAI_API_KEY"] as? String, + !apiKey.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty + else { + return nil + } + return CodexOAuthCredentials( + accessToken: apiKey, + refreshToken: "", + idToken: nil, + accountId: nil, + lastRefresh: nil) + } + + public static func save( + _ credentials: CodexOAuthCredentials, + env: [String: String] = ProcessInfo.processInfo.environment) throws + { + let url = self.authFilePath(env: env) + + var json: [String: Any] = [:] + if let data = try? Data(contentsOf: url), + let existing = try? JSONSerialization.jsonObject(with: data) as? [String: Any] + { + json = existing + } + + var tokens: [String: Any] = [ + "access_token": credentials.accessToken, + "refresh_token": credentials.refreshToken, + ] + if let idToken = credentials.idToken { + tokens["id_token"] = idToken + } + if let accountId = credentials.accountId { + tokens["account_id"] = accountId + } + + json["tokens"] = tokens + json["last_refresh"] = ISO8601DateFormatter().string(from: Date()) + + let data = try JSONSerialization.data(withJSONObject: json, options: [.prettyPrinted, .sortedKeys]) + let directory = url.deletingLastPathComponent() + try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true) + try self.writePrivateFile(data, to: url) + } + + private static func writePrivateFile( + _ data: Data, + to url: URL, + beforePublish: ((URL) throws -> Void)? = nil) throws + { + let fileManager = FileManager.default + let stagedURL = url.deletingLastPathComponent().appendingPathComponent( + ".\(url.lastPathComponent).codexbar-staged-\(UUID().uuidString)", + isDirectory: false) + let stagedPath = stagedURL.path + let descriptor = stagedPath.withCString { + open($0, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode_t(0o600)) + } + guard descriptor >= 0 else { + throw self.posixError(code: errno, path: stagedPath) + } + + let handle = FileHandle(fileDescriptor: descriptor, closeOnDealloc: true) + var handleIsOpen = true + do { + guard fchmod(descriptor, mode_t(0o600)) == 0 else { + throw self.posixError(code: errno, path: stagedPath) + } + try handle.write(contentsOf: data) + try handle.synchronize() + try handle.close() + handleIsOpen = false + + try beforePublish?(stagedURL) + try self.renameItem(at: stagedURL, to: url) + } catch { + if handleIsOpen { + try? handle.close() + } + try? fileManager.removeItem(at: stagedURL) + throw error + } + } + + private static func renameItem(at sourceURL: URL, to destinationURL: URL) throws { + let result = sourceURL.path.withCString { sourcePath in + destinationURL.path.withCString { destinationPath in + rename(sourcePath, destinationPath) + } + } + guard result == 0 else { + throw self.posixError(code: errno, path: destinationURL.path) + } + } + + private static func posixError(code: Int32, path: String) -> NSError { + NSError( + domain: NSPOSIXErrorDomain, + code: Int(code), + userInfo: [NSFilePathErrorKey: path]) + } + + private static func parseLastRefresh(from raw: Any?) -> Date? { + guard let value = raw as? String, !value.isEmpty else { return nil } + let formatter = ISO8601DateFormatter() + formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds] + if let date = formatter.date(from: value) { return date } + formatter.formatOptions = [.withInternetDateTime] + return formatter.date(from: value) + } + + private static func stringValue( + in dictionary: [String: Any], + snakeCaseKey: String, + camelCaseKey: String) + -> String? + { + if let value = dictionary[snakeCaseKey] as? String, !value.isEmpty { + return value + } + if let value = dictionary[camelCaseKey] as? String, !value.isEmpty { + return value + } + return nil + } +} + +#if DEBUG +extension CodexOAuthCredentialsStore { + static func _authFileURLForTesting(env: [String: String]) -> URL { + self.authFilePath(env: env) + } + + static func _writePrivateFileForTesting( + _ data: Data, + to url: URL, + beforePublish: @escaping (URL) throws -> Void) throws + { + try self.writePrivateFile(data, to: url, beforePublish: beforePublish) + } +} +#endif diff --git a/Sources/CodexBarCore/Providers/Codex/CodexOAuth/CodexOAuthUsageFetcher.swift b/Sources/CodexBarCore/Providers/Codex/CodexOAuth/CodexOAuthUsageFetcher.swift new file mode 100644 index 0000000..2ae5e3e --- /dev/null +++ b/Sources/CodexBarCore/Providers/Codex/CodexOAuth/CodexOAuthUsageFetcher.swift @@ -0,0 +1,655 @@ +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +public struct CodexUsageResponse: Decodable, Sendable { + public let planType: PlanType? + public let rateLimit: RateLimitDetails? + public let credits: CreditDetails? + public let individualLimit: SpendControlLimitSnapshot? + /// Model-specific limits (e.g. GPT-5.3-Codex-Spark) that sit alongside the primary/weekly windows. + public let additionalRateLimits: [AdditionalRateLimit]? + let additionalRateLimitsDecodeFailed: Bool + + enum CodingKeys: String, CodingKey { + case planType = "plan_type" + case rateLimit = "rate_limit" + case credits + case individualLimit = "individual_limit" + case individualLimitCamel = "individualLimit" + case additionalRateLimits = "additional_rate_limits" + } + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.planType = try? container.decodeIfPresent(PlanType.self, forKey: .planType) + self.rateLimit = try? container.decodeIfPresent(RateLimitDetails.self, forKey: .rateLimit) + self.credits = try? container.decodeIfPresent(CreditDetails.self, forKey: .credits) + self.individualLimit = (try? container.decodeIfPresent( + SpendControlLimitSnapshot.self, + forKey: .individualLimit)) + ?? (try? container.decodeIfPresent(SpendControlLimitSnapshot.self, forKey: .individualLimitCamel)) + // Optional and additive: missing/malformed extra limits must never disturb primary/weekly mapping. + // Decode per element so a single malformed entry cannot discard its valid siblings; a non-array + // value (or absent field) leaves `additionalRateLimits` nil and primary/weekly mapping untouched. + let additionalRateLimitsHadValue = Self.hasNonNilValue(container: container, key: .additionalRateLimits) + do { + let decoded = try container.decodeIfPresent( + [LossyAdditionalRateLimit].self, + forKey: .additionalRateLimits) + self.additionalRateLimits = decoded?.compactMap(\.value) + self.additionalRateLimitsDecodeFailed = decoded?.contains(where: \.decodeFailed) == true + || self.additionalRateLimits?.contains(where: \.hasWindowDecodeFailure) == true + } catch { + self.additionalRateLimits = nil + self.additionalRateLimitsDecodeFailed = additionalRateLimitsHadValue + } + } + + private static func hasNonNilValue( + container: KeyedDecodingContainer, + key: CodingKeys) -> Bool + { + guard container.contains(key) else { return false } + return (try? container.decodeNil(forKey: key)) == false + } + + public enum PlanType: Sendable, Decodable, Equatable { + case guest + case free + case go + case plus + case pro + case freeWorkspace + case team + case business + case education + case quorum + case k12 + case enterprise + case edu + case unknown(String) + + public var rawValue: String { + switch self { + case .guest: "guest" + case .free: "free" + case .go: "go" + case .plus: "plus" + case .pro: "pro" + case .freeWorkspace: "free_workspace" + case .team: "team" + case .business: "business" + case .education: "education" + case .quorum: "quorum" + case .k12: "k12" + case .enterprise: "enterprise" + case .edu: "edu" + case let .unknown(value): value + } + } + + public init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + let value = try container.decode(String.self) + switch value { + case "guest": self = .guest + case "free": self = .free + case "go": self = .go + case "plus": self = .plus + case "pro": self = .pro + case "free_workspace": self = .freeWorkspace + case "team": self = .team + case "business": self = .business + case "education": self = .education + case "quorum": self = .quorum + case "k12": self = .k12 + case "enterprise": self = .enterprise + case "edu": self = .edu + default: + self = .unknown(value) + } + } + } + + public struct RateLimitDetails: Decodable, Sendable { + public let primaryWindow: WindowSnapshot? + public let secondaryWindow: WindowSnapshot? + public let individualLimit: SpendControlLimitSnapshot? + let primaryWindowDecodeFailed: Bool + let secondaryWindowDecodeFailed: Bool + + enum CodingKeys: String, CodingKey { + case primaryWindow = "primary_window" + case secondaryWindow = "secondary_window" + case individualLimit = "individual_limit" + case individualLimitCamel = "individualLimit" + } + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + let primaryHadValue = Self.hasNonNilValue(container: container, key: .primaryWindow) + do { + self.primaryWindow = try container.decodeIfPresent(WindowSnapshot.self, forKey: .primaryWindow) + self.primaryWindowDecodeFailed = false + } catch { + self.primaryWindow = nil + self.primaryWindowDecodeFailed = primaryHadValue + } + + let secondaryHadValue = Self.hasNonNilValue(container: container, key: .secondaryWindow) + do { + self.secondaryWindow = try container.decodeIfPresent(WindowSnapshot.self, forKey: .secondaryWindow) + self.secondaryWindowDecodeFailed = false + } catch { + self.secondaryWindow = nil + self.secondaryWindowDecodeFailed = secondaryHadValue + } + self.individualLimit = (try? container.decodeIfPresent( + SpendControlLimitSnapshot.self, + forKey: .individualLimit)) + ?? (try? container.decodeIfPresent(SpendControlLimitSnapshot.self, forKey: .individualLimitCamel)) + } + + private static func hasNonNilValue( + container: KeyedDecodingContainer, + key: CodingKeys) -> Bool + { + guard container.contains(key) else { return false } + return (try? container.decodeNil(forKey: key)) == false + } + + var hasWindowDecodeFailure: Bool { + self.primaryWindowDecodeFailed || self.secondaryWindowDecodeFailed + } + } + + public struct WindowSnapshot: Decodable, Sendable { + public let usedPercent: Int + public let resetAt: Int + public let limitWindowSeconds: Int + + enum CodingKeys: String, CodingKey { + case usedPercent = "used_percent" + case resetAt = "reset_at" + case limitWindowSeconds = "limit_window_seconds" + } + } + + /// One entry of `additional_rate_limits`: a named, model-specific limit (e.g. GPT-5.3-Codex-Spark) + /// whose windows reuse the same shape as the primary/weekly `RateLimitDetails`. + public struct AdditionalRateLimit: Decodable, Sendable { + public let limitName: String? + public let meteredFeature: String? + public let rateLimit: RateLimitDetails? + let rateLimitDecodeFailed: Bool + + enum CodingKeys: String, CodingKey { + case limitName = "limit_name" + case meteredFeature = "metered_feature" + case rateLimit = "rate_limit" + } + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.limitName = try? container.decodeIfPresent(String.self, forKey: .limitName) + self.meteredFeature = try? container.decodeIfPresent(String.self, forKey: .meteredFeature) + let rateLimitHadValue = Self.hasNonNilValue(container: container, key: .rateLimit) + do { + self.rateLimit = try container.decodeIfPresent(RateLimitDetails.self, forKey: .rateLimit) + self.rateLimitDecodeFailed = false + } catch { + self.rateLimit = nil + self.rateLimitDecodeFailed = rateLimitHadValue + } + } + + private static func hasNonNilValue( + container: KeyedDecodingContainer, + key: CodingKeys) -> Bool + { + guard container.contains(key) else { return false } + return (try? container.decodeNil(forKey: key)) == false + } + + var hasWindowDecodeFailure: Bool { + self.rateLimitDecodeFailed || self.rateLimit?.hasWindowDecodeFailure == true + } + } + + /// Decodes a single `additional_rate_limits` element without ever throwing, so one malformed + /// entry cannot discard its valid siblings during array decoding. + private struct LossyAdditionalRateLimit: Decodable { + let value: AdditionalRateLimit? + let decodeFailed: Bool + + init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + self.value = try? container.decode(AdditionalRateLimit.self) + self.decodeFailed = self.value == nil + } + } + + public struct SpendControlLimitSnapshot: Decodable, Sendable { + public let limit: Double? + public let used: Double? + public let remainingPercent: Double? + public let resetsAt: Int? + + enum CodingKeys: String, CodingKey { + case limit + case used + case remainingPercent + case remainingPercentSnake = "remaining_percent" + case resetsAt + case resetsAtSnake = "resets_at" + } + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.limit = Self.decodeFlexibleDouble(container, forKey: .limit) + self.used = Self.decodeFlexibleDouble(container, forKey: .used) + self.remainingPercent = Self.decodeFlexibleDouble(container, forKey: .remainingPercent) + ?? Self.decodeFlexibleDouble(container, forKey: .remainingPercentSnake) + self.resetsAt = Self.decodeFlexibleInt(container, forKey: .resetsAt) + ?? Self.decodeFlexibleInt(container, forKey: .resetsAtSnake) + } + + private static func decodeFlexibleDouble( + _ container: KeyedDecodingContainer, + forKey key: CodingKeys) -> Double? + { + if let value = try? container.decodeIfPresent(Double.self, forKey: key) { + return value + } + if let value = try? container.decodeIfPresent(Int.self, forKey: key) { + return Double(value) + } + if let value = try? container.decodeIfPresent(String.self, forKey: key) { + return Double(value.trimmingCharacters(in: .whitespacesAndNewlines)) + } + return nil + } + + private static func decodeFlexibleInt( + _ container: KeyedDecodingContainer, + forKey key: CodingKeys) -> Int? + { + if let value = try? container.decodeIfPresent(Int.self, forKey: key) { + return value + } + if let value = try? container.decodeIfPresent(Double.self, forKey: key) { + return Int(value) + } + if let value = try? container.decodeIfPresent(String.self, forKey: key) { + return Int(value.trimmingCharacters(in: .whitespacesAndNewlines)) + } + return nil + } + } + + public struct CreditDetails: Decodable, Sendable { + public let hasCredits: Bool + public let unlimited: Bool + public let balance: Double? + + enum CodingKeys: String, CodingKey { + case hasCredits = "has_credits" + case unlimited + case balance + } + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.hasCredits = (try? container.decode(Bool.self, forKey: .hasCredits)) ?? false + self.unlimited = (try? container.decode(Bool.self, forKey: .unlimited)) ?? false + if let balance = try? container.decode(Double.self, forKey: .balance) { + self.balance = balance + } else if let balance = try? container.decode(String.self, forKey: .balance), + let value = Double(balance) + { + self.balance = value + } else { + self.balance = nil + } + } + } +} + +public enum CodexOAuthFetchError: LocalizedError, Sendable { + case unauthorized + case invalidResponse + case serverError(Int, String?) + case networkError(Error) + + public var errorDescription: String? { + switch self { + case .unauthorized: + return "Codex OAuth token expired or invalid. Run `codex` to re-authenticate." + case .invalidResponse: + return "Invalid response from Codex usage API." + case let .serverError(code, message): + if let message, !message.isEmpty { + return "Codex API error \(code): \(message)" + } + return "Codex API error \(code)." + case let .networkError(error): + return "Network error: \(error.localizedDescription)" + } + } +} + +public enum CodexOAuthUsageFetcher { + private static let defaultChatGPTBaseURL = "https://chatgpt.com/backend-api/" + private static let chatGPTUsagePath = "/wham/usage" + private static let codexUsagePath = "/api/codex/usage" + private static let rateLimitResetCreditsPath = "/wham/rate-limit-reset-credits" + + public static func fetchUsage( + accessToken: String, + accountId: String?, + env: [String: String] = ProcessInfo.processInfo.environment) async throws -> CodexUsageResponse + { + try await self.fetchUsage( + accessToken: accessToken, + accountId: accountId, + env: env, + session: CodexAuthenticatedHTTPTransport.current) + } + + public static func fetchUsage( + accessToken: String, + accountId: String?, + env: [String: String] = ProcessInfo.processInfo.environment, + session transport: any ProviderHTTPTransport) async throws -> CodexUsageResponse + { + var request = URLRequest( + url: Self.resolveUsageURL(env: env), + cachePolicy: .reloadIgnoringLocalCacheData, + timeoutInterval: 30) + request.httpMethod = "GET" + request.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization") + request.setValue("CodexBar", forHTTPHeaderField: "User-Agent") + request.setValue("application/json", forHTTPHeaderField: "Accept") + + if let accountId, !accountId.isEmpty { + request.setValue(accountId, forHTTPHeaderField: "ChatGPT-Account-Id") + } + + do { + let response = try await transport.response(for: request) + let data = response.data + + switch response.statusCode { + case 200...299: + do { + return try JSONDecoder().decode(CodexUsageResponse.self, from: data) + } catch { + throw CodexOAuthFetchError.invalidResponse + } + case 401, 403: + throw CodexOAuthFetchError.unauthorized + default: + let body = String(data: data, encoding: .utf8) + throw CodexOAuthFetchError.serverError(response.statusCode, body) + } + } catch let error as CodexOAuthFetchError { + throw error + } catch is CancellationError { + throw CancellationError() + } catch { + if Task.isCancelled || (error as? URLError)?.code == .cancelled { + throw CancellationError() + } + throw CodexOAuthFetchError.networkError(error) + } + } + + public static func fetchRateLimitResetCredits( + accessToken: String, + accountId: String?, + env: [String: String] = ProcessInfo.processInfo.environment, + timeout: TimeInterval = 4) async throws -> CodexRateLimitResetCreditsSnapshot + { + try await self.fetchRateLimitResetCredits( + accessToken: accessToken, + accountId: accountId, + env: env, + timeout: timeout, + session: CodexAuthenticatedHTTPTransport.current) + } + + public static func fetchRateLimitResetCredits( + accessToken: String, + accountId: String?, + env: [String: String] = ProcessInfo.processInfo.environment, + timeout: TimeInterval = 4, + session transport: any ProviderHTTPTransport) async throws + -> CodexRateLimitResetCreditsSnapshot + { + var request = URLRequest( + url: Self.resolveRateLimitResetCreditsURL(env: env), + cachePolicy: .reloadIgnoringLocalCacheData, + timeoutInterval: timeout) + request.httpMethod = "GET" + request.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization") + request.setValue("CodexBar", forHTTPHeaderField: "User-Agent") + request.setValue("application/json", forHTTPHeaderField: "Accept") + request.setValue("codex-1", forHTTPHeaderField: "OpenAI-Beta") + request.setValue("Codex Desktop", forHTTPHeaderField: "originator") + + if let accountId, !accountId.isEmpty { + request.setValue(accountId, forHTTPHeaderField: "ChatGPT-Account-ID") + } + + do { + let response = try await transport.response(for: request) + let data = response.data + + switch response.statusCode { + case 200...299: + do { + let decoder = JSONDecoder() + decoder.dateDecodingStrategy = .custom(Self.decodeISO8601Date) + let payload = try decoder.decode(RateLimitResetCreditsResponse.self, from: data) + guard payload.availableCount >= 0 else { + throw CodexOAuthFetchError.invalidResponse + } + return CodexRateLimitResetCreditsSnapshot( + credits: payload.credits.map(\.model), + availableCount: payload.availableCount, + updatedAt: Date()) + } catch { + throw CodexOAuthFetchError.invalidResponse + } + case 401, 403: + throw CodexOAuthFetchError.unauthorized + default: + let body = String(data: data, encoding: .utf8) + throw CodexOAuthFetchError.serverError(response.statusCode, body) + } + } catch let error as CodexOAuthFetchError { + throw error + } catch is CancellationError { + throw CancellationError() + } catch { + if Task.isCancelled || (error as? URLError)?.code == .cancelled { + throw CancellationError() + } + throw CodexOAuthFetchError.networkError(error) + } + } + + private static func resolveUsageURL(env: [String: String]) -> URL { + self.resolveUsageURL(env: env, configContents: nil) + } + + private static func resolveUsageURL(env: [String: String], configContents: String?) -> URL { + let baseURL = self.resolveChatGPTBaseURL(env: env, configContents: configContents) + let normalized = self.normalizeChatGPTBaseURL(baseURL) + let path = normalized.contains("/backend-api") ? Self.chatGPTUsagePath : Self.codexUsagePath + let full = normalized + path + return URL(string: full) ?? URL(string: Self.defaultChatGPTBaseURL + Self.chatGPTUsagePath)! + } + + private static func resolveRateLimitResetCreditsURL(env: [String: String]) -> URL { + self.resolveRateLimitResetCreditsURL(env: env, configContents: nil) + } + + private static func resolveRateLimitResetCreditsURL(env: [String: String], configContents: String?) -> URL { + let baseURL = self.resolveChatGPTBaseURL(env: env, configContents: configContents) + let normalized = self.normalizeChatGPTBaseURL(baseURL) + let full = normalized + Self.rateLimitResetCreditsPath + return URL(string: full) ?? URL(string: Self.defaultChatGPTBaseURL + Self.rateLimitResetCreditsPath)! + } + + private static func resolveChatGPTBaseURL(env: [String: String], configContents: String?) -> String { + if let configContents, let parsed = self.parseChatGPTBaseURL(from: configContents) { + return parsed + } + if let contents = self.loadConfigContents(env: env), + let parsed = self.parseChatGPTBaseURL(from: contents) + { + return parsed + } + return Self.defaultChatGPTBaseURL + } + + private static func normalizeChatGPTBaseURL(_ value: String) -> String { + var trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines) + if trimmed.isEmpty { trimmed = Self.defaultChatGPTBaseURL } + while trimmed.hasSuffix("/") { + trimmed.removeLast() + } + if trimmed.hasPrefix("https://chatgpt.com") || trimmed.hasPrefix("https://chat.openai.com"), + !trimmed.contains("/backend-api") + { + trimmed += "/backend-api" + } + return trimmed + } + + private static func parseChatGPTBaseURL(from contents: String) -> String? { + for rawLine in contents.split(whereSeparator: \.isNewline) { + let line = rawLine.split(separator: "#", maxSplits: 1, omittingEmptySubsequences: true).first + let trimmed = line?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" + guard !trimmed.isEmpty else { continue } + let parts = trimmed.split(separator: "=", maxSplits: 1, omittingEmptySubsequences: true) + guard parts.count == 2 else { continue } + let key = parts[0].trimmingCharacters(in: .whitespacesAndNewlines) + guard key == "chatgpt_base_url" else { continue } + var value = parts[1].trimmingCharacters(in: .whitespacesAndNewlines) + if value.hasPrefix("\""), value.hasSuffix("\"") { + value = String(value.dropFirst().dropLast()) + } else if value.hasPrefix("'"), value.hasSuffix("'") { + value = String(value.dropFirst().dropLast()) + } + return value.trimmingCharacters(in: .whitespacesAndNewlines) + } + return nil + } + + private static func loadConfigContents(env: [String: String]) -> String? { + let home = FileManager.default.homeDirectoryForCurrentUser + let codexHome = env["CODEX_HOME"]?.trimmingCharacters(in: .whitespacesAndNewlines) + let root = (codexHome?.isEmpty == false) ? URL(fileURLWithPath: codexHome!) : home + .appendingPathComponent(".codex") + let url = root.appendingPathComponent("config.toml") + return try? String(contentsOf: url, encoding: .utf8) + } + + private struct RateLimitResetCreditsResponse: Decodable { + let credits: [RateLimitResetCreditResponse] + let availableCount: Int + + private enum CodingKeys: String, CodingKey { + case credits + case availableCount = "available_count" + } + } + + private struct RateLimitResetCreditResponse: Decodable { + let id: String + let resetType: String + let status: CodexRateLimitResetCreditStatus + let grantedAt: Date + let expiresAt: Date? + let redeemStartedAt: Date? + let redeemedAt: Date? + let title: String? + let description: String? + + private enum CodingKeys: String, CodingKey { + case id + case resetType = "reset_type" + case status + case grantedAt = "granted_at" + case expiresAt = "expires_at" + case redeemStartedAt = "redeem_started_at" + case redeemedAt = "redeemed_at" + case title + case description + } + + var model: CodexRateLimitResetCredit { + CodexRateLimitResetCredit( + id: self.id, + resetType: self.resetType, + status: self.status, + grantedAt: self.grantedAt, + expiresAt: self.expiresAt, + redeemStartedAt: self.redeemStartedAt, + redeemedAt: self.redeemedAt, + title: self.title, + description: self.description) + } + } + + private static func decodeISO8601Date(from decoder: Decoder) throws -> Date { + let container = try decoder.singleValueContainer() + let raw = try container.decode(String.self) + let fractional = ISO8601DateFormatter() + fractional.formatOptions = [.withInternetDateTime, .withFractionalSeconds] + let seconds = ISO8601DateFormatter() + seconds.formatOptions = [.withInternetDateTime] + if let date = fractional.date(from: raw) ?? seconds.date(from: raw) { + return date + } + throw DecodingError.dataCorruptedError( + in: container, + debugDescription: "Invalid ISO-8601 date: \(raw)") + } +} + +#if DEBUG +extension CodexOAuthUsageFetcher { + static func _resolveUsageURLForTesting(env: [String: String] = [:], configContents: String? = nil) -> URL { + self.resolveUsageURL(env: env, configContents: configContents) + } + + static func _decodeUsageResponseForTesting(_ data: Data) throws -> CodexUsageResponse { + try JSONDecoder().decode(CodexUsageResponse.self, from: data) + } + + static func _resolveRateLimitResetCreditsURLForTesting( + env: [String: String] = [:], + configContents: String? = nil) -> URL + { + self.resolveRateLimitResetCreditsURL(env: env, configContents: configContents) + } + + static func _decodeRateLimitResetCreditsForTesting( + _ data: Data, + now: Date = Date()) throws -> CodexRateLimitResetCreditsSnapshot + { + let decoder = JSONDecoder() + decoder.dateDecodingStrategy = .custom(Self.decodeISO8601Date) + let payload = try decoder.decode(RateLimitResetCreditsResponse.self, from: data) + return CodexRateLimitResetCreditsSnapshot( + credits: payload.credits.map(\.model), + availableCount: payload.availableCount, + updatedAt: now) + } +} +#endif diff --git a/Sources/CodexBarCore/Providers/Codex/CodexOAuth/CodexTokenRefresher.swift b/Sources/CodexBarCore/Providers/Codex/CodexOAuth/CodexTokenRefresher.swift new file mode 100644 index 0000000..ff79764 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Codex/CodexOAuth/CodexTokenRefresher.swift @@ -0,0 +1,123 @@ +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +public enum CodexTokenRefresher { + private static let refreshEndpoint = URL(string: "https://auth.openai.com/oauth/token")! + private static let clientID = "app_EMoamEEZ73f0CkXaXp7hrann" + + public enum RefreshError: LocalizedError, Sendable { + case expired + case revoked + case reused + case networkError(Error) + case invalidResponse(String) + + public var errorDescription: String? { + switch self { + case .expired: + "Refresh token expired. Please run `codex` to log in again." + case .revoked: + "Refresh token was revoked. Please run `codex` to log in again." + case .reused: + "Refresh token was already used. Please run `codex` to log in again." + case let .networkError(error): + "Network error during token refresh: \(error.localizedDescription)" + case let .invalidResponse(message): + "Invalid refresh response: \(message)" + } + } + } + + public static func refresh(_ credentials: CodexOAuthCredentials) async throws -> CodexOAuthCredentials { + try await self.refresh(credentials, session: CodexAuthenticatedHTTPTransport.current) + } + + static func refresh( + _ credentials: CodexOAuthCredentials, + session transport: any ProviderHTTPTransport) async throws -> CodexOAuthCredentials + { + guard !credentials.refreshToken.isEmpty else { + return credentials + } + + var request = URLRequest( + url: Self.refreshEndpoint, + cachePolicy: .reloadIgnoringLocalCacheData, + timeoutInterval: 30) + request.httpMethod = "POST" + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + + let body: [String: String] = [ + "client_id": Self.clientID, + "grant_type": "refresh_token", + "refresh_token": credentials.refreshToken, + "scope": "openid profile email", + ] + request.httpBody = try JSONSerialization.data(withJSONObject: body) + + do { + let response = try await transport.response(for: request) + let data = response.data + guard response.statusCode == 200 else { + throw Self.refreshFailureError(statusCode: response.statusCode, data: data) + } + + guard let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else { + throw RefreshError.invalidResponse("Invalid JSON") + } + + let newAccessToken = json["access_token"] as? String ?? credentials.accessToken + let newRefreshToken = json["refresh_token"] as? String ?? credentials.refreshToken + let newIdToken = json["id_token"] as? String ?? credentials.idToken + + return CodexOAuthCredentials( + accessToken: newAccessToken, + refreshToken: newRefreshToken, + idToken: newIdToken, + accountId: credentials.accountId, + lastRefresh: Date()) + } catch let error as RefreshError { + throw error + } catch { + throw RefreshError.networkError(error) + } + } + + private static func extractErrorCode(from data: Data) -> String? { + guard let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else { return nil } + if let error = json["error"] as? [String: Any], let code = error["code"] as? String { return code } + if let error = json["error"] as? String { return error } + return json["code"] as? String + } + + private static func refreshFailureError(statusCode: Int, data: Data) -> RefreshError { + if let errorCode = extractErrorCode(from: data) { + switch errorCode.lowercased() { + case "refresh_token_expired": + return .expired + case "refresh_token_reused": + return .reused + case "invalid_grant", "refresh_token_invalidated": + return .revoked + default: + break + } + } + + if statusCode == 401 { + return .expired + } + + return .invalidResponse("Status \(statusCode)") + } +} + +#if DEBUG +extension CodexTokenRefresher { + static func _refreshFailureErrorForTesting(statusCode: Int, data: Data) -> RefreshError { + self.refreshFailureError(statusCode: statusCode, data: data) + } +} +#endif diff --git a/Sources/CodexBarCore/Providers/Codex/CodexOpenAIWorkspaceIdentityCache.swift b/Sources/CodexBarCore/Providers/Codex/CodexOpenAIWorkspaceIdentityCache.swift new file mode 100644 index 0000000..2809c8c --- /dev/null +++ b/Sources/CodexBarCore/Providers/Codex/CodexOpenAIWorkspaceIdentityCache.swift @@ -0,0 +1,115 @@ +import Foundation + +public struct CodexOpenAIWorkspaceIdentityCache: @unchecked Sendable { + public static let currentVersion = 1 + + private struct Payload: Codable { + let version: Int + var labelsByWorkspaceAccountID: [String: String] + + init( + version: Int = CodexOpenAIWorkspaceIdentityCache.currentVersion, + labelsByWorkspaceAccountID: [String: String]) + { + self.version = version + self.labelsByWorkspaceAccountID = labelsByWorkspaceAccountID + } + } + + #if DEBUG + @TaskLocal static var taskFileURLOverride: URL? + #endif + + private let fileURL: URL + private let fileManager: FileManager + + public init(fileURL: URL = Self.defaultURL(), fileManager: FileManager = .default) { + self.fileURL = fileURL + self.fileManager = fileManager + } + + public func workspaceLabel(for workspaceAccountID: String?) -> String? { + guard let normalizedWorkspaceAccountID = CodexOpenAIWorkspaceResolver + .normalizeWorkspaceAccountID(workspaceAccountID) + else { + return nil + } + + return self.loadPayload().labelsByWorkspaceAccountID[normalizedWorkspaceAccountID] + } + + public func store(_ identity: CodexOpenAIWorkspaceIdentity) throws { + guard let workspaceLabel = CodexOpenAIWorkspaceIdentity.normalizeWorkspaceLabel(identity.workspaceLabel) else { + return + } + + var payload = self.loadPayload() + payload.labelsByWorkspaceAccountID[identity.workspaceAccountID] = workspaceLabel + + let encoder = JSONEncoder() + encoder.outputFormatting = [.prettyPrinted, .sortedKeys] + let data = try encoder.encode(payload) + let directory = self.fileURL.deletingLastPathComponent() + if !self.fileManager.fileExists(atPath: directory.path) { + try self.fileManager.createDirectory(at: directory, withIntermediateDirectories: true) + } + try data.write(to: self.fileURL, options: [.atomic]) + try self.applySecurePermissionsIfNeeded() + } + + private func loadPayload() -> Payload { + guard self.fileManager.fileExists(atPath: self.fileURL.path), + let data = try? Data(contentsOf: self.fileURL), + let payload = try? JSONDecoder().decode(Payload.self, from: data), + payload.version == Self.currentVersion + else { + return Payload(labelsByWorkspaceAccountID: [:]) + } + + return payload + } + + private func applySecurePermissionsIfNeeded() throws { + #if os(macOS) + try self.fileManager.setAttributes([ + .posixPermissions: NSNumber(value: Int16(0o600)), + ], ofItemAtPath: self.fileURL.path) + #endif + } + + public static func defaultURL() -> URL { + #if DEBUG + if let override = self.taskFileURLOverride { + return override + } + #endif + + let base = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).first + ?? FileManager.default.homeDirectoryForCurrentUser + return base + .appendingPathComponent("CodexBar", isDirectory: true) + .appendingPathComponent("codex-openai-workspaces.json") + } +} + +#if DEBUG +extension CodexOpenAIWorkspaceIdentityCache { + public static func withFileURLOverrideForTesting( + _ fileURL: URL, + operation: () throws -> T) rethrows -> T + { + try self.$taskFileURLOverride.withValue(fileURL) { + try operation() + } + } + + public static func withFileURLOverrideForTesting( + _ fileURL: URL, + operation: () async throws -> T) async rethrows -> T + { + try await self.$taskFileURLOverride.withValue(fileURL) { + try await operation() + } + } +} +#endif diff --git a/Sources/CodexBarCore/Providers/Codex/CodexOpenAIWorkspaceResolver.swift b/Sources/CodexBarCore/Providers/Codex/CodexOpenAIWorkspaceResolver.swift new file mode 100644 index 0000000..9f50276 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Codex/CodexOpenAIWorkspaceResolver.swift @@ -0,0 +1,123 @@ +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +public struct CodexOpenAIWorkspaceIdentity: Equatable, Sendable { + public let workspaceAccountID: String + public let workspaceLabel: String? + + public init(workspaceAccountID: String, workspaceLabel: String?) { + self.workspaceAccountID = Self.normalizeWorkspaceAccountID(workspaceAccountID) + self.workspaceLabel = Self.normalizeWorkspaceLabel(workspaceLabel) + } + + public static func normalizeWorkspaceAccountID(_ value: String) -> String { + value.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() + } + + public static func normalizeWorkspaceLabel(_ value: String?) -> String? { + guard let trimmed = value?.trimmingCharacters(in: .whitespacesAndNewlines), !trimmed.isEmpty else { + return nil + } + return trimmed + } +} + +public enum CodexOpenAIWorkspaceResolver { + private struct AccountsResponse: Decodable { + let items: [AccountItem] + } + + private struct AccountItem: Decodable { + let id: String + let name: String? + } + + private static let accountsURL = URL(string: "https://chatgpt.com/backend-api/accounts")! + + public static func resolve(credentials: CodexOAuthCredentials) async throws -> CodexOpenAIWorkspaceIdentity? { + try await self.resolve(credentials: credentials, session: CodexAuthenticatedHTTPTransport.current) + } + + public static func resolve( + credentials: CodexOAuthCredentials, + session transport: any ProviderHTTPTransport) async throws -> CodexOpenAIWorkspaceIdentity? + { + guard let workspaceAccountID = normalizeWorkspaceAccountID(credentials.accountId) else { + return nil + } + + let identities = try await self.listWorkspaces(credentials: credentials, session: transport) + if let identity = identities.first(where: { $0.workspaceAccountID == workspaceAccountID }) { + return identity + } + + return CodexOpenAIWorkspaceIdentity( + workspaceAccountID: workspaceAccountID, + workspaceLabel: nil) + } + + public static func listWorkspaces( + credentials: CodexOAuthCredentials) async throws -> [CodexOpenAIWorkspaceIdentity] + { + try await self.listWorkspaces(credentials: credentials, session: CodexAuthenticatedHTTPTransport.current) + } + + public static func listWorkspaces( + credentials: CodexOAuthCredentials, + session transport: any ProviderHTTPTransport) async throws -> [CodexOpenAIWorkspaceIdentity] + { + var request = URLRequest( + url: self.accountsURL, + cachePolicy: .reloadIgnoringLocalCacheData, + timeoutInterval: 20) + request.httpMethod = "GET" + request.setValue("Bearer \(credentials.accessToken)", forHTTPHeaderField: "Authorization") + request.setValue("codex-cli", forHTTPHeaderField: "User-Agent") + request.setValue("application/json", forHTTPHeaderField: "Accept") + if let workspaceAccountID = normalizeWorkspaceAccountID(credentials.accountId) { + request.setValue(workspaceAccountID, forHTTPHeaderField: "ChatGPT-Account-Id") + } + + let response = try await transport.response(for: request) + guard (200..<300).contains(response.statusCode) + else { + throw CodexOpenAIWorkspaceResolverError.invalidResponse + } + + let decoded = try JSONDecoder().decode(AccountsResponse.self, from: response.data) + return decoded.items.compactMap { account in + guard let workspaceAccountID = self.normalizeWorkspaceAccountID(account.id) else { return nil } + return CodexOpenAIWorkspaceIdentity( + workspaceAccountID: workspaceAccountID, + workspaceLabel: self.resolveWorkspaceLabel(from: account)) + } + } + + public static func normalizeWorkspaceAccountID(_ value: String?) -> String? { + guard let trimmed = value?.trimmingCharacters(in: .whitespacesAndNewlines), !trimmed.isEmpty else { + return nil + } + return trimmed.lowercased() + } + + private static func resolveWorkspaceLabel(from account: AccountItem) -> String? { + let name = account.name?.trimmingCharacters(in: .whitespacesAndNewlines) + if let name, !name.isEmpty { + return name + } + return "Personal" + } +} + +public enum CodexOpenAIWorkspaceResolverError: LocalizedError, Sendable { + case invalidResponse + + public var errorDescription: String? { + switch self { + case .invalidResponse: + "OpenAI account lookup returned an invalid response." + } + } +} diff --git a/Sources/CodexBarCore/Providers/Codex/CodexPlanFormatting.swift b/Sources/CodexBarCore/Providers/Codex/CodexPlanFormatting.swift new file mode 100644 index 0000000..af546a3 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Codex/CodexPlanFormatting.swift @@ -0,0 +1,59 @@ +import Foundation + +public enum CodexPlanFormatting { + private static let exactDisplayNames: [String: String] = [ + "pro": "Pro 20x", + "prolite": "Pro 5x", + "pro_lite": "Pro 5x", + "pro-lite": "Pro 5x", + "pro lite": "Pro 5x", + ] + + private static let uppercaseWords: Set = [ + "cbp", + "k12", + ] + + public static func displayName(_ raw: String?) -> String? { + guard let raw = raw?.trimmingCharacters(in: .whitespacesAndNewlines), !raw.isEmpty else { + return nil + } + + let lower = raw.lowercased() + if let exact = Self.exactDisplayNames[lower] { + return exact + } + + let cleaned = UsageFormatter.cleanPlanName(raw) + let candidate = cleaned.trimmingCharacters(in: .whitespacesAndNewlines) + guard !candidate.isEmpty else { return raw } + + if let exact = Self.exactDisplayNames[candidate.lowercased()] { + return exact + } + + let components = candidate + .split(whereSeparator: { $0 == "_" || $0 == "-" || $0.isWhitespace }) + .map(String.init) + .filter { !$0.isEmpty } + + guard !components.isEmpty else { return candidate } + + let formatted = components.map(Self.wordDisplayName).joined(separator: " ") + return formatted.isEmpty ? candidate : formatted + } + + private static func wordDisplayName(_ raw: String) -> String { + let lower = raw.lowercased() + if Self.uppercaseWords.contains(lower) { + return lower.uppercased() + } + if raw == raw.uppercased(), raw.contains(where: \.isLetter) { + return raw + } + if let first = raw.first, first.isLowercase { + return raw.prefix(1).uppercased() + raw.dropFirst() + } + return raw + } +} diff --git a/Sources/CodexBarCore/Providers/Codex/CodexProviderDescriptor.swift b/Sources/CodexBarCore/Providers/Codex/CodexProviderDescriptor.swift new file mode 100644 index 0000000..5a15ee1 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Codex/CodexProviderDescriptor.swift @@ -0,0 +1,454 @@ +import Foundation + +public enum CodexProviderDescriptor { + public static let descriptor: ProviderDescriptor = Self.makeDescriptor() + + static func makeDescriptor() -> ProviderDescriptor { + ProviderDescriptor( + id: .codex, + metadata: ProviderMetadata( + id: .codex, + displayName: "Codex", + sessionLabel: "Session", + weeklyLabel: "Weekly", + opusLabel: nil, + supportsOpus: false, + supportsCredits: true, + creditsHint: "Credits unavailable; keep Codex running to refresh.", + toggleTitle: "Show Codex usage", + cliName: "codex", + defaultEnabled: true, + isPrimaryProvider: true, + usesAccountFallback: true, + browserCookieOrder: ProviderBrowserCookieDefaults.codexCookieImportOrder + ?? ProviderBrowserCookieDefaults.defaultImportOrder, + dashboardURL: "https://chatgpt.com/codex/settings/usage", + changelogURL: "https://github.com/openai/codex/releases", + statusPageURL: "https://status.openai.com/"), + branding: ProviderBranding( + iconStyle: .codex, + iconResourceName: "ProviderIcon-codex", + color: ProviderColor(red: 73 / 255, green: 163 / 255, blue: 176 / 255)), + tokenCost: ProviderTokenCostConfig( + supportsTokenCost: true, + noDataMessage: self.noDataMessage), + fetchPlan: ProviderFetchPlan( + sourceModes: [.auto, .web, .cli, .oauth], + pipeline: ProviderFetchPipeline(resolveStrategies: self.resolveStrategies)), + cli: ProviderCLIConfig( + name: "codex", + versionDetector: { _ in ProviderVersionDetector.codexVersion() })) + } + + private static func resolveStrategies(context: ProviderFetchContext) async -> [any ProviderFetchStrategy] { + let cli = CodexCLIUsageStrategy() + let oauth = CodexOAuthFetchStrategy() + let web = CodexWebDashboardStrategy() + + switch context.runtime { + case .cli: + switch context.sourceMode { + case .oauth: + return [oauth] + case .web: + return [web] + case .cli: + return [cli] + case .api: + return [] + case .auto: + return [oauth, cli] + } + case .app: + switch context.sourceMode { + case .oauth: + return [oauth] + case .cli: + return [cli] + case .web: + return [web] + case .api: + return [] + case .auto: + return [oauth, cli] + } + } + } + + private static func noDataMessage() -> String { + self.noDataMessage(env: ProcessInfo.processInfo.environment) + } + + private static func noDataMessage(env: [String: String], fileManager: FileManager = .default) -> String { + let base = CodexHomeScope.ambientHomeURL(env: env, fileManager: fileManager).path + let sessions = "\(base)/sessions" + let archived = "\(base)/archived_sessions" + return "No Codex sessions found in \(sessions) or \(archived)." + } + + public static func resolveUsageStrategy( + selectedDataSource: CodexUsageDataSource, + hasOAuthCredentials: Bool) -> CodexUsageStrategy + { + if selectedDataSource == .auto { + if hasOAuthCredentials { + return CodexUsageStrategy(dataSource: .oauth) + } + return CodexUsageStrategy(dataSource: .cli) + } + return CodexUsageStrategy(dataSource: selectedDataSource) + } +} + +public struct CodexUsageStrategy: Equatable, Sendable { + public let dataSource: CodexUsageDataSource +} + +struct CodexCLIUsageStrategy: ProviderFetchStrategy { + let id: String = "codex.cli" + let kind: ProviderFetchKind = .cli + + func isAvailable(_ context: ProviderFetchContext) async -> Bool { + Self.resolvedBinary(env: context.env) != nil + } + + func fetch(_ context: ProviderFetchContext) async throws -> ProviderFetchResult { + let snapshot = try await context.fetcher.loadLatestCLIAccountSnapshot() + guard let usage = snapshot.usage else { + guard context.includeCredits, let credits = snapshot.credits else { + throw UsageError.noRateLimitsFound + } + // Credits refresh can succeed even when RPC omits rate-limit windows. + return self.makeResult( + usage: UsageSnapshot( + primary: nil, + secondary: nil, + updatedAt: credits.updatedAt, + identity: snapshot.identity), + credits: credits, + sourceLabel: "codex-cli") + } + let credits = context.includeCredits ? snapshot.credits : nil + return self.makeResult( + usage: usage, + credits: credits, + sourceLabel: "codex-cli") + } + + func shouldFallback(on _: Error, context _: ProviderFetchContext) -> Bool { + false + } + + static func resolvedBinary( + env: [String: String], + loginPATH: [String]? = LoginShellPathCache.shared.current, + commandV: (String, String?, TimeInterval, FileManager) -> String? = ShellCommandLocator.commandV, + aliasResolver: (String, String?, TimeInterval, FileManager, String) -> String? = ShellCommandLocator + .resolveAlias, + fileManager: FileManager = .default, + home: String = NSHomeDirectory()) -> String? + { + BinaryLocator.resolveCodexBinary( + env: env, + loginPATH: loginPATH, + commandV: commandV, + aliasResolver: aliasResolver, + fileManager: fileManager, + home: home) + } +} + +struct CodexOAuthFetchStrategy: ProviderFetchStrategy { + let id: String = "codex.oauth" + let kind: ProviderFetchKind = .oauth + + func isAvailable(_ context: ProviderFetchContext) async -> Bool { + (try? CodexOAuthCredentialsStore.load(env: context.env)) != nil + } + + func fetch(_ context: ProviderFetchContext) async throws -> ProviderFetchResult { + var credentials = try CodexOAuthCredentialsStore.load(env: context.env) + + if credentials.needsRefresh, !credentials.refreshToken.isEmpty { + credentials = try await CodexTokenRefresher.refresh(credentials) + try CodexOAuthCredentialsStore.save(credentials, env: context.env) + } + + let usage = try await CodexOAuthUsageFetcher.fetchUsage( + accessToken: credentials.accessToken, + accountId: credentials.accountId, + env: context.env) + let resetCredits = try await Self.fetchResetCreditsIfRequested( + context: context, + credentials: credentials) + let updatedAt = Date() + let oauthResult = try Self.makeResult( + usageResponse: usage, + resetCredits: resetCredits, + credentials: credentials, + updatedAt: updatedAt, + allowEmptyUsageForResetCreditEnrichment: Self.defersResetCreditFetchToApp(context)) + return try await Self.replacingWithCLIMonthlyLimitIfAvailable(oauthResult, context: context) + } + + private static func shouldFetchResetCredits(_ context: ProviderFetchContext) -> Bool { + guard case .cli = context.runtime else { return false } + return context.includeCredits + } + + func shouldFallback(on error: Error, context: ProviderFetchContext) -> Bool { + guard context.sourceMode == .auto else { return false } + // Auto mode may launch the CLI as the next strategy. Keep that fallback + // limited to OAuth states the CLI can actually repair, otherwise + // transient API or decode failures can spawn `codex app-server` + // repeatedly instead of surfacing the original OAuth failure. + if let fetchError = error as? CodexOAuthFetchError { + switch fetchError { + case .unauthorized: + return true + case .invalidResponse, .serverError, .networkError: + return false + } + } + if let credentialsError = error as? CodexOAuthCredentialsError { + switch credentialsError { + case .notFound, .missingTokens: + return true + case .decodeFailed: + return false + } + } + switch error as? CodexTokenRefresher.RefreshError { + case .expired, .revoked, .reused: + return true + case .networkError, .invalidResponse, .none: + return false + } + } + + private static func mapCredits( + response: CodexUsageResponse, + updatedAt: Date) -> CreditsSnapshot? + { + let balance = response.credits?.balance + let creditLimit = (response.individualLimit ?? response.rateLimit?.individualLimit)? + .codexCreditLimitSnapshot(updatedAt: updatedAt) + guard balance != nil || creditLimit != nil else { return nil } + return CreditsSnapshot( + remaining: balance ?? 0, + events: [], + updatedAt: updatedAt, + codexCreditLimit: creditLimit) + } + + private static func makeResult( + usageResponse: CodexUsageResponse, + resetCredits: CodexRateLimitResetCreditsSnapshot? = nil, + credentials: CodexOAuthCredentials, + updatedAt: Date, + allowEmptyUsageForResetCreditEnrichment: Bool = false) throws -> ProviderFetchResult + { + let credits = Self.mapCredits(response: usageResponse, updatedAt: updatedAt) + let reconciled = CodexReconciledState.fromOAuth( + response: usageResponse, + credentials: credentials, + updatedAt: updatedAt) + + if let reconciled { + let dataConfidence: UsageDataConfidence = usageResponse.rateLimit?.hasWindowDecodeFailure == true + || usageResponse.additionalRateLimitsDecodeFailed + ? .unknown + : .exact + return CodexOAuthFetchStrategy().makeResult( + usage: reconciled.toUsageSnapshot() + .withCodexResetCredits(resetCredits) + .withDataConfidence(dataConfidence), + credits: credits, + sourceLabel: "oauth") + } + + guard credits != nil + || (resetCredits?.availableInventory(at: updatedAt).count ?? 0) > 0 + || allowEmptyUsageForResetCreditEnrichment + else { + throw UsageError.noRateLimitsFound + } + + // Credit balances and manual resets remain useful when OAuth omits + // rate-limit windows. Keep the partial result instead of discarding it. + return CodexOAuthFetchStrategy().makeResult( + usage: UsageSnapshot( + primary: nil, + secondary: nil, + tertiary: nil, + codexResetCredits: resetCredits, + updatedAt: updatedAt, + identity: CodexReconciledState.oauthIdentity( + response: usageResponse, + credentials: credentials)), + credits: credits, + sourceLabel: "oauth") + } + + private static func replacingWithCLIMonthlyLimitIfAvailable( + _ oauthResult: ProviderFetchResult, + context: ProviderFetchContext, + cliStrategy: any ProviderFetchStrategy = CodexCLIUsageStrategy()) async throws -> ProviderFetchResult + { + guard context.sourceMode == .auto, + context.includeCredits, + self.shouldTryCLIForMonthlyLimit(oauthResult) + else { return oauthResult } + guard await cliStrategy.isAvailable(context) else { return oauthResult } + let cliResult: ProviderFetchResult + do { + cliResult = try await cliStrategy.fetch(context) + } catch { + if error is CancellationError { throw error } + return oauthResult + } + guard let cliLimit = cliResult.credits?.codexCreditLimit, + self.identitiesAreCompatible(oauth: oauthResult.usage.identity, cli: cliResult.usage.identity), + let oauthCredits = oauthResult.credits + else { return oauthResult } + return ProviderFetchResult( + usage: oauthResult.usage, + credits: CreditsSnapshot( + remaining: oauthCredits.remaining, + events: oauthCredits.events, + updatedAt: oauthCredits.updatedAt, + codexCreditLimit: cliLimit), + dashboard: oauthResult.dashboard, + sourceLabel: oauthResult.sourceLabel, + strategyID: oauthResult.strategyID, + strategyKind: oauthResult.strategyKind) + } + + private static func fetchResetCreditsIfRequested( + context: ProviderFetchContext, + credentials: CodexOAuthCredentials) async throws -> CodexRateLimitResetCreditsSnapshot? + { + try await self.fetchResetCreditsIfRequested( + context: context, + credentials: credentials, + fetcher: { credentials in + try await CodexOAuthUsageFetcher.fetchRateLimitResetCredits( + accessToken: credentials.accessToken, + accountId: credentials.accountId, + env: context.env) + }) + } + + private static func defersResetCreditFetchToApp(_ context: ProviderFetchContext) -> Bool { + if case .app = context.runtime { return true } + return false + } + + private static func fetchResetCreditsIfRequested( + context: ProviderFetchContext, + credentials: CodexOAuthCredentials, + fetcher: @escaping @Sendable (CodexOAuthCredentials) async throws + -> CodexRateLimitResetCreditsSnapshot) async throws -> CodexRateLimitResetCreditsSnapshot? + { + guard self.shouldFetchResetCredits(context) else { return nil } + // The app enriches the winning outcome once in UsageStore. One-shot CLI callers do not + // pass through that app layer, so only their explicit credits flag reaches this request. + do { + return try await fetcher(credentials) + } catch { + if error is CancellationError || Task.isCancelled { throw CancellationError() } + return nil + } + } + + private static func identitiesAreCompatible( + oauth: ProviderIdentitySnapshot?, + cli: ProviderIdentitySnapshot?) -> Bool + { + guard let cliEmail = self.normalizedEmail(cli?.accountEmail), + let oauthEmail = self.normalizedEmail(oauth?.accountEmail) + else { return false } + return cliEmail == oauthEmail + } + + private static func normalizedEmail(_ email: String?) -> String? { + guard let normalized = email?.trimmingCharacters(in: .whitespacesAndNewlines).lowercased(), + !normalized.isEmpty + else { return nil } + return normalized + } + + private static func shouldTryCLIForMonthlyLimit(_ result: ProviderFetchResult) -> Bool { + guard let credits = result.credits else { return false } + return credits.remaining == 0 + && credits.codexCreditLimit == nil + && (result.usage.codexResetCredits?.availableInventory(at: result.usage.updatedAt).count ?? 0) == 0 + } +} + +#if DEBUG +extension CodexOAuthFetchStrategy { + static func _fetchResetCreditsForTesting( + context: ProviderFetchContext, + credentials: CodexOAuthCredentials, + fetcher: @escaping @Sendable (CodexOAuthCredentials) async throws + -> CodexRateLimitResetCreditsSnapshot) async throws -> CodexRateLimitResetCreditsSnapshot? + { + try await self.fetchResetCreditsIfRequested( + context: context, + credentials: credentials, + fetcher: fetcher) + } + + static func _shouldFetchResetCreditsForTesting(_ context: ProviderFetchContext) -> Bool { + self.shouldFetchResetCredits(context) + } +} +#endif + +#if DEBUG +extension CodexOAuthFetchStrategy { + static func _mapUsageForTesting(_ data: Data, credentials: CodexOAuthCredentials) throws -> UsageSnapshot? { + let usage = try JSONDecoder().decode(CodexUsageResponse.self, from: data) + return CodexReconciledState.fromOAuth(response: usage, credentials: credentials)?.toUsageSnapshot() + } + + static func _mapResultForTesting( + _ data: Data, + credentials: CodexOAuthCredentials, + resetCredits: CodexRateLimitResetCreditsSnapshot? = nil, + sourceMode: ProviderSourceMode = .oauth, + allowEmptyUsageForResetCreditEnrichment: Bool = false) throws -> ProviderFetchResult + { + let usageResponse = try JSONDecoder().decode(CodexUsageResponse.self, from: data) + _ = sourceMode + return try Self.makeResult( + usageResponse: usageResponse, + resetCredits: resetCredits, + credentials: credentials, + updatedAt: Date(), + allowEmptyUsageForResetCreditEnrichment: allowEmptyUsageForResetCreditEnrichment) + } + + static func _replaceWithCLIMonthlyLimitForTesting( + oauthResult: ProviderFetchResult, + context: ProviderFetchContext, + cliStrategy: any ProviderFetchStrategy) async throws -> ProviderFetchResult + { + try await self.replacingWithCLIMonthlyLimitIfAvailable( + oauthResult, + context: context, + cliStrategy: cliStrategy) + } + + static func _shouldTryCLIForMonthlyLimitForTesting(_ result: ProviderFetchResult) -> Bool { + self.shouldTryCLIForMonthlyLimit(result) + } +} + +extension CodexProviderDescriptor { + static func _noDataMessageForTesting(env: [String: String]) -> String { + self.noDataMessage(env: env) + } +} +#endif diff --git a/Sources/CodexBarCore/Providers/Codex/CodexProviderSettingsBuilder.swift b/Sources/CodexBarCore/Providers/Codex/CodexProviderSettingsBuilder.swift new file mode 100644 index 0000000..62de155 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Codex/CodexProviderSettingsBuilder.swift @@ -0,0 +1,93 @@ +import Foundation + +public struct CodexProviderSettingsBuilderInput: Sendable { + public let usageDataSource: CodexUsageDataSource + public let cookieSource: ProviderCookieSource + public let manualCookieHeader: String? + public let reconciliationSnapshot: CodexAccountReconciliationSnapshot + public let resolvedActiveSource: CodexResolvedActiveSource + + public init( + usageDataSource: CodexUsageDataSource, + cookieSource: ProviderCookieSource, + manualCookieHeader: String?, + reconciliationSnapshot: CodexAccountReconciliationSnapshot, + resolvedActiveSource: CodexResolvedActiveSource) + { + self.usageDataSource = usageDataSource + self.cookieSource = cookieSource + self.manualCookieHeader = manualCookieHeader + self.reconciliationSnapshot = reconciliationSnapshot + self.resolvedActiveSource = resolvedActiveSource + } +} + +public enum CodexKnownOwnerCatalog { + public static func candidates( + from snapshot: CodexAccountReconciliationSnapshot) -> [CodexDashboardKnownOwnerCandidate] + { + var candidates = snapshot.storedAccounts.map { account in + CodexDashboardKnownOwnerCandidate( + identity: snapshot.runtimeIdentity(for: account), + normalizedEmail: CodexIdentityResolver.normalizeEmail(snapshot.runtimeEmail(for: account))) + } + + if let liveSystemAccount = snapshot.liveSystemAccount { + candidates.append(CodexDashboardKnownOwnerCandidate( + identity: snapshot.runtimeIdentity(for: liveSystemAccount), + normalizedEmail: CodexIdentityResolver.normalizeEmail(liveSystemAccount.email))) + } + + for profileAccount in snapshot.profileHomeAccounts { + candidates.append(CodexDashboardKnownOwnerCandidate( + identity: snapshot.runtimeIdentity(for: profileAccount), + normalizedEmail: CodexIdentityResolver.normalizeEmail(profileAccount.email), + sourceIsolationIdentifier: CookieHeaderCache.Scope.profileHome(profileAccount.codexHomePath) + .isolationIdentifier)) + } + + return candidates + } +} + +public enum CodexProviderSettingsBuilder { + public static func make(input: CodexProviderSettingsBuilderInput) -> ProviderSettingsSnapshot + .CodexProviderSettings { + let snapshot = input.reconciliationSnapshot + let persistedSource = input.resolvedActiveSource.persistedSource + let managedSourceSelected = switch persistedSource { + case .liveSystem: + false + case .managedAccount: + true + case .profileHome: + false + } + let openAIWebCacheScope: CookieHeaderCache.Scope? = switch input.resolvedActiveSource.resolvedSource { + case .liveSystem: + nil + case let .managedAccount(id): + .managedAccount(id) + case let .profileHome(path): + .profileHome(path) + } + let profileAccountTargetUnavailable = switch input.resolvedActiveSource.resolvedSource { + case .liveSystem, .managedAccount: + false + case let .profileHome(path): + snapshot.profileHomeAccount(path: path) == nil + } + + return ProviderSettingsSnapshot.CodexProviderSettings( + usageDataSource: input.usageDataSource, + cookieSource: input.cookieSource, + manualCookieHeader: input.manualCookieHeader, + managedAccountStoreUnreadable: managedSourceSelected && snapshot.hasUnreadableAddedAccountStore, + managedAccountTargetUnavailable: managedSourceSelected + && snapshot.hasUnreadableAddedAccountStore == false + && snapshot.activeStoredAccount == nil, + profileAccountTargetUnavailable: profileAccountTargetUnavailable, + openAIWebCacheScope: openAIWebCacheScope, + dashboardAuthorityKnownOwners: CodexKnownOwnerCatalog.candidates(from: snapshot)) + } +} diff --git a/Sources/CodexBarCore/Providers/Codex/CodexRateWindowNormalizer.swift b/Sources/CodexBarCore/Providers/Codex/CodexRateWindowNormalizer.swift new file mode 100644 index 0000000..018100e --- /dev/null +++ b/Sources/CodexBarCore/Providers/Codex/CodexRateWindowNormalizer.swift @@ -0,0 +1,66 @@ +import Foundation + +enum CodexRateWindowNormalizer { + static func normalize( + primary: RateWindow?, + secondary: RateWindow?) + -> (primary: RateWindow?, secondary: RateWindow?) + { + switch (primary, secondary) { + case let (.some(primaryWindow), .some(secondaryWindow)): + switch (self.role(for: primaryWindow), self.role(for: secondaryWindow)) { + case (.session, .weekly), (.session, .unknown), (.unknown, .weekly): + (primaryWindow, secondaryWindow) + case (.weekly, .session), (.weekly, .unknown): + (secondaryWindow, primaryWindow) + default: + (primaryWindow, secondaryWindow) + } + case let (.some(primaryWindow), .none): + switch role(for: primaryWindow) { + case .weekly: + (nil, primaryWindow) + case .session, .unknown: + (primaryWindow, nil) + } + case let (.none, .some(secondaryWindow)): + switch self.role(for: secondaryWindow) { + case .session, .unknown: + (secondaryWindow, nil) + case .weekly: + (nil, secondaryWindow) + } + case (.none, .none): + (nil, nil) + } + } + + private enum WindowRole { + case session + case weekly + case unknown + } + + private static func role(for window: RateWindow) -> WindowRole { + switch window.windowMinutes { + case 300: + .session + case 10080: + .weekly + default: + .unknown + } + } +} + +#if DEBUG +extension CodexRateWindowNormalizer { + static func _normalizeForTesting( + primary: RateWindow?, + secondary: RateWindow?) + -> (primary: RateWindow?, secondary: RateWindow?) + { + self.normalize(primary: primary, secondary: secondary) + } +} +#endif diff --git a/Sources/CodexBarCore/Providers/Codex/CodexReconciledState.swift b/Sources/CodexBarCore/Providers/Codex/CodexReconciledState.swift new file mode 100644 index 0000000..83f8f28 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Codex/CodexReconciledState.swift @@ -0,0 +1,149 @@ +import Foundation + +public struct CodexReconciledState: Sendable { + public let session: RateWindow? + public let weekly: RateWindow? + /// Named model-specific limits (e.g. Codex Spark) surfaced through `UsageSnapshot.extraRateWindows`. + public let extraRateWindows: [NamedRateWindow] + public let identity: ProviderIdentitySnapshot? + public let updatedAt: Date + + public init( + session: RateWindow?, + weekly: RateWindow?, + extraRateWindows: [NamedRateWindow] = [], + identity: ProviderIdentitySnapshot?, + updatedAt: Date) + { + self.session = session + self.weekly = weekly + self.extraRateWindows = extraRateWindows + self.identity = identity + self.updatedAt = updatedAt + } + + public static func fromCLI( + primary: RateWindow?, + secondary: RateWindow?, + identity: ProviderIdentitySnapshot?, + updatedAt: Date = Date()) -> CodexReconciledState? + { + self.make(primary: primary, secondary: secondary, identity: identity, updatedAt: updatedAt) + } + + public static func fromOAuth( + response: CodexUsageResponse, + credentials: CodexOAuthCredentials, + updatedAt: Date = Date()) -> CodexReconciledState? + { + self.make( + primary: self.makeWindow(response.rateLimit?.primaryWindow), + secondary: self.makeWindow(response.rateLimit?.secondaryWindow), + extraRateWindows: CodexAdditionalRateLimitMapper.extraRateWindows( + from: response.additionalRateLimits, + now: updatedAt), + identity: self.oauthIdentity(response: response, credentials: credentials), + updatedAt: updatedAt) + } + + public static func fromAttachedDashboard( + snapshot: OpenAIDashboardSnapshot, + provider: UsageProvider = .codex, + accountEmail: String? = nil, + accountPlan: String? = nil) -> CodexReconciledState? + { + let resolvedEmail = accountEmail ?? snapshot.signedInEmail + let resolvedPlan = accountPlan ?? snapshot.accountPlan + let identity = ProviderIdentitySnapshot( + providerID: provider, + accountEmail: resolvedEmail, + accountOrganization: nil, + loginMethod: resolvedPlan) + + return self.make( + primary: snapshot.primaryLimit, + secondary: snapshot.secondaryLimit, + extraRateWindows: snapshot.extraRateWindows ?? [], + identity: identity, + updatedAt: snapshot.updatedAt) + } + + public func toUsageSnapshot() -> UsageSnapshot { + UsageSnapshot( + primary: self.session, + secondary: self.weekly, + tertiary: nil, + extraRateWindows: self.extraRateWindows.isEmpty ? nil : self.extraRateWindows, + updatedAt: self.updatedAt, + identity: self.identity) + } + + public static func oauthIdentity( + response: CodexUsageResponse, + credentials: CodexOAuthCredentials) -> ProviderIdentitySnapshot + { + ProviderIdentitySnapshot( + providerID: .codex, + accountEmail: self.resolveAccountEmail(from: credentials), + accountOrganization: nil, + loginMethod: self.resolvePlan(response: response, credentials: credentials)) + } + + private static func make( + primary: RateWindow?, + secondary: RateWindow?, + extraRateWindows: [NamedRateWindow] = [], + identity: ProviderIdentitySnapshot?, + updatedAt: Date) -> CodexReconciledState? + { + let normalized = CodexRateWindowNormalizer.normalize(primary: primary, secondary: secondary) + // Extra windows are supplemental, so they never resurrect a snapshot on their own: keep the + // existing primary/weekly gate to preserve current behavior when only extra limits are present. + guard normalized.primary != nil || normalized.secondary != nil else { + return nil + } + + return CodexReconciledState( + session: normalized.primary, + weekly: normalized.secondary, + extraRateWindows: extraRateWindows, + identity: identity, + updatedAt: updatedAt) + } + + private static func makeWindow(_ window: CodexUsageResponse.WindowSnapshot?) -> RateWindow? { + guard let window else { return nil } + let resetDate = Date(timeIntervalSince1970: TimeInterval(window.resetAt)) + let resetDescription = UsageFormatter.resetDescription(from: resetDate) + return RateWindow( + usedPercent: Double(window.usedPercent), + windowMinutes: window.limitWindowSeconds / 60, + resetsAt: resetDate, + resetDescription: resetDescription) + } + + private static func resolveAccountEmail(from credentials: CodexOAuthCredentials) -> String? { + guard let idToken = credentials.idToken, + let payload = UsageFetcher.parseJWT(idToken) + else { + return nil + } + + let profileDict = payload["https://api.openai.com/profile"] as? [String: Any] + let email = (payload["email"] as? String) ?? (profileDict?["email"] as? String) + return email?.trimmingCharacters(in: .whitespacesAndNewlines) + } + + private static func resolvePlan(response: CodexUsageResponse, credentials: CodexOAuthCredentials) -> String? { + if let plan = response.planType?.rawValue, !plan.isEmpty { return plan } + guard let idToken = credentials.idToken, + let payload = UsageFetcher.parseJWT(idToken) + else { + return nil + } + + let authDict = payload["https://api.openai.com/auth"] as? [String: Any] + let plan = (authDict?["chatgpt_plan_type"] as? String) ?? (payload["chatgpt_plan_type"] as? String) + return plan?.trimmingCharacters(in: .whitespacesAndNewlines) + } +} diff --git a/Sources/CodexBarCore/Providers/Codex/CodexSpendControlLimitMapping.swift b/Sources/CodexBarCore/Providers/Codex/CodexSpendControlLimitMapping.swift new file mode 100644 index 0000000..39415da --- /dev/null +++ b/Sources/CodexBarCore/Providers/Codex/CodexSpendControlLimitMapping.swift @@ -0,0 +1,25 @@ +import Foundation + +extension CodexUsageResponse.SpendControlLimitSnapshot { + func codexCreditLimitSnapshot(updatedAt: Date) -> CodexCreditLimitSnapshot? { + guard let limit, limit > 0 else { return nil } + let used: Double = if let used { + used + } else if let remainingPercent { + limit * max(0, min(100, 100 - remainingPercent)) / 100 + } else { + 0 + } + let remainingPercent = self.remainingPercent ?? max(0, min(100, 100 - (used / limit * 100))) + let resetsAt = self.resetsAt.flatMap { value -> Date? in + guard value > 0 else { return nil } + return Date(timeIntervalSince1970: TimeInterval(value)) + } + return CodexCreditLimitSnapshot( + used: used, + limit: limit, + remainingPercent: remainingPercent, + resetsAt: resetsAt, + updatedAt: updatedAt) + } +} diff --git a/Sources/CodexBarCore/Providers/Codex/CodexStatusProbe.swift b/Sources/CodexBarCore/Providers/Codex/CodexStatusProbe.swift new file mode 100644 index 0000000..a3cb8ee --- /dev/null +++ b/Sources/CodexBarCore/Providers/Codex/CodexStatusProbe.swift @@ -0,0 +1,294 @@ +import Foundation + +public struct CodexStatusSnapshot: Sendable { + public let credits: Double? + public let fiveHourPercentLeft: Int? + public let weeklyPercentLeft: Int? + public let fiveHourResetDescription: String? + public let weeklyResetDescription: String? + public let fiveHourResetsAt: Date? + public let weeklyResetsAt: Date? + public let codexCreditLimit: CodexCreditLimitSnapshot? + public let rawText: String + + public init( + credits: Double?, + fiveHourPercentLeft: Int?, + weeklyPercentLeft: Int?, + fiveHourResetDescription: String?, + weeklyResetDescription: String?, + fiveHourResetsAt: Date?, + weeklyResetsAt: Date?, + codexCreditLimit: CodexCreditLimitSnapshot? = nil, + rawText: String) + { + self.credits = credits + self.fiveHourPercentLeft = fiveHourPercentLeft + self.weeklyPercentLeft = weeklyPercentLeft + self.fiveHourResetDescription = fiveHourResetDescription + self.weeklyResetDescription = weeklyResetDescription + self.fiveHourResetsAt = fiveHourResetsAt + self.weeklyResetsAt = weeklyResetsAt + self.codexCreditLimit = codexCreditLimit + self.rawText = rawText + } +} + +public enum CodexStatusProbeError: LocalizedError, Sendable { + case codexNotInstalled + case launchBlocked(String) + case parseFailed(String) + case timedOut + case updateRequired(String) + + public var errorDescription: String? { + switch self { + case .codexNotInstalled: + "Codex CLI missing. Install via `npm i -g @openai/codex` (or bun install) and restart." + case let .launchBlocked(message): + message + case .parseFailed: + "Could not parse Codex status; will retry shortly." + case .timedOut: + "Codex status probe timed out." + case let .updateRequired(msg): + "Codex CLI update needed: \(msg)" + } + } +} + +/// Runs `codex` inside a PTY, sends `/status`, captures text, and parses credits/limits. +public struct CodexStatusProbe { + private static let defaultTimeoutSeconds: TimeInterval = 8.0 + private static let parseRetryTimeoutSeconds: TimeInterval = 4.0 + + public var codexBinary: String = "codex" + public var timeout: TimeInterval = Self.defaultTimeoutSeconds + public var keepCLISessionsAlive: Bool = false + public var environment: [String: String] = ProcessInfo.processInfo.environment + + public init() {} + + public init( + codexBinary: String = "codex", + timeout: TimeInterval = 8.0, + keepCLISessionsAlive: Bool = false, + environment: [String: String] = ProcessInfo.processInfo.environment) + { + self.codexBinary = codexBinary + self.timeout = timeout + self.keepCLISessionsAlive = keepCLISessionsAlive + self.environment = environment + } + + public func fetch() async throws -> CodexStatusSnapshot { + let env = self.environment + let resolved = BinaryLocator.resolveCodexBinary(env: env, loginPATH: LoginShellPathCache.shared.current) + ?? self.codexBinary + guard FileManager.default.isExecutableFile(atPath: resolved) || TTYCommandRunner.which(resolved) != nil else { + throw CodexStatusProbeError.codexNotInstalled + } + if let message = CodexCLILaunchGate.shared.backgroundSkipMessage(binary: resolved) { + throw CodexStatusProbeError.launchBlocked(message) + } + do { + return try await self.runAndParse(binary: resolved, rows: 60, cols: 200, timeout: self.timeout) + } catch let error as CodexStatusProbeError { + // Retry only parser-level flakes with a short second attempt. + switch error { + case .parseFailed: + return try await self.runAndParse( + binary: resolved, + rows: 70, + cols: 220, + timeout: Self.parseRetryTimeoutSeconds) + default: + throw error + } + } catch { + throw error + } + } + + // MARK: - Parsing + + public static func parse(text: String, now: Date = .init()) throws -> CodexStatusSnapshot { + let clean = TextParsing.stripANSICodes(text) + guard !clean.isEmpty else { throw CodexStatusProbeError.timedOut } + if clean.localizedCaseInsensitiveContains("data not available yet") { + throw CodexStatusProbeError.parseFailed("data not available yet") + } + if self.containsUpdatePrompt(clean) { + throw CodexStatusProbeError.updateRequired( + "Run `bun install -g @openai/codex` to continue (update prompt blocking /status).") + } + let credits = TextParsing.firstNumber(pattern: #"Credits:\s*([0-9][0-9.,]*)"#, text: clean) + // Pull reset info from the same lines that contain the percentages. + let fiveLine = TextParsing.firstLine(matching: #"5h limit[^\n]*"#, text: clean) + let weekLine = TextParsing.firstLine(matching: #"Weekly limit[^\n]*"#, text: clean) + let fivePct = fiveLine.flatMap(TextParsing.percentLeft(fromLine:)) + let weekPct = weekLine.flatMap(TextParsing.percentLeft(fromLine:)) + let fiveReset = fiveLine.flatMap(TextParsing.resetString(fromLine:)) + let weekReset = weekLine.flatMap(TextParsing.resetString(fromLine:)) + let monthlyLimit = self.parseMonthlyCreditLimit(text: clean, now: now) + if credits == nil, fivePct == nil, weekPct == nil, monthlyLimit == nil { + throw CodexStatusProbeError.parseFailed(clean.prefix(400).description) + } + return CodexStatusSnapshot( + credits: credits, + fiveHourPercentLeft: fivePct, + weeklyPercentLeft: weekPct, + fiveHourResetDescription: fiveReset, + weeklyResetDescription: weekReset, + fiveHourResetsAt: self.parseResetDate(from: fiveReset, now: now), + weeklyResetsAt: self.parseResetDate(from: weekReset, now: now), + codexCreditLimit: monthlyLimit, + rawText: clean) + } + + private static func parseMonthlyCreditLimit(text: String, now: Date) -> CodexCreditLimitSnapshot? { + guard let monthlyLine = TextParsing.firstLine(matching: #"Monthly credit limit[^\n]*"#, text: text) else { + return nil + } + guard let limit = TextParsing.firstNumber( + pattern: #"of\s+([0-9][0-9., ]*)\s+credits used"#, + text: text), + limit > 0 + else { + return nil + } + let used = TextParsing.firstNumber( + pattern: #"([0-9][0-9., ]*)\s+of\s+[0-9][0-9., ]*\s+credits used"#, + text: text) ?? 0 + let remainingPercent = TextParsing.percentLeft(fromLine: monthlyLine) + .map(Double.init) + ?? max(0, min(100, 100 - (used / limit * 100))) + let resetText = TextParsing.resetString(fromLine: monthlyLine) + return CodexCreditLimitSnapshot( + used: used, + limit: limit, + remainingPercent: remainingPercent, + resetsAt: self.parseResetDate(from: resetText, now: now), + updatedAt: now) + } + + private static func parseResetDate(from text: String?, now: Date) -> Date? { + guard var raw = text?.trimmingCharacters(in: .whitespacesAndNewlines), !raw.isEmpty else { return nil } + raw = raw.trimmingCharacters(in: CharacterSet(charactersIn: "()")) + raw = raw.replacingOccurrences(of: #"\s+"#, with: " ", options: .regularExpression) + .trimmingCharacters(in: .whitespacesAndNewlines) + + let calendar = Calendar(identifier: .gregorian) + let formatter = DateFormatter() + formatter.locale = Locale(identifier: "en_US_POSIX") + formatter.timeZone = TimeZone.current + formatter.defaultDate = now + + if let match = raw.firstMatch(of: /^([0-9]{1,2}:[0-9]{2}) on ([0-9]{1,2} [A-Za-z]{3})$/) { + raw = "\(match.output.2) \(match.output.1)" + formatter.dateFormat = "d MMM HH:mm" + if let date = formatter.date(from: raw) { + return self.bumpYearIfNeeded(date, now: now, calendar: calendar) + } + } + + if let match = raw.firstMatch(of: /^([0-9]{1,2}:[0-9]{2}) on ([A-Za-z]{3} [0-9]{1,2})$/) { + raw = "\(match.output.2) \(match.output.1)" + formatter.dateFormat = "MMM d HH:mm" + if let date = formatter.date(from: raw) { + return self.bumpYearIfNeeded(date, now: now, calendar: calendar) + } + } + + for format in ["HH:mm", "H:mm"] { + formatter.dateFormat = format + if let time = formatter.date(from: raw) { + let components = calendar.dateComponents([.hour, .minute], from: time) + guard let anchored = calendar.date( + bySettingHour: components.hour ?? 0, + minute: components.minute ?? 0, + second: 0, + of: now) + else { + return nil + } + if anchored >= now { + return anchored + } + return calendar.date(byAdding: .day, value: 1, to: anchored) + } + } + + return nil + } + + private static func bumpYearIfNeeded(_ date: Date, now: Date, calendar: Calendar) -> Date? { + if date >= now { + return date + } + return calendar.date(byAdding: .year, value: 1, to: date) + } + + private func runAndParse( + binary: String, + rows: UInt16, + cols: UInt16, + timeout: TimeInterval) async throws -> CodexStatusSnapshot + { + let stateHome = try CodexStatusProbeIsolation.supportDirectory(environment: self.environment) + let extraArgs = CodexStatusProbeIsolation.codexArguments(stateHome: stateHome) + let workingDirectory = CodexStatusProbeIsolation.workingDirectory(environment: self.environment) + let text: String + if self.keepCLISessionsAlive { + do { + text = try await CodexCLISession.shared.captureStatus( + binary: binary, + options: .init( + timeout: timeout, + rows: rows, + cols: cols, + environment: self.environment, + extraArgs: extraArgs, + workingDirectory: workingDirectory)) + } catch CodexCLISession.SessionError.processExited { + throw CodexStatusProbeError.timedOut + } catch CodexCLISession.SessionError.timedOut { + throw CodexStatusProbeError.timedOut + } catch let CodexCLISession.SessionError.launchFailed(message) { + if let throttled = CodexCLILaunchGate.shared.recordLaunchFailure(binary: binary, message: message) { + throw CodexStatusProbeError.launchBlocked(throttled) + } + throw CodexStatusProbeError.codexNotInstalled + } + } else { + let runner = TTYCommandRunner() + let script = "/status" + let result: TTYCommandRunner.Result + do { + result = try runner.run( + binary: binary, + send: script, + options: .init( + rows: rows, + cols: cols, + timeout: timeout, + workingDirectory: workingDirectory, + extraArgs: extraArgs, + baseEnvironment: self.environment, + forceCodexStatusMode: true)) + } catch let TTYCommandRunner.Error.launchFailed(message) { + if let throttled = CodexCLILaunchGate.shared.recordLaunchFailure(binary: binary, message: message) { + throw CodexStatusProbeError.launchBlocked(throttled) + } + throw CodexStatusProbeError.codexNotInstalled + } + text = result.text + } + return try Self.parse(text: text) + } + + private static func containsUpdatePrompt(_ text: String) -> Bool { + let lower = text.lowercased() + return lower.contains("update available") && lower.contains("codex") + } +} diff --git a/Sources/CodexBarCore/Providers/Codex/CodexStatusProbeIsolation.swift b/Sources/CodexBarCore/Providers/Codex/CodexStatusProbeIsolation.swift new file mode 100644 index 0000000..2401122 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Codex/CodexStatusProbeIsolation.swift @@ -0,0 +1,46 @@ +import Foundation + +enum CodexStatusProbeIsolation { + static func supportDirectory(environment: [String: String]) throws -> URL { + let baseURL: URL = if let tmp = environment["TMPDIR"]?.trimmingCharacters(in: .whitespacesAndNewlines), + !tmp.isEmpty + { + URL(fileURLWithPath: tmp, isDirectory: true) + } else { + FileManager.default.temporaryDirectory + } + + let directory = baseURL + .appendingPathComponent("CodexBar", isDirectory: true) + .appendingPathComponent("CodexStatusProbe", isDirectory: true) + try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true) + return directory + } + + static func workingDirectory(environment: [String: String]) -> URL? { + let home = environment["HOME"]?.trimmingCharacters(in: .whitespacesAndNewlines) + guard let home, !home.isEmpty else { return nil } + return URL(fileURLWithPath: home, isDirectory: true) + } + + static func codexArguments(stateHome: URL) -> [String] { + [ + "-s", + "read-only", + "-a", + "untrusted", + "-c", + "history.persistence=\"none\"", + "-c", + "experimental_thread_store={type=\"in_memory\",id=\"codexbar-status\"}", + "-c", + "sqlite_home=\"\(self.tomlEscaped(stateHome.path))\"", + ] + } + + private static func tomlEscaped(_ value: String) -> String { + value + .replacingOccurrences(of: "\\", with: "\\\\") + .replacingOccurrences(of: "\"", with: "\\\"") + } +} diff --git a/Sources/CodexBarCore/Providers/Codex/CodexSystemAccountObserver.swift b/Sources/CodexBarCore/Providers/Codex/CodexSystemAccountObserver.swift new file mode 100644 index 0000000..5b66209 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Codex/CodexSystemAccountObserver.swift @@ -0,0 +1,69 @@ +import Foundation + +public struct ObservedSystemCodexAccount: Equatable, Sendable { + public let email: String + public let workspaceLabel: String? + public let workspaceAccountID: String? + public let authFingerprint: String? + public let codexHomePath: String + public let observedAt: Date + public let identity: CodexIdentity + + public init( + email: String, + workspaceLabel: String? = nil, + workspaceAccountID: String? = nil, + authFingerprint: String? = nil, + codexHomePath: String, + observedAt: Date, + identity: CodexIdentity = .unresolved) + { + self.email = email + self.workspaceLabel = workspaceLabel + self.workspaceAccountID = workspaceAccountID + self.authFingerprint = CodexAuthFingerprint.normalize(authFingerprint) + self.codexHomePath = codexHomePath + self.observedAt = observedAt + self.identity = identity + } +} + +public protocol CodexSystemAccountObserving: Sendable { + func loadSystemAccount(environment: [String: String]) throws -> ObservedSystemCodexAccount? +} + +public struct DefaultCodexSystemAccountObserver: CodexSystemAccountObserving { + private let workspaceCache: CodexOpenAIWorkspaceIdentityCache + + public init(workspaceCache: CodexOpenAIWorkspaceIdentityCache = CodexOpenAIWorkspaceIdentityCache()) { + self.workspaceCache = workspaceCache + } + + public func loadSystemAccount(environment: [String: String]) throws -> ObservedSystemCodexAccount? { + let homeURL = CodexHomeScope.ambientHomeURL(env: environment) + let fetcher = UsageFetcher(environment: environment) + let account = fetcher.loadAuthBackedCodexAccount() + + guard let rawEmail = account.email?.trimmingCharacters(in: .whitespacesAndNewlines), + !rawEmail.isEmpty + else { + return nil + } + + let providerAccountID: String? = switch account.identity { + case let .providerAccount(id): + ManagedCodexAccount.normalizeProviderAccountID(id) + case .emailOnly, .unresolved: + nil + } + + return ObservedSystemCodexAccount( + email: rawEmail.lowercased(), + workspaceLabel: self.workspaceCache.workspaceLabel(for: providerAccountID), + workspaceAccountID: providerAccountID, + authFingerprint: CodexAuthFingerprint.fingerprint(homePath: homeURL.path), + codexHomePath: homeURL.path, + observedAt: Date(), + identity: account.identity) + } +} diff --git a/Sources/CodexBarCore/Providers/Codex/CodexUsageDataSource.swift b/Sources/CodexBarCore/Providers/Codex/CodexUsageDataSource.swift new file mode 100644 index 0000000..b3bb16c --- /dev/null +++ b/Sources/CodexBarCore/Providers/Codex/CodexUsageDataSource.swift @@ -0,0 +1,30 @@ +import Foundation + +public enum CodexUsageDataSource: String, CaseIterable, Identifiable, Sendable { + case auto + case oauth + case cli + + public var id: String { + self.rawValue + } + + public var displayName: String { + switch self { + case .auto: "Auto" + case .oauth: "OAuth API" + case .cli: "CLI (RPC/PTY)" + } + } + + public var sourceLabel: String { + switch self { + case .auto: + "auto" + case .oauth: + "oauth" + case .cli: + "cli" + } + } +} diff --git a/Sources/CodexBarCore/Providers/Codex/CodexVisibleAccountProjection.swift b/Sources/CodexBarCore/Providers/Codex/CodexVisibleAccountProjection.swift new file mode 100644 index 0000000..a25f3fe --- /dev/null +++ b/Sources/CodexBarCore/Providers/Codex/CodexVisibleAccountProjection.swift @@ -0,0 +1,287 @@ +import Foundation + +public struct CodexVisibleAccount: Equatable, Identifiable, Sendable { + public let id: String + public let email: String + public let workspaceLabel: String? + public let workspaceAccountID: String? + public let authFingerprint: String? + public let storedAccountID: UUID? + public let selectionSource: CodexActiveSource + public let isActive: Bool + public let isLive: Bool + public let canReauthenticate: Bool + public let canRemove: Bool + + public init( + id: String, + email: String, + workspaceLabel: String? = nil, + workspaceAccountID: String? = nil, + authFingerprint: String? = nil, + storedAccountID: UUID?, + selectionSource: CodexActiveSource, + isActive: Bool, + isLive: Bool, + canReauthenticate: Bool, + canRemove: Bool) + { + self.id = id + self.email = email + self.workspaceLabel = Self.normalizeWorkspaceLabel(workspaceLabel) + self.workspaceAccountID = workspaceAccountID + self.authFingerprint = CodexAuthFingerprint.normalize(authFingerprint) + self.storedAccountID = storedAccountID + self.selectionSource = selectionSource + self.isActive = isActive + self.isLive = isLive + self.canReauthenticate = canReauthenticate + self.canRemove = canRemove + } + + public var displayName: String { + guard let workspaceLabel else { return self.email } + return "\(self.email) — \(workspaceLabel)" + } + + public var menuDisplayName: String { + guard let menuWorkspaceLabel else { return self.email } + return "\(self.email) — \(menuWorkspaceLabel)" + } + + public var menuWorkspaceLabel: String? { + guard let workspaceLabel, workspaceLabel.compare("Personal", options: [.caseInsensitive]) != .orderedSame else { + return nil + } + return workspaceLabel + } + + public var authenticationHealthLabel: String? { + guard !self.isLive, self.storedAccountID != nil, self.authFingerprint == nil else { return nil } + return "Missing auth" + } + + private static func normalizeWorkspaceLabel(_ workspaceLabel: String?) -> String? { + guard let trimmed = workspaceLabel?.trimmingCharacters(in: .whitespacesAndNewlines), !trimmed.isEmpty else { + return nil + } + return trimmed + } +} + +public struct CodexVisibleAccountProjection: Equatable, Sendable { + public let visibleAccounts: [CodexVisibleAccount] + public let activeVisibleAccountID: String? + public let liveVisibleAccountID: String? + public let hasUnreadableAddedAccountStore: Bool + + public init( + visibleAccounts: [CodexVisibleAccount], + activeVisibleAccountID: String?, + liveVisibleAccountID: String?, + hasUnreadableAddedAccountStore: Bool) + { + self.visibleAccounts = visibleAccounts + self.activeVisibleAccountID = activeVisibleAccountID + self.liveVisibleAccountID = liveVisibleAccountID + self.hasUnreadableAddedAccountStore = hasUnreadableAddedAccountStore + } + + public func source(forVisibleAccountID id: String) -> CodexActiveSource? { + self.visibleAccounts.first { $0.id == id }?.selectionSource + } +} + +extension DefaultCodexAccountReconciler { + public func loadVisibleAccounts() -> CodexVisibleAccountProjection { + CodexVisibleAccountProjection.make(from: self.loadSnapshot()) + } +} + +extension CodexVisibleAccountProjection { + public static func make(from snapshot: CodexAccountReconciliationSnapshot) -> CodexVisibleAccountProjection { + let resolvedActiveSource = CodexActiveSourceResolver.resolve(from: snapshot).resolvedSource + var drafts: [VisibleAccountDraft] = [] + + for storedAccount in snapshot.storedAccounts { + let normalizedEmail = snapshot.runtimeEmail(for: storedAccount) + let runtimeIdentity = snapshot.runtimeIdentity(for: storedAccount) + let runtimeWorkspaceAccountID: String? = switch runtimeIdentity { + case let .providerAccount(id): + ManagedCodexAccount.normalizeWorkspaceAccountID(id) + case .emailOnly, .unresolved: + nil + } + drafts.append(VisibleAccountDraft( + email: normalizedEmail, + workspaceLabel: Self.normalizeWorkspaceLabel(storedAccount.workspaceLabel), + workspaceAccountID: storedAccount.workspaceAccountID ?? runtimeWorkspaceAccountID, + authFingerprint: storedAccount.authFingerprint, + storedAccountID: storedAccount.id, + selectionSource: .managedAccount(id: storedAccount.id), + isLive: false, + canReauthenticate: true, + canRemove: true, + identity: runtimeIdentity)) + } + + if let liveSystemAccount = snapshot.liveSystemAccount { + let normalizedEmail = Self.normalizeVisibleEmail(liveSystemAccount.email) + let liveIdentity = snapshot.runtimeIdentity(for: liveSystemAccount) + if let exactStoredAccountID = snapshot.matchingStoredAccountForLiveSystemAccount?.id, + let exactIndex = drafts.firstIndex(where: { $0.storedAccountID == exactStoredAccountID }) + { + let existingDraft = drafts[exactIndex] + let liveWorkspaceLabel = Self.normalizeWorkspaceLabel(liveSystemAccount.workspaceLabel) + drafts[exactIndex] = VisibleAccountDraft( + email: existingDraft.email, + workspaceLabel: liveWorkspaceLabel ?? existingDraft.workspaceLabel, + workspaceAccountID: liveSystemAccount.workspaceAccountID ?? existingDraft.workspaceAccountID, + authFingerprint: liveSystemAccount.authFingerprint ?? existingDraft.authFingerprint, + storedAccountID: existingDraft.storedAccountID, + selectionSource: .liveSystem, + isLive: true, + canReauthenticate: existingDraft.canReauthenticate, + canRemove: existingDraft.canRemove, + identity: liveIdentity) + } else if let existingIndex = drafts.firstIndex(where: { draft in + CodexIdentityMatcher.matches( + draft.identity, + lhsEmail: draft.email, + liveIdentity, + rhsEmail: normalizedEmail) + }) { + let existingDraft = drafts[existingIndex] + let liveWorkspaceLabel = Self.normalizeWorkspaceLabel(liveSystemAccount.workspaceLabel) + drafts[existingIndex] = VisibleAccountDraft( + email: existingDraft.email, + workspaceLabel: liveWorkspaceLabel ?? existingDraft.workspaceLabel, + workspaceAccountID: liveSystemAccount.workspaceAccountID ?? existingDraft.workspaceAccountID, + authFingerprint: liveSystemAccount.authFingerprint ?? existingDraft.authFingerprint, + storedAccountID: existingDraft.storedAccountID, + selectionSource: .liveSystem, + isLive: true, + canReauthenticate: existingDraft.canReauthenticate, + canRemove: existingDraft.canRemove, + identity: liveIdentity) + } else { + drafts.append(VisibleAccountDraft( + email: normalizedEmail, + workspaceLabel: Self.normalizeWorkspaceLabel(liveSystemAccount.workspaceLabel), + workspaceAccountID: liveSystemAccount.workspaceAccountID, + authFingerprint: liveSystemAccount.authFingerprint, + storedAccountID: nil, + selectionSource: .liveSystem, + isLive: true, + canReauthenticate: true, + canRemove: false, + identity: liveIdentity)) + } + } + + let livePath = snapshot.liveSystemAccount.flatMap { CodexHomeScope.normalizedHomePath($0.codexHomePath) } + let managedPaths = Set(snapshot.storedAccounts.compactMap { + CodexHomeScope.normalizedHomePath($0.managedHomePath) + }) + for profileAccount in snapshot.profileHomeAccounts { + let profilePath = CodexHomeScope.normalizedHomePath(profileAccount.codexHomePath) + guard let profilePath, + profilePath != livePath, + !managedPaths.contains(profilePath) + else { + continue + } + drafts.append(VisibleAccountDraft( + email: Self.normalizeVisibleEmail(profileAccount.email), + workspaceLabel: Self.normalizeWorkspaceLabel(profileAccount.workspaceLabel), + workspaceAccountID: profileAccount.workspaceAccountID, + authFingerprint: profileAccount.authFingerprint, + storedAccountID: nil, + selectionSource: .profileHome(path: profilePath), + isLive: false, + canReauthenticate: false, + canRemove: false, + identity: snapshot.runtimeIdentity(for: profileAccount))) + } + + let groupedByEmail = Dictionary(grouping: drafts.indices, by: { drafts[$0].email }) + let visibleAccounts = drafts.map { draft in + let id = Self.visibleAccountID(for: draft, emailGroupSize: groupedByEmail[draft.email]?.count ?? 0) + let isActive = switch resolvedActiveSource { + case .liveSystem: + draft.selectionSource == .liveSystem + case let .managedAccount(id): + draft.selectionSource == .managedAccount(id: id) + case let .profileHome(path): + draft.selectionSource == .profileHome(path: path) + } + + return CodexVisibleAccount( + id: id, + email: draft.email, + workspaceLabel: draft.workspaceLabel, + workspaceAccountID: draft.workspaceAccountID, + authFingerprint: draft.authFingerprint, + storedAccountID: draft.storedAccountID, + selectionSource: draft.selectionSource, + isActive: isActive, + isLive: draft.isLive, + canReauthenticate: draft.canReauthenticate, + canRemove: draft.canRemove) + }.sorted { lhs, rhs in + if lhs.email != rhs.email { + return lhs.email < rhs.email + } + if lhs.isLive != rhs.isLive { + return lhs.isLive && !rhs.isLive + } + if lhs.displayName != rhs.displayName { + return lhs.displayName < rhs.displayName + } + return lhs.id < rhs.id + } + + return CodexVisibleAccountProjection( + visibleAccounts: visibleAccounts, + activeVisibleAccountID: visibleAccounts.first { $0.isActive }?.id, + liveVisibleAccountID: visibleAccounts.first { $0.isLive }?.id, + hasUnreadableAddedAccountStore: snapshot.hasUnreadableAddedAccountStore) + } + + private static func normalizeVisibleEmail(_ email: String) -> String { + email.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() + } + + private static func normalizeWorkspaceLabel(_ workspaceLabel: String?) -> String? { + guard let trimmed = workspaceLabel?.trimmingCharacters(in: .whitespacesAndNewlines), !trimmed.isEmpty else { + return nil + } + return trimmed + } + + private static func visibleAccountID(for draft: VisibleAccountDraft, emailGroupSize: Int) -> String { + guard emailGroupSize > 1 else { return draft.email } + + switch draft.selectionSource { + case .liveSystem: + return "live:\(CodexIdentityMatcher.selectionKey(for: draft.identity, fallbackEmail: draft.email))" + case let .managedAccount(id): + return "managed:\(id.uuidString.lowercased())" + case let .profileHome(path): + return "profile:\(path)" + } + } +} + +private struct VisibleAccountDraft { + let email: String + let workspaceLabel: String? + let workspaceAccountID: String? + let authFingerprint: String? + let storedAccountID: UUID? + let selectionSource: CodexActiveSource + let isLive: Bool + let canReauthenticate: Bool + let canRemove: Bool + let identity: CodexIdentity +} diff --git a/Sources/CodexBarCore/Providers/Codex/CodexWebDashboardStrategy.swift b/Sources/CodexBarCore/Providers/Codex/CodexWebDashboardStrategy.swift new file mode 100644 index 0000000..12eedd4 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Codex/CodexWebDashboardStrategy.swift @@ -0,0 +1,343 @@ +#if os(macOS) +import AppKit +import Foundation + +public struct CodexWebDashboardStrategy: ProviderFetchStrategy { + public let id: String = "codex.web.dashboard" + public let kind: ProviderFetchKind = .webDashboard + + public init() {} + + public func isAvailable(_ context: ProviderFetchContext) async -> Bool { + context.sourceMode.usesWeb && + !Self.managedAccountStoreIsUnreadable(context) && + !Self.managedAccountTargetIsUnavailable(context) && + (!Self.profileAccountTargetIsUnavailable(context) || context.sourceMode == .web) + } + + public func fetch(_ context: ProviderFetchContext) async throws -> ProviderFetchResult { + guard !Self.managedAccountStoreIsUnreadable(context) else { + // A fail-closed placeholder CODEX_HOME does not identify a target account. If the managed store + // itself is unreadable, web import must not fall back to "any signed-in browser account". + throw OpenAIDashboardFetcher.FetchError.loginRequired + } + guard !Self.managedAccountTargetIsUnavailable(context) else { + // If the selected managed account no longer exists in a readable store, web import must not + // fall back to "any signed-in browser account" for that stale selection. + throw OpenAIDashboardFetcher.FetchError.loginRequired + } + guard !Self.profileAccountTargetIsUnavailable(context) else { + // A profile without an auth-backed email cannot safely target browser cookie import. + throw OpenAIDashboardFetcher.FetchError.loginRequired + } + + let options = OpenAIWebOptions( + deadline: OpenAIDashboardFetcher.deadline(startingAt: Date(), timeout: context.webTimeout), + debugDumpHTML: context.webDebugDumpHTML, + verbose: context.verbose) + + // Ensure AppKit is initialized before using WebKit in a CLI. + await MainActor.run { + _ = NSApplication.shared + } + + let result: OpenAIWebCodexResult + do { + result = try await Self.fetchOpenAIWebCodex( + context: context, + options: options, + browserDetection: context.browserDetection) + } catch let error as URLError where error.code == .timedOut { + throw OpenAIWebCodexError.timedOut(seconds: context.webTimeout) + } + return self.makeResult( + usage: result.usage, + credits: result.credits, + dashboard: result.dashboard, + sourceLabel: "openai-web") + } + + public func shouldFallback(on error: Error, context: ProviderFetchContext) -> Bool { + _ = error + return context.sourceMode == .auto + } + + private static func managedAccountStoreIsUnreadable(_ context: ProviderFetchContext) -> Bool { + context.settings?.codex?.managedAccountStoreUnreadable == true + } + + private static func managedAccountTargetIsUnavailable(_ context: ProviderFetchContext) -> Bool { + context.settings?.codex?.managedAccountTargetUnavailable == true + } + + private static func profileAccountTargetIsUnavailable(_ context: ProviderFetchContext) -> Bool { + context.settings?.codex?.profileAccountTargetUnavailable == true + } +} + +struct OpenAIWebCodexResult { + let usage: UsageSnapshot + let credits: CreditsSnapshot? + let dashboard: OpenAIDashboardSnapshot +} + +enum OpenAIWebCodexError: LocalizedError, Equatable { + case missingUsage + case policyRejected(CodexDashboardAuthorityDecision) + case timedOut(seconds: TimeInterval) + + var errorDescription: String? { + switch self { + case .missingUsage: + return "OpenAI web dashboard did not include usage limits." + case let .timedOut(seconds): + return "OpenAI web dashboard fetch timed out after \(seconds.formatted()) seconds." + case let .policyRejected(decision): + switch decision.reason { + case let .wrongEmail(expected, actual): + var details: [String] = [] + if let expected { + details.append("expected \(expected)") + } + if let actual { + details.append("got \(actual)") + } + if details.isEmpty { + return "OpenAI web dashboard belonged to the wrong account." + } + return "OpenAI web dashboard belonged to the wrong account (\(details.joined(separator: ", ")))." + case .unresolvedWithoutTrustedEvidence: + return "Active Codex identity is unresolved and no trusted auth-backed continuity exists." + case .providerAccountMissingScopedEmail: + return "Active Codex provider account is missing its scoped email, " + + "so dashboard ownership cannot be proven." + case .providerAccountLacksExactOwnershipProof: + return "OpenAI web dashboard could not be proven to belong to the active provider account." + case .missingDashboardSignedInEmail: + return "OpenAI web dashboard did not expose a signed-in email." + case let .sameEmailAmbiguity(email): + return "OpenAI web dashboard email \(email) is ambiguous across multiple known owners." + default: + return "OpenAI web dashboard was rejected by Codex dashboard authority." + } + } + } +} + +private struct OpenAIWebOptions { + let deadline: Date + let debugDumpHTML: Bool + let verbose: Bool +} + +@MainActor +private final class WebLogBuffer { + private var lines: [String] = [] + private let maxCount: Int + private let verbose: Bool + private let logger = CodexBarLog.logger(LogCategories.openAIWeb) + + init(maxCount: Int = 300, verbose: Bool) { + self.maxCount = maxCount + self.verbose = verbose + } + + func append(_ line: String) { + self.lines.append(line) + if self.lines.count > self.maxCount { + self.lines.removeFirst(self.lines.count - self.maxCount) + } + if self.verbose { + self.logger.verbose(line) + } + } + + func snapshot() -> [String] { + self.lines + } +} + +extension CodexWebDashboardStrategy { + @MainActor + fileprivate static func fetchOpenAIWebCodex( + context: ProviderFetchContext, + options: OpenAIWebOptions, + browserDetection: BrowserDetection) async throws -> OpenAIWebCodexResult + { + let logger = WebLogBuffer(verbose: options.verbose) + let log: @MainActor (String) -> Void = { line in + logger.append(line) + } + do { + let result = try await Self.fetchOpenAIWebDashboard( + context: context, + options: options, + browserDetection: browserDetection, + preferCachedCookieHeader: true, + logger: log) + return try Self.makeAuthorizedDashboardResult( + dashboard: result.dashboard, + context: context, + routingTargetEmail: result.routingTargetEmail) + } catch { + guard Self.shouldRetryWithFreshBrowserImport(after: error) else { + throw error + } + _ = try OpenAIDashboardBrowserCookieImporter.remainingTimeout(until: options.deadline) + log("Retrying OpenAI web dashboard with a fresh browser cookie import.") + let result = try await Self.fetchOpenAIWebDashboard( + context: context, + options: options, + browserDetection: browserDetection, + preferCachedCookieHeader: false, + logger: log) + return try Self.makeAuthorizedDashboardResult( + dashboard: result.dashboard, + context: context, + routingTargetEmail: result.routingTargetEmail) + } + } + + nonisolated static func shouldRetryWithFreshBrowserImport(after error: Error) -> Bool { + if error is OpenAIWebCodexError { + return error as? OpenAIWebCodexError == .missingUsage + } + if case OpenAIDashboardFetcher.FetchError.noDashboardData = error { + return true + } + return false + } + + @MainActor + static func makeAuthorizedDashboardResultForTesting( + dashboard: OpenAIDashboardSnapshot, + context: ProviderFetchContext, + routingTargetEmail: String?) + throws -> OpenAIWebCodexResult + { + try self.makeAuthorizedDashboardResult( + dashboard: dashboard, + context: context, + routingTargetEmail: routingTargetEmail) + } + + @MainActor + private static func makeAuthorizedDashboardResult( + dashboard: OpenAIDashboardSnapshot, + context: ProviderFetchContext, + routingTargetEmail: String?) throws -> OpenAIWebCodexResult + { + let input = CodexCLIDashboardAuthorityContext.makeLiveWebInput( + dashboard: dashboard, + context: context, + routingTargetEmail: routingTargetEmail) + let decision = CodexDashboardAuthority.evaluate(input) + + switch decision.disposition { + case .attach: + let attachedAccountEmail = CodexCLIDashboardAuthorityContext.attachmentEmail(from: input) + let credits = dashboard.toCreditsSnapshot() + let usage = dashboard.toUsageSnapshot(provider: .codex, accountEmail: attachedAccountEmail) + ?? Self.makeCreditsOnlyUsageSnapshot( + dashboard: dashboard, + attachedAccountEmail: attachedAccountEmail, + credits: credits) + guard let usage else { + throw OpenAIWebCodexError.missingUsage + } + if let attachedAccountEmail { + OpenAIDashboardCacheStore.save(OpenAIDashboardCache( + accountEmail: attachedAccountEmail, + snapshot: dashboard)) + } + return OpenAIWebCodexResult(usage: usage, credits: credits, dashboard: dashboard) + case .displayOnly: + if decision.cleanup.contains(.dashboardCache) { + OpenAIDashboardCacheStore.clear() + } + throw CodexDashboardPolicyError.displayOnly(decision) + case .failClosed: + if decision.cleanup.contains(.dashboardCache) { + OpenAIDashboardCacheStore.clear() + } + throw OpenAIWebCodexError.policyRejected(decision) + } + } + + private static func makeCreditsOnlyUsageSnapshot( + dashboard: OpenAIDashboardSnapshot, + attachedAccountEmail: String?, + credits: CreditsSnapshot?) -> UsageSnapshot? + { + guard credits != nil else { return nil } + return UsageSnapshot( + primary: nil, + secondary: nil, + tertiary: nil, + updatedAt: dashboard.updatedAt, + identity: ProviderIdentitySnapshot( + providerID: .codex, + accountEmail: attachedAccountEmail ?? dashboard.signedInEmail, + accountOrganization: nil, + loginMethod: dashboard.accountPlan)) + } + + private struct OpenAIWebDashboardFetchResult { + let dashboard: OpenAIDashboardSnapshot + let routingTargetEmail: String? + } + + @MainActor + private static func fetchOpenAIWebDashboard( + context: ProviderFetchContext, + options: OpenAIWebOptions, + browserDetection: BrowserDetection, + preferCachedCookieHeader: Bool, + logger: @MainActor @escaping (String) -> Void) async throws -> OpenAIWebDashboardFetchResult + { + let auth = context.fetcher.loadAuthBackedCodexAccount() + let routingTargetEmail = auth.email?.trimmingCharacters(in: .whitespacesAndNewlines) + let allowAnyAccount = routingTargetEmail == nil + + let importResult = try await OpenAIDashboardBrowserCookieImporter(browserDetection: browserDetection) + .importBestCookies( + intoAccountEmail: routingTargetEmail, + allowAnyAccount: allowAnyAccount, + preferCachedCookieHeader: preferCachedCookieHeader, + cacheScope: context.settings?.codex?.openAIWebCacheScope, + deadline: options.deadline, + logger: logger) + let effectiveEmail = routingTargetEmail ?? importResult.signedInEmail? + .trimmingCharacters(in: .whitespacesAndNewlines) + + let dashboard = try await OpenAIDashboardFetcher().loadLatestDashboard( + accountEmail: effectiveEmail, + cacheScope: context.settings?.codex?.openAIWebCacheScope, + logger: logger, + debugDumpHTML: options.debugDumpHTML, + timeout: OpenAIDashboardBrowserCookieImporter.remainingTimeout(until: options.deadline)) + return OpenAIWebDashboardFetchResult( + dashboard: dashboard, + routingTargetEmail: routingTargetEmail) + } +} +#else +public struct CodexWebDashboardStrategy: ProviderFetchStrategy { + public let id: String = "codex.web.dashboard" + public let kind: ProviderFetchKind = .webDashboard + + public init() {} + + public func isAvailable(_: ProviderFetchContext) async -> Bool { + false + } + + public func fetch(_: ProviderFetchContext) async throws -> ProviderFetchResult { + throw ProviderFetchError.noAvailableStrategy(.codex) + } + + public func shouldFallback(on _: Error, context _: ProviderFetchContext) -> Bool { + false + } +} +#endif diff --git a/Sources/CodexBarCore/Providers/CommandCode/CommandCodeCookieHeader.swift b/Sources/CodexBarCore/Providers/CommandCode/CommandCodeCookieHeader.swift new file mode 100644 index 0000000..f5835c8 --- /dev/null +++ b/Sources/CodexBarCore/Providers/CommandCode/CommandCodeCookieHeader.swift @@ -0,0 +1,85 @@ +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +/// A resolved CommandCode session cookie ready to be sent on `Cookie:` headers. +/// +/// CommandCode's API (api.commandcode.ai) authenticates with the better-auth session +/// cookie set by commandcode.ai. better-auth emits either `better-auth.session_token` +/// or `__Secure-better-auth.session_token` depending on whether `useSecureCookies` is +/// enabled (the `__Secure-` variant is required by browsers for HTTPS production). +public struct CommandCodeCookieOverride: Sendable, Equatable { + public let name: String + public let token: String + + public init(name: String, token: String) { + self.name = name + self.token = token + } + + /// `Cookie: name=value` header value. + public var headerValue: String { + "\(self.name)=\(self.token)" + } +} + +public enum CommandCodeCookieHeader { + /// Cookie names used by better-auth in production (HTTPS) and dev (HTTP). + /// The `__Secure-` variant is the standard production deployment. + public static let supportedSessionCookieNames = [ + "__Host-better-auth.session_token", + "__Secure-better-auth.session_token", + "better-auth.session_token", + ] + + /// Extract a session cookie from a list of `HTTPCookie` records. + public static func sessionCookie(from cookies: [HTTPCookie]) -> CommandCodeCookieOverride? { + let pairs = cookies.map { (name: $0.name, value: $0.value) } + return self.extractSessionCookie(from: pairs) + } + + /// Parse a raw `Cookie:` header (or bare token) and extract the session value. + public static func override(from raw: String?) -> CommandCodeCookieOverride? { + guard let raw = raw?.trimmingCharacters(in: .whitespacesAndNewlines), !raw.isEmpty else { + return nil + } + + // Bare token — assume the production cookie name. + if !raw.contains("="), !raw.contains(";") { + return CommandCodeCookieOverride( + name: "__Secure-better-auth.session_token", + token: raw) + } + + return self.extractSessionCookie(fromHeader: raw) + } + + private static func extractSessionCookie(fromHeader header: String) -> CommandCodeCookieOverride? { + var pairs: [(name: String, value: String)] = [] + for chunk in header.split(separator: ";") { + let trimmed = chunk.trimmingCharacters(in: .whitespacesAndNewlines) + guard let separator = trimmed.firstIndex(of: "=") else { continue } + let key = String(trimmed[.. CommandCodeCookieOverride? { + var byLowerName: [String: (name: String, value: String)] = [:] + for pair in pairs { + byLowerName[pair.name.lowercased()] = pair + } + for expected in self.supportedSessionCookieNames { + if let match = byLowerName[expected.lowercased()] { + return CommandCodeCookieOverride(name: match.name, token: match.value) + } + } + return nil + } +} diff --git a/Sources/CodexBarCore/Providers/CommandCode/CommandCodeCookieImporter.swift b/Sources/CodexBarCore/Providers/CommandCode/CommandCodeCookieImporter.swift new file mode 100644 index 0000000..3db2c52 --- /dev/null +++ b/Sources/CodexBarCore/Providers/CommandCode/CommandCodeCookieImporter.swift @@ -0,0 +1,230 @@ +import Foundation + +#if os(macOS) +import SweetCookieKit + +/// Imports CommandCode session cookies from installed browsers (Chrome by default). +public enum CommandCodeCookieImporter { + private static let importSessionCacheTTL: TimeInterval = 5 + private static let importSessionCache = ImportSessionCache(ttl: importSessionCacheTTL) + private static let log = CodexBarLog.logger(LogCategories.commandcodeCookie) + private static let cookieClient = BrowserCookieClient() + private static let cookieDomains = ["commandcode.ai", "www.commandcode.ai"] + private static let cookieImportOrder: BrowserCookieImportOrder = + ProviderDefaults.metadata[.commandcode]?.browserCookieOrder ?? Browser.defaultImportOrder + + public struct SessionInfo: Sendable { + public let cookies: [HTTPCookie] + public let sourceLabel: String + + public init(cookies: [HTTPCookie], sourceLabel: String) { + self.cookies = cookies + self.sourceLabel = sourceLabel + } + + public var sessionCookie: CommandCodeCookieOverride? { + CommandCodeCookieHeader.sessionCookie(from: self.cookies) + } + + public var cookieHeader: String { + self.cookies.map { "\($0.name)=\($0.value)" }.joined(separator: "; ") + } + } + + public static func importSessions( + browserDetection: BrowserDetection = BrowserDetection(), + logger: ((String) -> Void)? = nil) throws -> [SessionInfo] + { + if let cached = self.cachedImportSessions() { + return cached + } + + var sessions: [SessionInfo] = [] + let candidates = self.cookieImportOrder.cookieImportCandidates(using: browserDetection) + for browserSource in candidates { + do { + let perSource = try self.importSessions(from: browserSource, logger: logger) + sessions.append(contentsOf: perSource) + } catch { + BrowserCookieAccessGate.recordIfNeeded(error) + self.emit( + "\(browserSource.displayName) cookie import failed: \(error.localizedDescription)", + logger: logger) + } + } + + guard !sessions.isEmpty else { + throw CommandCodeCookieImportError.noCookies + } + self.storeImportSessions(sessions) + return sessions + } + + public static func importSessions( + from browserSource: Browser, + logger: ((String) -> Void)? = nil) throws -> [SessionInfo] + { + let query = BrowserCookieQuery(domains: self.cookieDomains) + let log: (String) -> Void = { msg in self.emit(msg, logger: logger) } + let sources = try Self.cookieClient.codexBarRecords( + matching: query, + in: browserSource, + logger: log) + + var sessions: [SessionInfo] = [] + let grouped = Dictionary(grouping: sources, by: { $0.store.profile.id }) + let sortedGroups = grouped.values.sorted { lhs, rhs in + self.mergedLabel(for: lhs) < self.mergedLabel(for: rhs) + } + + for group in sortedGroups where !group.isEmpty { + let label = self.mergedLabel(for: group) + let mergedRecords = self.mergeRecords(group) + guard !mergedRecords.isEmpty else { continue } + let httpCookies = BrowserCookieClient.makeHTTPCookies(mergedRecords, origin: query.origin) + guard !httpCookies.isEmpty else { continue } + + let session = SessionInfo(cookies: httpCookies, sourceLabel: label) + if let sessionCookie = session.sessionCookie { + log("Found \(sessionCookie.name) cookie in \(label)") + } else { + let names = httpCookies.map(\.name).joined(separator: ", ") + log("No known session name in \(label); sending all domain cookies (\(names))") + } + sessions.append(session) + } + return sessions + } + + public static func importSession( + browserDetection: BrowserDetection = BrowserDetection(), + logger: ((String) -> Void)? = nil) throws -> SessionInfo + { + let sessions = try self.importSessions(browserDetection: browserDetection, logger: logger) + guard let first = sessions.first else { throw CommandCodeCookieImportError.noCookies } + return first + } + + public static func hasSession( + browserDetection: BrowserDetection = BrowserDetection(), + logger: ((String) -> Void)? = nil) -> Bool + { + do { + let session = try self.importSession(browserDetection: browserDetection, logger: logger) + return !session.cookies.isEmpty + } catch { + return false + } + } + + static func invalidateImportSessionCache() { + self.importSessionCache.invalidate() + } + + private static func emit(_ message: String, logger: ((String) -> Void)?) { + logger?("[commandcode-cookie] \(message)") + self.log.debug(message) + } + + private static func cachedImportSessions(now: Date = Date()) -> [SessionInfo]? { + self.importSessionCache.load(now: now) + } + + private static func storeImportSessions(_ sessions: [SessionInfo], now: Date = Date()) { + self.importSessionCache.store(sessions, now: now) + } + + private static func mergedLabel(for sources: [BrowserCookieStoreRecords]) -> String { + guard let base = sources.map(\.label).min() else { return "Unknown" } + if base.hasSuffix(" (Network)") { + return String(base.dropLast(" (Network)".count)) + } + return base + } + + private static func mergeRecords(_ sources: [BrowserCookieStoreRecords]) -> [BrowserCookieRecord] { + let sortedSources = sources.sorted { lhs, rhs in + self.storePriority(lhs.store.kind) < self.storePriority(rhs.store.kind) + } + var mergedByKey: [String: BrowserCookieRecord] = [:] + for source in sortedSources { + for record in source.records { + let key = self.recordKey(record) + if let existing = mergedByKey[key] { + if self.shouldReplace(existing: existing, candidate: record) { + mergedByKey[key] = record + } + } else { + mergedByKey[key] = record + } + } + } + return Array(mergedByKey.values) + } + + private static func storePriority(_ kind: BrowserCookieStoreKind) -> Int { + switch kind { + case .network: 0 + case .primary: 1 + case .safari: 2 + } + } + + private static func recordKey(_ record: BrowserCookieRecord) -> String { + "\(record.name)|\(record.domain)|\(record.path)" + } + + private static func shouldReplace(existing: BrowserCookieRecord, candidate: BrowserCookieRecord) -> Bool { + switch (existing.expires, candidate.expires) { + case let (lhs?, rhs?): rhs > lhs + case (nil, .some): true + case (.some, nil): false + case (nil, nil): false + } + } + + private final class ImportSessionCache: @unchecked Sendable { + private let ttl: TimeInterval + private let lock = NSLock() + private var entry: (sessions: [SessionInfo], expiresAt: Date)? + + init(ttl: TimeInterval) { + self.ttl = ttl + } + + func load(now: Date) -> [SessionInfo]? { + self.lock.lock() + defer { self.lock.unlock() } + guard let entry = self.entry else { return nil } + guard entry.expiresAt > now else { + self.entry = nil + return nil + } + return entry.sessions + } + + func store(_ sessions: [SessionInfo], now: Date) { + self.lock.lock() + defer { self.lock.unlock() } + self.entry = (sessions: sessions, expiresAt: now.addingTimeInterval(self.ttl)) + } + + func invalidate() { + self.lock.lock() + defer { self.lock.unlock() } + self.entry = nil + } + } +} + +public enum CommandCodeCookieImportError: LocalizedError { + case noCookies + + public var errorDescription: String? { + switch self { + case .noCookies: + "No Command Code session cookies found in browsers. Sign in to commandcode.ai." + } + } +} +#endif diff --git a/Sources/CodexBarCore/Providers/CommandCode/CommandCodePlanCatalog.swift b/Sources/CodexBarCore/Providers/CommandCode/CommandCodePlanCatalog.swift new file mode 100644 index 0000000..16c7bce --- /dev/null +++ b/Sources/CodexBarCore/Providers/CommandCode/CommandCodePlanCatalog.swift @@ -0,0 +1,34 @@ +import Foundation + +/// Static catalog of CommandCode subscription plans → monthly credit allowance (in USD). +/// +/// The `/internal/billing/credits` endpoint exposes the *remaining* `monthlyCredits`, +/// not the plan total. The plan total is published on the public pricing page +/// (https://commandcode.ai/pricing) and is keyed by `planId` returned from +/// `/internal/billing/subscriptions`. +public enum CommandCodePlanCatalog { + public struct Plan: Sendable, Equatable { + public let id: String + public let displayName: String + /// Monthly credit allowance in USD. + public let monthlyCreditsUSD: Double + + public init(id: String, displayName: String, monthlyCreditsUSD: Double) { + self.id = id + self.displayName = displayName + self.monthlyCreditsUSD = monthlyCreditsUSD + } + } + + public static let plans: [Plan] = [ + Plan(id: "individual-go", displayName: "Go", monthlyCreditsUSD: 10), + Plan(id: "individual-pro", displayName: "Pro", monthlyCreditsUSD: 30), + Plan(id: "individual-max", displayName: "Max", monthlyCreditsUSD: 150), + Plan(id: "individual-ultra", displayName: "Ultra", monthlyCreditsUSD: 300), + ] + + public static func plan(forID planID: String) -> Plan? { + let normalized = planID.lowercased() + return self.plans.first(where: { $0.id == normalized }) + } +} diff --git a/Sources/CodexBarCore/Providers/CommandCode/CommandCodeProviderDescriptor.swift b/Sources/CodexBarCore/Providers/CommandCode/CommandCodeProviderDescriptor.swift new file mode 100644 index 0000000..c348d79 --- /dev/null +++ b/Sources/CodexBarCore/Providers/CommandCode/CommandCodeProviderDescriptor.swift @@ -0,0 +1,98 @@ +import Foundation + +public enum CommandCodeProviderDescriptor { + public static let descriptor: ProviderDescriptor = Self.makeDescriptor() + + static func makeDescriptor() -> ProviderDescriptor { + ProviderDescriptor( + id: .commandcode, + metadata: ProviderMetadata( + id: .commandcode, + displayName: "Command Code", + sessionLabel: "Monthly credits", + weeklyLabel: "Monthly", + opusLabel: nil, + supportsOpus: false, + supportsCredits: true, + creditsHint: "Monthly USD credits from Command Code billing.", + toggleTitle: "Show Command Code usage", + cliName: "commandcode", + defaultEnabled: false, + isPrimaryProvider: false, + usesAccountFallback: false, + browserCookieOrder: ProviderBrowserCookieDefaults.defaultImportOrder, + dashboardURL: "https://commandcode.ai/studio", + subscriptionDashboardURL: "https://commandcode.ai/sixhobbits/settings/billing", + statusPageURL: nil, + statusLinkURL: nil), + branding: ProviderBranding( + iconStyle: .commandcode, + iconResourceName: "ProviderIcon-commandcode", + color: ProviderColor(red: 0 / 255, green: 0 / 255, blue: 0 / 255)), + tokenCost: ProviderTokenCostConfig( + supportsTokenCost: false, + noDataMessage: { "Command Code cost summary is not yet supported." }), + fetchPlan: ProviderFetchPlan( + sourceModes: [.auto, .web], + pipeline: ProviderFetchPipeline(resolveStrategies: { _ in [CommandCodeWebFetchStrategy()] })), + cli: ProviderCLIConfig( + name: "commandcode", + aliases: ["command-code"], + versionDetector: nil)) + } +} + +struct CommandCodeWebFetchStrategy: ProviderFetchStrategy { + let id: String = "commandcode.web" + let kind: ProviderFetchKind = .web + + func isAvailable(_ context: ProviderFetchContext) async -> Bool { + guard context.settings?.commandcode?.cookieSource != .off else { return false } + if Self.manualCookieHeader(from: context) != nil { + return true + } + #if os(macOS) + return true + #else + return false + #endif + } + + func fetch(_ context: ProviderFetchContext) async throws -> ProviderFetchResult { + let cookieHeader: String + let sourceLabel: String + if let manual = Self.manualCookieHeader(from: context) { + cookieHeader = manual + sourceLabel = "manual" + } else { + #if os(macOS) + let session: CommandCodeCookieImporter.SessionInfo + do { + session = try CommandCodeCookieImporter.importSession() + } catch { + throw CommandCodeUsageError.missingCredentials + } + guard !session.cookies.isEmpty else { + throw CommandCodeUsageError.missingCredentials + } + cookieHeader = session.cookieHeader + sourceLabel = session.sourceLabel + #else + throw CommandCodeUsageError.missingCredentials + #endif + } + let snapshot = try await CommandCodeUsageFetcher.fetchUsage(cookieHeader: cookieHeader) + return self.makeResult( + usage: snapshot.toUsageSnapshot(), + sourceLabel: sourceLabel) + } + + private static func manualCookieHeader(from context: ProviderFetchContext) -> String? { + guard context.settings?.commandcode?.cookieSource == .manual else { return nil } + return CookieHeaderNormalizer.normalize(context.settings?.commandcode?.manualCookieHeader) + } + + func shouldFallback(on _: Error, context _: ProviderFetchContext) -> Bool { + false + } +} diff --git a/Sources/CodexBarCore/Providers/CommandCode/CommandCodeUsageError.swift b/Sources/CodexBarCore/Providers/CommandCode/CommandCodeUsageError.swift new file mode 100644 index 0000000..9e13b89 --- /dev/null +++ b/Sources/CodexBarCore/Providers/CommandCode/CommandCodeUsageError.swift @@ -0,0 +1,34 @@ +import Foundation + +public enum CommandCodeUsageError: LocalizedError, Sendable, Equatable { + case missingCredentials + case invalidCredentials + case networkError(String) + case apiError(Int) + case parseFailed(String) + case unknownPlan(String) + + public var errorDescription: String? { + switch self { + case .missingCredentials: + "Command Code session cookie not found. Sign in to commandcode.ai in Chrome." + case .invalidCredentials: + "Command Code session is invalid or expired. Sign in to commandcode.ai again." + case let .networkError(message): + "Command Code network error: \(message)" + case let .apiError(status): + "Command Code API returned status \(status)." + case let .parseFailed(message): + "Could not parse Command Code response: \(message)" + case let .unknownPlan(planID): + "Unknown Command Code plan: \(planID). Add it to CommandCodePlanCatalog." + } + } + + public var isAuthRelated: Bool { + switch self { + case .missingCredentials, .invalidCredentials: true + default: false + } + } +} diff --git a/Sources/CodexBarCore/Providers/CommandCode/CommandCodeUsageFetcher.swift b/Sources/CodexBarCore/Providers/CommandCode/CommandCodeUsageFetcher.swift new file mode 100644 index 0000000..74b8d92 --- /dev/null +++ b/Sources/CodexBarCore/Providers/CommandCode/CommandCodeUsageFetcher.swift @@ -0,0 +1,263 @@ +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +/// Fetches live billing data from `api.commandcode.ai` using a better-auth session +/// cookie scraped from the user's browser. +public enum CommandCodeUsageFetcher { + private static let log = CodexBarLog.logger(LogCategories.commandcodeUsage) + private static let requestTimeoutSeconds: TimeInterval = 15 + private static let subscriptionGraceSeconds: TimeInterval = 2 + private static let apiBase = URL(string: "https://api.commandcode.ai")! + private static let creditsPath = "/internal/billing/credits" + private static let subscriptionsPath = "/internal/billing/subscriptions" + private static let webOrigin = "https://commandcode.ai" + private static let userAgent = + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) " + + "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36" + + public static func fetchUsage( + cookieHeader: String, + session transport: any ProviderHTTPTransport = ProviderHTTPClient.shared, + now: Date = Date()) async throws -> CommandCodeUsageSnapshot + { + try await self.fetchUsage( + cookieHeader: cookieHeader, + transport: transport, + now: now, + subscriptionGrace: .seconds(self.subscriptionGraceSeconds)) + } + + static func _fetchUsageForTesting( + cookieHeader: String, + transport: any ProviderHTTPTransport, + now: Date = Date(), + subscriptionGrace: Duration) async throws -> CommandCodeUsageSnapshot + { + try await self.fetchUsage( + cookieHeader: cookieHeader, + transport: transport, + now: now, + subscriptionGrace: subscriptionGrace) + } + + private static func fetchUsage( + cookieHeader: String, + transport: any ProviderHTTPTransport, + now: Date, + subscriptionGrace: Duration) async throws -> CommandCodeUsageSnapshot + { + let (credits, subscription, subscriptionEnrichmentUnavailable) = try await self.fetchPayloads( + cookieHeader: cookieHeader, + transport: transport, + subscriptionGrace: subscriptionGrace) + + let plan: CommandCodePlanCatalog.Plan? = subscription.flatMap { sub in + CommandCodePlanCatalog.plan(forID: sub.planID) + } + + // If we got an active subscription with an unrecognised plan ID, surface that + // explicitly rather than silently dropping the totals row. + if let sub = subscription, sub.status.lowercased() == "active", plan == nil { + Self.log.error("Unknown CommandCode planId: \(sub.planID)") + throw CommandCodeUsageError.unknownPlan(sub.planID) + } + + return CommandCodeUsageSnapshot( + monthlyCreditsRemaining: credits.monthlyCredits, + purchasedCredits: credits.purchasedCredits, + premiumMonthlyCredits: credits.premiumMonthlyCredits, + opensourceMonthlyCredits: credits.opensourceMonthlyCredits, + plan: plan, + billingPeriodEnd: subscription?.currentPeriodEnd, + subscriptionStatus: subscription?.status, + subscriptionEnrichmentUnavailable: subscriptionEnrichmentUnavailable, + updatedAt: now) + } + + private static func fetchPayloads( + cookieHeader: String, + transport: any ProviderHTTPTransport, + subscriptionGrace: Duration) async throws -> (CreditsPayload, SubscriptionPayload?, Bool) + { + let subscriptionTask = Task { + try await self.fetchSubscription(cookieHeader: cookieHeader, transport: transport) + } + let credits: CreditsPayload + do { + credits = try await withTaskCancellationHandler { + try await self.fetchCredits(cookieHeader: cookieHeader, transport: transport) + } onCancel: { + subscriptionTask.cancel() + } + } catch { + subscriptionTask.cancel() + throw error + } + + do { + try Task.checkCancellation() + } catch { + subscriptionTask.cancel() + throw error + } + let race = BoundedTaskJoin(sourceTask: subscriptionTask) + switch await race.value(joinGrace: subscriptionGrace) { + case let .value(subscription): + try Task.checkCancellation() + return (credits, subscription, false) + case .timedOut: + try Task.checkCancellation() + Self.log.warning("Command Code subscription enrichment timed out") + return (credits, nil, true) + case let .failure(error): + subscriptionTask.cancel() + try Task.checkCancellation() + Self.log.warning("Command Code subscription enrichment failed: \(error.localizedDescription)") + return (credits, nil, true) + } + } + + // MARK: - Endpoints + + struct CreditsPayload { + let monthlyCredits: Double + let purchasedCredits: Double + let premiumMonthlyCredits: Double + let opensourceMonthlyCredits: Double + } + + struct SubscriptionPayload { + let planID: String + let status: String + let currentPeriodEnd: Date? + } + + private static func fetchCredits( + cookieHeader: String, + transport: any ProviderHTTPTransport) async throws -> CreditsPayload + { + let url = self.apiBase.appendingPathComponent(self.creditsPath) + let data = try await self.send(url: url, cookieHeader: cookieHeader, transport: transport) + return try self.parseCredits(data: data) + } + + private static func fetchSubscription( + cookieHeader: String, + transport: any ProviderHTTPTransport) async throws -> SubscriptionPayload? + { + let url = self.apiBase.appendingPathComponent(self.subscriptionsPath) + let data = try await self.send(url: url, cookieHeader: cookieHeader, transport: transport) + return try self.parseSubscription(data: data) + } + + private static func send( + url: URL, + cookieHeader: String, + transport: any ProviderHTTPTransport) async throws -> Data + { + var request = URLRequest(url: url) + request.httpMethod = "GET" + request.timeoutInterval = self.requestTimeoutSeconds + request.setValue(cookieHeader, forHTTPHeaderField: "Cookie") + request.setValue("application/json, text/plain, */*", forHTTPHeaderField: "Accept") + request.setValue("en-US,en;q=0.9", forHTTPHeaderField: "Accept-Language") + request.setValue(self.userAgent, forHTTPHeaderField: "User-Agent") + request.setValue(self.webOrigin, forHTTPHeaderField: "Origin") + request.setValue("\(self.webOrigin)/", forHTTPHeaderField: "Referer") + + let response: ProviderHTTPResponse + do { + response = try await transport.response(for: request) + } catch { + if error is CancellationError || (error as? URLError)?.code == .cancelled || Task.isCancelled { + throw CancellationError() + } + throw CommandCodeUsageError.networkError(error.localizedDescription) + } + if response.statusCode == 401 || response.statusCode == 403 { + throw CommandCodeUsageError.invalidCredentials + } + guard (200..<300).contains(response.statusCode) else { + let body = String(data: response.data, encoding: .utf8) ?? "" + Self.log.error("CommandCode \(url.path) → \(response.statusCode): \(body)") + throw CommandCodeUsageError.apiError(response.statusCode) + } + return response.data + } + + // MARK: - Parsing + + static func parseCredits(data: Data) throws -> CreditsPayload { + guard let root = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else { + throw CommandCodeUsageError.parseFailed("Credits: invalid JSON") + } + guard let credits = root["credits"] as? [String: Any] else { + throw CommandCodeUsageError.parseFailed("Credits: missing 'credits' object") + } + guard let monthly = self.double(from: credits["monthlyCredits"]) else { + throw CommandCodeUsageError.parseFailed("Credits: missing monthlyCredits") + } + return CreditsPayload( + monthlyCredits: monthly, + purchasedCredits: self.double(from: credits["purchasedCredits"]) ?? 0, + premiumMonthlyCredits: self.double(from: credits["premiumMonthlyCredits"]) ?? 0, + opensourceMonthlyCredits: self.double(from: credits["opensourceMonthlyCredits"]) ?? 0) + } + + static func parseSubscription(data: Data) throws -> SubscriptionPayload? { + guard let root = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else { + throw CommandCodeUsageError.parseFailed("Subscriptions: invalid JSON") + } + // Only an explicit successful null response identifies the free tier. Failure envelopes are transient. + guard let success = root["success"] as? Bool else { + throw CommandCodeUsageError.parseFailed("Subscriptions: missing success flag") + } + guard success else { + throw CommandCodeUsageError.parseFailed("Subscriptions: unsuccessful response") + } + guard let dataValue = root["data"] else { + throw CommandCodeUsageError.parseFailed("Subscriptions: missing data") + } + if dataValue is NSNull { + return nil + } + guard let data = dataValue as? [String: Any] else { + throw CommandCodeUsageError.parseFailed("Subscriptions: invalid data") + } + guard let planID = data["planId"] as? String, !planID.isEmpty else { + throw CommandCodeUsageError.parseFailed("Subscriptions: missing planId") + } + let status = (data["status"] as? String) ?? "unknown" + let periodEnd = self.date(from: data["currentPeriodEnd"]) + return SubscriptionPayload(planID: planID, status: status, currentPeriodEnd: periodEnd) + } + + // MARK: - Value coercion + + private static func double(from value: Any?) -> Double? { + switch value { + case let n as NSNumber: + let d = n.doubleValue + return d.isFinite ? d : nil + case let s as String: + let trimmed = s.trimmingCharacters(in: .whitespacesAndNewlines) + return Double(trimmed) + default: + return nil + } + } + + private static func date(from value: Any?) -> Date? { + guard let s = value as? String else { return nil } + let trimmed = s.trimmingCharacters(in: .whitespacesAndNewlines) + guard !trimmed.isEmpty else { return nil } + let fractional = ISO8601DateFormatter() + fractional.formatOptions = [.withInternetDateTime, .withFractionalSeconds] + if let date = fractional.date(from: trimmed) { return date } + let plain = ISO8601DateFormatter() + plain.formatOptions = [.withInternetDateTime] + return plain.date(from: trimmed) + } +} diff --git a/Sources/CodexBarCore/Providers/CommandCode/CommandCodeUsageSnapshot.swift b/Sources/CodexBarCore/Providers/CommandCode/CommandCodeUsageSnapshot.swift new file mode 100644 index 0000000..b5747a9 --- /dev/null +++ b/Sources/CodexBarCore/Providers/CommandCode/CommandCodeUsageSnapshot.swift @@ -0,0 +1,124 @@ +import Foundation + +/// Parsed view of CommandCode `/internal/billing/credits` + `/internal/billing/subscriptions`. +public struct CommandCodeUsageSnapshot: Sendable { + /// USD remaining in the current monthly grant (`credits.monthlyCredits`). + public let monthlyCreditsRemaining: Double + /// USD top-up balance carried over (`credits.purchasedCredits`). + public let purchasedCredits: Double + /// USD remaining in the premium monthly grant (`credits.premiumMonthlyCredits`). + public let premiumMonthlyCredits: Double + /// USD remaining in the open-source monthly grant (`credits.opensourceMonthlyCredits`). + public let opensourceMonthlyCredits: Double + /// Subscription plan, or nil when the user is on the free tier. + public let plan: CommandCodePlanCatalog.Plan? + /// `currentPeriodEnd` from the active subscription. + public let billingPeriodEnd: Date? + /// Subscription status (e.g. `active`, `canceled`). + public let subscriptionStatus: String? + /// The optional subscription request timed out or failed for this refresh. + public let subscriptionEnrichmentUnavailable: Bool + public let updatedAt: Date + + public init( + monthlyCreditsRemaining: Double, + purchasedCredits: Double, + premiumMonthlyCredits: Double, + opensourceMonthlyCredits: Double, + plan: CommandCodePlanCatalog.Plan?, + billingPeriodEnd: Date?, + subscriptionStatus: String?, + subscriptionEnrichmentUnavailable: Bool = false, + updatedAt: Date = Date()) + { + self.monthlyCreditsRemaining = monthlyCreditsRemaining + self.purchasedCredits = purchasedCredits + self.premiumMonthlyCredits = premiumMonthlyCredits + self.opensourceMonthlyCredits = opensourceMonthlyCredits + self.plan = plan + self.billingPeriodEnd = billingPeriodEnd + self.subscriptionStatus = subscriptionStatus + self.subscriptionEnrichmentUnavailable = subscriptionEnrichmentUnavailable + self.updatedAt = updatedAt + } + + /// USD allocation for the active monthly grant (from the catalog). + public var monthlyCreditsTotal: Double? { + self.plan?.monthlyCreditsUSD + } + + /// USD spent in the current monthly grant (total – remaining), clamped to [0, total]. + public var monthlyCreditsUsed: Double? { + guard let total = self.monthlyCreditsTotal else { return nil } + return max(0, min(total, total - self.monthlyCreditsRemaining)) + } + + public func toUsageSnapshot() -> UsageSnapshot { + let primary = self.makePrimaryWindow() + + let identity = ProviderIdentitySnapshot( + providerID: .commandcode, + accountEmail: nil, + accountOrganization: nil, + loginMethod: self.makeLoginMethod()) + + return UsageSnapshot( + primary: primary, + secondary: nil, + tertiary: nil, + providerCost: nil, + commandCodeSubscriptionEnrichmentUnavailable: self.subscriptionEnrichmentUnavailable, + commandCodeHasSubscriptionPlan: self.plan != nil, + commandCodeMonthlyGrantDepleted: self.monthlyCreditsRemaining <= 0, + updatedAt: self.updatedAt, + identity: identity) + } + + private func makePrimaryWindow() -> RateWindow? { + guard let total = self.monthlyCreditsTotal, total > 0 else { + // Free / unknown plan with no allowance — surface 100% so the bar renders empty. + if self.monthlyCreditsRemaining > 0 || self.purchasedCredits > 0 { + return RateWindow( + usedPercent: 0, + windowMinutes: nil, + resetsAt: self.billingPeriodEnd, + resetDescription: nil) + } + return nil + } + let used = self.monthlyCreditsUsed ?? 0 + let percent = min(100, max(0, (used / total) * 100)) + return RateWindow( + usedPercent: percent, + windowMinutes: nil, + resetsAt: self.billingPeriodEnd, + resetDescription: nil) + } + + private func makeLoginMethod() -> String? { + var parts: [String] = [] + if let name = self.plan?.displayName, !name.isEmpty { + parts.append(name) + } + if let total = self.monthlyCreditsTotal { + let used = self.monthlyCreditsUsed ?? 0 + parts.append("\(Self.formatUSD(used)) of \(Self.formatUSD(total))") + } else if self.monthlyCreditsRemaining > 0 { + parts.append("\(Self.formatUSD(self.monthlyCreditsRemaining)) remaining") + } + if self.purchasedCredits > 0 { + parts.append("+ \(Self.formatUSD(self.purchasedCredits)) credits") + } + return parts.isEmpty ? nil : parts.joined(separator: " · ") + } + + static func formatUSD(_ value: Double) -> String { + let formatter = NumberFormatter() + formatter.numberStyle = .currency + formatter.currencyCode = "USD" + formatter.locale = Locale(identifier: "en_US") + formatter.maximumFractionDigits = value < 100 ? 2 : 0 + formatter.minimumFractionDigits = value < 100 ? 2 : 0 + return formatter.string(from: NSNumber(value: value)) ?? "$\(value)" + } +} diff --git a/Sources/CodexBarCore/Providers/Copilot/CopilotBudgetWebFetcher.swift b/Sources/CodexBarCore/Providers/Copilot/CopilotBudgetWebFetcher.swift new file mode 100644 index 0000000..4c599fd --- /dev/null +++ b/Sources/CodexBarCore/Providers/Copilot/CopilotBudgetWebFetcher.swift @@ -0,0 +1,801 @@ +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif +#if os(macOS) +import SweetCookieKit +#endif + +public struct CopilotBudgetWebFetcher: Sendable { + public enum Error: Swift.Error, LocalizedError, Equatable { + case noSessionCookie + case notLoggedIn + case accountMismatch(expected: String, actual: String?) + case badStatus(Int) + case invalidResponse + + public var errorDescription: String? { + switch self { + case .noSessionCookie: + "No GitHub browser session cookie found." + case .notLoggedIn: + "GitHub browser session is not logged in." + case let .accountMismatch(expected, actual): + "GitHub browser session belongs to \(actual ?? "an unknown account"), expected \(expected)." + case let .badStatus(status): + "GitHub budgets request failed with HTTP \(status)." + case .invalidResponse: + "GitHub budgets response could not be decoded." + } + } + } + + struct BudgetResponse: Decodable { + let budgets: [Budget] + let hasNextPage: Bool? + + private enum CodingKeys: String, CodingKey { + case budgets + case payload + case hasNextPage + case hasNextPageSnake = "has_next_page" + } + + init(budgets: [Budget], hasNextPage: Bool? = nil) { + self.budgets = budgets + self.hasNextPage = hasNextPage + } + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + if let payload = try container.decodeIfPresent(BudgetResponse.self, forKey: .payload) { + self = payload + return + } + self.budgets = try container.decodeIfPresent([Budget].self, forKey: .budgets) ?? [] + self.hasNextPage = try container.decodeIfPresent(Bool.self, forKey: .hasNextPage) + ?? container.decodeIfPresent(Bool.self, forKey: .hasNextPageSnake) + } + } + + struct Budget: Decodable, Equatable { + let id: String? + let name: String? + let budgetType: String? + let budgetProductSkus: [String] + let budgetScope: String? + let budgetEntityName: String? + let budgetAmount: Double + let currentAmount: Double + + init( + id: String? = nil, + name: String? = nil, + budgetType: String? = nil, + budgetProductSkus: [String] = [], + budgetScope: String? = nil, + budgetEntityName: String? = nil, + budgetAmount: Double, + currentAmount: Double = 0) + { + self.id = id + self.name = name + self.budgetType = budgetType + self.budgetProductSkus = budgetProductSkus + self.budgetScope = budgetScope + self.budgetEntityName = budgetEntityName + self.budgetAmount = budgetAmount + self.currentAmount = currentAmount + } + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: DynamicCodingKey.self) + self.id = Self.decodeString(container: container, keys: ["id", "uuid", "budget_id", "budgetId"]) + self.name = Self.decodeString(container: container, keys: ["name", "display_name", "displayName", "title"]) + self.budgetType = Self.decodeString( + container: container, + keys: ["budget_type", "budgetType", "type", "pricing_target_type", "pricingTargetType"]) + self.budgetProductSkus = Self.decodeStringArray( + container: container, + keys: [ + "budget_product_skus", + "budgetProductSkus", + "budget_product_sku", + "budgetProductSku", + "product_skus", + "productSkus", + "skus", + "sku", + "product", + "product_name", + "productName", + "pricing_target_id", + "pricingTargetId", + ]) + self.budgetScope = Self.decodeString(container: container, keys: ["budget_scope", "budgetScope", "scope"]) + self.budgetEntityName = Self.decodeString( + container: container, + keys: [ + "budget_entity_name", + "budgetEntityName", + "entity_name", + "entityName", + "target_name", + "targetName", + ]) + self.budgetAmount = Self.decodeDouble( + container: container, + keys: [ + "budget_amount", + "budgetAmount", + "target_amount", + "targetAmount", + "spending_limit", + "spendingLimit", + "limit", + "amount", + "max", + ]) ?? 0 + self.currentAmount = Self.decodeDouble( + container: container, + keys: [ + "current_usage", + "currentUsage", + "current_amount", + "currentAmount", + "usage_amount", + "usageAmount", + "usage", + "spent", + "amount_used", + "amountUsed", + ]) ?? 0 + } + + var normalizedSelectors: Set { + let values = self.budgetProductSkus + [ + self.budgetType, + self.budgetEntityName, + self.name, + ].compactMap(\.self) + return Set(values.compactMap(CopilotBudgetWebFetcher.normalizedBillingIdentifier)) + } + + private static func decodeString( + container: KeyedDecodingContainer, + keys: [String]) -> String? + { + for key in keys { + guard let codingKey = DynamicCodingKey(key) else { continue } + if let value = try? container.decodeIfPresent(String.self, forKey: codingKey), !value.isEmpty { + return value + } + if let value = try? container.decodeIfPresent(Int.self, forKey: codingKey) { + return String(value) + } + } + return nil + } + + private static func decodeStringArray( + container: KeyedDecodingContainer, + keys: [String]) -> [String] + { + for key in keys { + guard let codingKey = DynamicCodingKey(key) else { continue } + if let values = try? container.decodeIfPresent([String].self, forKey: codingKey), !values.isEmpty { + return values + } + if let value = try? container.decodeIfPresent(String.self, forKey: codingKey), !value.isEmpty { + return [value] + } + if let values = try? container.decodeIfPresent([ProductSKU].self, forKey: codingKey), + !values.isEmpty + { + return values.flatMap(\.selectors) + } + } + return [] + } + + private static func decodeDouble( + container: KeyedDecodingContainer, + keys: [String]) -> Double? + { + for key in keys { + guard let codingKey = DynamicCodingKey(key) else { continue } + if let value = try? container.decodeIfPresent(Double.self, forKey: codingKey) { + return value + } + if let value = try? container.decodeIfPresent(Int.self, forKey: codingKey) { + return Double(value) + } + if let value = try? container.decodeIfPresent(String.self, forKey: codingKey), + let parsed = Self.parseAmount(value) + { + return parsed + } + if let value = try? container.decodeIfPresent(AmountValue.self, forKey: codingKey) { + return value.amount + } + } + return nil + } + + fileprivate static func parseAmount(_ value: String) -> Double? { + let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines) + let isNegative = trimmed.first == "-" + guard !trimmed.dropFirst(isNegative ? 1 : 0).contains("-") else { return nil } + let unsigned = trimmed.filter { $0.isNumber || $0 == "." } + guard !unsigned.isEmpty else { return nil } + return Double(isNegative ? "-\(unsigned)" : unsigned) + } + } + + struct GitHubWebIdentity: Equatable { + let id: String? + let login: String? + + init(id: String?, login: String?) { + let trimmedID = id?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" + let trimmedLogin = login?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" + self.id = trimmedID.isEmpty ? nil : trimmedID + self.login = trimmedLogin.isEmpty ? nil : trimmedLogin + } + + var displayName: String? { + self.login ?? self.id.map { "github:user:\($0)" } + } + } + + private struct ProductSKU: Decodable, Equatable { + let selectors: [String] + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: DynamicCodingKey.self) + self.selectors = [ + "sku", + "name", + "display_name", + "displayName", + "product", + "product_name", + "productName", + ].compactMap { key in + guard let codingKey = DynamicCodingKey(key) else { return nil } + return try? container.decodeIfPresent(String.self, forKey: codingKey) + } + } + } + + private struct AmountValue: Decodable { + let amount: Double? + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: DynamicCodingKey.self) + self.amount = [ + "amount", + "value", + "total", + "cents", + "formatted", + ].lazy.compactMap { key -> Double? in + guard let codingKey = DynamicCodingKey(key) else { return nil } + if let value = try? container.decodeIfPresent(Double.self, forKey: codingKey) { + return key == "cents" ? value / 100 : value + } + if let value = try? container.decodeIfPresent(Int.self, forKey: codingKey) { + return key == "cents" ? Double(value) / 100 : Double(value) + } + if let value = try? container.decodeIfPresent(String.self, forKey: codingKey) { + return Budget.parseAmount(value) + } + return nil + }.first + } + } + + private struct DynamicCodingKey: CodingKey { + let stringValue: String + let intValue: Int? + + init?(_ stringValue: String) { + self.stringValue = stringValue + self.intValue = nil + } + + init?(stringValue: String) { + self.init(stringValue) + } + + init?(intValue: Int) { + self.stringValue = String(intValue) + self.intValue = intValue + } + } + + private static let copilotProductID = "copilot" + private static let copilotPremiumRequestSKU = "copilot_premium_request" + private static let copilotAgentPremiumRequestSKU = "copilot_agent_premium_request" + private static let sparkPremiumRequestSKU = "spark_premium_request" + private static let copilotBudgetSelectors: Set = [ + copilotProductID, + copilotPremiumRequestSKU, + copilotAgentPremiumRequestSKU, + sparkPremiumRequestSKU, + ] + + private let cookieHeaderOverride: String? + private let expectedGitHubAccountIdentifier: String? + private let browserDetection: BrowserDetection + private let transport: any ProviderHTTPTransport + private let now: @Sendable () -> Date + + public init( + cookieHeaderOverride: String? = nil, + expectedGitHubAccountIdentifier: String? = nil, + browserDetection: BrowserDetection = BrowserDetection(), + transport: any ProviderHTTPTransport = ProviderHTTPClient.shared, + now: @escaping @Sendable () -> Date = { Date() }) + { + self.cookieHeaderOverride = CookieHeaderNormalizer.normalize(cookieHeaderOverride ?? "") + self.expectedGitHubAccountIdentifier = Self.normalizedExpectedAccountIdentifier( + expectedGitHubAccountIdentifier) + self.browserDetection = browserDetection + self.transport = transport + self.now = now + } + + public func fetchBudgetWindows() async throws -> [NamedRateWindow] { + if let cookieHeaderOverride, !cookieHeaderOverride.isEmpty { + return try await self.fetchBudgetWindows(cookieHeader: cookieHeaderOverride) + } + + if let cached = CookieHeaderCache.load(provider: .copilot), + !cached.cookieHeader.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty + { + do { + return try await self.fetchBudgetWindows(cookieHeader: cached.cookieHeader) + } catch { + if case Error.notLoggedIn = error { + CookieHeaderCache.clear(provider: .copilot) + } else if case Error.accountMismatch = error { + CookieHeaderCache.clear(provider: .copilot) + } else { + throw error + } + } + } + + #if os(macOS) + for session in CopilotGitHubCookieImporter.importSessions(browserDetection: self.browserDetection) { + do { + let windows = try await self.fetchBudgetWindows(cookieHeader: session.cookieHeader) + CookieHeaderCache.store( + provider: .copilot, + cookieHeader: session.cookieHeader, + sourceLabel: session.sourceLabel) + return windows + } catch { + if case Error.notLoggedIn = error { + continue + } + if case Error.accountMismatch = error { + continue + } + throw error + } + } + #endif + + throw Error.noSessionCookie + } + + func fetchBudgetWindows(cookieHeader: String) async throws -> [NamedRateWindow] { + let nonce = try await self.boundFetchNonce(cookieHeader: cookieHeader) + var allBudgets: [Budget] = [] + var page = 1 + let maxPages = 20 + var shouldContinue = true + while shouldContinue, page <= maxPages { + let response = try await self.fetchBudgetPage( + cookieHeader: cookieHeader, + nonce: nonce, + page: page) + allBudgets.append(contentsOf: response.budgets) + shouldContinue = response.hasNextPage == true + page += 1 + } + if shouldContinue { + CodexBarLog.logger(LogCategories.providers).warning( + "Copilot budget pagination reached page cap", + metadata: ["pageCap": "\(maxPages)"]) + } + return Self.extraRateWindows(from: allBudgets, now: self.now()) + } + + private func boundFetchNonce(cookieHeader: String) async throws -> String? { + guard self.expectedGitHubAccountIdentifier != nil else { + return await self.bestEffortFetchNonce(cookieHeader: cookieHeader) + } + let metadata = try await self.fetchBudgetPageMetadata(cookieHeader: cookieHeader) + try self.verifyExpectedGitHubAccount(metadata.identity) + return metadata.nonce + } + + private func bestEffortFetchNonce(cookieHeader: String) async -> String? { + do { + return try await self.fetchBudgetPageMetadata(cookieHeader: cookieHeader).nonce + } catch { + // GitHub accepts some budget requests without a nonce. Keep auth failures and + // page-shape changes non-fatal so a valid Cookie header can still be tried. + return nil + } + } + + private struct BudgetPageMetadata { + let nonce: String? + let identity: GitHubWebIdentity? + } + + private func fetchBudgetPageMetadata(cookieHeader: String) async throws -> BudgetPageMetadata { + guard let url = URL(string: "https://github.com/settings/billing/budgets") else { + throw URLError(.badURL) + } + var request = URLRequest(url: url) + request.timeoutInterval = 15 + request.setValue(cookieHeader, forHTTPHeaderField: "Cookie") + request.setValue("text/html,application/xhtml+xml", forHTTPHeaderField: "Accept") + request.setValue("CodexBar", forHTTPHeaderField: "User-Agent") + + let response = try await self.transport.response(for: request) + switch response.statusCode { + case 200: + guard let html = String(data: response.data, encoding: .utf8) else { throw Error.invalidResponse } + return BudgetPageMetadata( + nonce: Self.extractFetchNonce(from: html), + identity: Self.extractGitHubWebIdentity(from: html)) + case 401, 403: + throw Error.notLoggedIn + default: + throw Error.badStatus(response.statusCode) + } + } + + private func verifyExpectedGitHubAccount(_ actual: GitHubWebIdentity?) throws { + guard let expected = self.expectedGitHubAccountIdentifier else { return } + guard let actual else { throw Error.accountMismatch(expected: expected, actual: nil) } + guard Self.webIdentity(actual, matches: expected) else { + throw Error.accountMismatch(expected: expected, actual: actual.displayName) + } + } + + private func fetchBudgetPage(cookieHeader: String, nonce: String?, page: Int) async throws -> BudgetResponse { + guard var components = URLComponents(string: "https://github.com/settings/billing/budgets") else { + throw URLError(.badURL) + } + components.queryItems = [ + URLQueryItem(name: "page", value: "\(page)"), + URLQueryItem(name: "page_size", value: "10"), + URLQueryItem(name: "scope", value: "customer"), + ] + guard let url = components.url else { throw URLError(.badURL) } + var request = URLRequest(url: url) + request.timeoutInterval = 15 + request.setValue(cookieHeader, forHTTPHeaderField: "Cookie") + request.setValue("application/json", forHTTPHeaderField: "Accept") + request.setValue("https://github.com/settings/billing/budgets", forHTTPHeaderField: "Referer") + request.setValue("XMLHttpRequest", forHTTPHeaderField: "X-Requested-With") + request.setValue("true", forHTTPHeaderField: "GitHub-Verified-Fetch") + request.setValue("CodexBar", forHTTPHeaderField: "User-Agent") + if let nonce, !nonce.isEmpty { + request.setValue(nonce, forHTTPHeaderField: "X-Fetch-Nonce") + } + + let response = try await self.transport.response(for: request) + switch response.statusCode { + case 200: + do { + return try JSONDecoder().decode(BudgetResponse.self, from: response.data) + } catch { + throw Error.invalidResponse + } + case 401, 403: + throw Error.notLoggedIn + default: + throw Error.badStatus(response.statusCode) + } + } + + static func extractFetchNonce(from html: String) -> String? { + let patterns = [ + #"x-fetch-nonce"\s+content="([^"]+)""#, + #"X-Fetch-Nonce"\s*:\s*"([^"]+)""#, + #"fetchNonce"\s*:\s*"([^"]+)""#, + #"data-fetch-nonce="([^"]+)""#, + ] + for pattern in patterns { + guard let regex = try? NSRegularExpression(pattern: pattern, options: [.caseInsensitive]) else { + continue + } + let range = NSRange(html.startIndex.. GitHubWebIdentity? { + let id = self.extractMetaContent( + named: [ + "octolytics-actor-id", + "analytics-user-id", + "user-id", + ], + from: html) + let login = self.extractMetaContent( + named: [ + "user-login", + "octolytics-actor-login", + "analytics-user-login", + ], + from: html) + let identity = GitHubWebIdentity(id: id, login: login) + return identity.id == nil && identity.login == nil ? nil : identity + } + + private static let metaTagRegex = try? NSRegularExpression( + pattern: #"]*>"#, + options: [.caseInsensitive]) + + private static let metaAttributeRegex = try? NSRegularExpression( + pattern: #"([A-Za-z_:][-A-Za-z0-9_:.]*)\s*=\s*(['"])(.*?)\2"#, + options: [.caseInsensitive]) + + private static func extractMetaContent(named names: [String], from html: String) -> String? { + guard let metaTagRegex, let metaAttributeRegex else { return nil } + let expectedNames = Set(names.map { $0.lowercased() }) + var contentByName: [String: String] = [:] + let htmlRange = NSRange(html.startIndex.. Bool { + guard let expected = self.normalizedExpectedAccountIdentifier(expectedIdentifier), + let identity + else { return false } + if let expectedID = self.githubUserID(from: expected) { + return identity.id == expectedID + } + return identity.login?.lowercased() == expected + } + + static func normalizedGitHubAccountIdentifier(for identity: CopilotUsageFetcher.GitHubUserIdentity) -> String { + "github:user:\(identity.id)" + } + + private static func normalizedExpectedAccountIdentifier(_ identifier: String?) -> String? { + let trimmed = identifier?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" + return trimmed.isEmpty ? nil : trimmed.lowercased() + } + + private static func githubUserID(from identifier: String) -> String? { + let prefix = "github:user:" + guard identifier.hasPrefix(prefix) else { return nil } + let suffix = String(identifier.dropFirst(prefix.count)) + .trimmingCharacters(in: .whitespacesAndNewlines) + return suffix.isEmpty ? nil : suffix + } + + static func extraRateWindows(from budgets: [Budget], now: Date) -> [NamedRateWindow] { + var usedIDs = Set() + let resetDate = self.approximateNextMonthResetDate(now: now) + return budgets + .compactMap { budget in + let selectors = budget.normalizedSelectors + guard self.isCopilotBudget(budget, selectors: selectors) else { return nil } + let id = self.uniqueWindowID(for: budget, selectors: selectors, usedIDs: &usedIDs) + let usedPercent = budget.budgetAmount > 0 + ? min(999, max(0, budget.currentAmount / budget.budgetAmount * 100)) + : 0 + let window = RateWindow( + usedPercent: usedPercent, + windowMinutes: nil, + resetsAt: resetDate, + resetDescription: resetDate.map { + UsageFormatter.resetDescription(from: $0, now: now) + }) + return NamedRateWindow( + id: id, + title: self.windowTitle(for: budget, selectors: selectors), + window: window) + } + } + + private static func isCopilotBudget(_ budget: Budget, selectors: Set) -> Bool { + guard budget.budgetAmount > 0 else { return false } + return !selectors.isDisjoint(with: self.copilotBudgetSelectors) + } + + static func normalizedBillingIdentifier(_ value: String?) -> String? { + guard let value else { return nil } + let slug = self.slug(value) + guard !slug.isEmpty else { return nil } + let underscored = slug.replacingOccurrences(of: "-", with: "_") + if underscored == self.copilotProductID { + return self.copilotProductID + } + if underscored == "premium_request" || underscored == "premium_requests" { + return self.copilotPremiumRequestSKU + } + if underscored == "coding_agent_premium_request" || underscored == "coding_agent_premium_requests" { + return self.copilotAgentPremiumRequestSKU + } + if underscored.contains("spark"), underscored.contains("premium"), underscored.contains("request") { + return self.sparkPremiumRequestSKU + } + if underscored.contains("cloud") || underscored.contains("coding"), + underscored.contains("agent"), + underscored.contains("premium"), + underscored.contains("request") + { + return self.copilotAgentPremiumRequestSKU + } + if underscored.contains("bundled"), underscored.contains("premium"), underscored.contains("request") { + return self.copilotPremiumRequestSKU + } + if underscored.contains("copilot"), + underscored.contains("agent"), + underscored.contains("premium"), + underscored.contains("request") + { + return self.copilotAgentPremiumRequestSKU + } + if underscored.contains("copilot"), underscored.contains("premium"), underscored.contains("request") { + return self.copilotPremiumRequestSKU + } + return underscored + } + + private static func windowTitle(for budget: Budget, selectors: Set) -> String { + let budgetType = if selectors == [self.copilotProductID] { + "Copilot" + } else if selectors.contains(self.copilotAgentPremiumRequestSKU) { + "Copilot Agent Premium Requests" + } else if selectors.contains(self.sparkPremiumRequestSKU) { + "Spark Premium Requests" + } else if selectors.contains(self.copilotPremiumRequestSKU) { + "All Premium Request SKUs" + } else if let name = budget.name?.trimmingCharacters(in: .whitespacesAndNewlines), + !name.isEmpty + { + name + } else { + "Copilot Premium Requests" + } + return "Budget - \(budgetType)" + } + + private static func uniqueWindowID( + for budget: Budget, + selectors: Set, + usedIDs: inout Set) -> String + { + let source = budget.id ?? budget.budgetProductSkus.joined(separator: "-") + let slug = self.slug(source.isEmpty ? self.windowTitle(for: budget, selectors: selectors) : source) + let base = slug.isEmpty ? "copilot-budget" : "copilot-budget-\(slug)" + var candidate = base + var suffix = 2 + while !usedIDs.insert(candidate).inserted { + candidate = "\(base)-\(suffix)" + suffix += 1 + } + return candidate + } + + private static func approximateNextMonthResetDate(now: Date) -> Date? { + // GitHub's budget response does not expose a reset instant. Use the local + // start of next month as a display-only approximation. + var calendar = Calendar(identifier: .gregorian) + calendar.timeZone = .current + let components = calendar.dateComponents([.year, .month], from: now) + guard let monthStart = calendar.date(from: DateComponents( + year: components.year, + month: components.month, + day: 1)) + else { + return nil + } + return calendar.date(byAdding: .month, value: 1, to: monthStart) + } + + private static func slug(_ value: String) -> String { + var result = "" + var lastWasDash = false + for scalar in value.lowercased().unicodeScalars { + if CharacterSet.alphanumerics.contains(scalar) { + result.unicodeScalars.append(scalar) + lastWasDash = false + } else if !lastWasDash { + result.append("-") + lastWasDash = true + } + } + return result.trimmingCharacters(in: CharacterSet(charactersIn: "-")) + } +} + +#if os(macOS) +private enum CopilotGitHubCookieImporter { + private static let cookieClient = BrowserCookieClient() + private static let cookieImportOrder: BrowserCookieImportOrder = + ProviderDefaults.metadata[.copilot]?.browserCookieOrder ?? [.chrome] + private static let sessionCookieNames: Set = [ + "user_session", + "__Host-user_session_same_site", + "_gh_sess", + "logged_in", + "dotcom_user", + ] + + struct SessionInfo { + let cookies: [HTTPCookie] + let sourceLabel: String + + var cookieHeader: String { + self.cookies.map { "\($0.name)=\($0.value)" }.joined(separator: "; ") + } + } + + static func importSessions(browserDetection: BrowserDetection) -> [SessionInfo] { + let installedBrowsers = self.cookieImportOrder.cookieImportCandidates(using: browserDetection) + return installedBrowsers.flatMap { browser -> [SessionInfo] in + do { + return try self.importSessions(from: browser) + } catch { + BrowserCookieAccessGate.recordIfNeeded(error) + return [] + } + } + } + + private static func importSessions(from browser: Browser) throws -> [SessionInfo] { + let query = BrowserCookieQuery(domains: ["github.com", "www.github.com"]) + let sources = try self.cookieClient.codexBarRecords(matching: query, in: browser) + return sources.compactMap { source -> SessionInfo? in + guard !source.records.isEmpty else { return nil } + let cookies = BrowserCookieClient.makeHTTPCookies(source.records, origin: query.origin) + guard cookies.contains(where: { self.sessionCookieNames.contains($0.name) }) else { + return nil + } + return SessionInfo(cookies: cookies, sourceLabel: source.label) + } + } +} +#endif diff --git a/Sources/CodexBarCore/Providers/Copilot/CopilotDeviceFlow.swift b/Sources/CodexBarCore/Providers/Copilot/CopilotDeviceFlow.swift new file mode 100644 index 0000000..ed00333 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Copilot/CopilotDeviceFlow.swift @@ -0,0 +1,173 @@ +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +public struct CopilotDeviceFlow: Sendable { + public static let defaultHost = "github.com" + + private let clientID = "Iv1.b507a08c87ecfe98" // VS Code Client ID + private let scopes = "read:user" + private let host: String + + public struct DeviceCodeResponse: Decodable, Sendable { + public let deviceCode: String + public let userCode: String + public let verificationUri: String + public let verificationUriComplete: String? + public let expiresIn: Int + public let interval: Int + + public var verificationURLToOpen: String { + self.verificationUriComplete ?? self.verificationUri + } + + enum CodingKeys: String, CodingKey { + case deviceCode = "device_code" + case userCode = "user_code" + case verificationUri = "verification_uri" + case verificationUriComplete = "verification_uri_complete" + case expiresIn = "expires_in" + case interval + } + } + + public struct AccessTokenResponse: Decodable, Sendable { + public let accessToken: String + public let tokenType: String + public let scope: String + + enum CodingKeys: String, CodingKey { + case accessToken = "access_token" + case tokenType = "token_type" + case scope + } + } + + public init(enterpriseHost: String? = nil) { + self.host = Self.normalizedHost(enterpriseHost) + } + + public var deviceCodeURL: URL? { + Self.makeRequestURL(host: self.host, path: "/login/device/code") + } + + public var accessTokenURL: URL? { + Self.makeRequestURL(host: self.host, path: "/login/oauth/access_token") + } + + public static func normalizedHost(_ raw: String?) -> String { + guard var host = raw?.trimmingCharacters(in: .whitespacesAndNewlines), !host.isEmpty else { + return self.defaultHost + } + let componentsValue = host.contains("://") ? host : "https://\(host)" + if let components = URLComponents(string: componentsValue), + let parsedHost = components.host, + !parsedHost.isEmpty + { + host = parsedHost + if let port = components.port { + host += ":\(port)" + } + } else { + if host.hasPrefix("https://") { + host.removeFirst("https://".count) + } else if host.hasPrefix("http://") { + host.removeFirst("http://".count) + } + host = host.split(separator: "/", maxSplits: 1).first.map(String.init) ?? host + } + let normalized = host.trimmingCharacters(in: CharacterSet(charactersIn: ".")).lowercased() + return normalized.isEmpty ? Self.defaultHost : normalized + } + + public func requestDeviceCode() async throws -> DeviceCodeResponse { + guard let deviceCodeURL = self.deviceCodeURL else { + throw URLError(.badURL) + } + let request = URLRequest(url: deviceCodeURL) + + var postRequest = request + postRequest.httpMethod = "POST" + postRequest.setValue("application/json", forHTTPHeaderField: "Accept") + postRequest.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") + + let body = [ + "client_id": self.clientID, + "scope": self.scopes, + ] + postRequest.httpBody = Self.formURLEncodedBody(body) + + let response = try await ProviderHTTPClient.shared.response(for: postRequest) + + guard response.statusCode == 200 else { + throw URLError(.badServerResponse) + } + + return try JSONDecoder().decode(DeviceCodeResponse.self, from: response.data) + } + + public func pollForToken(deviceCode: String, interval: Int) async throws -> String { + guard let accessTokenURL = self.accessTokenURL else { + throw URLError(.badURL) + } + var request = URLRequest(url: accessTokenURL) + request.httpMethod = "POST" + request.setValue("application/json", forHTTPHeaderField: "Accept") + request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") + + let body = [ + "client_id": self.clientID, + "device_code": deviceCode, + "grant_type": "urn:ietf:params:oauth:grant-type:device_code", + ] + request.httpBody = Self.formURLEncodedBody(body) + + while true { + try await Task.sleep(nanoseconds: UInt64(interval) * 1_000_000_000) + try Task.checkCancellation() + + let response = try await ProviderHTTPClient.shared.response(for: request) + + // Check for error in JSON + if let json = try? JSONSerialization.jsonObject(with: response.data) as? [String: Any], + let error = json["error"] as? String + { + if error == "authorization_pending" { + continue + } + if error == "slow_down" { + try await Task.sleep(nanoseconds: 5_000_000_000) // Add 5s + continue + } + if error == "expired_token" { + throw URLError(.timedOut) + } + throw URLError(.userAuthenticationRequired) // Generic failure + } + + if let tokenResponse = try? JSONDecoder().decode(AccessTokenResponse.self, from: response.data) { + return tokenResponse.accessToken + } + } + } + + private static func formURLEncodedBody(_ parameters: [String: String]) -> Data { + let pairs = parameters + .map { key, value in + "\(Self.formEncode(key))=\(Self.formEncode(value))" + } + .joined(separator: "&") + return Data(pairs.utf8) + } + + static func makeRequestURL(host: String, path: String) -> URL? { + URL(string: "https://\(host)\(path)") + } + + private static func formEncode(_ value: String) -> String { + var allowed = CharacterSet.urlQueryAllowed + allowed.remove(charactersIn: "+&=") + return value.addingPercentEncoding(withAllowedCharacters: allowed) ?? value + } +} diff --git a/Sources/CodexBarCore/Providers/Copilot/CopilotProviderDescriptor.swift b/Sources/CodexBarCore/Providers/Copilot/CopilotProviderDescriptor.swift new file mode 100644 index 0000000..5a3b1f3 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Copilot/CopilotProviderDescriptor.swift @@ -0,0 +1,135 @@ +import Foundation + +public enum CopilotProviderDescriptor { + public static let descriptor: ProviderDescriptor = Self.makeDescriptor() + + static func makeDescriptor() -> ProviderDescriptor { + ProviderDescriptor( + id: .copilot, + metadata: ProviderMetadata( + id: .copilot, + displayName: "Copilot", + sessionLabel: "Premium", + weeklyLabel: "Chat", + opusLabel: nil, + supportsOpus: false, + supportsCredits: false, + creditsHint: "", + toggleTitle: "Show Copilot usage", + cliName: "copilot", + defaultEnabled: false, + isPrimaryProvider: false, + usesAccountFallback: false, + browserCookieOrder: ProviderBrowserCookieDefaults.copilotCookieImportOrder, + dashboardURL: "https://github.com/settings/copilot", + statusPageURL: "https://www.githubstatus.com/"), + branding: ProviderBranding( + iconStyle: .copilot, + iconResourceName: "ProviderIcon-copilot", + color: ProviderColor(red: 168 / 255, green: 85 / 255, blue: 247 / 255)), + tokenCost: ProviderTokenCostConfig( + supportsTokenCost: false, + noDataMessage: { "Copilot cost summary is not supported." }), + fetchPlan: ProviderFetchPlan( + sourceModes: [.auto, .api], + pipeline: ProviderFetchPipeline(resolveStrategies: { _ in [CopilotAPIFetchStrategy()] })), + cli: ProviderCLIConfig( + name: "copilot", + versionDetector: nil)) + } +} + +struct CopilotAPIFetchStrategy: ProviderFetchStrategy { + let id: String = "copilot.api" + let kind: ProviderFetchKind = .apiToken + + func isAvailable(_ context: ProviderFetchContext) async -> Bool { + Self.resolveToken(context: context) != nil + } + + func fetch(_ context: ProviderFetchContext) async throws -> ProviderFetchResult { + guard let token = Self.resolveToken(context: context), !token.isEmpty else { + throw URLError(.userAuthenticationRequired) + } + let fetcher = CopilotUsageFetcher( + token: token, + enterpriseHost: context.settings?.copilot?.enterpriseHost) + let usage = try await fetcher.fetch() + let snap = await self.addBudgetWindowsIfNeeded(to: usage, token: token, context: context) + return self.makeResult( + usage: snap, + sourceLabel: "api") + } + + func shouldFallback(on _: Error, context _: ProviderFetchContext) -> Bool { + false + } + + private static func resolveToken(context: ProviderFetchContext) -> String? { + ProviderTokenResolver.copilotToken(environment: context.env) + ?? ProviderTokenResolver.copilotResolution(environment: [ + "COPILOT_API_TOKEN": context.settings?.copilot?.apiToken ?? "", + ])?.token + } + + private func addBudgetWindowsIfNeeded( + to usage: UsageSnapshot, + token: String, + context: ProviderFetchContext) async -> UsageSnapshot + { + guard let settings = context.settings?.copilot, + settings.budgetExtrasEnabled, + settings.budgetCookieSource != .off + else { return usage } + + let manualCookieHeader = Self.budgetCookieHeaderOverride(from: settings) + if settings.budgetCookieSource == .manual, manualCookieHeader == nil { + return usage + } + do { + let expectedAccountIdentifier = try await self.expectedBudgetAccountIdentifier( + token: token, + settings: settings) + let extraRateWindows = try await CopilotBudgetWebFetcher( + cookieHeaderOverride: manualCookieHeader, + expectedGitHubAccountIdentifier: expectedAccountIdentifier, + browserDetection: context.browserDetection) + .fetchBudgetWindows() + guard !extraRateWindows.isEmpty else { return usage } + return usage.with(extraRateWindows: extraRateWindows) + } catch { + CodexBarLog.logger(LogCategories.providers).warning( + "Copilot budget extras unavailable", + metadata: ["error": "\(error.localizedDescription)"]) + return usage + } + } + + static func budgetCookieHeaderOverride( + from settings: ProviderSettingsSnapshot.CopilotProviderSettings) -> String? + { + guard settings.budgetCookieSource == .manual else { return nil } + return CookieHeaderNormalizer.normalize(settings.manualBudgetCookieHeader) + } + + private func expectedBudgetAccountIdentifier( + token: String, + settings: ProviderSettingsSnapshot.CopilotProviderSettings) async throws -> String + { + let identity = try await CopilotUsageFetcher.fetchGitHubIdentity(token: token) + let tokenIdentifier = CopilotBudgetWebFetcher.normalizedGitHubAccountIdentifier(for: identity) + if let selectedIdentifier = Self.normalizedBudgetAccountIdentifier(settings.selectedAccountExternalIdentifier), + selectedIdentifier != tokenIdentifier.lowercased(), + selectedIdentifier != identity.login.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() + { + CodexBarLog.logger(LogCategories.providers).warning( + "Ignoring stale Copilot account identifier") + } + return tokenIdentifier + } + + private static func normalizedBudgetAccountIdentifier(_ identifier: String?) -> String? { + let trimmed = identifier?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" + return trimmed.isEmpty ? nil : trimmed.lowercased() + } +} diff --git a/Sources/CodexBarCore/Providers/Copilot/CopilotUsageFetcher.swift b/Sources/CodexBarCore/Providers/Copilot/CopilotUsageFetcher.swift new file mode 100644 index 0000000..f9fe0fb --- /dev/null +++ b/Sources/CodexBarCore/Providers/Copilot/CopilotUsageFetcher.swift @@ -0,0 +1,186 @@ +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +public struct CopilotUsageFetcher: Sendable { + public struct GitHubUserIdentity: Decodable, Equatable, Sendable { + public let id: Int64 + public let login: String + + public init(id: Int64, login: String) { + self.id = id + self.login = login + } + } + + private let token: String + private let enterpriseHost: String? + private let transport: any ProviderHTTPTransport + + public init( + token: String, + enterpriseHost: String? = nil, + transport: any ProviderHTTPTransport = ProviderHTTPClient.shared) + { + self.token = token + self.enterpriseHost = enterpriseHost + self.transport = transport + } + + public static func apiHost(enterpriseHost: String?) -> String { + let host = CopilotDeviceFlow.normalizedHost(enterpriseHost) + if host == CopilotDeviceFlow.defaultHost { + return "api.github.com" + } + if host.hasPrefix("api.") { + return host + } + return "api.\(host)" + } + + public static func usageURL(enterpriseHost: String?) -> URL? { + CopilotDeviceFlow.makeRequestURL( + host: self.apiHost(enterpriseHost: enterpriseHost), + path: "/copilot_internal/user") + } + + public func fetch() async throws -> UsageSnapshot { + guard let url = Self.usageURL(enterpriseHost: self.enterpriseHost) else { + throw URLError(.badURL) + } + + var request = URLRequest(url: url) + // Use the GitHub OAuth token directly, not the Copilot token. + request.setValue("token \(self.token)", forHTTPHeaderField: "Authorization") + self.addCommonHeaders(to: &request) + + let response = try await self.transport.response(for: request) + + if response.statusCode == 401 || response.statusCode == 403 { + throw URLError(.userAuthenticationRequired) + } + + guard response.statusCode == 200 else { + throw URLError(.badServerResponse) + } + + let usage = try JSONDecoder().decode(CopilotUsageResponse.self, from: response.data) + let resetsAt = Self.parseQuotaResetDate(usage.quotaResetDate) + let premium = Self.makeRateWindow(from: usage.quotaSnapshots.premiumInteractions, resetsAt: resetsAt) + let chat = Self.makeRateWindow(from: usage.quotaSnapshots.chat, resetsAt: resetsAt) + + let primary: RateWindow? + let secondary: RateWindow? + if let premium { + primary = premium + secondary = chat + } else if let chatWindow = chat { + // Keep chat in the secondary slot so provider labels remain accurate + // ("Premium" for primary, "Chat" for secondary) on chat-only plans. + primary = nil + secondary = chatWindow + } else if usage.tokenBasedBilling { + // Copilot Business token-based billing currently exposes zero-entitlement + // placeholder quotas on this endpoint, so surface the plan without fake usage. + primary = nil + secondary = nil + } else { + throw URLError(.cannotDecodeRawData) + } + + let identity = ProviderIdentitySnapshot( + providerID: .copilot, + accountEmail: nil, + accountOrganization: nil, + loginMethod: usage.copilotPlan.capitalized) + return UsageSnapshot( + primary: primary, + secondary: secondary, + tertiary: nil, + providerCost: nil, + updatedAt: Date(), + identity: identity) + } + + public static func fetchGitHubUsername(token: String) async throws -> String { + try await self.fetchGitHubIdentity(token: token).login + } + + public static func fetchGitHubIdentity( + token: String, + transport: any ProviderHTTPTransport = ProviderHTTPClient.shared) + async throws -> GitHubUserIdentity + { + guard let url = URL(string: "https://api.github.com/user") else { + throw URLError(.badURL) + } + var request = URLRequest(url: url) + request.setValue("token \(token)", forHTTPHeaderField: "Authorization") + request.setValue("application/json", forHTTPHeaderField: "Accept") + + let response = try await transport.response(for: request) + switch response.statusCode { + case 200: + return try JSONDecoder().decode(GitHubUserIdentity.self, from: response.data) + case 401, 403: + throw URLError(.userAuthenticationRequired) + default: + throw URLError(.badServerResponse) + } + } + + private func addCommonHeaders(to request: inout URLRequest) { + request.setValue("application/json", forHTTPHeaderField: "Accept") + request.setValue("vscode/1.96.2", forHTTPHeaderField: "Editor-Version") + request.setValue("copilot-chat/0.26.7", forHTTPHeaderField: "Editor-Plugin-Version") + request.setValue("GitHubCopilotChat/0.26.7", forHTTPHeaderField: "User-Agent") + request.setValue("2025-04-01", forHTTPHeaderField: "X-Github-Api-Version") + } + + static func makeRateWindow( + from snapshot: CopilotUsageResponse.QuotaSnapshot?, + resetsAt: Date? = nil) -> RateWindow? + { + guard let snapshot else { return nil } + guard !snapshot.isPlaceholder else { return nil } + guard snapshot.hasPercentRemaining else { return nil } + let usedPercent = snapshot.usedPercent + let overQuotaDescription = snapshot.overQuotaUsedPercent.map { used in + String(format: "%.0f%% used", used) + } + let effectiveResetsAt = snapshot.unlimited ? nil : resetsAt + + return RateWindow( + usedPercent: usedPercent, + windowMinutes: nil, + resetsAt: effectiveResetsAt, + resetDescription: overQuotaDescription) + } + + static func parseQuotaResetDate(_ value: String?) -> Date? { + guard let raw = value?.trimmingCharacters(in: .whitespacesAndNewlines), !raw.isEmpty else { + return nil + } + + let fractionalISO = ISO8601DateFormatter() + fractionalISO.formatOptions = [.withInternetDateTime, .withFractionalSeconds] + if let date = fractionalISO.date(from: raw) { + return date + } + + let internetISO = ISO8601DateFormatter() + internetISO.formatOptions = [.withInternetDateTime] + if let date = internetISO.date(from: raw) { + return date + } + + let formatter = DateFormatter() + formatter.calendar = Calendar(identifier: .gregorian) + formatter.isLenient = false + formatter.locale = Locale(identifier: "en_US_POSIX") + formatter.timeZone = TimeZone(secondsFromGMT: 0) + formatter.dateFormat = "yyyy-MM-dd" + return formatter.date(from: raw) + } +} diff --git a/Sources/CodexBarCore/Providers/Crof/CrofProviderDescriptor.swift b/Sources/CodexBarCore/Providers/Crof/CrofProviderDescriptor.swift new file mode 100644 index 0000000..860733d --- /dev/null +++ b/Sources/CodexBarCore/Providers/Crof/CrofProviderDescriptor.swift @@ -0,0 +1,46 @@ +import Foundation + +public enum CrofProviderDescriptor { + public static let descriptor: ProviderDescriptor = Self.makeDescriptor() + + static func makeDescriptor() -> ProviderDescriptor { + ProviderDescriptor( + id: .crof, + metadata: ProviderMetadata( + id: .crof, + displayName: "Crof", + sessionLabel: "Requests", + weeklyLabel: "Credits", + opusLabel: nil, + supportsOpus: false, + supportsCredits: false, + creditsHint: "Credit balance from the Crof usage API", + toggleTitle: "Show Crof usage", + cliName: "crof", + defaultEnabled: false, + isPrimaryProvider: false, + usesAccountFallback: false, + browserCookieOrder: nil, + dashboardURL: "https://crof.ai/dashboard", + statusPageURL: nil, + statusLinkURL: nil), + branding: ProviderBranding( + iconStyle: .crof, + iconResourceName: "ProviderIcon-crof", + color: ProviderColor(red: 0.18, green: 0.67, blue: 0.58)), + tokenCost: ProviderTokenCostConfig( + supportsTokenCost: false, + noDataMessage: { "Crof cost summary is not available via API." }), + fetchPlan: .apiToken( + strategyID: "crof.api", + resolveToken: { ProviderTokenResolver.crofToken(environment: $0) }, + missingCredentialsError: { CrofUsageError.missingCredentials }, + loadUsage: { apiKey, _ in + try await CrofUsageFetcher.fetchUsage(apiKey: apiKey).toUsageSnapshot() + }), + cli: ProviderCLIConfig( + name: "crof", + aliases: ["crofai"], + versionDetector: nil)) + } +} diff --git a/Sources/CodexBarCore/Providers/Crof/CrofSettingsReader.swift b/Sources/CodexBarCore/Providers/Crof/CrofSettingsReader.swift new file mode 100644 index 0000000..14680a9 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Crof/CrofSettingsReader.swift @@ -0,0 +1,27 @@ +import Foundation + +public enum CrofSettingsReader { + public static let apiKeyEnvironmentKeys = ["CROF_API_KEY", "CROFAI_API_KEY"] + + public static func apiKey(environment: [String: String] = ProcessInfo.processInfo.environment) -> String? { + for key in self.apiKeyEnvironmentKeys { + if let value = self.cleaned(environment[key]) { + return value + } + } + return nil + } + + private static func cleaned(_ raw: String?) -> String? { + guard var value = raw?.trimmingCharacters(in: .whitespacesAndNewlines), !value.isEmpty else { + return nil + } + if (value.hasPrefix("\"") && value.hasSuffix("\"")) || + (value.hasPrefix("'") && value.hasSuffix("'")) + { + value = String(value.dropFirst().dropLast()) + } + value = value.trimmingCharacters(in: .whitespacesAndNewlines) + return value.isEmpty ? nil : value + } +} diff --git a/Sources/CodexBarCore/Providers/Crof/CrofUsageFetcher.swift b/Sources/CodexBarCore/Providers/Crof/CrofUsageFetcher.swift new file mode 100644 index 0000000..c8c3a4c --- /dev/null +++ b/Sources/CodexBarCore/Providers/Crof/CrofUsageFetcher.swift @@ -0,0 +1,89 @@ +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +public struct CrofUsageResponse: Decodable, Sendable { + public let credits: Double + public let requestsPlan: Double + public let usableRequests: Double + + enum CodingKeys: String, CodingKey { + case credits + case requestsPlan = "requests_plan" + case usableRequests = "usable_requests" + } +} + +public enum CrofUsageError: LocalizedError, Sendable, Equatable { + case missingCredentials + case networkError(String) + case apiError(Int) + case parseFailed(String) + + public var errorDescription: String? { + switch self { + case .missingCredentials: + "Missing Crof API key." + case let .networkError(message): + "Crof network error: \(message)" + case let .apiError(statusCode): + "Crof API error: HTTP \(statusCode)" + case let .parseFailed(message): + "Failed to parse Crof response: \(message)" + } + } +} + +public enum CrofUsageFetcher { + public static let usageURL = URL(string: "https://crof.ai/usage_api/")! + private static let timeoutSeconds: TimeInterval = 15 + + public static func fetchUsage( + apiKey: String, + session transport: any ProviderHTTPTransport = ProviderHTTPClient.shared) async throws -> CrofUsageSnapshot + { + let trimmed = apiKey.trimmingCharacters(in: .whitespacesAndNewlines) + guard !trimmed.isEmpty else { + throw CrofUsageError.missingCredentials + } + + var request = URLRequest(url: self.usageURL) + request.httpMethod = "GET" + request.timeoutInterval = Self.timeoutSeconds + request.setValue("Bearer \(trimmed)", forHTTPHeaderField: "Authorization") + request.setValue("application/json", forHTTPHeaderField: "Accept") + + let response: ProviderHTTPResponse + do { + response = try await transport.response(for: request) + } catch { + throw CrofUsageError.networkError(error.localizedDescription) + } + + guard response.statusCode == 200 else { + throw CrofUsageError.apiError(response.statusCode) + } + + return try self.parseSnapshot(response.data) + } + + static func _parseSnapshotForTesting(_ data: Data) throws -> CrofUsageSnapshot { + try self.parseSnapshot(data) + } + + private static func parseSnapshot(_ data: Data) throws -> CrofUsageSnapshot { + let decoded: CrofUsageResponse + do { + decoded = try JSONDecoder().decode(CrofUsageResponse.self, from: data) + } catch { + throw CrofUsageError.parseFailed(error.localizedDescription) + } + + return CrofUsageSnapshot( + credits: decoded.credits, + requestsPlan: decoded.requestsPlan, + usableRequests: decoded.usableRequests, + updatedAt: Date()) + } +} diff --git a/Sources/CodexBarCore/Providers/Crof/CrofUsageSnapshot.swift b/Sources/CodexBarCore/Providers/Crof/CrofUsageSnapshot.swift new file mode 100644 index 0000000..ee76bcb --- /dev/null +++ b/Sources/CodexBarCore/Providers/Crof/CrofUsageSnapshot.swift @@ -0,0 +1,83 @@ +import Foundation + +public struct CrofUsageSnapshot: Sendable { + private static let requestWindowMinutes = 24 * 60 + private static let resetTimeZone = TimeZone(identifier: "America/Chicago") ?? TimeZone(secondsFromGMT: -5)! + + public let credits: Double + public let requestsPlan: Double + public let usableRequests: Double + public let updatedAt: Date + + public init( + credits: Double, + requestsPlan: Double, + usableRequests: Double, + updatedAt: Date = Date()) + { + self.credits = credits + self.requestsPlan = requestsPlan + self.usableRequests = usableRequests + self.updatedAt = updatedAt + } + + public func toUsageSnapshot() -> UsageSnapshot { + let usedPercent: Double + if self.requestsPlan > 0 { + let usableRequests = max(0, min(self.requestsPlan, self.usableRequests)) + let remainingPercent = floor(usableRequests / self.requestsPlan * 100).clamped(to: 0...100) + usedPercent = 100 - remainingPercent + } else { + usedPercent = 100 + } + + let primary = RateWindow( + usedPercent: usedPercent, + windowMinutes: Self.requestWindowMinutes, + resetsAt: Self.nextRequestReset(after: self.updatedAt), + resetDescription: Self.formatRequestsLeft(self.usableRequests)) + + let creditsDetail = Self.formatCredits(self.credits) + let secondary = RateWindow( + // Crof returns a balance but no credit cap, so the bar only indicates present vs. exhausted credits. + usedPercent: self.credits > 0 ? 0 : 100, + windowMinutes: nil, + resetsAt: nil, + resetDescription: creditsDetail) + + return UsageSnapshot( + primary: primary, + secondary: secondary, + providerCost: nil, + updatedAt: self.updatedAt, + identity: ProviderIdentitySnapshot( + providerID: .crof, + accountEmail: nil, + accountOrganization: nil, + loginMethod: "API key")) + } + + private static func formatCredits(_ value: Double) -> String { + let clamped = max(0, value) + let cents = floor(clamped * 100) / 100 + return String(format: "$%.2f", cents) + } + + private static func formatRequestsLeft(_ value: Double) -> String { + let clamped = max(0, value) + let formatted = clamped.rounded() == clamped + ? String(format: "%.0f", clamped) + : String(format: "%.2f", clamped) + return "\(formatted) requests left" + } + + private static func nextRequestReset(after date: Date) -> Date? { + var calendar = Calendar(identifier: .gregorian) + calendar.timeZone = Self.resetTimeZone + + let startOfDay = calendar.startOfDay(for: date) + return startOfDay <= date + ? calendar.date(byAdding: .day, value: 1, to: startOfDay) + : startOfDay + } +} diff --git a/Sources/CodexBarCore/Providers/CrossModel/CrossModelProviderDescriptor.swift b/Sources/CodexBarCore/Providers/CrossModel/CrossModelProviderDescriptor.swift new file mode 100644 index 0000000..9a9c465 --- /dev/null +++ b/Sources/CodexBarCore/Providers/CrossModel/CrossModelProviderDescriptor.swift @@ -0,0 +1,63 @@ +import Foundation + +public enum CrossModelProviderDescriptor { + public static let descriptor: ProviderDescriptor = Self.makeDescriptor() + + static func makeDescriptor() -> ProviderDescriptor { + ProviderDescriptor( + id: .crossmodel, + metadata: ProviderMetadata( + id: .crossmodel, + displayName: "CrossModel", + sessionLabel: "Credits", + weeklyLabel: "Usage", + opusLabel: nil, + supportsOpus: false, + supportsCredits: false, + creditsHint: "", + toggleTitle: "Show CrossModel usage", + cliName: "crossmodel", + defaultEnabled: false, + isPrimaryProvider: false, + usesAccountFallback: false, + dashboardURL: "https://crossmodel.ai/console/usage", + statusPageURL: nil, + statusLinkURL: nil), + branding: ProviderBranding( + iconStyle: .crossmodel, + iconResourceName: "ProviderIcon-crossmodel", + color: ProviderColor(red: 124 / 255, green: 58 / 255, blue: 237 / 255)), + tokenCost: ProviderTokenCostConfig( + supportsTokenCost: false, + noDataMessage: { "CrossModel cost summary is not yet supported." }), + fetchPlan: .apiToken( + strategyID: "crossmodel.api", + resolveToken: { ProviderTokenResolver.crossModelToken(environment: $0) }, + missingCredentialsError: { CrossModelSettingsError.missingToken }, + loadUsage: { apiKey, context in + try await CrossModelUsageFetcher.fetchUsage( + apiKey: apiKey, + environment: context.env, + includeOptionalUsage: context.includeOptionalUsage).toUsageSnapshot() + }), + cli: ProviderCLIConfig( + name: "crossmodel", + aliases: ["cm"], + versionDetector: nil)) + } +} + +/// Errors related to CrossModel settings. +public enum CrossModelSettingsError: LocalizedError, Sendable, Equatable { + case missingToken + case invalidEndpointOverride(String) + + public var errorDescription: String? { + switch self { + case .missingToken: + "CrossModel API token not configured. Set CROSSMODEL_API_KEY environment variable or configure in Settings." + case let .invalidEndpointOverride(key): + "CrossModel endpoint override \(key) must use HTTPS (or a loopback HTTP host)." + } + } +} diff --git a/Sources/CodexBarCore/Providers/CrossModel/CrossModelSettingsReader.swift b/Sources/CodexBarCore/Providers/CrossModel/CrossModelSettingsReader.swift new file mode 100644 index 0000000..3e01237 --- /dev/null +++ b/Sources/CodexBarCore/Providers/CrossModel/CrossModelSettingsReader.swift @@ -0,0 +1,52 @@ +import Foundation + +/// Reads CrossModel settings from environment variables. +public enum CrossModelSettingsReader { + /// Environment variable key for the CrossModel API token. + public static let envKey = "CROSSMODEL_API_KEY" + /// Environment variable key for an optional API base URL override. + public static let urlEnvKey = "CROSSMODEL_API_URL" + + /// Returns the API token from environment if present and non-empty. + public static func apiToken(environment: [String: String] = ProcessInfo.processInfo.environment) -> String? { + self.cleaned(environment[self.envKey]) + } + + /// Returns the API base URL, defaulting to the production endpoint. + public static func apiURL(environment: [String: String] = ProcessInfo.processInfo.environment) -> URL { + if let override = self.validAPIURL(environment: environment) { + return override + } + return URL(string: "https://api.crossmodel.ai/v1")! + } + + public static func validateEndpointOverrides( + environment: [String: String] = ProcessInfo.processInfo.environment) throws + { + guard let raw = self.cleaned(environment[self.urlEnvKey]) else { return } + // Loopback HTTP is allowed so the provider can be exercised end-to-end + // against a locally running gateway during development. + guard ProviderEndpointOverrideValidator().validatedURLAllowingLoopbackHTTP(raw) == nil else { return } + throw CrossModelSettingsError.invalidEndpointOverride(self.urlEnvKey) + } + + static func cleaned(_ raw: String?) -> String? { + guard var value = raw?.trimmingCharacters(in: .whitespacesAndNewlines), !value.isEmpty else { + return nil + } + + if (value.hasPrefix("\"") && value.hasSuffix("\"")) || + (value.hasPrefix("'") && value.hasSuffix("'")) + { + value = String(value.dropFirst().dropLast()) + } + + value = value.trimmingCharacters(in: .whitespacesAndNewlines) + return value.isEmpty ? nil : value + } + + private static func validAPIURL(environment: [String: String]) -> URL? { + guard let raw = self.cleaned(environment[self.urlEnvKey]) else { return nil } + return ProviderEndpointOverrideValidator().validatedURLAllowingLoopbackHTTP(raw) + } +} diff --git a/Sources/CodexBarCore/Providers/CrossModel/CrossModelUsageStats.swift b/Sources/CodexBarCore/Providers/CrossModel/CrossModelUsageStats.swift new file mode 100644 index 0000000..7eb9242 --- /dev/null +++ b/Sources/CodexBarCore/Providers/CrossModel/CrossModelUsageStats.swift @@ -0,0 +1,417 @@ +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +// MARK: - Wire DTOs (CrossModel returns integer micro units; 1 major currency unit = 1_000_000 micro) + +/// `GET /v1/credits` response. +struct CrossModelCreditsResponse: Decodable { + let currency: String + let balanceMicro: Int64 + let uncollectedMicro: Int64 + + private enum CodingKeys: String, CodingKey { + case currency + case balanceMicro = "balance_micro" + case uncollectedMicro = "uncollected_micro" + } +} + +/// One usage window from `GET /v1/usage`. +struct CrossModelUsageWindowDTO: Decodable { + let costMicro: Int64 + let promptTokens: Int64 + let completionTokens: Int64 + let totalTokens: Int64 + let requestCount: Int64 + let successCount: Int64 + + private enum CodingKeys: String, CodingKey { + case costMicro = "cost_micro" + case promptTokens = "prompt_tokens" + case completionTokens = "completion_tokens" + case totalTokens = "total_tokens" + case requestCount = "request_count" + case successCount = "success_count" + } +} + +/// `GET /v1/usage` response. +struct CrossModelUsageResponse: Decodable { + let currency: String + let daily: CrossModelUsageWindowDTO + let weekly: CrossModelUsageWindowDTO + let monthly: CrossModelUsageWindowDTO +} + +// MARK: - Snapshot (currency-normalized, persisted in UsageSnapshot) + +/// One usage window with cost converted to the response currency's major unit. +public struct CrossModelUsageWindow: Codable, Sendable, Equatable { + public let cost: Double + public let promptTokens: Int + public let completionTokens: Int + public let totalTokens: Int + public let requestCount: Int + public let successCount: Int + + public init( + cost: Double, + promptTokens: Int, + completionTokens: Int, + totalTokens: Int, + requestCount: Int, + successCount: Int) + { + self.cost = cost + self.promptTokens = promptTokens + self.completionTokens = completionTokens + self.totalTokens = totalTokens + self.requestCount = requestCount + self.successCount = successCount + } + + init(dto: CrossModelUsageWindowDTO) { + self.cost = CrossModelUsageSnapshot.majorUnits(dto.costMicro) + self.promptTokens = Int(dto.promptTokens) + self.completionTokens = Int(dto.completionTokens) + self.totalTokens = Int(dto.totalTokens) + self.requestCount = Int(dto.requestCount) + self.successCount = Int(dto.successCount) + } +} + +/// Complete CrossModel usage snapshot: wallet balance plus UTC day/week/month spend. +public struct CrossModelUsageSnapshot: Codable, Sendable, Equatable { + public let currency: String + public let balance: Double + public let uncollected: Double + public let daily: CrossModelUsageWindow? + public let weekly: CrossModelUsageWindow? + public let monthly: CrossModelUsageWindow? + public let updatedAt: Date + + public init( + currency: String, + balance: Double, + uncollected: Double, + daily: CrossModelUsageWindow?, + weekly: CrossModelUsageWindow?, + monthly: CrossModelUsageWindow?, + updatedAt: Date) + { + self.currency = Self.normalizedCurrency(currency) + self.balance = balance + self.uncollected = uncollected + self.daily = daily + self.weekly = weekly + self.monthly = monthly + self.updatedAt = updatedAt + } + + static func majorUnits(_ micro: Int64) -> Double { + Double(micro) / 1_000_000.0 + } + + static func normalizedCurrency(_ raw: String) -> String { + raw.trimmingCharacters(in: .whitespacesAndNewlines).uppercased() + } + + /// Formatted balance for provider-owned menu/status display. + public var balanceDisplay: String { + self.currencyString(self.balance) + } + + public func currencyString(_ value: Double) -> String { + UsageFormatter.currencyString(value, currencyCode: self.currency) + } +} + +extension CrossModelUsageSnapshot { + public func toUsageSnapshot() -> UsageSnapshot { + let identity = ProviderIdentitySnapshot( + providerID: .crossmodel, + accountEmail: nil, + accountOrganization: nil, + loginMethod: "API key") + + return UsageSnapshot( + primary: nil, + secondary: nil, + tertiary: nil, + crossModelUsage: self, + updatedAt: self.updatedAt, + identity: identity, + dataConfidence: .exact) + } +} + +// MARK: - Fetcher + +/// Fetches balance + usage stats from the CrossModel API. +public struct CrossModelUsageFetcher: Sendable { + private static let log = CodexBarLog.logger(LogCategories.crossModelUsage) + private static let creditsRequestTimeoutSeconds: TimeInterval = 15 + private static let usageRequestTimeoutSeconds: TimeInterval = 3 + private static let maxErrorBodyLength = 240 + + /// Fetches balance (required) and usage windows (best-effort) using the provided API key. + public static func fetchUsage( + apiKey: String, + environment: [String: String] = ProcessInfo.processInfo.environment, + includeOptionalUsage: Bool = true, + transport: any ProviderHTTPTransport = ProviderHTTPClient.shared, + usageJoinGrace: Duration = .seconds(3)) async throws -> CrossModelUsageSnapshot + { + guard !apiKey.isEmpty else { + throw CrossModelUsageError.invalidCredentials + } + try CrossModelSettingsReader.validateEndpointOverrides(environment: environment) + + let baseURL = CrossModelSettingsReader.apiURL(environment: environment) + let credits = try await self.fetchCredits(apiKey: apiKey, baseURL: baseURL, transport: transport) + let currency = try self.normalizedResponseCurrency(credits.currency, endpoint: "credits") + + guard includeOptionalUsage else { + return CrossModelUsageSnapshot( + currency: currency, + balance: CrossModelUsageSnapshot.majorUnits(credits.balanceMicro), + uncollected: CrossModelUsageSnapshot.majorUnits(credits.uncollectedMicro), + daily: nil, + weekly: nil, + monthly: nil, + updatedAt: Date()) + } + + // Usage windows are best-effort: a slow or failing /usage call should not + // block the balance the user came to see. + let usage = try await self.fetchUsageWindows( + apiKey: apiKey, + baseURL: baseURL, + transport: transport, + joinGrace: usageJoinGrace) + let validatedUsage: CrossModelUsageResponse? + if let usage { + let usageCurrency: String + do { + usageCurrency = try self.normalizedResponseCurrency(usage.currency, endpoint: "usage") + } catch { + Self.log.error("CrossModel /usage omitted: invalid currency") + validatedUsage = nil + return CrossModelUsageSnapshot( + currency: currency, + balance: CrossModelUsageSnapshot.majorUnits(credits.balanceMicro), + uncollected: CrossModelUsageSnapshot.majorUnits(credits.uncollectedMicro), + daily: nil, + weekly: nil, + monthly: nil, + updatedAt: Date()) + } + guard usageCurrency == currency else { + Self.log.error("CrossModel currency mismatch: credits=\(currency) usage=\(usageCurrency)") + return CrossModelUsageSnapshot( + currency: currency, + balance: CrossModelUsageSnapshot.majorUnits(credits.balanceMicro), + uncollected: CrossModelUsageSnapshot.majorUnits(credits.uncollectedMicro), + daily: nil, + weekly: nil, + monthly: nil, + updatedAt: Date()) + } + validatedUsage = usage + } else { + validatedUsage = nil + } + + return CrossModelUsageSnapshot( + currency: currency, + balance: CrossModelUsageSnapshot.majorUnits(credits.balanceMicro), + uncollected: CrossModelUsageSnapshot.majorUnits(credits.uncollectedMicro), + daily: validatedUsage.map { CrossModelUsageWindow(dto: $0.daily) }, + weekly: validatedUsage.map { CrossModelUsageWindow(dto: $0.weekly) }, + monthly: validatedUsage.map { CrossModelUsageWindow(dto: $0.monthly) }, + updatedAt: Date()) + } + + private static func fetchCredits( + apiKey: String, + baseURL: URL, + transport: any ProviderHTTPTransport) async throws -> CrossModelCreditsResponse + { + let url = baseURL.appendingPathComponent("credits") + var request = URLRequest(url: url) + request.httpMethod = "GET" + request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization") + request.setValue("application/json", forHTTPHeaderField: "Accept") + request.timeoutInterval = Self.creditsRequestTimeoutSeconds + + let response = try await transport.response(for: request) + guard response.statusCode == 200 else { + let summary = LogRedactor.redact(Self.sanitizedResponseBodySummary(response.data)) + Self.log.error("CrossModel /credits returned \(response.statusCode): \(summary)") + if response.statusCode == 401 || response.statusCode == 403 { + throw CrossModelUsageError.invalidCredentials + } + throw CrossModelUsageError.apiError("HTTP \(response.statusCode)") + } + try self.validateSameOrigin(response: response, request: request, endpoint: "credits") + + do { + return try JSONDecoder().decode(CrossModelCreditsResponse.self, from: response.data) + } catch let error as DecodingError { + Self.log.error("CrossModel /credits decode error: \(error.localizedDescription)") + throw CrossModelUsageError.parseFailed(error.localizedDescription) + } + } + + private static func fetchUsageWindows( + apiKey: String, + baseURL: URL, + transport: any ProviderHTTPTransport, + joinGrace: Duration) async throws -> CrossModelUsageResponse? + { + let url = baseURL.appendingPathComponent("usage") + var request = URLRequest(url: url) + request.httpMethod = "GET" + request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization") + request.setValue("application/json", forHTTPHeaderField: "Accept") + request.timeoutInterval = Self.usageRequestTimeoutSeconds + + let sourceTask = Task { + let response = try await transport.response(for: request) + guard response.statusCode == 200 else { + Self.log.debug("CrossModel /usage enrichment returned \(response.statusCode)") + return nil + } + try self.validateSameOrigin(response: response, request: request, endpoint: "usage") + return try JSONDecoder().decode(CrossModelUsageResponse.self, from: response.data) + } + let join = BoundedTaskJoin(sourceTask: sourceTask) + let outcome = await join.value(joinGrace: joinGrace) + do { + switch outcome { + case let .value(response): + return response + case .timedOut: + Self.log.debug("Timed out fetching CrossModel /usage enrichment") + return nil + case let .failure(error): + throw error + } + } catch is CancellationError { + throw CancellationError() + } catch let error as URLError where error.code == .cancelled { + throw CancellationError() + } catch { + if Task.isCancelled { + throw CancellationError() + } + Self.log.debug("Failed to fetch CrossModel /usage enrichment: \(error.localizedDescription)") + return nil + } + } + + private static func normalizedResponseCurrency(_ raw: String, endpoint: String) throws -> String { + let currency = CrossModelUsageSnapshot.normalizedCurrency(raw) + guard !currency.isEmpty else { + throw CrossModelUsageError.parseFailed("Missing CrossModel /\(endpoint) currency") + } + return currency + } + + private static func validateSameOrigin( + response: ProviderHTTPResponse, + request: URLRequest, + endpoint: String) throws + { + guard let requestURL = request.url, + let responseURL = response.response.url, + let requestHost = requestURL.host?.lowercased(), + let responseHost = responseURL.host?.lowercased(), + requestURL.scheme?.lowercased() == responseURL.scheme?.lowercased(), + requestHost == responseHost, + self.effectivePort(for: requestURL) == self.effectivePort(for: responseURL) + else { + throw CrossModelUsageError.apiError("CrossModel /\(endpoint) redirected to a different origin") + } + } + + private static func effectivePort(for url: URL) -> Int? { + if let port = url.port { + return port + } + switch url.scheme?.lowercased() { + case "https": + return 443 + case "http": + return 80 + default: + return nil + } + } + + private static func sanitizedResponseBodySummary(_ data: Data) -> String { + guard !data.isEmpty else { return "empty body" } + guard let rawBody = String(bytes: data, encoding: .utf8) else { + return "non-text body (\(data.count) bytes)" + } + + let body = Self.redactSensitiveBodyContent(rawBody) + .replacingOccurrences(of: #"\s+"#, with: " ", options: .regularExpression) + .trimmingCharacters(in: .whitespacesAndNewlines) + + guard !body.isEmpty else { return "non-text body (\(data.count) bytes)" } + guard body.count > Self.maxErrorBodyLength else { return body } + + let index = body.index(body.startIndex, offsetBy: Self.maxErrorBodyLength) + return "\(body[.. String { + let replacements: [(String, String)] = [ + (#"(?i)(bearer\s+)[A-Za-z0-9._\-]+"#, "$1[REDACTED]"), + (#"(?i)(cm-)[A-Za-z0-9._\-]+"#, "$1[REDACTED]"), + ( + #"(?i)(\"(?:api_?key|authorization|token|access_token|refresh_token)\"\s*:\s*\")([^\"]+)(\")"#, + "$1[REDACTED]$3"), + ( + #"(?i)((?:api_?key|authorization|token|access_token|refresh_token)\s*[=:]\s*)([^,\s]+)"#, + "$1[REDACTED]"), + ] + + return replacements.reduce(text) { partial, replacement in + partial.replacingOccurrences( + of: replacement.0, + with: replacement.1, + options: .regularExpression) + } + } + + #if DEBUG + static func _sanitizedResponseBodySummaryForTesting(_ body: String) -> String { + self.sanitizedResponseBodySummary(Data(body.utf8)) + } + #endif +} + +/// Errors that can occur during CrossModel usage fetching. +public enum CrossModelUsageError: LocalizedError, Sendable, Equatable { + case invalidCredentials + case networkError(String) + case apiError(String) + case parseFailed(String) + + public var errorDescription: String? { + switch self { + case .invalidCredentials: + "Invalid CrossModel API credentials" + case let .networkError(message): + "CrossModel network error: \(message)" + case let .apiError(message): + "CrossModel API error: \(message)" + case let .parseFailed(message): + "Failed to parse CrossModel response: \(message)" + } + } +} diff --git a/Sources/CodexBarCore/Providers/Cursor/CursorProviderDescriptor.swift b/Sources/CodexBarCore/Providers/Cursor/CursorProviderDescriptor.swift new file mode 100644 index 0000000..983cae2 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Cursor/CursorProviderDescriptor.swift @@ -0,0 +1,70 @@ +import Foundation + +public enum CursorProviderDescriptor { + public static let descriptor: ProviderDescriptor = Self.makeDescriptor() + + static func makeDescriptor() -> ProviderDescriptor { + ProviderDescriptor( + id: .cursor, + metadata: ProviderMetadata( + id: .cursor, + displayName: "Cursor", + sessionLabel: "Total", + weeklyLabel: "Auto", + opusLabel: "API", + supportsOpus: true, + supportsCredits: true, + creditsHint: "On-demand usage beyond included plan limits.", + toggleTitle: "Show Cursor usage", + cliName: "cursor", + defaultEnabled: false, + isPrimaryProvider: false, + usesAccountFallback: false, + browserCookieOrder: ProviderBrowserCookieDefaults.cursorCookieImportOrder + ?? ProviderBrowserCookieDefaults.defaultImportOrder, + dashboardURL: "https://cursor.com/dashboard?tab=usage", + statusPageURL: "https://status.cursor.com", + statusLinkURL: nil), + branding: ProviderBranding( + iconStyle: .cursor, + iconResourceName: "ProviderIcon-cursor", + color: ProviderColor(red: 0 / 255, green: 191 / 255, blue: 165 / 255)), + tokenCost: ProviderTokenCostConfig( + supportsTokenCost: false, + noDataMessage: { "Cursor cost summary is not supported." }), + fetchPlan: ProviderFetchPlan( + sourceModes: [.auto, .cli, .web], + pipeline: ProviderFetchPipeline(resolveStrategies: { _ in [CursorStatusFetchStrategy()] })), + cli: ProviderCLIConfig( + name: "cursor", + versionDetector: nil)) + } +} + +struct CursorStatusFetchStrategy: ProviderFetchStrategy { + let id: String = "cursor.web" + let kind: ProviderFetchKind = .web + + func isAvailable(_ context: ProviderFetchContext) async -> Bool { + guard context.settings?.cursor?.cookieSource != .off else { return false } + return true + } + + func fetch(_ context: ProviderFetchContext) async throws -> ProviderFetchResult { + let probe = CursorStatusProbe(browserDetection: context.browserDetection) + let manual = Self.manualCookieHeader(from: context) + let snap = try await probe.fetch(cookieHeaderOverride: manual) + return self.makeResult( + usage: snap.toUsageSnapshot(), + sourceLabel: "web") + } + + func shouldFallback(on _: Error, context _: ProviderFetchContext) -> Bool { + false + } + + private static func manualCookieHeader(from context: ProviderFetchContext) -> String? { + guard context.settings?.cursor?.cookieSource == .manual else { return nil } + return CookieHeaderNormalizer.normalize(context.settings?.cursor?.manualCookieHeader) + } +} diff --git a/Sources/CodexBarCore/Providers/Cursor/CursorRequestUsage.swift b/Sources/CodexBarCore/Providers/Cursor/CursorRequestUsage.swift new file mode 100644 index 0000000..7bba64f --- /dev/null +++ b/Sources/CodexBarCore/Providers/Cursor/CursorRequestUsage.swift @@ -0,0 +1,23 @@ +import Foundation + +/// Request usage snapshot for legacy Cursor plans (request-based instead of token-based). +public struct CursorRequestUsage: Codable, Sendable { + /// Requests used this billing cycle + public let used: Int + /// Request limit (e.g., 500 for legacy enterprise plans) + public let limit: Int + + public init(used: Int, limit: Int) { + self.used = used + self.limit = limit + } + + public var usedPercent: Double { + guard self.limit > 0 else { return 0 } + return (Double(self.used) / Double(self.limit)) * 100 + } + + public var remainingPercent: Double { + max(0, 100 - self.usedPercent) + } +} diff --git a/Sources/CodexBarCore/Providers/Cursor/CursorStatusProbe.swift b/Sources/CodexBarCore/Providers/Cursor/CursorStatusProbe.swift new file mode 100644 index 0000000..bff2b00 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Cursor/CursorStatusProbe.swift @@ -0,0 +1,1475 @@ +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif +import SweetCookieKit +#if canImport(SQLite3) +import SQLite3 +#elseif canImport(CSQLite3) +import CSQLite3 +#endif + +#if os(macOS) || os(Linux) + +#if os(macOS) +private let cursorCookieImportOrder: BrowserCookieImportOrder = + ProviderDefaults.metadata[.cursor]?.browserCookieOrder ?? Browser.defaultImportOrder +#endif + +#if os(macOS) + +// MARK: - Cursor Cookie Importer + +/// Imports Cursor session cookies from browser cookies. +public enum CursorCookieImporter { + private static let cookieClient = BrowserCookieClient() + private static let sessionCookieNames: Set = [ + "WorkosCursorSessionToken", + "__Secure-next-auth.session-token", + "next-auth.session-token", + // WorkOS AuthKit (common default; configurable server-side) + "wos-session", + "__Secure-wos-session", + // Auth.js v5 + "authjs.session-token", + "__Secure-authjs.session-token", + ] + + /// Hosts whose cookies may authenticate Cursor web/API requests. + private static let cookieDomains = [ + "cursor.com", + "www.cursor.com", + "cursor.sh", + "authenticator.cursor.sh", + ] + + public struct SessionInfo: Sendable { + public let cookies: [HTTPCookie] + public let sourceLabel: String + + public init(cookies: [HTTPCookie], sourceLabel: String) { + self.cookies = cookies + self.sourceLabel = sourceLabel + } + + public var cookieHeader: String { + self.cookies.map { "\($0.name)=\($0.value)" }.joined(separator: "; ") + } + } + + /// Reads Cursor session cookies from one browser if present (no fallback to other browsers). + static func importSessionIfPresent( + browser: Browser, + browserDetection: BrowserDetection, + logger: ((String) -> Void)? = nil) -> SessionInfo? + { + self.importSessionsIfPresent( + browser: browser, + browserDetection: browserDetection, + logger: logger).first + } + + /// Reads all Cursor session-cookie candidates from one browser source order. + static func importSessionsIfPresent( + browser: Browser, + browserDetection: BrowserDetection, + logger: ((String) -> Void)? = nil) -> [SessionInfo] + { + self.importCookiesFromBrowser( + browser: browser, + browserDetection: browserDetection, + requireKnownSessionName: true, + logger: logger) + } + + /// Like ``importSessionIfPresent`` but accepts any non-empty cookie set for Cursor domains so the API can validate + /// (used after the strict name pass fails — e.g. new cookie names or host-only cookies). + static func importDomainCookiesIfPresent( + browser: Browser, + browserDetection: BrowserDetection, + logger: ((String) -> Void)? = nil) -> SessionInfo? + { + self.importDomainCookieSessionsIfPresent( + browser: browser, + browserDetection: browserDetection, + logger: logger).first + } + + /// Reads fallback cookie candidates whose names are not already covered by the strict session-cookie pass. + static func importDomainCookieSessionsIfPresent( + browser: Browser, + browserDetection: BrowserDetection, + logger: ((String) -> Void)? = nil) -> [SessionInfo] + { + self.importCookiesFromBrowser( + browser: browser, + browserDetection: browserDetection, + requireKnownSessionName: false, + logger: logger) + } + + private static func importCookiesFromBrowser( + browser: Browser, + browserDetection: BrowserDetection, + requireKnownSessionName: Bool, + logger: ((String) -> Void)?) -> [SessionInfo] + { + let log: (String) -> Void = { msg in logger?("[cursor-cookie] \(msg)") } + guard browserDetection.isCookieSourceAvailable(browser) else { return [] } + guard BrowserCookieAccessGate.shouldAttempt(browser) else { return [] } + + do { + let query = BrowserCookieQuery(domains: Self.cookieDomains) + let sources = try Self.cookieClient.codexBarRecords( + matching: query, + in: browser, + logger: log) + var sessions: [SessionInfo] = [] + for source in sources where !source.records.isEmpty { + let httpCookies = BrowserCookieClient.makeHTTPCookies(source.records, origin: query.origin) + let hasNamedSession = httpCookies.contains(where: { Self.sessionCookieNames.contains($0.name) }) + if hasNamedSession { + log("Found \(httpCookies.count) Cursor cookies in \(source.label)") + if requireKnownSessionName { + sessions.append(SessionInfo(cookies: httpCookies, sourceLabel: source.label)) + } + continue + } + if !requireKnownSessionName, !httpCookies.isEmpty { + log( + "Found \(httpCookies.count) Cursor domain cookies in \(source.label) " + + "(no known session name); will validate via API") + sessions.append(SessionInfo( + cookies: httpCookies, + sourceLabel: "\(source.label) (domain cookies)")) + continue + } + log("\(source.label) cookies found, but no Cursor session cookie present") + } + return sessions + } catch { + BrowserCookieAccessGate.recordIfNeeded(error) + log("\(browser.displayName) cookie import failed: \(error.localizedDescription)") + } + return [] + } + + /// Attempts to import Cursor cookies using the standard browser import order. + public static func importSession( + browserDetection: BrowserDetection, + logger: ((String) -> Void)? = nil) throws -> SessionInfo + { + let installedBrowsers = cursorCookieImportOrder.cookieImportCandidates(using: browserDetection) + for browserSource in installedBrowsers { + if let session = Self.importSessionsIfPresent( + browser: browserSource, + browserDetection: browserDetection, + logger: logger).first + { + return session + } + } + for browserSource in installedBrowsers { + if let session = Self.importDomainCookieSessionsIfPresent( + browser: browserSource, + browserDetection: browserDetection, + logger: logger).first + { + return session + } + } + + throw CursorStatusProbeError.noSessionCookie + } + + /// Check if Cursor session cookies are available + public static func hasSession(browserDetection: BrowserDetection, logger: ((String) -> Void)? = nil) -> Bool { + do { + let session = try self.importSession(browserDetection: browserDetection, logger: logger) + return !session.cookies.isEmpty + } catch { + return false + } + } +} +#endif + +// MARK: - Cursor API Models + +public struct CursorUsageSummary: Codable, Sendable { + public let billingCycleStart: String? + public let billingCycleEnd: String? + public let membershipType: String? + public let limitType: String? + public let isUnlimited: Bool? + public let autoModelSelectedDisplayMessage: String? + public let namedModelSelectedDisplayMessage: String? + public let individualUsage: CursorIndividualUsage? + public let teamUsage: CursorTeamUsage? +} + +public struct CursorIndividualUsage: Codable, Sendable { + public let plan: CursorPlanUsage? + public let onDemand: CursorOnDemandUsage? + /// Enterprise / team-member personal cap. Reported by Cursor when the account is part of a team or + /// enterprise plan with an individual quota. Values follow the same cents-based units as `plan`. + public let overall: CursorOverallUsage? + + public init( + plan: CursorPlanUsage? = nil, + onDemand: CursorOnDemandUsage? = nil, + overall: CursorOverallUsage? = nil) + { + self.plan = plan + self.onDemand = onDemand + self.overall = overall + } +} + +/// Personal cap reported under `individualUsage.overall` for Enterprise/Team members. +/// Mirrors the shape of `CursorOnDemandUsage`; values are in cents. +public struct CursorOverallUsage: Codable, Sendable { + public let enabled: Bool? + /// Usage in cents (e.g., 7384 = $73.84) + public let used: Int? + /// Limit in cents (e.g., 10000 = $100.00). `nil` indicates the API omitted a numeric cap. + public let limit: Int? + /// Remaining in cents. + public let remaining: Int? + + public init(enabled: Bool? = nil, used: Int? = nil, limit: Int? = nil, remaining: Int? = nil) { + self.enabled = enabled + self.used = used + self.limit = limit + self.remaining = remaining + } +} + +public struct CursorPlanUsage: Codable, Sendable { + public let enabled: Bool? + /// Usage in cents (e.g., 2000 = $20.00) + public let used: Int? + /// Limit in cents (e.g., 2000 = $20.00) + public let limit: Int? + /// Remaining in cents + public let remaining: Int? + public let breakdown: CursorPlanBreakdown? + public let autoPercentUsed: Double? + public let apiPercentUsed: Double? + public let totalPercentUsed: Double? +} + +public struct CursorPlanBreakdown: Codable, Sendable { + public let included: Int? + public let bonus: Int? + public let total: Int? +} + +public struct CursorOnDemandUsage: Codable, Sendable { + public let enabled: Bool? + /// Usage in cents + public let used: Int? + /// Limit in cents (nil if unlimited) + public let limit: Int? + /// Remaining in cents (nil if unlimited) + public let remaining: Int? +} + +public struct CursorTeamUsage: Codable, Sendable { + public let onDemand: CursorOnDemandUsage? + /// Shared team/enterprise pool counted across all members. Same cents-based units as the other usage blocks. + public let pooled: CursorPooledUsage? + + public init(onDemand: CursorOnDemandUsage? = nil, pooled: CursorPooledUsage? = nil) { + self.onDemand = onDemand + self.pooled = pooled + } +} + +/// Shared team/enterprise pool reported under `teamUsage.pooled`. Values are in cents. +public struct CursorPooledUsage: Codable, Sendable { + public let enabled: Bool? + /// Pool usage in cents. + public let used: Int? + /// Pool limit in cents. `nil` indicates an unlimited or unreported pool. + public let limit: Int? + /// Pool remaining in cents. + public let remaining: Int? + + public init(enabled: Bool? = nil, used: Int? = nil, limit: Int? = nil, remaining: Int? = nil) { + self.enabled = enabled + self.used = used + self.limit = limit + self.remaining = remaining + } +} + +// MARK: - Cursor Usage API Models (Legacy Request-Based Plans) + +/// Response from `/api/usage?user=ID` endpoint for legacy request-based plans. +public struct CursorUsageResponse: Codable, Sendable { + public let gpt4: CursorModelUsage? + public let startOfMonth: String? + + enum CodingKeys: String, CodingKey { + case gpt4 = "gpt-4" + case startOfMonth + } +} + +public struct CursorModelUsage: Codable, Sendable { + public let numRequests: Int? + public let numRequestsTotal: Int? + public let numTokens: Int? + public let maxRequestUsage: Int? + public let maxTokenUsage: Int? +} + +public struct CursorUserInfo: Codable, Sendable { + public let email: String? + public let emailVerified: Bool? + public let name: String? + public let sub: String? + public let createdAt: String? + public let updatedAt: String? + public let picture: String? + + enum CodingKeys: String, CodingKey { + case email + case emailVerified = "email_verified" + case name + case sub + case createdAt = "created_at" + case updatedAt = "updated_at" + case picture + } +} + +// MARK: - Cursor App Auth + +struct CursorAppAuthSession: Equatable { + let accessToken: String + + var isUsable: Bool { + guard !self.accessToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty, + (try? self.userID()) != nil, + let expiresAt = try? self.expiresAt() + else { + return false + } + return expiresAt.timeIntervalSinceNow > 60 + } + + func cookieHeader() throws -> String { + try "WorkosCursorSessionToken=\(self.userID())%3A%3A\(self.accessToken)" + } + + func userID() throws -> String { + let json = try self.payload() + guard let subject = json["sub"] as? String, + let userID = subject.split(separator: "|", omittingEmptySubsequences: true).last.map(String.init), + !userID.isEmpty + else { + throw CursorStatusProbeError.parseFailed("Cursor.app access token is missing a user ID") + } + + let allowed = CharacterSet.alphanumerics.union(CharacterSet(charactersIn: "._-")) + guard userID.unicodeScalars.allSatisfy(allowed.contains) else { + throw CursorStatusProbeError.parseFailed("Cursor.app access token has an invalid user ID") + } + + return userID + } + + private func expiresAt() throws -> Date { + let json = try self.payload() + guard let expiration = json["exp"] as? NSNumber else { + throw CursorStatusProbeError.parseFailed("Cursor.app access token is missing an expiration") + } + return Date(timeIntervalSince1970: expiration.doubleValue) + } + + private func payload() throws -> [String: Any] { + let parts = self.accessToken.split(separator: ".", omittingEmptySubsequences: false) + guard parts.count >= 2 else { + throw CursorStatusProbeError.parseFailed("Cursor.app access token is not a JWT") + } + + var payload = String(parts[1]) + .replacingOccurrences(of: "-", with: "+") + .replacingOccurrences(of: "_", with: "/") + payload += String(repeating: "=", count: (4 - payload.count % 4) % 4) + + guard let data = Data(base64Encoded: payload), + let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] + else { + throw CursorStatusProbeError.parseFailed("Cursor.app access token has an invalid payload") + } + + return json + } +} + +protocol CursorAppAuthSessionProviding: Sendable { + func loadSession() throws -> CursorAppAuthSession? +} + +struct CursorAppAuthStore: CursorAppAuthSessionProviding { + private static let defaultDBPath: String = Self.resolveDefaultDBPath() + + private let dbPath: String + + init(dbPath: String? = nil) { + self.dbPath = dbPath ?? Self.defaultDBPath + } + + static func resolveDefaultDBPath( + home: String = NSHomeDirectory(), + environment: [String: String] = ProcessInfo.processInfo.environment, + fileManager: FileManager = .default) -> String + { + #if os(macOS) + _ = environment + _ = fileManager + return "\(home)/Library/Application Support/Cursor/User/globalStorage/state.vscdb" + #elseif os(Linux) + let configHome = environment[CodexBarConfigStore.xdgConfigHomeEnvironmentKey]? + .trimmingCharacters(in: .whitespacesAndNewlines) + let expandedConfigHome = configHome.map { ($0 as NSString).expandingTildeInPath } + let base: String = if let expandedConfigHome, + !expandedConfigHome.isEmpty, + (expandedConfigHome as NSString).isAbsolutePath + { + expandedConfigHome + } else { + "\(home)/.config" + } + return "\(base)/Cursor/User/globalStorage/state.vscdb" + #else + _ = home + _ = environment + _ = fileManager + return "" + #endif + } + + func loadSession() throws -> CursorAppAuthSession? { + guard FileManager.default.fileExists(atPath: self.dbPath) else { return nil } + + guard let accessToken = try self.value(for: "cursorAuth/accessToken"), + !accessToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty + else { + return nil + } + + return CursorAppAuthSession(accessToken: accessToken) + } + + private func value(for key: String) throws -> String? { + var db: OpaquePointer? + guard sqlite3_open_v2(self.dbPath, &db, SQLITE_OPEN_READONLY, nil) == SQLITE_OK else { + let message = db.flatMap { String(cString: sqlite3_errmsg($0)) } ?? "unknown error" + sqlite3_close(db) + throw CursorStatusProbeError.networkError("SQLite error reading Cursor app auth: \(message)") + } + defer { sqlite3_close(db) } + sqlite3_busy_timeout(db, 250) + + let query = "SELECT value FROM ItemTable WHERE key = ? LIMIT 1;" + var stmt: OpaquePointer? + guard sqlite3_prepare_v2(db, query, -1, &stmt, nil) == SQLITE_OK else { + let message = db.flatMap { String(cString: sqlite3_errmsg($0)) } ?? "unknown error" + throw CursorStatusProbeError.networkError("SQLite error preparing Cursor app auth read: \(message)") + } + defer { sqlite3_finalize(stmt) } + + sqlite3_bind_text(stmt, 1, key, -1, SQLITE_TRANSIENT) + let stepResult = sqlite3_step(stmt) + guard stepResult == SQLITE_ROW else { + if stepResult == SQLITE_DONE { return nil } + let message = db.flatMap { String(cString: sqlite3_errmsg($0)) } ?? "unknown error" + throw CursorStatusProbeError.networkError("SQLite error reading Cursor app auth: \(message)") + } + + return Self.decodeSQLiteValue(stmt: stmt, index: 0) + } + + private static func decodeSQLiteValue(stmt: OpaquePointer?, index: Int32) -> String? { + switch sqlite3_column_type(stmt, index) { + case SQLITE_TEXT: + guard let c = sqlite3_column_text(stmt, index) else { return nil } + return String(cString: c) + case SQLITE_BLOB: + guard let bytes = sqlite3_column_blob(stmt, index) else { return nil } + let data = Data(bytes: bytes, count: Int(sqlite3_column_bytes(stmt, index))) + return String(data: data, encoding: .utf8) + ?? String(data: data, encoding: .utf16LittleEndian) + default: + return nil + } + } +} + +private let SQLITE_TRANSIENT = unsafeBitCast(-1, to: sqlite3_destructor_type.self) + +// MARK: - Cursor Status Snapshot + +public struct CursorStatusSnapshot: Sendable { + /// Percentage of included plan usage (0-100) — the "Total" headline number from Cursor's UI + public let planPercentUsed: Double + /// Auto + Composer usage percent (0-100), nil when not available + public let autoPercentUsed: Double? + /// API (named model) usage percent (0-100), nil when not available + public let apiPercentUsed: Double? + /// Included plan usage in USD + public let planUsedUSD: Double + /// Included plan limit in USD + public let planLimitUSD: Double + /// On-demand usage in USD + public let onDemandUsedUSD: Double + /// On-demand limit in USD (nil if unlimited) + public let onDemandLimitUSD: Double? + /// Team on-demand usage in USD (for team plans) + public let teamOnDemandUsedUSD: Double? + /// Team on-demand limit in USD + public let teamOnDemandLimitUSD: Double? + /// Billing cycle start date + public let billingCycleStart: Date? + /// Billing cycle reset date + public let billingCycleEnd: Date? + /// Membership type (e.g., "enterprise", "pro", "hobby") + public let membershipType: String? + /// User email + public let accountEmail: String? + /// User name + public let accountName: String? + /// Raw API response for debugging + public let rawJSON: String? + + // MARK: - Legacy Plan (Request-Based) Fields + + /// Requests used this billing cycle (legacy plans only) + public let requestsUsed: Int? + /// Request limit (non-nil indicates legacy request-based plan) + public let requestsLimit: Int? + + /// Whether this is a legacy request-based plan (vs token-based) + public var isLegacyRequestPlan: Bool { + self.requestsLimit != nil + } + + public init( + planPercentUsed: Double, + autoPercentUsed: Double? = nil, + apiPercentUsed: Double? = nil, + planUsedUSD: Double, + planLimitUSD: Double, + onDemandUsedUSD: Double, + onDemandLimitUSD: Double?, + teamOnDemandUsedUSD: Double?, + teamOnDemandLimitUSD: Double?, + billingCycleStart: Date? = nil, + billingCycleEnd: Date?, + membershipType: String?, + accountEmail: String?, + accountName: String?, + rawJSON: String?, + requestsUsed: Int? = nil, + requestsLimit: Int? = nil) + { + self.planPercentUsed = planPercentUsed + self.autoPercentUsed = autoPercentUsed + self.apiPercentUsed = apiPercentUsed + self.planUsedUSD = planUsedUSD + self.planLimitUSD = planLimitUSD + self.onDemandUsedUSD = onDemandUsedUSD + self.onDemandLimitUSD = onDemandLimitUSD + self.teamOnDemandUsedUSD = teamOnDemandUsedUSD + self.teamOnDemandLimitUSD = teamOnDemandLimitUSD + self.billingCycleStart = billingCycleStart + self.billingCycleEnd = billingCycleEnd + self.membershipType = membershipType + self.accountEmail = accountEmail + self.accountName = accountName + self.rawJSON = rawJSON + self.requestsUsed = requestsUsed + self.requestsLimit = requestsLimit + } + + /// Convert to UsageSnapshot for the common provider interface + public func toUsageSnapshot() -> UsageSnapshot { + let cursorRequests: CursorRequestUsage? = if let used = self.requestsUsed, + let limit = self.requestsLimit, + limit > 0 + { + CursorRequestUsage(used: used, limit: limit) + } else { + nil + } + + // Primary: For usable legacy request quotas, use request usage; otherwise preserve plan percentage. + let primaryUsedPercent = cursorRequests?.usedPercent ?? self.planPercentUsed + + let billingCycleWindowMinutes = Self.billingCycleWindowMinutes( + start: self.billingCycleStart, + end: self.billingCycleEnd) + + let primary = RateWindow( + usedPercent: primaryUsedPercent, + windowMinutes: billingCycleWindowMinutes, + resetsAt: self.billingCycleEnd, + resetDescription: self.billingCycleEnd.map { Self.formatResetDate($0) }) + + // Secondary: Auto + Composer usage (shown as its own bar below Total). + // Legacy request-based plans don't have the token-based Auto/API breakdown — those percentages + // come from the new usage-based pricing and are meaningless next to a request quota, so hide them. + let secondary: RateWindow? = cursorRequests != nil ? nil : self.autoPercentUsed.map { pct in + RateWindow( + usedPercent: pct, + windowMinutes: billingCycleWindowMinutes, + resetsAt: self.billingCycleEnd, + resetDescription: self.billingCycleEnd.map { Self.formatResetDate($0) }) + } + + // Tertiary: API (named model) usage — hidden for legacy request-based plans (see above). + let tertiary: RateWindow? = cursorRequests != nil ? nil : self.apiPercentUsed.map { pct in + RateWindow( + usedPercent: pct, + windowMinutes: billingCycleWindowMinutes, + resetsAt: self.billingCycleEnd, + resetDescription: self.billingCycleEnd.map { Self.formatResetDate($0) }) + } + + // Prefer a personal cap. Team accounts with no user cap expose only the shared on-demand budget. + let resolvedOnDemandUsed: Double + let resolvedOnDemandLimit: Double? + if (self.onDemandLimitUSD ?? 0) > 0 { + resolvedOnDemandUsed = self.onDemandUsedUSD + resolvedOnDemandLimit = self.onDemandLimitUSD + } else if (self.teamOnDemandLimitUSD ?? 0) > 0 { + resolvedOnDemandUsed = self.teamOnDemandUsedUSD ?? 0 + resolvedOnDemandLimit = self.teamOnDemandLimitUSD + } else { + resolvedOnDemandUsed = self.onDemandUsedUSD + resolvedOnDemandLimit = self.onDemandLimitUSD + } + + // Your own on-demand spend to surface alongside a shared team pool (nil when the budget is personal). + let personalOnDemandUsed: Double? = if (self.onDemandLimitUSD ?? 0) > 0 { + nil + } else if (self.teamOnDemandLimitUSD ?? 0) > 0 { + self.onDemandUsedUSD > 0 ? self.onDemandUsedUSD : nil + } else { + nil + } + + // Provider cost snapshot for on-demand usage (include budget before first spend) + let providerCost: ProviderCostSnapshot? = if resolvedOnDemandUsed > 0 + || (resolvedOnDemandLimit ?? 0) > 0 + { + ProviderCostSnapshot( + used: resolvedOnDemandUsed, + limit: resolvedOnDemandLimit ?? 0, + currencyCode: "USD", + period: "Monthly", + resetsAt: self.billingCycleEnd, + personalUsed: personalOnDemandUsed, + updatedAt: Date()) + } else { + nil + } + + let identity = ProviderIdentitySnapshot( + providerID: .cursor, + accountEmail: self.accountEmail, + accountOrganization: nil, + loginMethod: self.membershipType.map { Self.formatMembershipType($0) }) + return UsageSnapshot( + primary: primary, + secondary: secondary, + tertiary: tertiary, + providerCost: providerCost, + cursorRequests: cursorRequests, + updatedAt: Date(), + identity: identity) + } + + private static func formatResetDate(_ date: Date) -> String { + let formatter = DateFormatter() + formatter.dateFormat = "MMM d 'at' h:mma" + formatter.locale = Locale(identifier: "en_US_POSIX") + return "Resets " + formatter.string(from: date) + } + + private static func billingCycleWindowMinutes(start: Date?, end: Date?) -> Int? { + guard let start, + let end + else { return nil } + let minutes = Int((end.timeIntervalSince(start) / 60).rounded()) + return minutes > 0 ? minutes : nil + } + + private static func formatMembershipType(_ type: String) -> String { + switch type.lowercased() { + case "enterprise": + "Cursor Enterprise" + case "pro": + "Cursor Pro" + case "hobby": + "Cursor Hobby" + case "team": + "Cursor Team" + default: + "Cursor \(type.capitalized)" + } + } +} + +// MARK: - Cursor Status Probe Error + +public enum CursorStatusProbeError: LocalizedError, Sendable { + case notLoggedIn + case networkError(String) + case parseFailed(String) + case noSessionCookie + + static let safariFullDiskAccessHint = + "If you use Safari, grant CodexBar Full Disk Access in System Settings ▸ Privacy & Security." + + public var errorDescription: String? { + switch self { + case .notLoggedIn: + #if os(macOS) + "Not logged in to Cursor. Please log in via the CodexBar menu." + #else + "Not logged in to Cursor. Sign in to the Cursor app on this machine or paste a Cookie header copied " + + "from cursor.com into ~/.config/codexbar/config.json (legacy: ~/.codexbar/config.json)." + #endif + case let .networkError(msg): + "Cursor API error: \(msg)" + case let .parseFailed(msg): + "Could not parse Cursor usage: \(msg)" + case .noSessionCookie: + #if os(macOS) + "No Cursor session found. \(Self.safariFullDiskAccessHint) " + + "Please log in to cursor.com in \(cursorCookieImportOrder.loginHint). " + + "You can also sign in to Cursor from the CodexBar menu (Add / switch account)." + #else + "No Cursor session found. Sign in to the Cursor app on this machine or paste a Cookie header copied " + + "from cursor.com into ~/.config/codexbar/config.json (legacy: ~/.codexbar/config.json)." + #endif + } + } +} + +// MARK: - Cursor Session Store + +public actor CursorSessionStore { + public static let shared = CursorSessionStore() + + private var sessionCookies: [HTTPCookie] = [] + private var hasLoadedFromDisk = false + private let fileURL: URL + + private init() { + let fm = FileManager.default + let appSupport = fm.urls(for: .applicationSupportDirectory, in: .userDomainMask).first + ?? fm.temporaryDirectory + let dir = appSupport.appendingPathComponent("CodexBar", isDirectory: true) + try? fm.createDirectory(at: dir, withIntermediateDirectories: true) + self.fileURL = dir.appendingPathComponent("cursor-session.json") + + // Load saved cookies on init + Task { await self.loadFromDiskIfNeeded() } + } + + public func setCookies(_ cookies: [HTTPCookie]) { + self.hasLoadedFromDisk = true + self.sessionCookies = cookies + self.saveToDisk() + } + + public func getCookies() -> [HTTPCookie] { + self.loadFromDiskIfNeeded() + return self.sessionCookies + } + + public func clearCookies() { + self.hasLoadedFromDisk = true + self.sessionCookies = [] + try? FileManager.default.removeItem(at: self.fileURL) + } + + public func hasValidSession() -> Bool { + self.loadFromDiskIfNeeded() + return !self.sessionCookies.isEmpty + } + + #if DEBUG + func resetForTesting(clearDisk: Bool = true) { + self.hasLoadedFromDisk = false + self.sessionCookies = [] + if clearDisk { + try? FileManager.default.removeItem(at: self.fileURL) + } + } + #endif + + private func loadFromDiskIfNeeded() { + guard !self.hasLoadedFromDisk else { return } + self.hasLoadedFromDisk = true + self.loadFromDisk() + } + + private func saveToDisk() { + // Convert cookie properties to JSON-serializable format + // Date values must be converted to TimeInterval (Double) + let cookieData = self.sessionCookies.compactMap { cookie -> [String: Any]? in + guard let props = cookie.properties else { return nil } + var serializable: [String: Any] = [:] + for (key, value) in props { + let keyString = key.rawValue + if let date = value as? Date { + // Convert Date to TimeInterval for JSON compatibility + serializable[keyString] = date.timeIntervalSince1970 + serializable[keyString + "_isDate"] = true + } else if let url = value as? URL { + serializable[keyString] = url.absoluteString + serializable[keyString + "_isURL"] = true + } else if JSONSerialization.isValidJSONObject([value]) || + value is String || + value is Bool || + value is NSNumber + { + serializable[keyString] = value + } + } + return serializable + } + guard !cookieData.isEmpty, + let data = try? JSONSerialization.data(withJSONObject: cookieData, options: [.prettyPrinted]) + else { + return + } + try? data.write(to: self.fileURL) + } + + private func loadFromDisk() { + guard let data = try? Data(contentsOf: self.fileURL), + let cookieArray = try? JSONSerialization.jsonObject(with: data) as? [[String: Any]] + else { return } + + self.sessionCookies = cookieArray.compactMap { props in + // Convert back to HTTPCookiePropertyKey dictionary + var cookieProps: [HTTPCookiePropertyKey: Any] = [:] + for (key, value) in props { + // Skip marker keys + if key.hasSuffix("_isDate") || key.hasSuffix("_isURL") { continue } + + let propKey = HTTPCookiePropertyKey(key) + + // Check if this was a Date + if props[key + "_isDate"] as? Bool == true, let interval = value as? TimeInterval { + cookieProps[propKey] = Date(timeIntervalSince1970: interval) + } + // Check if this was a URL + else if props[key + "_isURL"] as? Bool == true, let urlString = value as? String { + cookieProps[propKey] = URL(string: urlString) + } else { + cookieProps[propKey] = value + } + } + return HTTPCookie(properties: cookieProps) + } + } +} + +// MARK: - Cursor Status Probe + +public struct CursorStatusProbe: Sendable { + public let baseURL: URL + public var timeout: TimeInterval = 15.0 + private let browserDetection: BrowserDetection + private let browserCookieImportOrder: BrowserCookieImportOrder + private let urlSession: any ProviderHTTPTransport + private let appAuthStore: any CursorAppAuthSessionProviding + + public init( + baseURL: URL = URL(string: "https://cursor.com")!, + timeout: TimeInterval = 15.0, + browserDetection: BrowserDetection, + urlSession: any ProviderHTTPTransport = ProviderHTTPClient.shared) + { + self.init( + baseURL: baseURL, + timeout: timeout, + browserDetection: browserDetection, + browserCookieImportOrder: Self.defaultBrowserCookieImportOrder, + urlSession: urlSession, + appAuthStore: CursorAppAuthStore()) + } + + init( + baseURL: URL = URL(string: "https://cursor.com")!, + timeout: TimeInterval = 15.0, + browserDetection: BrowserDetection, + browserCookieImportOrder: BrowserCookieImportOrder = Self.defaultBrowserCookieImportOrder, + urlSession: any ProviderHTTPTransport = ProviderHTTPClient.shared, + appAuthStore: any CursorAppAuthSessionProviding) + { + self.baseURL = baseURL + self.timeout = timeout + self.browserDetection = browserDetection + self.browserCookieImportOrder = browserCookieImportOrder + self.urlSession = urlSession + self.appAuthStore = appAuthStore + } + + /// Fetch Cursor usage using a first-party web session derived from Cursor.app's access token. + func fetchWithAppAuthSession(_ session: CursorAppAuthSession) async throws -> CursorStatusSnapshot { + try await self.fetchWithCookieHeader( + session.cookieHeader(), + requestUsageUserIDFallback: session.userID()) + } + + /// Fetch Cursor usage with manual cookie header (for debugging). + public func fetchWithManualCookies(_ cookieHeader: String) async throws -> CursorStatusSnapshot { + try await self.fetchWithCookieHeader(cookieHeader) + } + + /// Fetch Cursor usage using browser cookies with fallback to stored session. + public func fetch( + cookieHeaderOverride: String? = nil, + allowCachedSessions: Bool = true, + allowAppAuthFallback: Bool = true, + logger: ((String) -> Void)? = nil) + async throws -> CursorStatusSnapshot + { + let log: (String) -> Void = { msg in logger?("[cursor] \(msg)") } + var firstRecoverableError: CursorStatusProbeError? + + if let override = CookieHeaderNormalizer.normalize(cookieHeaderOverride) { + log("Using manual cookie header") + return try await self.fetchWithCookieHeader(override) + } + + if allowCachedSessions, + let cached = CookieHeaderCache.load(provider: .cursor), + !cached.cookieHeader.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty + { + log("Using cached cookie header from \(cached.sourceLabel)") + do { + return try await self.fetchWithCookieHeader(cached.cookieHeader) + } catch let error as CursorStatusProbeError { + if case .notLoggedIn = error { + CookieHeaderCache.clear(provider: .cursor) + } else { + throw error + } + } catch { + throw error + } + } + + #if os(macOS) + // Try each browser in order. The first browser that *has* session cookie names is not always valid + // (e.g. stale Chrome tokens); keep trying until the API accepts a session or we run out of browsers. + let browserCandidates = self.browserCookieImportOrder.cookieImportCandidates(using: self.browserDetection) + switch await self.scanBrowsers( + browserCandidates, + importSessions: { browser in + CursorCookieImporter.importSessionsIfPresent( + browser: browser, + browserDetection: self.browserDetection, + logger: log) + }, + attemptFetch: { session in + await self.fetchIfSessionAccepted(session, log: log) + }) + { + case let .succeeded(snapshot): + return snapshot + case let .exhausted(error): + firstRecoverableError = error ?? firstRecoverableError + } + + switch await self.scanBrowsers( + browserCandidates, + importSessions: { browser in + CursorCookieImporter.importDomainCookieSessionsIfPresent( + browser: browser, + browserDetection: self.browserDetection, + logger: log) + }, + attemptFetch: { session in + await self.fetchIfSessionAccepted(session, log: log) + }) + { + case let .succeeded(snapshot): + return snapshot + case let .exhausted(error): + firstRecoverableError = error ?? firstRecoverableError + } + #endif + + // Fall back to stored session cookies (from "Add Account" login flow) + if allowCachedSessions { + let storedCookies = await CursorSessionStore.shared.getCookies() + if !storedCookies.isEmpty { + log("Using stored session cookies") + let cookieHeader = storedCookies.map { "\($0.name)=\($0.value)" }.joined(separator: "; ") + do { + return try await self.fetchWithCookieHeader(cookieHeader) + } catch let error as CursorStatusProbeError { + if case .notLoggedIn = error { + // Clear only when auth is invalid; keep for transient failures. + await CursorSessionStore.shared.clearCookies() + log("Stored session invalid, cleared") + } else { + log("Stored session failed: \(error.localizedDescription)") + firstRecoverableError = firstRecoverableError ?? error + } + } catch { + log("Stored session failed: \(error.localizedDescription)") + firstRecoverableError = firstRecoverableError ?? .networkError(error.localizedDescription) + } + } + } + + // A transient failure for an explicitly selected session must not switch to Cursor.app's account. + if let firstRecoverableError { + throw firstRecoverableError + } + + // Last fallback: derive Cursor's first-party web session from the app token in its global state DB. + // Reusing the web flow preserves modern billing, legacy request quotas, and account-scoped identity. + if allowAppAuthFallback, + let appSession = try? self.appAuthStore.loadSession(), + appSession.isUsable + { + log("Using Cursor.app local auth fallback") + do { + return try await self.fetchWithAppAuthSession(appSession) + } catch let error as CursorStatusProbeError { + if case .notLoggedIn = error { + log("Cursor.app local auth was rejected") + } else { + firstRecoverableError = firstRecoverableError ?? error + } + } catch { + firstRecoverableError = firstRecoverableError ?? .networkError(error.localizedDescription) + } + } + + if let firstRecoverableError { + throw firstRecoverableError + } + + throw CursorStatusProbeError.noSessionCookie + } + + #if os(macOS) + enum ImportedSessionFetchOutcome { + case succeeded(CursorStatusSnapshot) + case tryNextBrowser + case failed(CursorStatusProbeError) + } + + enum ImportedSessionScanResult { + case succeeded(CursorStatusSnapshot) + case exhausted(CursorStatusProbeError?) + } + + func scanBrowsers( + _ browsers: [Browser], + importSessions: (Browser) -> [CursorCookieImporter.SessionInfo], + attemptFetch: (CursorCookieImporter.SessionInfo) async -> ImportedSessionFetchOutcome) async + -> ImportedSessionScanResult + { + var firstFailure: CursorStatusProbeError? + + for browser in browsers { + let sessions = importSessions(browser) + guard !sessions.isEmpty else { continue } + for session in sessions { + switch await attemptFetch(session) { + case let .succeeded(snapshot): + return .succeeded(snapshot) + case .tryNextBrowser: + continue + case let .failed(error): + firstFailure = firstFailure ?? error + } + } + } + + return .exhausted(firstFailure) + } + + func scanImportedSessions( + _ sessions: [CursorCookieImporter.SessionInfo], + attemptFetch: (CursorCookieImporter.SessionInfo) async -> ImportedSessionFetchOutcome) async + -> ImportedSessionScanResult + { + var firstFailure: CursorStatusProbeError? + + for session in sessions { + switch await attemptFetch(session) { + case let .succeeded(snapshot): + return .succeeded(snapshot) + case .tryNextBrowser: + continue + case let .failed(error): + firstFailure = firstFailure ?? error + } + } + + return .exhausted(firstFailure) + } + + private func fetchIfSessionAccepted( + _ session: CursorCookieImporter.SessionInfo, + log: @escaping (String) -> Void) async -> ImportedSessionFetchOutcome + { + log("Trying Cursor session from \(session.sourceLabel)") + do { + let snapshot = try await self.fetchWithCookieHeader(session.cookieHeader) + CookieHeaderCache.store( + provider: .cursor, + cookieHeader: session.cookieHeader, + sourceLabel: session.sourceLabel) + return .succeeded(snapshot) + } catch let error as CursorStatusProbeError { + if case .notLoggedIn = error { + log("Cursor API rejected cookies from \(session.sourceLabel); trying next browser if any") + return .tryNextBrowser + } + log("Cursor fetch failed using \(session.sourceLabel): \(error.localizedDescription)") + return .failed(error) + } catch { + log("Cursor fetch failed using \(session.sourceLabel): \(error.localizedDescription)") + return .failed(.networkError(error.localizedDescription)) + } + } + #endif + + private func fetchWithCookieHeader( + _ cookieHeader: String, + requestUsageUserIDFallback: String? = nil) async throws -> CursorStatusSnapshot + { + enum FetchPart: Sendable { + case usageSummary((CursorUsageSummary, String)) + case userInfo(Result) + } + + var usageSummaryResult: (CursorUsageSummary, String)? + var userInfo: CursorUserInfo? + + try await withThrowingTaskGroup(of: FetchPart.self) { group in + group.addTask { + try await .usageSummary(self.fetchUsageSummary(cookieHeader: cookieHeader)) + } + group.addTask { + do { + return try await .userInfo(.success(self.fetchUserInfo(cookieHeader: cookieHeader))) + } catch { + return .userInfo(.failure(error)) + } + } + + while let result = try await group.next() { + switch result { + case let .usageSummary(value): + usageSummaryResult = value + case let .userInfo(value): + userInfo = try? value.get() + } + } + } + + guard let usageSummaryResult else { + throw CursorStatusProbeError.networkError("Cursor usage summary fetch did not complete") + } + + let (usageSummary, rawJSON) = usageSummaryResult + + // Fetch legacy request usage only if user has a sub ID. + // Uses try? to avoid breaking the flow for users where this endpoint fails or returns unexpected data. + var requestUsage: CursorUsageResponse? + var requestUsageRawJSON: String? + if let userId = userInfo?.sub ?? requestUsageUserIDFallback { + do { + let (usage, usageRawJSON) = try await self.fetchRequestUsage(userId: userId, cookieHeader: cookieHeader) + requestUsage = usage + requestUsageRawJSON = usageRawJSON + } catch { + // Silently ignore - not all plans have this endpoint + } + } + + // Combine raw JSON for debugging + var combinedRawJSON: String? = rawJSON + if let usageJSON = requestUsageRawJSON { + combinedRawJSON = (combinedRawJSON ?? "") + "\n\n--- /api/usage response ---\n" + usageJSON + } + + return self.parseUsageSummary( + usageSummary, + userInfo: userInfo, + rawJSON: combinedRawJSON, + requestUsage: requestUsage) + } + + private func fetchUsageSummary(cookieHeader: String) async throws -> (CursorUsageSummary, String) { + let url = self.baseURL.appendingPathComponent("/api/usage-summary") + var request = URLRequest(url: url) + request.timeoutInterval = self.timeout + request.setValue("application/json", forHTTPHeaderField: "Accept") + request.setValue(cookieHeader, forHTTPHeaderField: "Cookie") + + let (data, response) = try await self.urlSession.data(for: request) + + guard let httpResponse = response as? HTTPURLResponse else { + throw CursorStatusProbeError.networkError("Invalid response") + } + + if httpResponse.statusCode == 401 || httpResponse.statusCode == 403 { + throw CursorStatusProbeError.notLoggedIn + } + + guard httpResponse.statusCode == 200 else { + throw CursorStatusProbeError.networkError("HTTP \(httpResponse.statusCode)") + } + + let rawJSON = String(data: data, encoding: .utf8) ?? "" + + do { + let decoder = JSONDecoder() + let summary = try decoder.decode(CursorUsageSummary.self, from: data) + return (summary, rawJSON) + } catch { + throw CursorStatusProbeError + .parseFailed("JSON decode failed: \(error.localizedDescription). Raw: \(rawJSON.prefix(200))") + } + } + + private func fetchUserInfo(cookieHeader: String) async throws -> CursorUserInfo { + let url = self.baseURL.appendingPathComponent("/api/auth/me") + var request = URLRequest(url: url) + request.timeoutInterval = self.timeout + request.setValue("application/json", forHTTPHeaderField: "Accept") + request.setValue(cookieHeader, forHTTPHeaderField: "Cookie") + + let (data, response) = try await self.urlSession.data(for: request) + + guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else { + throw CursorStatusProbeError.networkError("Failed to fetch user info") + } + + let decoder = JSONDecoder() + return try decoder.decode(CursorUserInfo.self, from: data) + } + + private func fetchRequestUsage( + userId: String, + cookieHeader: String) async throws -> (CursorUsageResponse, String) + { + let url = self.baseURL.appendingPathComponent("/api/usage") + .appending(queryItems: [URLQueryItem(name: "user", value: userId)]) + var request = URLRequest(url: url) + request.timeoutInterval = self.timeout + request.setValue("application/json", forHTTPHeaderField: "Accept") + request.setValue(cookieHeader, forHTTPHeaderField: "Cookie") + + let (data, response) = try await self.urlSession.data(for: request) + + guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else { + throw CursorStatusProbeError.networkError("Failed to fetch request usage") + } + + let rawJSON = String(data: data, encoding: .utf8) ?? "" + let decoder = JSONDecoder() + let usage = try decoder.decode(CursorUsageResponse.self, from: data) + return (usage, rawJSON) + } + + func parseUsageSummary( + _ summary: CursorUsageSummary, + userInfo: CursorUserInfo?, + rawJSON: String?, + requestUsage: CursorUsageResponse? = nil) -> CursorStatusSnapshot + { + func parseBillingCycleDate(_ dateString: String?) -> Date? { + guard let dateString else { return nil } + let formatter = ISO8601DateFormatter() + formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds] + return formatter.date(from: dateString) ?? ISO8601DateFormatter().date(from: dateString) + } + let billingCycleStart = parseBillingCycleDate(summary.billingCycleStart) + let billingCycleEnd = parseBillingCycleDate(summary.billingCycleEnd) + + // Convert cents to USD (plan percent derives from raw values to avoid percent unit mismatches). + // Use plan.limit directly - breakdown.total represents total *used* credits, not the limit. + let planUsedRaw = Double(summary.individualUsage?.plan?.used ?? 0) + let planLimitRaw = Double(summary.individualUsage?.plan?.limit ?? 0) + func normPct(_ value: Double?) -> Double? { + guard let v = value else { return nil } + if v < 0 { return 0 } + if v > 100 { return 100 } + return v + } + + func normalizeTotalPercent(_ v: Double) -> Double { + max(0, min(100, v)) + } + + // Cursor's usage-summary percent fields are already in percentage units, even when they are fractional + // values below 1.0 (for example 0.36 means 0.36%, which the dashboard rounds to 0%). + let autoPercent = normPct(summary.individualUsage?.plan?.autoPercentUsed) + let apiPercent = normPct(summary.individualUsage?.plan?.apiPercentUsed) + + // Enterprise / team-member personal cap (cents). Reported under `individualUsage.overall` for accounts + // that don't get a `plan` block. Falls through to existing logic when absent so non-enterprise paths + // are untouched. + let overallUsedRaw = (summary.individualUsage?.overall?.used).map(Double.init) + let overallLimitRaw = (summary.individualUsage?.overall?.limit).map(Double.init) + + // Shared team/enterprise pool (cents). Last-resort fallback when no individual data is available. + let pooledUsedRaw = (summary.teamUsage?.pooled?.used).map(Double.init) + let pooledLimitRaw = (summary.teamUsage?.pooled?.limit).map(Double.init) + + // Headline "Total" precedence: + // 1. `individualUsage.plan.totalPercentUsed` (existing behavior for Pro/Hobby/etc.) + // 2. averaged `auto` + `api` lane percents (existing behavior) + // 3. either lane alone (existing behavior) + // 4. `individualUsage.plan` ratio (existing behavior) + // 5. NEW: `individualUsage.overall` ratio (Enterprise/Team personal cap) + // 6. NEW: `teamUsage.pooled` ratio (last resort when no individual data is reported) + let planPercentUsed: Double = if let totalPercentUsed = summary.individualUsage?.plan?.totalPercentUsed { + normalizeTotalPercent(totalPercentUsed) + } else if let autoUsed = autoPercent, let apiUsed = apiPercent { + max(0, min(100, (autoUsed + apiUsed) / 2)) + } else if let apiUsed = apiPercent { + max(0, min(100, apiUsed)) + } else if let autoUsed = autoPercent { + max(0, min(100, autoUsed)) + } else if planLimitRaw > 0 { + (planUsedRaw / planLimitRaw) * 100 + } else if let used = overallUsedRaw, let limit = overallLimitRaw, limit > 0 { + normalizeTotalPercent((used / limit) * 100) + } else if let used = pooledUsedRaw, let limit = pooledLimitRaw, limit > 0 { + normalizeTotalPercent((used / limit) * 100) + } else { + 0 + } + + // USD figures: prefer the source the headline ultimately came from. When `plan` is missing but + // `overall` or `pooled` carry the cents, surface those so the on-demand display and downstream + // consumers see real dollar amounts instead of zeros. + let planUsed: Double + let planLimit: Double + if planLimitRaw > 0 || planUsedRaw > 0 { + planUsed = planUsedRaw / 100.0 + planLimit = planLimitRaw / 100.0 + } else if let usedCents = overallUsedRaw, let limitCents = overallLimitRaw { + planUsed = usedCents / 100.0 + planLimit = limitCents / 100.0 + } else if let usedCents = pooledUsedRaw, let limitCents = pooledLimitRaw { + planUsed = usedCents / 100.0 + planLimit = limitCents / 100.0 + } else { + planUsed = 0 + planLimit = 0 + } + + let onDemandUsed = Double(summary.individualUsage?.onDemand?.used ?? 0) / 100.0 + let onDemandLimit: Double? = summary.individualUsage?.onDemand?.limit.map { Double($0) / 100.0 } + + let teamOnDemandUsed: Double? = summary.teamUsage?.onDemand?.used.map { Double($0) / 100.0 } + let teamOnDemandLimit: Double? = summary.teamUsage?.onDemand?.limit.map { Double($0) / 100.0 } + + // Legacy request-based plan: maxRequestUsage being non-nil indicates a request-based plan + let requestsUsed: Int? = requestUsage?.gpt4?.numRequestsTotal ?? requestUsage?.gpt4?.numRequests + let requestsLimit: Int? = requestUsage?.gpt4?.maxRequestUsage + + return CursorStatusSnapshot( + planPercentUsed: planPercentUsed, + autoPercentUsed: autoPercent, + apiPercentUsed: apiPercent, + planUsedUSD: planUsed, + planLimitUSD: planLimit, + onDemandUsedUSD: onDemandUsed, + onDemandLimitUSD: onDemandLimit, + teamOnDemandUsedUSD: teamOnDemandUsed, + teamOnDemandLimitUSD: teamOnDemandLimit, + billingCycleStart: billingCycleStart, + billingCycleEnd: billingCycleEnd, + membershipType: summary.membershipType, + accountEmail: userInfo?.email, + accountName: userInfo?.name, + rawJSON: rawJSON, + requestsUsed: requestsUsed, + requestsLimit: requestsLimit) + } + + #if os(macOS) + private static let defaultBrowserCookieImportOrder: BrowserCookieImportOrder = cursorCookieImportOrder + #else + private static let defaultBrowserCookieImportOrder: BrowserCookieImportOrder = [] + #endif +} + +#else + +// MARK: - Cursor (Unsupported) + +public enum CursorStatusProbeError: LocalizedError, Sendable { + case notSupported + + public var errorDescription: String? { + "Cursor is only supported on macOS." + } +} + +public struct CursorStatusSnapshot: Sendable { + public init() {} + + public func toUsageSnapshot() -> UsageSnapshot { + UsageSnapshot( + primary: RateWindow(usedPercent: 0, windowMinutes: nil, resetsAt: nil, resetDescription: nil), + secondary: nil, + tertiary: nil, + providerCost: nil, + updatedAt: Date(), + identity: nil) + } +} + +public struct CursorStatusProbe: Sendable { + public init( + baseURL: URL = URL(string: "https://cursor.com")!, + timeout: TimeInterval = 15.0, + browserDetection: BrowserDetection, + urlSession: any ProviderHTTPTransport = ProviderHTTPClient.shared) + { + _ = baseURL + _ = timeout + _ = browserDetection + _ = urlSession + } + + public func fetch(logger: ((String) -> Void)? = nil) async throws -> CursorStatusSnapshot { + _ = logger + throw CursorStatusProbeError.notSupported + } + + public func fetch( + cookieHeaderOverride _: String? = nil, + allowCachedSessions _: Bool = true, + logger: ((String) -> Void)? = nil) async throws -> CursorStatusSnapshot + { + try await self.fetch(logger: logger) + } +} + +#endif diff --git a/Sources/CodexBarCore/Providers/DeepSeek/DeepSeekProviderDescriptor.swift b/Sources/CodexBarCore/Providers/DeepSeek/DeepSeekProviderDescriptor.swift new file mode 100644 index 0000000..f2847c7 --- /dev/null +++ b/Sources/CodexBarCore/Providers/DeepSeek/DeepSeekProviderDescriptor.swift @@ -0,0 +1,48 @@ +import Foundation + +public enum DeepSeekProviderDescriptor { + public static let descriptor: ProviderDescriptor = Self.makeDescriptor() + + static func makeDescriptor() -> ProviderDescriptor { + ProviderDescriptor( + id: .deepseek, + metadata: ProviderMetadata( + id: .deepseek, + displayName: "DeepSeek", + sessionLabel: "Balance", + weeklyLabel: "Balance", + opusLabel: nil, + supportsOpus: false, + supportsCredits: false, + creditsHint: "", + toggleTitle: "Show DeepSeek usage", + cliName: "deepseek", + defaultEnabled: false, + isPrimaryProvider: false, + usesAccountFallback: false, + browserCookieOrder: nil, + dashboardURL: "https://platform.deepseek.com/usage", + statusPageURL: nil, + statusLinkURL: "https://status.deepseek.com"), + branding: ProviderBranding( + iconStyle: .deepseek, + iconResourceName: "ProviderIcon-deepseek", + color: ProviderColor(red: 0.32, green: 0.49, blue: 0.94)), + tokenCost: ProviderTokenCostConfig( + supportsTokenCost: false, + noDataMessage: { "DeepSeek per-day cost history is not available via API." }), + fetchPlan: .apiToken( + strategyID: "deepseek.api", + resolveToken: { ProviderTokenResolver.deepseekToken(environment: $0) }, + missingCredentialsError: { DeepSeekUsageError.missingCredentials }, + loadUsage: { apiKey, context in + try await DeepSeekUsageFetcher.fetchUsage( + apiKey: apiKey, + includeOptionalUsage: context.includeOptionalUsage).toUsageSnapshot() + }), + cli: ProviderCLIConfig( + name: "deepseek", + aliases: ["deep-seek", "ds"], + versionDetector: nil)) + } +} diff --git a/Sources/CodexBarCore/Providers/DeepSeek/DeepSeekSettingsReader.swift b/Sources/CodexBarCore/Providers/DeepSeek/DeepSeekSettingsReader.swift new file mode 100644 index 0000000..3c787ca --- /dev/null +++ b/Sources/CodexBarCore/Providers/DeepSeek/DeepSeekSettingsReader.swift @@ -0,0 +1,33 @@ +import Foundation + +public struct DeepSeekSettingsReader: Sendable { + public static let apiKeyEnvironmentKey = "DEEPSEEK_API_KEY" + public static let apiKeyEnvironmentKeys = [Self.apiKeyEnvironmentKey, "DEEPSEEK_KEY"] + + public static func apiKey( + environment: [String: String] = ProcessInfo.processInfo.environment) -> String? + { + for key in self.apiKeyEnvironmentKeys { + guard let raw = environment[key]?.trimmingCharacters(in: .whitespacesAndNewlines), + !raw.isEmpty + else { + continue + } + let cleaned = Self.cleaned(raw) + if !cleaned.isEmpty { + return cleaned + } + } + return nil + } + + private static func cleaned(_ raw: String) -> String { + var value = raw + if (value.hasPrefix("\"") && value.hasSuffix("\"")) || + (value.hasPrefix("'") && value.hasSuffix("'")) + { + value = String(value.dropFirst().dropLast()) + } + return value.trimmingCharacters(in: .whitespacesAndNewlines) + } +} diff --git a/Sources/CodexBarCore/Providers/DeepSeek/DeepSeekUsageCostParser.swift b/Sources/CodexBarCore/Providers/DeepSeek/DeepSeekUsageCostParser.swift new file mode 100644 index 0000000..77e6e4f --- /dev/null +++ b/Sources/CodexBarCore/Providers/DeepSeek/DeepSeekUsageCostParser.swift @@ -0,0 +1,709 @@ +import Foundation + +// MARK: - Amount Response Models + +struct DeepSeekAmountPayload: Decodable { + let code: Int? + let msg: String? + let data: DeepSeekAmountData? + + private enum CodingKeys: String, CodingKey { + case code, msg, data + } + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.code = try container.decodeIfPresent(Int.self, forKey: .code) + self.msg = try container.decodeIfPresent(String.self, forKey: .msg) + if container.contains(.data) { + if let dataValue = try? container.decodeIfPresent(DeepSeekAmountData.self, forKey: .data) { + self.data = dataValue + } else { + self.data = nil + } + } else { + self.data = nil + } + } +} + +struct DeepSeekAmountData: Decodable { + let bizCode: Int? + let bizMsg: String? + let bizData: DeepSeekAmountBizData? + + private enum CodingKeys: String, CodingKey { + case bizCode = "biz_code" + case bizMsg = "biz_msg" + case bizData = "biz_data" + } + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.bizCode = try container.decodeIfPresent(Int.self, forKey: .bizCode) + self.bizMsg = try container.decodeIfPresent(String.self, forKey: .bizMsg) + if container.contains(.bizData) { + if let dataValue = try? container.decodeIfPresent(DeepSeekAmountBizData.self, forKey: .bizData) { + self.bizData = dataValue + } else { + self.bizData = nil + } + } else { + self.bizData = nil + } + } +} + +struct DeepSeekAmountBizData: Decodable { + let total: [DeepSeekModelUsage]? + let days: [DeepSeekDayUsage]? + + private enum CodingKeys: String, CodingKey { + case total, days + } +} + +// MARK: - Cost Response Models + +struct DeepSeekCostPayload: Decodable { + let code: Int? + let msg: String? + let data: DeepSeekCostData? + + private enum CodingKeys: String, CodingKey { + case code, msg, data + } + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.code = try container.decodeIfPresent(Int.self, forKey: .code) + self.msg = try container.decodeIfPresent(String.self, forKey: .msg) + if container.contains(.data) { + if let dataValue = try? container.decodeIfPresent(DeepSeekCostData.self, forKey: .data) { + self.data = dataValue + } else { + self.data = nil + } + } else { + self.data = nil + } + } +} + +struct DeepSeekCostData: Decodable { + let bizCode: Int? + let bizMsg: String? + let bizData: [DeepSeekCostBizDataItem]? + + private enum CodingKeys: String, CodingKey { + case bizCode = "biz_code" + case bizMsg = "biz_msg" + case bizData = "biz_data" + } + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.bizCode = try container.decodeIfPresent(Int.self, forKey: .bizCode) + self.bizMsg = try container.decodeIfPresent(String.self, forKey: .bizMsg) + self.bizData = try container.decodeIfPresent([DeepSeekCostBizDataItem].self, forKey: .bizData) + } +} + +struct DeepSeekCostBizDataItem: Decodable { + let total: [DeepSeekCostModelUsage]? + let days: [DeepSeekCostDayUsage]? + let currency: String? + + private enum CodingKeys: String, CodingKey { + case total, days, currency + } +} + +// MARK: - Shared Models + +struct DeepSeekModelUsage: Decodable { + let model: String? + let usage: [DeepSeekUsageItem]? + + private enum CodingKeys: String, CodingKey { + case model, usage + } +} + +struct DeepSeekDayUsage: Decodable { + let date: String? + let data: [DeepSeekModelUsage]? + + private enum CodingKeys: String, CodingKey { + case date, data + } +} + +struct DeepSeekUsageItem: Decodable { + let type: String? + let amount: String? + + private enum CodingKeys: String, CodingKey { + case type, amount + } +} + +struct DeepSeekCostModelUsage: Decodable { + let model: String? + let usage: [DeepSeekCostItem]? + + private enum CodingKeys: String, CodingKey { + case model, usage + } +} + +struct DeepSeekCostDayUsage: Decodable { + let date: String? + let data: [DeepSeekCostModelUsage]? + + private enum CodingKeys: String, CodingKey { + case date, data + } +} + +struct DeepSeekCostItem: Decodable { + let type: String? + let amount: String? + + private enum CodingKeys: String, CodingKey { + case type, amount + } +} + +// MARK: - Domain Models + +public struct DeepSeekUsageSummary: Sendable, Equatable { + public let todayTokens: Int + public let currentMonthTokens: Int + public let todayCost: Double? + public let currentMonthCost: Double? + public let requestCount: Int + public let currentMonthRequestCount: Int + public let topModel: String? + public let categoryBreakdown: [DeepSeekCategoryBreakdown] + public let daily: [DeepSeekDailyUsage] + public let currency: String + public let updatedAt: Date + + public init( + todayTokens: Int, + currentMonthTokens: Int, + todayCost: Double?, + currentMonthCost: Double?, + requestCount: Int, + currentMonthRequestCount: Int, + topModel: String?, + categoryBreakdown: [DeepSeekCategoryBreakdown], + daily: [DeepSeekDailyUsage], + currency: String, + updatedAt: Date) + { + self.todayTokens = todayTokens + self.currentMonthTokens = currentMonthTokens + self.todayCost = todayCost + self.currentMonthCost = currentMonthCost + self.requestCount = requestCount + self.currentMonthRequestCount = currentMonthRequestCount + self.topModel = topModel + self.categoryBreakdown = categoryBreakdown + self.daily = daily + self.currency = currency + self.updatedAt = updatedAt + } +} + +public struct DeepSeekCategoryBreakdown: Sendable, Equatable { + public let category: DeepSeekUsageCategory + public let tokens: Int + public let cost: Double? + + public init(category: DeepSeekUsageCategory, tokens: Int, cost: Double?) { + self.category = category + self.tokens = tokens + self.cost = cost + } +} + +public enum DeepSeekUsageCategory: String, Sendable, Equatable { + case promptCacheHitToken = "PROMPT_CACHE_HIT_TOKEN" + case promptCacheMissToken = "PROMPT_CACHE_MISS_TOKEN" + case responseToken = "RESPONSE_TOKEN" + case request = "REQUEST" + + public init?(rawValue: String) { + switch rawValue.uppercased() { + case "PROMPT_CACHE_HIT_TOKEN": + self = .promptCacheHitToken + case "PROMPT_CACHE_MISS_TOKEN": + self = .promptCacheMissToken + case "RESPONSE_TOKEN": + self = .responseToken + case "REQUEST": + self = .request + default: + return nil + } + } +} + +public struct DeepSeekDailyUsage: Sendable, Equatable { + public let date: String + public let totalTokens: Int + public let cost: Double? + public let requestCount: Int + + public init(date: String, totalTokens: Int, cost: Double?, requestCount: Int) { + self.date = date + self.totalTokens = totalTokens + self.cost = cost + self.requestCount = requestCount + } +} + +// MARK: - Parsing + +enum DeepSeekUsageCostParser { + static func decodeAmountPayload(data: Data) throws -> DeepSeekAmountPayload { + try JSONDecoder().decode(DeepSeekAmountPayload.self, from: data) + } + + static func decodeCostPayload(data: Data) throws -> DeepSeekCostPayload { + try JSONDecoder().decode(DeepSeekCostPayload.self, from: data) + } + + static func parse( + amountData: Data, + costData: Data, + now: Date = Date(), + calendar: Calendar = .current) throws -> DeepSeekUsageSummary + { + let amountPayload: DeepSeekAmountPayload + let costPayload: DeepSeekCostPayload + do { + amountPayload = try self.decodeAmountPayload(data: amountData) + } catch { + throw DeepSeekUsageError.parseFailed("amount: \(error.localizedDescription)") + } + do { + costPayload = try self.decodeCostPayload(data: costData) + } catch { + throw DeepSeekUsageError.parseFailed("cost: \(error.localizedDescription)") + } + + // Validate responses + if let code = amountPayload.code, code != 0 { + throw DeepSeekUsageError.apiError("amount code \(code)") + } + if let bizCode = amountPayload.data?.bizCode, bizCode != 0 { + throw DeepSeekUsageError.apiError("amount biz_code \(bizCode)") + } + if let code = costPayload.code, code != 0 { + throw DeepSeekUsageError.apiError("cost code \(code)") + } + if let bizCode = costPayload.data?.bizCode, bizCode != 0 { + throw DeepSeekUsageError.apiError("cost biz_code \(bizCode)") + } + + guard let amountBizData = amountPayload.data?.bizData else { + throw DeepSeekUsageError.parseFailed("Missing amount biz_data") + } + + let currency = costPayload.data?.bizData?.first?.currency ?? "CNY" + + // Parse total amounts + let totalAmounts = amountBizData.total ?? [] + let totalCosts = costPayload.data?.bizData?.first?.total ?? [] + + // Parse daily data + let dailyAmounts = amountBizData.days ?? [] + let dailyCosts = costPayload.data?.bizData?.first?.days ?? [] + + return self.aggregate(input: AggregationInput( + totalAmounts: totalAmounts, + totalCosts: totalCosts, + dailyAmounts: dailyAmounts, + dailyCosts: dailyCosts, + currency: currency, + now: now, + calendar: calendar)) + } + + // MARK: - Aggregation + + private struct AggregationContext { + let calendar: Calendar + let todayString: String + let startOfMonth: Date + let now: Date + let dailyAmountMap: [String: [String: [DeepSeekUsageItem]]] + let dailyCostMap: [String: [String: [DeepSeekCostItem]]] + let allDates: Set + + init( + dailyAmounts: [DeepSeekDayUsage], + dailyCosts: [DeepSeekCostDayUsage], + now: Date, + calendar: Calendar) + { + self.calendar = calendar + self.now = now + self.todayString = Self.dayString(now, calendar: calendar) + + var components = calendar.dateComponents([.year, .month], from: now) + components.day = 1 + self.startOfMonth = calendar.date(from: components) ?? now + + self.dailyAmountMap = Self.buildAmountMap(from: dailyAmounts) + self.dailyCostMap = Self.buildCostMap(from: dailyCosts) + + var dates: Set = [] + for date in self.dailyAmountMap.keys { + dates.insert(date) + } + for date in self.dailyCostMap.keys { + dates.insert(date) + } + self.allDates = dates + } + + static func dayString(_ date: Date, calendar: Calendar) -> String { + let components = calendar.dateComponents([.year, .month, .day], from: date) + guard let year = components.year, + let month = components.month, + let day = components.day + else { return "" } + return String(format: "%04d-%02d-%02d", year, month, day) + } + + static func buildAmountMap( + from dailyAmounts: [DeepSeekDayUsage]) -> [String: [String: [DeepSeekUsageItem]]] + { + var result: [String: [String: [DeepSeekUsageItem]]] = [:] + for dayUsage in dailyAmounts { + guard let date = dayUsage.date else { continue } + var modelMap: [String: [DeepSeekUsageItem]] = [:] + for modelUsage in dayUsage.data ?? [] { + guard let model = modelUsage.model else { continue } + let items = modelUsage.usage ?? [] + if !items.isEmpty { + modelMap[model] = items + } + } + if !modelMap.isEmpty { + result[date] = modelMap + } + } + return result + } + + static func buildCostMap( + from dailyCosts: [DeepSeekCostDayUsage]) -> [String: [String: [DeepSeekCostItem]]] + { + var result: [String: [String: [DeepSeekCostItem]]] = [:] + for dayUsage in dailyCosts { + guard let date = dayUsage.date else { continue } + var modelMap: [String: [DeepSeekCostItem]] = [:] + for modelUsage in dayUsage.data ?? [] { + guard let model = modelUsage.model else { continue } + let items = modelUsage.usage ?? [] + if !items.isEmpty { + modelMap[model] = items + } + } + if !modelMap.isEmpty { + result[date] = modelMap + } + } + return result + } + } + + private struct AggregationInput { + let totalAmounts: [DeepSeekModelUsage] + let totalCosts: [DeepSeekCostModelUsage] + let dailyAmounts: [DeepSeekDayUsage] + let dailyCosts: [DeepSeekCostDayUsage] + let currency: String + let now: Date + let calendar: Calendar + } + + private static func aggregate(input: AggregationInput) -> DeepSeekUsageSummary { + let ctx = AggregationContext( + dailyAmounts: input.dailyAmounts, + dailyCosts: input.dailyCosts, + now: input.now, + calendar: input.calendar) + + // Today aggregation + let todayResult = self.aggregateDay( + dateString: ctx.todayString, + amountMap: ctx.dailyAmountMap, + costMap: ctx.dailyCostMap, + calendar: ctx.calendar) + + // Month aggregation + let dailyCtx = DailyAggregationContext( + allDates: ctx.allDates, + startOfMonth: ctx.startOfMonth, + now: ctx.now, + amountMap: ctx.dailyAmountMap, + costMap: ctx.dailyCostMap, + calendar: ctx.calendar) + let monthResult = self.aggregateMonth(ctx: dailyCtx) + + // Model and category breakdown from totals + let (topModel, categoryBreakdown) = self.buildBreakdowns( + totalAmounts: input.totalAmounts, + totalCosts: input.totalCosts) + + // Daily usage array + let dailyUsages = self.buildDailyUsages(ctx: dailyCtx) + + return DeepSeekUsageSummary( + todayTokens: todayResult.tokens, + currentMonthTokens: monthResult.tokens, + todayCost: todayResult.cost, + currentMonthCost: monthResult.cost, + requestCount: todayResult.requests, + currentMonthRequestCount: monthResult.requests, + topModel: topModel, + categoryBreakdown: categoryBreakdown, + daily: dailyUsages, + currency: input.currency, + updatedAt: input.now) + } + + private struct DayAggregationResult { + let tokens: Int + let cost: Double? + let requests: Int + } + + private struct DailyAggregationContext { + let allDates: Set + let startOfMonth: Date + let now: Date + let amountMap: [String: [String: [DeepSeekUsageItem]]] + let costMap: [String: [String: [DeepSeekCostItem]]] + let calendar: Calendar + } + + private static func aggregateDay( + dateString: String, + amountMap: [String: [String: [DeepSeekUsageItem]]], + costMap: [String: [String: [DeepSeekCostItem]]], + calendar: Calendar) -> DayAggregationResult + { + var tokens = 0 + var cost: Double? + var requests = 0 + + if let amounts = amountMap[dateString] { + for items in amounts.values { + for item in items { + guard let category = DeepSeekUsageCategory(rawValue: item.type ?? "") else { continue } + if category == .request { + requests += self.parseTokenAmount(item.amount) + } else { + tokens += self.parseTokenAmount(item.amount) + } + } + } + } + + if let costs = costMap[dateString] { + for items in costs.values { + for item in items { + guard let category = DeepSeekUsageCategory(rawValue: item.type ?? "") else { continue } + if category != .request { + let amount = Self.parseCostAmount(item.amount) + if let existing = cost { + cost = existing + amount + } else { + cost = amount + } + } + } + } + } + + return DayAggregationResult(tokens: tokens, cost: cost, requests: requests) + } + + private static func aggregateMonth(ctx: DailyAggregationContext) -> DayAggregationResult { + var tokens = 0 + var cost: Double? + var requests = 0 + + for date in ctx.allDates { + guard let parsed = self.parseDate(date, calendar: ctx.calendar), + parsed >= ctx.startOfMonth, + parsed <= ctx.now + else { continue } + + if let amounts = ctx.amountMap[date] { + for items in amounts.values { + for item in items { + guard let category = DeepSeekUsageCategory(rawValue: item.type ?? "") else { continue } + if category == .request { + requests += Self.parseTokenAmount(item.amount) + } else { + tokens += Self.parseTokenAmount(item.amount) + } + } + } + } + + if let costs = ctx.costMap[date] { + for items in costs.values { + for item in items { + guard let category = DeepSeekUsageCategory(rawValue: item.type ?? "") else { continue } + if category != .request { + let amount = Self.parseCostAmount(item.amount) + if let existing = cost { + cost = existing + amount + } else { + cost = amount + } + } + } + } + } + } + + return DayAggregationResult(tokens: tokens, cost: cost, requests: requests) + } + + private static func buildBreakdowns( + totalAmounts: [DeepSeekModelUsage], + totalCosts: [DeepSeekCostModelUsage]) -> (String?, [DeepSeekCategoryBreakdown]) + { + var modelTokens: [String: Int] = [:] + var categoryTokens: [DeepSeekUsageCategory: Int] = [:] + var categoryCosts: [DeepSeekUsageCategory: Double] = [:] + + for modelUsage in totalAmounts { + guard let model = modelUsage.model else { continue } + var total = 0 + for item in modelUsage.usage ?? [] { + guard let category = DeepSeekUsageCategory(rawValue: item.type ?? "") else { continue } + if category != .request { + let amount = Self.parseTokenAmount(item.amount) + total += amount + categoryTokens[category, default: 0] += amount + } + } + modelTokens[model] = total + } + + for costUsage in totalCosts { + guard costUsage.model != nil else { continue } + for item in costUsage.usage ?? [] { + guard let category = DeepSeekUsageCategory(rawValue: item.type ?? "") else { continue } + if category != .request { + let amount = Self.parseCostAmount(item.amount) + categoryCosts[category, default: 0] += amount + } + } + } + + let topModel = modelTokens.max { + if $0.value == $1.value { return $0.key > $1.key } + return $0.value < $1.value + }?.key + + var breakdown: [DeepSeekCategoryBreakdown] = [] + for category in [DeepSeekUsageCategory.promptCacheHitToken, .promptCacheMissToken, .responseToken] { + breakdown.append(DeepSeekCategoryBreakdown( + category: category, + tokens: categoryTokens[category] ?? 0, + cost: categoryCosts[category])) + } + + return (topModel, breakdown) + } + + private static func buildDailyUsages(ctx: DailyAggregationContext) -> [DeepSeekDailyUsage] { + var result: [DeepSeekDailyUsage] = [] + + for date in ctx.allDates.sorted() { + guard let parsed = self.parseDate(date, calendar: ctx.calendar), + parsed >= ctx.startOfMonth, + parsed <= ctx.now + else { continue } + + var dayTokens = 0 + var dayCost: Double? + var dayRequests = 0 + + if let amounts = ctx.amountMap[date] { + for items in amounts.values { + for item in items { + guard let category = DeepSeekUsageCategory(rawValue: item.type ?? "") else { continue } + if category == .request { + dayRequests += Self.parseTokenAmount(item.amount) + } else { + dayTokens += Self.parseTokenAmount(item.amount) + } + } + } + } + + if let costs = ctx.costMap[date] { + for items in costs.values { + for item in items { + guard let category = DeepSeekUsageCategory(rawValue: item.type ?? "") else { continue } + if category != .request { + let amount = Self.parseCostAmount(item.amount) + if let existing = dayCost { + dayCost = existing + amount + } else { + dayCost = amount + } + } + } + } + } + + result.append(DeepSeekDailyUsage( + date: date, + totalTokens: dayTokens, + cost: dayCost, + requestCount: dayRequests)) + } + + return result + } + + // MARK: - Helpers + + private static func parseTokenAmount(_ value: String?) -> Int { + guard let value, let intValue = Int64(value.trimmingCharacters(in: .whitespacesAndNewlines)) else { + return 0 + } + return Int(intValue) + } + + private static func parseCostAmount(_ value: String?) -> Double { + guard let value else { return 0 } + let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines) + return Double(trimmed) ?? 0 + } + + private static func parseDate(_ text: String, calendar: Calendar) -> Date? { + let trimmed = text.trimmingCharacters(in: .whitespacesAndNewlines) + guard !trimmed.isEmpty else { return nil } + let formatter = DateFormatter() + formatter.locale = Locale(identifier: "en_US_POSIX") + formatter.calendar = calendar + formatter.timeZone = calendar.timeZone + formatter.dateFormat = "yyyy-MM-dd" + return formatter.date(from: trimmed) + } +} diff --git a/Sources/CodexBarCore/Providers/DeepSeek/DeepSeekUsageFetcher.swift b/Sources/CodexBarCore/Providers/DeepSeek/DeepSeekUsageFetcher.swift new file mode 100644 index 0000000..d2f956c --- /dev/null +++ b/Sources/CodexBarCore/Providers/DeepSeek/DeepSeekUsageFetcher.swift @@ -0,0 +1,432 @@ +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +// MARK: - API response types + +public struct DeepSeekBalanceResponse: Decodable, Sendable { + public let isAvailable: Bool + public let balanceInfos: [DeepSeekBalanceInfo] + + enum CodingKeys: String, CodingKey { + case isAvailable = "is_available" + case balanceInfos = "balance_infos" + } +} + +public struct DeepSeekBalanceInfo: Decodable, Sendable { + public let currency: String + public let totalBalance: String + public let grantedBalance: String + public let toppedUpBalance: String + + enum CodingKeys: String, CodingKey { + case currency + case totalBalance = "total_balance" + case grantedBalance = "granted_balance" + case toppedUpBalance = "topped_up_balance" + } +} + +// MARK: - Domain snapshot + +public struct DeepSeekUsageSnapshot: Sendable { + public let isAvailable: Bool + public let currency: String + public let totalBalance: Double + public let grantedBalance: Double + public let toppedUpBalance: Double + public let usageSummary: DeepSeekUsageSummary? + public let updatedAt: Date + + public init( + isAvailable: Bool, + currency: String, + totalBalance: Double, + grantedBalance: Double, + toppedUpBalance: Double, + usageSummary: DeepSeekUsageSummary? = nil, + updatedAt: Date) + { + self.isAvailable = isAvailable + self.currency = currency + self.totalBalance = totalBalance + self.grantedBalance = grantedBalance + self.toppedUpBalance = toppedUpBalance + self.usageSummary = usageSummary + self.updatedAt = updatedAt + } + + public func toUsageSnapshot() -> UsageSnapshot { + let symbol = self.currency == "CNY" ? "¥" : "$" + + let balanceDetail: String + let usedPercent: Double + if self.totalBalance <= 0 { + balanceDetail = "\(symbol)0.00 — add credits at platform.deepseek.com" + usedPercent = 100 + } else if !self.isAvailable { + balanceDetail = "Balance unavailable for API calls" + usedPercent = 100 + } else { + let total = String(format: "\(symbol)%.2f", self.totalBalance) + let paid = String(format: "\(symbol)%.2f", self.toppedUpBalance) + let granted = String(format: "\(symbol)%.2f", self.grantedBalance) + balanceDetail = "\(total) (Paid: \(paid) / Granted: \(granted))" + usedPercent = 0 + } + + let identity = ProviderIdentitySnapshot( + providerID: .deepseek, + accountEmail: nil, + accountOrganization: nil, + loginMethod: nil) + let balanceWindow = RateWindow( + usedPercent: usedPercent, + windowMinutes: nil, + resetsAt: nil, + resetDescription: balanceDetail) + + return UsageSnapshot( + primary: balanceWindow, + secondary: nil, + tertiary: nil, + providerCost: nil, + deepseekUsage: self.usageSummary, + updatedAt: self.updatedAt, + identity: identity) + } +} + +// MARK: - Errors + +public enum DeepSeekUsageError: LocalizedError, Sendable { + case missingCredentials + case networkError(String) + case apiError(String) + case parseFailed(String) + + public var errorDescription: String? { + switch self { + case .missingCredentials: + "Missing DeepSeek API key." + case let .networkError(message): + "DeepSeek network error: \(message)" + case let .apiError(message): + "DeepSeek API error: \(message)" + case let .parseFailed(message): + "Failed to parse DeepSeek response: \(message)" + } + } +} + +// MARK: - Fetcher + +public struct DeepSeekUsageFetcher: Sendable { + private static let log = CodexBarLog.logger(LogCategories.deepSeekUsage) + private static let balanceURL = URL(string: "https://api.deepseek.com/user/balance")! + private static let usageAmountURL = URL(string: "https://platform.deepseek.com/api/v0/usage/amount")! + private static let usageCostURL = URL(string: "https://platform.deepseek.com/api/v0/usage/cost")! + private static let timeoutSeconds: TimeInterval = 15 + private static let optionalSummaryJoinGrace: Duration = .seconds(2) + private static var apiCalendar: Calendar { + var calendar = Calendar(identifier: .gregorian) + calendar.locale = Locale(identifier: "en_US_POSIX") + calendar.timeZone = TimeZone(secondsFromGMT: 0) ?? .gmt + return calendar + } + + public static func fetchUsage( + apiKey: String, + includeOptionalUsage: Bool = true) async throws -> DeepSeekUsageSnapshot + { + try await self.fetchUsage( + apiKey: apiKey, + includeOptionalUsage: includeOptionalUsage, + optionalSummaryJoinGrace: self.optionalSummaryJoinGrace, + fetchBalanceData: { key in + try await self.fetchBalanceData(apiKey: key) + }, + fetchSummary: { key in + try await self.fetchUsageSummary(apiKey: key) + }) + } + + static func _fetchUsageForTesting( + apiKey: String, + includeOptionalUsage: Bool, + optionalSummaryJoinGrace: Duration = .zero, + fetchBalanceData: @escaping @Sendable (String) async throws -> Data, + fetchSummary: @escaping @Sendable (String) async throws -> DeepSeekUsageSummary) + async throws -> DeepSeekUsageSnapshot + { + try await self.fetchUsage( + apiKey: apiKey, + includeOptionalUsage: includeOptionalUsage, + optionalSummaryJoinGrace: optionalSummaryJoinGrace, + fetchBalanceData: fetchBalanceData, + fetchSummary: fetchSummary) + } + + private static func fetchUsage( + apiKey: String, + includeOptionalUsage: Bool, + optionalSummaryJoinGrace: Duration, + fetchBalanceData: @escaping @Sendable (String) async throws -> Data, + fetchSummary: @escaping @Sendable (String) async throws -> DeepSeekUsageSummary) + async throws -> DeepSeekUsageSnapshot + { + guard !apiKey.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else { + throw DeepSeekUsageError.missingCredentials + } + + let summaryTask: Task? = if includeOptionalUsage { + Task { + try await fetchSummary(apiKey) + } + } else { + nil + } + + let balanceData: Data + do { + balanceData = try await withTaskCancellationHandler { + try await fetchBalanceData(apiKey) + } onCancel: { + summaryTask?.cancel() + } + } catch { + summaryTask?.cancel() + throw error + } + var snapshot: DeepSeekUsageSnapshot + do { + snapshot = try Self.parseSnapshot(data: balanceData) + } catch { + summaryTask?.cancel() + throw error + } + + if let summaryTask { + let summary = try await self.completedOptionalUsageSummary( + from: summaryTask, + joinGrace: optionalSummaryJoinGrace) + if let summary { + snapshot = DeepSeekUsageSnapshot( + isAvailable: snapshot.isAvailable, + currency: snapshot.currency, + totalBalance: snapshot.totalBalance, + grantedBalance: snapshot.grantedBalance, + toppedUpBalance: snapshot.toppedUpBalance, + usageSummary: summary, + updatedAt: snapshot.updatedAt) + } + } + + return snapshot + } + + private static func fetchBalanceData(apiKey: String) async throws -> Data { + var request = URLRequest(url: self.balanceURL) + request.httpMethod = "GET" + request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization") + request.setValue("application/json", forHTTPHeaderField: "Accept") + request.timeoutInterval = Self.timeoutSeconds + + let response = try await ProviderHTTPClient.shared.response(for: request) + let data = response.data + guard response.statusCode == 200 else { + Self.log.error("DeepSeek balance endpoint returned HTTP \(response.statusCode)") + throw DeepSeekUsageError.apiError("HTTP \(response.statusCode)") + } + + return data + } + + private static func completedOptionalUsageSummary( + from task: Task, + joinGrace: Duration) async throws -> DeepSeekUsageSummary? + { + let race = BoundedTaskJoin(sourceTask: task) + switch await race.value(joinGrace: joinGrace) { + case let .value(summary): + try Task.checkCancellation() + return summary + case .timedOut: + try Task.checkCancellation() + return nil + case let .failure(error): + task.cancel() + if Task.isCancelled { + throw error + } + return nil + } + } + + static func _parseSnapshotForTesting(_ data: Data) throws -> DeepSeekUsageSnapshot { + try self.parseSnapshot(data: data) + } + + public static func fetchUsageSummary( + apiKey: String, + now: Date = Date(), + calendar: Calendar? = nil) async throws -> DeepSeekUsageSummary + { + let calendar = calendar ?? self.apiCalendar + let period = try self.usagePeriod(now: now, calendar: calendar) + + let amountData = try await self.fetchAmount(apiKey: apiKey, month: period.month, year: period.year) + let costData = try await self.fetchCost(apiKey: apiKey, month: period.month, year: period.year) + + return try DeepSeekUsageCostParser.parse( + amountData: amountData, + costData: costData, + now: now, + calendar: calendar) + } + + static func _apiUsagePeriodForTesting(now: Date, calendar: Calendar? = nil) throws -> (month: Int, year: Int) { + try self.usagePeriod(now: now, calendar: calendar ?? self.apiCalendar) + } + + private static func usagePeriod(now: Date, calendar: Calendar) throws -> (month: Int, year: Int) { + let monthComponents = calendar.dateComponents([.month, .year], from: now) + guard let month = monthComponents.month, let year = monthComponents.year else { + throw DeepSeekUsageError.parseFailed("Could not determine current month/year") + } + return (month: month, year: year) + } + + private static func fetchAmount(apiKey: String, month: Int, year: Int) async throws -> Data { + guard var components = URLComponents(url: self.usageAmountURL, resolvingAgainstBaseURL: false) else { + throw DeepSeekUsageError.networkError("Invalid URL") + } + components.queryItems = [ + URLQueryItem(name: "month", value: String(month)), + URLQueryItem(name: "year", value: String(year)), + ] + guard let url = components.url else { + throw DeepSeekUsageError.networkError("Could not construct URL") + } + + var request = URLRequest(url: url) + request.httpMethod = "GET" + request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization") + request.setValue("application/json", forHTTPHeaderField: "Accept") + request.timeoutInterval = Self.timeoutSeconds + + let response = try await ProviderHTTPClient.shared.response(for: request) + let data = response.data + guard response.statusCode == 200 else { + if response.statusCode == 401 || response.statusCode == 403 { + throw DeepSeekUsageError.missingCredentials + } + throw DeepSeekUsageError.apiError("HTTP \(response.statusCode)") + } + + return data + } + + private static func fetchCost(apiKey: String, month: Int, year: Int) async throws -> Data { + guard var components = URLComponents(url: self.usageCostURL, resolvingAgainstBaseURL: false) else { + throw DeepSeekUsageError.networkError("Invalid URL") + } + components.queryItems = [ + URLQueryItem(name: "month", value: String(month)), + URLQueryItem(name: "year", value: String(year)), + ] + guard let url = components.url else { + throw DeepSeekUsageError.networkError("Could not construct URL") + } + + var request = URLRequest(url: url) + request.httpMethod = "GET" + request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization") + request.setValue("application/json", forHTTPHeaderField: "Accept") + request.timeoutInterval = Self.timeoutSeconds + + let response = try await ProviderHTTPClient.shared.response(for: request) + let data = response.data + guard response.statusCode == 200 else { + if response.statusCode == 401 || response.statusCode == 403 { + throw DeepSeekUsageError.missingCredentials + } + throw DeepSeekUsageError.apiError("HTTP \(response.statusCode)") + } + + return data + } + + static func _parseUsageSummaryForTesting( + amountData: Data, + costData: Data, + now: Date = Date(), + calendar: Calendar = .current) throws -> DeepSeekUsageSummary + { + try DeepSeekUsageCostParser.parse( + amountData: amountData, + costData: costData, + now: now, + calendar: calendar) + } + + private static func parseSnapshot(data: Data) throws -> DeepSeekUsageSnapshot { + let decoded: DeepSeekBalanceResponse + do { + decoded = try JSONDecoder().decode(DeepSeekBalanceResponse.self, from: data) + } catch { + throw DeepSeekUsageError.parseFailed(error.localizedDescription) + } + + let balances = try decoded.balanceInfos.map(Self.parseBalanceInfo) + guard !balances.isEmpty else { + return DeepSeekUsageSnapshot( + isAvailable: false, + currency: "USD", + totalBalance: 0, + grantedBalance: 0, + toppedUpBalance: 0, + updatedAt: Date()) + } + + // Prefer USD when it is funded, but do not hide a positive CNY balance behind + // an empty USD row returned by the API. + let selected = balances.first { $0.currency == "USD" && $0.totalBalance > 0 } + ?? balances.first { $0.totalBalance > 0 } + ?? balances.first { $0.currency == "USD" } + ?? balances[0] + + return DeepSeekUsageSnapshot( + isAvailable: decoded.isAvailable, + currency: selected.currency, + totalBalance: selected.totalBalance, + grantedBalance: selected.grantedBalance, + toppedUpBalance: selected.toppedUpBalance, + updatedAt: Date()) + } + + private struct ParsedBalanceInfo { + let currency: String + let totalBalance: Double + let grantedBalance: Double + let toppedUpBalance: Double + } + + private static func parseBalanceInfo(_ info: DeepSeekBalanceInfo) throws -> ParsedBalanceInfo { + guard + let total = Double(info.totalBalance), + let granted = Double(info.grantedBalance), + let toppedUp = Double(info.toppedUpBalance) + else { + throw DeepSeekUsageError.parseFailed("Non-numeric balance value in response.") + } + + return ParsedBalanceInfo( + currency: info.currency, + totalBalance: total, + grantedBalance: granted, + toppedUpBalance: toppedUp) + } +} diff --git a/Sources/CodexBarCore/Providers/Deepgram/DeepgramProviderDescriptor.swift b/Sources/CodexBarCore/Providers/Deepgram/DeepgramProviderDescriptor.swift new file mode 100644 index 0000000..5e77cb4 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Deepgram/DeepgramProviderDescriptor.swift @@ -0,0 +1,102 @@ +import Foundation + +public enum DeepgramProviderDescriptor { + public static let descriptor: ProviderDescriptor = Self.makeDescriptor() + + static func makeDescriptor() -> ProviderDescriptor { + ProviderDescriptor( + id: .deepgram, + metadata: ProviderMetadata( + id: .deepgram, + displayName: "Deepgram", + sessionLabel: "Requests", + weeklyLabel: "Usage", + opusLabel: nil, + supportsOpus: false, + supportsCredits: false, + creditsHint: "Usage summary from Deepgram API", + toggleTitle: "Show Deepgram usage", + cliName: "deepgram", + defaultEnabled: false, + isPrimaryProvider: false, + usesAccountFallback: false, + browserCookieOrder: nil, + dashboardURL: "https://console.deepgram.com/project/", + statusPageURL: nil, + statusLinkURL: "https://status.deepgram.com"), + branding: ProviderBranding( + iconStyle: .deepgram, + iconResourceName: "ProviderIcon-deepgram", + color: ProviderColor( + red: 100 / 255, + green: 103 / 255, + blue: 242 / 255)), + tokenCost: ProviderTokenCostConfig( + supportsTokenCost: false, + noDataMessage: { + "Deepgram cost summary is not yet supported." + }), + fetchPlan: ProviderFetchPlan( + sourceModes: [.auto, .api], + pipeline: ProviderFetchPipeline( + resolveStrategies: { _ in + [DeepgramAPIFetchStrategy()] + })), + cli: ProviderCLIConfig( + name: "deepgram", + aliases: ["dg"], + versionDetector: nil)) + } +} + +struct DeepgramAPIFetchStrategy: ProviderFetchStrategy { + let id: String = "deepgram.api" + let kind: ProviderFetchKind = .apiToken + + func isAvailable(_ context: ProviderFetchContext) async -> Bool { + Self.resolveAPIKey(context) != nil + } + + func fetch(_ context: ProviderFetchContext) async throws -> ProviderFetchResult { + guard let apiKey = Self.resolveAPIKey(context) else { + throw DeepgramSettingsError.missingToken + } + + let usage = try await DeepgramUsageFetcher.fetchUsage( + apiKey: apiKey, + projectID: Self.resolveProjectID(context), + environment: context.env) + + return self.makeResult( + usage: usage.toUsageSnapshot(), + sourceLabel: "api") + } + + func shouldFallback(on _: Error, context _: ProviderFetchContext) -> Bool { + false + } + + private static func resolveAPIKey(_ context: ProviderFetchContext) -> String? { + ProviderTokenResolver.deepgramResolution( + type: .apiKey, + environment: context.env) + } + + private static func resolveProjectID(_ context: ProviderFetchContext) -> String? { + ProviderTokenResolver.deepgramResolution( + type: .projectID, + environment: context.env) + } +} + +/// Errors related to Deepgram settings +public enum DeepgramSettingsError: LocalizedError, Sendable { + case missingToken + + public var errorDescription: String? { + switch self { + case .missingToken: + "Deepgram API token not configured. Set DEEPGRAM_API_KEY environment variable or configure in Settings." + } + } +} diff --git a/Sources/CodexBarCore/Providers/Deepgram/DeepgramSettingsReader.swift b/Sources/CodexBarCore/Providers/Deepgram/DeepgramSettingsReader.swift new file mode 100644 index 0000000..beb8610 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Deepgram/DeepgramSettingsReader.swift @@ -0,0 +1,33 @@ +import Foundation + +public struct DeepgramSettingsReader: Sendable { + public static let apiKeyEnvironmentKey = "DEEPGRAM_API_KEY" + public static let projectIDEnvironmentKey = "DEEPGRAM_PROJECT_ID" + + public static func apiKey( + environment: [String: String] = ProcessInfo.processInfo.environment) -> String? + { + self.cleaned(environment[self.apiKeyEnvironmentKey]) + } + + public static func projectID( + environment: [String: String] = ProcessInfo.processInfo.environment) -> String? + { + self.cleaned(environment[self.projectIDEnvironmentKey]) + } + + private static func cleaned(_ raw: String?) -> String? { + guard var value = raw?.trimmingCharacters(in: .whitespacesAndNewlines), !value.isEmpty else { + return nil + } + + if (value.hasPrefix("\"") && value.hasSuffix("\"")) || + (value.hasPrefix("'") && value.hasSuffix("'")) + { + value = String(value.dropFirst().dropLast()) + } + + value = value.trimmingCharacters(in: .whitespacesAndNewlines) + return value.isEmpty ? nil : value + } +} diff --git a/Sources/CodexBarCore/Providers/Deepgram/DeepgramUsageFetcher.swift b/Sources/CodexBarCore/Providers/Deepgram/DeepgramUsageFetcher.swift new file mode 100644 index 0000000..0cbbc44 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Deepgram/DeepgramUsageFetcher.swift @@ -0,0 +1,561 @@ +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +public enum DeepgramUsageError: LocalizedError, Sendable { + case missingAPIKey + case invalidEndpointOverride(String) + case invalidCredentials + case invalidProjectID + case forbidden(String) + case networkError(String) + case apiError(String) + case parseFailed(String) + + public var errorDescription: String? { + switch self { + case .missingAPIKey: + "Missing Deepgram API key. Set apiKey in ~/.codexbar/config.json or DEEPGRAM_API_KEY." + case let .invalidEndpointOverride(key): + "Deepgram endpoint override \(key) must use HTTPS or a bare host." + case .invalidCredentials: + "Deepgram API key is invalid or expired." + case .invalidProjectID: + "Deepgram project ID is invalid or no projects were returned for this API key." + case let .forbidden(message): + "Deepgram rejected access: \(message)" + case let .networkError(message): + "Deepgram network error: \(message)" + case let .apiError(message): + "Deepgram API error: \(message)" + case let .parseFailed(message): + "Deepgram parse error: \(message)" + } + } +} + +// MARK: - API Responses + +public struct DeepgramProjectsResponse: Decodable, Sendable { + public let projects: [DeepgramProject] +} + +public struct DeepgramProject: Decodable, Sendable, Equatable { + public let projectID: String + public let name: String? + + private enum CodingKeys: String, CodingKey { + case projectID = "project_id" + case name + } + + public init(projectID: String, name: String? = nil) { + self.projectID = projectID + self.name = name + } +} + +public struct DeepgramUsageResponse: Decodable, Sendable { + public let start: String? + public let end: String? + public let resolution: DeepgramUsageResolution? + public let results: [DeepgramUsageResult] +} + +public struct DeepgramUsageResolution: Decodable, Sendable { + public let units: String? + public let amount: Int? +} + +public struct DeepgramUsageResult: Codable, Sendable { + public let start: String? + public let end: String? + public let hours: Double? + public let totalHours: Double? + public let agentHours: Double? + public let tokensIn: Int? + public let tokensOut: Int? + public let ttsCharacters: Int? + public let requests: Int? + + private enum CodingKeys: String, CodingKey { + case start + case end + case hours + case totalHours = "total_hours" + case agentHours = "agent_hours" + case tokensIn = "tokens_in" + case tokensOut = "tokens_out" + case ttsCharacters = "tts_characters" + case requests + } +} + +// MARK: - Query + +public struct DeepgramUsageQuery: Sendable { + public var start: String? + public var end: String? + + public init( + start: String? = nil, + end: String? = nil) + { + self.start = start + self.end = end + } + + public func queryItems() -> [URLQueryItem] { + var items: [URLQueryItem] = [] + + func add(_ name: String, _ value: String?) { + guard let value = value?.trimmingCharacters(in: .whitespacesAndNewlines), + !value.isEmpty + else { + return + } + items.append(URLQueryItem(name: name, value: value)) + } + + add("start", self.start) + add("end", self.end) + + return items + } +} + +// MARK: - Snapshot + +public struct DeepgramUsageSnapshot: Codable, Sendable { + public let projectID: String + public let projectName: String? + public let projectCount: Int + public let start: String? + public let end: String? + public let hours: Double + public let totalHours: Double + public let agentHours: Double + public let tokensIn: Int + public let tokensOut: Int + public let ttsCharacters: Int + public let requests: Int + public let updatedAt: Date + + public init( + projectID: String, + projectName: String? = nil, + projectCount: Int = 1, + start: String?, + end: String?, + hours: Double, + totalHours: Double, + agentHours: Double = 0, + tokensIn: Int = 0, + tokensOut: Int = 0, + ttsCharacters: Int = 0, + requests: Int, + updatedAt: Date) + { + self.projectID = projectID + self.projectName = projectName + self.projectCount = projectCount + self.start = start + self.end = end + self.hours = hours + self.totalHours = totalHours + self.agentHours = agentHours + self.tokensIn = tokensIn + self.tokensOut = tokensOut + self.ttsCharacters = ttsCharacters + self.requests = requests + self.updatedAt = updatedAt + } +} + +extension DeepgramUsageSnapshot { + public func toUsageSnapshot() -> UsageSnapshot { + let identity = ProviderIdentitySnapshot( + providerID: .deepgram, + accountEmail: nil, + accountOrganization: nil, + loginMethod: self.identityLabel) + + return UsageSnapshot( + primary: nil, + secondary: nil, + tertiary: nil, + providerCost: nil, + deepgramUsage: self, + updatedAt: self.updatedAt, + identity: identity) + } + + public var displayLines: [String] { + var lines: [String] = [] + lines.append("Requests: \(Self.formatInteger(self.requests))") + + var usageParts: [String] = [] + if self.hours > 0 { + usageParts.append("\(Self.formatDecimal(self.hours)) audio hours") + } + if self.totalHours > 0 { + usageParts.append("\(Self.formatDecimal(self.totalHours)) billable hours") + } + if !usageParts.isEmpty { + lines.append(usageParts.joined(separator: " · ")) + } + + var modelParts: [String] = [] + if self.agentHours > 0 { + modelParts.append("\(Self.formatDecimal(self.agentHours)) agent hours") + } + if self.tokensIn > 0 || self.tokensOut > 0 { + modelParts.append("\(Self.formatInteger(self.tokensIn + self.tokensOut)) tokens") + } + if self.ttsCharacters > 0 { + modelParts.append("\(Self.formatInteger(self.ttsCharacters)) TTS chars") + } + if !modelParts.isEmpty { + lines.append(modelParts.joined(separator: " · ")) + } + + if let start, let end { + lines.append("Period: \(start) to \(end)") + } + + return lines + } + + private var identityLabel: String? { + if self.projectCount > 1 { + return "\(self.projectCount) projects" + } + if let projectName = self.projectName?.trimmingCharacters(in: .whitespacesAndNewlines), + !projectName.isEmpty + { + return "Project: \(projectName)" + } + return "Project: \(self.projectID)" + } + + fileprivate static func aggregate( + _ snapshots: [DeepgramUsageSnapshot], + updatedAt: Date) throws -> DeepgramUsageSnapshot + { + guard let first = snapshots.first else { + throw DeepgramUsageError.invalidProjectID + } + if snapshots.count == 1 { return first } + return DeepgramUsageSnapshot( + projectID: "all", + projectName: nil, + projectCount: snapshots.count, + start: snapshots.compactMap(\.start).min(), + end: snapshots.compactMap(\.end).max(), + hours: snapshots.reduce(0) { $0 + $1.hours }, + totalHours: snapshots.reduce(0) { $0 + $1.totalHours }, + agentHours: snapshots.reduce(0) { $0 + $1.agentHours }, + tokensIn: snapshots.reduce(0) { $0 + $1.tokensIn }, + tokensOut: snapshots.reduce(0) { $0 + $1.tokensOut }, + ttsCharacters: snapshots.reduce(0) { $0 + $1.ttsCharacters }, + requests: snapshots.reduce(0) { $0 + $1.requests }, + updatedAt: updatedAt) + } + + private static func formatInteger(_ value: Int) -> String { + let formatter = NumberFormatter() + formatter.locale = Locale(identifier: "en_US_POSIX") + formatter.numberStyle = .decimal + formatter.usesGroupingSeparator = true + formatter.groupingSeparator = "," + formatter.maximumFractionDigits = 0 + return formatter.string(from: NSNumber(value: value)) ?? "\(value)" + } + + private static func formatDecimal(_ value: Double) -> String { + let formatter = NumberFormatter() + formatter.locale = Locale(identifier: "en_US_POSIX") + formatter.numberStyle = .decimal + formatter.usesGroupingSeparator = true + formatter.groupingSeparator = "," + formatter.minimumFractionDigits = value == floor(value) ? 0 : 1 + formatter.maximumFractionDigits = 1 + return formatter.string(from: NSNumber(value: value)) ?? String(format: "%.1f", value) + } +} + +// MARK: - Fetcher + +public struct DeepgramUsageFetcher: Sendable { + public static let apiURLKey = "DEEPGRAM_API_URL" + + private static let log = CodexBarLog.logger(LogCategories.deepgramUsage) + private static let defaultBaseURL = URL(string: "https://api.deepgram.com/v1")! + + private struct FetchContext { + let apiKey: String + let query: DeepgramUsageQuery + let timeout: TimeInterval + let environment: [String: String] + let transport: ProviderHTTPTransport + let updatedAt: Date + } + + public static func fetchUsage( + apiKey: String, + projectID: String? = nil, + query: DeepgramUsageQuery = DeepgramUsageQuery(), + timeout: TimeInterval = 15, + environment: [String: String] = ProcessInfo.processInfo.environment, + transport: ProviderHTTPTransport = ProviderHTTPClient.shared) async throws -> DeepgramUsageSnapshot + { + let cleanedAPIKey = apiKey.trimmingCharacters(in: .whitespacesAndNewlines) + guard !cleanedAPIKey.isEmpty else { + throw DeepgramUsageError.missingAPIKey + } + try self.validateEndpointOverrides(environment: environment) + + let updatedAt = Date() + let context = FetchContext( + apiKey: cleanedAPIKey, + query: query, + timeout: timeout, + environment: environment, + transport: transport, + updatedAt: updatedAt) + + if let cleanedProjectID = self.cleaned(projectID) { + return try await self.fetchUsage( + project: DeepgramProject(projectID: cleanedProjectID), + context: context) + } + + let projects = try await self.listProjects( + apiKey: cleanedAPIKey, + timeout: timeout, + environment: environment, + transport: transport) + guard !projects.isEmpty else { + throw DeepgramUsageError.invalidProjectID + } + + var snapshots: [DeepgramUsageSnapshot] = [] + snapshots.reserveCapacity(projects.count) + for project in projects { + let snapshot = try await self.fetchUsage( + project: project, + context: context) + snapshots.append(snapshot) + } + return try DeepgramUsageSnapshot.aggregate(snapshots, updatedAt: updatedAt) + } + + static func _parseSnapshotForTesting( + _ data: Data, + projectID: String = "project-test", + projectName: String? = nil, + updatedAt: Date = Date()) throws -> DeepgramUsageSnapshot + { + try self.parseUsage( + data: data, + project: DeepgramProject(projectID: projectID, name: projectName), + updatedAt: updatedAt) + } + + private static func listProjects( + apiKey: String, + timeout: TimeInterval, + environment: [String: String], + transport: ProviderHTTPTransport) async throws -> [DeepgramProject] + { + let url = self.apiURL(environment: environment).appendingPathComponent("projects") + var request = URLRequest(url: url) + request.httpMethod = "GET" + request.timeoutInterval = timeout + request.setValue("Token \(apiKey)", forHTTPHeaderField: "Authorization") + request.setValue("application/json", forHTTPHeaderField: "Accept") + + let response = try await self.perform(request: request, transport: transport) + do { + return try JSONDecoder().decode(DeepgramProjectsResponse.self, from: response.data).projects + } catch { + Self.log.error("Deepgram projects decode failed: \(error.localizedDescription)") + throw DeepgramUsageError.parseFailed(error.localizedDescription) + } + } + + private static func fetchUsage( + project: DeepgramProject, + context: FetchContext) async throws -> DeepgramUsageSnapshot + { + let url = try self.usageURL( + projectID: project.projectID, + query: context.query, + environment: context.environment) + + var request = URLRequest(url: url) + request.httpMethod = "GET" + request.timeoutInterval = context.timeout + request.setValue("Token \(context.apiKey)", forHTTPHeaderField: "Authorization") + request.setValue("application/json", forHTTPHeaderField: "Accept") + + let response = try await self.perform(request: request, transport: context.transport) + return try self.parseUsage(data: response.data, project: project, updatedAt: context.updatedAt) + } + + private static func perform( + request: URLRequest, + transport: ProviderHTTPTransport) async throws -> ProviderHTTPResponse + { + let response: ProviderHTTPResponse + do { + response = try await transport.response(for: request) + } catch { + throw DeepgramUsageError.networkError(error.localizedDescription) + } + + guard response.statusCode == 200 else { + let summary = self.responseSummary(response.data) + Self.log.error("Deepgram returned HTTP \(response.statusCode): \(summary)") + + switch response.statusCode { + case 401: + throw DeepgramUsageError.invalidCredentials + case 403: + throw DeepgramUsageError.forbidden( + "The API key may not have access to the project or the Management API. HTTP 403: \(summary)") + case 400: + throw DeepgramUsageError.apiError("Bad request. HTTP 400: \(summary)") + default: + throw DeepgramUsageError.apiError("HTTP \(response.statusCode): \(summary)") + } + } + + return response + } + + private static func usageURL( + projectID: String, + query: DeepgramUsageQuery, + environment: [String: String]) throws -> URL + { + let usageURL = self.apiURL(environment: environment) + .appendingPathComponent("projects") + .appendingPathComponent(projectID) + .appendingPathComponent("usage") + .appendingPathComponent("breakdown") + + guard var components = URLComponents(url: usageURL, resolvingAgainstBaseURL: false) else { + throw DeepgramUsageError.networkError("Invalid usage URL") + } + + let queryItems = query.queryItems() + if !queryItems.isEmpty { + components.queryItems = queryItems + } + + guard let finalURL = components.url else { + throw DeepgramUsageError.networkError("Invalid usage query") + } + + return finalURL + } + + private static func apiURL(environment: [String: String]) -> URL { + if let raw = self.cleaned(environment[self.apiURLKey]), + let url = ProviderEndpointOverrideValidator.normalizedHTTPSURL(from: raw) + { + return url + } + + return self.defaultBaseURL + } + + public static func validateEndpointOverrides(environment: [String: String] = ProcessInfo.processInfo + .environment) throws + { + guard let raw = self.cleaned(environment[self.apiURLKey]) else { return } + guard ProviderEndpointOverrideValidator.normalizedHTTPSURL(from: raw) == nil else { return } + throw DeepgramUsageError.invalidEndpointOverride(self.apiURLKey) + } + + private static func parseUsage( + data: Data, + project: DeepgramProject, + updatedAt: Date) throws -> DeepgramUsageSnapshot + { + do { + let response = try JSONDecoder().decode(DeepgramUsageResponse.self, from: data) + return DeepgramUsageSnapshot( + projectID: project.projectID, + projectName: project.name, + start: response.start, + end: response.end, + hours: response.results.reduce(0) { $0 + ($1.hours ?? 0) }, + totalHours: response.results.reduce(0) { $0 + ($1.totalHours ?? 0) }, + agentHours: response.results.reduce(0) { $0 + ($1.agentHours ?? 0) }, + tokensIn: response.results.reduce(0) { $0 + ($1.tokensIn ?? 0) }, + tokensOut: response.results.reduce(0) { $0 + ($1.tokensOut ?? 0) }, + ttsCharacters: response.results.reduce(0) { $0 + ($1.ttsCharacters ?? 0) }, + requests: response.results.reduce(0) { $0 + ($1.requests ?? 0) }, + updatedAt: updatedAt) + } catch let error as DecodingError { + Self.log.error("Deepgram decoding error: \(error.localizedDescription)") + Self.log.error("Deepgram raw response: \(self.responseSummary(data))") + throw DeepgramUsageError.parseFailed(error.localizedDescription) + } catch { + Self.log.error("Deepgram parse error: \(error.localizedDescription)") + Self.log.error("Deepgram raw response: \(self.responseSummary(data))") + throw DeepgramUsageError.parseFailed(error.localizedDescription) + } + } + + private static func cleaned(_ raw: String?) -> String? { + guard let value = raw?.trimmingCharacters(in: .whitespacesAndNewlines), !value.isEmpty else { + return nil + } + return value + } + + private static func responseSummary(_ data: Data) -> String { + guard !data.isEmpty else { return "empty body" } + + guard let text = String(data: data, encoding: .utf8) else { + return "non-text body (\(data.count) bytes)" + } + + let cleaned = text + .replacingOccurrences(of: #"\s+"#, with: " ", options: .regularExpression) + .trimmingCharacters(in: .whitespacesAndNewlines) + + guard !cleaned.isEmpty else { + return "empty body" + } + + let maxLength = 240 + guard cleaned.count > maxLength else { + return self.redact(cleaned) + } + + let index = cleaned.index(cleaned.startIndex, offsetBy: maxLength) + return self.redact("\(cleaned[.. String { + let replacements: [(String, String)] = [ + (#"(?i)(token\s+)[A-Za-z0-9._\-]+"#, "$1[REDACTED]"), + (#"(?i)(dg_[A-Za-z0-9._\-]+)"#, "[REDACTED]"), + ( + #"(?i)(\"(?:api_?key|authorization|token|access_token|refresh_token)\"\s*:\s*\")([^\"]+)(\")"#, + "$1[REDACTED]$3"), + ] + + return replacements.reduce(text) { partial, replacement in + partial.replacingOccurrences( + of: replacement.0, + with: replacement.1, + options: .regularExpression) + } + } +} diff --git a/Sources/CodexBarCore/Providers/Devin/DevinProviderDescriptor.swift b/Sources/CodexBarCore/Providers/Devin/DevinProviderDescriptor.swift new file mode 100644 index 0000000..8cdcd55 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Devin/DevinProviderDescriptor.swift @@ -0,0 +1,92 @@ +import Foundation + +public enum DevinProviderDescriptor { + public static let descriptor: ProviderDescriptor = Self.makeDescriptor() + + static func makeDescriptor() -> ProviderDescriptor { + ProviderDescriptor( + id: .devin, + metadata: ProviderMetadata( + id: .devin, + displayName: "Devin", + sessionLabel: "Daily", + weeklyLabel: "Weekly", + opusLabel: nil, + supportsOpus: false, + supportsCredits: false, + creditsHint: "", + toggleTitle: "Show Devin usage", + cliName: "devin", + defaultEnabled: false, + isPrimaryProvider: false, + usesAccountFallback: false, + browserCookieOrder: ProviderBrowserCookieDefaults.devinCookieImportOrder, + dashboardURL: "https://app.devin.ai", + subscriptionDashboardURL: "https://app.devin.ai/settings/usage", + statusPageURL: nil), + branding: ProviderBranding( + iconStyle: .devin, + iconResourceName: "ProviderIcon-devin", + color: ProviderColor(red: 70 / 255, green: 180 / 255, blue: 130 / 255)), + tokenCost: ProviderTokenCostConfig( + supportsTokenCost: false, + noDataMessage: { "Devin cost summary is not supported." }), + fetchPlan: ProviderFetchPlan( + sourceModes: [.auto, .web], + pipeline: ProviderFetchPipeline(resolveStrategies: { _ in [DevinWebFetchStrategy()] })), + cli: ProviderCLIConfig( + name: "devin", + versionDetector: nil)) + } +} + +struct DevinWebFetchStrategy: ProviderFetchStrategy { + let id: String = "devin.web" + let kind: ProviderFetchKind = .web + + func isAvailable(_ context: ProviderFetchContext) async -> Bool { + let settings = context.settings?.devin + let source = settings?.cookieSource ?? .auto + guard source != .off else { return false } + if source == .manual { + return DevinUsageFetcher.manualAuth(from: Self.bearerTokenOverride(context: context)) != nil + } + #if os(macOS) + return true + #else + return false + #endif + } + + func fetch(_ context: ProviderFetchContext) async throws -> ProviderFetchResult { + let fetcher = DevinUsageFetcher(browserDetection: context.browserDetection) + let settings = context.settings?.devin + let logger: ((String) -> Void)? = context.verbose + ? { msg in CodexBarLog.logger(LogCategories.devin).verbose(msg) } + : nil + let snapshot = try await fetcher.fetch( + bearerTokenOverride: settings?.cookieSource == .manual ? Self.bearerTokenOverride(context: context) : nil, + organizationOverride: Self.organizationOverride(context: context), + timeout: context.webTimeout, + logger: logger) + return self.makeResult( + usage: snapshot.toUsageSnapshot(), + sourceLabel: "web") + } + + func shouldFallback(on _: Error, context _: ProviderFetchContext) -> Bool { + false + } + + private static func bearerTokenOverride(context: ProviderFetchContext) -> String? { + context.env["DEVIN_BEARER_TOKEN"] + ?? context.env["DEVIN_AUTHORIZATION"] + ?? context.settings?.devin?.manualBearerToken + } + + private static func organizationOverride(context: ProviderFetchContext) -> String? { + context.env["DEVIN_ORGANIZATION"] + ?? context.env["DEVIN_ORG"] + ?? context.settings?.devin?.organization + } +} diff --git a/Sources/CodexBarCore/Providers/Devin/DevinSessionImporter.swift b/Sources/CodexBarCore/Providers/Devin/DevinSessionImporter.swift new file mode 100644 index 0000000..102ed65 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Devin/DevinSessionImporter.swift @@ -0,0 +1,459 @@ +import Foundation +#if os(macOS) +import SweetCookieKit +#endif + +#if os(macOS) +enum DevinSessionImporter { + nonisolated(unsafe) static var importSessionOverrideForTesting: + ((BrowserDetection, String?, ((String) -> Void)?) -> SessionInfo?)? + + private static let storageOrigin = "https://app.devin.ai" + private static let externalOrgPrefix = "last-internal-org-for-external-org-v1-" + + struct SessionInfo: Equatable { + let accessToken: String + let organization: String? + let internalOrganizationID: String? + let sourceLabel: String + } + + struct LocalStorageCandidate { + let label: String + let url: URL + } + + static func importSession( + browserDetection: BrowserDetection, + organizationOverride: String? = nil, + logger: ((String) -> Void)? = nil) -> SessionInfo? + { + if let override = self.importSessionOverrideForTesting { + return override(browserDetection, organizationOverride, logger) + } + + let sessions = self.importSessions( + browserDetection: browserDetection, + organizationOverride: organizationOverride, + logger: logger) + return sessions.first + } + + static func importSessions( + browserDetection: BrowserDetection, + organizationOverride: String? = nil, + logger: ((String) -> Void)? = nil) -> [SessionInfo] + { + if let override = self.importSessionOverrideForTesting { + return override(browserDetection, organizationOverride, logger).map { [$0] } ?? [] + } + + let log: (String) -> Void = { msg in logger?("[devin-storage] \(msg)") } + let candidates = self.chromeLocalStorageCandidates(browserDetection: browserDetection) + if !candidates.isEmpty { + log("Chrome local storage candidates: \(candidates.count)") + } + + var sessions: [SessionInfo] = [] + for candidate in candidates { + let storage = self.readLocalStorage(from: candidate.url, logger: log) + guard let session = self.session( + from: storage, + organizationOverride: organizationOverride, + sourceLabel: candidate.label) + else { + continue + } + log( + "Found Devin session in \(candidate.label); " + + "organization=\(session.organization != nil), internalOrganizationID=" + + "\(session.internalOrganizationID != nil)") + sessions.append(session) + } + sessions = self.rankSessions(self.deduplicateSessions(sessions)) + + if sessions.isEmpty { + log("No Devin session found in browser local storage") + } + return sessions + } + + static func session( + from storage: [String: String], + organizationOverride: String? = nil, + sourceLabel: String) -> SessionInfo? + { + guard let accessToken = self.accessToken(from: storage) else { + return nil + } + let organizationInfo = self.organizationInfo(from: storage, organizationOverride: organizationOverride) + return SessionInfo( + accessToken: accessToken, + organization: organizationInfo.organization, + internalOrganizationID: organizationInfo.internalOrganizationID, + sourceLabel: sourceLabel) + } + + static func accessToken(from storage: [String: String]) -> String? { + for (key, value) in storage where self.isAuth1StorageKey(key) { + guard let json = self.jsonObject(from: value), + let token = self.findAuth1Token(in: json) + else { + continue + } + return token + } + + for (key, value) in storage where self.isAuth0StorageKey(key) { + guard let json = self.jsonObject(from: value), + let token = self.findAccessToken(in: json) + else { + continue + } + return token + } + + for value in storage.values { + guard let json = self.jsonObject(from: value), + let token = self.findAccessToken(in: json) + else { + continue + } + return token + } + + return nil + } + + static func deduplicateSessions(_ sessions: [SessionInfo]) -> [SessionInfo] { + var order: [String] = [] + var bestByToken: [String: SessionInfo] = [:] + for session in sessions { + if let existing = bestByToken[session.accessToken] { + if self.organizationScore(session) > self.organizationScore(existing) { + bestByToken[session.accessToken] = session + } + } else { + order.append(session.accessToken) + bestByToken[session.accessToken] = session + } + } + return order.compactMap { bestByToken[$0] } + } + + static func rankSessions(_ sessions: [SessionInfo]) -> [SessionInfo] { + sessions.enumerated() + .sorted { lhs, rhs in + let lhsScore = self.organizationScore(lhs.element) + let rhsScore = self.organizationScore(rhs.element) + return lhsScore == rhsScore ? lhs.offset < rhs.offset : lhsScore > rhsScore + } + .map(\.element) + } + + private static func organizationScore(_ session: SessionInfo) -> Int { + (session.organization == nil ? 0 : 1) + (session.internalOrganizationID == nil ? 0 : 2) + } + + static func organizationInfo( + from storage: [String: String], + organizationOverride: String?) -> (organization: String?, internalOrganizationID: String?) + { + let override = DevinUsageFetcher.normalizedOrganization(organizationOverride) + let overrideSlug = override.flatMap(self.slug(fromNormalizedOrganization:)) + var firstInternalOrgID: String? + + for (key, value) in storage where self.isExternalOrgStorageKey(key) { + let suffix = self.externalOrgSlug(from: key) + let orgID = self.cleanedOrgID(value) + if firstInternalOrgID == nil { + firstInternalOrgID = orgID + } + if let overrideSlug, suffix == overrideSlug { + return (override, orgID) + } + if override == nil, suffix != "null" { + return ("org/\(suffix)", orgID) + } + } + + if let inferred = self.inferredOrganizationInfo(from: storage, override: override) { + return inferred + } + + if let override { + return (override, firstInternalOrgID ?? self.orgID(fromNormalizedOrganization: override)) + } + + return (firstInternalOrgID.map { "organizations/\($0)" }, firstInternalOrgID) + } + + static func decodedStorageValue(_ value: String) -> String { + let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines) + guard !trimmed.isEmpty else { return trimmed } + if let data = trimmed.data(using: .utf8), + let decoded = try? JSONDecoder().decode(String.self, from: data) + { + return decoded.trimmingCharacters(in: .whitespacesAndNewlines) + } + return trimmed.trimmingCharacters(in: CharacterSet(charactersIn: "\"")) + .trimmingCharacters(in: .whitespacesAndNewlines) + } + + static func chromeLocalStorageCandidates(browserDetection: BrowserDetection) -> [LocalStorageCandidate] { + let installedBrowsers = self.localStorageBrowsers(browserDetection: browserDetection) + let roots = ChromiumProfileLocator + .roots(for: installedBrowsers, homeDirectories: BrowserCookieClient.defaultHomeDirectories()) + .map { (url: $0.url, labelPrefix: $0.labelPrefix) } + + var candidates: [LocalStorageCandidate] = [] + for root in roots { + candidates.append(contentsOf: self.chromeProfileLocalStorageDirs( + root: root.url, + labelPrefix: root.labelPrefix)) + } + return candidates + } + + static func localStorageBrowsers(browserDetection: BrowserDetection) -> [Browser] { + let order = ProviderDefaults.metadata[.devin]?.browserCookieOrder ?? [.chrome] + return order.browsersWithProfileData(using: browserDetection) + } + + private static func chromeProfileLocalStorageDirs(root: URL, labelPrefix: String) -> [LocalStorageCandidate] { + guard let entries = try? FileManager.default.contentsOfDirectory( + at: root, + includingPropertiesForKeys: [.isDirectoryKey], + options: [.skipsHiddenFiles]) + else { return [] } + + return entries.filter { url in + guard let isDir = (try? url.resourceValues(forKeys: [.isDirectoryKey]).isDirectory), isDir else { + return false + } + let name = url.lastPathComponent + return name == "Default" || name.hasPrefix("Profile ") || name.hasPrefix("user-") + } + .sorted { $0.lastPathComponent < $1.lastPathComponent } + .compactMap { dir in + let levelDBURL = dir.appendingPathComponent("Local Storage").appendingPathComponent("leveldb") + guard FileManager.default.fileExists(atPath: levelDBURL.path) else { return nil } + return LocalStorageCandidate(label: "\(labelPrefix) \(dir.lastPathComponent)", url: levelDBURL) + } + } + + private static func readLocalStorage(from levelDBURL: URL, logger: ((String) -> Void)?) -> [String: String] { + var storage: [String: String] = [:] + let entries = SweetCookieKit.ChromiumLocalStorageReader.readEntries( + for: self.storageOrigin, + in: levelDBURL, + logger: logger) + for entry in entries { + storage[entry.key] = self.decodedStorageValue(entry.value) + } + + let textEntries = SweetCookieKit.ChromiumLocalStorageReader.readTextEntries( + in: levelDBURL, + logger: logger) + for entry in textEntries where storage[entry.key] == nil { + if self.isUsefulStorageKey(entry.key) { + storage[entry.key] = self.decodedStorageValue(entry.value) + } + } + + return storage + } + + private static func jsonObject(from raw: String) -> Any? { + guard let data = raw.data(using: .utf8) else { return nil } + return try? JSONSerialization.jsonObject(with: data) + } + + private static func findAuth1Token(in object: Any) -> String? { + guard let dictionary = object as? [String: Any], + let token = dictionary["token"] as? String + else { + return nil + } + let value = token.trimmingCharacters(in: .whitespacesAndNewlines) + return value.hasPrefix("auth1_") && value.count > 20 ? value : nil + } + + private static func findAccessToken(in object: Any) -> String? { + if let dictionary = object as? [String: Any] { + for key in ["access_token", "accessToken"] { + if let value = dictionary[key] as? String, + self.looksLikeToken(value) + { + return value + } + } + for value in dictionary.values { + if let found = self.findAccessToken(in: value) { + return found + } + } + } + + if let array = object as? [Any] { + for value in array { + if let found = self.findAccessToken(in: value) { + return found + } + } + } + + return nil + } + + private static func looksLikeToken(_ raw: String) -> Bool { + let value = raw.trimmingCharacters(in: .whitespacesAndNewlines) + return value.count > 20 && (value.hasPrefix("eyJ") || value.contains(".")) + } + + private static func isAuth1StorageKey(_ key: String) -> Bool { + key.hasSuffix("auth1_session") + } + + private static func isAuth0StorageKey(_ key: String) -> Bool { + key.contains("auth0spajs@@::") + } + + private static func isExternalOrgStorageKey(_ key: String) -> Bool { + key.contains(self.externalOrgPrefix) + } + + private static func isUsefulStorageKey(_ key: String) -> Bool { + self.isAuth1StorageKey(key) || + self.isAuth0StorageKey(key) || + self.isExternalOrgStorageKey(key) || + key.contains("post-auth-v") || + key.contains("member-info-v") || + key.contains("feature-flags-cache:org-") || + key.contains("feature-flags-cache:org_") + } + + private static func inferredOrganizationInfo( + from storage: [String: String], + override: String?) -> (organization: String?, internalOrganizationID: String?)? + { + let overrideSlug = override.flatMap(self.slug(fromNormalizedOrganization:)) + let overrideOrgID = override.flatMap(self.orgID(fromNormalizedOrganization:)) + var fallbackSlug: String? + var fallbackInternalOrgID: String? + + for (key, value) in storage { + let object = self.jsonObject(from: value) + let internalOrgID = self.cleanedOrgID(self.firstString( + in: object, + matching: ["internalOrgId", "internal_org_id", "org_id", "orgId"])) + ?? self.internalOrgIDFromStorageKey(key) + let slug = self.cleanedSlug( + self.slugFromPostAuthKey(key) ?? + self.firstString(in: object, matching: ["orgName", "org_name", "externalOrgId", "external_org_id"])) + + if let overrideOrgID, internalOrgID == overrideOrgID { + return (override, internalOrgID) + } + if let overrideSlug, slug == overrideSlug { + return (override, internalOrgID) + } + + if fallbackSlug == nil, let slug { + fallbackSlug = slug + } + if fallbackInternalOrgID == nil, let internalOrgID { + fallbackInternalOrgID = internalOrgID + } + } + + if let override, fallbackInternalOrgID != nil { + return (override, fallbackInternalOrgID) + } + + if let fallbackSlug { + return ("org/\(fallbackSlug)", fallbackInternalOrgID) + } + if let fallbackInternalOrgID { + return ("organizations/\(fallbackInternalOrgID)", fallbackInternalOrgID) + } + + return nil + } + + private static func externalOrgSlug(from key: String) -> String { + guard let range = key.range(of: self.externalOrgPrefix) else { return key } + return String(key[range.upperBound...]) + } + + private static func cleanedOrgID(_ raw: String) -> String? { + let value = self.decodedStorageValue(raw) + guard DevinUsageFetcher.isInternalOrganizationID(value) else { return nil } + return value + } + + private static func cleanedOrgID(_ raw: String?) -> String? { + guard let raw else { return nil } + return self.cleanedOrgID(raw) + } + + private static func cleanedSlug(_ raw: String?) -> String? { + guard let raw else { return nil } + let value = self.decodedStorageValue(raw) + .trimmingCharacters(in: CharacterSet(charactersIn: "/")) + .trimmingCharacters(in: .whitespacesAndNewlines) + guard !value.isEmpty, value != "null", !DevinUsageFetcher.isInternalOrganizationID(value) else { + return nil + } + if value.hasPrefix("org/") { + return String(value.dropFirst(4)) + } + return value + } + + private static func slugFromPostAuthKey(_ key: String) -> String? { + guard let range = key.range(of: "-org_name-") else { return nil } + return String(key[range.upperBound...]) + } + + private static func internalOrgIDFromStorageKey(_ key: String) -> String? { + guard let range = key.range(of: #"org[-_][A-Za-z0-9]{8,}"#, options: .regularExpression) else { + return nil + } + return self.cleanedOrgID(String(key[range])) + } + + private static func firstString(in object: Any?, matching keys: Set) -> String? { + if let dictionary = object as? [String: Any] { + for (key, value) in dictionary { + if keys.contains(key), let string = value as? String, !string.isEmpty { + return string + } + if let found = self.firstString(in: value, matching: keys) { + return found + } + } + } + + if let array = object as? [Any] { + for value in array { + if let found = self.firstString(in: value, matching: keys) { + return found + } + } + } + + return nil + } + + private static func slug(fromNormalizedOrganization organization: String) -> String? { + guard organization.hasPrefix("org/") else { return nil } + return String(organization.dropFirst(4)) + } + + private static func orgID(fromNormalizedOrganization organization: String) -> String? { + guard organization.hasPrefix("organizations/") else { return nil } + return String(organization.dropFirst("organizations/".count)) + } +} +#endif diff --git a/Sources/CodexBarCore/Providers/Devin/DevinUsageFetcher.swift b/Sources/CodexBarCore/Providers/Devin/DevinUsageFetcher.swift new file mode 100644 index 0000000..5ae7657 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Devin/DevinUsageFetcher.swift @@ -0,0 +1,271 @@ +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +public struct DevinUsageFetcher: Sendable { + private static let log = CodexBarLog.logger(LogCategories.devin) + private static let baseURL = URL(string: "https://app.devin.ai")! + private static let defaultUserAgent = + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) " + + "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36" + + public struct RequestAuth: Sendable, Equatable { + public let bearerToken: String + public let organization: String? + public let internalOrganizationID: String? + public let sourceLabel: String + + public init( + bearerToken: String, + organization: String?, + internalOrganizationID: String?, + sourceLabel: String) + { + self.bearerToken = bearerToken + self.organization = organization + self.internalOrganizationID = internalOrganizationID + self.sourceLabel = sourceLabel + } + } + + public let browserDetection: BrowserDetection + + public init(browserDetection: BrowserDetection) { + self.browserDetection = browserDetection + } + + public func fetch( + bearerTokenOverride: String? = nil, + organizationOverride: String? = nil, + timeout: TimeInterval = 15, + logger: ((String) -> Void)? = nil, + now: Date = Date(), + transport: any ProviderHTTPTransport = ProviderHTTPClient.shared) async throws -> DevinUsageSnapshot + { + let auths = try self.resolveAuths( + bearerTokenOverride: bearerTokenOverride, + organizationOverride: organizationOverride, + logger: logger) + var lastError: Error? + for auth in auths { + do { + return try await Self.fetchQuotaUsage( + auth: auth, + organizationOverride: organizationOverride, + timeout: timeout, + logger: logger, + now: now, + transport: transport) + } catch { + lastError = error + logger?("[devin] Session from \(auth.sourceLabel) failed: \(error.localizedDescription)") + if auth.sourceLabel == "manual" || !Self.shouldTryNextSession(after: error) { + throw error + } + } + } + throw lastError ?? DevinUsageError.noSession + } + + public static func fetchQuotaUsage( + auth: RequestAuth, + organizationOverride: String? = nil, + timeout: TimeInterval = 15, + logger: ((String) -> Void)? = nil, + now: Date = Date(), + transport: any ProviderHTTPTransport = ProviderHTTPClient.shared) async throws -> DevinUsageSnapshot + { + let organization = self.normalizedOrganization(organizationOverride) ?? + self.normalizedOrganization(auth.organization) + guard let organization else { + throw DevinUsageError.missingOrganization + } + + var lastError: Error? + for path in self.candidatePaths( + organization: organization, + internalOrganizationID: auth.internalOrganizationID) + { + let data: Data + do { + data = try await self.fetch( + path: path, + auth: auth, + timeout: timeout, + transport: transport) + } catch { + lastError = error + logger?("[devin] /api/\(path) failed: \(error.localizedDescription)") + if case DevinUsageError.invalidCredentials = error { + throw error + } + continue + } + logger?("[devin] Fetched quota usage from /api/\(path)") + return try DevinUsageParser.parse(data, organization: organization, now: now) + } + + throw lastError ?? DevinUsageError.apiError("No Devin quota endpoint succeeded.") + } + + public static func manualAuth(from raw: String?, organization: String? = nil) -> RequestAuth? { + guard var token = raw?.trimmingCharacters(in: .whitespacesAndNewlines), !token.isEmpty else { + return nil + } + if token.lowercased().hasPrefix("authorization:") { + token = token.dropHeaderName().trimmingCharacters(in: .whitespacesAndNewlines) + } + if token.lowercased().hasPrefix("bearer ") { + token = String(token.dropFirst(7)).trimmingCharacters(in: .whitespacesAndNewlines) + } + guard !token.isEmpty else { return nil } + return RequestAuth( + bearerToken: token, + organization: self.normalizedOrganization(organization), + internalOrganizationID: self.internalOrganizationID(from: organization), + sourceLabel: "manual") + } + + private func resolveAuths( + bearerTokenOverride: String?, + organizationOverride: String?, + logger: ((String) -> Void)?) throws -> [RequestAuth] + { + if let manual = Self.manualAuth(from: bearerTokenOverride, organization: organizationOverride) { + logger?("[devin] Using manual Bearer token") + return [manual] + } + + #if os(macOS) + let normalizedOrganizationOverride = Self.normalizedOrganization(organizationOverride) + let sessions = DevinSessionImporter.importSessions( + browserDetection: self.browserDetection, + organizationOverride: normalizedOrganizationOverride, + logger: logger) + guard !sessions.isEmpty else { + throw DevinUsageError.noSession + } + logger?("[devin] Found \(sessions.count) browser session(s)") + return sessions.map { session in + RequestAuth( + bearerToken: session.accessToken, + organization: normalizedOrganizationOverride ?? Self.normalizedOrganization(session.organization), + internalOrganizationID: session.internalOrganizationID, + sourceLabel: session.sourceLabel) + } + #else + throw DevinUsageError.noSession + #endif + } + + static func shouldTryNextSession(after error: Error) -> Bool { + switch error { + case DevinUsageError.invalidCredentials, DevinUsageError.apiError, DevinUsageError.missingOrganization: + true + default: + false + } + } + + private static func fetch( + path: String, + auth: RequestAuth, + timeout: TimeInterval, + transport: any ProviderHTTPTransport) async throws -> Data + { + let url = self.baseURL.appending(path: "api/\(path)") + var request = URLRequest(url: url) + request.httpMethod = "GET" + request.timeoutInterval = timeout + request.setValue("application/json", forHTTPHeaderField: "Accept") + request.setValue("en-US,en;q=0.9", forHTTPHeaderField: "Accept-Language") + request.setValue(self.defaultUserAgent, forHTTPHeaderField: "User-Agent") + request.setValue("Bearer \(auth.bearerToken)", forHTTPHeaderField: "Authorization") + if let internalOrganizationID = auth.internalOrganizationID { + request.setValue(internalOrganizationID, forHTTPHeaderField: "x-cog-org-id") + } + let response = try await transport.response(for: request) + guard response.statusCode == 200 else { + let body = String(data: response.data.prefix(200), encoding: .utf8) ?? "" + if response.statusCode == 401 || response.statusCode == 403 { + throw DevinUsageError.invalidCredentials + } + Self.log.error("Devin API returned \(response.statusCode): \(body)") + throw DevinUsageError.apiError("HTTP \(response.statusCode)") + } + return response.data + } + + private static func candidatePaths(organization: String, internalOrganizationID: String?) -> [String] { + var paths: [String] = [] + let normalized = self.normalizedOrganization(organization) ?? organization + if let internalOrganizationID { + paths.append("\(internalOrganizationID)/billing/quota/usage") + } + paths.append("\(normalized)/billing/quota/usage") + if normalized.hasPrefix("org/") { + let slug = String(normalized.dropFirst(4)) + paths.append("\(slug)/billing/quota/usage") + } + if !normalized.hasPrefix("org/"), !normalized.hasPrefix("organizations/") { + paths.append("org/\(normalized)/billing/quota/usage") + } + if let internalOrganizationID { + paths.append("organizations/\(internalOrganizationID)/billing/quota/usage") + } + return paths.removingDuplicates() + } + + public static func normalizedOrganization(_ raw: String?) -> String? { + guard var value = raw?.trimmingCharacters(in: .whitespacesAndNewlines), !value.isEmpty else { + return nil + } + if let url = URL(string: value), + let host = url.host?.lowercased(), + host == "devin.ai" || host.hasSuffix(".devin.ai") + { + let components = url.path.split(separator: "/").map(String.init) + if components.count >= 2, components[0] == "org" { + value = "org/\(components[1])" + } else if components.count >= 2, components[0] == "organizations" { + value = "organizations/\(components[1])" + } + } + value = value.trimmingCharacters(in: CharacterSet(charactersIn: "/")) + if value.hasPrefix("org/") || value.hasPrefix("organizations/") { + return value + } + if self.isInternalOrganizationID(value) { + return "organizations/\(value)" + } + return "org/\(value)" + } + + private static func internalOrganizationID(from raw: String?) -> String? { + guard let normalized = self.normalizedOrganization(raw), + normalized.hasPrefix("organizations/") + else { + return nil + } + return String(normalized.dropFirst("organizations/".count)) + } + + static func isInternalOrganizationID(_ value: String) -> Bool { + value.hasPrefix("org-") || value.hasPrefix("org_") + } +} + +extension String { + fileprivate func dropHeaderName() -> String { + guard let index = self.firstIndex(of: ":") else { return self } + return String(self[self.index(after: index)...]) + } +} + +extension [String] { + fileprivate func removingDuplicates() -> [String] { + var seen = Set() + return self.filter { seen.insert($0).inserted } + } +} diff --git a/Sources/CodexBarCore/Providers/Devin/DevinUsageSnapshot.swift b/Sources/CodexBarCore/Providers/Devin/DevinUsageSnapshot.swift new file mode 100644 index 0000000..8b7b2b7 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Devin/DevinUsageSnapshot.swift @@ -0,0 +1,345 @@ +import CoreFoundation +import Foundation + +public enum DevinUsageError: LocalizedError, Sendable { + case noSession + case missingOrganization + case invalidCredentials + case apiError(String) + case parseFailed(String) + + public var errorDescription: String? { + switch self { + case .noSession: + "No Devin browser session found. Please log in to app.devin.ai or paste a Bearer token." + case .missingOrganization: + "No Devin organization was found. Open an app.devin.ai/org/... page " + + "or set the organization in Devin settings." + case .invalidCredentials: + "Devin session token is invalid or expired." + case let .apiError(message): + "Devin API error: \(message)" + case let .parseFailed(message): + "Could not parse Devin usage: \(message)" + } + } +} + +public struct DevinQuotaWindow: Sendable, Equatable { + public let usedPercent: Double + public let resetsAt: Date? + + public init(usedPercent: Double, resetsAt: Date? = nil) { + self.usedPercent = min(100, max(0, usedPercent)) + self.resetsAt = resetsAt + } +} + +public struct DevinUsageSnapshot: Sendable, Equatable { + public let daily: DevinQuotaWindow? + public let weekly: DevinQuotaWindow? + public let planName: String? + public let organization: String? + public let updatedAt: Date + public let overageBalance: Double? + + public init( + daily: DevinQuotaWindow?, + weekly: DevinQuotaWindow?, + planName: String?, + organization: String?, + updatedAt: Date, + overageBalance: Double? = nil) + { + self.daily = daily + self.weekly = weekly + self.planName = planName + self.organization = organization + self.updatedAt = updatedAt + self.overageBalance = overageBalance + } + + public func toUsageSnapshot() -> UsageSnapshot { + let primary = self.daily.map { + RateWindow( + usedPercent: $0.usedPercent, + windowMinutes: 24 * 60, + resetsAt: $0.resetsAt, + resetDescription: "Daily") + } + let secondary = self.weekly.map { + RateWindow( + usedPercent: $0.usedPercent, + windowMinutes: 7 * 24 * 60, + resetsAt: $0.resetsAt, + resetDescription: "Weekly") + } + let identity = ProviderIdentitySnapshot( + providerID: .devin, + accountEmail: nil, + accountOrganization: self.organization, + loginMethod: self.planName) + let providerCost: ProviderCostSnapshot? = self.overageBalance.map { + ProviderCostSnapshot( + used: $0, + limit: 0, + currencyCode: "USD", + period: "Extra usage balance", + updatedAt: self.updatedAt) + } + return UsageSnapshot( + primary: primary, + secondary: secondary, + providerCost: providerCost, + updatedAt: self.updatedAt, + identity: identity) + } +} + +public enum DevinUsageParser { + public static func parse(_ data: Data, organization: String?, now: Date = Date()) throws -> DevinUsageSnapshot { + let object = try JSONSerialization.jsonObject(with: data) + return try self.parse(object, organization: organization, now: now) + } + + public static func parse(_ object: Any, organization: String?, now: Date = Date()) throws -> DevinUsageSnapshot { + let current = (object as? [String: Any]).map(self.currentQuotaWindows) + let daily = current?.daily ?? self.findWindow(in: object, matching: self.isDailyKey) + let weekly = current?.weekly ?? self.findWindow(in: object, matching: self.isWeeklyKey) + guard daily != nil || weekly != nil else { + throw DevinUsageError.parseFailed("Missing Devin quota windows.") + } + + return DevinUsageSnapshot( + daily: daily, + weekly: weekly, + planName: self.findPlanName(in: object), + organization: self.displayOrganization(from: organization), + updatedAt: now, + overageBalance: self.findOverageBalance(in: object)) + } + + private static func findOverageBalance(in object: Any) -> Double? { + guard let dictionary = object as? [String: Any] else { return nil } + if let value = self.nonnegativeFiniteDouble(dictionary["overage_balance"]) { return value } + if let cents = self.nonnegativeFiniteDouble(dictionary["overage_balance_cents"]) { return cents / 100.0 } + return nil + } + + private static func nonnegativeFiniteDouble(_ value: Any?) -> Double? { + guard let value = self.double(value), value.isFinite, value >= 0 else { return nil } + return value + } + + private static func currentQuotaWindows(_ dictionary: [String: Any]) + -> (daily: DevinQuotaWindow?, weekly: DevinQuotaWindow?) + { + let daily = self.currentQuotaWindow( + percent: dictionary["daily_percentage"], + resetsAt: dictionary["daily_reset_at"]) + let weekly = self.currentQuotaWindow( + percent: dictionary["weekly_percentage"], + resetsAt: dictionary["weekly_reset_at"]) + return (daily, weekly) + } + + private static func currentQuotaWindow(percent: Any?, resetsAt: Any?) -> DevinQuotaWindow? { + guard let usedPercent = self.double(percent) else { return nil } + return DevinQuotaWindow( + usedPercent: usedPercent < 1 ? usedPercent * 100 : usedPercent, + resetsAt: self.date(from: resetsAt)) + } + + private static func findWindow(in object: Any, matching keyMatches: (String) -> Bool) -> DevinQuotaWindow? { + if let dictionary = object as? [String: Any] { + for (key, value) in dictionary where keyMatches(key) { + if let window = self.window(from: value) { + return window + } + } + for value in dictionary.values { + if let found = self.findWindow(in: value, matching: keyMatches) { + return found + } + } + } + + if let array = object as? [Any] { + for value in array { + if let found = self.findWindow(in: value, matching: keyMatches) { + return found + } + } + } + + return nil + } + + private static func window(from object: Any) -> DevinQuotaWindow? { + guard let dictionary = object as? [String: Any] else { + guard let percent = self.percent(from: object) else { return nil } + return DevinQuotaWindow(usedPercent: percent, resetsAt: nil) + } + + if let percent = self.percent(from: dictionary) { + return DevinQuotaWindow( + usedPercent: percent, + resetsAt: self.findResetDate(in: dictionary)) + } + + if let nested = dictionary.values.lazy.compactMap({ self.window(from: $0) }).first { + return nested + } + + return nil + } + + private static func percent(from object: Any) -> Double? { + if let number = self.double(object) { + return number <= 1 ? number * 100 : number + } + guard let dictionary = object as? [String: Any] else { return nil } + + let directKeys = [ + "used_percent", + "usedPercent", + "usage_percent", + "usagePercent", + "percent_used", + "percentUsed", + "percent", + ] + for key in directKeys { + if let value = self.double(dictionary[key]) { + return value <= 1 ? value * 100 : value + } + } + + let remainingKeys = ["remaining_percent", "remainingPercent", "percent_remaining", "percentRemaining"] + for key in remainingKeys { + if let value = self.double(dictionary[key]) { + let percent = value <= 1 ? value * 100 : value + return 100 - percent + } + } + + let used = self.firstDouble(in: dictionary, keys: ["used", "usage", "used_count", "usedCount", "consumed"]) + let limit = self.firstDouble(in: dictionary, keys: ["limit", "quota", "total", "max", "available"]) + if let used, let limit, limit > 0 { + return used / limit * 100 + } + + let remaining = self.firstDouble(in: dictionary, keys: ["remaining", "left", "available"]) + if let remaining, let limit, limit > 0 { + return (limit - remaining) / limit * 100 + } + + return nil + } + + private static func findPlanName(in object: Any) -> String? { + if let dictionary = object as? [String: Any] { + for key in ["plan_name", "planName", "plan", "tier", "subscription_tier", "subscriptionTier"] { + if let value = dictionary[key] as? String, + let cleaned = self.cleanDisplay(value) + { + return cleaned + } + } + for value in dictionary.values { + if let found = self.findPlanName(in: value) { + return found + } + } + } + + if let array = object as? [Any] { + for value in array { + if let found = self.findPlanName(in: value) { + return found + } + } + } + + return nil + } + + private static func findResetDate(in dictionary: [String: Any]) -> Date? { + for (key, value) in dictionary where key.localizedCaseInsensitiveContains("reset") { + if let date = self.date(from: value) { + return date + } + } + return nil + } + + private static func date(from value: Any?) -> Date? { + if let raw = value as? String { + if let date = ISO8601DateFormatter().date(from: raw) { + return date + } + if let number = Double(raw) { + return self.date(from: number) + } + } + if let number = self.double(value) { + return self.date(from: number) + } + return nil + } + + private static func date(from number: Double) -> Date? { + guard number > 0 else { return nil } + let seconds = number > 10_000_000_000 ? number / 1000 : number + return Date(timeIntervalSince1970: seconds) + } + + private static func firstDouble(in dictionary: [String: Any], keys: [String]) -> Double? { + for key in keys { + if let value = self.double(dictionary[key]) { + return value + } + } + return nil + } + + private static func double(_ value: Any?) -> Double? { + switch value { + case let number as NSNumber: + CFGetTypeID(number) == CFBooleanGetTypeID() ? nil : number.doubleValue + case let string as String: + Double(string.trimmingCharacters(in: .whitespacesAndNewlines)) + default: + nil + } + } + + private static func isDailyKey(_ raw: String) -> Bool { + let key = raw.lowercased() + return !key.contains("hide") && (key.contains("daily") || key.contains("day")) + } + + private static func isWeeklyKey(_ raw: String) -> Bool { + let key = raw.lowercased() + return !key.contains("hide") && (key.contains("weekly") || key.contains("week")) + } + + private static func displayOrganization(from raw: String?) -> String? { + guard let raw = raw?.trimmingCharacters(in: .whitespacesAndNewlines), !raw.isEmpty else { return nil } + if raw.hasPrefix("org/") { + return String(raw.dropFirst(4)) + } + if raw.hasPrefix("organizations/") { + return String(raw.dropFirst("organizations/".count)) + } + return raw + } + + private static func cleanDisplay(_ raw: String) -> String? { + let cleaned = raw.trimmingCharacters(in: .whitespacesAndNewlines) + guard !cleaned.isEmpty else { return nil } + return cleaned.split(separator: "_").flatMap { $0.split(separator: "-") }.map { part in + part.prefix(1).uppercased() + String(part.dropFirst()) + }.joined(separator: " ") + } +} diff --git a/Sources/CodexBarCore/Providers/Doubao/DoubaoProviderDescriptor.swift b/Sources/CodexBarCore/Providers/Doubao/DoubaoProviderDescriptor.swift new file mode 100644 index 0000000..386c039 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Doubao/DoubaoProviderDescriptor.swift @@ -0,0 +1,110 @@ +import Foundation + +public enum DoubaoProviderDescriptor { + public static let descriptor: ProviderDescriptor = Self.makeDescriptor() + + public static func primaryLabel(window: RateWindow?) -> String? { + guard window?.windowMinutes == nil, + window?.resetDescription?.localizedCaseInsensitiveContains("request") == true + else { + return nil + } + return "Requests" + } + + static func makeDescriptor() -> ProviderDescriptor { + ProviderDescriptor( + id: .doubao, + metadata: ProviderMetadata( + id: .doubao, + displayName: "Doubao", + sessionLabel: "5-hour", + weeklyLabel: "Weekly", + opusLabel: "Monthly", + supportsOpus: true, + supportsCredits: false, + creditsHint: "", + toggleTitle: "Show Doubao usage", + cliName: "doubao", + defaultEnabled: false, + isPrimaryProvider: false, + usesAccountFallback: false, + browserCookieOrder: nil, + dashboardURL: "https://console.volcengine.com/ark/region:ark+cn-beijing/openManagement?LLM=%7B%7D&advancedActiveKey=subscribe", + statusPageURL: nil), + branding: ProviderBranding( + iconStyle: .doubao, + iconResourceName: "ProviderIcon-doubao", + color: ProviderColor(red: 51 / 255, green: 112 / 255, blue: 255 / 255)), + tokenCost: ProviderTokenCostConfig( + supportsTokenCost: false, + noDataMessage: { "Doubao cost summary is not available." }), + fetchPlan: ProviderFetchPlan( + sourceModes: [.auto, .api], + pipeline: ProviderFetchPipeline(resolveStrategies: { _ in + [DoubaoAPIFetchStrategy()] + })), + cli: ProviderCLIConfig( + name: "doubao", + aliases: ["volcengine", "ark", "bytedance"], + versionDetector: nil)) + } +} + +struct DoubaoAPIFetchStrategy: ProviderFetchStrategy { + let id: String = "doubao.api" + let kind: ProviderFetchKind = .apiToken + private let codingPlanUsageLoader: @Sendable (DoubaoCodingPlanCredentials) async throws -> DoubaoUsageSnapshot + private let arkUsageLoader: @Sendable (String) async throws -> DoubaoUsageSnapshot + + init( + codingPlanUsageLoader: @escaping @Sendable (DoubaoCodingPlanCredentials) async throws + -> DoubaoUsageSnapshot = { credentials in + try await DoubaoUsageFetcher.fetchCodingPlanUsage(credentials: credentials) + }, + arkUsageLoader: @escaping @Sendable (String) async throws -> DoubaoUsageSnapshot = { apiKey in + try await DoubaoUsageFetcher.fetchUsage(apiKey: apiKey) + }) + { + self.codingPlanUsageLoader = codingPlanUsageLoader + self.arkUsageLoader = arkUsageLoader + } + + func isAvailable(_ context: ProviderFetchContext) async -> Bool { + DoubaoSettingsReader.codingPlanCredentials(environment: context.env) != nil || + ProviderTokenResolver.doubaoToken(environment: context.env) != nil + } + + func fetch(_ context: ProviderFetchContext) async throws -> ProviderFetchResult { + let apiKey = ProviderTokenResolver.doubaoToken(environment: context.env) + if let credentials = DoubaoSettingsReader.codingPlanCredentials(environment: context.env) { + do { + let usage = try await self.codingPlanUsageLoader(credentials) + return self.makeResult(usage: usage.toUsageSnapshot(), sourceLabel: "api") + } catch { + if Self.isCancellation(error) { + throw error + } + guard let apiKey else { + throw error + } + let usage = try await self.arkUsageLoader(apiKey) + return self.makeResult(usage: usage.toUsageSnapshot(), sourceLabel: "api") + } + } + + guard let apiKey else { + throw DoubaoUsageError.missingCredentials + } + let usage = try await self.arkUsageLoader(apiKey) + return self.makeResult(usage: usage.toUsageSnapshot(), sourceLabel: "api") + } + + func shouldFallback(on _: Error, context _: ProviderFetchContext) -> Bool { + false + } + + private static func isCancellation(_ error: Error) -> Bool { + error is CancellationError || (error as? URLError)?.code == .cancelled || Task.isCancelled + } +} diff --git a/Sources/CodexBarCore/Providers/Doubao/DoubaoSettingsReader.swift b/Sources/CodexBarCore/Providers/Doubao/DoubaoSettingsReader.swift new file mode 100644 index 0000000..479d281 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Doubao/DoubaoSettingsReader.swift @@ -0,0 +1,86 @@ +import Foundation + +public struct DoubaoSettingsReader: Sendable { + public static let apiKeyEnvironmentKeys = [ + "ARK_API_KEY", + "VOLCENGINE_API_KEY", + "DOUBAO_API_KEY", + ] + public static let accessKeyIDEnvironmentKeys = [ + "VOLCENGINE_ACCESS_KEY_ID", + "VOLCENGINE_ACCESS_KEY", + "VOLC_ACCESSKEY", + "DOUBAO_ACCESS_KEY_ID", + ] + public static let secretAccessKeyEnvironmentKeys = [ + "VOLCENGINE_SECRET_ACCESS_KEY", + "VOLCENGINE_SECRET_KEY", + "VOLCENGINE_ACCESS_KEY_SECRET", + "VOLC_SECRETKEY", + "DOUBAO_SECRET_ACCESS_KEY", + ] + public static let regionEnvironmentKeys = [ + "VOLCENGINE_REGION", + "VOLCENGINE_REGION_ID", + "VOLC_REGION", + "DOUBAO_REGION", + ] + public static let defaultRegion = "cn-beijing" + + public static func apiKey( + environment: [String: String] = ProcessInfo.processInfo.environment) -> String? + { + self.firstValue(in: environment, keys: self.apiKeyEnvironmentKeys) + } + + public static func accessKeyID( + environment: [String: String] = ProcessInfo.processInfo.environment) -> String? + { + self.firstValue(in: environment, keys: self.accessKeyIDEnvironmentKeys) + } + + public static func secretAccessKey( + environment: [String: String] = ProcessInfo.processInfo.environment) -> String? + { + self.firstValue(in: environment, keys: self.secretAccessKeyEnvironmentKeys) + } + + public static func region(environment: [String: String] = ProcessInfo.processInfo.environment) -> String { + self.firstValue(in: environment, keys: self.regionEnvironmentKeys) ?? self.defaultRegion + } + + public static func codingPlanCredentials( + environment: [String: String] = ProcessInfo.processInfo.environment) -> DoubaoCodingPlanCredentials? + { + guard let accessKeyID = self.accessKeyID(environment: environment), + let secretAccessKey = self.secretAccessKey(environment: environment) + else { + return nil + } + return DoubaoCodingPlanCredentials( + accessKeyID: accessKeyID, + secretAccessKey: secretAccessKey, + region: self.region(environment: environment)) + } + + private static func firstValue(in environment: [String: String], keys: [String]) -> String? { + for key in keys { + guard let cleaned = self.cleaned(environment[key]) else { continue } + return cleaned + } + return nil + } + + static func cleaned(_ raw: String?) -> String? { + guard var value = raw?.trimmingCharacters(in: .whitespacesAndNewlines), !value.isEmpty else { + return nil + } + if (value.hasPrefix("\"") && value.hasSuffix("\"")) || + (value.hasPrefix("'") && value.hasSuffix("'")) + { + value = String(value.dropFirst().dropLast()) + } + value = value.trimmingCharacters(in: .whitespacesAndNewlines) + return value.isEmpty ? nil : value + } +} diff --git a/Sources/CodexBarCore/Providers/Doubao/DoubaoUsageFetcher.swift b/Sources/CodexBarCore/Providers/Doubao/DoubaoUsageFetcher.swift new file mode 100644 index 0000000..cc5b7a0 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Doubao/DoubaoUsageFetcher.swift @@ -0,0 +1,548 @@ +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +public struct DoubaoUsageSnapshot: Sendable { + public let remainingRequests: Int + public let limitRequests: Int + public let resetTime: Date? + public let updatedAt: Date + public let apiKeyValid: Bool + public let totalTokens: Int? + public let requestLimitsReliable: Bool + public let codingPlanUsage: DoubaoCodingPlanUsage? + public init( + remainingRequests: Int, + limitRequests: Int, + resetTime: Date?, + updatedAt: Date, + apiKeyValid: Bool = false, + totalTokens: Int? = nil, + requestLimitsReliable: Bool = true, + codingPlanUsage: DoubaoCodingPlanUsage? = nil) + { + self.remainingRequests = remainingRequests + self.limitRequests = limitRequests + self.resetTime = resetTime + self.updatedAt = updatedAt + self.apiKeyValid = apiKeyValid + self.totalTokens = totalTokens + self.requestLimitsReliable = requestLimitsReliable + self.codingPlanUsage = codingPlanUsage + } + + public func toUsageSnapshot() -> UsageSnapshot { + if let codingPlanUsage { + return codingPlanUsage.toUsageSnapshot(updatedAt: self.updatedAt) + } + + let primary: RateWindow? + if self.limitRequests > 0, self.requestLimitsReliable { + let used = max(0, self.limitRequests - self.remainingRequests) + primary = RateWindow( + usedPercent: min(100, max(0, Double(used) / Double(self.limitRequests) * 100)), + windowMinutes: nil, + resetsAt: self.resetTime, + resetDescription: "\(used)/\(self.limitRequests) requests") + } else if self.apiKeyValid { + // Ark can return successful requests without a trustworthy request-limit window. + // Omitting the window prevents the UI from presenting unknown usage as 100% left. + primary = nil + } else { + primary = RateWindow( + usedPercent: 0, + windowMinutes: nil, + resetsAt: self.resetTime, + resetDescription: "No usage data") + } + + let identity = ProviderIdentitySnapshot( + providerID: .doubao, + accountEmail: nil, + accountOrganization: nil, + loginMethod: nil) + + return UsageSnapshot( + primary: primary, + secondary: nil, + tertiary: nil, + providerCost: nil, + updatedAt: self.updatedAt, + identity: identity) + } +} + +public struct DoubaoCodingPlanUsage: Sendable, Equatable { + public struct Quota: Sendable, Equatable { + public let level: String + public let percent: Double + public let resetTime: Date? + + public init(level: String, percent: Double, resetTime: Date?) { + self.level = level + self.percent = percent + self.resetTime = resetTime + } + } + + public let status: String? + public let updateTime: Date? + public let quotas: [Quota] + + public init(status: String?, updateTime: Date?, quotas: [Quota]) { + self.status = status + self.updateTime = updateTime + self.quotas = quotas + } + + public func toUsageSnapshot(updatedAt: Date) -> UsageSnapshot { + let primary = self.rateWindow(levels: ["session", "5-hour", "five_hour"], minutes: 5 * 60) + let secondary = self.rateWindow(levels: ["weekly", "week"], minutes: 7 * 24 * 60) + let tertiary = self.rateWindow(levels: ["monthly", "month"], minutes: 30 * 24 * 60) + let identity = ProviderIdentitySnapshot( + providerID: .doubao, + accountEmail: nil, + accountOrganization: nil, + loginMethod: self.status) + + return UsageSnapshot( + primary: primary, + secondary: secondary, + tertiary: tertiary, + providerCost: nil, + updatedAt: self.updateTime ?? updatedAt, + identity: identity) + } + + private func rateWindow(levels: Set, minutes: Int) -> RateWindow? { + guard let quota = self.quotas.first(where: { levels.contains($0.level.lowercased()) }) else { + return nil + } + let percent = min(100, max(0, quota.percent)) + return RateWindow( + usedPercent: percent, + windowMinutes: minutes, + resetsAt: quota.resetTime, + resetDescription: nil) + } +} + +public enum DoubaoUsageError: LocalizedError, Sendable { + case missingCredentials + case networkError(String) + case apiError(Int, String) + case parseFailed(String) + + public var errorDescription: String? { + switch self { + case .missingCredentials: + "Missing Doubao API key (ARK_API_KEY)." + case let .networkError(message): + "Doubao network error: \(message)" + case let .apiError(code, message): + "Doubao API error (\(code)): \(message)" + case let .parseFailed(message): + "Failed to parse Doubao response: \(message)" + } + } +} + +public struct DoubaoUsageFetcher: Sendable { + private static let log = CodexBarLog.logger(LogCategories.doubaoUsage) + private static let apiURL = URL(string: "https://ark.cn-beijing.volces.com/api/coding/v3/chat/completions")! + private static let codingPlanAPIURL = URL( + string: "https://open.volcengineapi.com/?Action=GetCodingPlanUsage&Version=2024-01-01")! + + /// Models to probe, ordered by likelihood. We try multiple models because + /// different key types may not have access to every model. + private static let probeModels = [ + "doubao-seed-2.0-code", + "doubao-1.5-pro-32k", + "doubao-lite-32k", + ] + + private struct ProbeResult { + let snapshot: DoubaoUsageSnapshot + let statusCode: Int + + var hasAmbiguousZeroRemaining: Bool { + self.statusCode == 200 + && self.snapshot.requestLimitsReliable + && self.snapshot.limitRequests > 0 + && self.snapshot.remainingRequests == 0 + } + } + + public static func fetchUsage( + apiKey: String, + session transport: any ProviderHTTPTransport = ProviderHTTPClient.shared) async throws -> DoubaoUsageSnapshot + { + guard !apiKey.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else { + throw DoubaoUsageError.missingCredentials + } + + var lastError: Error? + for model in self.probeModels { + do { + let result = try await self.probe(apiKey: apiKey, model: model, transport: transport) + guard result.hasAmbiguousZeroRemaining else { + return result.snapshot + } + + return try await self.confirmAmbiguousZeroRemaining( + initial: result, + apiKey: apiKey, + model: model, + transport: transport) + } catch let error as DoubaoUsageError { + if case let .apiError(code, _) = error, code == 404 || code == 403 { + Self.log.debug("Doubao probe model \(model) unavailable (\(code)), trying next") + lastError = error + continue + } + throw error + } + } + throw lastError ?? DoubaoUsageError.apiError(0, "All probe models failed") + } + + public static func fetchCodingPlanUsage( + credentials: DoubaoCodingPlanCredentials, + session transport: any ProviderHTTPTransport = ProviderHTTPClient.shared, + date: Date = Date()) async throws -> DoubaoUsageSnapshot + { + guard !credentials.accessKeyID.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty, + !credentials.secretAccessKey.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty + else { + throw DoubaoUsageError.missingCredentials + } + + let body = Data() + var request = URLRequest(url: self.codingPlanAPIURL) + request.httpMethod = "POST" + request.timeoutInterval = 15 + request.httpBody = body + request.setValue("application/json", forHTTPHeaderField: "Accept") + DoubaoVolcengineSigner.sign( + request: &request, + body: body, + credentials: credentials, + date: date) + + let response = try await transport.response(for: request) + guard response.statusCode == 200 else { + let summary = Self.apiErrorSummary(statusCode: response.statusCode, data: response.data) + Self.log.error("Doubao coding plan API returned \(response.statusCode): \(summary)") + throw DoubaoUsageError.apiError(response.statusCode, summary) + } + + let codingPlanUsage = try self.decodeCodingPlanUsage(from: response.data) + return DoubaoUsageSnapshot( + remainingRequests: 0, + limitRequests: 0, + resetTime: nil, + updatedAt: codingPlanUsage.updateTime ?? date, + apiKeyValid: true, + codingPlanUsage: codingPlanUsage) + } + + static func decodeCodingPlanUsage(from data: Data) throws -> DoubaoCodingPlanUsage { + let response: CodingPlanUsageResponse + do { + response = try JSONDecoder().decode(CodingPlanUsageResponse.self, from: data) + } catch { + throw DoubaoUsageError.parseFailed(error.localizedDescription) + } + let usage = response.result + let quotas = usage.quotaUsage.map { quota in + DoubaoCodingPlanUsage.Quota( + level: quota.level, + percent: quota.percent, + resetTime: self.date(fromEpoch: quota.resetTimestamp)) + } + return DoubaoCodingPlanUsage( + status: usage.status, + updateTime: self.date(fromEpoch: usage.updateTimestamp), + quotas: quotas) + } + + private static func date(fromEpoch timestamp: TimeInterval?) -> Date? { + guard let timestamp, timestamp > 0 else { return nil } + return Date(timeIntervalSince1970: timestamp) + } + + private static func confirmAmbiguousZeroRemaining( + initial: ProbeResult, + apiKey: String, + model: String, + transport: any ProviderHTTPTransport) async throws -> DoubaoUsageSnapshot + { + do { + let confirmation = try await self.probe(apiKey: apiKey, model: model, transport: transport) + // This path starts only after a complete HTTP 200 request-limit pair + // reported zero. An immediate 429 confirms that exhausted state even + // when Ark omits the headers from the throttle response. + if confirmation.statusCode == 429 { + return confirmation.snapshot.requestLimitsReliable + ? confirmation.snapshot + : initial.snapshot + } + guard confirmation.hasAmbiguousZeroRemaining else { + return confirmation.snapshot + } + + Self.log.warning( + """ + Doubao Ark returned limit=\(confirmation.snapshot.limitRequests) remaining=0 \ + with HTTP 200 twice; treating request-limit headers as unreliable. + """) + return DoubaoUsageSnapshot( + remainingRequests: confirmation.snapshot.remainingRequests, + limitRequests: confirmation.snapshot.limitRequests, + resetTime: confirmation.snapshot.resetTime, + updatedAt: confirmation.snapshot.updatedAt, + apiKeyValid: confirmation.snapshot.apiKeyValid, + totalTokens: confirmation.snapshot.totalTokens, + requestLimitsReliable: false) + } catch { + if error is CancellationError || (error as? URLError)?.code == .cancelled { + throw error + } + self.log.warning( + """ + Doubao zero-remaining confirmation failed; preserving the initial exhausted state: \ + \(error.localizedDescription) + """) + return initial.snapshot + } + } + + private static func probe( + apiKey: String, + model: String, + transport: any ProviderHTTPTransport) async throws -> ProbeResult + { + var request = URLRequest(url: self.apiURL) + request.httpMethod = "POST" + request.timeoutInterval = 15 + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + request.setValue("application/json", forHTTPHeaderField: "Accept") + request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization") + + let body: [String: Any] = [ + "model": model, + "max_tokens": 1, + "messages": [ + ["role": "user", "content": "hi"], + ] as [[String: Any]], + ] + + request.httpBody = try JSONSerialization.data(withJSONObject: body) + + let response = try await transport.response(for: request) + let data = response.data + + // Accept both 200 (success) and 429 (rate limited) – both carry rate limit headers. + guard response.statusCode == 200 || response.statusCode == 429 else { + let summary = Self.apiErrorSummary(statusCode: response.statusCode, data: data) + Self.log.error("Doubao API returned \(response.statusCode): \(summary)") + throw DoubaoUsageError.apiError(response.statusCode, summary) + } + + let headers = response.response.allHeaderFields + let remaining = Self.intHeader(headers, "x-ratelimit-remaining-requests") + let limit = Self.intHeader(headers, "x-ratelimit-limit-requests") + let resetString = Self.stringHeader(headers, "x-ratelimit-reset-requests") + + let resetTime: Date? = resetString.flatMap(Self.parseResetTime) + + var totalTokens: Int? + if remaining == nil, limit == nil, + let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any], + let usage = json["usage"] as? [String: Any] + { + totalTokens = usage["total_tokens"] as? Int + } + + // 429 means the key is valid but rate-limited; treat it as valid so the UI + // shows "Active" instead of "No usage data" when headers are absent. + let keyValid = response.statusCode == 200 || response.statusCode == 429 + // A request-limit header on 429 identifies request-bucket exhaustion even + // when Ark omits remaining. A bare 429 may describe another throttle. + let requestLimitsReliable = response.statusCode == 429 + ? limit != nil + : limit != nil && remaining != nil + + let snapshot = DoubaoUsageSnapshot( + remainingRequests: remaining ?? 0, + limitRequests: limit ?? 0, + resetTime: resetTime, + updatedAt: Date(), + apiKeyValid: keyValid, + totalTokens: totalTokens, + requestLimitsReliable: requestLimitsReliable) + + Self.log.debug( + """ + Doubao usage parsed remaining=\(snapshot.remainingRequests) \ + limit=\(snapshot.limitRequests) valid=\(snapshot.apiKeyValid) + """) + + return ProbeResult(snapshot: snapshot, statusCode: response.statusCode) + } + + private static func stringHeader(_ headers: [AnyHashable: Any], _ name: String) -> String? { + if let value = headers[name] as? String { return value } + for (key, val) in headers { + if let keyStr = key as? String, + keyStr.caseInsensitiveCompare(name) == .orderedSame, + let valStr = val as? String + { + return valStr + } + } + return nil + } + + private static func intHeader(_ headers: [AnyHashable: Any], _ name: String) -> Int? { + if let value = headers[name] as? String, let int = Int(value) { + return int + } + if let value = headers[name.lowercased()] as? String, let int = Int(value) { + return int + } + for (key, val) in headers { + if let keyStr = key as? String, + keyStr.lowercased() == name.lowercased(), + let valStr = val as? String, + let int = Int(valStr) + { + return int + } + } + return nil + } + + private static func parseResetTime(_ value: String) -> Date? { + let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines) + if trimmed.isEmpty { return nil } + + let isoFormatter = ISO8601DateFormatter() + isoFormatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds] + if let date = isoFormatter.date(from: trimmed) { return date } + let isoFallback = ISO8601DateFormatter() + isoFallback.formatOptions = [.withInternetDateTime] + if let date = isoFallback.date(from: trimmed) { return date } + + var seconds: TimeInterval = 0 + let pattern = /(\d+)([dhms])/ + for match in trimmed.matches(of: pattern) { + guard let num = Double(match.1) else { continue } + switch match.2 { + case "d": seconds += num * 86400 + case "h": seconds += num * 3600 + case "m": seconds += num * 60 + case "s": seconds += num + default: break + } + } + if seconds > 0 { + return Date().addingTimeInterval(seconds) + } + + if let secs = TimeInterval(trimmed) { + return Date().addingTimeInterval(secs) + } + + return nil + } + + private static func apiErrorSummary(statusCode: Int, data: Data) -> String { + guard let root = try? JSONSerialization.jsonObject(with: data), + let json = root as? [String: Any] + else { + if let text = String(data: data, encoding: .utf8)? + .trimmingCharacters(in: .whitespacesAndNewlines), + !text.isEmpty + { + return self.compactText(text) + } + return "Unexpected response body (\(data.count) bytes)." + } + + // Volcengine Top OpenAPI error shape: { "ResponseMetadata": { "Error": { "Code": ..., "Message": ... } } } + if let metadata = json["ResponseMetadata"] as? [String: Any], + let volcError = metadata["Error"] as? [String: Any] + { + let code = (volcError["Code"] as? String)?.trimmingCharacters(in: .whitespacesAndNewlines) + let message = (volcError["Message"] as? String)?.trimmingCharacters(in: .whitespacesAndNewlines) + switch (code?.isEmpty == false ? code : nil, message?.isEmpty == false ? message : nil) { + case let (code?, message?): + return Self.compactText("\(code): \(message)") + case let (code?, nil): + return Self.compactText(code) + case let (nil, message?): + return Self.compactText(message) + case (nil, nil): + break + } + } + + if let error = json["error"] as? [String: Any], + let message = error["message"] as? String + { + let trimmed = message.trimmingCharacters(in: .whitespacesAndNewlines) + if !trimmed.isEmpty { return Self.compactText(trimmed) } + } + + if let message = json["message"] as? String { + let trimmed = message.trimmingCharacters(in: .whitespacesAndNewlines) + if !trimmed.isEmpty { return Self.compactText(trimmed) } + } + + return "HTTP \(statusCode) (\(data.count) bytes)." + } + + private static func compactText(_ text: String, maxLength: Int = 200) -> String { + let collapsed = text + .components(separatedBy: .newlines) + .joined(separator: " ") + .trimmingCharacters(in: .whitespacesAndNewlines) + if collapsed.count <= maxLength { return collapsed } + let limitIndex = collapsed.index(collapsed.startIndex, offsetBy: maxLength) + return "\(collapsed[.. String + { + let dateKey = Self.hmac(key: SymmetricKey(data: Data(secretAccessKey.utf8)), message: dateStamp) + let regionKey = Self.hmac(key: SymmetricKey(data: dateKey), message: region) + let serviceKey = Self.hmac(key: SymmetricKey(data: regionKey), message: Self.service) + let signingKey = Self.hmac(key: SymmetricKey(data: serviceKey), message: Self.terminator) + let signature = HMAC.authenticationCode( + for: Data(stringToSign.utf8), + using: SymmetricKey(data: signingKey)) + return Data(signature).map { String(format: "%02x", $0) }.joined() + } + + private static func hmac(key: SymmetricKey, message: String) -> Data { + let digest = HMAC.authenticationCode(for: Data(message.utf8), using: key) + return Data(digest) + } + + private static func sha256Hex(_ data: Data) -> String { + SHA256.hash(data: data).map { String(format: "%02x", $0) }.joined() + } + + private static func canonicalURI(_ url: URL) -> String { + let path = url.path.isEmpty ? "/" : url.path + return Self.percentEncode(path, encodeSlash: false) + } + + private static func canonicalQueryString(_ url: URL) -> String { + guard let components = URLComponents(url: url, resolvingAgainstBaseURL: false), + let queryItems = components.queryItems, + !queryItems.isEmpty + else { + return "" + } + var pairs: [(key: String, value: String)] = queryItems.map { item in + ( + key: Self.percentEncode(item.name), + value: Self.percentEncode(item.value ?? "")) + } + pairs.sort { lhs, rhs in + lhs.key == rhs.key ? lhs.value < rhs.value : lhs.key < rhs.key + } + return pairs + .map { pair in "\(pair.key)=\(pair.value)" } + .joined(separator: "&") + } + + private static func percentEncode(_ value: String, encodeSlash: Bool = true) -> String { + var allowed = CharacterSet.alphanumerics + allowed.insert(charactersIn: "-_.~") + if !encodeSlash { + allowed.insert("/") + } + return value.addingPercentEncoding(withAllowedCharacters: allowed) ?? value + } + + private static let timestampFormatter: DateFormatter = { + let formatter = DateFormatter() + formatter.locale = Locale(identifier: "en_US_POSIX") + formatter.timeZone = TimeZone(secondsFromGMT: 0) + formatter.dateFormat = "yyyyMMdd'T'HHmmss'Z'" + return formatter + }() + + private static let dateFormatter: DateFormatter = { + let formatter = DateFormatter() + formatter.locale = Locale(identifier: "en_US_POSIX") + formatter.timeZone = TimeZone(secondsFromGMT: 0) + formatter.dateFormat = "yyyyMMdd" + return formatter + }() +} diff --git a/Sources/CodexBarCore/Providers/ElevenLabs/ElevenLabsProviderDescriptor.swift b/Sources/CodexBarCore/Providers/ElevenLabs/ElevenLabsProviderDescriptor.swift new file mode 100644 index 0000000..1981614 --- /dev/null +++ b/Sources/CodexBarCore/Providers/ElevenLabs/ElevenLabsProviderDescriptor.swift @@ -0,0 +1,49 @@ +import Foundation + +public enum ElevenLabsProviderDescriptor { + public static let descriptor: ProviderDescriptor = Self.makeDescriptor() + + static func makeDescriptor() -> ProviderDescriptor { + ProviderDescriptor( + id: .elevenlabs, + metadata: ProviderMetadata( + id: .elevenlabs, + displayName: "ElevenLabs", + sessionLabel: "Credits", + weeklyLabel: "Voices", + opusLabel: nil, + supportsOpus: false, + supportsCredits: false, + creditsHint: "", + toggleTitle: "Show ElevenLabs usage", + cliName: "elevenlabs", + defaultEnabled: false, + isPrimaryProvider: false, + usesAccountFallback: false, + browserCookieOrder: nil, + dashboardURL: "https://elevenlabs.io/app/developers/usage", + subscriptionDashboardURL: "https://elevenlabs.io/app/subscription", + statusPageURL: nil, + statusLinkURL: "https://status.elevenlabs.io"), + branding: ProviderBranding( + iconStyle: .elevenlabs, + iconResourceName: "ProviderIcon-elevenlabs", + color: ProviderColor(red: 0.92, green: 0.92, blue: 0.90)), + tokenCost: ProviderTokenCostConfig( + supportsTokenCost: false, + noDataMessage: { "ElevenLabs cost history is not available via API yet." }), + fetchPlan: .apiToken( + strategyID: "elevenlabs.api", + resolveToken: { ProviderTokenResolver.elevenLabsToken(environment: $0) }, + missingCredentialsError: { ElevenLabsUsageError.missingCredentials }, + loadUsage: { apiKey, context in + try await ElevenLabsUsageFetcher.fetchUsage( + apiKey: apiKey, + environment: context.env).toUsageSnapshot() + }), + cli: ProviderCLIConfig( + name: "elevenlabs", + aliases: ["11labs", "eleven"], + versionDetector: nil)) + } +} diff --git a/Sources/CodexBarCore/Providers/ElevenLabs/ElevenLabsSettingsReader.swift b/Sources/CodexBarCore/Providers/ElevenLabs/ElevenLabsSettingsReader.swift new file mode 100644 index 0000000..2ffecec --- /dev/null +++ b/Sources/CodexBarCore/Providers/ElevenLabs/ElevenLabsSettingsReader.swift @@ -0,0 +1,62 @@ +import Foundation + +public enum ElevenLabsSettingsReader { + public static let apiKeyEnvironmentKey = "ELEVENLABS_API_KEY" + public static let apiKeyEnvironmentKeys = [ + Self.apiKeyEnvironmentKey, + "XI_API_KEY", + ] + public static let apiURLEnvironmentKey = "ELEVENLABS_API_URL" + + public static func apiKey(environment: [String: String] = ProcessInfo.processInfo.environment) -> String? { + for key in self.apiKeyEnvironmentKeys { + guard let token = self.cleaned(environment[key]) else { continue } + return token + } + return nil + } + + public static func apiURL(environment: [String: String] = ProcessInfo.processInfo.environment) -> URL { + if let override = self.validAPIURL(environment: environment) { + return override + } + return URL(string: "https://api.elevenlabs.io")! + } + + public static func validateEndpointOverrides( + environment: [String: String] = ProcessInfo.processInfo.environment) throws + { + guard let raw = self.cleaned(environment[self.apiURLEnvironmentKey]) else { return } + guard ProviderEndpointOverrideValidator.normalizedHTTPSURL(from: raw) == nil else { return } + throw ElevenLabsSettingsError.invalidEndpointOverride(self.apiURLEnvironmentKey) + } + + static func cleaned(_ raw: String?) -> String? { + guard var value = raw?.trimmingCharacters(in: .whitespacesAndNewlines), !value.isEmpty else { + return nil + } + if (value.hasPrefix("\"") && value.hasSuffix("\"")) || + (value.hasPrefix("'") && value.hasSuffix("'")) + { + value = String(value.dropFirst().dropLast()) + } + value = value.trimmingCharacters(in: .whitespacesAndNewlines) + return value.isEmpty ? nil : value + } + + private static func validAPIURL(environment: [String: String]) -> URL? { + guard let raw = self.cleaned(environment[self.apiURLEnvironmentKey]) else { return nil } + return ProviderEndpointOverrideValidator.normalizedHTTPSURL(from: raw) + } +} + +public enum ElevenLabsSettingsError: LocalizedError, Sendable, Equatable { + case invalidEndpointOverride(String) + + public var errorDescription: String? { + switch self { + case let .invalidEndpointOverride(key): + "ElevenLabs endpoint override \(key) must use HTTPS or a bare host." + } + } +} diff --git a/Sources/CodexBarCore/Providers/ElevenLabs/ElevenLabsUsageFetcher.swift b/Sources/CodexBarCore/Providers/ElevenLabs/ElevenLabsUsageFetcher.swift new file mode 100644 index 0000000..9befb3c --- /dev/null +++ b/Sources/CodexBarCore/Providers/ElevenLabs/ElevenLabsUsageFetcher.swift @@ -0,0 +1,252 @@ +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +public struct ElevenLabsOverage: Codable, Sendable, Equatable { + public let amount: String? + public let currency: String? +} + +public struct ElevenLabsSubscriptionResponse: Decodable, Sendable { + public let tier: String? + public let characterCount: Int + public let characterLimit: Int + public let voiceSlotsUsed: Int? + public let professionalVoiceSlotsUsed: Int? + public let voiceLimit: Int? + public let professionalVoiceLimit: Int? + public let currentOverage: ElevenLabsOverage? + public let status: String? + public let nextCharacterCountResetUnix: Int? + + private enum CodingKeys: String, CodingKey { + case tier + case characterCount = "character_count" + case characterLimit = "character_limit" + case voiceSlotsUsed = "voice_slots_used" + case professionalVoiceSlotsUsed = "professional_voice_slots_used" + case voiceLimit = "voice_limit" + case professionalVoiceLimit = "professional_voice_limit" + case currentOverage = "current_overage" + case status + case nextCharacterCountResetUnix = "next_character_count_reset_unix" + } +} + +public struct ElevenLabsUsageSnapshot: Codable, Sendable, Equatable { + public let tier: String? + public let characterCount: Int + public let characterLimit: Int + public let voiceSlotsUsed: Int? + public let professionalVoiceSlotsUsed: Int? + public let voiceLimit: Int? + public let professionalVoiceLimit: Int? + public let currentOverage: ElevenLabsOverage? + public let status: String? + public let resetsAt: Date? + public let updatedAt: Date + + public init( + tier: String?, + characterCount: Int, + characterLimit: Int, + voiceSlotsUsed: Int?, + professionalVoiceSlotsUsed: Int?, + voiceLimit: Int?, + professionalVoiceLimit: Int?, + currentOverage: ElevenLabsOverage?, + status: String?, + resetsAt: Date?, + updatedAt: Date) + { + self.tier = tier + self.characterCount = characterCount + self.characterLimit = characterLimit + self.voiceSlotsUsed = voiceSlotsUsed + self.professionalVoiceSlotsUsed = professionalVoiceSlotsUsed + self.voiceLimit = voiceLimit + self.professionalVoiceLimit = professionalVoiceLimit + self.currentOverage = currentOverage + self.status = status + self.resetsAt = resetsAt + self.updatedAt = updatedAt + } + + public var usedPercent: Double { + guard self.characterLimit > 0 else { return 0 } + return max(0, Double(self.characterCount) / Double(self.characterLimit) * 100) + } + + public var remainingCharacters: Int { + max(0, self.characterLimit - self.characterCount) + } + + public func toUsageSnapshot() -> UsageSnapshot { + let primary = RateWindow( + usedPercent: self.usedPercent, + windowMinutes: nil, + resetsAt: self.resetsAt, + resetDescription: self.characterSummary) + let extraWindows = self.voiceWindows() + let identity = ProviderIdentitySnapshot( + providerID: .elevenlabs, + accountEmail: nil, + accountOrganization: nil, + loginMethod: self.displayTier) + + return UsageSnapshot( + primary: primary, + secondary: nil, + tertiary: nil, + extraRateWindows: extraWindows.isEmpty ? nil : extraWindows, + updatedAt: self.updatedAt, + identity: identity) + } + + private var displayTier: String? { + guard let tier = tier?.trimmingCharacters(in: .whitespacesAndNewlines), !tier.isEmpty else { + return status + } + let statusSuffix = if let status, !status.isEmpty, status.lowercased() != "active" { + " · \(status)" + } else { + "" + } + return "\(tier.replacingOccurrences(of: "_", with: " ").capitalized)\(statusSuffix)" + } + + private var characterSummary: String { + "\(Self.formatCount(self.characterCount)) / \(Self.formatCount(self.characterLimit)) credits" + } + + private func voiceWindows() -> [NamedRateWindow] { + var windows: [NamedRateWindow] = [] + if let used = voiceSlotsUsed, let limit = voiceLimit, limit > 0 { + windows.append(NamedRateWindow( + id: "voice-slots", + title: "Voice slots", + window: RateWindow( + usedPercent: Double(used) / Double(limit) * 100, + windowMinutes: nil, + resetsAt: nil, + resetDescription: "\(used) / \(limit)"))) + } + if let used = professionalVoiceSlotsUsed, let limit = professionalVoiceLimit, limit > 0 { + windows.append(NamedRateWindow( + id: "professional-voices", + title: "Professional voices", + window: RateWindow( + usedPercent: Double(used) / Double(limit) * 100, + windowMinutes: nil, + resetsAt: nil, + resetDescription: "\(used) / \(limit)"))) + } + return windows + } + + private static func formatCount(_ value: Int) -> String { + let formatter = NumberFormatter() + formatter.locale = Locale(identifier: "en_US_POSIX") + formatter.numberStyle = .decimal + formatter.usesGroupingSeparator = true + formatter.groupingSeparator = "," + formatter.maximumFractionDigits = 0 + return formatter.string(from: NSNumber(value: value)) ?? "\(value)" + } +} + +public enum ElevenLabsUsageError: LocalizedError, Sendable { + case missingCredentials + case networkError(String) + case apiError(String) + case parseFailed(String) + + public var errorDescription: String? { + switch self { + case .missingCredentials: + "Missing ElevenLabs API key. Set apiKey in ~/.codexbar/config.json or ELEVENLABS_API_KEY." + case let .networkError(message): + "ElevenLabs network error: \(message)" + case let .apiError(message): + "ElevenLabs API error: \(message)" + case let .parseFailed(message): + "Failed to parse ElevenLabs response: \(message)" + } + } +} + +public struct ElevenLabsUsageFetcher: Sendable { + private static let log = CodexBarLog.logger(LogCategories.elevenLabsUsage) + private static let timeoutSeconds: TimeInterval = 15 + + public static func fetchUsage( + apiKey: String, + environment: [String: String] = ProcessInfo.processInfo.environment) async throws -> ElevenLabsUsageSnapshot + { + let trimmed = apiKey.trimmingCharacters(in: .whitespacesAndNewlines) + guard !trimmed.isEmpty else { + throw ElevenLabsUsageError.missingCredentials + } + try ElevenLabsSettingsReader.validateEndpointOverrides(environment: environment) + + let url = Self.subscriptionURL(baseURL: ElevenLabsSettingsReader.apiURL(environment: environment)) + var request = URLRequest(url: url) + request.httpMethod = "GET" + request.setValue(trimmed, forHTTPHeaderField: "xi-api-key") + request.setValue("application/json", forHTTPHeaderField: "Accept") + request.timeoutInterval = Self.timeoutSeconds + + let response = try await ProviderHTTPClient.shared.response(for: request) + switch response.statusCode { + case 200: + return try Self.parseSnapshot(data: response.data, updatedAt: Date()) + case 401, 403: + throw ElevenLabsUsageError.missingCredentials + default: + Self.log.error("ElevenLabs API returned \(response.statusCode)") + throw ElevenLabsUsageError.apiError("HTTP \(response.statusCode)") + } + } + + static func _parseSnapshotForTesting(_ data: Data, updatedAt: Date) throws -> ElevenLabsUsageSnapshot { + try self.parseSnapshot(data: data, updatedAt: updatedAt) + } + + private static func parseSnapshot(data: Data, updatedAt: Date) throws -> ElevenLabsUsageSnapshot { + let decoded: ElevenLabsSubscriptionResponse + do { + decoded = try JSONDecoder().decode(ElevenLabsSubscriptionResponse.self, from: data) + } catch { + throw ElevenLabsUsageError.parseFailed(error.localizedDescription) + } + + let resetsAt = decoded.nextCharacterCountResetUnix.map { + Date(timeIntervalSince1970: TimeInterval($0)) + } + + return ElevenLabsUsageSnapshot( + tier: decoded.tier, + characterCount: decoded.characterCount, + characterLimit: decoded.characterLimit, + voiceSlotsUsed: decoded.voiceSlotsUsed, + professionalVoiceSlotsUsed: decoded.professionalVoiceSlotsUsed, + voiceLimit: decoded.voiceLimit, + professionalVoiceLimit: decoded.professionalVoiceLimit, + currentOverage: decoded.currentOverage, + status: decoded.status, + resetsAt: resetsAt, + updatedAt: updatedAt) + } + + private static func subscriptionURL(baseURL: URL) -> URL { + var url = baseURL + let pathComponents = url.path.split(separator: "/") + if pathComponents.last == "v1" { + url.append(path: "user/subscription") + } else { + url.append(path: "v1/user/subscription") + } + return url + } +} diff --git a/Sources/CodexBarCore/Providers/Factory/FactoryLocalStorageImporter.swift b/Sources/CodexBarCore/Providers/Factory/FactoryLocalStorageImporter.swift new file mode 100644 index 0000000..08f0cde --- /dev/null +++ b/Sources/CodexBarCore/Providers/Factory/FactoryLocalStorageImporter.swift @@ -0,0 +1,383 @@ +import Foundation +#if os(macOS) +import SQLite3 +import SweetCookieKit +#endif + +#if os(macOS) +enum FactoryLocalStorageImporter { + struct TokenInfo { + let refreshToken: String + let accessToken: String? + let organizationID: String? + let sourceLabel: String + } + + static func importWorkOSTokens( + browserDetection: BrowserDetection, + logger: ((String) -> Void)? = nil) -> [TokenInfo] + { + let log: (String) -> Void = { msg in logger?("[factory-storage] \(msg)") } + var tokens: [TokenInfo] = [] + + let safariCandidates = self.safariLocalStorageCandidates() + let chromeCandidates = self.chromeLocalStorageCandidates(browserDetection: browserDetection) + if !safariCandidates.isEmpty { + log("Safari local storage candidates: \(safariCandidates.count)") + } + if !chromeCandidates.isEmpty { + log("Chrome local storage candidates: \(chromeCandidates.count)") + } + + let candidates = safariCandidates + chromeCandidates + for candidate in candidates { + let match: WorkOSTokenMatch? = switch candidate.kind { + case let .chromeLevelDB(levelDBURL): + self.readWorkOSToken(from: levelDBURL) + case let .safariSQLite(dbURL): + self.readWorkOSTokenFromSafariSQLite(dbURL: dbURL, logger: log) + } + guard let token = match else { continue } + log("Found WorkOS refresh token in \(candidate.label)") + tokens.append(TokenInfo( + refreshToken: token.refreshToken, + accessToken: token.accessToken, + organizationID: token.organizationID, + sourceLabel: candidate.label)) + } + + if tokens.isEmpty { + log("No WorkOS refresh token found in browser local storage") + } + + return tokens + } + + static func hasSafariWorkOSRefreshToken() -> Bool { + for candidate in self.safariLocalStorageCandidates() { + guard case let .safariSQLite(dbURL) = candidate.kind else { continue } + if self.readWorkOSTokenFromSafariSQLite(dbURL: dbURL) != nil { + return true + } + } + return false + } + + // MARK: - Chrome local storage discovery + + private enum LocalStorageSourceKind { + case chromeLevelDB(URL) + case safariSQLite(URL) + } + + private struct LocalStorageCandidate { + let label: String + let kind: LocalStorageSourceKind + } + + private static func chromeLocalStorageCandidates(browserDetection: BrowserDetection) -> [LocalStorageCandidate] { + let browsers: [Browser] = [ + .chrome, + .chromeBeta, + .chromeCanary, + .arc, + .arcBeta, + .arcCanary, + .dia, + .chatgptAtlas, + .chromium, + .helium, + ] + + // Filter to browsers with profile data to avoid unnecessary filesystem access. + let installedBrowsers = browsers.browsersWithProfileData(using: browserDetection) + + let roots = ChromiumProfileLocator + .roots(for: installedBrowsers, homeDirectories: BrowserCookieClient.defaultHomeDirectories()) + .map { (url: $0.url, labelPrefix: $0.labelPrefix) } + + var candidates: [LocalStorageCandidate] = [] + for root in roots { + candidates.append(contentsOf: self.chromeProfileLocalStorageDirs( + root: root.url, + labelPrefix: root.labelPrefix)) + } + return candidates + } + + private static func chromeProfileLocalStorageDirs(root: URL, labelPrefix: String) -> [LocalStorageCandidate] { + guard let entries = try? FileManager.default.contentsOfDirectory( + at: root, + includingPropertiesForKeys: [.isDirectoryKey], + options: [.skipsHiddenFiles]) + else { return [] } + + let profileDirs = entries.filter { url in + guard let isDir = (try? url.resourceValues(forKeys: [.isDirectoryKey]).isDirectory), isDir else { + return false + } + let name = url.lastPathComponent + return name == "Default" || name.hasPrefix("Profile ") || name.hasPrefix("user-") + } + .sorted { $0.lastPathComponent < $1.lastPathComponent } + + return profileDirs.compactMap { dir in + let levelDBURL = dir.appendingPathComponent("Local Storage").appendingPathComponent("leveldb") + guard FileManager.default.fileExists(atPath: levelDBURL.path) else { return nil } + let label = "\(labelPrefix) \(dir.lastPathComponent)" + return LocalStorageCandidate(label: label, kind: .chromeLevelDB(levelDBURL)) + } + } + + private static func safariLocalStorageCandidates() -> [LocalStorageCandidate] { + let root = FileManager.default.homeDirectoryForCurrentUser + .appendingPathComponent("Library") + .appendingPathComponent("Containers") + .appendingPathComponent("com.apple.Safari") + .appendingPathComponent("Data") + .appendingPathComponent("Library") + .appendingPathComponent("WebKit") + .appendingPathComponent("WebsiteData") + .appendingPathComponent("Default") + + guard FileManager.default.fileExists(atPath: root.path) else { return [] } + + let targets = ["app.factory.ai", "auth.factory.ai"] + var candidates: [LocalStorageCandidate] = [] + + guard let enumerator = FileManager.default.enumerator( + at: root, + includingPropertiesForKeys: [.isRegularFileKey], + options: [.skipsHiddenFiles]) + else { return [] } + + for case let fileURL as URL in enumerator { + guard fileURL.lastPathComponent == "origin" else { continue } + guard (try? fileURL.resourceValues(forKeys: [.isRegularFileKey]).isRegularFile) == true else { + continue + } + guard let data = try? Data(contentsOf: fileURL, options: [.mappedIfSafe]) else { continue } + let ascii = String(data: data, encoding: .utf8) ?? String(data: data, encoding: .isoLatin1) ?? "" + guard targets.contains(where: { ascii.contains($0) }) else { continue } + + let storageURL = fileURL.deletingLastPathComponent() + .appendingPathComponent("LocalStorage") + .appendingPathComponent("localstorage.sqlite3") + guard FileManager.default.fileExists(atPath: storageURL.path) else { continue } + let host = self.extractSafariOriginHost(from: ascii) ?? "app.factory.ai" + candidates.append(LocalStorageCandidate(label: "Safari (\(host))", kind: .safariSQLite(storageURL))) + } + + var seen = Set() + return candidates.filter { candidate in + let key: String = switch candidate.kind { + case let .chromeLevelDB(url): + url.path + case let .safariSQLite(url): + url.path + } + if seen.contains(key) { return false } + seen.insert(key) + return true + } + } + + private static func extractSafariOriginHost(from ascii: String) -> String? { + let targets = ["app.factory.ai", "auth.factory.ai", "factory.ai"] + for host in targets where ascii.contains(host) { + return host + } + return nil + } + + // MARK: - Token extraction + + private struct WorkOSTokenMatch { + let refreshToken: String + let accessToken: String? + let organizationID: String? + } + + private static func readWorkOSToken(from levelDBURL: URL) -> WorkOSTokenMatch? { + guard let entries = try? FileManager.default.contentsOfDirectory( + at: levelDBURL, + includingPropertiesForKeys: [.contentModificationDateKey], + options: [.skipsHiddenFiles]) + else { return nil } + + let files = entries.filter { url in + let ext = url.pathExtension.lowercased() + return ext == "ldb" || ext == "log" + } + .sorted { lhs, rhs in + let left = (try? lhs.resourceValues(forKeys: [.contentModificationDateKey]).contentModificationDate) + let right = (try? rhs.resourceValues(forKeys: [.contentModificationDateKey]).contentModificationDate) + return (left ?? .distantPast) > (right ?? .distantPast) + } + + for file in files { + guard let data = try? Data(contentsOf: file, options: [.mappedIfSafe]) else { continue } + if let match = self.extractWorkOSToken(from: data) { + return match + } + } + return nil + } + + private static func extractWorkOSToken(from data: Data) -> WorkOSTokenMatch? { + guard let contents = String(data: data, encoding: .utf8) ?? + String(data: data, encoding: .isoLatin1) + else { return nil } + guard contents.contains("workos:refresh-token") else { return nil } + + let refreshToken = self.matchToken( + in: contents, + pattern: "workos:refresh-token[^A-Za-z0-9_-]*([A-Za-z0-9_-]{20,})") + guard let refreshToken else { return nil } + + let accessToken = self.matchToken( + in: contents, + pattern: "workos:access-token[^A-Za-z0-9_-]*([A-Za-z0-9_-]{20,})") + + let organizationID = self.extractOrganizationID(from: accessToken) + return WorkOSTokenMatch( + refreshToken: refreshToken, + accessToken: accessToken, + organizationID: organizationID) + } + + private static func readWorkOSTokenFromSafariSQLite( + dbURL: URL, + logger: ((String) -> Void)? = nil) -> WorkOSTokenMatch? + { + var db: OpaquePointer? + guard sqlite3_open_v2(dbURL.path, &db, SQLITE_OPEN_READONLY, nil) == SQLITE_OK else { + if let c = sqlite3_errmsg(db) { + logger?("Safari local storage open failed: \(String(cString: c))") + } + return nil + } + defer { sqlite3_close(db) } + + sqlite3_busy_timeout(db, 250) + let tables = self.fetchTableNames(db: db, logger: logger) + if tables.isEmpty { + logger?("Safari local storage table lookup returned no tables") + } + let table = tables + .contains("ItemTable") ? "ItemTable" : (tables.contains("localstorage") ? "localstorage" : nil) + guard let table else { + logger?("Safari local storage missing ItemTable/localstorage tables (found: \(tables.sorted()))") + return nil + } + + let refreshToken = self.fetchLocalStorageValue(db: db, table: table, key: "workos:refresh-token") + guard let refreshToken, !refreshToken.isEmpty else { + logger?("Safari local storage missing workos:refresh-token") + return nil + } + let accessToken = self.fetchLocalStorageValue(db: db, table: table, key: "workos:access-token") + + let organizationID = self.extractOrganizationID(from: accessToken) + return WorkOSTokenMatch( + refreshToken: refreshToken, + accessToken: accessToken, + organizationID: organizationID) + } + + private static func extractOrganizationID(from accessToken: String?) -> String? { + guard let accessToken, accessToken.contains(".") else { return nil } + let parts = accessToken.split(separator: ".") + guard parts.count == 3 else { return nil } + let payload = String(parts[1]) + .replacingOccurrences(of: "-", with: "+") + .replacingOccurrences(of: "_", with: "/") + let padded = payload + String(repeating: "=", count: (4 - payload.count % 4) % 4) + guard let data = Data(base64Encoded: padded), + let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] + else { + return nil + } + return json["org_id"] as? String + } + + private static func fetchTableNames(db: OpaquePointer?, logger: ((String) -> Void)? = nil) -> Set { + let sql = "SELECT name FROM sqlite_master WHERE type='table'" + var stmt: OpaquePointer? + guard sqlite3_prepare_v2(db, sql, -1, &stmt, nil) == SQLITE_OK else { + if let c = sqlite3_errmsg(db) { + logger?("Safari local storage table query failed: \(String(cString: c))") + } + return [] + } + defer { sqlite3_finalize(stmt) } + var names = Set() + while true { + let step = sqlite3_step(stmt) + if step == SQLITE_ROW { + if let c = sqlite3_column_text(stmt, 0) { + names.insert(String(cString: c)) + } + } else { + if step != SQLITE_DONE, let c = sqlite3_errmsg(db) { + logger?("Safari local storage table query failed: \(String(cString: c))") + } + break + } + } + return names + } + + private static func fetchLocalStorageValue(db: OpaquePointer?, table: String, key: String) -> String? { + let sql = "SELECT value FROM \(table) WHERE key = ? LIMIT 1" + var stmt: OpaquePointer? + guard sqlite3_prepare_v2(db, sql, -1, &stmt, nil) == SQLITE_OK else { return nil } + defer { sqlite3_finalize(stmt) } + let transient = unsafeBitCast(-1, to: sqlite3_destructor_type.self) + _ = key.withCString { cString in + sqlite3_bind_text(stmt, 1, cString, -1, transient) + } + guard sqlite3_step(stmt) == SQLITE_ROW else { return nil } + return self.decodeSQLiteValue(stmt: stmt, index: 0) + } + + private static func decodeSQLiteValue(stmt: OpaquePointer?, index: Int32) -> String? { + let type = sqlite3_column_type(stmt, index) + switch type { + case SQLITE_TEXT: + guard let c = sqlite3_column_text(stmt, index) else { return nil } + return String(cString: c) + case SQLITE_BLOB: + guard let bytes = sqlite3_column_blob(stmt, index) else { return nil } + let count = Int(sqlite3_column_bytes(stmt, index)) + let data = Data(bytes: bytes, count: count) + return self.decodeValueData(data) + default: + return nil + } + } + + private static func decodeValueData(_ data: Data) -> String? { + if let decoded = String(data: data, encoding: .utf16LittleEndian) { + return decoded.trimmingCharacters(in: .controlCharacters) + } + if let decoded = String(data: data, encoding: .utf8) { + return decoded.trimmingCharacters(in: .controlCharacters) + } + if let decoded = String(data: data, encoding: .isoLatin1) { + return decoded.trimmingCharacters(in: .controlCharacters) + } + return nil + } + + private static func matchToken(in contents: String, pattern: String) -> String? { + guard let regex = try? NSRegularExpression(pattern: pattern, options: []) else { return nil } + let range = NSRange(contents.startIndex.. 1, + let tokenRange = Range(match.range(at: 1), in: contents) + else { return nil } + return String(contents[tokenRange]) + } +} +#endif diff --git a/Sources/CodexBarCore/Providers/Factory/FactoryManualCredentials.swift b/Sources/CodexBarCore/Providers/Factory/FactoryManualCredentials.swift new file mode 100644 index 0000000..ae4698a --- /dev/null +++ b/Sources/CodexBarCore/Providers/Factory/FactoryManualCredentials.swift @@ -0,0 +1,58 @@ +import Foundation + +extension FactoryStatusProbe { + struct ManualCredentials { + let cookieHeader: String? + let bearerToken: String? + } + + static func manualCredentials(from raw: String?) -> ManualCredentials? { + guard let raw = raw?.trimmingCharacters(in: .whitespacesAndNewlines), !raw.isEmpty else { + return nil + } + let normalizedCookieHeader = CookieHeaderNormalizer.normalize(raw) + let cookieHeader = normalizedCookieHeader.flatMap { + CookieHeaderNormalizer.pairs(from: $0).isEmpty ? nil : $0 + } + let bearerToken = self.authorizationBearerToken(from: raw) + ?? normalizedCookieHeader.flatMap(self.bearerToken(fromHeader:)) + ?? self.bareBearerToken(from: raw) + guard cookieHeader != nil || bearerToken != nil else { return nil } + return ManualCredentials(cookieHeader: cookieHeader, bearerToken: bearerToken) + } + + static func bearerToken(fromHeader cookieHeader: String) -> String? { + for pair in CookieHeaderNormalizer.pairs(from: cookieHeader) where pair.name == "access-token" { + let token = pair.value.trimmingCharacters(in: .whitespacesAndNewlines) + if !token.isEmpty { return token } + } + return nil + } + + private static func authorizationBearerToken(from raw: String) -> String? { + let pattern = #"(?i)(?:authorization\s*:\s*)?bearer\s+([A-Za-z0-9._~+/=-]+)"# + guard let regex = try? NSRegularExpression(pattern: pattern, options: []) else { return nil } + let range = NSRange(raw.startIndex..= 2, + let tokenRange = Range(match.range(at: 1), in: raw) + else { + return nil + } + let token = raw[tokenRange].trimmingCharacters(in: .whitespacesAndNewlines) + return token.isEmpty ? nil : String(token) + } + + private static func bareBearerToken(from raw: String) -> String? { + let token = raw.trimmingCharacters(in: .whitespacesAndNewlines) + guard !token.contains("="), + !token.contains(";"), + !token.contains(" "), + !token.contains("\n"), + token.count >= 40 || token.split(separator: ".").count >= 3 + else { + return nil + } + return token + } +} diff --git a/Sources/CodexBarCore/Providers/Factory/FactoryProviderDescriptor.swift b/Sources/CodexBarCore/Providers/Factory/FactoryProviderDescriptor.swift new file mode 100644 index 0000000..f3f3892 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Factory/FactoryProviderDescriptor.swift @@ -0,0 +1,145 @@ +import Foundation + +public enum FactoryProviderDescriptor { + public static let descriptor: ProviderDescriptor = Self.makeDescriptor() + + static func makeDescriptor() -> ProviderDescriptor { + ProviderDescriptor( + id: .factory, + metadata: ProviderMetadata( + id: .factory, + displayName: "Droid", + sessionLabel: "Standard", + weeklyLabel: "Premium", + opusLabel: nil, + supportsOpus: false, + supportsCredits: false, + creditsHint: "", + toggleTitle: "Show Droid usage", + cliName: "factory", + defaultEnabled: false, + isPrimaryProvider: false, + usesAccountFallback: false, + browserCookieOrder: ProviderBrowserCookieDefaults.defaultImportOrder, + dashboardURL: "https://app.factory.ai/settings/billing", + statusPageURL: "https://status.factory.ai", + statusLinkURL: nil), + branding: ProviderBranding( + iconStyle: .factory, + iconResourceName: "ProviderIcon-factory", + color: ProviderColor(red: 255 / 255, green: 107 / 255, blue: 53 / 255)), + tokenCost: ProviderTokenCostConfig( + supportsTokenCost: false, + noDataMessage: { "Droid cost summary is not supported." }), + fetchPlan: ProviderFetchPlan( + // `.cli` remains as an Auto compatibility alias for persisted configs from older builds + // that advertised `[.auto, .cli]` while only implementing the web strategy. + sourceModes: [.auto, .api, .web, .cli], + pipeline: ProviderFetchPipeline(resolveStrategies: self.resolveStrategies)), + cli: ProviderCLIConfig( + name: "factory", + versionDetector: nil)) + } + + private static func resolveStrategies(context: ProviderFetchContext) async -> [any ProviderFetchStrategy] { + switch context.sourceMode { + case .api: + [FactoryAPIFetchStrategy()] + case .web: + [FactoryStatusFetchStrategy()] + case .auto, .cli: + // Legacy `source: cli` behaves as Auto (API key first, then cookies/WorkOS on macOS). + // Recoverable API failures fall through to web; explicit `.api` does not. + [FactoryAPIFetchStrategy(), FactoryStatusFetchStrategy()] + case .oauth: + [] + } + } +} + +struct FactoryAPIFetchStrategy: ProviderFetchStrategy { + let id: String = "factory.api" + let kind: ProviderFetchKind = .apiToken + + func isAvailable(_ context: ProviderFetchContext) async -> Bool { + // Explicit API mode always runs so a missing key surfaces as FactoryStatusProbeError.missingAPIKey. + // Auto mode only tries API when a key is resolvable, then falls back to cookies/WorkOS + // for missing/unauthorized keys and other recoverable API failures. + context.sourceMode == .api || Self.resolveAPIKey(environment: context.env) != nil + } + + func fetch(_ context: ProviderFetchContext) async throws -> ProviderFetchResult { + guard let apiKey = Self.resolveAPIKey(environment: context.env) else { + throw FactoryStatusProbeError.missingAPIKey + } + + let probe = FactoryStatusProbe(browserDetection: context.browserDetection) + do { + let snap = try await probe.fetch(apiKey: apiKey) + return self.makeResult( + usage: snap.toUsageSnapshot(), + sourceLabel: "api") + } catch let error as FactoryStatusProbeError { + throw Self.mapAPIError(error) + } + } + + func shouldFallback(on error: Error, context: ProviderFetchContext) -> Bool { + // Explicit API mode stays strict. Auto/cli keep cookies/WorkOS as a recoverable fallback so + // timeouts, DNS/5xx failures, and parse changes do not strand existing web setups. + guard context.sourceMode == .auto || context.sourceMode == .cli else { return false } + if error is CancellationError || (error as? URLError)?.code == .cancelled { + return false + } + return true + } + + private static func resolveAPIKey(environment: [String: String]) -> String? { + FactorySettingsReader.apiKey(environment: environment) + } + + private static func mapAPIError(_ error: FactoryStatusProbeError) -> FactoryStatusProbeError { + switch error { + case .notLoggedIn: + .unauthorizedAPIKey + case let .networkError(message) + where message.contains("HTTP 401") || message.contains("HTTP 403"): + .unauthorizedAPIKey + default: + error + } + } +} + +struct FactoryStatusFetchStrategy: ProviderFetchStrategy { + let id: String = "factory.web" + let kind: ProviderFetchKind = .web + + func isAvailable(_ context: ProviderFetchContext) async -> Bool { + #if !os(macOS) + // Cookie/WorkOS import is macOS-only; Linux relies on API-key auth instead. + return false + #else + guard context.settings?.factory?.cookieSource != .off else { return false } + return true + #endif + } + + func fetch(_ context: ProviderFetchContext) async throws -> ProviderFetchResult { + let probe = FactoryStatusProbe(browserDetection: context.browserDetection) + let manual = Self.manualCookieHeader(from: context) + let snap = try await probe.fetch(cookieHeaderOverride: manual) + return self.makeResult( + usage: snap.toUsageSnapshot(), + sourceLabel: "web") + } + + func shouldFallback(on _: Error, context _: ProviderFetchContext) -> Bool { + false + } + + private static func manualCookieHeader(from context: ProviderFetchContext) -> String? { + guard context.settings?.factory?.cookieSource == .manual else { return nil } + return context.settings?.factory?.manualCookieHeader?.trimmingCharacters(in: .whitespacesAndNewlines) + } +} diff --git a/Sources/CodexBarCore/Providers/Factory/FactorySessionStore.swift b/Sources/CodexBarCore/Providers/Factory/FactorySessionStore.swift new file mode 100644 index 0000000..1d569cb --- /dev/null +++ b/Sources/CodexBarCore/Providers/Factory/FactorySessionStore.swift @@ -0,0 +1,179 @@ +import Foundation + +#if os(macOS) + +// MARK: - Factory Session Store + +public actor FactorySessionStore { + public static let shared = FactorySessionStore() + + private var sessionCookies: [HTTPCookie] = [] + private var bearerToken: String? + private var refreshToken: String? + private var fileURL: URL + private var didLoadFromDisk = false + + private init() { + let fm = FileManager.default + let appSupport = fm.urls(for: .applicationSupportDirectory, in: .userDomainMask).first + ?? fm.temporaryDirectory + let dir = appSupport.appendingPathComponent("CodexBar", isDirectory: true) + try? fm.createDirectory(at: dir, withIntermediateDirectories: true) + self.fileURL = dir.appendingPathComponent("factory-session.json") + } + + public func setCookies(_ cookies: [HTTPCookie]) { + self.didLoadFromDisk = true + self.sessionCookies = cookies + self.saveToDisk() + } + + public func getCookies() -> [HTTPCookie] { + self.loadFromDiskIfNeeded() + return self.sessionCookies + } + + public func clearCookies() { + self.loadFromDiskIfNeeded() + self.didLoadFromDisk = true + self.sessionCookies = [] + self.saveToDisk() + } + + public func setBearerToken(_ token: String?) { + self.didLoadFromDisk = true + self.bearerToken = token + self.saveToDisk() + } + + public func getBearerToken() -> String? { + self.loadFromDiskIfNeeded() + return self.bearerToken + } + + public func setRefreshToken(_ token: String?) { + self.didLoadFromDisk = true + self.refreshToken = token + self.saveToDisk() + } + + public func getRefreshToken() -> String? { + self.loadFromDiskIfNeeded() + return self.refreshToken + } + + public func clearSession() { + self.didLoadFromDisk = true + self.sessionCookies = [] + self.bearerToken = nil + self.refreshToken = nil + try? FileManager.default.removeItem(at: self.fileURL) + } + + public func hasValidSession() -> Bool { + self.loadFromDiskIfNeeded() + return !self.sessionCookies.isEmpty || self.bearerToken != nil || self.refreshToken != nil + } + + func resetInMemoryForTesting() { + self.sessionCookies = [] + self.bearerToken = nil + self.refreshToken = nil + self.didLoadFromDisk = false + } + + func useFileURLForTesting(_ fileURL: URL) { + self.fileURL = fileURL + self.sessionCookies = [] + self.bearerToken = nil + self.refreshToken = nil + self.didLoadFromDisk = false + try? FileManager.default.removeItem(at: fileURL) + } + + private func saveToDisk() { + let cookieData = self.sessionCookies.compactMap { cookie -> [String: Any]? in + guard let props = cookie.properties else { return nil } + var serializable: [String: Any] = [:] + for (key, value) in props { + let keyString = key.rawValue + if let date = value as? Date { + serializable[keyString] = date.timeIntervalSince1970 + serializable[keyString + "_isDate"] = true + } else if let url = value as? URL { + serializable[keyString] = url.absoluteString + serializable[keyString + "_isURL"] = true + } else if JSONSerialization.isValidJSONObject([value]) || + value is String || + value is Bool || + value is NSNumber + { + serializable[keyString] = value + } + } + return serializable + } + + var payload: [String: Any] = [:] + if !cookieData.isEmpty { + payload["cookies"] = cookieData + } + if let bearerToken { + payload["bearerToken"] = bearerToken + } + if let refreshToken { + payload["refreshToken"] = refreshToken + } + + guard !payload.isEmpty, + let data = try? JSONSerialization.data(withJSONObject: payload, options: [.prettyPrinted]) + else { + try? FileManager.default.removeItem(at: self.fileURL) + return + } + try? data.write(to: self.fileURL) + } + + private func loadFromDisk() { + guard let data = try? Data(contentsOf: self.fileURL), + let json = try? JSONSerialization.jsonObject(with: data) + else { return } + + var cookieArray: [[String: Any]] = [] + if let dict = json as? [String: Any] { + if let stored = dict["cookies"] as? [[String: Any]] { + cookieArray = stored + } + self.bearerToken = dict["bearerToken"] as? String + self.refreshToken = dict["refreshToken"] as? String + } else if let stored = json as? [[String: Any]] { + cookieArray = stored + } + + self.sessionCookies = cookieArray.compactMap { props in + var cookieProps: [HTTPCookiePropertyKey: Any] = [:] + for (key, value) in props { + if key.hasSuffix("_isDate") || key.hasSuffix("_isURL") { continue } + + let propKey = HTTPCookiePropertyKey(key) + + if props[key + "_isDate"] as? Bool == true, let interval = value as? TimeInterval { + cookieProps[propKey] = Date(timeIntervalSince1970: interval) + } else if props[key + "_isURL"] as? Bool == true, let urlString = value as? String { + cookieProps[propKey] = URL(string: urlString) + } else { + cookieProps[propKey] = value + } + } + return HTTPCookie(properties: cookieProps) + } + } + + private func loadFromDiskIfNeeded() { + guard !self.didLoadFromDisk else { return } + self.didLoadFromDisk = true + self.loadFromDisk() + } +} + +#endif diff --git a/Sources/CodexBarCore/Providers/Factory/FactorySettingsReader.swift b/Sources/CodexBarCore/Providers/Factory/FactorySettingsReader.swift new file mode 100644 index 0000000..e200e4d --- /dev/null +++ b/Sources/CodexBarCore/Providers/Factory/FactorySettingsReader.swift @@ -0,0 +1,71 @@ +import Foundation + +public enum FactorySettingsReader { + public static let apiTokenKey = "FACTORY_API_KEY" + + /// Resolves a Factory API key from `FACTORY_API_KEY`, then optional `~/.factory/.env`. + /// Dotenv lookup uses `HOME` from `environment` when present; otherwise the process home directory + /// when `environment` is omitted. Tests can pass an empty env (no `HOME`) to skip dotenv. + public static func apiKey( + environment: [String: String] = ProcessInfo.processInfo.environment, + homeDirectory: URL? = nil) -> String? + { + if let fromEnv = self.cleaned(environment[self.apiTokenKey]) { + return fromEnv + } + guard let home = homeDirectory ?? self.homeDirectory(from: environment) else { + return nil + } + return self.apiKeyFromFactoryDotEnv(homeDirectory: home) + } + + public static func apiKeyFromFactoryDotEnv(homeDirectory: URL) -> String? { + let envFile = homeDirectory + .appendingPathComponent(".factory", isDirectory: true) + .appendingPathComponent(".env", isDirectory: false) + guard let contents = try? String(contentsOf: envFile, encoding: .utf8) else { + return nil + } + return self.parseFactoryAPIKey(fromDotEnv: contents) + } + + static func parseFactoryAPIKey(fromDotEnv contents: String) -> String? { + for rawLine in contents.split(whereSeparator: \.isNewline) { + var line = String(rawLine).trimmingCharacters(in: .whitespacesAndNewlines) + guard !line.isEmpty, !line.hasPrefix("#") else { continue } + if line.hasPrefix("export ") { + line = String(line.dropFirst("export ".count)) + .trimmingCharacters(in: .whitespacesAndNewlines) + } + guard let separator = line.firstIndex(of: "=") else { continue } + let key = String(line[.. URL? { + guard let home = self.cleaned(environment["HOME"]) else { + return nil + } + let expanded = NSString(string: home).expandingTildeInPath + return URL(fileURLWithPath: expanded, isDirectory: true) + } + + static func cleaned(_ raw: String?) -> String? { + guard var value = raw?.trimmingCharacters(in: .whitespacesAndNewlines), !value.isEmpty else { + return nil + } + + if (value.hasPrefix("\"") && value.hasSuffix("\"")) || + (value.hasPrefix("'") && value.hasSuffix("'")) + { + value = String(value.dropFirst().dropLast()) + } + + value = value.trimmingCharacters(in: .whitespacesAndNewlines) + return value.isEmpty ? nil : value + } +} diff --git a/Sources/CodexBarCore/Providers/Factory/FactoryStatusProbe+APIKey.swift b/Sources/CodexBarCore/Providers/Factory/FactoryStatusProbe+APIKey.swift new file mode 100644 index 0000000..44c69bc --- /dev/null +++ b/Sources/CodexBarCore/Providers/Factory/FactoryStatusProbe+APIKey.swift @@ -0,0 +1,62 @@ +import Foundation + +extension FactoryStatusProbe { + /// Fetch Factory usage using a Factory API key (`FACTORY_API_KEY` / `fk-…`). + public func fetch( + apiKey: String, + logger: ((String) -> Void)? = nil) async throws -> FactoryStatusSnapshot + { + let trimmed = apiKey.trimmingCharacters(in: .whitespacesAndNewlines) + guard !trimmed.isEmpty else { + throw FactoryStatusProbeError.missingAPIKey + } + let log: (String) -> Void = { msg in logger?("[factory] \(msg)") } + log("Using Factory API key") + return try await self.fetchWithBearerToken(trimmed, logger: log) + } + + func fetchWithBearerToken( + _ bearerToken: String, + logger: (String) -> Void) async throws -> FactoryStatusSnapshot + { + let candidates = [Self.apiBaseURL, self.baseURL] + var lastError: Error? + var preferredAuthError: FactoryStatusProbeError? + for baseURL in candidates { + if baseURL != Self.apiBaseURL { + logger("Trying Factory bearer base URL: \(baseURL.host ?? baseURL.absoluteString)") + } + do { + return try await self.fetchWithCookieHeader( + "", + bearerToken: bearerToken, + baseURL: baseURL) + } catch { + if preferredAuthError == nil, + let authError = Self.preferredBearerAuthError(from: error) + { + preferredAuthError = authError + } + lastError = error + } + } + // Prefer 401/403 auth failures over later host noise (e.g. 404) so API-key Auto mode + // can map to unauthorizedAPIKey and fall back to cookies/WorkOS. + if let preferredAuthError { throw preferredAuthError } + if let lastError { throw lastError } + throw FactoryStatusProbeError.notLoggedIn + } + + private static func preferredBearerAuthError(from error: Error) -> FactoryStatusProbeError? { + guard let factoryError = error as? FactoryStatusProbeError else { return nil } + switch factoryError { + case .notLoggedIn: + return factoryError + case let .networkError(message) + where message.contains("HTTP 401") || message.contains("HTTP 403"): + return factoryError + default: + return nil + } + } +} diff --git a/Sources/CodexBarCore/Providers/Factory/FactoryStatusProbe.swift b/Sources/CodexBarCore/Providers/Factory/FactoryStatusProbe.swift new file mode 100644 index 0000000..c7ea7bd --- /dev/null +++ b/Sources/CodexBarCore/Providers/Factory/FactoryStatusProbe.swift @@ -0,0 +1,1485 @@ +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif +#if os(macOS) +import SweetCookieKit + +private let factoryCookieImportOrder: BrowserCookieImportOrder = + ProviderDefaults.metadata[.factory]?.browserCookieOrder ?? Browser.defaultImportOrder + +// MARK: - Factory Cookie Importer + +/// Imports Factory session cookies from browser cookies. +public enum FactoryCookieImporter { + private static let cookieClient = BrowserCookieClient() + private static let sessionCookieNames: Set = [ + "wos-session", + "__Secure-next-auth.session-token", + "next-auth.session-token", + "__Secure-authjs.session-token", + "__Host-authjs.csrf-token", + "authjs.session-token", + "session", + "access-token", + ] + + private static let authSessionCookieNames: Set = [ + "__Secure-next-auth.session-token", + "next-auth.session-token", + "__Secure-authjs.session-token", + "authjs.session-token", + ] + private static let appBaseURL = URL(string: "https://app.factory.ai")! + private static let authBaseURL = URL(string: "https://auth.factory.ai")! + private static let apiBaseURL = URL(string: "https://api.factory.ai")! + + public struct SessionInfo: Sendable { + public let cookies: [HTTPCookie] + public let sourceLabel: String + + public init(cookies: [HTTPCookie], sourceLabel: String) { + self.cookies = cookies + self.sourceLabel = sourceLabel + } + + public var cookieHeader: String { + self.cookies.map { "\($0.name)=\($0.value)" }.joined(separator: "; ") + } + } + + /// Returns all Factory sessions across supported browsers. + public static func importSessions( + browserDetection: BrowserDetection, + logger: ((String) -> Void)? = nil) throws -> [SessionInfo] + { + let log: (String) -> Void = { msg in logger?("[factory-cookie] \(msg)") } + var sessions: [SessionInfo] = [] + + // Filter to cookie-eligible browsers to avoid unnecessary keychain prompts + let installedBrowsers = factoryCookieImportOrder.cookieImportCandidates(using: browserDetection) + for browserSource in installedBrowsers { + do { + let perSource = try self.importSessions(from: browserSource, logger: logger) + sessions.append(contentsOf: perSource) + } catch { + BrowserCookieAccessGate.recordIfNeeded(error) + log("\(browserSource.displayName) cookie import failed: \(error.localizedDescription)") + } + } + + guard !sessions.isEmpty else { + throw FactoryStatusProbeError.noSessionCookie + } + return sessions + } + + public static func importSessions( + from browserSource: Browser, + logger: ((String) -> Void)? = nil) throws -> [SessionInfo] + { + let log: (String) -> Void = { msg in logger?("[factory-cookie] \(msg)") } + let cookieDomains = ["factory.ai", "app.factory.ai", "auth.factory.ai"] + let query = BrowserCookieQuery(domains: cookieDomains) + let sources = try Self.cookieClient.codexBarRecords( + matching: query, + in: browserSource, + logger: log) + + var sessions: [SessionInfo] = [] + for source in sources where !source.records.isEmpty { + let httpCookies = BrowserCookieClient.makeHTTPCookies(source.records, origin: query.origin) + if httpCookies.contains(where: { Self.sessionCookieNames.contains($0.name) }) { + log("Found \(httpCookies.count) Factory cookies in \(source.label)") + log("\(source.label) cookie names: \(self.cookieNames(from: httpCookies))") + if let token = httpCookies.first(where: { $0.name == "access-token" })?.value { + let hint = token.contains(".") ? "jwt" : "opaque" + log("\(source.label) access-token cookie: \(token.count) chars (\(hint))") + } + if let token = httpCookies.first(where: { self.authSessionCookieNames.contains($0.name) })?.value { + let hint = token.contains(".") ? "jwt" : "opaque" + log("\(source.label) session cookie: \(token.count) chars (\(hint))") + } + sessions.append(SessionInfo(cookies: httpCookies, sourceLabel: source.label)) + } else { + log("\(source.label) cookies found, but no Factory session cookie present") + } + } + return sessions + } + + /// Attempts to import Factory cookies using the standard browser import order. + public static func importSession( + browserDetection: BrowserDetection, + logger: ((String) -> Void)? = nil) throws -> SessionInfo + { + let sessions = try self.importSessions(browserDetection: browserDetection, logger: logger) + guard let first = sessions.first else { + throw FactoryStatusProbeError.noSessionCookie + } + return first + } + + /// Check if Factory session cookies are available + public static func hasSession(browserDetection: BrowserDetection, logger: ((String) -> Void)? = nil) -> Bool { + do { + return try !(self.importSessions(browserDetection: browserDetection, logger: logger)).isEmpty + } catch { + return false + } + } + + private static func cookieNames(from cookies: [HTTPCookie]) -> String { + let names = Set(cookies.map { "\($0.name)@\($0.domain)" }).sorted() + return names.joined(separator: ", ") + } +} + +#endif + +// MARK: - Factory API Models + +public struct FactoryAuthResponse: Codable, Sendable { + public let featureFlags: FactoryFeatureFlags? + public let organization: FactoryOrganization? + public let userProfile: FactoryUserProfile? +} + +public struct FactoryUserProfile: Codable, Sendable { + public let id: String? + public let email: String? +} + +public struct FactoryFeatureFlags: Codable, Sendable { + public let flags: [String: Bool]? + public let configs: [String: AnyCodable]? +} + +public struct FactoryOrganization: Codable, Sendable { + public let id: String? + public let name: String? + public let subscription: FactorySubscription? + + enum CodingKeys: String, CodingKey { + case id + case name + case subscription + } +} + +public struct FactorySubscription: Codable, Sendable { + public let factoryTier: String? + public let orbSubscription: FactoryOrbSubscription? +} + +public struct FactoryOrbSubscription: Codable, Sendable { + public let plan: FactoryPlan? + public let status: String? +} + +public struct FactoryPlan: Codable, Sendable { + public let name: String? + public let id: String? +} + +public struct FactoryUsageResponse: Codable, Sendable { + public let usage: FactoryUsageData? + public let source: String? + public let userId: String? +} + +public struct FactoryUsageData: Codable, Sendable { + public let startDate: Int64? + public let endDate: Int64? + public let standard: FactoryTokenUsage? + public let premium: FactoryTokenUsage? +} + +public struct FactoryTokenUsage: Codable, Sendable { + public let userTokens: Int64? + public let orgTotalTokensUsed: Int64? + public let totalAllowance: Int64? + public let usedRatio: Double? + public let orgOverageUsed: Int64? + public let basicAllowance: Int64? + public let orgOverageLimit: Int64? +} + +public struct FactoryBillingLimitsResponse: Codable, Sendable { + public let usesTokenRateLimitsBilling: Bool + public let limits: FactoryTokenRateLimits? + public let extraUsageBalanceCents: Int + public let overagePreference: String? + public let extraUsageAllowed: Bool + public let tokenRateLimitsRolloutEligible: Bool + + enum CodingKeys: String, CodingKey { + case usesTokenRateLimitsBilling + case limits + case extraUsageBalanceCents + case overagePreference + case extraUsageAllowed + case tokenRateLimitsRolloutEligible + } + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.usesTokenRateLimitsBilling = try container + .decodeIfPresent(Bool.self, forKey: .usesTokenRateLimitsBilling) ?? false + self.limits = try container.decodeIfPresent(FactoryTokenRateLimits.self, forKey: .limits) + self.extraUsageBalanceCents = try container.decodeIfPresent(Int.self, forKey: .extraUsageBalanceCents) ?? 0 + self.overagePreference = try container.decodeIfPresent(String.self, forKey: .overagePreference) + self.extraUsageAllowed = try container.decodeIfPresent(Bool.self, forKey: .extraUsageAllowed) ?? false + self.tokenRateLimitsRolloutEligible = try container + .decodeIfPresent(Bool.self, forKey: .tokenRateLimitsRolloutEligible) ?? false + } +} + +public struct FactoryTokenRateLimits: Codable, Sendable { + public let standard: FactoryLimitPool + public let core: FactoryLimitPool? +} + +public struct FactoryLimitPool: Codable, Sendable { + public let fiveHour: FactoryBillingWindow + public let weekly: FactoryBillingWindow + public let monthly: FactoryBillingWindow + + public var hasUsageData: Bool { + [self.fiveHour, self.weekly, self.monthly].contains { + $0.usedPercent > 0 || $0.windowEnd != nil || $0.secondsRemaining != nil + } + } +} + +public struct FactoryBillingWindow: Codable, Sendable { + public let usedPercent: Double + public let windowEnd: FlexibleFactoryDate? + public let secondsRemaining: Double? + + public func resetAt(now: Date) -> Date? { + if let secondsRemaining, secondsRemaining > 0 { + return now.addingTimeInterval(secondsRemaining) + } + guard let windowEnd = self.windowEnd?.date, windowEnd > now else { + return nil + } + return windowEnd + } + + public func effectiveUsedPercent(now: Date) -> Double { + // Factory can leave stale values after short rolling windows expire. The web UI treats + // that state as reset, so mirror it here instead of showing expired usage. + if self.resetAt(now: now) == nil, self.windowEnd != nil, self.secondsRemaining == nil { + return 0 + } + return min(100, max(0, self.usedPercent)) + } + + public func rateWindow(windowMinutes: Int?, title: String, now: Date) -> RateWindow { + let reset = self.resetAt(now: now) + return RateWindow( + usedPercent: self.effectiveUsedPercent(now: now), + windowMinutes: windowMinutes, + resetsAt: reset, + resetDescription: reset.map { FactoryStatusSnapshot.formatResetDate($0) }) + } +} + +public struct FlexibleFactoryDate: Codable, Sendable { + public let date: Date + + public init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + if let seconds = try? container.decode(Double.self) { + self.date = Date(timeIntervalSince1970: seconds > 1e12 ? seconds / 1000.0 : seconds) + return + } + let string = try container.decode(String.self) + if let numeric = Double(string) { + self.date = Date(timeIntervalSince1970: numeric > 1e12 ? numeric / 1000.0 : numeric) + return + } + + let fractional = ISO8601DateFormatter() + fractional.formatOptions = [.withInternetDateTime, .withFractionalSeconds] + if let parsed = fractional.date(from: string) ?? ISO8601DateFormatter().date(from: string) { + self.date = parsed + return + } + throw DecodingError.dataCorruptedError(in: container, debugDescription: "Invalid Factory date") + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + try container.encode(self.date) + } +} + +/// Helper for encoding arbitrary JSON +public struct AnyCodable: Codable, Sendable { + public init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + if container.decodeNil() { + return + } + _ = try? container.decode([String: AnyCodable].self) + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + try container.encodeNil() + } +} + +// MARK: - Factory Status Snapshot + +public struct FactoryStatusSnapshot: Sendable { + /// Standard token usage (user) + public let standardUserTokens: Int64 + /// Standard token usage (org total) + public let standardOrgTokens: Int64 + /// Standard token allowance + public let standardAllowance: Int64 + /// Standard usage ratio from API (0.0-1.0), preferred over manual calculation + /// Falls back to percent-scale (0.0-100.0) when allowance is unavailable. + public let standardUsedRatio: Double? + /// Premium token usage (user) + public let premiumUserTokens: Int64 + /// Premium token usage (org total) + public let premiumOrgTokens: Int64 + /// Premium token allowance + public let premiumAllowance: Int64 + /// Premium usage ratio from API (0.0-1.0), preferred over manual calculation + /// Falls back to percent-scale (0.0-100.0) when allowance is unavailable. + public let premiumUsedRatio: Double? + /// Billing period start + public let periodStart: Date? + /// Billing period end + public let periodEnd: Date? + /// Plan name + public let planName: String? + /// Factory tier (enterprise, team, etc.) + public let tier: String? + /// Organization name + public let organizationName: String? + /// User email + public let accountEmail: String? + /// User ID + public let userId: String? + /// Raw JSON for debugging + public let rawJSON: String? + /// New Factory token-rate-limits billing payload, when enabled for the account. + public let tokenRateLimits: FactoryTokenRateLimits? + public let extraUsageBalanceCents: Int? + public let overagePreference: String? + + public init( + standardUserTokens: Int64, + standardOrgTokens: Int64, + standardAllowance: Int64, + standardUsedRatio: Double? = nil, + premiumUserTokens: Int64, + premiumOrgTokens: Int64, + premiumAllowance: Int64, + premiumUsedRatio: Double? = nil, + periodStart: Date?, + periodEnd: Date?, + planName: String?, + tier: String?, + organizationName: String?, + accountEmail: String?, + userId: String?, + rawJSON: String?, + tokenRateLimits: FactoryTokenRateLimits? = nil, + extraUsageBalanceCents: Int? = nil, + overagePreference: String? = nil) + { + self.standardUserTokens = standardUserTokens + self.standardOrgTokens = standardOrgTokens + self.standardAllowance = standardAllowance + self.standardUsedRatio = standardUsedRatio + self.premiumUserTokens = premiumUserTokens + self.premiumOrgTokens = premiumOrgTokens + self.premiumAllowance = premiumAllowance + self.premiumUsedRatio = premiumUsedRatio + self.periodStart = periodStart + self.periodEnd = periodEnd + self.planName = planName + self.tier = tier + self.organizationName = organizationName + self.accountEmail = accountEmail + self.userId = userId + self.rawJSON = rawJSON + self.tokenRateLimits = tokenRateLimits + self.extraUsageBalanceCents = extraUsageBalanceCents + self.overagePreference = overagePreference + } + + /// Convert to UsageSnapshot for the common provider interface + public func toUsageSnapshot() -> UsageSnapshot { + if let tokenRateLimits { + return self.tokenRateLimitsUsageSnapshot(from: tokenRateLimits) + } + + // Primary: Standard tokens used (as percentage of allowance, capped reasonably) + let standardPercent = self.calculateUsagePercent( + used: self.standardUserTokens, + allowance: self.standardAllowance, + apiRatio: self.standardUsedRatio) + + let primary = RateWindow( + usedPercent: standardPercent, + windowMinutes: nil, + resetsAt: self.periodEnd, + resetDescription: self.periodEnd.map { Self.formatResetDate($0) }) + + // Secondary: Premium tokens used + let premiumPercent = self.calculateUsagePercent( + used: self.premiumUserTokens, + allowance: self.premiumAllowance, + apiRatio: self.premiumUsedRatio) + + let secondary = RateWindow( + usedPercent: premiumPercent, + windowMinutes: nil, + resetsAt: self.periodEnd, + resetDescription: self.periodEnd.map { Self.formatResetDate($0) }) + + // Format login method as tier + plan + let loginMethod: String? = { + var parts: [String] = [] + if let tier = self.tier, !tier.isEmpty { + parts.append("Factory \(tier.capitalized)") + } + if let plan = self.planName, !plan.isEmpty, !plan.lowercased().contains("factory") { + parts.append(plan) + } + return parts.isEmpty ? nil : parts.joined(separator: " - ") + }() + + let identity = ProviderIdentitySnapshot( + providerID: .factory, + accountEmail: self.accountEmail, + accountOrganization: self.organizationName, + loginMethod: loginMethod) + return UsageSnapshot( + primary: primary, + secondary: secondary, + tertiary: nil, + providerCost: nil, + updatedAt: Date(), + identity: identity) + } + + private func tokenRateLimitsUsageSnapshot(from limits: FactoryTokenRateLimits) -> UsageSnapshot { + let now = Date() + let primary = limits.standard.fiveHour.rateWindow(windowMinutes: 5 * 60, title: "5h", now: now) + let secondary = limits.standard.weekly.rateWindow(windowMinutes: 7 * 24 * 60, title: "7-day", now: now) + let tertiary = limits.standard.monthly.rateWindow(windowMinutes: nil, title: "Monthly", now: now) + + let coreWindows: [NamedRateWindow]? = if let core = limits.core, core.hasUsageData { + [ + NamedRateWindow( + id: "factory-core-5h", + title: "Core 5h", + window: core.fiveHour.rateWindow(windowMinutes: 5 * 60, title: "Core 5h", now: now)), + NamedRateWindow( + id: "factory-core-7d", + title: "Core 7-day", + window: core.weekly.rateWindow(windowMinutes: 7 * 24 * 60, title: "Core 7-day", now: now)), + NamedRateWindow( + id: "factory-core-monthly", + title: "Core Monthly", + window: core.monthly.rateWindow(windowMinutes: nil, title: "Core Monthly", now: now)), + ] + } else { + nil + } + + let loginMethod: String? = { + var parts: [String] = [] + if let tier = self.tier, !tier.isEmpty { + parts.append("Factory \(tier.capitalized)") + } + if let plan = self.planName, !plan.isEmpty, !plan.lowercased().contains("factory") { + parts.append(plan) + } + if let overagePreference, !overagePreference.isEmpty { + parts.append("Fallback: \(overagePreference)") + } + return parts.isEmpty ? nil : parts.joined(separator: " - ") + }() + + let identity = ProviderIdentitySnapshot( + providerID: .factory, + accountEmail: self.accountEmail, + accountOrganization: self.organizationName, + loginMethod: loginMethod) + let providerCost = self.extraUsageBalanceCents.map { + ProviderCostSnapshot( + used: Double($0) / 100.0, + limit: 0, + currencyCode: "USD", + period: "Extra usage balance", + updatedAt: now) + } + return UsageSnapshot( + primary: primary, + secondary: secondary, + tertiary: tertiary, + extraRateWindows: coreWindows, + providerCost: providerCost, + updatedAt: now, + identity: identity) + } + + private func calculateUsagePercent(used: Int64, allowance: Int64, apiRatio: Double?) -> Double { + // Prefer API-provided ratio when available and valid. + // This handles plan-specific limits correctly on the server side, + // avoiding issues with missing/sentinel values in totalAllowance. + let unlimitedThreshold: Int64 = 1_000_000_000_000 + if let ratio = apiRatio, + !(ratio == 0 && used > 0 && allowance > 0 && allowance <= unlimitedThreshold), + let percent = Self.percentFromAPIRatio(ratio, allowance: allowance, unlimitedThreshold: unlimitedThreshold) + { + return percent + } + + // Fallback: calculate from used/allowance. + // Treat very large allowances (> 1 trillion) as unlimited. + if allowance > unlimitedThreshold { + // For unlimited, show a token count-based pseudo-percentage (capped at 100%). + // Use 100M tokens as a reference point for "100%". + let referenceTokens: Double = 100_000_000 + return min(100, Double(used) / referenceTokens * 100) + } + guard allowance > 0 else { return 0 } + return min(100, Double(used) / Double(allowance) * 100) + } + + private static func percentFromAPIRatio( + _ ratio: Double, + allowance: Int64, + unlimitedThreshold: Int64) -> Double? + { + guard ratio.isFinite else { return nil } + + // Primary: ratio scale (0.0 - 1.0). Clamp to account for rounding. + if ratio >= -0.001, ratio <= 1.001 { + return min(100, max(0, ratio * 100)) + } + + // TODO: Confirm usedRatio contract (0.0-1.0 vs 0.0-100.0) and tighten this fallback. + // Secondary: percent scale (0.0 - 100.0), only when allowance is missing/unreliable. + // This avoids misinterpreting slightly-over-1 ratios when we can calculate locally. + let allowanceIsReliable = allowance > 0 && allowance <= unlimitedThreshold + if !allowanceIsReliable, ratio >= -0.1, ratio <= 100.1 { + return min(100, max(0, ratio)) + } + + return nil + } + + static func formatResetDate(_ date: Date) -> String { + let formatter = DateFormatter() + formatter.dateFormat = "MMM d 'at' h:mma" + formatter.locale = Locale(identifier: "en_US_POSIX") + return "Resets " + formatter.string(from: date) + } +} + +// MARK: - Factory Status Probe + +public struct FactoryStatusProbe: Sendable { + public let baseURL: URL + public var timeout: TimeInterval = 15.0 + private static let staleTokenCookieNames: Set = [ + "access-token", + "__recent_auth", + ] + private static let sessionCookieNames: Set = [ + "session", + "wos-session", + ] + private static let authSessionCookieNames: Set = [ + "__Secure-next-auth.session-token", + "next-auth.session-token", + "__Secure-authjs.session-token", + "authjs.session-token", + ] + static let appBaseURL = URL(string: "https://app.factory.ai")! + static let authBaseURL = URL(string: "https://auth.factory.ai")! + static let apiBaseURL = URL(string: "https://api.factory.ai")! + private static let workosClientIDs = [ + "client_01HXRMBQ9BJ3E7QSTQ9X2PHVB7", + "client_01HNM792M5G5G1A2THWPXKFMXB", + ] + + private struct WorkOSAuthResponse: Decodable { + let access_token: String + let refresh_token: String? + let organization_id: String? + } + + private let browserDetection: BrowserDetection + private let transport: any ProviderHTTPTransport + + public init( + baseURL: URL = URL(string: "https://app.factory.ai")!, + timeout: TimeInterval = 15.0, + browserDetection: BrowserDetection, + transport: any ProviderHTTPTransport = ProviderHTTPClient.shared) + { + self.baseURL = baseURL + self.timeout = timeout + self.browserDetection = browserDetection + self.transport = transport + } + + /// Fetch Factory usage using browser cookies with fallback to stored session. + public func fetch( + cookieHeaderOverride: String? = nil, + logger: ((String) -> Void)? = nil) async throws -> FactoryStatusSnapshot + { + #if os(macOS) + let log: (String) -> Void = { msg in logger?("[factory] \(msg)") } + var lastError: Error? + + let manualOverride = cookieHeaderOverride?.trimmingCharacters(in: .whitespacesAndNewlines) + if manualOverride?.isEmpty == false { + guard let override = Self.manualCredentials(from: manualOverride) else { + throw FactoryStatusProbeError.noSessionCookie + } + if let cookieHeader = override.cookieHeader { + log("Using manual cookie header") + let candidates = [ + self.baseURL, + Self.authBaseURL, + Self.apiBaseURL, + ] + for baseURL in candidates { + do { + return try await self.fetchWithCookieHeader( + cookieHeader, + bearerToken: override.bearerToken, + baseURL: baseURL) + } catch { + lastError = error + } + } + } + if let bearerToken = override.bearerToken { + log("Using manual Factory bearer token") + return try await self.fetchWithBearerToken(bearerToken, logger: log) + } + if let lastError { throw lastError } + throw FactoryStatusProbeError.noSessionCookie + } + + if let cached = CookieHeaderCache.load(provider: .factory), + !cached.cookieHeader.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty + { + log("Using cached cookie header from \(cached.sourceLabel)") + let bearer = Self.bearerToken(fromHeader: cached.cookieHeader) + do { + return try await self.fetchWithCookieHeader( + cached.cookieHeader, + bearerToken: bearer, + baseURL: self.baseURL) + } catch { + if case FactoryStatusProbeError.notLoggedIn = error { + CookieHeaderCache.clear(provider: .factory) + } + lastError = error + } + } + + // Filter to only installed browsers to avoid unnecessary keychain prompts + let installedChromiumAndFirefox = [.chrome, .firefox].cookieImportCandidates(using: self.browserDetection) + + let attempts: [() async -> FetchAttemptResult] = [ + { await self.attemptStoredCookies(logger: log) }, + { await self.attemptStoredBearer(logger: log) }, + { await self.attemptStoredRefreshToken(logger: log) }, + { await self.attemptLocalStorageTokens(logger: log) }, + { await self.attemptBrowserCookies(logger: log, sources: [.safari]) }, + { await self.attemptWorkOSCookies(logger: log, sources: [.safari]) }, + { await self.attemptBrowserCookies(logger: log, sources: installedChromiumAndFirefox) }, + { await self.attemptWorkOSCookies(logger: log, sources: installedChromiumAndFirefox) }, + ] + + for attempt in attempts { + switch await attempt() { + case let .success(snapshot): + return snapshot + case let .failure(error): + lastError = error + case .skipped: + continue + } + } + + if let lastError { throw lastError } + throw FactoryStatusProbeError.noSessionCookie + #else + _ = cookieHeaderOverride + _ = logger + throw FactoryStatusProbeError.notSupported + #endif + } + + #if os(macOS) + private enum FetchAttemptResult { + case success(FactoryStatusSnapshot) + case failure(Error) + case skipped + } + + private func attemptBrowserCookies( + logger: @escaping (String) -> Void, + sources: [Browser]) async -> FetchAttemptResult + { + do { + var lastError: Error? + for browserSource in sources { + let sessions = try FactoryCookieImporter.importSessions(from: browserSource, logger: logger) + for session in sessions { + logger("Using cookies from \(session.sourceLabel)") + do { + let snapshot = try await self.fetchWithCookies(session.cookies, logger: logger) + await FactorySessionStore.shared.setCookies(session.cookies) + CookieHeaderCache.store( + provider: .factory, + cookieHeader: session.cookieHeader, + sourceLabel: session.sourceLabel) + return .success(snapshot) + } catch { + lastError = error + logger("Browser session fetch failed for \(session.sourceLabel): \(error.localizedDescription)") + } + } + } + if let lastError { return .failure(lastError) } + return .skipped + } catch { + BrowserCookieAccessGate.recordIfNeeded(error) + logger("Browser cookie import failed: \(error.localizedDescription)") + return .failure(error) + } + } + + private func attemptStoredCookies(logger: (String) -> Void) async -> FetchAttemptResult { + let storedCookies = await FactorySessionStore.shared.getCookies() + guard !storedCookies.isEmpty else { return .skipped } + logger("Using stored session cookies") + do { + return try await .success(self.fetchWithCookies(storedCookies, logger: logger)) + } catch { + if case FactoryStatusProbeError.notLoggedIn = error { + await FactorySessionStore.shared.clearCookies() + logger("Stored session cookies invalid, cleared") + } else { + logger("Stored session failed: \(error.localizedDescription)") + } + return .failure(error) + } + } + + private func attemptStoredBearer(logger: (String) -> Void) async -> FetchAttemptResult { + guard let bearerToken = await FactorySessionStore.shared.getBearerToken() else { return .skipped } + logger("Using stored Factory bearer token") + do { + return try await .success(self.fetchWithBearerToken(bearerToken, logger: logger)) + } catch { + return .failure(error) + } + } + + private func attemptStoredRefreshToken(logger: (String) -> Void) async -> FetchAttemptResult { + guard let refreshToken = await FactorySessionStore.shared.getRefreshToken(), + !refreshToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty + else { + return .skipped + } + logger("Using stored WorkOS refresh token") + do { + return try await .success(self.fetchWithWorkOSRefreshToken( + refreshToken, + organizationID: nil, + logger: logger)) + } catch { + if self.isInvalidGrant(error) { + await FactorySessionStore.shared.setRefreshToken(nil) + } else if case FactoryStatusProbeError.noSessionCookie = error { + await FactorySessionStore.shared.setRefreshToken(nil) + } + return .failure(error) + } + } + + private func attemptLocalStorageTokens(logger: @escaping (String) -> Void) async -> FetchAttemptResult { + let workosTokens = FactoryLocalStorageImporter.importWorkOSTokens( + browserDetection: self.browserDetection, + logger: logger) + guard !workosTokens.isEmpty else { return .skipped } + var lastError: Error? + for token in workosTokens { + guard !token.refreshToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else { + continue + } + logger("Using WorkOS refresh token from \(token.sourceLabel)") + if let accessToken = token.accessToken { + do { + await FactorySessionStore.shared.setBearerToken(accessToken) + return try await .success(self.fetchWithBearerToken(accessToken, logger: logger)) + } catch { + lastError = error + } + } + do { + return try await .success(self.fetchWithWorkOSRefreshToken( + token.refreshToken, + organizationID: token.organizationID, + logger: logger)) + } catch { + if self.isInvalidGrant(error) { + await FactorySessionStore.shared.setRefreshToken(nil) + } + lastError = error + } + } + if let lastError { return .failure(lastError) } + return .skipped + } + + private func attemptWorkOSCookies( + logger: @escaping (String) -> Void, + sources: [Browser]) async -> FetchAttemptResult + { + let log: (String) -> Void = { msg in logger("[factory-workos] \(msg)") } + var lastError: Error? + + for browserSource in sources { + do { + let query = BrowserCookieQuery(domains: ["workos.com"]) + let sources = try BrowserCookieClient().codexBarRecords( + matching: query, + in: browserSource, + logger: log) + for source in sources where !source.records.isEmpty { + let cookies = BrowserCookieClient.makeHTTPCookies(source.records, origin: query.origin) + guard !cookies.isEmpty else { continue } + log("Using WorkOS cookies from \(source.label)") + do { + let auth = try await self.fetchWorkOSAccessTokenWithCookies( + cookies: cookies, + logger: logger) + await FactorySessionStore.shared.setBearerToken(auth.access_token) + if let refreshToken = auth.refresh_token { + await FactorySessionStore.shared.setRefreshToken(refreshToken) + } + return try await .success(self.fetchWithBearerToken(auth.access_token, logger: logger)) + } catch { + lastError = error + log("WorkOS cookie auth failed for \(source.label): \(error.localizedDescription)") + } + } + } catch { + BrowserCookieAccessGate.recordIfNeeded(error) + log("\(browserSource.displayName) WorkOS cookie import failed: \(error.localizedDescription)") + lastError = error + } + } + + if let lastError { return .failure(lastError) } + return .skipped + } + + private func fetchWithWorkOSRefreshToken( + _ refreshToken: String, + organizationID: String?, + logger: (String) -> Void) async throws -> FactoryStatusSnapshot + { + let auth = try await self.fetchWorkOSAccessToken( + refreshToken: refreshToken, + organizationID: organizationID) + await FactorySessionStore.shared.setBearerToken(auth.access_token) + if let newRefresh = auth.refresh_token { + await FactorySessionStore.shared.setRefreshToken(newRefresh) + } + return try await self.fetchWithBearerToken(auth.access_token, logger: logger) + } + + private func fetchWithCookies( + _ cookies: [HTTPCookie], + logger: (String) -> Void) async throws -> FactoryStatusSnapshot + { + let candidates = Self.baseURLCandidates(default: self.baseURL, cookies: cookies) + var lastError: Error? + + for baseURL in candidates { + if baseURL != self.baseURL { + logger("Trying Factory base URL: \(baseURL.host ?? baseURL.absoluteString)") + } + do { + return try await self.fetchWithCookies(cookies, baseURL: baseURL, logger: logger) + } catch { + lastError = error + } + } + + if let lastError { throw lastError } + throw FactoryStatusProbeError.noSessionCookie + } + + private func fetchWithCookies( + _ cookies: [HTTPCookie], + baseURL: URL, + logger: (String) -> Void) async throws -> FactoryStatusSnapshot + { + let header = Self.cookieHeader(from: cookies) + let bearerToken = Self.bearerToken(from: cookies) + do { + return try await self.fetchWithCookieHeader(header, bearerToken: bearerToken, baseURL: baseURL) + } catch let error as FactoryStatusProbeError { + if case .notLoggedIn = error, bearerToken != nil { + logger("Retrying without Authorization header") + return try await self.fetchWithCookieHeader(header, bearerToken: nil, baseURL: baseURL) + } + guard case let .networkError(message) = error, + message.contains("HTTP 409") + else { + throw error + } + + var lastError: Error? = error + if bearerToken != nil { + logger("Retrying without Authorization header (HTTP 409)") + do { + return try await self.fetchWithCookieHeader(header, bearerToken: nil, baseURL: baseURL) + } catch { + lastError = error + } + } + + let retries: [(String, (HTTPCookie) -> Bool)] = [ + ("Retrying without access-token cookies", { !Self.staleTokenCookieNames.contains($0.name) }), + ("Retrying without session cookies", { !Self.sessionCookieNames.contains($0.name) }), + ("Retrying without access-token/session cookies", { + !Self.staleTokenCookieNames.contains($0.name) && !Self.sessionCookieNames.contains($0.name) + }), + ] + + for (label, predicate) in retries { + let filtered = cookies.filter(predicate) + guard filtered.count < cookies.count else { continue } + logger(label) + do { + let filteredBearer = Self.bearerToken(from: filtered) + return try await self.fetchWithCookieHeader( + Self.cookieHeader(from: filtered), + bearerToken: filteredBearer, + baseURL: baseURL) + } catch let retryError as FactoryStatusProbeError { + switch retryError { + case let .networkError(retryMessage) + where retryMessage.contains("HTTP 409") && + retryMessage.localizedCaseInsensitiveContains("stale token"): + lastError = retryError + continue + case .notLoggedIn: + lastError = retryError + continue + default: + throw retryError + } + } + } + + let authOnly = cookies.filter { + Self.authSessionCookieNames.contains($0.name) || $0.name == "__Host-authjs.csrf-token" + } + if !authOnly.isEmpty, authOnly.count < cookies.count { + logger("Retrying with auth session cookies only") + do { + return try await self.fetchWithCookieHeader( + Self.cookieHeader(from: authOnly), + bearerToken: Self.bearerToken(from: authOnly), + baseURL: baseURL) + } catch let retryError as FactoryStatusProbeError { + lastError = retryError + } + } + + if let lastError { throw lastError } + throw error + } catch { + throw error + } + } + + private static func cookieHeader(from cookies: [HTTPCookie]) -> String { + cookies.map { "\($0.name)=\($0.value)" }.joined(separator: "; ") + } + + #endif + + func fetchWithCookieHeader( + _ cookieHeader: String, + bearerToken: String?, + baseURL: URL) async throws -> FactoryStatusSnapshot + { + // First fetch auth info to get user ID and org info + let authInfo = try await self.fetchAuthInfo( + cookieHeader: cookieHeader, + bearerToken: bearerToken, + baseURL: baseURL) + + let userId = factoryUserIdFromAuth(authInfo) + ?? factoryUserIdFromBearerToken(bearerToken) + + if let billingLimits = try await self.fetchBillingLimitsIfAvailable( + cookieHeader: cookieHeader, + bearerToken: bearerToken), + billingLimits.usesTokenRateLimitsBilling, + let tokenRateLimits = billingLimits.limits + { + return self.buildTokenRateLimitsSnapshot( + authInfo: authInfo, + billingLimits: billingLimits, + tokenRateLimits: tokenRateLimits, + userId: userId) + } + + // Fetch usage data + let usageData = try await self.fetchUsage( + cookieHeader: cookieHeader, + bearerToken: bearerToken, + userId: userId, + baseURL: baseURL) + + return self.buildSnapshot(authInfo: authInfo, usageData: usageData, userId: userId) + } + + private func fetchBillingLimitsIfAvailable( + cookieHeader: String, + bearerToken: String?) async throws -> FactoryBillingLimitsResponse? + { + let url = Self.apiBaseURL.appendingPathComponent("/api/billing/limits") + var request = URLRequest(url: url) + request.timeoutInterval = self.timeout + request.httpMethod = "GET" + request.setValue("application/json", forHTTPHeaderField: "Accept") + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + request.setValue("https://app.factory.ai", forHTTPHeaderField: "Origin") + request.setValue("https://app.factory.ai/", forHTTPHeaderField: "Referer") + request.setValue("web-app", forHTTPHeaderField: "x-factory-client") + if !cookieHeader.isEmpty { + request.setValue(cookieHeader, forHTTPHeaderField: "Cookie") + } + if let bearerToken { + request.setValue("Bearer \(bearerToken)", forHTTPHeaderField: "Authorization") + } + + let data: Data + let response: URLResponse + do { + (data, response) = try await self.transport.data(for: request) + } catch { + return nil + } + + guard let httpResponse = response as? HTTPURLResponse else { + return nil + } + + guard httpResponse.statusCode == 200 else { + return nil + } + + return try? JSONDecoder().decode(FactoryBillingLimitsResponse.self, from: data) + } + + private func fetchAuthInfo( + cookieHeader: String, + bearerToken: String?, + baseURL: URL) async throws -> FactoryAuthResponse + { + let url = baseURL.appendingPathComponent("/api/app/auth/me") + var request = URLRequest(url: url) + request.timeoutInterval = self.timeout + request.httpMethod = "GET" + request.setValue("application/json", forHTTPHeaderField: "Accept") + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + request.setValue("https://app.factory.ai", forHTTPHeaderField: "Origin") + request.setValue("https://app.factory.ai/", forHTTPHeaderField: "Referer") + if !cookieHeader.isEmpty { + request.setValue(cookieHeader, forHTTPHeaderField: "Cookie") + } + request.setValue("web-app", forHTTPHeaderField: "x-factory-client") + if let bearerToken { + request.setValue("Bearer \(bearerToken)", forHTTPHeaderField: "Authorization") + } + + let (data, response) = try await self.transport.data(for: request) + + guard let httpResponse = response as? HTTPURLResponse else { + throw FactoryStatusProbeError.networkError("Invalid response") + } + + if httpResponse.statusCode == 401 { + throw FactoryStatusProbeError.notLoggedIn + } + + if httpResponse.statusCode == 403 { + let body = String(data: data, encoding: .utf8)? + .trimmingCharacters(in: .whitespacesAndNewlines) ?? "" + let snippet = body.isEmpty ? "" : ": \(body.prefix(200))" + throw FactoryStatusProbeError.networkError("HTTP 403 Forbidden\(snippet)") + } + + guard httpResponse.statusCode == 200 else { + let body = String(data: data, encoding: .utf8)? + .trimmingCharacters(in: .whitespacesAndNewlines) ?? "" + let snippet = body.isEmpty ? "" : ": \(body.prefix(200))" + throw FactoryStatusProbeError.networkError("HTTP \(httpResponse.statusCode)\(snippet)") + } + + do { + let decoder = JSONDecoder() + return try decoder.decode(FactoryAuthResponse.self, from: data) + } catch { + let rawJSON = String(data: data, encoding: .utf8) ?? "" + throw FactoryStatusProbeError + .parseFailed("Auth decode failed: \(error.localizedDescription). Raw: \(rawJSON.prefix(200))") + } + } + + private func fetchUsage( + cookieHeader: String, + bearerToken: String?, + userId: String?, + baseURL: URL) async throws -> FactoryUsageResponse + { + var components = URLComponents( + url: baseURL.appendingPathComponent("/api/organization/subscription/usage"), + resolvingAgainstBaseURL: false) + components?.queryItems = [ + URLQueryItem(name: "useCache", value: "true"), + ] + if let userId { + components?.queryItems?.append(URLQueryItem(name: "userId", value: userId)) + } + let url = components?.url ?? baseURL.appendingPathComponent("/api/organization/subscription/usage") + var request = URLRequest(url: url) + request.timeoutInterval = self.timeout + request.httpMethod = "GET" + request.setValue("application/json", forHTTPHeaderField: "Accept") + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + request.setValue("https://app.factory.ai", forHTTPHeaderField: "Origin") + request.setValue("https://app.factory.ai/", forHTTPHeaderField: "Referer") + if !cookieHeader.isEmpty { + request.setValue(cookieHeader, forHTTPHeaderField: "Cookie") + } + request.setValue("web-app", forHTTPHeaderField: "x-factory-client") + if let bearerToken { + request.setValue("Bearer \(bearerToken)", forHTTPHeaderField: "Authorization") + } + + let (data, response) = try await self.transport.data(for: request) + + guard let httpResponse = response as? HTTPURLResponse else { + throw FactoryStatusProbeError.networkError("Invalid response") + } + + if httpResponse.statusCode == 401 || httpResponse.statusCode == 403 { + throw FactoryStatusProbeError.notLoggedIn + } + + guard httpResponse.statusCode == 200 else { + let body = String(data: data, encoding: .utf8)? + .trimmingCharacters(in: .whitespacesAndNewlines) ?? "" + let snippet = body.isEmpty ? "" : ": \(body.prefix(200))" + throw FactoryStatusProbeError.networkError("HTTP \(httpResponse.statusCode)\(snippet)") + } + + do { + let decoder = JSONDecoder() + return try decoder.decode(FactoryUsageResponse.self, from: data) + } catch { + let rawJSON = String(data: data, encoding: .utf8) ?? "" + throw FactoryStatusProbeError + .parseFailed("Usage decode failed: \(error.localizedDescription). Raw: \(rawJSON.prefix(200))") + } + } + + #if os(macOS) + private static func baseURLCandidates(default baseURL: URL, cookies: [HTTPCookie]) -> [URL] { + let cookieDomains = Set( + cookies.map { + $0.domain.trimmingCharacters(in: CharacterSet(charactersIn: ".")) + }) + + var candidates: [URL] = [] + if cookieDomains.contains("auth.factory.ai") { + candidates.append(Self.authBaseURL) + } + candidates.append(Self.apiBaseURL) + candidates.append(Self.appBaseURL) + candidates.append(baseURL) + + var seen = Set() + return candidates.filter { url in + let key = url.absoluteString + if seen.contains(key) { return false } + seen.insert(key) + return true + } + } + + private static func bearerToken(from cookies: [HTTPCookie]) -> String? { + let accessToken = cookies.first(where: { $0.name == "access-token" })?.value + let sessionToken = cookies.first(where: { Self.authSessionCookieNames.contains($0.name) })?.value + let legacySession = cookies.first(where: { $0.name == "session" })?.value + + if let accessToken, accessToken.contains(".") { + return accessToken + } + if let sessionToken, sessionToken.contains(".") { + return sessionToken + } + if let legacySession, legacySession.contains(".") { + return legacySession + } + return accessToken ?? sessionToken + } + + private func fetchWorkOSAccessToken( + refreshToken: String, + organizationID: String?) async throws -> WorkOSAuthResponse + { + var lastError: Error? + for clientID in Self.workosClientIDs { + do { + return try await self.fetchWorkOSAccessToken( + refreshToken: refreshToken, + organizationID: organizationID, + clientID: clientID) + } catch { + lastError = error + } + } + if let lastError { throw lastError } + throw FactoryStatusProbeError.networkError("WorkOS auth failed") + } + + private func fetchWorkOSAccessToken( + refreshToken: String, + organizationID: String?, + clientID: String) async throws -> WorkOSAuthResponse + { + guard let url = URL(string: "https://api.workos.com/user_management/authenticate") else { + throw FactoryStatusProbeError.networkError("WorkOS auth URL unavailable") + } + + var request = URLRequest(url: url) + request.timeoutInterval = self.timeout + request.httpMethod = "POST" + request.setValue("application/json", forHTTPHeaderField: "Accept") + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + + var body: [String: Any] = [ + "client_id": clientID, + "grant_type": "refresh_token", + "refresh_token": refreshToken, + ] + if let organizationID { + body["organization_id"] = organizationID + } + request.httpBody = try JSONSerialization.data(withJSONObject: body, options: []) + + let (data, response) = try await self.transport.data(for: request) + guard let httpResponse = response as? HTTPURLResponse else { + throw FactoryStatusProbeError.networkError("Invalid WorkOS response") + } + + guard httpResponse.statusCode == 200 else { + if httpResponse.statusCode == 400, Self.isMissingWorkOSRefreshToken(data) { + throw FactoryStatusProbeError.noSessionCookie + } + let body = String(data: data, encoding: .utf8)? + .trimmingCharacters(in: .whitespacesAndNewlines) ?? "" + let snippet = body.isEmpty ? "" : ": \(body.prefix(200))" + throw FactoryStatusProbeError.networkError("WorkOS HTTP \(httpResponse.statusCode)\(snippet)") + } + + let decoder = JSONDecoder() + return try decoder.decode(WorkOSAuthResponse.self, from: data) + } + + private func fetchWorkOSAccessTokenWithCookies( + cookies: [HTTPCookie], + logger: (String) -> Void) async throws -> WorkOSAuthResponse + { + let cookieHeader = Self.cookieHeader(from: cookies) + guard !cookieHeader.isEmpty else { + throw FactoryStatusProbeError.networkError("Missing WorkOS cookies") + } + + var lastError: Error? + for clientID in Self.workosClientIDs { + do { + return try await self.fetchWorkOSAccessTokenWithCookies( + cookieHeader: cookieHeader, + organizationID: nil, + clientID: clientID) + } catch { + lastError = error + logger("WorkOS cookie auth failed for client \(clientID): \(error.localizedDescription)") + } + } + if let lastError { throw lastError } + throw FactoryStatusProbeError.networkError("WorkOS cookie auth failed") + } + + private func fetchWorkOSAccessTokenWithCookies( + cookieHeader: String, + organizationID: String?, + clientID: String) async throws -> WorkOSAuthResponse + { + guard let url = URL(string: "https://api.workos.com/user_management/authenticate") else { + throw FactoryStatusProbeError.networkError("WorkOS auth URL unavailable") + } + + var request = URLRequest(url: url) + request.timeoutInterval = self.timeout + request.httpMethod = "POST" + request.setValue("application/json", forHTTPHeaderField: "Accept") + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + request.setValue(cookieHeader, forHTTPHeaderField: "Cookie") + + var body: [String: Any] = [ + "client_id": clientID, + "grant_type": "refresh_token", + "useCookie": true, + ] + if let organizationID { + body["organization_id"] = organizationID + } + request.httpBody = try JSONSerialization.data(withJSONObject: body, options: []) + + let (data, response) = try await self.transport.data(for: request) + guard let httpResponse = response as? HTTPURLResponse else { + throw FactoryStatusProbeError.networkError("Invalid WorkOS response") + } + + guard httpResponse.statusCode == 200 else { + if httpResponse.statusCode == 400, Self.isMissingWorkOSRefreshToken(data) { + throw FactoryStatusProbeError.noSessionCookie + } + let bodyText = String(data: data, encoding: .utf8)? + .trimmingCharacters(in: .whitespacesAndNewlines) ?? "" + let snippet = bodyText.isEmpty ? "" : ": \(bodyText.prefix(200))" + throw FactoryStatusProbeError.networkError("WorkOS HTTP \(httpResponse.statusCode)\(snippet)") + } + + let decoder = JSONDecoder() + return try decoder.decode(WorkOSAuthResponse.self, from: data) + } + + private func isInvalidGrant(_ error: Error) -> Bool { + guard case let FactoryStatusProbeError.networkError(message) = error else { + return false + } + return message.localizedCaseInsensitiveContains("invalid_grant") + } + + static func isMissingWorkOSRefreshToken(_ data: Data) -> Bool { + guard let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else { + return false + } + guard let description = json["error_description"] as? String else { return false } + return description.localizedCaseInsensitiveContains("missing refresh token") + } + + #endif + + private func buildSnapshot( + authInfo: FactoryAuthResponse, + usageData: FactoryUsageResponse, + userId: String?) -> FactoryStatusSnapshot + { + let usage = usageData.usage + + let periodStart: Date? = usage?.startDate.map { Date(timeIntervalSince1970: TimeInterval($0) / 1000) } + let periodEnd: Date? = usage?.endDate.map { Date(timeIntervalSince1970: TimeInterval($0) / 1000) } + + return FactoryStatusSnapshot( + standardUserTokens: usage?.standard?.userTokens ?? 0, + standardOrgTokens: usage?.standard?.orgTotalTokensUsed ?? 0, + standardAllowance: usage?.standard?.totalAllowance ?? 0, + standardUsedRatio: usage?.standard?.usedRatio, + premiumUserTokens: usage?.premium?.userTokens ?? 0, + premiumOrgTokens: usage?.premium?.orgTotalTokensUsed ?? 0, + premiumAllowance: usage?.premium?.totalAllowance ?? 0, + premiumUsedRatio: usage?.premium?.usedRatio, + periodStart: periodStart, + periodEnd: periodEnd, + planName: authInfo.organization?.subscription?.orbSubscription?.plan?.name, + tier: authInfo.organization?.subscription?.factoryTier, + organizationName: authInfo.organization?.name, + accountEmail: nil, // Email is in JWT, not in auth response body + userId: userId ?? usageData.userId, + rawJSON: nil) + } + + private func buildTokenRateLimitsSnapshot( + authInfo: FactoryAuthResponse, + billingLimits: FactoryBillingLimitsResponse, + tokenRateLimits: FactoryTokenRateLimits, + userId: String?) -> FactoryStatusSnapshot + { + FactoryStatusSnapshot( + standardUserTokens: 0, + standardOrgTokens: 0, + standardAllowance: 0, + standardUsedRatio: nil, + premiumUserTokens: 0, + premiumOrgTokens: 0, + premiumAllowance: 0, + premiumUsedRatio: nil, + periodStart: nil, + periodEnd: nil, + planName: authInfo.organization?.subscription?.orbSubscription?.plan?.name, + tier: authInfo.organization?.subscription?.factoryTier, + organizationName: authInfo.organization?.name, + accountEmail: nil, + userId: userId, + rawJSON: nil, + tokenRateLimits: tokenRateLimits, + extraUsageBalanceCents: billingLimits.extraUsageBalanceCents, + overagePreference: billingLimits.overagePreference) + } +} + +private func factoryUserIdFromAuth(_ auth: FactoryAuthResponse) -> String? { + factoryNormalizedString(auth.userProfile?.id) +} + +private func factoryUserIdFromBearerToken(_ token: String?) -> String? { + guard let token, + let claims = UsageFetcher.parseJWT(token), + let subject = claims["sub"] as? String + else { + return nil + } + return factoryNormalizedString(subject) +} + +private func factoryNormalizedString(_ value: String?) -> String? { + guard let value = value?.trimmingCharacters(in: .whitespacesAndNewlines), !value.isEmpty else { + return nil + } + return value +} diff --git a/Sources/CodexBarCore/Providers/Factory/FactoryStatusProbeError.swift b/Sources/CodexBarCore/Providers/Factory/FactoryStatusProbeError.swift new file mode 100644 index 0000000..a486eec --- /dev/null +++ b/Sources/CodexBarCore/Providers/Factory/FactoryStatusProbeError.swift @@ -0,0 +1,47 @@ +import Foundation +#if os(macOS) +import SweetCookieKit + +private let factoryAPIKeyCookieImportOrder: BrowserCookieImportOrder = + ProviderDefaults.metadata[.factory]?.browserCookieOrder ?? Browser.defaultImportOrder +#endif + +public enum FactoryStatusProbeError: LocalizedError, Sendable, Equatable { + case notSupported + case notLoggedIn + case missingAPIKey + case unauthorizedAPIKey + case networkError(String) + case parseFailed(String) + case noSessionCookie + + public var errorDescription: String? { + switch self { + case .notSupported: + "Factory browser-cookie auth is only supported on macOS. Use FACTORY_API_KEY / --source api on Linux." + case .notLoggedIn: + #if os(macOS) + "No usable Droid session found. Log in to app.factory.ai in \(factoryAPIKeyCookieImportOrder.loginHint), " + + "then refresh Droid." + #else + "No usable Droid session found. Log in to app.factory.ai, then refresh Droid." + #endif + case .missingAPIKey: + "Droid API key missing. Set FACTORY_API_KEY, add providers[].apiKey for factory in " + + "~/.codexbar/config.json, or run `codexbar config set-api-key --provider factory`." + case .unauthorizedAPIKey: + "Droid API authentication failed (401/403). Refresh FACTORY_API_KEY or regenerate a key at " + + "app.factory.ai/settings/api-keys." + case let .networkError(msg): + "Factory API error: \(msg)" + case let .parseFailed(msg): + "Could not parse Factory usage: \(msg)" + case .noSessionCookie: + #if os(macOS) + "No Factory session found. Please log in to app.factory.ai in \(factoryAPIKeyCookieImportOrder.loginHint)." + #else + "No Factory session found. Please log in to app.factory.ai." + #endif + } + } +} diff --git a/Sources/CodexBarCore/Providers/Gemini/GeminiConsumerTierMigration.swift b/Sources/CodexBarCore/Providers/Gemini/GeminiConsumerTierMigration.swift new file mode 100644 index 0000000..36ee22b --- /dev/null +++ b/Sources/CodexBarCore/Providers/Gemini/GeminiConsumerTierMigration.swift @@ -0,0 +1,16 @@ +import Foundation + +/// Shared copy for Google's June 2026 Gemini CLI consumer-tier shutdown. +public enum GeminiConsumerTierMigration { + public static let deprecationError = """ + Google no longer supports Gemini CLI OAuth for individual, AI Pro, or Ultra accounts. \ + Enable CodexBar's Antigravity provider, sign in to Antigravity or run `agy`, then refresh. + """ + + public static let oauthRecoveryError = """ + Could not refresh Gemini OAuth credentials. Reinstall or update Gemini CLI, or set \ + GEMINI_OAUTH_CLIENT_ID and GEMINI_OAUTH_CLIENT_SECRET. Consumer Google AI Pro/Ultra \ + accounts blocked by the June 2026 Gemini CLI shutdown should use CodexBar's Antigravity \ + provider instead. Workspace and education accounts should keep using Gemini. + """ +} diff --git a/Sources/CodexBarCore/Providers/Gemini/GeminiOAuthConfig.swift b/Sources/CodexBarCore/Providers/Gemini/GeminiOAuthConfig.swift new file mode 100644 index 0000000..4463648 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Gemini/GeminiOAuthConfig.swift @@ -0,0 +1,77 @@ +import Foundation + +/// Gemini CLI OAuth client resolution helpers for token refresh. +/// Mirrors Antigravity's env override pattern. +public enum GeminiOAuthConfig: Sendable { + public struct ClientCredentials: Sendable, Equatable { + public let clientID: String + public let clientSecret: String + + public init(clientID: String, clientSecret: String) { + self.clientID = clientID + self.clientSecret = clientSecret + } + } + + /// Test-injectable environment view so suites can override OAuth knobs without + /// mutating process-wide env (which races parallel Gemini suites). + public struct EnvironmentValues: Sendable, Equatable { + public var clientID: String? + public var clientSecret: String? + public var oauth2JSPath: String? + + public init(clientID: String? = nil, clientSecret: String? = nil, oauth2JSPath: String? = nil) { + self.clientID = clientID + self.clientSecret = clientSecret + self.oauth2JSPath = oauth2JSPath + } + + public static func fromProcessEnvironment( + _ environment: [String: String] = ProcessInfo.processInfo.environment) -> Self + { + Self( + clientID: environment["GEMINI_OAUTH_CLIENT_ID"], + clientSecret: environment["GEMINI_OAUTH_CLIENT_SECRET"], + oauth2JSPath: environment["GEMINI_OAUTH2_JS_PATH"]) + } + } + + @TaskLocal public static var environmentOverride: EnvironmentValues? + + public static var currentEnvironment: EnvironmentValues { + self.environmentOverride ?? .fromProcessEnvironment() + } + + public static var configuredClientID: String? { + self.currentEnvironment.clientID? + .trimmingCharacters(in: .whitespacesAndNewlines) + .nilIfEmpty + } + + public static var configuredClientSecret: String? { + self.currentEnvironment.clientSecret? + .trimmingCharacters(in: .whitespacesAndNewlines) + .nilIfEmpty + } + + public static var configuredOAuth2JSPath: String? { + self.currentEnvironment.oauth2JSPath? + .trimmingCharacters(in: .whitespacesAndNewlines) + .nilIfEmpty + } + + public static func environmentClient() -> ClientCredentials? { + guard let clientID = configuredClientID, + let clientSecret = configuredClientSecret + else { + return nil + } + return ClientCredentials(clientID: clientID, clientSecret: clientSecret) + } +} + +extension String { + fileprivate var nilIfEmpty: String? { + self.isEmpty ? nil : self + } +} diff --git a/Sources/CodexBarCore/Providers/Gemini/GeminiProviderDescriptor.swift b/Sources/CodexBarCore/Providers/Gemini/GeminiProviderDescriptor.swift new file mode 100644 index 0000000..322ad1f --- /dev/null +++ b/Sources/CodexBarCore/Providers/Gemini/GeminiProviderDescriptor.swift @@ -0,0 +1,65 @@ +import Foundation + +public enum GeminiProviderDescriptor { + public static let descriptor: ProviderDescriptor = Self.makeDescriptor() + + static func makeDescriptor() -> ProviderDescriptor { + ProviderDescriptor( + id: .gemini, + metadata: ProviderMetadata( + id: .gemini, + displayName: "Gemini", + sessionLabel: "Pro", + weeklyLabel: "Flash", + opusLabel: "Flash Lite", + supportsOpus: true, + supportsCredits: false, + creditsHint: "", + toggleTitle: "Show Gemini usage", + cliName: "gemini", + defaultEnabled: false, + isPrimaryProvider: false, + usesAccountFallback: false, + dashboardURL: "https://gemini.google.com", + changelogURL: "https://github.com/google-gemini/gemini-cli/releases", + statusPageURL: nil, + statusLinkURL: "https://www.google.com/appsstatus/dashboard/products/npdyhgECDJ6tB66MxXyo/history", + statusWorkspaceProductID: "npdyhgECDJ6tB66MxXyo"), + branding: ProviderBranding( + iconStyle: .gemini, + iconResourceName: "ProviderIcon-gemini", + color: ProviderColor(red: 171 / 255, green: 135 / 255, blue: 234 / 255)), + tokenCost: ProviderTokenCostConfig( + supportsTokenCost: false, + noDataMessage: { "Gemini cost summary is not supported." }), + fetchPlan: ProviderFetchPlan( + sourceModes: [.auto, .api], + pipeline: ProviderFetchPipeline(resolveStrategies: { _ in [GeminiStatusFetchStrategy()] })), + cli: ProviderCLIConfig( + name: "gemini", + versionDetector: { _ in ProviderVersionDetector.geminiVersion() })) + } +} + +struct GeminiStatusFetchStrategy: ProviderFetchStrategy { + static let sourceLabel = "oauth-api" + + let id: String = "gemini.api" + let kind: ProviderFetchKind = .apiToken + + func isAvailable(_: ProviderFetchContext) async -> Bool { + true + } + + func fetch(_: ProviderFetchContext) async throws -> ProviderFetchResult { + let probe = GeminiStatusProbe() + let snap = try await probe.fetch() + return self.makeResult( + usage: snap.toUsageSnapshot(), + sourceLabel: Self.sourceLabel) + } + + func shouldFallback(on _: Error, context _: ProviderFetchContext) -> Bool { + false + } +} diff --git a/Sources/CodexBarCore/Providers/Gemini/GeminiStatusProbe+DataLoader.swift b/Sources/CodexBarCore/Providers/Gemini/GeminiStatusProbe+DataLoader.swift new file mode 100644 index 0000000..502f496 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Gemini/GeminiStatusProbe+DataLoader.swift @@ -0,0 +1,131 @@ +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +extension GeminiStatusProbe { + public static func defaultDataLoader(for request: URLRequest) async throws -> (Data, URLResponse) { + let loader = Self.dataLoaderWithCurlFallback( + primary: { request in + try await ProviderHTTPClient.shared.data(for: request) + }, + fallback: Self.curlDataLoader) + return try await loader(request) + } + + public static func dataLoaderWithCurlFallback( + primary: @escaping @Sendable (URLRequest) async throws -> (Data, URLResponse), + fallback: @escaping @Sendable (URLRequest) async throws -> (Data, URLResponse)) + -> @Sendable (URLRequest) async throws -> (Data, URLResponse) + { + { request in + do { + return try await primary(request) + } catch { + guard Self.isURLSessionTimeout(error) else { + throw error + } + CodexBarLog.logger(LogCategories.geminiProbe) + .warning("Gemini URLSession timed out; retrying with curl") + return try await fallback(request) + } + } + } + + private static func isURLSessionTimeout(_ error: Error) -> Bool { + if let urlError = error as? URLError { + return urlError.code == .timedOut + } + + let nsError = error as NSError + return nsError.domain == NSURLErrorDomain && nsError.code == NSURLErrorTimedOut + } + + private static func curlDataLoader(for request: URLRequest) async throws -> (Data, URLResponse) { + guard let url = request.url else { + throw URLError(.badURL) + } + + let fileManager = FileManager.default + let tempDir = fileManager.temporaryDirectory + .appendingPathComponent("codexbar-gemini-curl-\(UUID().uuidString)", isDirectory: true) + try fileManager.createDirectory( + at: tempDir, + withIntermediateDirectories: true, + attributes: [.posixPermissions: 0o700]) + defer { + try? fileManager.removeItem(at: tempDir) + } + + let configURL = tempDir.appendingPathComponent("curl.conf") + var config = [ + "silent", + "show-error", + "location", + "url = \(Self.curlConfigQuote(url.absoluteString))", + "max-time = \(max(1, Int(ceil(request.timeoutInterval))))", + ] + + if let method = request.httpMethod, !method.isEmpty { + config.append("request = \(Self.curlConfigQuote(method))") + } + + for (name, value) in (request.allHTTPHeaderFields ?? [:]).sorted(by: { $0.key < $1.key }) { + let header = "\(name): \(value)" + guard !header.contains("\n"), !header.contains("\r") else { + throw GeminiStatusProbeError.apiError("Invalid request header") + } + config.append("header = \(Self.curlConfigQuote(header))") + } + + if let body = request.httpBody { + let bodyURL = tempDir.appendingPathComponent("body") + try body.write(to: bodyURL, options: .atomic) + try fileManager.setAttributes([.posixPermissions: 0o600], ofItemAtPath: bodyURL.path) + config.append("data-binary = \(Self.curlConfigQuote("@\(bodyURL.path)"))") + } + + config.append("write-out = \(Self.curlConfigQuote(Self.curlHTTPStatusMarker + "%{http_code}"))") + try config.joined(separator: "\n").write(to: configURL, atomically: true, encoding: .utf8) + try fileManager.setAttributes([.posixPermissions: 0o600], ofItemAtPath: configURL.path) + + let result = try await SubprocessRunner.run( + binary: "/usr/bin/curl", + arguments: ["--config", configURL.path], + environment: TTYCommandRunner.enrichedEnvironment(), + timeout: max(5, request.timeoutInterval + 2), + label: "gemini-api-curl") + + return try Self.parseCurlDataLoaderResult(result.stdout, url: url) + } + + private static let curlHTTPStatusMarker = "__CODEXBAR_HTTP_STATUS__:" + + private static func curlConfigQuote(_ value: String) -> String { + let escaped = value + .replacingOccurrences(of: "\\", with: "\\\\") + .replacingOccurrences(of: "\"", with: "\\\"") + return "\"\(escaped)\"" + } + + private static func parseCurlDataLoaderResult(_ output: String, url: URL) throws -> (Data, URLResponse) { + guard let markerRange = output.range(of: curlHTTPStatusMarker, options: .backwards) else { + throw GeminiStatusProbeError.apiError("curl response missing HTTP status") + } + + let body = String(output[.. 0, + let response = HTTPURLResponse( + url: url, + statusCode: statusCode, + httpVersion: nil, + headerFields: nil) + else { + throw GeminiStatusProbeError.apiError("curl response had invalid HTTP status") + } + + return (Data(body.utf8), response) + } +} diff --git a/Sources/CodexBarCore/Providers/Gemini/GeminiStatusProbe.swift b/Sources/CodexBarCore/Providers/Gemini/GeminiStatusProbe.swift new file mode 100644 index 0000000..27c46d8 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Gemini/GeminiStatusProbe.swift @@ -0,0 +1,1397 @@ +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif +#if canImport(Darwin) +import Darwin +#elseif canImport(Glibc) +import Glibc +#elseif canImport(Musl) +import Musl +#endif + +public struct GeminiModelQuota: Sendable { + public let modelId: String + public let percentLeft: Double + public let resetTime: Date? + public let resetDescription: String? +} + +public struct GeminiStatusSnapshot: Sendable { + public let modelQuotas: [GeminiModelQuota] + public let rawText: String + public let accountEmail: String? + public let accountPlan: String? + + // Convenience: lowest quota across all models (for icon display) + public var lowestPercentLeft: Double? { + self.modelQuotas.min(by: { $0.percentLeft < $1.percentLeft })?.percentLeft + } + + /// Legacy compatibility + public var dailyPercentLeft: Double? { + self.lowestPercentLeft + } + + public var resetDescription: String? { + self.modelQuotas.min(by: { $0.percentLeft < $1.percentLeft })?.resetDescription + } + + /// Converts Gemini quotas to a unified UsageSnapshot. + /// Groups quotas by tier: Pro (24h window) as primary, Flash (24h window) as secondary, + /// Flash Lite (24h window) as tertiary. + public func toUsageSnapshot() -> UsageSnapshot { + let lower = self.modelQuotas.map { ($0.modelId.lowercased(), $0) } + let flashLiteQuotas = lower.filter { Self.isFlashLiteModel(id: $0.0) }.map(\.1) + let flashQuotas = lower.filter { Self.isFlashModel(id: $0.0) }.map(\.1) + let proQuotas = lower.filter { Self.isProModel(id: $0.0) }.map(\.1) + + let flashLiteMin = flashLiteQuotas.min(by: { $0.percentLeft < $1.percentLeft }) + let flashMin = flashQuotas.min(by: { $0.percentLeft < $1.percentLeft }) + let proMin = proQuotas.min(by: { $0.percentLeft < $1.percentLeft }) + + // Keep missing tiers nil so downstream selectors can fall back to a quota the account actually reports. + let primary: RateWindow? = proMin.map { + RateWindow( + usedPercent: 100 - $0.percentLeft, + windowMinutes: 1440, + resetsAt: $0.resetTime, + resetDescription: $0.resetDescription) + } + + let secondary: RateWindow? = flashMin.map { + RateWindow( + usedPercent: 100 - $0.percentLeft, + windowMinutes: 1440, + resetsAt: $0.resetTime, + resetDescription: $0.resetDescription) + } + let tertiary: RateWindow? = flashLiteMin.map { + RateWindow( + usedPercent: 100 - $0.percentLeft, + windowMinutes: 1440, + resetsAt: $0.resetTime, + resetDescription: $0.resetDescription) + } + + let identity = ProviderIdentitySnapshot( + providerID: .gemini, + accountEmail: self.accountEmail, + accountOrganization: nil, + loginMethod: self.accountPlan) + return UsageSnapshot( + primary: primary, + secondary: secondary, + tertiary: tertiary, + updatedAt: Date(), + identity: identity) + } + + private static func isFlashLiteModel(id: String) -> Bool { + id.contains("flash-lite") + } + + private static func isFlashModel(id: String) -> Bool { + id.contains("flash") && !self.isFlashLiteModel(id: id) + } + + private static func isProModel(id: String) -> Bool { + id.contains("pro") + } +} + +public enum GeminiStatusProbeError: LocalizedError, Sendable, Equatable { + case geminiNotInstalled + case notLoggedIn + case unsupportedAuthType(String) + case consumerTierDeprecated + case parseFailed(String) + case timedOut + case apiError(String) + + public var errorDescription: String? { + switch self { + case .geminiNotInstalled: + "Gemini CLI is not installed or not on PATH." + case .notLoggedIn: + "Not logged in to Gemini. Run 'gemini' in Terminal to authenticate." + case let .unsupportedAuthType(authType): + "Gemini \(authType) auth not supported. Use Google account (OAuth) instead." + case .consumerTierDeprecated: + GeminiConsumerTierMigration.deprecationError + case let .parseFailed(msg): + "Could not parse Gemini usage: \(msg)" + case .timedOut: + "Gemini quota API request timed out." + case let .apiError(msg): + "Gemini API error: \(msg)" + } + } + + /// Detects Google's consumer-tier Gemini CLI shutdown responses. + public static func isConsumerTierDeprecationSignal(_ text: String) -> Bool { + let normalized = text.lowercased() + if normalized.contains("unsupported_client") { + return true + } + if normalized.contains("ineligibletiererror") { + return true + } + if normalized.contains("no longer supported"), normalized.contains("gemini code assist") { + return true + } + if normalized.contains("migrate"), normalized.contains("antigravity"), normalized.contains("gemini") { + return true + } + return false + } + + public static func throwIfConsumerTierDeprecated(data: Data) throws { + guard let text = String(data: data, encoding: .utf8), + isConsumerTierDeprecationSignal(text) + else { + return + } + throw GeminiStatusProbeError.consumerTierDeprecated + } +} + +public enum GeminiAuthType: String, Sendable { + case oauthPersonal = "oauth-personal" + case apiKey = "gemini-api-key" + case vertexAI = "vertex-ai" + case unknown +} + +/// User tier IDs returned from the Cloud Code Private API (loadCodeAssist). +/// Maps to: google3/cloud/developer_experience/cloudcode/pa/service/usertier.go +public enum GeminiUserTierId: String, Sendable { + case free = "free-tier" + case legacy = "legacy-tier" + case standard = "standard-tier" +} + +public struct GeminiStatusProbe: Sendable { + public var timeout: TimeInterval = 10.0 + public var homeDirectory: String + public var dataLoader: @Sendable (URLRequest) async throws -> (Data, URLResponse) + private static let log = CodexBarLog.logger(LogCategories.geminiProbe) + private static let quotaEndpoint = "https://cloudcode-pa.googleapis.com/v1internal:retrieveUserQuota" + private static let loadCodeAssistEndpoint = "https://cloudcode-pa.googleapis.com/v1internal:loadCodeAssist" + private static let projectsEndpoint = "https://cloudresourcemanager.googleapis.com/v1/projects" + private static let credentialsPath = "/.gemini/oauth_creds.json" + private static let settingsPath = "/.gemini/settings.json" + private static let tokenRefreshEndpoint = "https://oauth2.googleapis.com/token" + + public init( + timeout: TimeInterval = 10.0, + homeDirectory: String = NSHomeDirectory(), + dataLoader: @escaping @Sendable (URLRequest) async throws -> (Data, URLResponse) = Self.defaultDataLoader) + { + self.timeout = timeout + self.homeDirectory = homeDirectory + self.dataLoader = dataLoader + } + + /// Reads the current Gemini auth type from settings.json + public static func currentAuthType(homeDirectory: String = NSHomeDirectory()) -> GeminiAuthType { + let settingsURL = URL(fileURLWithPath: homeDirectory + Self.settingsPath) + + guard let data = try? Data(contentsOf: settingsURL), + let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any], + let security = json["security"] as? [String: Any], + let auth = security["auth"] as? [String: Any], + let selectedType = auth["selectedType"] as? String + else { + return .unknown + } + + if selectedType == "api-key" { + return .apiKey + } + return GeminiAuthType(rawValue: selectedType) ?? .unknown + } + + public func fetch() async throws -> GeminiStatusSnapshot { + // Block explicitly unsupported auth types; allow unknown to try OAuth creds + let authType = Self.currentAuthType(homeDirectory: self.homeDirectory) + switch authType { + case .apiKey: + throw GeminiStatusProbeError.unsupportedAuthType("API key") + case .vertexAI: + throw GeminiStatusProbeError.unsupportedAuthType("Vertex AI") + case .oauthPersonal, .unknown: + break + } + + let snap = try await Self.fetchViaAPI( + timeout: self.timeout, + homeDirectory: self.homeDirectory, + dataLoader: self.dataLoader) + + Self.log.info("Gemini API fetch ok", metadata: [ + "dailyPercentLeft": "\(snap.dailyPercentLeft ?? -1)", + ]) + return snap + } + + // MARK: - Direct API approach + + private static func fetchViaAPI( + timeout: TimeInterval, + homeDirectory: String, + dataLoader: @escaping @Sendable (URLRequest) async throws -> (Data, URLResponse)) async throws + -> GeminiStatusSnapshot + { + let creds = try Self.loadCredentials(homeDirectory: homeDirectory) + + let expiryStr = creds.expiryDate.map { "\($0)" } ?? "nil" + let hasRefresh = creds.refreshToken != nil + Self.log.debug("Token check", metadata: [ + "expiry": expiryStr, + "hasRefresh": hasRefresh ? "1" : "0", + "now": "\(Date())", + ]) + + var accessToken = creds.accessToken?.isEmpty == false ? creds.accessToken : nil + var idToken = creds.idToken + let needsRefresh = accessToken == nil || creds.expiryDate.map { $0 < Date() } == true + if needsRefresh { + if accessToken == nil { + Self.log.info("No access token found; attempting refresh from stored Gemini credentials") + } else if let expiry = creds.expiryDate { + Self.log.info("Token expired; attempting refresh", metadata: [ + "expiry": "\(expiry)", + ]) + } + + guard let refreshToken = creds.refreshToken, !refreshToken.isEmpty else { + Self.log.error("No refresh token available") + throw GeminiStatusProbeError.notLoggedIn + } + accessToken = try await Self.refreshAccessToken( + refreshToken: refreshToken, + timeout: timeout, + homeDirectory: homeDirectory, + dataLoader: dataLoader) + idToken = (try? Self.loadCredentials(homeDirectory: homeDirectory).idToken) ?? idToken + } + guard let accessToken else { + Self.log.error("No access token found") + throw GeminiStatusProbeError.notLoggedIn + } + + // Extract account info from JWT + let claims = Self.extractClaimsFromToken(idToken) + + // Load Code Assist status to get project ID and tier (aligned with CLI setupUser logic) + let caStatus = try await Self.loadCodeAssistStatus( + accessToken: accessToken, + timeout: timeout, + dataLoader: dataLoader) + + // Determine the project ID to use for quota fetching. + // Priority: + // 1. Project ID returned by loadCodeAssist (e.g. managed project for free tier) + // 2. Discovered project ID from cloud resource manager (e.g. user's own project) + var projectId = caStatus.projectId + if projectId == nil { + projectId = try? await Self.discoverGeminiProjectId( + accessToken: accessToken, + timeout: timeout, + dataLoader: dataLoader) + } + + guard let url = URL(string: Self.quotaEndpoint) else { + throw GeminiStatusProbeError.apiError("Invalid endpoint URL") + } + + var request = URLRequest(url: url) + request.httpMethod = "POST" + request.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization") + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + + // Include project ID for accurate quota + if let projectId { + request.httpBody = Data("{\"project\": \"\(projectId)\"}".utf8) + } else { + request.httpBody = Data("{}".utf8) + } + request.timeoutInterval = timeout + + let (data, response) = try await dataLoader(request) + + guard let httpResponse = response as? HTTPURLResponse else { + throw GeminiStatusProbeError.apiError("Invalid response") + } + + if httpResponse.statusCode == 401 { + try GeminiStatusProbeError.throwIfConsumerTierDeprecated(data: data) + throw GeminiStatusProbeError.notLoggedIn + } + + guard httpResponse.statusCode == 200 else { + try GeminiStatusProbeError.throwIfConsumerTierDeprecated(data: data) + throw GeminiStatusProbeError.apiError("HTTP \(httpResponse.statusCode)") + } + + let snapshot = try Self.parseAPIResponse(data, email: claims.email) + + let plan = Self.resolveAccountPlan( + tier: caStatus.tier, + hostedDomain: claims.hostedDomain, + paidTierName: caStatus.paidTierName) + + return GeminiStatusSnapshot( + modelQuotas: snapshot.modelQuotas, + rawText: snapshot.rawText, + accountEmail: snapshot.accountEmail, + accountPlan: plan) + } + + private static func discoverGeminiProjectId( + accessToken: String, + timeout: TimeInterval, + dataLoader: @escaping @Sendable (URLRequest) async throws -> (Data, URLResponse)) async throws + -> String? + { + guard let url = URL(string: projectsEndpoint) else { return nil } + + var request = URLRequest(url: url) + request.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization") + request.timeoutInterval = timeout + + let (data, response) = try await dataLoader(request) + + guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else { + return nil + } + + guard let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any], + let projects = json["projects"] as? [[String: Any]] + else { + return nil + } + + // Look for Gemini API project (has "generative-language" label or "gen-lang-client" prefix) + for project in projects { + guard let projectId = project["projectId"] as? String else { continue } + + // Check for gen-lang-client prefix (Gemini CLI projects) + if projectId.hasPrefix("gen-lang-client") { + return projectId + } + + // Check for generative-language label + if let labels = project["labels"] as? [String: String], + labels["generative-language"] != nil + { + return projectId + } + } + + return nil + } + + private struct CodeAssistStatus { + let tier: GeminiUserTierId? + let projectId: String? + let paidTierName: String? + + static let empty = CodeAssistStatus(tier: nil, projectId: nil, paidTierName: nil) + } + + private static func loadCodeAssistStatus( + accessToken: String, + timeout: TimeInterval, + dataLoader: @escaping @Sendable (URLRequest) async throws -> (Data, URLResponse)) async throws + -> CodeAssistStatus + { + guard let url = URL(string: loadCodeAssistEndpoint) else { + self.log.warning("loadCodeAssist: invalid endpoint URL") + return .empty + } + + var request = URLRequest(url: url) + request.httpMethod = "POST" + request.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization") + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + request.httpBody = Data("{\"metadata\":{\"ideType\":\"GEMINI_CLI\",\"pluginType\":\"GEMINI\"}}".utf8) + request.timeoutInterval = timeout + + let data: Data + let response: URLResponse + do { + (data, response) = try await dataLoader(request) + } catch { + Self.log.warning("loadCodeAssist: request failed", metadata: ["error": "\(error)"]) + return .empty + } + + guard let httpResponse = response as? HTTPURLResponse else { + Self.log.warning("loadCodeAssist: invalid response type") + return .empty + } + + guard httpResponse.statusCode == 200 else { + try GeminiStatusProbeError.throwIfConsumerTierDeprecated(data: data) + Self.log.warning("loadCodeAssist: HTTP error", metadata: [ + "statusCode": "\(httpResponse.statusCode)", + "body": String(data: data, encoding: .utf8) ?? "", + ]) + return .empty + } + + guard let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else { + Self.log.warning("loadCodeAssist: failed to parse JSON", metadata: [ + "body": String(data: data, encoding: .utf8) ?? "", + ]) + return .empty + } + + let rawProjectId: String? = { + if let project = json["cloudaicompanionProject"] as? String { + return project + } + if let project = json["cloudaicompanionProject"] as? [String: Any] { + if let projectId = project["id"] as? String { + return projectId + } + if let projectId = project["projectId"] as? String { + return projectId + } + } + return nil + }() + let trimmedProjectId = rawProjectId?.trimmingCharacters(in: .whitespacesAndNewlines) + let projectId = trimmedProjectId?.isEmpty == true ? nil : trimmedProjectId + if let projectId { + Self.log.info("loadCodeAssist: project detected", metadata: ["projectId": projectId]) + } + + let tierId = (json["currentTier"] as? [String: Any])?["id"] as? String + let paidTierName = Self.parsePaidTierName(from: json) + + guard let tierId else { + Self.log.warning("loadCodeAssist: no currentTier.id in response", metadata: [ + "json": "\(json)", + ]) + return CodeAssistStatus(tier: nil, projectId: projectId, paidTierName: paidTierName) + } + + guard let tier = GeminiUserTierId(rawValue: tierId) else { + Self.log.warning("loadCodeAssist: unknown tier ID", metadata: ["tierId": tierId]) + return CodeAssistStatus(tier: nil, projectId: projectId, paidTierName: paidTierName) + } + + Self.log.info("loadCodeAssist: success", metadata: [ + "tier": tierId, + "projectId": projectId ?? "nil", + "paidTierName": paidTierName ?? "nil", + ]) + return CodeAssistStatus(tier: tier, projectId: projectId, paidTierName: paidTierName) + } + + private struct OAuthCredentials { + let accessToken: String? + let idToken: String? + let refreshToken: String? + let expiryDate: Date? + } + + fileprivate struct OAuthClientCredentials { + let clientId: String + let clientSecret: String + } + + private static func isLikelyFnmManagedPath(_ path: String) -> Bool { + let normalized = path.replacingOccurrences(of: "\\", with: "/") + return normalized.contains("/fnm_multishells/") + || (normalized.contains("/node-versions/") && normalized.contains("/fnm/")) + } + + private static func resolveExecutableOnEnvironmentPath( + named executable: String, + environment: [String: String]) -> String? + { + guard let path = environment["PATH"] else { return nil } + for directory in path.split(separator: ":") where !directory.isEmpty { + let candidate = URL(fileURLWithPath: String(directory), isDirectory: true) + .appendingPathComponent(executable) + .path + if FileManager.default.isExecutableFile(atPath: candidate) { + return candidate + } + } + return nil + } + + private static func resolveGeminiPackageRootViaFnm( + fnmPath: String, + environment: [String: String]) -> String? + { + guard let currentVersion = runProcess( + executable: fnmPath, + arguments: ["current"], + environment: environment, + timeout: 2.0), + !currentVersion.isEmpty + else { + return nil + } + + // Prefer npm root -g because require.resolve searches from the current + // working directory and often fails for globally-installed packages. + if let npmRoot = runProcess( + executable: fnmPath, + arguments: [ + "exec", + "--using", + currentVersion, + "npm", + "root", + "-g", + ], + environment: environment, + timeout: 4.0), + !npmRoot.isEmpty + { + let packageRoot = "\(npmRoot)/@google/gemini-cli" + let packageJSONPath = "\(packageRoot)/package.json" + if FileManager.default.fileExists(atPath: packageJSONPath) { + return packageRoot + } + } + + // Fallback for non-npm global installations. + if let packageJSONPath = runProcess( + executable: fnmPath, + arguments: [ + "exec", + "--using", + currentVersion, + "node", + "-p", + "require.resolve('@google/gemini-cli/package.json')", + ], + environment: environment, + timeout: 4.0), + !packageJSONPath.isEmpty + { + return (packageJSONPath as NSString).deletingLastPathComponent + } + + return nil + } + + private static func findGeminiPackageRoot(startingAt path: String) -> String? { + let fileManager = FileManager.default + var currentURL = URL(fileURLWithPath: path).standardizedFileURL + + var isDirectory: ObjCBool = false + if !fileManager.fileExists(atPath: currentURL.path, isDirectory: &isDirectory) || !isDirectory.boolValue { + currentURL.deleteLastPathComponent() + } + + // Bound the walk so an unrelated Gemini install elsewhere on the host + // (e.g. a global npm/brew install unrelated to the resolved binary) can't + // contaminate discovery started from the actual binary path. + let maxAscents = 8 + for _ in 0...maxAscents { + let packageJSONURL = currentURL.appendingPathComponent("package.json") + if let data = try? Data(contentsOf: packageJSONURL), + let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any], + json["name"] as? String == "@google/gemini-cli" + { + return currentURL.path + } + + // Also check for a global Node installation layout: + // /lib/node_modules/@google/gemini-cli/package.json + let globalPackageJSONURL = currentURL + .appendingPathComponent("lib") + .appendingPathComponent("node_modules") + .appendingPathComponent("@google") + .appendingPathComponent("gemini-cli") + .appendingPathComponent("package.json") + if let data = try? Data(contentsOf: globalPackageJSONURL), + let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any], + json["name"] as? String == "@google/gemini-cli" + { + return globalPackageJSONURL.deletingLastPathComponent().path + } + + // Homebrew layout: + // /libexec/lib/node_modules/@google/gemini-cli/package.json + let homebrewPackageJSONURL = currentURL + .appendingPathComponent("libexec") + .appendingPathComponent("lib") + .appendingPathComponent("node_modules") + .appendingPathComponent("@google") + .appendingPathComponent("gemini-cli") + .appendingPathComponent("package.json") + if let data = try? Data(contentsOf: homebrewPackageJSONURL), + let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any], + json["name"] as? String == "@google/gemini-cli" + { + return homebrewPackageJSONURL.deletingLastPathComponent().path + } + + let parentURL = currentURL.deletingLastPathComponent() + if parentURL.path == currentURL.path { + return nil + } + currentURL = parentURL + } + + return nil + } + + private static func extractOAuthCredentials(fromGeminiPackageRoot packageRoot: String) -> OAuthClientCredentials? { + // Check the standard distributed file first, then any sibling core package + let oauthFile = "dist/src/code_assist/oauth2.js" + let candidatePaths = [ + "\(packageRoot)/\(oauthFile)", + "\(packageRoot)/node_modules/@google/gemini-cli-core/\(oauthFile)", + ] + + for path in candidatePaths { + if let content = try? String(contentsOfFile: path, encoding: .utf8), + let credentials = Self.parseOAuthCredentials(from: content) + { + return credentials + } + } + + return Self.extractOAuthCredentialsFromBundle(packageRoot: packageRoot) + } + + private static func extractOAuthCredentialsFromBundle(packageRoot: String) -> OAuthClientCredentials? { + let bundleRoot = URL(fileURLWithPath: packageRoot).appendingPathComponent("bundle", isDirectory: true) + let entryURL = bundleRoot.appendingPathComponent("gemini.js") + + guard FileManager.default.fileExists(atPath: entryURL.path) else { + return nil + } + + var pendingURLs = [entryURL] + var visitedPaths = Set() + + while !pendingURLs.isEmpty { + let currentURL = pendingURLs.removeFirst() + let standardizedPath = currentURL.standardizedFileURL.path + guard visitedPaths.insert(standardizedPath).inserted, + let content = try? String(contentsOf: currentURL, encoding: .utf8) + else { + continue + } + + if let credentials = Self.parseOAuthCredentials(from: content) { + return credentials + } + + let imports = Self.extractRelativeJavaScriptImports(from: content) + for importPath in imports { + let nextURL = URL(fileURLWithPath: importPath, relativeTo: currentURL.deletingLastPathComponent()) + .standardizedFileURL + guard nextURL.path.hasPrefix(bundleRoot.path) else { continue } + pendingURLs.append(nextURL) + } + } + + guard let bundleFiles = try? FileManager.default.contentsOfDirectory( + at: bundleRoot, + includingPropertiesForKeys: nil, + options: [.skipsHiddenFiles]) + else { + return nil + } + + for url in bundleFiles where url.pathExtension == "js" && !visitedPaths.contains(url.standardizedFileURL.path) { + guard let content = try? String(contentsOf: url, encoding: .utf8) else { continue } + if let credentials = Self.parseOAuthCredentials(from: content) { + return credentials + } + } + + return nil + } + + private static func extractRelativeJavaScriptImports(from content: String) -> [String] { + let patterns = [ + #"(?:import|export)\s+(?:[^;]*?\s+from\s+)?[\"'](\./[^\"']+\.js)[\"']"#, + #"import\(\s*[\"'](\./[^\"']+\.js)[\"']\s*\)"#, + ] + + var discoveredPaths: [String] = [] + var seen = Set() + let fullRange = NSRange(content.startIndex..., in: content) + + for pattern in patterns { + guard let regex = try? NSRegularExpression(pattern: pattern) else { continue } + for match in regex.matches(in: content, range: fullRange) { + guard let range = Range(match.range(at: 1), in: content) else { continue } + let path = String(content[range]) + if seen.insert(path).inserted { + discoveredPaths.append(path) + } + } + } + + return discoveredPaths + } + + private static func extractOAuthCredentialsFromLegacyPaths(realGeminiPath: String) -> OAuthClientCredentials? { + let binDir = (realGeminiPath as NSString).deletingLastPathComponent + let baseDir = (binDir as NSString).deletingLastPathComponent + + let oauthSubpath = + "node_modules/@google/gemini-cli/node_modules/@google/gemini-cli-core/dist/src/code_assist/oauth2.js" + let nixShareSubpath = + "share/gemini-cli/node_modules/@google/gemini-cli-core/dist/src/code_assist/oauth2.js" + let oauthFile = "dist/src/code_assist/oauth2.js" + let possiblePaths = [ + // Homebrew nested structure + "\(baseDir)/libexec/lib/\(oauthSubpath)", + "\(baseDir)/lib/\(oauthSubpath)", + // Nix package layout + "\(baseDir)/\(nixShareSubpath)", + // Bun/npm sibling structure: gemini-cli-core is a sibling to gemini-cli + "\(baseDir)/../gemini-cli-core/\(oauthFile)", + // npm nested inside gemini-cli + "\(baseDir)/node_modules/@google/gemini-cli-core/\(oauthFile)", + ] + + for path in possiblePaths { + if let content = try? String(contentsOfFile: path, encoding: .utf8), + let credentials = Self.parseOAuthCredentials(from: content) + { + return credentials + } + } + + return nil + } + + private static func parseOAuthCredentials(from content: String) -> OAuthClientCredentials? { + // Match: const/let/var OAUTH_CLIENT_ID = '...'; + let clientIdPattern = #"(?:const|let|var)?\s*OAUTH_CLIENT_ID\s*=\s*['"]([\w\-\.]+)['"]\s*;"# + let secretPattern = #"(?:const|let|var)?\s*OAUTH_CLIENT_SECRET\s*=\s*['"]([\w\-]+)['"]\s*;"# + + guard let clientIdRegex = try? NSRegularExpression(pattern: clientIdPattern), + let secretRegex = try? NSRegularExpression(pattern: secretPattern) + else { + return nil + } + + let range = NSRange(content.startIndex..., in: content) + + guard let clientIdMatch = clientIdRegex.firstMatch(in: content, range: range), + let clientIdRange = Range(clientIdMatch.range(at: 1), in: content), + let secretMatch = secretRegex.firstMatch(in: content, range: range), + let secretRange = Range(secretMatch.range(at: 1), in: content) + else { + return nil + } + + let clientId = String(content[clientIdRange]) + let clientSecret = String(content[secretRange]) + + return OAuthClientCredentials(clientId: clientId, clientSecret: clientSecret) + } + + private static func refreshAccessToken( + refreshToken: String, + timeout: TimeInterval, + homeDirectory: String, + dataLoader: @escaping @Sendable (URLRequest) async throws -> (Data, URLResponse)) async throws + -> String + { + guard let url = URL(string: tokenRefreshEndpoint) else { + throw GeminiStatusProbeError.apiError("Invalid token refresh URL") + } + + var request = URLRequest(url: url) + request.httpMethod = "POST" + request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") + request.timeoutInterval = timeout + + guard let oauthCreds = Self.extractOAuthCredentials() else { + Self.log.error("Could not extract OAuth credentials from Gemini CLI") + throw GeminiStatusProbeError.apiError(GeminiConsumerTierMigration.oauthRecoveryError) + } + + let body = [ + "client_id=\(oauthCreds.clientId)", + "client_secret=\(oauthCreds.clientSecret)", + "refresh_token=\(refreshToken)", + "grant_type=refresh_token", + ].joined(separator: "&") + request.httpBody = body.data(using: .utf8) + + let (data, response) = try await dataLoader(request) + + guard let httpResponse = response as? HTTPURLResponse else { + throw GeminiStatusProbeError.apiError("Invalid refresh response") + } + + guard httpResponse.statusCode == 200 else { + try GeminiStatusProbeError.throwIfConsumerTierDeprecated(data: data) + Self.log.error("Token refresh failed", metadata: [ + "statusCode": "\(httpResponse.statusCode)", + ]) + throw GeminiStatusProbeError.notLoggedIn + } + + guard let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any], + let newAccessToken = json["access_token"] as? String + else { + throw GeminiStatusProbeError.parseFailed("Could not parse refresh response") + } + + // Update stored credentials with new token + try Self.updateStoredCredentials(json, homeDirectory: homeDirectory) + + Self.log.info("Token refreshed successfully") + return newAccessToken + } + + private static func updateStoredCredentials(_ refreshResponse: [String: Any], homeDirectory: String) throws { + let credsURL = URL(fileURLWithPath: homeDirectory + Self.credentialsPath) + + guard let existingCreds = try? Data(contentsOf: credsURL), + var json = try? JSONSerialization.jsonObject(with: existingCreds) as? [String: Any] + else { + return + } + + // Update with new values from refresh response + if let accessToken = refreshResponse["access_token"] { + json["access_token"] = accessToken + } + if let expiresIn = refreshResponse["expires_in"] as? Double { + json["expiry_date"] = (Date().timeIntervalSince1970 + expiresIn) * 1000 + } + if let idToken = refreshResponse["id_token"] { + json["id_token"] = idToken + } + + let updatedData = try JSONSerialization.data(withJSONObject: json, options: [.prettyPrinted]) + try updatedData.write(to: credsURL, options: .atomic) + } + + private static func loadCredentials(homeDirectory: String) throws -> OAuthCredentials { + let credsURL = URL(fileURLWithPath: homeDirectory + Self.credentialsPath) + + guard FileManager.default.fileExists(atPath: credsURL.path) else { + throw GeminiStatusProbeError.notLoggedIn + } + + let data = try Data(contentsOf: credsURL) + guard let json = try JSONSerialization.jsonObject(with: data) as? [String: Any] else { + throw GeminiStatusProbeError.parseFailed("Invalid credentials file") + } + + let accessToken = json["access_token"] as? String + let idToken = json["id_token"] as? String + let refreshToken = json["refresh_token"] as? String + + var expiryDate: Date? + if let expiryMs = json["expiry_date"] as? Double { + expiryDate = Date(timeIntervalSince1970: expiryMs / 1000) + } + + return OAuthCredentials( + accessToken: accessToken, + idToken: idToken, + refreshToken: refreshToken, + expiryDate: expiryDate) + } + + private struct TokenClaims { + let email: String? + let hostedDomain: String? + } + + private static func extractClaimsFromToken(_ idToken: String?) -> TokenClaims { + guard let token = idToken else { return TokenClaims(email: nil, hostedDomain: nil) } + + let parts = token.components(separatedBy: ".") + guard parts.count >= 2 else { return TokenClaims(email: nil, hostedDomain: nil) } + + var payload = parts[1] + .replacingOccurrences(of: "-", with: "+") + .replacingOccurrences(of: "_", with: "/") + + let remainder = payload.count % 4 + if remainder > 0 { + payload += String(repeating: "=", count: 4 - remainder) + } + + guard let data = Data(base64Encoded: payload, options: .ignoreUnknownCharacters), + let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] + else { + return TokenClaims(email: nil, hostedDomain: nil) + } + + return TokenClaims( + email: json["email"] as? String, + hostedDomain: json["hd"] as? String) + } + + private static func extractEmailFromToken(_ idToken: String?) -> String? { + self.extractClaimsFromToken(idToken).email + } + + private struct QuotaBucket: Decodable { + let remainingFraction: Double? + let resetTime: String? + let modelId: String? + let tokenType: String? + } + + private struct QuotaResponse: Decodable { + let buckets: [QuotaBucket]? + } + + private static func parseAPIResponse(_ data: Data, email: String?) throws -> GeminiStatusSnapshot { + let decoder = JSONDecoder() + let response = try decoder.decode(QuotaResponse.self, from: data) + + guard let buckets = response.buckets, !buckets.isEmpty else { + throw GeminiStatusProbeError.parseFailed("No quota buckets in response") + } + + // Group quotas by model, keeping lowest per model (input tokens usually) + var modelQuotaMap: [String: (fraction: Double, resetString: String?)] = [:] + + for bucket in buckets { + guard let modelId = bucket.modelId, let fraction = bucket.remainingFraction else { continue } + + if let existing = modelQuotaMap[modelId] { + if fraction < existing.fraction { + modelQuotaMap[modelId] = (fraction, bucket.resetTime) + } + } else { + modelQuotaMap[modelId] = (fraction, bucket.resetTime) + } + } + + // Convert to sorted array (by model name for consistent ordering) + let quotas = modelQuotaMap + .sorted { $0.key < $1.key } + .map { modelId, info in + let resetDate = info.resetString.flatMap { Self.parseResetTime($0) } + return GeminiModelQuota( + modelId: modelId, + percentLeft: info.fraction * 100, + resetTime: resetDate, + resetDescription: info.resetString.flatMap { Self.formatResetTime($0) }) + } + + let rawText = String(data: data, encoding: .utf8) ?? "" + + return GeminiStatusSnapshot( + modelQuotas: quotas, + rawText: rawText, + accountEmail: email, + accountPlan: nil) + } + + private static func parseResetTime(_ isoString: String) -> Date? { + let formatter = ISO8601DateFormatter() + formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds] + + if let date = formatter.date(from: isoString) { + return date + } + formatter.formatOptions = [.withInternetDateTime] + return formatter.date(from: isoString) + } + + private static func formatResetTime(_ isoString: String) -> String { + guard let resetDate = parseResetTime(isoString) else { + return "Resets soon" + } + + let now = Date() + let interval = resetDate.timeIntervalSince(now) + + if interval <= 0 { + return "Resets soon" + } + + let hours = Int(interval / 3600) + let minutes = Int((interval.truncatingRemainder(dividingBy: 3600)) / 60) + + if hours > 0 { + return "Resets in \(hours)h \(minutes)m" + } else { + return "Resets in \(minutes)m" + } + } + + // MARK: - Legacy CLI parsing (kept for fallback) + + public static func parse(text: String) throws -> GeminiStatusSnapshot { + let clean = TextParsing.stripANSICodes(text) + guard !clean.isEmpty else { throw GeminiStatusProbeError.timedOut } + + let quotas = Self.parseModelUsageTable(clean) + + if quotas.isEmpty { + if clean.contains("Login with Google") || clean.contains("Use Gemini API key") { + throw GeminiStatusProbeError.notLoggedIn + } + if clean.contains("Waiting for auth"), !clean.contains("Usage") { + throw GeminiStatusProbeError.notLoggedIn + } + throw GeminiStatusProbeError.parseFailed("No usage data found in /stats output") + } + + return GeminiStatusSnapshot( + modelQuotas: quotas, + rawText: text, + accountEmail: nil, + accountPlan: nil) + } + + private static func parseModelUsageTable(_ text: String) -> [GeminiModelQuota] { + let lines = text.components(separatedBy: .newlines) + var quotas: [GeminiModelQuota] = [] + + let pattern = #"(gemini[-\w.]+)\s+[\d-]+\s+([0-9]+(?:\.[0-9]+)?)\s*%\s*\(([^)]+)\)"# + guard let regex = try? NSRegularExpression(pattern: pattern, options: [.caseInsensitive]) else { + return [] + } + + for line in lines { + let cleanLine = line.replacingOccurrences(of: "│", with: " ") + let range = NSRange(cleanLine.startIndex..= 4 else { continue } + + guard let modelRange = Range(match.range(at: 1), in: cleanLine), + let pctRange = Range(match.range(at: 2), in: cleanLine), + let pct = Double(cleanLine[pctRange]) + else { continue } + + let modelId = String(cleanLine[modelRange]) + var resetDesc: String? + if let resetRange = Range(match.range(at: 3), in: cleanLine) { + resetDesc = String(cleanLine[resetRange]).trimmingCharacters(in: .whitespaces) + } + + quotas.append(GeminiModelQuota( + modelId: modelId, + percentLeft: pct, + resetTime: nil, + resetDescription: resetDesc)) + } + + return quotas + } +} + +extension GeminiStatusProbe { + fileprivate static func extractOAuthCredentials() -> OAuthClientCredentials? { + if let resolved = GeminiOAuthConfig.environmentClient() { + return OAuthClientCredentials(clientId: resolved.clientID, clientSecret: resolved.clientSecret) + } + if let path = GeminiOAuthConfig.configuredOAuth2JSPath, + let credentials = Self.parseOAuthCredentials(fromFile: path) + { + return credentials + } + if let credentials = Self.discoverOAuthCredentialsFromInstalledCLI() { + return OAuthClientCredentials(clientId: credentials.clientID, clientSecret: credentials.clientSecret) + } + if let credentials = Self.discoverOAuthCredentialsFromKnownInstallPaths() { + return credentials + } + return nil + } + + /// Optional Homebrew/npm prefixes for last-resort discovery when the gemini + /// binary cannot be resolved (GUI PATH / sandbox). Tests inject fake Cellar trees. + @TaskLocal public static var knownInstallPrefixesForTesting: [String]? + + fileprivate static func discoverOAuthCredentialsFromKnownInstallPaths() -> OAuthClientCredentials? { + let oauthFile = "dist/src/code_assist/oauth2.js" + let nestedOAuthFile = + "node_modules/@google/gemini-cli/node_modules/@google/gemini-cli-core/\(oauthFile)" + let home = FileManager.default.homeDirectoryForCurrentUser.path + + // When tests inject Homebrew prefixes, skip the hard-coded host paths so + // fixture Cellar trees are not shadowed by the developer's real install. + if Self.knownInstallPrefixesForTesting == nil { + let possiblePaths = [ + "/opt/homebrew/lib/node_modules/@google/gemini-cli-core/\(oauthFile)", + "/opt/homebrew/lib/\(nestedOAuthFile)", + "/usr/local/lib/node_modules/@google/gemini-cli-core/\(oauthFile)", + "/usr/local/lib/\(nestedOAuthFile)", + "\(home)/.npm-global/lib/node_modules/@google/gemini-cli-core/\(oauthFile)", + "\(home)/.npm-global/lib/\(nestedOAuthFile)", + ] + + for path in possiblePaths { + if let credentials = Self.parseOAuthCredentials(fromFile: path) { + return credentials + } + } + } + + // Homebrew Cellar/opt libexec layouts keep credentials inside the package + // bundle when GUI PATH cannot resolve `/opt/homebrew/bin/gemini`. + for packageRoot in Self.knownHomebrewGeminiPackageRoots() { + if let credentials = Self.extractOAuthCredentials(fromGeminiPackageRoot: packageRoot) { + return credentials + } + } + return nil + } + + fileprivate static func knownHomebrewPrefixes() -> [String] { + if let overrides = self.knownInstallPrefixesForTesting, !overrides.isEmpty { + return overrides + } + return ["/opt/homebrew", "/usr/local"] + } + + fileprivate static func knownHomebrewGeminiPackageRoots( + fileManager: FileManager = .default) -> [String] + { + var roots: [String] = [] + var seen = Set() + + func appendPackageRoot(under prefixRoot: String) { + let packageRoot = URL(fileURLWithPath: prefixRoot) + .appendingPathComponent("libexec") + .appendingPathComponent("lib") + .appendingPathComponent("node_modules") + .appendingPathComponent("@google") + .appendingPathComponent("gemini-cli") + .path + guard fileManager.fileExists(atPath: packageRoot), + seen.insert(packageRoot).inserted + else { + return + } + roots.append(packageRoot) + } + + for prefix in Self.knownHomebrewPrefixes() { + let optRoot = "\(prefix)/opt/gemini-cli" + if fileManager.fileExists(atPath: optRoot) { + appendPackageRoot(under: optRoot) + } + + let cellarRoot = "\(prefix)/Cellar/gemini-cli" + guard let versions = try? fileManager.contentsOfDirectory(atPath: cellarRoot) else { + continue + } + for version in versions.sorted() { + appendPackageRoot(under: "\(cellarRoot)/\(version)") + } + } + + return roots + } + + fileprivate static func parseOAuthCredentials(fromFile path: String) -> OAuthClientCredentials? { + guard let content = try? String(contentsOfFile: path, encoding: .utf8) else { + return nil + } + return Self.parseOAuthCredentials(from: content) + } + + fileprivate static func discoverOAuthCredentialsFromInstalledCLI() -> GeminiOAuthConfig.ClientCredentials? { + let env = ProcessInfo.processInfo.environment + + guard let geminiPath = BinaryLocator.resolveGeminiBinary( + env: env, + loginPATH: LoginShellPathCache.shared.current) + ?? TTYCommandRunner.which("gemini") + else { + return nil + } + + let resolvedGeminiPath = URL(fileURLWithPath: geminiPath).resolvingSymlinksInPath().path + + if let credentials = Self.extractOAuthCredentialsFromLegacyPaths(realGeminiPath: resolvedGeminiPath) { + return GeminiOAuthConfig.ClientCredentials( + clientID: credentials.clientId, + clientSecret: credentials.clientSecret) + } + + if Self.isLikelyFnmManagedPath(geminiPath) || Self.isLikelyFnmManagedPath(resolvedGeminiPath), + let fnmPath = Self.resolveExecutableOnEnvironmentPath(named: "fnm", environment: env) + ?? TTYCommandRunner.which("fnm"), + let packageRoot = Self.resolveGeminiPackageRootViaFnm(fnmPath: fnmPath, environment: env), + let credentials = Self.extractOAuthCredentials(fromGeminiPackageRoot: packageRoot) + { + return GeminiOAuthConfig.ClientCredentials( + clientID: credentials.clientId, + clientSecret: credentials.clientSecret) + } + + if let packageRoot = Self.findGeminiPackageRoot(startingAt: resolvedGeminiPath), + let credentials = Self.extractOAuthCredentials(fromGeminiPackageRoot: packageRoot) + { + return GeminiOAuthConfig.ClientCredentials( + clientID: credentials.clientId, + clientSecret: credentials.clientSecret) + } + + return nil + } + + /// Plan display strings with tier mapping: + /// - paidTier.name: Most-specific paid subscription label from Google, regardless of currentTier + /// - standard-tier: Paid subscription fallback (Code Assist Standard/Enterprise, Developer Program Premium) + /// - free-tier + hd claim: Workspace account (Gemini included free since Jan 2025) + /// - free-tier: Personal free account + /// - legacy-tier: Unknown legacy/grandfathered tier + /// - nil (API failed): Leave blank (no display) + fileprivate static func resolveAccountPlan( + tier: GeminiUserTierId?, + hostedDomain: String?, + paidTierName: String?) -> String? + { + // Match Gemini CLI's contract: a named paid tier is the most specific plan signal, + // even when currentTier is missing, unknown, or still reports free-tier. + if let paidTierName { + self.log.info("Paid tier detected", metadata: [ + "tier": tier?.rawValue ?? "unknown", + "plan": paidTierName, + ]) + return paidTierName + } + + switch (tier, hostedDomain) { + case (.standard, _): + return "Paid" + case let (.free, .some(domain)): + Self.log.info("Workspace account detected", metadata: ["domain": domain]) + return "Workspace" + case (.free, .none): + Self.log.info("Personal free account") + return "Free" + case (.legacy, _): + return "Legacy" + case (.none, _): + self.log.info("Tier detection failed, leaving plan blank") + return nil + } + } + + private static func parsePaidTierName(from json: [String: Any]) -> String? { + guard let paidTier = json["paidTier"] as? [String: Any], + let rawName = paidTier["name"] as? String + else { + return nil + } + let trimmed = rawName.trimmingCharacters(in: .whitespacesAndNewlines) + return trimmed.isEmpty ? nil : trimmed + } +} + +extension GeminiStatusProbe { + private static let processTimeoutQueue = DispatchQueue( + label: "com.steipete.codexbar.gemini-process-timeout", + qos: .utility, + attributes: .concurrent) + + package static func runProcess( + executable: String, + arguments: [String], + environment: [String: String], + timeout: TimeInterval) -> String? + { + let process = Process() + process.executableURL = URL(fileURLWithPath: executable) + process.arguments = arguments + + var mergedEnvironment = environment + mergedEnvironment["PATH"] = PathBuilder.effectivePATH( + purposes: [.tty, .nodeTooling], + env: environment, + loginPATH: LoginShellPathCache.shared.current) + process.environment = mergedEnvironment + + let stdout = Pipe() + let stderr = Pipe() + process.standardOutput = stdout + process.standardError = stderr + process.standardInput = nil + + let stdoutCapture = ProcessPipeCapture(pipe: stdout) + let stderrCapture = ProcessPipeCapture(pipe: stderr) + + do { + try process.run() + } catch { + stdoutCapture.stop() + stdout.fileHandleForWriting.closeFile() + stderrCapture.stop() + stderr.fileHandleForWriting.closeFile() + return nil + } + // Process has duplicated these descriptors. Closing the parent's copies lets readers observe EOF as + // soon as the helper exits instead of spending the full drain grace period on every successful call. + stdout.fileHandleForWriting.closeFile() + stderr.fileHandleForWriting.closeFile() + stdoutCapture.start() + stderrCapture.start() + let pid = process.processIdentifier + let processGroup: pid_t? = setpgid(pid, pid) == 0 ? pid : nil + + // Wait synchronously for Foundation to reap the helper. A separate timer owns timeout termination, + // so neither termination-handler scheduling nor stale Process.isRunning state controls normal exits. + let timeoutState = GeminiProcessTimeoutState() + let timeoutTimer = DispatchSource.makeTimerSource(queue: Self.processTimeoutQueue) + timeoutTimer.schedule(deadline: .now() + max(0, timeout)) + timeoutTimer.setEventHandler { + guard process.isRunning else { return } + timeoutState.markTimedOut() + SubprocessRunner.terminateProcess(process, processGroup: processGroup) + } + timeoutTimer.resume() + process.waitUntilExit() + timeoutTimer.cancel() + + if timeoutState.didTimeOut { + stdoutCapture.stop() + stderrCapture.stop() + return nil + } + + let data = stdoutCapture.finishFirstLineSynchronously(timeout: 1) + stderrCapture.stop() + let output = ProcessPipeCapture.decodeUTF8(data) + .trimmingCharacters(in: .whitespacesAndNewlines) + guard process.terminationStatus == 0, !output.isEmpty else { + return nil + } + + return output.components(separatedBy: .newlines).first? + .trimmingCharacters(in: .whitespacesAndNewlines) + } +} + +private final class GeminiProcessTimeoutState: @unchecked Sendable { + private let lock = NSLock() + private var timedOut = false + + var didTimeOut: Bool { + self.lock.lock() + defer { self.lock.unlock() } + return self.timedOut + } + + func markTimedOut() { + self.lock.lock() + self.timedOut = true + self.lock.unlock() + } +} diff --git a/Sources/CodexBarCore/Providers/Grok/GrokAuth.swift b/Sources/CodexBarCore/Providers/Grok/GrokAuth.swift new file mode 100644 index 0000000..9544808 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Grok/GrokAuth.swift @@ -0,0 +1,188 @@ +import Foundation + +public struct GrokCredentials: Sendable { + public let accessToken: String + public let refreshToken: String? + public let scope: String + public let authMode: String? + public let userId: String? + public let email: String? + public let firstName: String? + public let lastName: String? + public let teamId: String? + public let oidcIssuer: String? + public let oidcClientId: String? + public let expiresAt: Date? + public let createTime: Date? + + public init( + accessToken: String, + refreshToken: String?, + scope: String, + authMode: String?, + userId: String?, + email: String?, + firstName: String?, + lastName: String?, + teamId: String?, + oidcIssuer: String?, + oidcClientId: String?, + expiresAt: Date?, + createTime: Date?) + { + self.accessToken = accessToken + self.refreshToken = refreshToken + self.scope = scope + self.authMode = authMode + self.userId = userId + self.email = email + self.firstName = firstName + self.lastName = lastName + self.teamId = teamId + self.oidcIssuer = oidcIssuer + self.oidcClientId = oidcClientId + self.expiresAt = expiresAt + self.createTime = createTime + } + + public var displayName: String? { + let parts = [self.firstName, self.lastName].compactMap { $0?.nilIfEmpty } + guard !parts.isEmpty else { return nil } + return parts.joined(separator: " ") + } + + public var isExpired: Bool { + guard let expiresAt else { return false } + return Date() >= expiresAt + } + + public var loginMethod: String? { + switch self.authMode?.lowercased() { + case "oidc": "SuperGrok" + case "session": "session" + case nil: nil + default: self.authMode + } + } +} + +public enum GrokCredentialsError: LocalizedError, Sendable { + case notFound + case decodeFailed(String) + case missingTokens + + public var errorDescription: String? { + switch self { + case .notFound: + "Grok auth.json not found. Run `grok login` to authenticate." + case let .decodeFailed(message): + "Failed to decode Grok credentials: \(message)" + case .missingTokens: + "Grok auth.json exists but contains no access tokens." + } + } +} + +public enum GrokCredentialsStore { + /// Top-level OIDC scope used by `grok login` for SuperGrok subscribers. + public static let oidcScopePrefix = "https://auth.x.ai::" + /// Legacy/session scope used by older `grok login` flows. + public static let legacySessionScope = "https://accounts.x.ai/sign-in" + + public static func grokHomeURL( + env: [String: String] = ProcessInfo.processInfo.environment, + fileManager: FileManager = .default) -> URL + { + if let custom = env["GROK_HOME"]?.nilIfEmpty { + return URL(fileURLWithPath: (custom as NSString).expandingTildeInPath) + } + let home = fileManager.homeDirectoryForCurrentUser + return home.appendingPathComponent(".grok", isDirectory: true) + } + + public static func authFileURL( + env: [String: String] = ProcessInfo.processInfo.environment, + fileManager: FileManager = .default) -> URL + { + self.grokHomeURL(env: env, fileManager: fileManager).appendingPathComponent("auth.json") + } + + public static func load(env: [String: String] = ProcessInfo.processInfo.environment) throws -> GrokCredentials { + let url = self.authFileURL(env: env) + guard FileManager.default.fileExists(atPath: url.path) else { + throw GrokCredentialsError.notFound + } + let data = try Data(contentsOf: url) + return try self.parse(data: data) + } + + public static func parse(data: Data) throws -> GrokCredentials { + let raw: Any + do { + raw = try JSONSerialization.jsonObject(with: data) + } catch { + throw GrokCredentialsError.decodeFailed(error.localizedDescription) + } + guard let root = raw as? [String: Any] else { + throw GrokCredentialsError.decodeFailed("Invalid JSON (expected object at root)") + } + + // `auth.json` is a map keyed by scope URL. Prefer the OIDC scope (SuperGrok), + // fall back to the legacy session scope. + let preferredEntry = Self.selectPreferredEntry(in: root) + guard let (scope, entry) = preferredEntry else { + throw GrokCredentialsError.missingTokens + } + guard let key = entry["key"] as? String, !key.isEmpty else { + throw GrokCredentialsError.missingTokens + } + + return GrokCredentials( + accessToken: key, + refreshToken: (entry["refresh_token"] as? String)?.nilIfEmpty, + scope: scope, + authMode: (entry["auth_mode"] as? String)?.nilIfEmpty, + userId: (entry["user_id"] as? String)?.nilIfEmpty, + email: (entry["email"] as? String)?.nilIfEmpty, + firstName: (entry["first_name"] as? String)?.nilIfEmpty, + lastName: (entry["last_name"] as? String)?.nilIfEmpty, + teamId: (entry["team_id"] as? String)?.nilIfEmpty, + oidcIssuer: (entry["oidc_issuer"] as? String)?.nilIfEmpty, + oidcClientId: (entry["oidc_client_id"] as? String)?.nilIfEmpty, + expiresAt: Self.parseDate(entry["expires_at"]), + createTime: Self.parseDate(entry["create_time"])) + } + + private static func selectPreferredEntry(in root: [String: Any]) -> (scope: String, entry: [String: Any])? { + var oidcCandidate: (String, [String: Any])? + var legacyCandidate: (String, [String: Any])? + for (scope, value) in root { + guard let entry = value as? [String: Any] else { continue } + // Only accept entries that actually carry a usable bearer token. A + // stale/partial OIDC record (key missing or empty) must not shadow a + // healthy legacy session entry. + guard let key = entry["key"] as? String, !key.isEmpty else { continue } + if scope.hasPrefix(self.oidcScopePrefix) { + oidcCandidate = (scope, entry) + } else if scope == self.legacySessionScope || scope.contains("/sign-in") { + legacyCandidate = (scope, entry) + } + } + return oidcCandidate ?? legacyCandidate + } + + private static func parseDate(_ raw: Any?) -> Date? { + guard let value = raw as? String, !value.isEmpty else { return nil } + let formatter = ISO8601DateFormatter() + formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds] + if let date = formatter.date(from: value) { return date } + formatter.formatOptions = [.withInternetDateTime] + return formatter.date(from: value) + } +} + +extension String { + fileprivate var nilIfEmpty: String? { + self.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty ? nil : self + } +} diff --git a/Sources/CodexBarCore/Providers/Grok/GrokCookieImporter.swift b/Sources/CodexBarCore/Providers/Grok/GrokCookieImporter.swift new file mode 100644 index 0000000..2efd4ee --- /dev/null +++ b/Sources/CodexBarCore/Providers/Grok/GrokCookieImporter.swift @@ -0,0 +1,213 @@ +import Foundation + +#if os(macOS) +import SweetCookieKit + +public enum GrokCookieImporter { + private static let importSessionCacheTTL: TimeInterval = 5 + private static let importSessionCache = ImportSessionCache(ttl: importSessionCacheTTL) + private static let log = CodexBarLog.logger(LogCategories.providers) + private static let cookieClient = BrowserCookieClient() + private static let cookieDomains = ["grok.com"] + private static let cookieImportOrder: BrowserCookieImportOrder = + ProviderDefaults.metadata[.grok]?.browserCookieOrder ?? Browser.defaultImportOrder + + public struct SessionInfo: Sendable { + public let cookies: [HTTPCookie] + public let sourceLabel: String + + public init(cookies: [HTTPCookie], sourceLabel: String) { + self.cookies = cookies + self.sourceLabel = sourceLabel + } + + public var cookieHeader: String { + self.cookies.map { "\($0.name)=\($0.value)" }.joined(separator: "; ") + } + } + + public static func importSessions( + browserDetection: BrowserDetection = BrowserDetection(), + logger: ((String) -> Void)? = nil) throws -> [SessionInfo] + { + if let cached = self.cachedImportSessions() { + return cached + } + + var sessions: [SessionInfo] = [] + let candidates = self.cookieImportOrder.cookieImportCandidates(using: browserDetection) + for browserSource in candidates { + do { + let perSource = try self.importSessions(from: browserSource, logger: logger) + sessions.append(contentsOf: perSource) + } catch { + BrowserCookieAccessGate.recordIfNeeded(error) + self.emit( + "\(browserSource.displayName) cookie import failed: \(error.localizedDescription)", + logger: logger) + } + } + + guard !sessions.isEmpty else { throw GrokWebBillingError.missingCredentials } + self.storeImportSessions(sessions) + return sessions + } + + public static func importSessions( + from browserSource: Browser, + logger: ((String) -> Void)? = nil) throws -> [SessionInfo] + { + let query = BrowserCookieQuery(domains: self.cookieDomains) + let log: (String) -> Void = { msg in self.emit(msg, logger: logger) } + let sources = try Self.cookieClient.codexBarRecords( + matching: query, + in: browserSource, + logger: log) + + var sessions: [SessionInfo] = [] + let grouped = Dictionary(grouping: sources, by: { $0.store.profile.id }) + let sortedGroups = grouped.values.sorted { lhs, rhs in + self.mergedLabel(for: lhs) < self.mergedLabel(for: rhs) + } + + for group in sortedGroups where !group.isEmpty { + let label = self.mergedLabel(for: group) + let mergedRecords = self.mergeRecords(group) + guard mergedRecords.contains(where: { $0.name == "sso" || $0.name == "sso-rw" }) else { continue } + let httpCookies = BrowserCookieClient.makeHTTPCookies(mergedRecords, origin: query.origin) + guard !httpCookies.isEmpty else { continue } + log("Found Grok session cookies in \(label)") + sessions.append(SessionInfo(cookies: httpCookies, sourceLabel: label)) + } + return sessions + } + + public static func importSession( + browserDetection: BrowserDetection = BrowserDetection(), + logger: ((String) -> Void)? = nil) throws -> SessionInfo + { + let sessions = try self.importSessions(browserDetection: browserDetection, logger: logger) + guard let first = sessions.first else { throw GrokWebBillingError.missingCredentials } + return first + } + + public static func hasSession( + browserDetection: BrowserDetection = BrowserDetection(), + logger: ((String) -> Void)? = nil) -> Bool + { + do { + _ = try self.importSession(browserDetection: browserDetection, logger: logger) + return true + } catch { + return false + } + } + + static func invalidateImportSessionCache() { + self.importSessionCache.invalidate() + } + + private static func emit(_ message: String, logger: ((String) -> Void)?) { + logger?("[grok-cookie] \(message)") + self.log.debug("\(message)") + } + + private static func cachedImportSessions(now: Date = Date()) -> [SessionInfo]? { + self.importSessionCache.load(now: now) + } + + private static func storeImportSessions(_ sessions: [SessionInfo], now: Date = Date()) { + self.importSessionCache.store(sessions, now: now) + } + + private static func mergedLabel(for sources: [BrowserCookieStoreRecords]) -> String { + guard let base = sources.map(\.label).min() else { return "Unknown" } + if base.hasSuffix(" (Network)") { + return String(base.dropLast(" (Network)".count)) + } + return base + } + + private static func mergeRecords(_ sources: [BrowserCookieStoreRecords]) -> [BrowserCookieRecord] { + let sortedSources = sources.sorted { lhs, rhs in + self.storePriority(lhs.store.kind) < self.storePriority(rhs.store.kind) + } + var mergedByKey: [String: BrowserCookieRecord] = [:] + for source in sortedSources { + for record in source.records { + let key = self.recordKey(record) + if let existing = mergedByKey[key] { + if self.shouldReplace(existing: existing, candidate: record) { + mergedByKey[key] = record + } + } else { + mergedByKey[key] = record + } + } + } + return Array(mergedByKey.values) + } + + private static func storePriority(_ kind: BrowserCookieStoreKind) -> Int { + switch kind { + case .network: 0 + case .primary: 1 + case .safari: 2 + } + } + + private static func recordKey(_ record: BrowserCookieRecord) -> String { + "\(record.name)|\(record.domain)|\(record.path)" + } + + private static func shouldReplace(existing: BrowserCookieRecord, candidate: BrowserCookieRecord) -> Bool { + switch (existing.expires, candidate.expires) { + case let (lhs?, rhs?): rhs > lhs + case (nil, .some): true + case (.some, nil): false + case (nil, nil): false + } + } + + private final class ImportSessionCache: @unchecked Sendable { + private let ttl: TimeInterval + private let lock = NSLock() + private var entry: (sessions: [SessionInfo], expiresAt: Date)? + + init(ttl: TimeInterval) { + self.ttl = ttl + } + + func load(now: Date) -> [SessionInfo]? { + self.lock.lock() + defer { self.lock.unlock() } + guard let entry = self.entry, entry.expiresAt > now else { + self.entry = nil + return nil + } + return entry.sessions + } + + func store(_ sessions: [SessionInfo], now: Date) { + self.lock.lock() + self.entry = (sessions, now.addingTimeInterval(self.ttl)) + self.lock.unlock() + } + + func invalidate() { + self.lock.lock() + self.entry = nil + self.lock.unlock() + } + } +} +#else +public enum GrokCookieImporter { + public static func hasSession( + browserDetection _: BrowserDetection = BrowserDetection(), + logger _: ((String) -> Void)? = nil) -> Bool + { + false + } +} +#endif diff --git a/Sources/CodexBarCore/Providers/Grok/GrokLocalSessionScanner.swift b/Sources/CodexBarCore/Providers/Grok/GrokLocalSessionScanner.swift new file mode 100644 index 0000000..c5b1afd --- /dev/null +++ b/Sources/CodexBarCore/Providers/Grok/GrokLocalSessionScanner.swift @@ -0,0 +1,100 @@ +import Foundation + +/// Aggregated stats from local `~/.grok/sessions/**/signals.json` files. +/// Used as a local fallback view when the JSON-RPC billing call is unavailable. +public struct GrokLocalSessionSummary: Sendable { + public let sessionCount: Int + public let totalTokens: Int + public let lastSessionAt: Date? + public let primaryModel: String? + public let models: [String] + + public init( + sessionCount: Int, + totalTokens: Int, + lastSessionAt: Date?, + primaryModel: String?, + models: [String]) + { + self.sessionCount = sessionCount + self.totalTokens = totalTokens + self.lastSessionAt = lastSessionAt + self.primaryModel = primaryModel + self.models = models + } +} + +public enum GrokLocalSessionScanner { + public static let defaultLookbackDays = 30 + + /// Walk `~/.grok/sessions///signals.json` and aggregate stats. + public static func summarize( + env: [String: String] = ProcessInfo.processInfo.environment, + fileManager: FileManager = .default, + lookbackDays: Int = defaultLookbackDays, + now: Date = .init()) -> GrokLocalSessionSummary + { + let root = GrokCredentialsStore.grokHomeURL(env: env, fileManager: fileManager) + .appendingPathComponent("sessions", isDirectory: true) + guard let rootEnum = fileManager.enumerator( + at: root, + includingPropertiesForKeys: [.contentModificationDateKey, .isDirectoryKey], + options: [.skipsHiddenFiles]) + else { + return GrokLocalSessionSummary( + sessionCount: 0, + totalTokens: 0, + lastSessionAt: nil, + primaryModel: nil, + models: []) + } + + let lookbackCutoff = Calendar.current.date(byAdding: .day, value: -lookbackDays, to: now) ?? now + var sessionCount = 0 + var totalTokens = 0 + var lastSessionAt: Date? + var modelCounts: [String: Int] = [:] + + while let url = rootEnum.nextObject() as? URL { + guard url.lastPathComponent == "signals.json" else { continue } + let attrs = try? url.resourceValues(forKeys: [.contentModificationDateKey]) + let mtime = attrs?.contentModificationDate ?? Date.distantPast + guard mtime >= lookbackCutoff else { continue } + + guard let data = try? Data(contentsOf: url), + let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] + else { continue } + + sessionCount += 1 + let beforeCompaction = (json["totalTokensBeforeCompaction"] as? Int) ?? 0 + let contextUsed = (json["contextTokensUsed"] as? Int) ?? 0 + totalTokens += beforeCompaction + contextUsed + + if mtime > (lastSessionAt ?? Date.distantPast) { + lastSessionAt = mtime + } + + if let primary = (json["primaryModelId"] as? String)?.trimmingCharacters(in: .whitespacesAndNewlines), + !primary.isEmpty + { + modelCounts[primary, default: 0] += 1 + } + if let models = json["modelsUsed"] as? [String] { + for model in models { + let trimmed = model.trimmingCharacters(in: .whitespacesAndNewlines) + if !trimmed.isEmpty { + modelCounts[trimmed, default: 0] += 1 + } + } + } + } + + let sortedModels = modelCounts.sorted { $0.value > $1.value }.map(\.key) + return GrokLocalSessionSummary( + sessionCount: sessionCount, + totalTokens: totalTokens, + lastSessionAt: lastSessionAt, + primaryModel: sortedModels.first, + models: sortedModels) + } +} diff --git a/Sources/CodexBarCore/Providers/Grok/GrokProviderDescriptor.swift b/Sources/CodexBarCore/Providers/Grok/GrokProviderDescriptor.swift new file mode 100644 index 0000000..6aaf76f --- /dev/null +++ b/Sources/CodexBarCore/Providers/Grok/GrokProviderDescriptor.swift @@ -0,0 +1,223 @@ +import Foundation + +public enum GrokProviderDescriptor { + public static let descriptor: ProviderDescriptor = Self.makeDescriptor() + + static func makeDescriptor() -> ProviderDescriptor { + ProviderDescriptor( + id: .grok, + metadata: ProviderMetadata( + id: .grok, + displayName: "Grok", + sessionLabel: "Credits", + weeklyLabel: "On-demand", + opusLabel: nil, + supportsOpus: false, + supportsCredits: false, + creditsHint: "", + toggleTitle: "Show Grok usage", + cliName: "grok", + defaultEnabled: false, + isPrimaryProvider: false, + usesAccountFallback: false, + browserCookieOrder: ProviderBrowserCookieDefaults.grokCookieImportOrder, + dashboardURL: "https://grok.com/?_s=usage", + changelogURL: "https://x.ai/news", + statusPageURL: nil, + statusLinkURL: "https://status.x.ai"), + branding: ProviderBranding( + iconStyle: .grok, + iconResourceName: "ProviderIcon-grok", + color: ProviderColor(red: 16 / 255, green: 163 / 255, blue: 127 / 255)), + tokenCost: ProviderTokenCostConfig( + supportsTokenCost: false, + noDataMessage: { "Grok cost summary is not supported yet." }), + fetchPlan: ProviderFetchPlan( + sourceModes: [.auto, .cli, .web], + pipeline: ProviderFetchPipeline(resolveStrategies: self.resolveStrategies)), + cli: ProviderCLIConfig( + name: "grok", + versionDetector: { _ in GrokStatusProbe.detectVersion() })) + } + + private static func resolveStrategies(context: ProviderFetchContext) async -> [any ProviderFetchStrategy] { + switch context.sourceMode { + case .auto: + [GrokCLIFetchStrategy(), GrokWebFetchStrategy()] + case .cli: + [GrokCLIFetchStrategy()] + case .web: + [GrokWebFetchStrategy()] + case .api, .oauth: + [] + } + } + + /// Returns a contextual label for Grok's primary usage bar ("Weekly" or "Monthly"). + /// Prefer the billing period duration when available; fall back to reset distance for + /// web billing payloads that expose only a reset timestamp. + public static func primaryLabel(window: RateWindow?, now: Date = .now) -> String? { + if let minutes = window?.windowMinutes { + return self.primaryLabel(duration: TimeInterval(minutes) * 60) + } + return self.primaryLabel(resetsAt: window?.resetsAt, now: now) + } + + public static func primaryLabel(resetsAt: Date?, now: Date = .now) -> String? { + guard let resetsAt else { return nil } + return self.primaryLabel(duration: resetsAt.timeIntervalSince(now)) + } + + private static func primaryLabel(duration seconds: TimeInterval) -> String? { + guard seconds > 3600 else { return nil } + let days = Int((seconds / 86400).rounded(.toNearestOrAwayFromZero)) + if (4...12).contains(days) { return "Weekly" } + if (20...45).contains(days) { return "Monthly" } + return nil + } +} + +struct GrokCLIFetchStrategy: ProviderFetchStrategy { + let id: String = "grok.cli" + let kind: ProviderFetchKind = .cli + + func isAvailable(_ context: ProviderFetchContext) async -> Bool { + BinaryLocator.resolveGrokBinary(env: context.env) != nil + } + + func fetch(_ context: ProviderFetchContext) async throws -> ProviderFetchResult { + let probe = GrokStatusProbe() + let snap = try await probe.fetch(env: context.env) + return self.makeResult( + usage: snap.toUsageSnapshot(), + sourceLabel: "grok-cli") + } + + func shouldFallback(on _: Error, context: ProviderFetchContext) -> Bool { + context.sourceMode == .auto + } +} + +struct GrokWebFetchStrategy: ProviderFetchStrategy { + let id: String = "grok.web" + let kind: ProviderFetchKind = .web + + static func canImportBrowserCookies(runtime: ProviderRuntime, env: [String: String]) -> Bool { + runtime == .app || env["CODEXBAR_ALLOW_BROWSER_COOKIE_IMPORT"] == "1" + } + + func isAvailable(_ context: ProviderFetchContext) async -> Bool { + #if os(macOS) + if Self.canImportBrowserCookies(runtime: context.runtime, env: context.env), + GrokCookieImporter.hasSession(browserDetection: context.browserDetection) + { + return true + } + #endif + return FileManager.default.fileExists(atPath: GrokCredentialsStore.authFileURL(env: context.env).path) + } + + func fetch(_ context: ProviderFetchContext) async throws -> ProviderFetchResult { + let (webBilling, sourceLabel, authenticatedByAuthFile) = try await self.fetchWebBilling(context: context) + let credentials = Self.credentialsForWebBillingSnapshot( + credentials: try? GrokCredentialsStore.load(env: context.env), + authenticatedByAuthFile: authenticatedByAuthFile) + let snapshot = GrokUsageSnapshot( + billing: nil, + webBilling: webBilling, + credentials: GrokStatusProbe.credentialsForSnapshot( + credentials: credentials, + billing: nil, + webBilling: webBilling), + localSummary: GrokLocalSessionScanner.summarize(env: context.env), + cliVersion: GrokStatusProbe.detectVersion(env: context.env), + updatedAt: Date()) + return self.makeResult( + usage: snapshot.toUsageSnapshot(), + sourceLabel: sourceLabel) + } + + private func fetchWebBilling(context: ProviderFetchContext) async throws -> ( + snapshot: GrokWebBillingSnapshot, + sourceLabel: String, + authenticatedByAuthFile: Bool) + { + let credentialsResult: Result = Result { + try GrokCredentialsStore.load(env: context.env) + } + let browserCredentials = try? credentialsResult.get() + + #if os(macOS) + if Self.canImportBrowserCookies(runtime: context.runtime, env: context.env) { + var lastCookieError: Error? + do { + let sessions = try GrokCookieImporter.importSessions(browserDetection: context.browserDetection) + let (snapshot, sourceLabel) = try await Self.fetchFirstValidCookieSession( + sessions, + credentials: browserCredentials) + return (snapshot, sourceLabel, false) + } catch { + lastCookieError = error + } + if browserCredentials == nil { + if FileManager.default.fileExists( + atPath: GrokCredentialsStore.authFileURL(env: context.env).path) + { + _ = try credentialsResult.get() + } + throw lastCookieError ?? GrokWebBillingError.missingCredentials + } + } + #endif + + let authCredentials = try credentialsResult.get() + guard !authCredentials.isExpired else { + throw GrokWebBillingError.missingCredentials + } + let snapshot = try await GrokWebBillingFetcher.fetch(credentials: authCredentials) + return (snapshot, "grok-web", true) + } + + static func credentialsForWebBillingSnapshot( + credentials: GrokCredentials?, + authenticatedByAuthFile: Bool) -> GrokCredentials? + { + authenticatedByAuthFile ? credentials : nil + } + + #if os(macOS) + static func fetchFirstValidCookieSession( + _ sessions: [GrokCookieImporter.SessionInfo], + credentials: GrokCredentials? = nil, + fetch: ((String, GrokCredentials?) async throws -> GrokWebBillingSnapshot)? = nil) async throws + -> (GrokWebBillingSnapshot, String) + { + let fetchSnapshot = fetch ?? { cookieHeader, credentials in + try await GrokWebBillingFetcher.fetch( + cookieHeader: cookieHeader, + credentials: credentials) + } + var lastError: Error? + for session in sessions { + for authCredentials in Self.cookieAuthAttempts(credentials: credentials) { + do { + let snapshot = try await fetchSnapshot(session.cookieHeader, authCredentials) + return (snapshot, session.sourceLabel) + } catch { + lastError = error + } + } + } + throw lastError ?? GrokWebBillingError.missingCredentials + } + + static func cookieAuthAttempts(credentials: GrokCredentials?) -> [GrokCredentials?] { + guard let credentials, !credentials.isExpired else { return [nil] } + return [credentials, nil] + } + #endif + + func shouldFallback(on _: Error, context _: ProviderFetchContext) -> Bool { + false + } +} diff --git a/Sources/CodexBarCore/Providers/Grok/GrokRPCClient.swift b/Sources/CodexBarCore/Providers/Grok/GrokRPCClient.swift new file mode 100644 index 0000000..a0feea7 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Grok/GrokRPCClient.swift @@ -0,0 +1,371 @@ +import Foundation + +/// JSON-RPC client for `grok agent stdio` (ACP protocol). +/// +/// The protocol mirrors Codex's app-server (newline-delimited JSON-RPC 2.0 over stdin/stdout), +/// but uses `protocolVersion`/`clientCapabilities` for the `initialize` call instead of +/// `clientInfo`. Billing is fetched via the `x.ai/billing` extension method. +final class GrokRPCClient: @unchecked Sendable { + private static let log = CodexBarLog.logger(LogCategories.grok) + + private let process = Process() + private let stdinPipe = Pipe() + private let stdoutPipe = Pipe() + private let stderrPipe = Pipe() + private let initializeTimeoutSeconds: TimeInterval + private let requestTimeoutSeconds: TimeInterval + private var nextID: Int = 1 + private let stdoutLineStream: AsyncStream + private let stdoutLineContinuation: AsyncStream.Continuation + + init( + executable: String = "grok", + arguments: [String] = ["agent", "stdio"], + environment: [String: String] = ProcessInfo.processInfo.environment, + initializeTimeoutSeconds: TimeInterval = 4.0, + requestTimeoutSeconds: TimeInterval = 3.0) throws + { + self.initializeTimeoutSeconds = initializeTimeoutSeconds + self.requestTimeoutSeconds = requestTimeoutSeconds + var stdoutContinuation: AsyncStream.Continuation! + self.stdoutLineStream = AsyncStream { continuation in + stdoutContinuation = continuation + } + self.stdoutLineContinuation = stdoutContinuation + + let resolvedExec = BinaryLocator.resolveGrokBinary(env: environment) + ?? TTYCommandRunner.which(executable) + + guard let resolvedExec else { + Self.log.warning("Grok RPC binary not found", metadata: ["binary": executable]) + throw GrokRPCError.binaryNotFound + } + + var env = environment + env["PATH"] = PathBuilder.effectivePATH(purposes: [.rpc], env: env) + + self.process.environment = env + self.process.executableURL = URL(fileURLWithPath: "/usr/bin/env") + self.process.arguments = [resolvedExec] + arguments + self.process.standardInput = self.stdinPipe + self.process.standardOutput = self.stdoutPipe + self.process.standardError = self.stderrPipe + + do { + try self.process.run() + Self.log.debug("Grok RPC started", metadata: ["binary": resolvedExec]) + } catch { + Self.log.warning("Grok RPC failed to start", metadata: ["error": error.localizedDescription]) + throw GrokRPCError.startFailed(error.localizedDescription) + } + + let stdoutHandle = self.stdoutPipe.fileHandleForReading + let stdoutLineContinuation = self.stdoutLineContinuation + let stdoutBuffer = LineBuffer() + stdoutHandle.readabilityHandler = { handle in + let data = handle.availableData + if data.isEmpty { + handle.readabilityHandler = nil + stdoutLineContinuation.finish() + return + } + let lines = stdoutBuffer.appendAndDrainLines(data) + for lineData in lines { + stdoutLineContinuation.yield(lineData) + } + } + + let stderrHandle = self.stderrPipe.fileHandleForReading + stderrHandle.readabilityHandler = { handle in + let data = handle.availableData + if data.isEmpty { + handle.readabilityHandler = nil + return + } + guard let text = String(data: data, encoding: .utf8), !text.isEmpty else { return } + for line in text.split(whereSeparator: \.isNewline) { + #if !os(Linux) + fputs("[grok stderr] \(line)\n", stderr) + #endif + } + } + } + + deinit { + self.shutdown() + } + + func initialize() async throws { + let params: [String: Any] = [ + "protocolVersion": "1", + "clientCapabilities": [ + "fs": ["readTextFile": false, "writeTextFile": false], + "terminal": false, + ], + ] + _ = try await self.request( + method: "initialize", + params: params, + timeout: self.initializeTimeoutSeconds) + } + + /// Calls `x.ai/billing` and returns the decoded response. + func fetchBilling() async throws -> GrokBillingResponse { + let message = try await self.request(method: "x.ai/billing", params: [:]) + return try self.decodeResult(from: message) + } + + func shutdown() { + if self.process.isRunning { + Self.log.debug("Grok RPC stopping") + self.process.terminate() + } + } + + // MARK: - JSON-RPC plumbing (mirrors CodexRPCClient) + + private struct SendableJSONMessage: @unchecked Sendable { + let value: [String: Any] + } + + private func request( + method: String, + params: [String: Any]? = nil, + timeout: TimeInterval? = nil) async throws -> [String: Any] + { + let id = self.nextID + self.nextID += 1 + try self.sendRequest(id: id, method: method, params: params) + + let resolvedTimeout = timeout ?? self.requestTimeoutSeconds + let wrapped = try await self.withTimeout(seconds: resolvedTimeout, method: method) { + while true { + let message = try await self.readNextMessage() + // Skip notifications (no id) or unrelated responses. + if message["id"] == nil { continue } + guard let messageID = self.jsonID(message["id"]), messageID == id else { continue } + if let error = message["error"] as? [String: Any] { + let messageText = (error["message"] as? String) ?? "unknown JSON-RPC error" + throw GrokRPCError.requestFailed(messageText) + } + return SendableJSONMessage(value: message) + } + } + return wrapped.value + } + + private func withTimeout( + seconds: TimeInterval, + method: String, + body: @escaping @Sendable () async throws -> T) async throws -> T + { + try await withThrowingTaskGroup(of: T.self) { group in + group.addTask { try await body() } + group.addTask { [weak self] in + try await Task.sleep(for: .seconds(seconds)) + self?.terminateProcessForTimeout(method: method) + throw GrokRPCError.timeout(method: method) + } + do { + guard let result = try await group.next() else { + throw GrokRPCError.timeout(method: method) + } + group.cancelAll() + return result + } catch { + group.cancelAll() + throw error + } + } + } + + private func terminateProcessForTimeout(method: String) { + if self.process.isRunning { + Self.log.warning("Grok RPC timed out on `\(method)`; terminating process") + self.process.terminate() + } + } + + private func sendRequest(id: Int, method: String, params: [String: Any]?) throws { + let paramsValue: Any = params ?? [:] + let payload: [String: Any] = [ + "jsonrpc": "2.0", + "id": id, + "method": method, + "params": paramsValue, + ] + try self.sendPayload(payload) + } + + private func sendPayload(_ payload: [String: Any]) throws { + let raw = try JSONSerialization.data(withJSONObject: payload) + // Foundation's JSONSerialization escapes "/" as "\/" by default. Grok's + // ACP server treats the escaped form as a *different* method name (it does + // not unescape before lookup), so `x.ai/billing` becomes "Method not found" + // when sent as `x.ai\/billing`. Re-encode without slash escapes to match + // the on-the-wire shape the grok agent expects. + let unescaped = String(data: raw, encoding: .utf8)? + .replacingOccurrences(of: "\\/", with: "/") + let data = unescaped.flatMap { $0.data(using: .utf8) } ?? raw + if let preview = String(data: data.prefix(200), encoding: .utf8) { + Self.log.debug("grok rpc -> \(preview)") + } + self.stdinPipe.fileHandleForWriting.write(data) + self.stdinPipe.fileHandleForWriting.write(Data([0x0A])) + } + + private func readNextMessage() async throws -> [String: Any] { + for await lineData in self.stdoutLineStream { + if lineData.isEmpty { continue } + if let preview = String(data: lineData.prefix(300), encoding: .utf8) { + Self.log.debug("grok rpc <- \(preview)") + } + if let json = try? JSONSerialization.jsonObject(with: lineData) as? [String: Any] { + return json + } + } + throw GrokRPCError.malformed("grok agent stdio closed stdout") + } + + private func decodeResult(from message: [String: Any]) throws -> T { + guard let result = message["result"] else { + throw GrokRPCError.malformed("missing result field") + } + let data = try JSONSerialization.data(withJSONObject: result) + let decoder = JSONDecoder() + return try decoder.decode(T.self, from: data) + } + + private func jsonID(_ value: Any?) -> Int? { + switch value { + case let int as Int: int + case let number as NSNumber: number.intValue + default: nil + } + } + + private final class LineBuffer: @unchecked Sendable { + private var buffer = Data() + private let lock = NSLock() + + func appendAndDrainLines(_ data: Data) -> [Data] { + self.lock.lock() + defer { lock.unlock() } + self.buffer.append(data) + var out: [Data] = [] + while let newline = self.buffer.firstIndex(of: 0x0A) { + let lineData = Data(self.buffer[.. }` in the wire format. +public struct GrokBillingResponse: Codable, Sendable { + public let billingCycle: GrokBillingCycle? + public let monthlyLimit: GrokCent? + public let onDemandCap: GrokCent? + public let onDemandEnabled: Bool? + public let disabledByConfig: Bool? + public let usage: GrokBillingUsage? + + private enum CodingKeys: String, CodingKey { + case billingCycle + case monthlyLimit + case onDemandCap + case onDemandEnabled = "on_demand_enabled" + case disabledByConfig + case usage + } +} + +public struct GrokBillingCycle: Codable, Sendable { + public let billingPeriodStart: String? + public let billingPeriodEnd: String? +} + +public struct GrokBillingUsage: Codable, Sendable { + public let includedUsed: GrokCent? + public let onDemandUsed: GrokCent? + public let totalUsed: GrokCent? +} + +public struct GrokCent: Codable, Sendable { + public let val: Int? +} + +extension GrokBillingResponse { + /// Convenience accessor: monthly usage as a 0–100 percent. + public var monthlyUsedPercent: Double? { + guard let limit = self.monthlyLimit?.val, limit > 0, + let used = self.usage?.totalUsed?.val + else { return nil } + return min(100.0, max(0.0, Double(used) / Double(limit) * 100.0)) + } + + public var billingPeriodEndDate: Date? { + guard let raw = self.billingCycle?.billingPeriodEnd else { return nil } + return GrokBillingResponse.parseISO8601(raw) + } + + public var billingPeriodStartDate: Date? { + guard let raw = self.billingCycle?.billingPeriodStart else { return nil } + return GrokBillingResponse.parseISO8601(raw) + } + + public var billingPeriodMinutes: Int? { + guard let start = self.billingPeriodStartDate, + let end = self.billingPeriodEndDate, + end > start + else { return nil } + return Int(end.timeIntervalSince(start) / 60) + } + + private static func parseISO8601(_ raw: String) -> Date? { + let formatter = ISO8601DateFormatter() + formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds] + if let date = formatter.date(from: raw) { return date } + formatter.formatOptions = [.withInternetDateTime] + return formatter.date(from: raw) + } +} diff --git a/Sources/CodexBarCore/Providers/Grok/GrokStatusProbe.swift b/Sources/CodexBarCore/Providers/Grok/GrokStatusProbe.swift new file mode 100644 index 0000000..5473d24 --- /dev/null +++ b/Sources/CodexBarCore/Providers/Grok/GrokStatusProbe.swift @@ -0,0 +1,147 @@ +import Foundation + +public struct GrokUsageSnapshot: Sendable { + public let billing: GrokBillingResponse? + public let webBilling: GrokWebBillingSnapshot? + public let credentials: GrokCredentials? + public let localSummary: GrokLocalSessionSummary? + public let cliVersion: String? + public let updatedAt: Date + + public init( + billing: GrokBillingResponse?, + webBilling: GrokWebBillingSnapshot? = nil, + credentials: GrokCredentials?, + localSummary: GrokLocalSessionSummary?, + cliVersion: String?, + updatedAt: Date) + { + self.billing = billing + self.webBilling = webBilling + self.credentials = credentials + self.localSummary = localSummary + self.cliVersion = cliVersion + self.updatedAt = updatedAt + } + + public func toUsageSnapshot() -> UsageSnapshot { + // Primary window: credit usage (against included limit) from the CLI RPC, + // falling back to the web billing RPC used by grok.com when the agent surface lacks billing. + var primary: RateWindow? + if let billing, + let percent = billing.monthlyUsedPercent + { + primary = RateWindow( + usedPercent: percent, + windowMinutes: billing.billingPeriodMinutes, + resetsAt: billing.billingPeriodEndDate, + resetDescription: nil) + } else if let webBilling, + let percent = webBilling.usedPercent + { + primary = RateWindow( + usedPercent: percent, + windowMinutes: nil, + resetsAt: webBilling.resetsAt, + resetDescription: nil) + } + + let identity = ProviderIdentitySnapshot( + providerID: .grok, + accountEmail: self.credentials?.email, + accountOrganization: self.credentials?.teamId, + loginMethod: self.credentials?.loginMethod) + + return UsageSnapshot( + primary: primary, + secondary: nil, + tertiary: nil, + updatedAt: self.updatedAt, + identity: identity) + } +} + +public struct GrokStatusProbe: Sendable { + public init() {} + + public static func detectVersion(env: [String: String] = ProcessInfo.processInfo.environment) -> String? { + guard let binary = BinaryLocator.resolveGrokBinary(env: env) else { return nil } + guard let output = ProviderVersionDetector.run( + path: binary, + args: ["--version"], + environment: env, + mergeStandardError: true) + else { return nil } + // Output is like "grok 0.1.210 (8b63e9068c)" — strip the leading "grok " so + // callers can prefix the CLI name themselves without duplicating it. + let withoutPrefix = output.replacingOccurrences( + of: #"^grok\s+"#, + with: "", + options: [.regularExpression]) + .trimmingCharacters(in: .whitespacesAndNewlines) + return withoutPrefix.isEmpty ? nil : withoutPrefix + } + + public func fetch(env: [String: String] = ProcessInfo.processInfo.environment) async throws -> GrokUsageSnapshot { + // Credentials are optional: we still show identity-less state if the user + // hasn't logged in, with a clear hint via the RPC error. + let credentials = try? GrokCredentialsStore.load(env: env) + + var billing: GrokBillingResponse? + var rpcError: Error? + do { + let client = try GrokRPCClient(environment: env) + defer { client.shutdown() } + try await client.initialize() + billing = try await client.fetchBilling() + } catch { + rpcError = error + } + + // Local fallback summary always succeeds (empty if no sessions yet). + let localSummary = GrokLocalSessionScanner.summarize(env: env) + let cliVersion = Self.detectVersion(env: env) + + // `localSummary` is *not* currently projected into a visible RateWindow or + // identity field, so a stale `~/.grok/sessions/` directory must not + // suppress the auth-required hint. CLI-only fetches need a billing + // response; the provider pipeline owns the separate web fallback. + if billing == nil { + throw rpcError ?? GrokRPCError.notAuthenticated + } + + return GrokUsageSnapshot( + billing: billing, + webBilling: nil, + credentials: Self.credentialsForSnapshot( + credentials: credentials, + billing: billing, + webBilling: nil), + localSummary: localSummary, + cliVersion: cliVersion, + updatedAt: Date()) + } + + static func credentialsForSnapshot( + credentials: GrokCredentials?, + billing: GrokBillingResponse?, + webBilling: GrokWebBillingSnapshot? = nil) -> GrokCredentials? + { + // If remote usage succeeded, xAI accepted auth and the local + // identity is still useful even when the persisted expires_at is stale. + if billing != nil || webBilling != nil { return credentials } + return credentials.flatMap { $0.isExpired ? nil : $0 } + } + + static func shouldSurfaceRemoteAuthError(_ error: Error?) -> Bool { + guard let error = error as? GrokWebBillingError else { return false } + switch error { + case let .requestFailed(status, _): + return status == 401 || status == 403 + case let .rpcFailed(status, _): + return status == 16 + case .missingCredentials, .emptyResponse, .invalidResponse, .parseFailed: + return false + } + } +} diff --git a/Sources/CodexBarCore/Providers/Grok/GrokWebBillingFetcher.swift b/Sources/CodexBarCore/Providers/Grok/GrokWebBillingFetcher.swift new file mode 100644 index 0000000..4ab67ac --- /dev/null +++ b/Sources/CodexBarCore/Providers/Grok/GrokWebBillingFetcher.swift @@ -0,0 +1,433 @@ +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +public struct GrokWebBillingSnapshot: Sendable, Equatable { + public let usedPercent: Double? + public let resetsAt: Date? + + public init(usedPercent: Double?, resetsAt: Date?) { + self.usedPercent = usedPercent + self.resetsAt = resetsAt + } +} + +public enum GrokWebBillingError: LocalizedError, Sendable { + case missingCredentials + case emptyResponse + case invalidResponse + case requestFailed(Int, String) + case rpcFailed(Int, String) + case parseFailed + + public var errorDescription: String? { + switch self { + case .missingCredentials: + "Grok web billing requires a signed-in grok.com browser session or `grok login`." + case .emptyResponse: + "Grok web billing returned no protobuf payload." + case .invalidResponse: + "Grok web billing returned an invalid response." + case let .requestFailed(status, body): + if status == 401 || status == 403 { + Self.reauthMessage + } else { + "Grok web billing request failed with HTTP \(status): \(body)" + } + case let .rpcFailed(status, message): + if Self.isAuthenticationFailure(status: status, message: message) { + Self.reauthMessage + } else { + "Grok web billing RPC failed with status \(status): \(message)" + } + case .parseFailed: + "Could not parse Grok web billing usage." + } + } + + private static let reauthMessage = + "Grok web billing rejected credentials. Sign in to grok.com in Chrome or run `grok login` to refresh xAI auth." + + static func isAuthenticationFailure(status: Int, message: String) -> Bool { + if status == 16 { return true } + guard status == 7 else { return false } + let lower = message.lowercased() + return lower.contains("bad-credentials") || + lower.contains("unauthenticated") || + (lower.contains("oauth2") && lower.contains("could not be validated")) || + (lower.contains("access token") && + (lower.contains("invalid") || + lower.contains("expired") || + lower.contains("could not be validated"))) + } +} + +public enum GrokWebBillingFetcher { + public static let defaultEndpoint = + URL(string: "https://grok.com/grok_api_v2.GrokBuildBilling/GetGrokCreditsConfig")! + private static let requestTimeoutSeconds: TimeInterval = 15 + + public static func fetch( + credentials: GrokCredentials, + session transport: any ProviderHTTPTransport = ProviderHTTPClient.shared, + endpoint: URL = Self.defaultEndpoint) async throws -> GrokWebBillingSnapshot + { + try await self.fetch( + authorizationHeader: "Bearer \(credentials.accessToken)", + cookieHeader: nil, + transport: transport, + endpoint: endpoint) + } + + public static func fetch( + cookieHeader: String, + session transport: any ProviderHTTPTransport = ProviderHTTPClient.shared, + endpoint: URL = Self.defaultEndpoint) async throws -> GrokWebBillingSnapshot + { + try await self.fetch( + cookieHeader: cookieHeader, + credentials: nil, + session: transport, + endpoint: endpoint) + } + + public static func fetch( + cookieHeader: String, + credentials: GrokCredentials?, + session transport: any ProviderHTTPTransport = ProviderHTTPClient.shared, + endpoint: URL = Self.defaultEndpoint) async throws -> GrokWebBillingSnapshot + { + let authorizationHeader = credentials.flatMap { credential in + credential.isExpired ? nil : "Bearer \(credential.accessToken)" + } + return try await self.fetch( + authorizationHeader: authorizationHeader, + cookieHeader: cookieHeader, + transport: transport, + endpoint: endpoint) + } + + private static func fetch( + authorizationHeader: String?, + cookieHeader: String?, + transport: any ProviderHTTPTransport, + endpoint: URL) async throws -> GrokWebBillingSnapshot + { + do { + return try await self.fetchOnce( + authorizationHeader: authorizationHeader, + cookieHeader: cookieHeader, + transport: transport, + endpoint: endpoint) + } catch where self.shouldRetry(error) { + return try await self.fetchOnce( + authorizationHeader: authorizationHeader, + cookieHeader: cookieHeader, + transport: transport, + endpoint: endpoint) + } + } + + private static func fetchOnce( + authorizationHeader: String?, + cookieHeader: String?, + transport: any ProviderHTTPTransport, + endpoint: URL) async throws -> GrokWebBillingSnapshot + { + var request = URLRequest(url: endpoint) + request.httpMethod = "POST" + request.timeoutInterval = Self.requestTimeoutSeconds + request.httpBody = Data([0x00, 0x00, 0x00, 0x00, 0x00]) + if let authorizationHeader { + request.setValue(authorizationHeader, forHTTPHeaderField: "Authorization") + } + if let cookieHeader { + request.setValue(cookieHeader, forHTTPHeaderField: "Cookie") + } + request.setValue("https://grok.com", forHTTPHeaderField: "Origin") + request.setValue("https://grok.com/?_s=usage", forHTTPHeaderField: "Referer") + request.setValue("*/*", forHTTPHeaderField: "Accept") + request.setValue("application/grpc-web+proto", forHTTPHeaderField: "Content-Type") + request.setValue("1", forHTTPHeaderField: "x-grpc-web") + request.setValue("connect-es/2.1.1", forHTTPHeaderField: "x-user-agent") + request.setValue("CodexBar", forHTTPHeaderField: "User-Agent") + + let response: ProviderHTTPResponse + do { + response = try await transport.response(for: request) + } catch let error as URLError where error.code == .badServerResponse { + throw GrokWebBillingError.invalidResponse + } catch { + throw error + } + guard response.statusCode == 200 else { + let body = String(data: response.data.prefix(400), encoding: .utf8) ?? "" + throw GrokWebBillingError.requestFailed(response.statusCode, body) + } + try Self.validateGRPCStatusFields(Self.grpcHeaderFields(from: response.response.allHeaderFields)) + try Self.validateGRPCWebTrailers(response.data) + + return try Self.parseGRPCWebResponse(response.data) + } + + private static func shouldRetry(_ error: Error) -> Bool { + if let urlError = error as? URLError { + return urlError.code == .timedOut || urlError.code == .networkConnectionLost + } + if case let GrokWebBillingError.requestFailed(status, body) = error { + if [408, 502, 503, 504].contains(status) { return true } + return body.localizedCaseInsensitiveContains("timeout") + || body.localizedCaseInsensitiveContains("deadline") + } + guard case let GrokWebBillingError.rpcFailed(status, message) = error else { return false } + if status == 4 { return true } + guard status == 1 else { return false } + return message.localizedCaseInsensitiveContains("timeout") + || message.localizedCaseInsensitiveContains("deadline") + || message.localizedCaseInsensitiveContains("expired") + } + + static func parseGRPCWebResponse(_ data: Data, now: Date = Date()) throws -> GrokWebBillingSnapshot { + var payloads = Self.grpcWebDataFrames(from: data) + if payloads.isEmpty, Self.looksLikeProtobufPayload(data) { + payloads = [data] + } + guard !payloads.isEmpty else { throw GrokWebBillingError.emptyResponse } + + var scan = ProtobufScan() + for payload in payloads { + scan.merge(Self.scanProtobuf(payload, depth: 0)) + } + + let parsedPercent = scan.fixed32Fields + .filter { field in + field.path.last == 1 && field.value.isFinite && field.value >= 0 && field.value <= 100 + } + .min { lhs, rhs in + lhs.path.count == rhs.path.count ? lhs.order < rhs.order : lhs.path.count < rhs.path.count + } + .map { Double($0.value) } + + let resetFields = scan.varintFields.compactMap { field -> (path: [UInt64], date: Date)? in + let raw = field.value + guard raw >= 1_700_000_000, raw <= 2_100_000_000 else { return nil } + return (field.path, Date(timeIntervalSince1970: TimeInterval(raw))) + } + let futureResetFields = resetFields.filter { $0.date > now } + let reset = futureResetFields + .filter { $0.path == [1, 5, 1] } + .map(\.date) + .min() ?? futureResetFields + .map(\.date) + .min() + + let hasUsagePeriod = scan.varintFields.contains { field in + field.path.starts(with: [1, 6]) || + (field.path == [1, 8, 1] && (field.value == 1 || field.value == 2)) + } + let noUsageYet = parsedPercent == nil && + scan.fixed32Fields.isEmpty && + reset != nil && + hasUsagePeriod + guard let percent = parsedPercent ?? (noUsageYet ? 0 : nil) else { + throw GrokWebBillingError.parseFailed + } + return GrokWebBillingSnapshot(usedPercent: percent, resetsAt: reset) + } + + static func looksLikeProtobufPayload(_ data: Data) -> Bool { + guard let first = data.first else { return false } + let fieldNumber = first >> 3 + let wireType = first & 0x07 + return fieldNumber > 0 && (wireType == 0 || wireType == 1 || wireType == 2 || wireType == 5) + } + + static func grpcWebDataFrames(from data: Data) -> [Data] { + let bytes = [UInt8](data) + var frames: [Data] = [] + var index = 0 + while index < bytes.count { + guard index + 5 <= bytes.count else { return [] } + let flags = bytes[index] + let length = (Int(bytes[index + 1]) << 24) + | (Int(bytes[index + 2]) << 16) + | (Int(bytes[index + 3]) << 8) + | Int(bytes[index + 4]) + let start = index + 5 + let end = start + length + guard length >= 0, end <= bytes.count else { return [] } + if flags & 0x80 == 0 { + frames.append(Data(bytes[start.. [String: String] { + var fields: [String: String] = [:] + for (key, value) in headers { + let normalizedKey = String(describing: key) + .trimmingCharacters(in: .whitespacesAndNewlines) + .lowercased() + guard normalizedKey.hasPrefix("grpc-") else { continue } + fields[normalizedKey] = String(describing: value) + .trimmingCharacters(in: .whitespacesAndNewlines) + .removingPercentEncoding ?? "" + } + return fields + } + + static func grpcWebTrailerFields(from data: Data) -> [String: String] { + let bytes = [UInt8](data) + var fields: [String: String] = [:] + var index = 0 + while index + 5 <= bytes.count { + let flags = bytes[index] + let length = (Int(bytes[index + 1]) << 24) + | (Int(bytes[index + 2]) << 16) + | (Int(bytes[index + 3]) << 8) + | Int(bytes[index + 4]) + let start = index + 5 + let end = start + length + guard length >= 0, end <= bytes.count else { break } + if flags & 0x80 != 0, let text = String(data: Data(bytes[start.. ProtobufScan { + self.scanProtobuf(data, depth: depth, path: [], order: 0).scan + } + + private static func scanProtobuf( + _ data: Data, + depth: Int, + path: [UInt64], + order: Int) -> (scan: ProtobufScan, order: Int) + { + let bytes = [UInt8](data) + var scan = ProtobufScan() + var index = 0 + var nextOrder = order + + while index < bytes.count { + let fieldStart = index + guard let key = Self.readVarint(bytes, index: &index), key != 0 else { + index = fieldStart + 1 + continue + } + let fieldNumber = key >> 3 + let wireType = key & 0x07 + let fieldPath = path + [fieldNumber] + + switch wireType { + case 0: + if let value = Self.readVarint(bytes, index: &index) { + scan.varintFields.append(ProtobufScan.VarintField(path: fieldPath, value: value)) + } else { + index = fieldStart + 1 + } + case 1: + guard index + 8 <= bytes.count else { return (scan, nextOrder) } + index += 8 + case 2: + guard let length = Self.readVarint(bytes, index: &index), + length <= UInt64(bytes.count - index) + else { + index = fieldStart + 1 + continue + } + let start = index + let end = index + Int(length) + if depth < 4 { + let nested = Self.scanProtobuf( + Data(bytes[start.. UInt64? { + var value: UInt64 = 0 + var shift: UInt64 = 0 + while index < bytes.count, shift < 64 { + let byte = bytes[index] + index += 1 + value |= UInt64(byte & 0x7F) << shift + if byte & 0x80 == 0 { return value } + shift += 7 + } + return nil + } +} diff --git a/Sources/CodexBarCore/Providers/Groq/GroqProviderDescriptor.swift b/Sources/CodexBarCore/Providers/Groq/GroqProviderDescriptor.swift new file mode 100644 index 0000000..f4214da --- /dev/null +++ b/Sources/CodexBarCore/Providers/Groq/GroqProviderDescriptor.swift @@ -0,0 +1,49 @@ +import Foundation + +public enum GroqProviderDescriptor { + public static let descriptor: ProviderDescriptor = Self.makeDescriptor() + + static func makeDescriptor() -> ProviderDescriptor { + ProviderDescriptor( + id: .groq, + metadata: ProviderMetadata( + id: .groq, + displayName: "Groq", + sessionLabel: "Requests", + weeklyLabel: "Tokens", + opusLabel: nil, + supportsOpus: false, + supportsCredits: false, + creditsHint: "", + toggleTitle: "Show Groq usage", + cliName: "groqcloud", + defaultEnabled: false, + isPrimaryProvider: false, + usesAccountFallback: false, + browserCookieOrder: nil, + dashboardURL: "https://console.groq.com/dashboard/metrics", + statusPageURL: nil, + statusLinkURL: "https://status.groq.com"), + branding: ProviderBranding( + iconStyle: .groq, + iconResourceName: "ProviderIcon-groq", + color: ProviderColor(red: 245 / 255, green: 104 / 255, blue: 68 / 255)), + tokenCost: ProviderTokenCostConfig( + supportsTokenCost: false, + noDataMessage: { "Groq cost history is not available via the metrics API." }), + fetchPlan: .apiToken( + strategyID: "groq.api", + sourceLabel: "metrics", + resolveToken: { ProviderTokenResolver.groqToken(environment: $0) }, + missingCredentialsError: { GroqUsageError.missingCredentials }, + loadUsage: { apiKey, context in + try await GroqUsageFetcher.fetchUsage( + apiKey: apiKey, + environment: context.env).toUsageSnapshot() + }), + cli: ProviderCLIConfig( + name: "groqcloud", + aliases: ["groq", "groq-api"], + versionDetector: nil)) + } +} diff --git a/Sources/CodexBarCore/Providers/Groq/GroqSettingsReader.swift b/Sources/CodexBarCore/Providers/Groq/GroqSettingsReader.swift new file mode 100644 index 0000000..65c8a4a --- /dev/null +++ b/Sources/CodexBarCore/Providers/Groq/GroqSettingsReader.swift @@ -0,0 +1,58 @@ +import Foundation + +public enum GroqSettingsReader { + public static let apiKeyEnvironmentKey = "GROQ_API_KEY" + public static let apiURLEnvironmentKey = "GROQ_API_URL" + + public static func apiKey( + environment: [String: String] = ProcessInfo.processInfo.environment) -> String? + { + self.cleaned(environment[self.apiKeyEnvironmentKey]) + } + + public static func apiURL( + environment: [String: String] = ProcessInfo.processInfo.environment) -> URL + { + if let override = self.validAPIURL(environment: environment) { + return override + } + return URL(string: "https://api.groq.com/v1")! + } + + public static func validateEndpointOverrides( + environment: [String: String] = ProcessInfo.processInfo.environment) throws + { + guard let raw = self.cleaned(environment[self.apiURLEnvironmentKey]) else { return } + guard ProviderEndpointOverrideValidator.normalizedHTTPSURL(from: raw) == nil else { return } + throw GroqSettingsError.invalidEndpointOverride(self.apiURLEnvironmentKey) + } + + static func cleaned(_ raw: String?) -> String? { + guard var value = raw?.trimmingCharacters(in: .whitespacesAndNewlines), !value.isEmpty else { + return nil + } + if (value.hasPrefix("\"") && value.hasSuffix("\"")) || + (value.hasPrefix("'") && value.hasSuffix("'")) + { + value = String(value.dropFirst().dropLast()) + } + value = value.trimmingCharacters(in: .whitespacesAndNewlines) + return value.isEmpty ? nil : value + } + + private static func validAPIURL(environment: [String: String]) -> URL? { + guard let raw = self.cleaned(environment[self.apiURLEnvironmentKey]) else { return nil } + return ProviderEndpointOverrideValidator.normalizedHTTPSURL(from: raw) + } +} + +public enum GroqSettingsError: LocalizedError, Sendable, Equatable { + case invalidEndpointOverride(String) + + public var errorDescription: String? { + switch self { + case let .invalidEndpointOverride(key): + "Groq endpoint override \(key) must use HTTPS or a bare host." + } + } +} diff --git a/Sources/CodexBarCore/Providers/Groq/GroqUsageFetcher.swift b/Sources/CodexBarCore/Providers/Groq/GroqUsageFetcher.swift new file mode 100644 index 0000000..bff9a1b --- /dev/null +++ b/Sources/CodexBarCore/Providers/Groq/GroqUsageFetcher.swift @@ -0,0 +1,235 @@ +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +public enum GroqUsageError: LocalizedError, Sendable { + case missingCredentials + case invalidURL + case accessDenied(String) + case apiError(String) + case parseFailed(String) + + public var errorDescription: String? { + switch self { + case .missingCredentials: + "Missing Groq API key. Set apiKey in ~/.codexbar/config.json or GROQ_API_KEY." + case .invalidURL: + "Groq metrics URL is invalid." + case let .accessDenied(message): + "Groq metrics access denied: \(message)" + case let .apiError(message): + "Groq metrics API error: \(message)" + case let .parseFailed(message): + "Groq metrics parse error: \(message)" + } + } +} + +public struct GroqUsageSnapshot: Codable, Sendable, Equatable { + public let requestRatePerSecond: Double + public let inputTokenRatePerSecond: Double + public let outputTokenRatePerSecond: Double + public let promptCacheHitRatePerSecond: Double + public let updatedAt: Date + + public init( + requestRatePerSecond: Double, + inputTokenRatePerSecond: Double, + outputTokenRatePerSecond: Double, + promptCacheHitRatePerSecond: Double = 0, + updatedAt: Date) + { + self.requestRatePerSecond = requestRatePerSecond + self.inputTokenRatePerSecond = inputTokenRatePerSecond + self.outputTokenRatePerSecond = outputTokenRatePerSecond + self.promptCacheHitRatePerSecond = promptCacheHitRatePerSecond + self.updatedAt = updatedAt + } + + public var requestsPerMinute: Double { + self.requestRatePerSecond * 60 + } + + public var tokensPerMinute: Double { + (self.inputTokenRatePerSecond + self.outputTokenRatePerSecond) * 60 + } + + public var cacheHitsPerMinute: Double { + self.promptCacheHitRatePerSecond * 60 + } + + public func toUsageSnapshot() -> UsageSnapshot { + UsageSnapshot( + primary: RateWindow( + usedPercent: 0, + windowMinutes: 5, + resetsAt: nil, + resetDescription: "\(Self.formatDecimal(self.requestsPerMinute)) req/min"), + secondary: RateWindow( + usedPercent: 0, + windowMinutes: 5, + resetsAt: nil, + resetDescription: "\(Self.formatDecimal(self.tokensPerMinute)) tok/min"), + tertiary: self.promptCacheHitRatePerSecond > 0 ? RateWindow( + usedPercent: 0, + windowMinutes: 5, + resetsAt: nil, + resetDescription: "\(Self.formatDecimal(self.cacheHitsPerMinute)) cache/min") : nil, + updatedAt: self.updatedAt, + identity: ProviderIdentitySnapshot( + providerID: .groq, + accountEmail: nil, + accountOrganization: nil, + loginMethod: "Prometheus metrics")) + } + + static func formatDecimal(_ value: Double) -> String { + if value >= 100 { + return String(format: "%.0f", value) + } + if value >= 10 { + return String(format: "%.1f", value) + } + return String(format: "%.2f", value) + } +} + +private struct GroqPrometheusResponse: Decodable { + struct Payload: Decodable { + let result: [Series] + } + + struct Series: Decodable { + let value: [PrometheusValue]? + } + + enum PrometheusValue: Decodable { + case number(Double) + case string(String) + + init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + if let number = try? container.decode(Double.self) { + self = .number(number) + return + } + self = try .string(container.decode(String.self)) + } + + var doubleValue: Double? { + switch self { + case let .number(number): + number + case let .string(text): + Double(text) + } + } + } + + let status: String + let data: Payload? + let error: String? +} + +public struct GroqUsageFetcher: Sendable { + public init() {} + + public static func fetchUsage( + apiKey: String, + environment: [String: String] = ProcessInfo.processInfo.environment, + transport: any ProviderHTTPTransport = ProviderHTTPClient.shared, + updatedAt: Date = Date()) async throws -> GroqUsageSnapshot + { + guard !apiKey.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else { + throw GroqUsageError.missingCredentials + } + try GroqSettingsReader.validateEndpointOverrides(environment: environment) + let baseURL = GroqSettingsReader.apiURL(environment: environment) + .appendingPathComponent("metrics") + .appendingPathComponent("prometheus") + + async let requests = Self.queryScalar( + query: "sum(model_project_id_status_code:requests:rate5m)", + apiKey: apiKey, + baseURL: baseURL, + transport: transport) + async let inputTokens = Self.queryScalar( + query: "sum(model_project_id:tokens_in:rate5m)", + apiKey: apiKey, + baseURL: baseURL, + transport: transport) + async let outputTokens = Self.queryScalar( + query: "sum(model_project_id:tokens_out:rate5m)", + apiKey: apiKey, + baseURL: baseURL, + transport: transport) + async let cacheHits = Self.queryScalar( + query: "sum(model_project_id:prompt_cache_hits:rate5m)", + apiKey: apiKey, + baseURL: baseURL, + transport: transport) + + return try await GroqUsageSnapshot( + requestRatePerSecond: requests, + inputTokenRatePerSecond: inputTokens, + outputTokenRatePerSecond: outputTokens, + promptCacheHitRatePerSecond: cacheHits, + updatedAt: updatedAt) + } + + public static func _parseScalarForTesting(_ data: Data) throws -> Double { + try self.parseScalar(data: data) + } + + private static func queryScalar( + query: String, + apiKey: String, + baseURL: URL, + transport: any ProviderHTTPTransport) async throws -> Double + { + guard var components = URLComponents( + url: baseURL.appendingPathComponent("api/v1/query"), + resolvingAgainstBaseURL: false) + else { throw GroqUsageError.invalidURL } + components.queryItems = [URLQueryItem(name: "query", value: query)] + guard let url = components.url else { throw GroqUsageError.invalidURL } + + var request = URLRequest(url: url) + request.httpMethod = "GET" + request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization") + request.setValue("application/json", forHTTPHeaderField: "Accept") + + let response = try await transport.response(for: request) + guard (200..<300).contains(response.statusCode) else { + let summary = Self.responseSummary(response.data) + if response.statusCode == 401 || response.statusCode == 403 { + throw GroqUsageError.accessDenied(summary) + } + throw GroqUsageError.apiError("HTTP \(response.statusCode): \(summary)") + } + return try self.parseScalar(data: response.data) + } + + private static func parseScalar(data: Data) throws -> Double { + do { + let decoded = try JSONDecoder().decode(GroqPrometheusResponse.self, from: data) + guard decoded.status == "success" else { + throw GroqUsageError.apiError(decoded.error ?? "query failed") + } + return decoded.data?.result.compactMap { series in + series.value?.last?.doubleValue + }.reduce(0, +) ?? 0 + } catch let error as GroqUsageError { + throw error + } catch { + throw GroqUsageError.parseFailed(error.localizedDescription) + } + } + + private static func responseSummary(_ data: Data) -> String { + String(bytes: data.prefix(500), encoding: .utf8)? + .trimmingCharacters(in: .whitespacesAndNewlines) + ?? "" + } +} diff --git a/Sources/CodexBarCore/Providers/JetBrains/JetBrainsIDEDetector.swift b/Sources/CodexBarCore/Providers/JetBrains/JetBrainsIDEDetector.swift new file mode 100644 index 0000000..c1850f5 --- /dev/null +++ b/Sources/CodexBarCore/Providers/JetBrains/JetBrainsIDEDetector.swift @@ -0,0 +1,150 @@ +import Foundation + +public struct JetBrainsIDEInfo: Sendable, Equatable, Hashable { + public let name: String + public let version: String + public let basePath: String + public let quotaFilePath: String + + public init(name: String, version: String, basePath: String, quotaFilePath: String) { + self.name = name + self.version = version + self.basePath = basePath + self.quotaFilePath = quotaFilePath + } + + public var displayName: String { + "\(self.name) \(self.version)" + } +} + +public enum JetBrainsIDEDetector { + private static let idePatterns: [(prefix: String, displayName: String)] = [ + ("IntelliJIdea", "IntelliJ IDEA"), + ("PyCharm", "PyCharm"), + ("WebStorm", "WebStorm"), + ("GoLand", "GoLand"), + ("CLion", "CLion"), + ("DataGrip", "DataGrip"), + ("RubyMine", "RubyMine"), + ("Rider", "Rider"), + ("PhpStorm", "PhpStorm"), + ("AppCode", "AppCode"), + ("Fleet", "Fleet"), + ("AndroidStudio", "Android Studio"), + ("RustRover", "RustRover"), + ("Aqua", "Aqua"), + ("DataSpell", "DataSpell"), + ] + + private static let quotaFileName = "AIAssistantQuotaManager2.xml" + + public static func detectInstalledIDEs(includeMissingQuota: Bool = false) -> [JetBrainsIDEInfo] { + let basePaths = self.jetBrainsConfigBasePaths() + var detectedIDEs: [JetBrainsIDEInfo] = [] + + let fileManager = FileManager.default + for basePath in basePaths { + guard fileManager.fileExists(atPath: basePath) else { continue } + guard let contents = try? fileManager.contentsOfDirectory(atPath: basePath) else { continue } + + for dirname in contents { + guard let ideInfo = parseIDEDirectory(dirname: dirname, basePath: basePath) else { continue } + if includeMissingQuota || fileManager.fileExists(atPath: ideInfo.quotaFilePath) { + detectedIDEs.append(ideInfo) + } + } + } + + return detectedIDEs.sorted { lhs, rhs in + if lhs.name == rhs.name { + return self.compareVersions(lhs.version, rhs.version) > 0 + } + return lhs.name < rhs.name + } + } + + public static func detectLatestIDE() -> JetBrainsIDEInfo? { + let ides = self.detectInstalledIDEs() + guard !ides.isEmpty else { return nil } + + let fileManager = FileManager.default + var latestIDE: JetBrainsIDEInfo? + var latestModificationDate: Date? + + for ide in ides { + guard let attrs = try? fileManager.attributesOfItem(atPath: ide.quotaFilePath), + let modDate = attrs[.modificationDate] as? Date + else { continue } + + if latestModificationDate == nil || modDate > latestModificationDate! { + latestModificationDate = modDate + latestIDE = ide + } + } + + return latestIDE ?? ides.first + } + + private static func jetBrainsConfigBasePaths() -> [String] { + let homeDir = FileManager.default.homeDirectoryForCurrentUser.path + #if os(macOS) + return [ + "\(homeDir)/Library/Application Support/JetBrains", + "\(homeDir)/Library/Application Support/Google", + ] + #else + return [ + "\(homeDir)/.config/JetBrains", + "\(homeDir)/.local/share/JetBrains", + "\(homeDir)/.config/Google", + ] + #endif + } + + private static func parseIDEDirectory(dirname: String, basePath: String) -> JetBrainsIDEInfo? { + let dirnameLower = dirname.lowercased() + for (prefix, displayName) in self.idePatterns { + let prefixLower = prefix.lowercased() + guard dirnameLower.hasPrefix(prefixLower) else { continue } + let versionPart = String(dirname.dropFirst(prefix.count)) + let version = versionPart.isEmpty ? "Unknown" : versionPart + let idePath = "\(basePath)/\(dirname)" + let quotaFilePath = quotaFilePath(for: idePath) + return JetBrainsIDEInfo( + name: displayName, + version: version, + basePath: idePath, + quotaFilePath: quotaFilePath) + } + return nil + } + + #if DEBUG + + // MARK: - Test hooks (DEBUG-only) + + public static func _parseIDEDirectoryForTesting(dirname: String, basePath: String) -> JetBrainsIDEInfo? { + self.parseIDEDirectory(dirname: dirname, basePath: basePath) + } + #endif + + public static func quotaFilePath(for ideBasePath: String) -> String { + "\(ideBasePath)/options/\(self.quotaFileName)" + } + + private static func compareVersions(_ v1: String, _ v2: String) -> Int { + let parts1 = v1.split(separator: ".").compactMap { Int($0) } + let parts2 = v2.split(separator: ".").compactMap { Int($0) } + + let maxLen = max(parts1.count, parts2.count) + for i in 0.. ProviderDescriptor { + ProviderDescriptor( + id: .jetbrains, + metadata: ProviderMetadata( + id: .jetbrains, + displayName: "JetBrains AI", + sessionLabel: "Current", + weeklyLabel: "Refill", + opusLabel: nil, + supportsOpus: false, + supportsCredits: false, + creditsHint: "", + toggleTitle: "Show JetBrains AI usage", + cliName: "jetbrains", + defaultEnabled: false, + isPrimaryProvider: false, + usesAccountFallback: false, + dashboardURL: nil, + statusPageURL: nil), + branding: ProviderBranding( + iconStyle: .jetbrains, + iconResourceName: "ProviderIcon-jetbrains", + color: ProviderColor(red: 255 / 255, green: 51 / 255, blue: 153 / 255)), + tokenCost: ProviderTokenCostConfig( + supportsTokenCost: false, + noDataMessage: { "JetBrains AI cost summary is not supported." }), + fetchPlan: ProviderFetchPlan( + sourceModes: [.auto, .cli], + pipeline: ProviderFetchPipeline(resolveStrategies: { _ in [JetBrainsStatusFetchStrategy()] })), + cli: ProviderCLIConfig( + name: "jetbrains", + versionDetector: nil)) + } +} + +struct JetBrainsStatusFetchStrategy: ProviderFetchStrategy { + let id: String = "jetbrains.local" + let kind: ProviderFetchKind = .localProbe + + func isAvailable(_: ProviderFetchContext) async -> Bool { + true + } + + func fetch(_ context: ProviderFetchContext) async throws -> ProviderFetchResult { + let probe = JetBrainsStatusProbe(settings: context.settings) + let snap = try await probe.fetch() + let usage = try snap.toUsageSnapshot() + return self.makeResult( + usage: usage, + sourceLabel: "local") + } + + func shouldFallback(on _: Error, context _: ProviderFetchContext) -> Bool { + false + } +} diff --git a/Sources/CodexBarCore/Providers/JetBrains/JetBrainsStatusProbe.swift b/Sources/CodexBarCore/Providers/JetBrains/JetBrainsStatusProbe.swift new file mode 100644 index 0000000..198d830 --- /dev/null +++ b/Sources/CodexBarCore/Providers/JetBrains/JetBrainsStatusProbe.swift @@ -0,0 +1,355 @@ +import Foundation +#if os(macOS) && canImport(FoundationXML) +import FoundationXML +#endif + +public struct JetBrainsQuotaInfo: Sendable, Equatable { + public let type: String? + public let used: Double + public let maximum: Double + public let available: Double + public let until: Date? + + public init(type: String?, used: Double, maximum: Double, available: Double?, until: Date?) { + self.type = type + self.used = used + self.maximum = maximum + // Use available if provided, otherwise calculate from maximum - used + self.available = available ?? max(0, maximum - used) + self.until = until + } + + /// Percentage of quota that has been used (0-100) + public var usedPercent: Double { + guard self.maximum > 0 else { return 0 } + return min(100, max(0, (self.used / self.maximum) * 100)) + } + + /// Percentage of quota remaining (0-100), based on available value + public var remainingPercent: Double { + guard self.maximum > 0 else { return 100 } + return min(100, max(0, (self.available / self.maximum) * 100)) + } +} + +public struct JetBrainsRefillInfo: Sendable, Equatable { + public let type: String? + public let next: Date? + public let amount: Double? + public let duration: String? + + public init(type: String?, next: Date?, amount: Double?, duration: String?) { + self.type = type + self.next = next + self.amount = amount + self.duration = duration + } +} + +public struct JetBrainsStatusSnapshot: Sendable { + public let quotaInfo: JetBrainsQuotaInfo + public let refillInfo: JetBrainsRefillInfo? + public let detectedIDE: JetBrainsIDEInfo? + + public init(quotaInfo: JetBrainsQuotaInfo, refillInfo: JetBrainsRefillInfo?, detectedIDE: JetBrainsIDEInfo?) { + self.quotaInfo = quotaInfo + self.refillInfo = refillInfo + self.detectedIDE = detectedIDE + } + + public func toUsageSnapshot() throws -> UsageSnapshot { + // Primary shows monthly credits usage with next refill date + // IDE displays: "今月のクレジット残り X / Y" with "Z月D日に更新されます" + let refillDate = self.refillInfo?.next + let primary = RateWindow( + usedPercent: self.quotaInfo.usedPercent, + windowMinutes: nil, + resetsAt: refillDate, + resetDescription: Self.formatResetDescription(refillDate)) + + let identity = ProviderIdentitySnapshot( + providerID: .jetbrains, + accountEmail: nil, + accountOrganization: self.detectedIDE?.displayName, + loginMethod: self.quotaInfo.type) + + return UsageSnapshot( + primary: primary, + secondary: nil, + tertiary: nil, + updatedAt: Date(), + identity: identity) + } + + private static func formatResetDescription(_ date: Date?) -> String? { + guard let date else { return nil } + let now = Date() + let interval = date.timeIntervalSince(now) + guard interval > 0 else { return "Expired" } + + let hours = Int(interval / 3600) + let minutes = Int((interval.truncatingRemainder(dividingBy: 3600)) / 60) + + if hours > 24 { + let days = hours / 24 + let remainingHours = hours % 24 + return "Resets in \(days)d \(remainingHours)h" + } else if hours > 0 { + return "Resets in \(hours)h \(minutes)m" + } else { + return "Resets in \(minutes)m" + } + } +} + +public enum JetBrainsStatusProbeError: LocalizedError, Sendable, Equatable { + case noIDEDetected + case quotaFileNotFound(String) + case parseError(String) + case noQuotaInfo + + public var errorDescription: String? { + switch self { + case .noIDEDetected: + "No JetBrains IDE with AI Assistant detected. Install a JetBrains IDE and enable AI Assistant." + case let .quotaFileNotFound(path): + "JetBrains AI quota file not found at \(path). Enable AI Assistant in your IDE." + case let .parseError(message): + "Could not parse JetBrains AI quota: \(message)" + case .noQuotaInfo: + "No quota information found in the JetBrains AI configuration." + } + } +} + +public struct JetBrainsStatusProbe: Sendable { + private let settings: ProviderSettingsSnapshot? + + public init(settings: ProviderSettingsSnapshot? = nil) { + self.settings = settings + } + + public func fetch() async throws -> JetBrainsStatusSnapshot { + let (quotaFilePath, detectedIDE) = try self.resolveQuotaFilePath() + return try Self.parseQuotaFile(at: quotaFilePath, detectedIDE: detectedIDE) + } + + private func resolveQuotaFilePath() throws -> (String, JetBrainsIDEInfo?) { + if let customPath = self.settings?.jetbrainsIDEBasePath?.trimmingCharacters(in: .whitespacesAndNewlines), + !customPath.isEmpty + { + let expandedBasePath = (customPath as NSString).expandingTildeInPath + let quotaPath = JetBrainsIDEDetector.quotaFilePath(for: expandedBasePath) + return (quotaPath, nil) + } + + guard let detectedIDE = JetBrainsIDEDetector.detectLatestIDE() else { + throw JetBrainsStatusProbeError.noIDEDetected + } + return (detectedIDE.quotaFilePath, detectedIDE) + } + + public static func parseQuotaFile( + at path: String, + detectedIDE: JetBrainsIDEInfo?) throws -> JetBrainsStatusSnapshot + { + guard FileManager.default.fileExists(atPath: path) else { + throw JetBrainsStatusProbeError.quotaFileNotFound(path) + } + + let xmlData: Data + do { + xmlData = try Data(contentsOf: URL(fileURLWithPath: path)) + } catch { + throw JetBrainsStatusProbeError.parseError("Failed to read file: \(error.localizedDescription)") + } + + return try Self.parseXMLData(xmlData, detectedIDE: detectedIDE) + } + + public static func parseXMLData(_ data: Data, detectedIDE: JetBrainsIDEInfo?) throws -> JetBrainsStatusSnapshot { + #if os(macOS) + let document: XMLDocument + do { + document = try XMLDocument(data: data) + } catch { + throw JetBrainsStatusProbeError.parseError("Invalid XML: \(error.localizedDescription)") + } + + let quotaInfoRaw = try? document + .nodes(forXPath: "//component[@name='AIAssistantQuotaManager2']/option[@name='quotaInfo']/@value") + .first? + .stringValue + let nextRefillRaw = try? document + .nodes(forXPath: "//component[@name='AIAssistantQuotaManager2']/option[@name='nextRefill']/@value") + .first? + .stringValue + #else + let parseResult = JetBrainsXMLParser.parse(data: data) + let quotaInfoRaw = parseResult.quotaInfo + let nextRefillRaw = parseResult.nextRefill + #endif + + guard let quotaInfoRaw, !quotaInfoRaw.isEmpty else { + throw JetBrainsStatusProbeError.noQuotaInfo + } + + let quotaInfoDecoded = Self.decodeHTMLEntities(quotaInfoRaw) + let quotaInfo = try Self.parseQuotaInfoJSON(quotaInfoDecoded) + + var refillInfo: JetBrainsRefillInfo? + if let nextRefillRaw, !nextRefillRaw.isEmpty { + let nextRefillDecoded = Self.decodeHTMLEntities(nextRefillRaw) + refillInfo = try? Self.parseRefillInfoJSON(nextRefillDecoded) + } + + return JetBrainsStatusSnapshot( + quotaInfo: quotaInfo, + refillInfo: refillInfo, + detectedIDE: detectedIDE) + } + + private static func decodeHTMLEntities(_ string: String) -> String { + string + .replacingOccurrences(of: " ", with: "\n") + .replacingOccurrences(of: """, with: "\"") + .replacingOccurrences(of: "&", with: "&") + .replacingOccurrences(of: "<", with: "<") + .replacingOccurrences(of: ">", with: ">") + .replacingOccurrences(of: "'", with: "'") + } + + private static func parseQuotaInfoJSON(_ jsonString: String) throws -> JetBrainsQuotaInfo { + guard let data = jsonString.data(using: .utf8) else { + throw JetBrainsStatusProbeError.parseError("Invalid JSON encoding") + } + + guard let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else { + throw JetBrainsStatusProbeError.parseError("Invalid JSON format") + } + + let type = json["type"] as? String + let currentStr = json["current"] as? String + let maximumStr = json["maximum"] as? String + let untilStr = json["until"] as? String + + // tariffQuota contains the actual available credits + let tariffQuota = json["tariffQuota"] as? [String: Any] + let availableStr = tariffQuota?["available"] as? String + + let used = currentStr.flatMap { Double($0) } ?? 0 + let maximum = maximumStr.flatMap { Double($0) } ?? 0 + let available = availableStr.flatMap { Double($0) } + let until = untilStr.flatMap { Self.parseDate($0) } + + return JetBrainsQuotaInfo(type: type, used: used, maximum: maximum, available: available, until: until) + } + + private static func parseRefillInfoJSON(_ jsonString: String) throws -> JetBrainsRefillInfo { + guard let data = jsonString.data(using: .utf8) else { + throw JetBrainsStatusProbeError.parseError("Invalid JSON encoding") + } + + guard let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else { + throw JetBrainsStatusProbeError.parseError("Invalid JSON format") + } + + let type = json["type"] as? String + let nextStr = json["next"] as? String + let amountStr = json["amount"] as? String + let duration = json["duration"] as? String + + let next = nextStr.flatMap { Self.parseDate($0) } + let amount = amountStr.flatMap { Double($0) } + + let tariff = json["tariff"] as? [String: Any] + let tariffAmountStr = tariff?["amount"] as? String + let tariffDuration = tariff?["duration"] as? String + let finalAmount = amount ?? tariffAmountStr.flatMap { Double($0) } + let finalDuration = duration ?? tariffDuration + + return JetBrainsRefillInfo(type: type, next: next, amount: finalAmount, duration: finalDuration) + } + + private static func parseDate(_ string: String) -> Date? { + let formatter = ISO8601DateFormatter() + formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds] + if let date = formatter.date(from: string) { + return date + } + + formatter.formatOptions = [.withInternetDateTime] + return formatter.date(from: string) + } +} + +#if !os(macOS) +/// Simple regex-based XML parser to avoid libxml2 dependency on Linux. +/// Only extracts quotaInfo and nextRefill values from AIAssistantQuotaManager2 component. +private enum JetBrainsXMLParser { + struct ParseResult { + let quotaInfo: String? + let nextRefill: String? + } + + static func parse(data: Data) -> ParseResult { + guard let content = String(data: data, encoding: .utf8) else { + return ParseResult(quotaInfo: nil, nextRefill: nil) + } + + // Find the AIAssistantQuotaManager2 component block + guard let componentRange = self.findComponentRange(in: content) else { + return ParseResult(quotaInfo: nil, nextRefill: nil) + } + + let componentContent = String(content[componentRange]) + + let quotaInfo = self.extractOptionValue(named: "quotaInfo", from: componentContent) + let nextRefill = self.extractOptionValue(named: "nextRefill", from: componentContent) + + return ParseResult(quotaInfo: quotaInfo, nextRefill: nextRefill) + } + + private static func findComponentRange(in content: String) -> Range? { + // Match ... + let pattern = #"]*name\s*=\s*["']AIAssistantQuotaManager2["'][^>]*>[\s\S]*?"# + guard let regex = try? NSRegularExpression(pattern: pattern, options: []), + let match = regex.firstMatch( + in: content, + options: [], + range: NSRange(content.startIndex..., in: content)), + let range = Range(match.range, in: content) + else { + return nil + } + return range + } + + private static func extractOptionValue(named name: String, from content: String) -> String? { + // Match
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
#b|9h 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 z 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 YU!=yw9cip0AOHXW07*qoM6N<$f-G^cA^-pY literal 0 HcmV?d00001 diff --git a/docs/command-code.md b/docs/command-code.md new file mode 100644 index 0000000..e7bd5c5 --- /dev/null +++ b/docs/command-code.md @@ -0,0 +1,51 @@ +--- +summary: "Command Code provider notes: cookie authentication and monthly credit parsing." +read_when: + - Debugging Command Code cookie import or usage parsing + - Updating Command Code billing or credit display + - Adjusting Command Code provider UI/menu behavior +--- + +# Command Code + +CodexBar surfaces [Command Code](https://commandcode.ai) monthly USD credits next +to your other AI coding providers. + +## Data source + +- `https://api.commandcode.ai` billing endpoints, authenticated with the + signed-in Command Code web session. +- The provider reads monthly credit usage, plan allowance, remaining credits, + and billing-cycle reset timing when the account data is available. + +## Authentication + +Command Code support uses browser cookies or a manually pasted cookie header. + +1. Sign in to `https://commandcode.ai` in a supported browser. +2. Open Settings -> Providers -> Command Code. +3. Enable Command Code and leave Cookie source on Automatic, or switch to Manual + and paste a `Cookie:` header/cURL capture from Command Code. + +Automatic import looks for better-auth session cookies from `commandcode.ai` +and `www.commandcode.ai`. If automatic import cannot find a session, use the +manual cookie field. + +On Linux, browser import is unavailable. Set `cookieSource` to `manual` and +provide the Command Code `Cookie` header in `cookieHeader`; both `auto` and +`web` CLI source modes then use the billing API. + +## Display + +- The menu bar item and provider card use the Command Code icon and label. +- The primary row shows monthly credits used/remaining. +- Widgets do not expose Command Code in the provider picker yet. + +## Related files + +- `Sources/CodexBarCore/Providers/CommandCode/` - descriptor, cookie import, + billing fetcher, snapshot mapping, and plan catalog. +- `Sources/CodexBar/Providers/CommandCode/` - settings store bridge and + provider settings UI. +- `Tests/CodexBarTests/CommandCode*Tests.swift` - parser, cookie, settings, + and icon coverage. diff --git a/docs/configuration.md b/docs/configuration.md new file mode 100644 index 0000000..bb18d37 --- /dev/null +++ b/docs/configuration.md @@ -0,0 +1,208 @@ +--- +summary: "CodexBar config file layout for CLI + app settings." +read_when: + - "Editing the CodexBar config file or moving settings off Keychain." + - "Adding new provider settings fields or defaults." + - "Explaining CLI/app configuration and security." +--- + +# Configuration + +CodexBar reads a single JSON config file for CLI and app provider settings. +API keys, manual cookie headers, source selection, ordering, and token accounts live here. Keychain is still used for runtime cookie caches, browser Safe Storage access, and provider OAuth/device-flow credentials where those flows require it. + +## Location +- `CODEXBAR_CONFIG=/path/to/config.json` when set. +- `$XDG_CONFIG_HOME/codexbar/config.json` when `XDG_CONFIG_HOME` is set to an absolute path. Relative values are + ignored. +- `~/.config/codexbar/config.json` by default for new installs. +- `~/.codexbar/config.json` for existing legacy installs when no XDG config exists. +- The directory is created if missing. +- Permissions are set to `0600` whenever CodexBar writes the file on macOS and Linux. + +## Root shape +```json +{ + "version": 1, + "providers": [ + { + "id": "codex", + "enabled": true, + "source": "auto", + "cookieSource": "auto", + "cookieHeader": null, + "apiKey": null, + "enterpriseHost": null, + "region": null, + "workspaceID": null, + "tokenAccounts": null + } + ] +} +``` + +## Provider fields +All provider fields are optional unless noted. + +- `id` (required): provider identifier. +- `enabled`: enable/disable provider (defaults to provider default). +- `source`: preferred source mode. + - `auto|web|cli|oauth|api` + - `auto` uses provider-specific fallback order (see `docs/providers.md`). + - `api` uses the provider's API-backed mode; only some providers consume the `apiKey` field. +- `apiKey`: raw API token for providers that support config-backed direct API usage. +- `enterpriseHost`: provider-specific API host/base URL override. Used by Azure OpenAI, Copilot, LLM Proxy, LiteLLM, + ClawRouter, and Wayfinder. +- `cookieSource`: cookie selection policy. + - `auto` (browser import), `manual` (use `cookieHeader`), `off` (disable cookies) +- `cookieHeader`: raw cookie header value (e.g. `key=value; other=...`). +- `region`: provider-specific region (e.g. `zai`, `minimax`). +- `workspaceID`: provider-specific workspace/deployment/project ID (e.g. Azure OpenAI deployment, OpenAI API project, + `opencode`). +- `tokenAccounts`: multi-account tokens for providers in `TokenAccountSupportCatalog`. + +## Manual cookies +Use manual cookies when automatic browser import is unavailable, disabled, or too noisy for your setup. +The app and CLI both read the same resolved config file, so a manual cookie saved in the UI is also used by +`codexbar`, and a cookie written by tooling is shown in the app after reload. + +`cookieHeader` expects the HTTP `Cookie:` request header value for the provider origin, not a raw Netscape cookie +export. In browser DevTools, open the Network tab, select a request for the provider site, and copy the request +header named `Cookie`. You can paste either the full `Cookie: name=value; other=value` string or just +`name=value; other=value`. + +If you have a Netscape export, convert each non-comment row to `name=value` and join values with `; `. Do not paste +the raw `# Netscape HTTP Cookie File` text into `cookieHeader`. + +Example placeholder config: + +```json +{ + "version": 1, + "providers": [ + { + "id": "example-provider", + "enabled": true, + "cookieSource": "manual", + "cookieHeader": "session=; other=" + } + ] +} +``` + +Validate after editing: + +```bash +codexbar config validate +codexbar usage --provider example-provider --verbose +``` + +CLI shortcuts: + +```bash +codexbar config providers +codexbar config enable --provider grok +codexbar config disable --provider cursor +printf '%s' "$ELEVENLABS_API_KEY" | codexbar config set-api-key --provider elevenlabs --stdin +printf '%s' "$OPENAI_ADMIN_KEY" | codexbar config set-api-key --provider openai --stdin +printf '%s' "$GROQ_API_KEY" | codexbar config set-api-key --provider groq --stdin +printf '%s' "$LLM_PROXY_API_KEY" | codexbar config set-api-key --provider llmproxy --stdin +printf '%s' "$LITELLM_API_KEY" | codexbar config set-api-key --provider litellm --stdin +printf '%s' "$CLAWROUTER_API_KEY" | codexbar config set-api-key --provider clawrouter --stdin +printf '%s' "$SUB2API_API_KEY" | codexbar config set-api-key --provider sub2api --stdin +``` + +OpenAI API project scoping uses `workspaceID` in config. This maps to `OPENAI_PROJECT_ID` for Admin API usage and is +only applied to the configured OpenAI key, not to selected OpenAI token accounts: + +```json +{ + "id": "openai", + "enabled": true, + "apiKey": "", + "workspaceID": "proj_..." +} +``` + +LLM Proxy also needs a base URL. Set `enterpriseHost` in config or `LLM_PROXY_BASE_URL` in the process environment: + +```json +{ + "id": "llmproxy", + "enabled": true, + "apiKey": "", + "enterpriseHost": "https://proxy.example.com" +} +``` + +LiteLLM also needs a base URL. Set `enterpriseHost` in config or `LITELLM_BASE_URL` in the process environment: + +```json +{ + "id": "litellm", + "enabled": true, + "apiKey": "", + "enterpriseHost": "https://litellm.example.com" +} +``` + +ClawRouter defaults to the hosted service. To use another deployment, set `enterpriseHost` in config or +`CLAWROUTER_BASE_URL` in the process environment: + +```json +{ + "id": "clawrouter", + "enabled": true, + "apiKey": "", + "enterpriseHost": "https://router.example.com" +} +``` + +sub2api needs its self-hosted base URL. Set `enterpriseHost` in config or `SUB2API_BASE_URL` in the process +environment. Add labeled token accounts in Settings when one deployment has multiple group API keys: + +```json +{ + "id": "sub2api", + "enabled": true, + "apiKey": "", + "enterpriseHost": "https://sub2api.example.com" +} +``` + +See [CLI configuration](cli-configuration.md) for scripting examples and output formats. + +Manual cookies are secrets. Keep the CodexBar config file private, leave its permissions at `0600`, never commit it, +and never paste real cookie values or readable DevTools screenshots into public issues. + +### tokenAccounts +```json +{ + "version": 1, + "activeIndex": 0, + "accounts": [ + { + "id": "00000000-0000-0000-0000-000000000000", + "label": "user@example.com", + "token": "sk-...", + "addedAt": 1735123456, + "lastUsed": 1735220000 + } + ] +} +``` + +z.ai team accounts also use `usageScope`, `organizationId`, and `workspaceID`; see [z.ai](zai.md). + +## Provider IDs +Current IDs (see `Sources/CodexBarCore/Providers/Providers.swift`): +`codex`, `openai`, `azureopenai`, `claude`, `cursor`, `opencode`, `opencodego`, `alibaba`, `alibabatokenplan`, `factory`, `gemini`, `antigravity`, `copilot`, `devin`, `zai`, `minimax`, `manus`, `kimi`, `kilo`, `kiro`, `vertexai`, `augment`, `jetbrains`, `kimik2`, `moonshot`, `amp`, `t3chat`, `ollama`, `synthetic`, `warp`, `openrouter`, `elevenlabs`, `windsurf`, `zed`, `perplexity`, `mimo`, `doubao`, `sakana`, `abacus`, `mistral`, `deepseek`, `codebuff`, `crof`, `venice`, `commandcode`, `qoder`, `stepfun`, `bedrock`, `grok`, `groq`, `llmproxy`, `litellm`, `deepgram`, `poe`, `chutes`, `crossmodel`, `clawrouter`, `sub2api`, `wayfinder`. + +## Ordering +The order of `providers` controls display/order in the app and CLI. Reorder the array to change ordering. + +## Notes +- Fields not relevant to a provider are ignored. +- Omitted providers are appended with defaults during normalization. +- Keep the file private; it contains secrets. +- Validate the file with `codexbar config validate` (JSON output available with `--format json`). diff --git a/docs/copilot.md b/docs/copilot.md new file mode 100644 index 0000000..9643cc2 --- /dev/null +++ b/docs/copilot.md @@ -0,0 +1,69 @@ +--- +summary: "Copilot provider data sources: GitHub device flow, Copilot internal usage API, and optional GitHub web budgets." +read_when: + - Debugging Copilot login or usage parsing + - Updating GitHub OAuth device flow behavior +--- + +# Copilot provider + +Copilot uses GitHub OAuth device flow and the Copilot internal usage API for primary usage. Optional budget extras use GitHub web cookies only when enabled. + +## Data sources + fallback order + +1) **GitHub OAuth device flow** (user initiated) + - Device code request: + - `POST https://github.com/login/device/code` + - Token polling: + - `POST https://github.com/login/oauth/access_token` + - Optional enterprise host: + - set Copilot `enterpriseHost` in `~/.codexbar/config.json` or the provider settings UI + - CodexBar normalizes values such as `https://octocorp.ghe.com/login` to `octocorp.ghe.com` + - device flow uses `https:///login/...` + - Scope: `read:user`. + - Token stored in config: + - `~/.codexbar/config.json` → `providers[].apiKey` for `copilot` + - token accounts use `providers[].tokenAccounts` + +2) **Usage fetch** + - `GET https://api.github.com/copilot_internal/user` + - With an enterprise host, the API host is `api.`. + - Headers: + - `Authorization: token ` + - `Accept: application/json` + - `Editor-Version: vscode/1.96.2` + - `Editor-Plugin-Version: copilot-chat/0.26.7` + - `User-Agent: GitHubCopilotChat/0.26.7` + - `X-Github-Api-Version: 2025-04-01` + +3) **Budget fetch** (optional GitHub web endpoint, best-effort) + - Disabled by default. The Copilot provider's "Budget extras" setting must be enabled before CodexBar imports + github.com cookies or renders budget bars. + - CodexBar asks the logged-in GitHub web endpoint for customer-scope budgets: + - `GET https://github.com/settings/billing/budgets?page=&page_size=10&scope=customer` + - Headers: + - `Cookie: ` + - `Accept: application/json` + - `X-Requested-With: XMLHttpRequest` + - `GitHub-Verified-Fetch: true` + - `X-Fetch-Nonce: ` + - CodexBar first tries to read a fresh nonce from `https://github.com/settings/billing/budgets`, then calls the JSON + endpoint. If GitHub rejects the web request, CodexBar keeps the normal Copilot quota bars and omits budget bars. + - This is intentionally not the public GitHub REST billing API. The REST API did not expose the personal budget list + for the tested individual account. + +## Snapshot mapping +- Primary: `quotaSnapshots.premiumInteractions` percent remaining → used percent. +- Secondary: `quotaSnapshots.chat` percent remaining → used percent. +- Extra: positive Copilot billing budgets from the GitHub web endpoint → `extraRateWindows`, only when "Budget extras" + is enabled. + - Product budget: `copilot` + - SKU budgets: `copilot_premium_request`, `copilot_agent_premium_request`, `spark_premium_request` +- Reset dates are not provided by the API. +- Plan label from `copilotPlan`. + +## Key files +- `Sources/CodexBarCore/Providers/Copilot/CopilotUsageFetcher.swift` +- `Sources/CodexBarCore/Providers/Copilot/CopilotDeviceFlow.swift` +- `Sources/CodexBar/Providers/Copilot/CopilotLoginFlow.swift` +- `Sources/CodexBar/CopilotTokenStore.swift` (legacy migration helper) diff --git a/docs/cost-window-comparisons.md b/docs/cost-window-comparisons.md new file mode 100644 index 0000000..3351fa0 --- /dev/null +++ b/docs/cost-window-comparisons.md @@ -0,0 +1,35 @@ +# Cost window comparison decision + +Issues: [#1500](https://github.com/steipete/CodexBar/issues/1500), [#1708](https://github.com/steipete/CodexBar/issues/1708) + +## Proposed product shape + +Keep the existing history-window setting as the maximum local scan window. Add an opt-in **Show shorter comparison periods** preference, defaulting off. When enabled, the cost card adds fixed 7, 30, and 90-day totals that are shorter than the selected history window. + +Examples: + +- 30-day history: Today, Last 30 days, Last 7 days. +- 90-day history: Today, Last 90 days, Last 7 days, Last 30 days. +- 365-day history: Today, Last 365 days, Last 7 days, Last 30 days, Last 90 days. + +The implementation derives every comparison from the already-loaded daily report. It does not widen scans, add network requests, retain new data, or change provider source selection. Missing calendar days remain zero-usage days rather than making “last 7 days” mean “last 7 non-empty rows.” + +## Why this does not claim lifetime cost + +“All available local logs” and “lifetime since install” are different contracts. Local Codex, Claude, and Pi logs may be moved, pruned, excluded, or created before CodexBar was installed. The existing plan-utilization history is also capped and has no token or cost ledger. A 365-day total therefore cannot honestly be labeled a lifetime bill. + +A true #1708 implementation needs separate approval for an append-only local ledger with: + +- an explicit collection start date and completeness state; +- provider/account ownership and reset behavior; +- migration, retention, export, and deletion controls; +- privacy documentation and bounded storage tests; +- UI wording that separates observed utilization snapshots from estimated local-log cost. + +Recommendation: ship the opt-in comparison rows for #1500 independently. Keep #1708 open until the ledger/data-retention contract is approved; label any future scan-only total **Available local logs**, never **Lifetime**. + +## Maintainer choice + +1. **Recommended:** merge with the preference default off. Existing UI and scan cost stay unchanged until a user opts in. +2. Default the preference on. More useful immediately, but adds vertical menu density for existing users. +3. Keep the model only and revisit the presentation. This preserves tested calendar-window aggregation without shipping a new setting. diff --git a/docs/crof.md b/docs/crof.md new file mode 100644 index 0000000..59fd9b7 --- /dev/null +++ b/docs/crof.md @@ -0,0 +1,42 @@ +--- +summary: "Crof provider data source: API key + usage_api request quota." +read_when: + - Adding or tweaking Crof usage parsing + - Updating Crof API key handling + - Documenting Crof reset behavior +--- + +# Crof provider + +Crof is API-only. CodexBar reads `GET https://crof.ai/usage_api/` with a +Bearer token and displays the returned request quota and dollar credit balance. + +## Data sources + +1. **API key** supplied via `CROF_API_KEY`, `CROFAI_API_KEY`, or Settings → + Providers → Crof. Settings values are stored in `~/.codexbar/config.json`. +2. **Usage endpoint** + - `GET https://crof.ai/usage_api/` + - Request headers: `Authorization: Bearer `, `Accept: application/json` + - Response fields: `credits`, `requests_plan`, `usable_requests` + +## Usage details + +- The primary row shows request quota with the exact usable request count on the right. + The visible remaining percent is floored so partially used quotas like `998/1000` + do not round up to `100% left`. +- Crof support said quota reset is around midnight Central time; CodexBar models this + as the next `America/Chicago` midnight so daylight saving time maps to GMT-5 when + appropriate. +- The secondary row shows the current Crof dollar balance, floored to cents so tiny + microcent-level burns never overstate the remaining balance. +- Reset timing is inferred until Crof exposes reset metadata in the usage API. +- The provider icon is SVG and CodexBar renders it as a template image so it + matches the other monochrome provider icons. +- Dashboard: `https://crof.ai/dashboard`. + +## Related files + +- `Sources/CodexBarCore/Providers/Crof/` +- `Sources/CodexBar/Providers/Crof/` +- `Tests/CodexBarTests/CrofUsageFetcherTests.swift` diff --git a/docs/crossmodel.md b/docs/crossmodel.md new file mode 100644 index 0000000..454233a --- /dev/null +++ b/docs/crossmodel.md @@ -0,0 +1,69 @@ +--- +summary: "CrossModel provider: API key wallet balance and daily/weekly/monthly spend." +read_when: + - Debugging CrossModel API key usage or spend parsing + - Updating CrossModel balance or spend display + - Explaining CrossModel setup and environment variables +--- + +# CrossModel Provider + +[CrossModel](https://crossmodel.ai) is a multi-provider, OpenAI- and Anthropic-compatible API aggregation platform. You call one API and CrossModel routes the request to the right upstream provider, billing a prepaid wallet. + +## Authentication + +CrossModel uses API key authentication. Create a key in the [CrossModel console](https://crossmodel.ai/console/api-keys). Keys start with `cm-`. + +### Environment Variable + +Set the `CROSSMODEL_API_KEY` environment variable: + +```bash +export CROSSMODEL_API_KEY="cm-..." +``` + +### Settings + +You can also configure the API key in CodexBar Settings → Providers → CrossModel. + +### CLI config + +```bash +printf '%s' "$CROSSMODEL_API_KEY" | codexbar config set-api-key --provider crossmodel --stdin +``` + +## Data Source + +The CrossModel provider fetches data from two read-only API endpoints: + +1. **Credits API** (`/v1/credits`): Returns the wallet balance (`balance_micro`), currency, and any in-flight holds (`uncollected_micro`). All amounts are integer micro units (1 major currency unit = 1,000,000 micro). + +2. **Usage API** (`/v1/usage`): Returns currency plus spend, token, and request counts for the current UTC day, ISO week, and calendar month. CodexBar only displays usage spend when `/usage` currency matches `/credits` currency. + +## Display + +The CrossModel menu card shows: + +- **Balance**: Displayed in the CrossModel menu section and (optionally) in the menu bar using the API currency +- **Spend notes**: Today / this week / this month spend +- **Spend chart**: Day/week/month spend via the shared inline dashboard + +## CLI Usage + +```bash +codexbar --provider crossmodel +codexbar -p cm # alias +``` + +## Environment Variables + +| Variable | Description | +|----------|-------------| +| `CROSSMODEL_API_KEY` | Your CrossModel API key (required) | +| `CROSSMODEL_API_URL` | Override the base API URL (optional, defaults to `https://api.crossmodel.ai/v1`; loopback HTTP is allowed for local testing) | + +## Notes + +- Usage values are cached on CrossModel's side and may be up to 60 seconds stale. +- CrossModel uses a prepaid wallet; there is no per-key spending limit, so no quota meter is shown. +- The balance call is required; the usage call is best-effort, deadline-bounded, and will not block the balance if it is slow, unavailable, or returns a mismatched currency. diff --git a/docs/cursor.md b/docs/cursor.md new file mode 100644 index 0000000..24be1e7 --- /dev/null +++ b/docs/cursor.md @@ -0,0 +1,86 @@ +--- +summary: "Cursor provider data sources: browser cookies or stored session; usage + billing via cursor.com APIs." +read_when: + - Debugging Cursor usage parsing + - Updating Cursor cookie import or session storage + - Adjusting Cursor provider UI/menu behavior +--- + +# Cursor provider + +Cursor is primarily web-backed. Usage is fetched via browser cookies or a stored WebKit session, with Cursor.app local auth as a final fallback. + +## Data sources + fallback order + +1) **Cached cookie header** (preferred) + - Stored after successful browser import. + - Keychain cache: `com.steipete.codexbar.cache` (account `cookie.cursor`). + +2) **Browser cookie import** + - Cookie order from provider metadata (default: Safari → Chrome → Firefox). + - Domain filters: `cursor.com`, `cursor.sh`. + - Cookie names required (any one counts): + - `WorkosCursorSessionToken` + - `__Secure-next-auth.session-token` + - `next-auth.session-token` + +3) **Stored session cookies** (fallback) + - Captured by the "Add Account" WebKit login flow. + - Login teardown uses `WebKitTeardown` to avoid Intel WebKit crashes. + - Stored at: `~/Library/Application Support/CodexBar/cursor-session.json`. + +4) **Cursor.app local auth** (last fallback) + - Reads Cursor.app's VS Code-style global state DB for the local app bearer token. + - File: + - macOS: `~/Library/Application Support/Cursor/User/globalStorage/state.vscdb` + - Linux: `$XDG_CONFIG_HOME/Cursor/User/globalStorage/state.vscdb` (default `~/.config/Cursor/...`) + - Used only after cookie/session sources fail so existing account-selection precedence stays stable. + - On Linux, this is the primary automatic source because browser import and the WebKit login flow are macOS-only. + - Derives Cursor's first-party web-session cookie, then uses the same usage and account endpoints as browser sessions. + - Account identity comes from that authenticated session; cached app profile fields are not mixed across accounts. + +Manual option: +- Preferences → Providers → Cursor → Cookie source → Manual. +- Paste the `Cookie:` header from a cursor.com request. + +## API endpoints +- `GET https://cursor.com/api/usage-summary` + - Plan usage (included), on-demand usage, billing cycle window. +- `GET https://cursor.com/api/auth/me` + - User email + name. +- `GET https://cursor.com/api/usage?user=ID` + - Legacy request-based plan usage (request counts + limits). + +## Cookie file paths +- Safari: `~/Library/Cookies/Cookies.binarycookies` +- Chrome/Chromium forks: `~/Library/Application Support/Google/Chrome/*/Cookies` +- Firefox: `~/Library/Application Support/Firefox/Profiles/*/cookies.sqlite` + +## Linux CLI +- `codexbar usage --provider cursor` reads the signed-in Cursor app's access token from the Linux global state DB and reuses the same `cursor.com` usage endpoints as macOS. +- Automatic browser cookie import and the in-app WebKit login flow remain macOS-only. +- Manual cookie headers from `~/.config/codexbar/config.json` (or legacy `~/.codexbar/config.json`) work on Linux. + +## Local storage footprint +When **Settings → Advanced → Track provider local storage** is enabled on macOS, CodexBar measures: +- `~/Library/Application Support/Cursor` +- `~/Library/Application Support/Caches/cursor-updater` +- `~/.cursor` +- `~/Library/Caches/Cursor` +- `~/Library/Caches/com.todesktop.230313mzl4w4u92` +- `~/Library/Caches/com.todesktop.230313mzl4w4u92.ShipIt` +- `~/Library/Caches/cursor-compile-cache` +- `~/Library/HTTPStorages/com.todesktop.230313mzl4w4u92` + +The storage detail lists measured paths and their sizes. CodexBar does not delete Cursor data. + +## Snapshot mapping +- Primary: plan usage percent (included plan). +- Secondary: Auto + Composer usage percent. +- Tertiary: API (named model) usage percent. +- Provider cost: Extra usage USD. A capped individual budget wins; team accounts without a user cap use the shared team on-demand budget. +- Reset: billing cycle end date. + +## Key files +- `Sources/CodexBarCore/Providers/Cursor/CursorStatusProbe.swift` +- `Sources/CodexBar/CursorLoginRunner.swift` (login flow) diff --git a/docs/custom-provider-design.md b/docs/custom-provider-design.md new file mode 100644 index 0000000..9b430ed --- /dev/null +++ b/docs/custom-provider-design.md @@ -0,0 +1,257 @@ +--- +summary: "Accepted security and architecture boundary for declarative HTTP JSON providers." +read_when: + - Evaluating issue 1735 + - Designing runtime-defined provider identities + - Reviewing configurable endpoint or response-mapping changes +--- + +# Declarative custom provider design + +Status: accepted design boundary. This document defines a bounded MVP; it does not authorize runtime networking or +implement the feature. + +Issue: [#1735](https://github.com/steipete/CodexBar/issues/1735) + +## Decision summary + +A declarative provider can reduce one-off integrations, but it is not a small extension of LLM Proxy or LiteLLM. +Those providers still have compile-time `UsageProvider` identities, descriptors, implementations, request shapes, and response +decoders. A custom provider adds two new trust boundaries: + +1. a config file chooses where CodexBar sends a secret; +2. untrusted response data controls user-visible usage, cost, and identity fields. + +Accepted direction: pursue a config-only, GET-only, HTTP JSON MVP after separating runtime provider instance identity +from the closed `UsageProvider` enum. Do not add a single `.custom` enum case: multiple configured providers would then +collide in caches, status items, history, widgets, and settings. + +## Current constraints + +- `ProviderConfig.id` decodes directly as `UsageProvider`. +- `ProviderDescriptorRegistry` bootstraps exactly one descriptor for every `UsageProvider.allCases` value. +- `ProviderImplementationRegistry` constructs implementations with an exhaustive `UsageProvider` switch. +- Usage, errors, status, history, icons, settings, and menu state are keyed by `UsageProvider` across the app. +- The settings sidebar now persists provider-pane selection as `provider:` and still assumes one + pane per compile-time provider, reinforcing that dynamic identities need the shared seam rather than a parallel UI path. +- LLM Proxy and LiteLLM accept a configured base URL, but their request paths, auth header, decoding, and snapshot + mapping remain provider-specific Swift code. +- `ProviderEndpointOverrideValidator` already provides hardened HTTPS host parsing and an explicit loopback-HTTP mode, + while `ProviderHTTPClient` limits redirects to the same HTTPS origin. Reuse those primitives, but add a custom-provider + policy for fragments, auth-dependent loopback rules, redirect rejection, response limits, and secret-safe errors. + +## Proposed MVP contract + +### Configuration + +Keep the existing provider array and introduce config version 2 with a tagged provider definition. Existing entries remain +first-party definitions; custom entries have a stable user-chosen instance ID and a fixed implementation kind. + +```json +{ + "version": 2, + "providers": [ + { + "id": "acme-gateway", + "kind": "custom-http-json", + "label": "Acme Gateway", + "enabled": true, + "request": { + "method": "GET", + "url": "https://gateway.example.com/v1/quota", + "authentication": { "type": "bearer" } + }, + "mapping": { + "primary": { + "usedPercent": { "path": "quota.used_pct" }, + "resetsAt": { "path": "quota.reset_at", "dateFormat": "iso8601" }, + "windowMinutes": { "path": "quota.window_minutes" } + }, + "cost": { + "used": { "path": "spend.usd" }, + "currency": "USD", + "period": "Approx. spend" + }, + "identity": { + "organization": { "path": "plan.name" }, + "loginMethod": { "literal": "api" } + } + } + } + ] +} +``` + +Rules: + +- `id`: lowercase ASCII letters, digits, and hyphens; 1–64 characters; unique across first-party and custom providers. +- `label`: required, trimmed, 1–80 characters. MVP uses a built-in generic icon. +- `method`: only `GET`. +- `authentication`: `none`, `bearer`, or `x-api-key`; the secret is never inline. Authenticated instances read only their + derived variable `CODEXBAR_CUSTOM__API_KEY`, with the ID uppercased and hyphens replaced by underscores. + A definition cannot name an arbitrary environment variable or header; bearer uses `Authorization` and x-api-key uses + `X-API-Key`. +- `mapping.primary`: optional. When present, requires exactly one of `usedPercent` or `remainingPercent`. Optional fields + are omitted when their paths are missing or null. +- `mapping.cost`: when present, requires `used`; `currency` is a three-letter uppercase literal and `period` is a bounded + literal. A missing limit maps to zero, matching existing sparse cost snapshots. +- `mapping.identity`: optional bounded strings. The configured provider instance ID, not response data, owns snapshot + identity. +- A definition that produces neither a rate window nor cost data is invalid. + +### Mapping language + +Use a typed dot-path subset, not JSONPath, jq, JavaScript, predicates, or string interpolation. + +Grammar: + +```text +path = segment *("." segment / "[" index "]") +segment = ALPHA *(ALPHA / DIGIT / "_" / "-") +index = 1*DIGIT +``` + +Each target field determines its accepted type. Number coercion accepts JSON numbers and finite numeric strings only. +Percentages are clamped to 0–100 after rejecting NaN and infinity. Dates require an explicit format: `iso8601`, +`unix-seconds`, or `unix-milliseconds`. Display strings are trimmed and length-limited. Missing optional paths do not fail +the whole snapshot; a present value with the wrong type does. + +No wildcards, recursive descent, filters, arithmetic, template evaluation, or user-supplied code. Multi-window arrays and +aggregation are later design work. + +Hard limits: 16 mapped leaves per definition; 256 UTF-8 bytes and 32 components per path; 64 ASCII characters per +segment; array indices 0–4095; response JSON nesting depth 64; mapped display strings 256 UTF-8 bytes. Validate these +limits before traversal. Preflight structural nesting directly on the bounded response bytes with an iterative, +string-aware scanner before materializing JSON, so a hostile nested payload cannot exhaust the call stack. + +### Network and secret boundary + +- Require HTTPS for authenticated requests. Allow HTTP only for an unauthenticated loopback URL (`localhost`, + `127.0.0.0/8`, or `::1`). Reject URL user info and fragments. +- Extend `ProviderEndpointOverrideValidator`; do not create a second URL parser. Use a dedicated + `ProviderHTTPClient` configuration that rejects every redirect, even though the shared client safely permits same-origin + HTTPS redirects. +- Bind the secret to the validated origin. Disable redirects for MVP; a 3xx response is an error. +- Before any custom-provider fetch, require a local approval record binding the instance ID, complete normalized request + URL, origin, and auth type. Authenticated approvals also bind the fixed header and derived variable name. Store this + record outside the provider config. First use requires explicit app or interactive CLI confirmation that displays the + exact normalized URL and auth fields; headless use fails closed. No import or bulk-approval path is allowed. Loopback, + IP-literal, `.local`, and visibly private targets require typing the normalized URL instead of accepting a button. Any + bound-field change invalidates approval before the next fetch. This gate applies to unauthenticated loopback HTTP too. +- Never interpolate a secret into a URL, path, query, body, label, mapping, diagnostic, or log. +- Resolve the derived environment variable only after approval, when the provider is enabled and a fetch starts. Do not + enumerate the environment. +- Use a dedicated `URLSessionConfiguration.ephemeral` session with `httpCookieStorage = nil`, + `httpShouldSetCookies = false`, `urlCredentialStorage = nil`, `urlCache = nil`, and a reload-ignoring-local-cache policy. + Do not share a session with first-party providers. A dedicated challenge handler allows normal server-trust evaluation + only and cancels client-certificate or HTTP authentication challenges. +- Send `Accept-Encoding: identity`, reject a non-identity `Content-Encoding`, and enforce the streaming 1 MiB cap on bytes + delivered after URL loading's decoding and before JSON materialization. Cancel the task when the cap is exceeded. Use a + 15-second total timeout and a JSON content-type check. +- Accept only 2xx responses. Error text may include status and a bounded generic summary, never request headers or the raw + response body. +- Keep custom-provider response data out of provider status polling, cookie import, OAuth, Keychain, token accounts, + browser automation, and CLI subprocess paths. +- Custom definitions must be local config only. No remote catalogs, downloaded definitions, or config URLs. + +### Runtime identity seam + +Introduce a `ProviderInstanceID` string value that identifies one configured instance. Keep `UsageProvider` as the +compile-time implementation kind for first-party providers. + +```text +ProviderDefinition + firstParty(instanceID, UsageProvider, ProviderConfig) + customHTTPJSON(instanceID, CustomHTTPJSONConfig) +``` + +Migrate runtime dictionaries, persistence keys, `ProviderIdentitySnapshot.providerID`, and identity accessors that +represent an enabled provider instance to `ProviderInstanceID`. First-party instance IDs retain their current raw values, +preserving existing config and stored history. Provider-specific fetchers continue to receive `UsageProvider`; the custom +fetcher receives only its validated custom definition. Provider-specific identity payloads remain keyed by their +compile-time implementation kind, while shared organization and login-method fields belong to the provider instance. + +This seam must land independently with characterization tests before the custom network path. It prevents a custom +provider from being threaded through exhaustive first-party switches or sharing state with another custom instance. + +## Threat model + +| Threat | Required mitigation | +|---|---| +| Shared or malicious config exfiltrates a secret | Dedicated per-instance variable; separate full-URL/auth approval before secret resolution; config changes invalidate approval; redirects disabled | +| Endpoint redirects auth to another host | Treat every redirect as failure | +| Shared config silently probes or changes a GET target | No network access before separate full-URL approval; any URL change invalidates it; no bulk approval; elevated confirmation for visibly local/private targets | +| Hostile JSON causes CPU or memory pressure | 1 MiB cap; bounded depth and path length; no recursive expressions; request timeout | +| Response injects misleading or huge menu text | Typed targets; numeric bounds; string trimming and length limits; configured identity wins | +| Secret or response leaks through diagnostics | Redacted request description; no headers or raw response body in errors/logs | +| Two custom providers overwrite one another | Stable `ProviderInstanceID` keys throughout runtime and persistence | +| Config silently changes first-party behavior | Tagged definition; versioned decoder; duplicate/reserved ID rejection; migration tests | + +Out of scope: defending a user from a request URL they explicitly approved, including a public hostname that later +resolves to a local or private address. Approval grants that origin network authority for the approved URL; the +confirmation must state this clearly. CodexBar still must contain the service response and must never disclose unrelated +credentials. + +## Explicit non-goals + +- Settings UI for creating or editing custom providers. +- Full JSONPath, jq, scripts, plugins, transforms, arithmetic, or templates. +- POST/PUT/PATCH/DELETE, request bodies, refresh mutations, or multiple endpoints. +- Arbitrary headers, cookies, OAuth, browser sessions, Keychain discovery, file-secret references, or inline secrets. +- Custom SVG/file icons, downloaded assets, or remote provider manifests. +- Status-page discovery, incident notifications, chat/model APIs, cost-log scanning, widgets, or token accounts. +- Arrays of rate windows, cross-response joins, pagination, aggregation, or provider-specific special cases. +- Compatibility shims that reinterpret an unknown first-party provider ID as a custom provider. + +## Implementation slices + +1. **Identity seam:** add `ProviderInstanceID`; migrate config/runtime/persistence keys without behavior changes; add + decode, history, enablement, menu, CLI, and widget characterization tests. +2. **Pure evaluator:** add config types, validator, dot-path parser, typed coercion, and `UsageSnapshot` mapping using only + fixture data. +3. **Bounded transport:** add URL/auth policy and an injected HTTP transport; prove redirect, timeout, size, content-type, + status, and redaction behavior. +4. **Config and CLI integration:** version-2 migration, `codexbar config validate`, local approval records and interactive + approval command, diagnostics, and custom-provider CLI output. No live credentials in tests. +5. **App integration:** generic metadata/icon, refresh lifecycle, menu rendering, persistence, and disabled/error states + through existing shared provider UI. + +Each slice should be a separately reviewable PR. Do not combine the identity migration and arbitrary networking in one +change. + +## Required proof before enabling the feature + +- Config v1 round-trip and v1-to-v2 migration preserve every existing provider entry. +- Duplicate, reserved, malformed, and colliding instance IDs fail validation. +- Multiple custom instances keep snapshots, errors, histories, menu selection, and persistence isolated. +- URL table covers HTTPS, user info, fragments, loopback HTTP, private/public HTTP, IPv4/IPv6, ports, and redirects. +- Auth tests prove the secret reaches only the intended header and never URL, errors, fixtures, snapshots, or logs. +- Approval tests prove first use and every bound-field change fail closed before network or environment access, and that + one instance cannot reuse another instance's approval or derived secret variable. UI/CLI proof covers exact-URL + display, no bulk approval, and typed confirmation for loopback, IP-literal, `.local`, and visibly private targets. +- Mapping tests cover missing/null paths, arrays, wrong types, date formats, finite-number enforcement, every numeric + path/depth/count bound, iterative depth rejection, and string limits. +- Transport tests cover timeout, cancellation, decoded response cap, compressed-response rejection, content type, + non-2xx, and 3xx without live network access. +- Transport isolation tests prove ambient cookies and URL credentials are neither sent nor persisted and cached responses + are not reused. +- Source-blind CLI proof: a fixture endpoint plus isolated config produces the expected usage, cost, identity, and redacted + failure output. +- `make test`, `make check`, structured autoreview, and exact-head CI are green for every implementation PR. + +## Accepted owner decisions + +1. Declarative provider support is worth the runtime identity migration and long-term versioned schema support. +2. MVP may use unauthenticated loopback HTTP only under the same separate approval gate, including typed confirmation of + the normalized URL. Every authenticated request requires HTTPS. +3. A derived per-instance environment variable plus local URL/auth approval is the only MVP secret source. Keychain + storage is deferred; the initial design must not imply or preserve a second secret path. +4. MVP supports one primary rate window, with cost and identity optional. Multi-window and aggregation semantics remain + out of scope. +5. The first integrated surface is CLI-only. App settings and menu integration wait until the shared runtime accepts + dynamic identities without provider-specific side paths. + +Implementation gate: keep custom-provider networking disabled until the independent identity migration, pure evaluator, +bounded transport, approval flow, and their required proof land as separately reviewable changes. If an implementation +cannot preserve this boundary, stop rather than shipping a single `.custom` slot, a parallel UI path, or a compatibility +fallback. diff --git a/docs/deepgram.md b/docs/deepgram.md new file mode 100644 index 0000000..bda08e7 --- /dev/null +++ b/docs/deepgram.md @@ -0,0 +1,111 @@ +--- +summary: "Deepgram provider: API key setup, project discovery, and usage-breakdown metrics." +read_when: + - Debugging Deepgram API key or project selection + - Updating Deepgram usage parsing or menu display + - Explaining Deepgram setup to users +--- + +# Deepgram Provider + +[Deepgram](https://deepgram.com) is a speech AI platform that provides APIs for speech-to-text, text-to-speech, audio intelligence, and related voice features. + +## Authentication + +Deepgram uses API key authentication. Get your API key from the [Deepgram Console](https://console.deepgram.com). + +The API key must have access to the project you want to query. For usage data, the key also needs the `usage:read` scope for that project. + +### Environment Variables + +Set the `DEEPGRAM_API_KEY` environment variable: + +```bash +export DEEPGRAM_API_KEY="dg_..." +``` + +Optionally set a Deepgram project ID: + +```bash +export DEEPGRAM_PROJECT_ID="your-project-uuid" +``` + +If `DEEPGRAM_PROJECT_ID` is omitted, CodexBar calls Deepgram's project list endpoint and aggregates usage across all projects visible to the API key. + +### Settings + +You can also configure the API key and optional project ID in CodexBar Settings → Providers → Deepgram. + +### CLI config + +```bash +printf '%s' "$DEEPGRAM_API_KEY" | codexbar config set-api-key --provider deepgram --stdin +``` + +## Data Source + +The Deepgram provider fetches summarized usage data from the Deepgram Management API. + +1. **Projects API** (`/v1/projects`): Lists projects visible to the API key when no project ID is configured. +2. **Usage Breakdown API** (`/v1/projects/{PROJECT_ID}/usage/breakdown`): Returns summarized project usage over a date range. The response includes fields such as `start`, `end`, `resolution`, and `results`. + +Each usage result may include: + +* `start` +* `end` +* `hours` +* `total_hours` +* `agent_hours` +* `tokens_in` +* `tokens_out` +* `tts_characters` +* `requests` + +Deepgram's usage breakdown endpoint supports querying with `start` and `end` date parameters. The response includes summarized usage results for the selected period. + +## Display + +The Deepgram menu card shows: + +* **Usage notes**: Request count, total audio hours, total billable hours, agent hours, token totals, and TTS characters when returned by Deepgram +* **Identity**: Project name, project ID, or aggregated project count + +Deepgram does not currently provide a credit balance through this provider. The provider displays usage, not remaining credits. + +## CLI Usage + +```bash +codexbar --provider deepgram +codexbar -p dg # alias +``` + +## Environment Variables + +* **DEEPGRAM_API_KEY**: Your Deepgram API key. Required. +* **DEEPGRAM_PROJECT_ID**: Optional Deepgram project UUID. Leave unset to aggregate all visible projects. +* **DEEPGRAM_API_URL**: Override the base API URL. Optional, defaults to `https://api.deepgram.com/v1`. + Override values must be explicit HTTPS URLs or bare hosts/paths that CodexBar normalizes to HTTPS. Explicit + `http://` URLs fail closed before the Deepgram API key is attached to a request. For local proxy testing, use an + HTTPS listener or omit the scheme and let CodexBar normalize the override to HTTPS. + +## Permissions + +The API key must have permission to read usage data for the configured project. + +If the key is valid but lacks the correct scope, Deepgram may return an error like: + +```text +INSUFFICIENT_PERMISSIONS +Your account does not have the required scope to perform that action for this project. +Check that your account has the 'usage:read' scope for this project. +``` + +In that case, create or update a Deepgram API key with the `usage:read` scope for the target project. + +## Notes + +* Deepgram usage data is project-scoped. +* The project ID should be the project UUID, not just the project display name. +* The provider uses `Authorization: Token ` for requests. +* This provider currently reports usage metrics, not credit balance or per-request cost. +* Summarized usage data is not limited to 90 days, while console logs are limited to 90 days. diff --git a/docs/deepseek.md b/docs/deepseek.md new file mode 100644 index 0000000..1db239e --- /dev/null +++ b/docs/deepseek.md @@ -0,0 +1,39 @@ +--- +summary: "DeepSeek provider data sources: API key + balance endpoint." +read_when: + - Adding or tweaking DeepSeek balance parsing + - Updating API key handling + - Documenting new provider behavior +--- + +# DeepSeek provider + +DeepSeek is API-only. Balance is reported by `GET https://api.deepseek.com/user/balance`, +so CodexBar only needs a valid API key to show your remaining credit balance. + +## Data sources + +1. **API key** supplied via `DEEPSEEK_API_KEY` / `DEEPSEEK_KEY`, or selected from DeepSeek token accounts in `~/.codexbar/config.json`. +2. **Balance endpoint** + - `GET https://api.deepseek.com/user/balance` + - Request headers: `Authorization: Bearer `, `Accept: application/json` + - Response contains `is_available`, and a `balance_infos` array with per-currency entries + (`total_balance`, `granted_balance`, `topped_up_balance`). + +## Usage details + +- The menu card shows total balance with the paid vs. granted breakdown: + e.g. `$50.00 (Paid: $40.00 / Granted: $10.00)`. +- The API separates granted balance from topped-up balance; CodexBar labels these as granted vs. paid credit. +- When multiple currencies are present, USD is shown preferentially. +- If total balance is zero, CodexBar shows an add-credits message. If balance is nonzero but `is_available` is false, it shows "Balance unavailable for API calls". +- There is no session or weekly window — DeepSeek does not expose per-window quota via API. +- Token-account selection injects the selected key into the fetch environment; otherwise CodexBar reads `DEEPSEEK_API_KEY` / `DEEPSEEK_KEY`. + +## Key files + +- `Sources/CodexBarCore/Providers/DeepSeek/DeepSeekProviderDescriptor.swift` (descriptor + fetch strategy) +- `Sources/CodexBarCore/Providers/DeepSeek/DeepSeekUsageFetcher.swift` (HTTP client + JSON parser) +- `Sources/CodexBarCore/Providers/DeepSeek/DeepSeekSettingsReader.swift` (env var resolution) +- `Sources/CodexBar/Providers/DeepSeek/DeepSeekProviderImplementation.swift` (provider activation and token-account visibility) +- `Sources/CodexBarCore/TokenAccountSupportCatalog+Data.swift` (DeepSeek token-account injection) diff --git a/docs/devin.md b/docs/devin.md new file mode 100644 index 0000000..df4f146 --- /dev/null +++ b/docs/devin.md @@ -0,0 +1,43 @@ +--- +summary: "Devin provider auth, quota endpoint, and setup." +read_when: + - Adding or modifying the Devin provider + - Debugging Devin localStorage import or quota parsing + - Explaining Devin setup +--- + +# Devin Provider + +The Devin provider tracks included daily and weekly usage quotas from +[app.devin.ai](https://app.devin.ai). + +## Setup + +1. Sign in to Devin in Google Chrome. +2. Open the organization Usage & Limits page once. +3. Enable **Devin** in **Settings → Providers**. + +Automatic mode reads only the Devin session and organization metadata from Chrome localStorage. It does not scan other +browsers. CodexBar sends the session token only to `https://app.devin.ai`. + +## Manual Auth + +Set **Auth source** to **Manual**, then paste either the bare token or the full `Authorization: Bearer ...` header value +from an app.devin.ai API request. The optional organization field accepts a slug, an internal `org_...` ID, or the full +organization URL. + +Environment overrides: + +- `DEVIN_BEARER_TOKEN` or `DEVIN_AUTHORIZATION` +- `DEVIN_ORGANIZATION` or `DEVIN_ORG` + +## Data Source + +CodexBar requests: + +```text +GET https://app.devin.ai/api//billing/quota/usage +``` + +The response supplies daily and weekly usage percentages plus reset timestamps. If Devin changes or expires the browser +session, sign in again and refresh CodexBar. diff --git a/docs/doubao.md b/docs/doubao.md new file mode 100644 index 0000000..40c7cfa --- /dev/null +++ b/docs/doubao.md @@ -0,0 +1,22 @@ +--- +summary: "Doubao provider notes: API-key auth and Volcengine Ark request-limit tracking." +read_when: + - Adding or modifying the Doubao provider + - Debugging Doubao API-key setup + - Explaining Doubao usage display +--- + +# Doubao Provider + +Doubao tracks Volcengine Ark request-limit headers by probing the chat-completions endpoint with a configured API key. + +## Setup +1. Enable **Doubao** in Settings → Providers. +2. Paste an API key in the provider settings, or set `ARK_API_KEY`, `VOLCENGINE_API_KEY`, or `DOUBAO_API_KEY`. +3. Refresh provider usage. + +## Behavior +- Endpoint: `POST https://ark.cn-beijing.volces.com/api/coding/v3/chat/completions` +- Probe models: `doubao-seed-2.0-code`, `doubao-1.5-pro-32k`, `doubao-lite-32k` +- Reads `x-ratelimit-remaining-requests`, `x-ratelimit-limit-requests`, and `x-ratelimit-reset-requests` when returned. +- If the key is valid but rate-limit headers are missing, CodexBar shows the key as active and links to the dashboard for details. diff --git a/docs/elevenlabs.md b/docs/elevenlabs.md new file mode 100644 index 0000000..dae8b14 --- /dev/null +++ b/docs/elevenlabs.md @@ -0,0 +1,63 @@ +--- +summary: "ElevenLabs provider notes: API key setup and subscription usage fields." +read_when: + - Adding or modifying the ElevenLabs provider + - Debugging ElevenLabs API keys or subscription usage parsing + - Adjusting ElevenLabs credit or voice-slot labels +--- + +# ElevenLabs Provider + +The ElevenLabs provider reads subscription usage from the ElevenLabs API using an API key. + +## Features + +- Character credit usage from the current subscription period. +- Reset timing when the API returns `next_character_count_reset_unix`. +- Voice slot and professional voice slot usage when those fields are present. +- Plan/status text from the subscription response. + +## Setup + +### CLI + +Store the API key without opening Settings: + +```bash +printf '%s' "$ELEVENLABS_API_KEY" | codexbar config set-api-key --provider elevenlabs --stdin +``` + +This trims the piped key, writes it to `~/.codexbar/config.json` with restrictive permissions, and enables ElevenLabs by default. Use `--no-enable` to save the key without enabling the provider. + +### Settings + +1. Open **Settings -> Providers** +2. Enable **ElevenLabs** +3. Open `https://elevenlabs.io/app/settings/api-keys` +4. Create or copy an API key +5. Paste the key into CodexBar's ElevenLabs provider settings + +### Environment Variables + +CodexBar also accepts these environment variables: + +- `ELEVENLABS_API_KEY` +- `XI_API_KEY` + +For tests or self-hosted/proxy setups, override the API base URL with `ELEVENLABS_API_URL`. + +## How It Works + +- Endpoint: `GET https://api.elevenlabs.io/v1/user/subscription` +- Auth header: `xi-api-key` +- Fields used: `character_count`, `character_limit`, `voice_slots_used`, `voice_limit`, `professional_voice_slots_used`, `professional_voice_limit`, `tier`, `status`, `next_character_count_reset_unix` + +## Troubleshooting + +### "Missing ElevenLabs API key" + +Set the key with `codexbar config set-api-key --provider elevenlabs --stdin`, add it in **Settings -> Providers -> ElevenLabs**, set `ELEVENLABS_API_KEY`, or configure an ElevenLabs token account. + +### "ElevenLabs API error" + +Confirm the API key is valid and that the current network can reach `api.elevenlabs.io`. diff --git a/docs/factory.md b/docs/factory.md new file mode 100644 index 0000000..5924ba0 --- /dev/null +++ b/docs/factory.md @@ -0,0 +1,147 @@ +--- +summary: "Factory (Droid) provider data sources: API key, browser cookies, WorkOS tokens, and Factory APIs." +read_when: + - Debugging Factory/Droid usage fetch + - Updating Factory cookie, API key, or WorkOS token handling + - Adjusting Factory provider UI/menu behavior +--- + +# Factory (Droid) provider + +Factory (displayed as "Droid") supports API-key and web-based auth. Source mode can be `auto`, `api`, or `web`. + +## Data sources + fallback order + +### API (`api`) +1. Resolve a Factory API key from, in order: + - `~/.codexbar/config.json` `providers[].apiKey` for `factory` (also via Settings or + `codexbar config set-api-key --provider factory`) + - `FACTORY_API_KEY` + - optional `~/.factory/.env` (`FACTORY_API_KEY=…` or `export FACTORY_API_KEY=…`) +2. Call Factory APIs with `Authorization: Bearer ` (same billing-limits / bearer path as session tokens). + +### Web (`web`) +Fetch attempts run in this exact order: +1) **Cached cookie header** (Keychain cache `com.steipete.codexbar.cache`, account `cookie.factory`). +2) **Stored session** (`~/Library/Application Support/CodexBar/factory-session.json`). +3) **Stored bearer token** (same session file). +4) **Stored WorkOS refresh token** (same session file). +5) **Local storage WorkOS tokens** (Safari + Chrome/Chromium/Arc leveldb). +6) **Browser cookies (Safari only)** for Factory domains. +7) **WorkOS cookies (Safari)** to mint tokens. +8) **Browser cookies (Chrome, Firefox)** for Factory domains. +9) **WorkOS cookies (Chrome, Firefox)** to mint tokens. + +If a step succeeds, we cache cookies/tokens back into the session store. + +Manual option: +- Preferences → Providers → Droid → Cookie source → Manual. +- Paste the `Cookie:` header from app.factory.ai. + +### Auto (`auto`) +1. Try API first when a key is resolvable. +2. Fall back to web strategies on missing/unauthorized keys and other recoverable API failures + (timeouts, DNS/network errors, 5xx, parse failures). Cancellation does not fall back. +3. Explicit `api` mode stays strict and does not fall back to web. +4. When both an API key and a browser/WorkOS session are available, Auto may surface the API-key + account rather than the browser session. Use explicit `web` (or `api`) to pin account precedence. + +## Settings +- Preferences → Providers → Droid: + - Usage source: `Auto`, `API key`, `Browser cookies` + - API key: optional override for `FACTORY_API_KEY` / `~/.factory/.env` + - Cookie source: Automatic / Manual (web path) + +## CLI +```bash +printf '%s' "$FACTORY_API_KEY" | codexbar config set-api-key --provider factory --stdin +codexbar usage --provider factory --source api +codexbar usage --provider factory --source web +``` + +## Cookie import +- Cookie domains: `factory.ai`, `app.factory.ai`, `auth.factory.ai`. +- Cookie names considered a session: + - `wos-session` + - `__Secure-next-auth.session-token` + - `next-auth.session-token` + - `__Secure-authjs.session-token` + - `__Host-authjs.csrf-token` + - `authjs.session-token` + - `session` + - `access-token` +- Stale-token retry filters: + - `access-token`, `__recent_auth`. + +## Base URL selection +- Candidates are tried in order (deduped): + - `https://auth.factory.ai` + - `https://api.factory.ai` + - `https://app.factory.ai` + - `baseURL` (default `https://app.factory.ai`) +- Cookie domains influence candidate ordering (auth domain first if present). + +## Factory API endpoints +All requests set: +- `Accept: application/json` +- `Content-Type: application/json` +- `Origin: https://app.factory.ai` +- `Referer: https://app.factory.ai/` +- `x-factory-client: web-app` +- `Authorization: Bearer ` when a bearer token / API key is available. +- `Cookie: ` when cookies are available. + +Endpoints: +- `GET https://api.factory.ai/api/billing/limits` + - Preferred when the account uses token-rate-limits billing (5h / weekly / monthly windows). +- `GET /api/app/auth/me` + - Returns org + subscription metadata + feature flags. +- `GET /api/organization/subscription/usage` + - Query: `useCache=true` and optional `userId` + - Returns Standard + Premium token usage and billing window. + +## WorkOS token minting +- Endpoint: + - `POST https://api.workos.com/user_management/authenticate` +- Body: + - `client_id`: one of + - `client_01HXRMBQ9BJ3E7QSTQ9X2PHVB7` + - `client_01HNM792M5G5G1A2THWPXKFMXB` + - `grant_type`: `refresh_token` + - `refresh_token`: from local storage or session store + - Optional: `organization_id` + - When using cookies: `useCookie: true` + `Cookie: ` + +## Local storage WorkOS token extraction +- Safari: + - Root: `~/Library/Containers/com.apple.Safari/Data/Library/WebKit/WebsiteData/Default` + - Finds `origin` files containing `app.factory.ai` or `auth.factory.ai`, then reads + `LocalStorage/localstorage.sqlite3`. +- Chrome/Chromium/Arc/Helium: + - Roots under `~/Library/Application Support//User Data//Local Storage/leveldb`. + - Helium uses `~/Library/Application Support/net.imput.helium//Local Storage/leveldb` (no `User Data`). + - Scans LevelDB files for `workos:refresh-token` and `workos:access-token`. +- Parsed tokens: + - `workos:refresh-token` (required) + - `workos:access-token` (optional) + - Organization ID parsed from JWT when available. + +## Session storage +- File: `~/Library/Application Support/CodexBar/factory-session.json` +- Stores cookies + bearer token + WorkOS refresh token. + +## Snapshot mapping +- Token-rate-limits accounts: primary 5h, secondary weekly, tertiary monthly (+ optional Core windows). +- Legacy Standard/Premium accounts: primary Standard, secondary Premium; reset at billing period end. +- Plan/tier + org name from auth response. + +## Troubleshooting +- Missing API key: set `FACTORY_API_KEY`, Settings → Droid → API key, or `codexbar config set-api-key --provider factory`. +- Unauthorized API key (401/403): regenerate at app.factory.ai/settings/api-keys. +- Missing session: log in to app.factory.ai in a supported browser, or paste a Cookie header in Manual mode. + +## Key files +- `Sources/CodexBarCore/Providers/Factory/FactoryProviderDescriptor.swift` +- `Sources/CodexBarCore/Providers/Factory/FactorySettingsReader.swift` +- `Sources/CodexBarCore/Providers/Factory/FactoryStatusProbe.swift` +- `Sources/CodexBarCore/Providers/Factory/FactoryLocalStorageImporter.swift` diff --git a/docs/features/feature-credits.webp b/docs/features/feature-credits.webp new file mode 100644 index 0000000000000000000000000000000000000000..72b1d46ef09083ecf90d84d71a5c09bec5493890 GIT binary patch literal 246520 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 z%0D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�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 literal 0 HcmV?d00001 diff --git a/docs/features/feature-resets.webp b/docs/features/feature-resets.webp new file mode 100644 index 0000000000000000000000000000000000000000..00211bf99102d91b225acc41372b0f088a388f40 GIT binary patch literal 494596 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 o60*q4xnVHKV*%zyAGO=cns#IZ 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 z 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�d)_WPyN^E!;}hWzv{Jv^TY&nw-7 z`U`~gk)P2q!%|s0<6NNPI@s_qAyJrvr}d;Fp@x_=Nx;mI+Cc4|&wVA%X5yNU;w_VXPi-A zM&dRdyXo?5qyuSLDzqF>2-65PSF!D>j_{9boQ0)&m6@CmZ^(x0^vfbk71aUirIoXZcZS;!1H@jr7D{y;opkC2o>j8bJ)k#Kh$juM#$gQYfoAmQ%o z0#zSkT>%KKRg=CNYmUwW#irWTi@OT~*?nM{;g-2)>lcBv?ef|qSOIMW z=h6(3AqR<`*W=q81ev$UygshWD$A?2=cTaCwH=DCdZ1iI)KSVIi&SoB{DA*?AwbwQRyO{)$H}nHxBm<78>$RJ2)dt)v5wRJXpZ>-yXOk;h+qcrz;)?t zGp`}e=Q#nmG7?!sB4RYT4(id^MTI)f_@U@e2`|CKhtp$iI+ zd#qkCKbBRwC6trSQ?=6UZ_}Q9NwrV+!|Ic92(O$&93F>bTJG zgH8)8c>&}I}mJ^^$ps3YsaTR@k&La3FGsO zeSp&3d_;xSBNjZ&a|=wS>9OVH1Ibe4EbfOVv`~5C}H`rX0*b6=KV>(B|6MK`KayhG0l+=gu zuz~B`4b836>UHLPVf-?!X(V7|MH|LEwcl3A3=OktN>_41NflIUd_-VC74t27x@;Na zx%{+D9bBpC9vfu4Rl@L3ax6M7G$8iY@`C)9i|zse3=s|dziM7ltMtaXi674im(6dS z$=tZ|ZHt*9%AVsysb<3n_$ZjB%!*3QUsUyCuC#fQJ>362frT7Xwn!wM5VkaR3l-n( zKYJt_IYMcQKNz1Wx}-2A276J0J{h0IY>!xQuMuh2==P%5bN^T9nI`CDuG35=K?pUG zOj;d6L3h1?NVkq&1LW1UKv-Wp)cfnaY_COSxXbsW%@pF|g||moYjO}0j)v7Un69^$ zrNU^T)YH}Z8&c`4^0*L08DNAVm*?UdrHrfpB-<4PX}sz6bq|u8GhICE_Nvvt|mO9^h8)vazz<6~?IReDw0KT1$ zl`#2~Jzr_n(GpP_adO6>=f}5#2><#ui2ogtzGefE;a`XZyIx$1o01STp1}gEsxJiV z|7ZWUl+75h_&(3KeUEss_e=cP0`jQSrcCUQ_fvzLq62+I%tk3Q3fo0^%!OO~QK4!6 zPP%n~_rwbC&22##JYORjHQn3XqAgJg#HabpcTd94y8PU#z^6u!3nSp3y}N>ns=1Uy zvCj-3W&vH76F{+t=ascsWC!IKNSh8FCB+@ND%3HHcOt8C4+>t5n1>zVstdk0$60)h zA5?-{_;Qd}j=5Hw2_T-?m0VS4-;dBf45l=iBtojn^DR0g*nTch!{JXY1g~_4j4S~r z<}e}gWiQQ^oNt;)qJ_G_J;}@#i`5LHFpl}7yPJ%M;cpVxR8?MkD@1>KEEkVOIvWZ# z;=${560@KxNZTJ%n4k~%qFWJ>d8sRYcAxZl0}0a&<0gCah~4j9KFnm+?#CGCBQD|O zQ(I-$RyN-#m3bP%)Bgu7FR9btL*4Zc6KMyI6_LtMxhi(dF)h^iDYVaf<-u|d!k*%! zFaM?Za6E6o9*mck)<6(zBeL{j$K)m@qz8uK`;+``c_1we+l4?g6F>}7)fWF&C8<2W zj5{UQ9EzEsiysFEFN`;4kz>I5;jLVt#Kl*dl*uoH_wyze+UTUf(c8j(k4}T10~*<8 z$`)tD9*|>2gOe*pvfH^zibl{E;?Vp3D%Hnnz;$RvmKjuY7)sIDQPnFOC}Jt9uF_m) z=oz8}F}xjUzKs5ztdN`$>;KTQdh%yAo1okr%=RKrQ7ciVc?sw zF3GSTTtiDGNRG9GB^hg~xzbA#jcLgl;%%d=6WC!M2BcYAMjGVV@g;r@7@dMEAF$JB ze{+$S^B0^7*XK{1nkYN6w!0Z)VCd&fyc|sZYNVl=*xRNrkmRyVy&aodxv@U4nvYO2 z$JO>d>Bx)D$ELR&Cf53&e+XnIU$&#r!u}&EHmw{9HZY$f`5!!C*GNkk13a9@DsH7> zc@ChNVyBNXulAzb$kvU)*#VQNKCHT(af!nq`h$ibWIlW0BJ?Vt_K61}YBec_ zr_lP1?v(15fqGS?tVotsAte~y&GXTsa}=Av6aWxMxh07|=Cnm?5>V@1=9!{z1KCu* zj^xHc8{!DT>bjy_(`_R91AK&56a`Qkzy=EQsA1O$qJa#LCrYW;T+KgU72Mzo+&}oO zsnP{bsoP6-N>Hhn+7_OZ*rtzIzQ&jwW6=N*tg6PO?xSxWaIagZA$|r(+xq>Gej-*k zXn5|)nNUXS>&<$>HLmX9!l6h>5d)RyEtH;y5!ps^W64o7>M{fwtzY_e*0o&hZW#a%pQHiMBL4T`uy+ew}i`>#lK{4arXS)@)uciV1b>q9>;0-DkmRTW;XmFhl9*X5^YpT_Ty)H_cP1t(ef z7MsnCeU1UVF?pCF*vzRU7QZl^0?Bn6hRM-b^s@xhp?&|k+w87XJ0{8d0ne4X=G-N` zLc!0c&eo3bHC_R%P>g3;i4~*p!dBG<_V+h@4XxIxPd?>(gKrw^#U;rWHmPQmP?P;T zqS5YJ;`ms?K=BaSnwR}8=_XFVX__TkyZ${A!gPz<&D|ZXA8(t=mYNbXAbM%)6&vqo z6Qf&58LiGt)diy(c+iQlrF13QBJF*sx^;nN#}gf#Q!R*%^K;^G&2;K@jAW){o?A@BazCXOBa$@OW{(NN9cSV1hZsFfgK z5NBIwyy23sV*9W+d!}EwzYsa730Fh9CQ7VH%J5_oSGRuoR;0F>ttAcz6d8{nkH%7|UqW&(GW)sCHmKIX9R&MhJ z%P`&n-1-~?tsk5zgaWP@qE4P-8Rk*sEEYG@PWC7wy)CGLCt2I!wJas+2BMdEJ|W02GjslC_J10I^eMEpEpi~Z^Lcyg7p*MUn@#$3seJ?4}9HQJ2o%?F@FK=~ze zmAe7FIY`IQBmby4Wg=z*;bu8f%92-@yEiCD3y{xXJ&ha+yS2mkk^l{D8JUFwKZ<#_ zffLa!nD31Mjjaxwo`AOqpAlCg&SKVlJSUs{Sz{iZoSj^>4iVa9DTA?b=^3gPqUdT` z`ssjdegDpzz-G7f>4rX!TYn*-*-h(D#09z|HZLC(S*$|A*L{JO`gsim1M3%9;gl-n z%H~nz+P}+}GKp+GRj3O|Fqw!oInOeerKWaxfshU%;69-it=WPC5S+v91D)0Yu$wY^qMn>>x0E>9wJ4HnpeYy~!N12skLcgf4P zwpQ+3f|esH*9D!5c&WGrWnIrsc;$1FHqWcqX*8s{jOeGY%y~}%(XYBw&p|@XcoE&`v{o*~!Ka}~{LrhZ|EcfKH`(hr1l9f%5`Lff`}QnpxkTVW%KYB^R@Fyf-)w4v zUhw{+9~pBrrCsmz1BE10j0IO6t5O)YT;UqkFT4l(m#vO$scQZraOURAvhQ zSeNovUo~g?{uYC;TlCGodwrIPAsTs!0TVpkVZAU!v5pL_1OD#Ls3711ODUj3Af6J=^p+**fYH%pXj2gR=frHIQgl*d98Xk-*^deAzex(qWf zWFx0U!dC_`Ft@HAxbW3kF?O+0Ql)hu*8M?OsB^`ypChhXkZuoMO!MO?vgWB&8&BPq zqT%WrL+LKzZQ;x*6L7;$BwzwEiEGisL?j^KbW%5j+c;n^sZpIYjO?C0`j zaTcSf(_9c_F8tAPlqh{qO0?3I6fQ}_ceDIz$LwumDvmM%b@hgc5~$M17C-XJyAEqk zZuZp50h62@(xhuA%;sV3UW2gYA&GL_NQE548_7Q{;oEO-9X*H^hhOM24QiLH;)4_| z@%VO`QO7OhqJFM-+1SoC>9BVx{i0X)+XB*CnGG*8&>qlYQD6BUjGyHF?S1YGJ)gE0 zqX!#UwDUXaQICrUSLGUAzh^;DiVOZtLkA15DzyDforFJ3ZDmHeZh-l{RpiZJZWy+2 zUMZD@=g>$u^?V*oWec&hx$k|LGhBNVOxfq1vbc`(#S!PyYLQQyD_E(!mN7!X5WhpF zShN;A=EU)|ufm9Aa-D~n922E+a&TF0%B#`PRzfYc04dGlk;axFWVPMP9!wVDGz1tQ zwqCri{7xJwgF=TjiawnihBDAqC$in7r?@{EsDiF!HM4j}3_5o^lNvd!wH-MB7Tv|A zALgOOIndrJR6WDhBx>leE1K}e4>d&~q>By;a{Rv>fnq1Sc4IwSnPSmZ z&VT6*ENmM6*9$CqCrQ1Pj$u|p#G)iGzvjnil2ZnoICm3+QWA~03&ffNkFrXmXDO82 zT8gkSU4bEflR>Nul7V ze$%;h6vQOIXr`#MNZ>qS>5Qw+qF^rDwRfaS-IIA}Bs^jq?jKViPk+y`0se!5QnFar zZ^3i0fowjox37_h(0~({rnzN( zgV`I7}ljBupU#|@gfwcS= z?a@4*U=FtDz?uYDtk&1m2>!q{lPq11jpe;pi3X{{{MvY^z>a3{<$?H$N`V8aEo7sw z7wchPB7J7hfG}U6b^6wEe>QqzSQDy6+=R-Bq2J0)387K zKFzl^boJt4mIja$9WN6nZO*(BahTLM^XD)~k1n=;6t|U{W?R7kO^sfyXUMic;^>E-{4ER$yhod> zR8OHxUr#Yxj?xuDWD641D(jCAqjz5YhI9`S`ByVj+pR`;3;v=5wE|8e+05dgT$D^x zfnMv8`jk-6%=QZj&f+l*1rl6Izy`h%z+oUjo9Wbu<@OjYhp|A4gu7q+>FJzJ+VK&V zZLBHa;bCixdK~lk9L8>pep<@Jjcu@sE0@+$B?e?Y2UB3=j^8yGmP!}PXROnockN?* zJsYblDhuaQ&pph`Xu*`iD(WZQm-1FEiv%<+(4raGUf)K}x}?8}Bo+uyyznHz$I<*V z#~{6~vW&=O@p)OYSw;A@P+V|?!dz>-3Gc(v{=B^0IXiA5^3ia?!F@WmTc@!|p{4bv zToL*L-5)hBc@&5Z8PFCpCO{^*=1BmJH@+5jLylL$gY}RkXY>oBs=J^f*v>sUuqCoF zdwWKGP5pSDeuxBeX$xboL+Bn+9W*5<9cVWS4v)OtqA#WS8@s}+aqU1Yj@^+# z&QtnooUZ`=*u9sCSMR4#vUTUizEU!nVr?R6XWRlbH)x!0vTKN3lz%6FDEa;ad=CFg z>l9daDgJ}=f`A38F^8tyyZoLYrriek@dQ6aS_neTf(O%4;-SGr!9<#o>jpJ2!C-D) zcKJ?!qBmIdl0=rX+!c&-b`LS3|&q#w#b zd2=&B)TMn?Ew>JhWE&3tdBo7aX9Wu+Dp!QqUhEPey$RV(x0Va?7Qxbsh&>Qq{R!wt zF7Db-)8C};R*}!j1vdj)VVsS}S6Ej5DHrl`k<+g0FgYgZV3hKud;x~&h`Bq0D zGl`6#gz(bBWz$|j3kydSHhw}Zf%`^tl&y6nP*{t$nVv~?{wF-EaL5=%MK%<*!v@b~ zIOL{Fbu@`Yw-@_|o1EDVoJDeX0&;3&{zw}qgCyhot=mG;>TH}xi`f9+8F<&z7F_D*X&5YfPd$ucnL8Hc<6fW*NRfA>KH8m68 zC6Q(Wm`8a_y){bJpkIWsbqRQAZp|Yno|oq^z4fK86{O9wxcf9($3P>xjeIUX9WpUU zU3*d_kLxPfvmrg4MX@2Qy{a>wGr-hQA*&W<VF2zQ>yWoxM4j~<~3mod&uB>!@ z*ooGh2mWDt_7DgLsv33rzxg1W)H@TZ2`njEI4QBIGS%nyH0y~jmIh>cgph<*6uxrs zuk>gT_cNuzKR5Wy{3@;g?n|8Y>q8TGfDt@dO9y>++z2^yK@~ojvr$`8mfbTWT7C{( zC1vxscteAdVlm*Z~7kw{{L>%Q3a7~eCpKKycTJXr`Ru|9Ad{kQtlVQ0Vpki{EtM+6QK)5 zGpNXP3!P=mY#FN+uZm~22#*};<12h$FjHk1a_zNd5QQcA;Qs$r-RlkbDMj@ze1n;M zB{IeouuA0>G?bnvLkgDFw`f=1$$|-Q@2zSfs}3`T?!jooodG~ZUy-kf97e| zlR96;fJh5qQjkS535w_mwW&-bS04XgfFsgB2FN;GV!LQx{ih^9P4ys+`q1RAw(}C0mzilMC&L>U-RP?r4MKOxuz=36!*2l!iywzLXyXC@1 zY#%sTM(=v-NJgJv%Gh+~nH3t(x)dlW@YTo5E-jiFqD{tVOEt2I{o?xBwF(xLo&e(l zw-Z>Sl$r#`1nLh(MY>{WS}Dj?ry2|d&4$L0zmtG&vG6@0hj6ycZ22F`LW**)a<>b@ z+IxtDy^UP~6gIuDka2|>7e=U5(gp>YdrI#ock+;dU56Fc?Wi>na(pkdB8O-kr#r`d z4*kxW8NU}&9Mz$)7lw76j)tFL&mDQS)Zdnv8h!HT@-VOC`=krQxk^?-@9W7 zM`y0^F>Qgh0+eU|HhJM}4Ac0p(>-Znmj{n|TvB@o)K zRwc$1u8p%~@sRZ=?^Lx8M$u~QMp?WKuFdyr{%g$5#9Vdjd;b(X2eArZoYwE#39ng5cbZbX_bp z++da~sj$ZqwCM_%1a4hE@UNiRnN6ae3eRu3U!eh0r{W0|-B~E%y-=yS~dcEy6Qzl)p4w#i*6|kDdeI9zqxvzx@aNwF#j{Fr>Xw;AQu#0y#YZNMNb?i zL?F&VU;=Kf#yPq|YrgZORK9JxfFFR<1vUE)!Og6{t=K#&ORyZ-h(o@~o!11?NXYl| z32^&k&|y=Kw80yr*p_CoBqDc(DZu={YPGnSNmEYBA$GcB0$ehTwhe(-I2oprfX}^l z-A}XCpB&x^tCR?6for406DD+<3#yw>4P{HKe)2lID|=?K>8tkuDUbcRl9{jLD!M&3%K-GmqBUJK%4H8pK^j- zh)kiheUJ=nZYzFL@g7`c%ZT-I^-C_=_{Dprv~e#cITA%xR~g(F<&)iS%S5TM1$WTV zW`c;IAS!}w-#@&TW6tfvo{t%2-0fs-GJiqcZ0A-QKbQuH(74+7>F|1n&yh4`R=b{k z-LewiaF2Y2S12tSwt7K3l=OxY*QuJN>RSR0^HklKlMy`=%8+T zp{+5E${;sAa_ioS4eHKfbaZr-epd`%uS6J0qT)6+-91!w308%2_+!>NSW>2vI#<0(CW$?og*$1^Rkxl(Ve>vyFCBo8wDFQ8t@l_&=m38O|e2oXso*y zV~{1U{?ZP~Y8wJS1QRJ@s!-i0+5Jyolk~{<4Nv3diny*TvSskE2uJpq^G6E&2U%uT zW0!;rvRi;NM$1aC9=GmlofThZe1MCru=%5D^< z8fR3LKEyi<$wyv=vu-{zYq;ibtT;*`J+m!|ew5=VEI=(-b(D+Z(H_){gKrcCnBC~K6Jpl~#N~Od);J^aqiXyS9h^Y1SyY96?|NQKw(hA| zElQ*4xoQA&3|`O*2HKlwddIc*)D2TR%2zXyjH>D*aw(VF!zv~T^fuC0g3-68u*TDq z+=G3yWiT*IV}Ag-z^i?P26nldgnDN#xQq zio0&Y!GXqNM+fEL968iAPXpo|w#4~tb+clKiZ({~NQqLgest)hUdhC>pVu0-x|b;D z?WQO(6>|j}N$OH|$jC>pBM4V}&A=*RqM^8w&%e%s#YT@7#8Z!?;MXoD_Vwl65nFTo zE*zgMh*sI>sa1F%#_%CyAc! zA$PE`a0LUss0gWv3O4&wa{c=dmpu6`xmg=I4ef6TIBl4wl)g$I6 zoGGtPUIwQp`5Tz9|Ha@KxzOmTj8z~emlrSyFKw|6jd*gz_@>_G!i%t-oC9g3&g5YH zdBORo#Z1MU&n3^#&b*x)0-4Wy7e0D)b&j*;DT3PGxJ;{y4)?D{W8wd!EQBIOx3nqVCCNR@l8Ez40nyjxq2^GSytO$F zw0|~;&)50^#F(|Sl6)He00rCk9&?{;@Sn$Afu49QSP=pC+>1a9bU_aLXrY8hhT0dJ zv0mwqWA23JB@!5s+BbdMbKB6y#s#u~0&H3Gh*(9*#MzpLRv!bwS78M(n%G?PKo#?m z1k+9{ES;P%^VQ(g-zFAYeJEV5h(9`k#5-A=kxFT(l(EQc^SDFzScyHoNfZu=b=Hmg zkYAZVv6in#zK6VE+j=g2UyOMA^d#bOZ6Lxwi4%w6}z3WM;y@8jW4FqyU$UBjPp_(T{p-pN>h5Oj z%hla~_B7FkU1vKMfs~tbH9C*Ot?Yu|*P?W{Dlu10;z+H_+N}}n3mn)CwuV*0|cQhK?GX?|{)O{pt0+e)4Xzz+3?0fGCpgU~`-fkonyQ;k3 zV33!D0?X!%0yETPwF_i8$P>c~OdEnxR;J7!7zRJ}#|?W~+s1L}M-@U#Uw*)eMgWzy zjB?!h578xvka^#3y=uF76rG0LD1e8Ne$6X?IrAZ0XPN*}Wlsd=W!{bvue(qH8s^HO z6MD44KwM!ea4#Hx-*0@m1eZ8g zr&g&q^oTIWj4JqUUKuzH_G)a$Dii~Z<6j_vRH;ibb774?h#f4cG5ru41LqMR%sG1o zfb0Kw`jRi3_)Q)zwtRGA^ebqY7=m1mP|V{AsCnYYubbzUzr;M<3p+;Bmvl91$XbfK zkYUOr`%PKoUaU^BCpUVvzPKuF1})^zJ4hZLn}>WQAK>R2_{t0Jeik`m(C-(c)97#P z&BzlVDCa8OUfi*rho@pqF{2nbn-k1QLiLsEU7Td@lD?UsyLZp+@NMc+Im`QnNy47` ze%1swz2MqL6|D8#ed}Dkl-r387N!pZq_DIAnyd={5f6yPB3SK@?ru#QmVynqP;HJj z#mdoU{Au-PwVyeSn^LB~T;oTM{*P~}rqp7A#+$7w-W6A))UDhjQJbG5)*0t3U2FfR zjNwu?e(az^^>UVlZV8z=Qi-xGh57qUCc8$-I^R1s(iGF58_Gq5E7GlFIawrB4e zB@CnrC}Bpm&Vl$N&pHX?K)nRdc$PuilynKk*L9ISyOAlq{`jtos*SwqzbRP&DzEvh zVY6Hw@F6AS;G}O4kvRwi?@ov3W%r5>*o~Y6)_>m2n{#!msWVTCf%g{H;p1FOlRLWQ zoBpu%6d_|ou*eB6Q91c($yaTAqSGZmRzaoM>Jn#6m%E#7TXy*bi!mT=()nks~*nBx@OSR!z*Jz|+1 zucOL}`*XqNRruUa*>j2Y9tKy==kxKT+HTpVpDg@7%D{8x+>vGOGl#`{Cz%jQOAMhZ zqa?4fGc^FsDG;IxFV9aU)cXbxR=w?GtUhLi)uJc`Fo)-CU_xB-3;^uW6<%egQ;^fP)hw??@=s%}pc1 zZudCL{k94x3KC7oX+)d{i$wDr*1QC@{;#5ARIGoVuQbnh6jlULQgV0He$JbD8GmLYN;?nC z{3`n9f*iz6BCSq{;in5p)3&+BKGUZRJL2XuUoEyC0!b<-LbQk_^f$j6O~ZO5SnP;U zl#T)yvT!5^@eJ;^;fV+C1cK3QA0pgdj_#es?Gv2UhPlHWCJ6GLQV|OGPqvxp84$+$ zD(z+v#o4m%P#N>Ie>lCUQl{SL+ZYoq6ssl^5*@m@Qe(Sn=o1C!!lX5rZjkn&ui1Rd z7%)qtA#oZlyFnl6`&snE)U2t(NzK1FbmT>EaF!nh!0HkRwHPk$!kPJ&k~OlgBaTzg z&=)k@BqBPZ&!GM1tqwq=5#FCdA118%4U>5cg7=U`8N;a{+NGTe>&fT;u^m8cfqiF% zbzc69btz70*KoB$+~#H~cZk*BTg+3M0oxiviindQ-cOK?$vgR1=eg#S#tJ-h4PibG z;*FLAX`_pq^2qyb3d8=q&dDaFBE48-f(Et)%2p3C`!u!iW}+<8Myos2#nbn3K`tZL z)L$OIdi2F#+F+UOR1ZOGaN)Z5%}o}?{|wmv_7sI{R52r7S`D$6O-;)w5lV1IdY@~Y zLW=TL{AEk{x16wGOKDaBXQzrLPHvnn+v$>#!r#iX??asit_TvjnuGi06KL4V;*|TL zqw}piflB?7;F3QpdNhHCr>hYeQ{9z^QCykR5=ER$WVjL4=|G8TU7{s|h1TwtHvo!s=pT)vkOpC1r$9>Po#*IetrMC?Wr@n;0_i&?6K*72N-)$;R zp}4tvY5XUD+Pu&HQmpqtk(t?_LvN-aayaTa&>b^=@LO=K>zmSuAmjx<;9p{nH z`9e95kn~0xZA0~1Jp*)n#-|`rMhnSK2qifr_v4wuK@PR{iRgFC>E|eXX%$Zw1k2CF zAWqpTIhjFN%_SkfgvPlF>9s9iRqJjRBFf>4*{a+q8G2Mq(9#1irymczI0llH)^^%w zc(g^8d*!H@^)gUg8Ugl;pgjk8>5fN4EsjH|N!;+?jKc zn(d1BbJbzLwxls7GiS=&;D-Pi} zuk_GEeNlAMS-)XH7H4nO2T22jf9iWSnG}%)uHmY_aLgh{=9t=Eg%Te75bn)-CUF@k z1;xsr%F<|r6w<2fxhF@oc~uaGrL6FhK1w{;wG&JfMY^&?4GBp)$nvp9_EeE~+KiKX zR+Yd+E9y7$n1r{Y9|E|`#T%D7K)0VEH#|r~+%5DOE~pEvbc+Wpu*z}NSJq~k`X7@v z()0;Kc5MF~TfP9F_220B;aSVkpU=Bs5CCQAT}}xIqrIaZ>t<7};5FcAY40F`i@Uaj z=ygvn80k|kk*xmI=dS92$hJyyCK2hpGC}wSdt|_weZ`Gkcat^bWkd01EXbQ6`}BU{ z{Ecv@QeXD)Hi3#H=84@gQlawO5|SmTBul%_^X$$z)84Xo7?2()UHPm`v*!F07IRAd z)z^6tGBWxxpMtK32S=`GtJrk_X@Si=Y+aqWn>=%8zg`j`7{m zmMFwi7RpG{<^CGK%?NTsH0xdcfq8G#TGeuzyALRkfMX7xSLwi9!Rc!aeTsLD1>M#7A&oa%%O$B#M-* zUh;TCu!Q_Xo+;BvZ?oiI{GaSuODrb8is|7S)I*0KzwpuDf?wEPE40iT-I`AeUFef> z2W;8%XRfE6M8SSCKPQ0+3sRX5>ayW&tqv0QcDk86ULc zlqr#PPfP5JOnrgsMLDTslGxXZc@hX!prU&GQj9GTb{)^giN~C&qC{0lO}kKl`L%iEkC_#YpL$q=Z=34!!pzx0S}#nfH`Vyj zc-Z3{cYqtGyS(yq_SoUb#N3<(bN$TcV7U8fb@Y0^4GFoDG1IN<^y5yCp!wJomk4wx zi?XfdjqLQCTrD%r!mEZ4%HovV>WqOtv$RuiP_J1vQy?u3U!w2-4PpuFf(2E_IR*mP zE*UoDg+bBj>z^kH3Ht+w5^hDoF-nmIf( z$3?(uO<&N(eD3sHWPnJ?W_+juIG&2mZn5Z`rS=sCNqmHP)ilL-Vxs8S-5bYhjL=Pp z)!XgNKOCo`$!T*Q`a$MOje`{c>c&lMQQy94g^G$y6i^-kB9V z!EaeK(zOhr2pOX_UUpPiYqnnJaC8KH?}#)LAg>mX{Tb>$!xdXp7XLAO8~?||B7X?G zx;&8PK)}7=_L^+yAbiXew21eWX@aw|iYi^o(9vh z)5h5qfEhlyE9H|aFQ|cKe@60SreO28GvAw zu>jvJXF(0&))~t=hVrqfuFDnjkNcT}zmQaKH3)QKU=rUwTxsA+F2Mj|AYkV$%Uw zs&V%*kJi>X?}YWc?V7x4Umctg>b@;j2wb+-(|{-b8F<+fgalXnK88a~=nnK-bh6Khed3DRRJ5#)_?*TbQP<)x9qFv2E!~XoSWOGJucK{wzx6`HsU+Mpp zmK+*w9yH+~CHS#TOWUA_a7vm-bXNOn>VxFv=B^H}0+a+^p|!Q**H#0Y(C?9_K`PPJ zP5*GSS=P-}XLK6t2@d973ogIgdQS<}3+Dy)jfq^C;CMHJlj2y!REMflnhVRh4eR2G zZqd2)LAn-zNIDSM=RWdN;*&3B8E19GApvY0>6PHloz1kOXe*@b zDZ2nYWJ51OWKRZ&`19fxvvv1@;gFQ=!`YGoSEIg4is%vC#A{1`F`1Xmo!_N~+8I?H zOmnKZF{X0JDUG6jU9FW7MT#t*k?KIFwdI)NS-kb_h7AK+z3{xcmD8%>#wwsTRiTul zgxS7#KK-fgiBXWuM(X*J*%`nMhA-#ZR)(YY+UK1nE7Hy8QuYQPgX_VQ0VWHaPu$}l zQN{d^jJg49#%Y0vn{!;DNFBek!r7Q=W!&e7`fi<9dQd35WY?zf->v+c8odKwdGr$d z+d(cl>Dj}s@D|sIL$>?h#i!=(D8hW^UmA%9MeaDb@_mu$V`99sV)ZwK7DkJR}PA(*m!{F20Fk^RMZbkvuV@)F~eI(Mx zx?JDqPNu~dBnu8?(`a$v9?NXyq@7BwKYm0vz3Y}lmMX53V(0@qsN;UV5693Pko;Ft>iM}1AIP$OW$Kir5uG)V*90sa~ z!9b6qw(#7cRYJ4~cF)n_m~qTYRfDJa%XW4AY|>2kgq>_~vm=c%9J>8-{|KYsZ(|Fk zgrJV7Vuo4fFXSSy$$qO%<3`7ok%7hREXIFhy|*boZg-3SNfnVwolh2|fF};zr`-wS za2qAC#EY3?+Lpy*FoHd(O)?Wz1V>Oedc(|K;(a$$hP0@B9|{iJAk$;pMgs&tY4N6* zQ+LcaxWI+p1$azmRJJ&8IL3=^GbL=}>`tW0o^@2xM8Ym~yWb>Vn?#Ns5GP?zAXtrJ zKSVwtcCPL9IIcZL4?X-blrc)l+9*}(d#Hha8-bg`zU1&%cH9re;*1X$;`V#)<()PR zmTpm}VU)s%!!Ee#{!YutX!8Mpu1UaFFhI@)bgw_H1hu1D@@_8Dpp88v? z!g=`9i`brK|ClX-4lw1s5=GjUnPU8@Az|fc_B?wZ!A|1qRjJ4_G~HF{3p34DKc;-W zhL*&V6MhM;=*Ubjd-&=n$?u4h>#ae zr0G%Q}n{4%Cp5CW`-wC4yo|NXMG0*-QAQ z8pj6mdD~+sobKHNBk%Gn@;9x8%SJA%hlwlwk4HtpiTrnBHk&NU-M#UFY_thAUsT|q z95YASou*9)EkAwn4e)zd)jKzvu5wX9J)J32hCZ62K(2o2`;}AO)#9aB;Zc+36rj#g zwg(PN-jinuUv}^#uM&SEENP82WiR@OuJ7!#jmyV2?xGMs{VlJ!~S_PTag#2b(%eLe`AmSR@*`*{< z97EA*(B+B(@vqof5UM6_->)nT6*q1$Ahngi(8G|LXlK%zy|n`I&DY3pzQ*hE*<6f+ zuzS<4Tb@oZfkC8@D`d!;jk}*W{)9A!J*Ay4EE5IBGN-aj2Z@Lb1$$($4FwQ%`RFmg zurVvS4l+UUKsmBw-NRv|$Wxe+`h2rYv{-*Pv}FK9M+jY!wzJq4@Z|Xw#DX5gV8kI8 zB^*BP&@v3ak#zgvZpupsfK+G?e`m=%A_|8iRg8Y_uymzvJ*F6jx{J2k%uKu#I3P5- zP#hPwM1&#Nrb5COKC9LfGA6ew!P3@6vQiC{L`}Rw{37a}hf0Sc%=`ch6swQNVW;Eb z-~@4iWJ10*@uFB7#3#LBZ4ODd-?<>Rj53_w$F%j_6R>Xt=8jBsGVa}hT2%u<_!3QW zw|yTb_#62$ZvJwgvW$b47797K6k%0u)887jZFgWaUZu=-%eTahKy=|rx^7{Q@om+N zTqDuWen{W$f>Got&oub{dcI;tKH9UL<4v-BMtHYEDhY{m5|(P7-)}ubjtW+28rj>A zO`2~@4d9oJlz@;&v0ll-1;$wVvJ^TamwoWhgIN8!EYCc&Ge*z3sMb*P%3*>+Bd-2P z$WpiTsEi}}0MIH{-V?4b~Cu3Tf@u4cVUKbn*>id$NUCCj|2hFaRv{M}8S|$7n1mkN`Kg zurVBKp>zIG6gAjP1=3mAw#ds(*LtEF`)h62%m245uRz?*XLTIg(F_Y)BXnznTD+{3{#V`wvKWlJs-utv8jdf~QSif>E_cyrtw75!9>l^y&ZF{-ObrNh7;r?v2PX$F2E)VP2}%^5;R!UXXzq=XrY4@xKxT3uR?^ zMKI#AVOu1I3o(J#Ug!Vk9=zVs*{OD9%sv?{Da8{yFR6Fk|a`M&vigs zOMji~ks#D!zTcLE?q7q<>CwZduz%8o$%Yd%cZnt-nmQO?LLlt=7gUpA#$WUUSBSyg zs5K)Y`hwm1&!-_t2L>9F`#z_9;EqmvG3%TlI*(g%M<(?9@1y7`zgzV%bN!7(_?-4- zLRqFm|DWD1iclalDV}h-Ckzv8?x|=%Y5UqW>Otk3pV_LaA1iKgsoR~rIWfbfWNxzfH&G04!51<8>w zgf@Xt^$;`NkSy6)75|(>01PPLTxO`L#)0;<1F24NZ-{75b&3N@=TKI4JCxj^U!Am4 zm3JpQ1FISOHkJr|Kl-I+?uP2VvpAbgZSt#Kktf>Y>h*1=o|f0ESH(2mz63LxxXR6D zh${S!yBc{s{6NB0j1v->CA)-!_m9(be0D*k!!aZQ&bttw}mhNC(!?|q$Yl8Q? z1Ou1tE92(4S;^rK$^4vkMyWbUpXx>mgRd&X4J_g)^M=}SaYtZovk@lNf%+ccndw5R z*Iz!GHm(5)feCxq$VB%3l!6(iT7j1I9wgDe@(ZyQf!dG3F!5eZ1vI}q$PKltjl6`8 z|EGR*`@f5X0e?JUUIEM#d`cq>wnGO!qK7&c*t!lr+qZ8p0M zV86TimEl{K5I4OaU0O12N7)9nS)GYvU+f(zZ>pot&uqpyokm)rg48(;c(@e1hlqzluqfGSo8yi!tXMu$z3%Awk6Z_k=0wt^km($y$!La``4=@ug^!kBDM6=QjC?-99Xj25VqVaC< zq3cvik!V?;yJm&?`j94f6U#9O7y6QZ#aCe-1;lrWs2hie0$Kg)bt&RBr?+}_ccC%p z>Cjcqo>65%AnwrpkvSIt9)YP|zI|c6pvk`2S0_SHdTVi&NV8wuVcuk){}I1~_+GN+ zq=ofG3HX%~&x1LwC6cvHdYwmM8O%RrH}F-8142)k5i_W)a8@XJq+FIV)2pGQASXd? zQ21j}WK|0MDgn%NNNCptpq7m|R;O2nVuHmKrO|7B{2c;gbgbP%(-xAxDT&O{$?jb- z&MCoL@>5}9l8we7lK18uI0`DgxnX=yWU?|u3ZjkX?95CQE#7XDS4fm%H1Z~Fj0wIO zK|gq4t!Y4*Y_MP&0bj<7ysdNs7aBd|eIQv~1vO{IF>gr7z19Nq3Z7+g!8!L*gjZ_E zAHmlJ>1$&b7{o1O$8a}z3)Vu}e)uG*&r)nxYOm#dQZxOn4iz%({To+K*FlXgXIk&K z|K(nNexnSR*co4LCBvQ$K|^DqBO|BT+f046MqI=Jrd)J^mmd}|U4`vyzR8hy;b?wN zB*U+)vnaFD>r!IAP7&p&-yQPbobo$nuK+_nRMs|Kr@hU-5f&233ZiYJgVYI??f=K$ zi`mCJ-^Iz39kp%h^)2S#I*TcIJ4b%AtJf~we-o2dpjf}y*<`Np)X;&%Bqp-=gS87t zgWk#%<+nho)Cl&}pgrq1deaj5xH1G)<{CE_gv0TtkKXO3f|*+{sXs_`jHR;@52;TP zqf|8lcMj7qJT~$|oaWDgl`|_`wSA}RQU%r+n)@@+^6|WoyoG6Mk1A!LmIUMb3=e1e z)(l)Evg!u^FTS3{uYA6Qdd^Jiv=uCF7VcmbFU$LZsV>I)(qV9Z7f%?~LJC>v1!m=A zBt-B31$HB3Hw;(x>46i8h*pCx>x+5?02F;>f$la2=3(C}h+r@_ZH4UE)CZL>ztPj} z?D&IAetJ$+0k^LSXa~t-he*8V_tcJ;%ZU6Ji@cfQjt`TUDSmCSCoKfOp*u(8d3URw zbFP_+ob(wB$z0Dp*ez<1QXvi)!(>)6{=1#!#~%kW$$E%8Av&4BZOkL|l`cA`UrPRy zE@q=7Be?9i)4BtH^_Iis=v*uGI$ zpa-BY^EMN8_FZM9bXGLXP>mNDXv%JP91(?T?U-($Cu#J2-;bes?nE!u%i9(Ke$C7K zGc4sjeL47p?cPI79S&;{GP1e|8lOB1ks5lbICm~9?>>WXq;@L%fCLdcbAB9j+S-kOd4HY@8>m}Z{ZI*PR&#VDs3&I)s(K3DfzB(7F933?T5 ziAAD5seAEb@mBF$H|gV54Av&;*AW?q%L{XLS6Y7CXbaqEKp0RNuHKw|U&>6$E@{fMkGE z0GQm#i5>?ao~g+bEg3H;Oj;!$emvN&1fh}M{~rLL$O&$c;QAe|c?Y4OBc7vn`j znI&denn5rd2-U>ZzutC-&j9oUv^5h#dEw+kj=N$HFrXIyXnuj0+}7Y zGby&S(4EjlkW$?5^(4yvH3;L`F8w4qg zM{65tXxg1j5#IVHIJgQy@|ftUCw-S{P>L%vKE}^jN49$@f?wAen>7d zxf#vzHQj>`Bw3CMQ1xfm$``o=8Z&{ag+K%oYAFA{B$JH3?j=8p^p$byP(G);n|~!? zRN5s@?G{(5d0!U#n(nK*{m59?K4gFYxi#YS?)r<_k_MVr z-ZFl+#Lr0SsG3r#s-~%R#Aq?9$K{&$!gIR29(exd z_4zZUk{}(ER6YuQc0Xdm3YFRiAhV06?qwhK%d1s7utQji4KCSf;Z&~AjtQBAEd}sT zPz>61G%|`xFS5Txndd zJD7=jo()684W@!MtUW%a8^%O@@WwPn_Q%*CWKr0rK50r(Bk@#^z_X6*)r3>s&!vuh zwx=MUs3ex^&AQCzx$B#mSMSn=WHt-*#V)D18jO3aHF4qn%0+XRv}wUMH78BH9f!G8 zOZ)}cnLo!RMcYfmLLOmkqv`< za>Q6+rTMBixMg`kK$ihnQzdK=n0tnO-U-Z$bd?0~NOVBhs#=H3j|OttTbvM4k``Q=J2M0BPIZ4xRSgiBy%-{}ORgvZFE@OL(3sR_5W+C4)yD2Y zQDCq{$T~JSux)_}+D9YBMDJf53;Nf31gXxujl#%Y7UhsY8suVMk=!|DCpOc_VEm#I zgnv$)aKIT*`k#&i^Mw$4e%F3CnXkA8TFdt5VOs&iCgte3h`wm$v@=DUb?bC)sbwpo z8TZZw=w{MhL+hbbA-`V3+mOt(`&QXJ*xdbBx1>T!+M@%IS8*?yyzsO$j)v3>2opnf zoh1`uNlM8!|0?MZwEeELtMShyUEiaI)XhhQ;SU#C@ zME+kXY4DZr0K)xcK z3aA#3_JuAX>)YvUf@cp^)A0|8-jPDeMYAaKoEk^f)w~c}amQN5?}l#gI_U$Id!f5^ z?OM*e5w0_tHv|ON*Y%5utB3<_hrLRNciRk6A*mNJk28hx_I2Id+$T4b$tt!QC6KIX zu>AaMj-kf=#5Bl>oE>#Lmxh_klJiA0LcJ6;Mme;narUg#$kPk!{gd7Uhb0I$ZjbAQ zFr~a!&rY(IVT)OHb>`!HU}NG*oBtXB)m15d@xn)0x=SVHNaK|i_FZ7j(H@<-h)zpb zOyXX3h4=12mC3{=7FNK}ejk^0`F?i}@SIfI6^fAEi6fzq(}3ZVNsu5=l#g z%lRgVw6#bpC*=;+;cS1Px>o{R$=@Ixc3Nv_K2<*s=lc8igMeH{U@#CKta|&;g}|2` z53foL&`*~|z0$VXGu%-tPIlov^V*9xU93HDu0#{^#LidWG&HTwqo>iG0Y0AdUUT;E z!P)6_N(3nqcIU+*l?U5ut@k?^R1g7EC8s&C8H6~x&5i9N#<_vuw)6z2l0e^agLIB> zw!(X&Q0YGn%4JwgXwL=+o(MCNbF8zxhMHbCs}326UbXC3}|4h80w=LsPVzj{@N>LdjC4UoorE?s~BAF zzRF44FNYiFqeGKPxMUrMp9XTYFAM-{AnIUEQ_Btp*tmOKn%dmpY+3F_^0(&>-B#p*>|h@K88AP`#C+)$ zu1>!>o}A77-&nYy5E@ptG@O8oj8p7a5zbMrx`xReR%MOvYd5INJX|*`orw28P}(xy z$dG_hKpqQ*@L^{ymuMsmBJ=ZemM}VI*ibiose|8=l~G?Y1;qLMRx2E+CKY09@%12* zf{ETa$8>5ESxgec)`aRdyiX9nYtd@6hCu`-_x4^5-*e3|z<{MfrCqs1Kfs8~B28

CeBO{cL9K0U2U71$%JjLTthZSVgk@DNV+Mu3$+OMuB!zjuB z5$NeN0Z>Qjb`6)Gw0a9D^<1U`?Jq+S+X%|Kqk6{(N1@w_w2>04D;$DdG!f&D8}#h9 z0B|MVF5Ek|s0AUw`mp%y{tAi3qbRTAF(S}4Xp~WG8Lx-oKX+~D@l{h*u8xAOIi$4h zP;D$W?~7a4S1Osc+QW5;iTC{L?~9v!lUFIqwD~JDXGefjS6`8r|Mazxh4rN>@tGWH z{FSTLj^d|qMIPid-f&08^_aD?V3vyt410WofS-c(%w1+LoV?TV?2e^!XmGyT>O`rB#&RYOdb4HBf?{`4 zsxRg}*RtI|I4+oLWzESnwIN0}Ojz^+YpF)AgfViO;yt?KRyXOM7J*yv)9Po&OCGW? z7&Pn$2O>YJXh}MUrF6H=T{DN9PKx>hgGtLt?{=z-jXd2bXT!uh5DR7dmlUJx&}#7L z+u^s$cc`|n^rb1hbNn_eiM1m$xsE(zqBDL|#eW7~!yY*z`VJdfVX54zcg8pV1<% zI6*C3JXRD(F_7;OZ!W^o?XT{#o_KL^A=L%6^Rwqy2p1B z=rj00W1OW9niDg@W#!G--*H^k<6y6r!K`xa2+!tJ*nens=S6~o#+4{54P~t#sh0zr zg^j>H$-}}q0MytzMI_f|48`=RQ(R($-USH>qoH(h(Dij{rS}z&o#N>Fh~H})jKAjs z`Uz|B<(_f>9AaTJee2}E^zUmXrN)LdI=M6y2SfH{JKh})e=ghm@MGhreWy~OK(NVC zaU*r3wo*k6`s!xDuBF3j z`cIpDgnnd4UWt=i#2n}Ngih9yAX-Yd?jsLvZ|WEdnnrevzP0$luj<>2)7loILOCEz zgg>hD5qs{3Hwo zs9RSc|0^s=2`}+7xWXi)-SmC(x3Dmt2y4@`NnKV9zK1I7Lsz^)Se4~R?g1CB?LGl?R)n#=vr|I2< z%|u-7F_=cKq7Fp+i)hkgofyJlnMbr8*GHSGtEu9ZS*I3mN>iG(cgJCZu%dr*Je|Po z&R<+mjWw)b1KcO8ozD;i5D_N8N37P|3}_ZJqRv+y<>~iITOvDMM9)nd$auP?5%cdVSWa`Y^$D&W8kB3e6&-f3KS70y+Lr`Yeo=a-%y!OIE}uL*W5ukEmZ+=u z*lUM!$rrh@vs^@=3wSm6^urUZ;LR4DFp&Ra@Lc=O(-jm^imGH6pwi}**<50{;5RE= zWj}rQbg~~Sh!GsH&f-#`O%9eTa@Qa3J!w>9f(I0L6e96$fYJ^mkQ(kE1#lD-d3wb2 z6LcG=DNBXoFEPPWhR`*JF_@h=h{$d5KD!GbAUpsRsRIz(zZ(lxzMsWg;@SFz9|!cD zIws`0X{k^@_Ifm6r_UIKO6qY-lf&X3Yjoal~2dn(Y#%YVM7r!?!YPqz2ZvvzZjQlEo`LtUtK!co9$g81( zJ-vd3rHI=Oi;-??EE3{Le`gp>y-Kily??*D(~0M1V8AlwB7EUq zZBWM>;vy-1;KF?dzNN!)4$XQQiodBZWRqsc!}zD6Gg07ktqb>Rf4b59_s;aall$1i z-5Zge7ReSjPf0&|%_dVKjWTIh#3f!{lyATF5jBJJiEz+)FZPT&8B*|x{F~IFn4iIV zR&M@o1s~6`w{{&29Fqi;`Jru}>@A4`c{zSGKPdQaoI}5YP&Tis z9X_C`Sbb=1cR*^lf8Xz6)4qxo@)h%?j(Okc4GU2!Li=pA^|8oGmvf+;!oq#!w3g66 zdT#uOrbM6ls?WA99M4gTx9XXyrq3h4$UFUI;?pd>`hCBL3K1tc1)}6i-T`s*|9?7k zqmx1WbUlu#l%$xNhHgQWW?jiLhN#(o_Cp*irE%|1$3$pF%{*7fhutBSjb zXmYOSh3*RA}Jx{1d%30|r;QZu{h?an+~Q>h)o5<4e`gU`+l020drj0g0!Cj7e6GYCipv z;z9!bQP;5)ttSh{%Wm}uY*sX=vIikpC`+@Yb|436=00_Zx-CF+JUGxh7`nZ$w?r$w zRZfz2Tg-nF)i-_QX=Td#27VoAUrKovnam{fI_ndYBNlpXmx5@Taj@%H zva%}r+tMyDEYPTzwECSS`F^!QREt;VA(;&{V?))}o>p;*Q!Bd2?QKk|)|4JYu96B1 z^vuo|IY_W;#b0?IwGo03QtqC*R|=-a`<20sN;oV)jGZjP%;f-u6vXYLyhO~7C=`nc zmv;h*Q|f79N)SY;dQe0>sGZUDxfX>jSa?;3t^ z&O~S;4+?7}PgZxLC281l7Vsav0uRb*>~hwi=TAR;TC02K7T~S^fNpYn(gVTNmy*%$ zwnu>B+m`|=joUQ|MPL0XlYY)8ky+QKpK=oT-Jv7-^`o7qL0U*Pw-h8o+d`UZz2ta? zwL6LBh_v$TXdv}bP4=V0EFe65i|)^L?l(0X^*bKEA3{R(Dln=iR3vC6tLos<_&E_~TMdlbJlN-irT8lzgpc&9u4?+m#YFbA=? zMvO939Cv1_dg0-_v1`Bc!~Wb_Pp;%6wdrPOSF?RHQ9L9^y_a8fb^fMBi)S#aWk@S0eVp;_{axWtBerbKqe`eYA*P8WWNV^Nop3vg6SAQ@ zr4ArPke3p^Lt1ZETI%##(;YJt3D&(^X}>hjoj<~(s z%x3}~vFEg;Yf)vT_o07-m1VPz@s;JDY)F{8TLf#2s z-NJQ}D?=zQzfscc%d^UG%4&*l*@+nMqH)_d^jI4(YAi_ckfoda{4XSk{wZ0AKp7x@_DwJO#K9;IVx$nL7FZP*nFz6=f0w; zBr@a1bW_g9b{Wtg*YA+HX`$)DD|jwc{-uHh<(9(;AT=TtPTjAGkUK0As;La2r7{@h zgtf<2Uf-AuMgl-&1ljnv0xDg3DC%>iTrUI35JG4-y$;pbBF?uHJSoAsc_jNfNQIH} znPweChqZR&VG@-q-oyfp;1Q=Cg6t{?&}*Y&J2%u0GnKVH`t&HyHpw#~IUH~JMm-FG z8QK5OQ;5+Oi1qYG1>!FWn`?xea-8LYVb>r2hl=B8>P{mefsyx*}W*;5pZiJ=HLhA6;(9#R&fN+ik zp6N7-EFH|55_Rg`-Gu4+*9l8t>0&vUxvR&=m0NLx1a13F2rYmxK#_Sr*sanEL^8zU zT*}2W+=3<~muvc7El!v3_11?gEFhi1tRy<{Ay1GTU`L9}qPo$}*kP-Eghu@57k3FQ zqe6HEMn|WDTgm~9%pg&b7XjPuHxgH?E~AKF`lGz(?yTUm+Rk>__2R|~o~p0{Jsg@? z2S?nkq6XbaIrynY#PGWJVyy{tGw1K*@;zvPUNbsFJWEHBCHN8>K79h)SoD5E8{bR) zCw_zVlXR`*;jR&cwNd|;0Sg(f^ikS>Tes#zeJgjevyU2GEU+<6UuVE4o-s<{`@m|9 z@Lx~0SY7T0vYd~M6=?0M7$jeeB4$FS5-aM`( z524_H{--hDBHql1NqZiygxZWo-wNHC$rpUTioOg|MH*WO^#!&~@^q;q(h;5!om`(O zbdt-#s;4b(GRTq2xgblGxH|*ap2fRQU5UA*lzuO0F|Nh$#}Ef|Su}niome&h`=>aK zSdrMM5a2Sm`U=Z0^YL!AY}t}m%zB4Ee@ZkfRbL&T82j8h!ue@BJH!*}aQ|@_wD2#| z4OTiYKSok;F0B29MJB&`Is>vRxPGM!zMR%^QsQsnAf5Voezg$?iQV9RG2$;cjAe!T z>~Q4$+>9?xBTBPaX~}CJ{}Cd$R@)^d2YOv}IX^|*8&Egz8|oAfF!96ST|%_&t=58%LR>5ye4XPtMn?HElW=*`JYe+`TZ3h-p#*wI52i#E4Jj?RRt*pQU#&S zhU*(i?`$J5UBCS~(D#c3Q++~X)Wn?tRVvdT*s)JxhW>M zin6fFNuBHbf}FXv7YeX&TB(bgjJxkxjbg+WJUMUqR$H)baVM+#YsWKA$VVoMYQs>G z2L=Dpj`57wh<=B_<0IX5=c6UNMIPFaoKY^1Ed@3HzbUn(OBsusA36mxA2sRY^IR1x zfp`#@$St@W$s`IbS1^Nm>9gvx3W%zC zHnJx0=*qTi#oNN8ZlaH1Yll+uhhmZLFP{#R#z1R~<#KsW&)M>Sq%al_YWx9MT zC}kVc!Y+oQ4^dIzM{TfecrW?(H$|Q&XtGD>>tQlx1=YtR?EDt53 zW{TAjxchucu-R#CI*~I;Mvcp^fv!7qJT%pbF*2FREev&rau&KgqoWVc&=v8;3ghB? z7q+tQE!Gup+~81lYUBaM%(cTR?I{^hO_@USZ4}18#p!p$Kx=f}d$r;-8H8Mwj6fY# z1XoO%_dddJ0m3&P%y?c!9;=N$(!gB--QrT~!h@Am%i-4@dk)@`*wr1rNQmk1RqCc- z?VY*N#uc>DWU9knd^qJHRa~=H$D7Tad?j%hH6^!=8p6 zIdTa%-$kqgA?^M)3Fs8*nso$qic~*!0UR&#sLPV+iOWX*ZNcXM~f&#NQ?ge zy&?XXXL@PY#^1<{#Ylh9FXM;uRLe5>O(EE(1nu2~CSf;=Z=jW6`jld^%I^1U3cDBf zax2TAvf-W5kz-^$4N5U`|ER)F2<4eWrkI1+kS!Y}Ivb%%HYxYJXo063ZT zLoG*?>9Kogk!zW3gfx8^i}bhZZ4#K>Rsjtnu3oa~J!{B~mm4KstFV`YH-`u8ZL5Mx z{uDjnOiZ|$Q>0umsC$ig8)-qf!X?|zPZSKQ`kLq;T;b?*w2zyfiXrcChFY0Q-9W%q z2{!PVzYjQrMj@|Z+Wlp$(^TS~&ug%TaG1*f&M$F|%M~Q2t=@9<_JH_9I6s*AR3tX@2&wW?CED2=Ov^K1pw*S!J_h&~;`}ys zp4QIbN%md=W%eZ4ylCjba8cdOr`qTAjtPyf6F2KJvu&lYt>!Y(?l22jvL)FJ-(j+f z_vd_r2HdUCzla(r-~Hrg#X!~fth-(H5e!t4XW6?bna{7tUG-HYYUhcl2M?(|qM%V^ zsyHQ7=-3qMQ(bA6yhtKLNn2(?x^uNdQOcv>I#O5f3x-S$B)jKnrpQkJ432&QRtpL+ zA#0KQx||Xo&Zi}9F+2MTwhNnwAqIKHvm|`Jl)klfi)s1@`?`BQ>v?&QzVmn!HqxkV=PBObr zJ@Ckh0@rugWVs-gA;R;hC&Y{Yq0S^-VGt$%iQ^E^;m50Hc!-`R(Zkv*yWH4L-otTX z9$)48CNuEA$sa?r5fE@xZ`>01CA=~nsRJ?eqoUeLr{X5fCR0UZz&wS97;OF0U8KHwyp6yy zn_1ia&E^)o!v0|^k9o}EO*+eZZlS?aiI0(aOes7D;iB8%D5syy1gdaUeG!G3`1lji zH{Dl4QM(DZAoKvI*QnYGE~^XpK}YvT>H0vu8g*kz{$>`nk3l8ys^M@S0PabJEf6P3 zRkH|^?KvvAQg{>)950Gflny(WU`mWv(dnf9iw#qi|NXiZw_!3mDv7+JD7yb!uE9Rh z2I4q#m#Scjw3hLfqxfva){asKbJO<@KuRV6FNkgNXBjBgvsV>hCJ}k5ocRz_pExXF~8YHnWdY z`}!?RK?}9moZWea@En!@Vma{$u#nj;L2vdo<+3mUPoUrmt3VkljV0J~yUvFuTmp87 zHGP&nD2bj$nZ>dG4dKjVYs*AACEyVMok^c!SOh%%0tv;rpq*aawAoy)AwWv%N|c>K zd~VRq;ZNiIGWDT<4qNS_4MrB(&Byr^u2;HH>ah5%!FZfVsJ6H1gQktNZac_IKBTfz zG#&4&I2(QZ#)vgOLxv&%ri*$<$90m22i1a{3Wv4Kw|sqKtvQhWwPG2VYfFiQoXM_* zB`&VdQ&Q&nSW4royNB_Y5n#QSjCk(?{}vx@wSm6+Sale>p!=+TOP+oA)~I-XbztjT z1vWa!x29l>Qjs2w413rc>C{KgY5{=CC<2yPKJ5vRZd@$`4jpflzooeA>~=M<#BRrr zODBS#cTPuGv%6!uFJouNieDFJfqW=$LXM3kp_d*M+yTRHIbFd;6vWQ(l!|1$>#Q~S zpedBbEW8g|p_9HXQpT!^ES@5xnXm|)V9Vk;M!MYP+B9QI(>*;yH@z5g6DM~geR;SK z#PVMFHbFg8)Q>xD5-DS2?}7K5RhPnsL5R*8EeBFb%Ne9j5;s#OFx%|2QDH|x1nJ{X zW@P{bwlL(TeYqyJ!|VcmdC`_q<7~7j^CkRE;`WStbOhf~0#C|9)GjpY1Y7a^9=qfk zaZK+_Kkq}Umsf#A7)%%!DUJ$Wf)jsYD_U@d9%py6Pj)&@s|%^b$tvS~XNzsK>ha!B zNYgOt`eu+Npw$(A1rY$tpV@S&S7s8{80RyYxVTNk2kYi(*LN&@?Fi8YFh6KsP!bvN7TZ#W^@~< z>Ouv5k9rO6VsAyE;Ovtw5-r57_avk|lG(8X3=DE4K&(deWF0&20$qa--$CZD9ti8E z40`+v`nJAj_AHiCkkoyqNuKw8tIR_+n%2(l_~!&|To-@A`V?acBKB;lsdHlf5IVH> znUJ(H1F)1_%RV_ZwKypuA(b@PyL5@$Q#N?7o#5tSK2s@Po{zARHaA}xphfJE8^+n2G*jyTMzc?r zcL*YV*LxrXBNhHY>uQTVN$c_As5+Y>4M^Cip`EP;rgAi!;2dQ*kmxBpTQ$&`)E5cPqEMU#WlxF(*LZ5)`-Kr&-*N021`;oowlYUOi<;;q z&S58vtVQ?M9;-F+t%*xqz0&nEhP0bRU72XWzET1F-%FXVLn%`ynk~A-2=U!BlcoAE zFb$f`QC0xP8H3*S%WcoLb)AVbEfwhqjHq}CFGAt7Z6Ck;OyupbWjhXK@vdo@kp=TI zZpxkoQb=Q~iY?o9?26&cDjyg}@G2qaYZ+mEMB1G^^Qh z+h3>wuA(@4;$_Siob<=IV0X|)3`RF-JZmM=wZ%XZ&kFd{^;895ggt7nw|Zk8$iiF4 z@?LG!#B274cv~y-xI`m)HRA1u!`_+OyTHMR+ar8}6_#Azrc;rm=LxcS3et_>Rmr8s zrZUnQQsnJw}HqRFUbba2Xo+-7D5D& zb(L1rG{KbTc8U;%$i1*i;~0HW+6g8v^oxj|y`3L)9cY*Nut2(=N&5BdFxspY_nerF z7hkg!#sG~M)~&qa0ORGX5YGe|CyR01QFS|!SK=^g3Z)60Sed9c`z5IEhHbOA7_0`B z-l5^H?GSnT_I_L&>=vIPq~O`OxtoLCnl&genq_o^=?i1QS|cM|v%0=nZ(!x8o zVca7tDQqz(bD;c_kL{?7{T&5*PA>cHNk4r<=XE zLwk1x?2)~vcD+j+8o6LVxzlRsT#0k1xC3y&1$4aJP3nlDOE;B#ayO+P6@@VjDfnB! zd=P8#4y`Gx=*0|U;;xw{xEY(xHH>5(Omuxo3M+Ede9op8z^^9&oTAu~s;imva16xL zBk-d!!BJ%@(?e{`WG2d1m=wUc(Kk6pdwYPUJ0-Fen=ta{o-y{~%GRn?CMmAh56FN# zlB>+KBr8jRxGVc6!39EY7|xs3f^$Z{jRUNd1gf%0i~$M2_7IB$G7!d@V18R|9*(S1 z!~Dd+=)md=(FRz7ZMn-vzO@PuVl$R}?4%>5n=!$N}!g~|gM$G#GF_nU$z!<~p zeMRGw?i{3kF?c($mOoR}51P8MfRkdY78MHoZXf$EnbEUCrMm>K3^P&{7ZL=hD|g_> z4a7USg>0K!rw75Kf>`re2R3ILrF{jdW8TE?L_}%m1A`N_B?kZ+=pOib6u9%`a9{9n z9*v`}BYw*x?Kj2I157zeH?Xsu7X1m^|LB~6nK&pMAp7r>ji=FLXYL-)$_G0a)5V5e zFWO^Tk^eC)xEu!hLT!1o%9ofnKB}=sIq+FCoT)?WgaWxwrkvPRqVF9z{>qk^}V z3Rf&p+V37L!Fk|dOh@_H1=@byOQASB)Q(_lE`<=Hk8u&mwwO6-Pi+IAz?~eW#|irs zCwCe@UWhWNsKpsXUR2$n-;L{9;gLWgR4g0FS;$*~Dh(?fS#W}F&fm+nhw|I< z)5?W1U4~jAKG+k1asCovAjwGeqlJJ0@_!Kydj4$ z7w#T%E{W&#l}mn$Mq9hE+i4jKL@p0gveAJx?6-A2D?R^bjJuq$*{RoUao@7D;61=i z7TSm}aPOJ|k-w{th@6_O`*ov=%Y(>ZT}|TxR&a-!J|v>7+RkSxPQI+b`bjLgaz$*lKTyIVC&>0J)Xd8@w5mchV|d}n4LBDF&hV|iaOrCDMdYTG&RrJ+a>a+MtW zOyYjTOB;0H(J&{w3E{IOF~@}?`2eGrDWUX3yx1A_7ns9b4aOWv$t$mO%WEk{!1~-= z!-U^d*(LnSw{~i^#+)~P^KW#Vvv)vZMilBZk1Y!nLI1goe|yh_-b?)yubxiTA z6Ru#-(=ovK*I$Y67Nx@4xI=>@N<$Dg`X{gOW29TJY0xY`u|=!?y96LQ5XV%B+@P*o zshUy!uxk$o7qmg#MTXouC=~+#ao2xjX{O%L>?Yk#EF^pJi(2A>R8v>BjR@9sbm;rD@AHyMMV>;AZBlF{bO^fV2VXBrj2XGTok;b&tkuP; z_mzFtO8{;hc*#zdA#~YgZ=6qvJE3?5pNvZ<{>!XCD zY_81)NxRa-qX;*^o*K@J0p>IsQ6nNt1b-!cy@Avy&6cO#UFXsP-YHt^8ENuEzw2Wz zf7ji_0B6+4;~7Eggy5na;A6fOOxqIP>kC^7i{IA*5S3li5A&<^#(lfLcbb_o(txa zPDN-i*Ky49hd)oa9|@WWsht_Nca#OP&!8sQ&mJ8f2CIEtl93!q@>>eIi_4G=JJ8)`QNu&~SoykT#L0bG&m%QaL4|8}k=(Ta%E`ZO7W4X`J*7Po7=XqG^E_zy@flWKPHL}v-X zfXARqHBCdZ*KP(L!Rf~9uVV()2rX%YJt3R8F zsPVZxkbn3pJx!B`?Xb!9dM-6cyA*bfTR_S75zQ}a?vDe$gdBd{o$&k-g7u0P^;m4R z{XJ2-;>Wkfh!(*~me?h4z>jpV$U_FlPm%+N42u{ zr>1PvbIaoWr$%vLkL}fn^-_zLmB;82mq$g8YyFSJnN>>|>;`PxPr_eP{<9I!t7_rgl7ia_a&3ezZHz9s)-NA@n~tdC+?K zY*lm&Buy8K>;45rG9I489>s0Z*aJibiwy{Dz#|B{ekM4A^1dA0{LKq6XVZq=#69hn71tnZuA_)#tI^+B;qcAJ8~6?`xFlHT z$3sY_wynQh-&BWhO4Zqbn^`fSivDA_h5ls3fw!;R=b9^$v<|)Q)j3cwb+Xh zQCbn2lmxp$81m|~nahYx-{C^S3v~0Pvql|mZ`cth=?pVaMIZgc0(CARhi7{y5;g{D zF7EUe#&PjceKK{TBDRO!hmc|FOsQfZ-28zE@$djx)Ov^!D;}1Kw@?vQO@!wQWzko+ z%DAC%T)o+ncBy*pIuC3~C=QZY-MP3^*924>$dY0is!1WIHZiJtq=P?&Z4VSsT3w=K{1u?i+a88n# z!8-jkW9yxW?vayv;=JlU)Efrdr@gQ-7cyavazL|jLa=Dd(esxs%>ZV8KBh3NW6;iY zp%5BvpI=2k;oqxqnF6_+0$12@;6TN|VX5Rs0yo7DtLPlMuHI6RbdM-_qZYf4=1Zug z6tS`rd<2TMADwOK@8AR}Ql4SC+2JmaX`pL<=28(E(js(S#sjr8XhhL%Er^B`h1@Z+ zr(o8beq%7b;nqhNw0)g$8}%dC{c+3l&K{_0P`BrAEiO{phoFnY8h9PU#Blo*WqKD{Go;#oa5kJ!E>;rfA!$h(BR(eGdT zh5oV19_^;k$3OxR8I_vKtTQdqj z5~qlEiQOJ%rl)3}Vw8)`*w0ztQq{PN|re2qb8=HH+C1CJ;C~FI;Vu9_b%pybZie|p>fpQw{yINblwC1M&ZkuuX6m+C(%3^J2 z7EV_wrs~19li5^6@P54c-<^RIoy9ST<+Jm=8@XfzghRzs?iPXJB_S`Fj4W)j!I2r= z*H91{KLy%u6j?}4d0Abjj!@8q58%N!{OPZ#w%=5H0_x_k9U!FqRX>p{dxB}u`|2pA z!O_pMoWO0PPS&4u=ibMUKc$Qt*mh%me2trv(KioD0?OhV*jMSY+-&u3i6Cgf>Rzu>4Rb|}0q zNS{Fi1;5aY&w)@=p)i+=P|8}+>es~IV6?ChXehLNq3mI7#bD!Ifa@Dnv+{6BO|(gL z_78{hSvD#EHsU2_vKp_#i)LDeQ&52Lt@8q5l2A|vDHh(_)P@r851X*C9`>@9j=GUP zgqtLwbS^tQ=-8kGtLe=tbg3nxBYujk<(bMvA7e>phKY3&2jjeWzmjqozS~+gwU8Ccjy*D#19xMT zT(0!D?KyfBBBOG39gQ}czFZzG&~ztu*i*k#a|D0hI9?=q%E{pPKphjyO_1~-57828 zbEUx7Y{9vWqN6(uX3&8-?s!rilA=pqwR_;8CP3G^U7f+T1Xeq74Xf^2FlYd&{ToGa zGII~cFVebb3HpwQO?9t%V1KxmgfPkXwstLh3RLF!Zynieeyv5t@vQ3nx}#wA=ymwH zYhUwHBCg$S@wWa!un(S!ivn5_9gQj6AdbKvpO_+Wnrf;4or8wG=<-g`D`SQ3t|}>@ zZo(Kl!`stsrC#69*?XqgwqNX|XP)sJD_2tIj?$5WwS!MD%7@^^d6}U@ysGC#gwpna zl>c^n8ZKZ__R`mKx>0VTp%F$lWF{B7`OXX6pP&KtJ5;(?QdBNeH$_p8TU9#8@V&9% z@D0d9f-h^K0(D8-sV&^~enElpU9Le5o#qM>Z#Zm~#j9S&S?X<}kYG`==$ z>}oXlk8of$IP3+Y;y=A!&MwUg7C7Qc)WFbU5hgsQb^WB=YE7~g7a8BSC#fV*QeE7k z5y%~lYO5{K)eX0AmCwS1wu$cPasU!vWUXNMaC~gyDCWs8hygN$bN(Z6{aqgM?*i$_ zTzTagQwMe>JHp41<0f{amlhOL2vzDe;N0I)N? z`Kg*A#(({@tw(;2UV%cKZS<!n;AuH5Yfx#tOBh%kr`P01^FrNB8@UB)Sg93KPM+H2&o*;H2 z_%;K9F>BxbwXPQAt8*?_27a8{({s%j?jZ3aMZNhS#iCHY${eg=YY4WQk@Rn^vzv zT>kw#1_9wU^*v=?p!6`t^F)PlEHsflyeBoc>soFOuG#F(1eP;dT{~IqiJ4Kvb!`@% z%ghCIV)!BjojpD|Y`AYtCeG(t$t%$eJWQs~yUMp^4B5&*_5mJq%)X@!UFUI>j}1de zMRm?P-eW3fm|hbt8Fw@b@H)9R$&w<))wptL*$wTREdn7{X&=ODd*MbAp%_$n6+^${ zdf1+`ytp*??RG)nMkwpJv^bu928-Wd*k$9#-!YwV9t*~TDJls9O;P=(2_lA^fO^q& zas%2sWnfwHH3^Rm>|%}B%Tr8668f1MXrdlHYaXZ-Mhk+5&;SMrEdiq!T5dzvxR~@W+GAXfr4ZdNur zNkYh-4Xn)8Bx6N}BBy+|f7F#RC1= zt>#eI^Sm7YVY6VJ8+X<;*knsm;ho@^agT=IlROol-h1}=HDu0s zaERD(o+@4M+S%BFg;Kb|Q_t5%h_ZNhIfNFr2=P1*9r#R5@0NY)n1=t4Xbq~+ZJGzX za9#hi13sc5rj~vltQI4Wrt;+p#+;>FeK@^RNR=vg-^Vtk^ zy3eNq{3y`u)g;Xeh^Uoo+Wq<3IKX zkEy)t+9uQFI9#$xB=-PsJsbIBXQyHDzibF`1yqJoKg6`ruVe{-uI&frAs<*~H>o{+ zlCWBDH`ai6LoO9&RKl5dxiaijhX~@LR6N1z)lt24GN2nYXdV5{ z?g`Jiyk!bo5`97;SBQe}fn6MkJpox}QelML091gtRQbe~>tuwUR9vmCzxE&e?H%lE z)e`>&_v-dTZPcXdZ@+o50}bh$K--5`v-K zE+yVvR}|9wL0D^JiNvI>DHQmxNEu42)E{nmz*q3~dFN13;SUNiX|pRf<(mP#IJ7X~ z`Xu~m!bz*xRt#;8NS1iG20(QCXa4kOZn9}EU&h_{WJ*>=-t%fN`I1!Bohx6Eg+ujU zRzM7V)eN$3*LHIejgoLi;0dN!H(i!|IdgdlG)>og!ux0({`;?NjXM-qff(hToF7rO z!uGW4@p{Bf3G$H4*`#FV7torp(CQoAWOBzmyJapVwFK%kN#%K;oB1OTmn==U& zT3D1(s)x*Hk7&^%Z#I1#Y@=)-B|&)+89$uNY3(PLsBCMZV_hv5llqAq^d46PL;@n& zWvWZNFX}VXrk%uePIbuUyz(WqdCW>iNIjKZ`5j724qn$=Q0#5z)c_sa)2&jW#@l%& zYW9rUgAxRKo={AG_!Z@_nkl{_e$Pq+NFaC>zN%#6BN|Lz5dRSF%W-o+|-brB*>X!5Wa~1$k_Ch6Tj9!63_IrMc)#9}hhM>f-b`tQ!yQukWT8OEz;MCJ=c~Rinf_&k%- zxwdW%gCTd0I!j;?5$Mz!;J71!`LK8iB&uA1#k8e97$j6e5faVwIRVsFTmQ~jU#Y1zmmc%nfioj2)P4UL zBY7)P#IO|u@vY;laEu;;EWfS#ZQ2%c!yeL*F6+pbf+N7{uV5{m<#nh#HGjUd!|)S; z`rn#+d>33clXu#MY_fHK3~VMvyg-b9ncf#~e@bku=%`JMuw8?BHNe%7IpC)G2~{z+ zaGkgO#H&fn8Pp?@Zg$>8DIPop;6kVtqG+gDTE$a^Oal7#f?6WeI(o5UHP4xOkf=ky zBC7E<+0(-Tp5$k!20odnKMAiSIfl0l&w1rZ1b`)blE=SZP(mWJ?9Ad}vjTZbsA9;T z#XCPK-V3Z;-Hp>KsU@{E*LH-;XOm}p_&*-8%oeulrQbm8hIDNnJkZJ4-^~xuN$qx7 z1VvfV6hxbp97QZ`3|v>1A^A4K>zl8eHyrNCIE}rhI{a$=Z`O4z;ukKFp=;RX)MRXD zsY#SkJuTkUBd!EtLnKd z!f(SPPwM)sxEg?^}r5#PFur(TgUe&EbC zi^4HVcuFB}668c1H|P6hdLtEHW(8>Q)V_;^fDf!eZC>+Z?W*BB~lgu2zp!l)L zRFwYSRHh+b^bFX1)Zg7aKyh-LHaa_Zpcy5TN5V1tL1cGO!Aco8ktMf?{omRS3PXW{ zYnNCm(qT}I+6?|b`hu9KN@2tM7(Y~eUhS(&e#x05=_$J21G@Sc@oKg+Wbg+MaVLef z;q>zicUmA3&nSU6uJRj`Tx8p@FAsOsh~qejx|rX=@$X09;0r2A?uNwmg3L+GMWeA? z{eJr~=A{CWzsY}so19UMd=kXiOK_p!rl^dtXMH0$p-Lbr<+2TyGT6sUe%@Av@6QfT z1#>z^4Nz5d8^K$Uy0g~y^lEVsT&FLIZP@X5q6xHxWayP9P zZtM@x$2#u}UdF=gqgaSb?m@-fOAHp`hAT?B!d>*~P|06Q(g+D43zxY`8V|y;Ot#ZR z#aBByEZ)#;K%^rKc5>0Etk_UZdsy;!sK+&I`9)felE|7GK>VMcSkohpqxe(MPz@!y zeyt<7977fXKB^`|m@$#m5S%+kdLBQ5DO>2o&9*4n73cG7{@43e}dtO$T7d0zbXKnzPJRdJLH(+`4 zezi3-D#r;8q&5ie6*<>XqV67n$F*~ouR{mE5l`tphqJOQW764`uF%c%=TXCc#ZWW= z!I`h1dJ%K*jHBynfTzzUMzIyI`O7q=j8gC=Tw02v&*gn=Vt%)EOO~EH6`a814wvhr z0MvDK9!1xCQzZAq4h?wQGb0qf>{>=LHy+fvC`xqba{-Q<#Kr|vH1@ZK45#AXWxlTb zT-*1=mI}p=mGoUzew-X8)H7wQKO5XyT32s2xpHJdC0iV!b5|Jj-ivXMF}X-bNc4ZX z6@x9umf6_dLqablj2odfessZ-4}8lpHMvs+>Kxek!Tx610YcAM`KZgCcN=~3=cxw(67(b(ZS4Vr)CySbD_CekKakq z-k=4Ho^${YnJ_k)HE7?}a_?5W#PSqAege3IEfRx8EOo-&WRyZ){qZ|FO`tWAqKI_l z5SGR{lVDD7m>G^j_cQO6-_1jtYTRNl2?Y72IEb zeqQ?{%RXWpcK^n_cdQ&;-2GI2aqAchl@~4~0LhF_NfwLOVX7iLv2m49P z(O=cgqAq^c7gf{0g!QJ?$Jf$A_6ag^+I?t5n%{N;e=G)W=eIT@3l4gjrX%>%$4;5( zpVeGKw~{XPi2zk=k^+u$e5fv|O74`GKJ60f2->Bj&ml|IA(fQM@wqPetaagNUU+XQ zEHcpPLv!mLotLcV|327rsgm;}wTP7%T7h17iPjWUjDW1IkUUc{QdeK@+!8Z5E|%Uv zUa#9aNu!uJ#9{IJ2o*?M!N$fWYd#CzDeZu>n-ek5Q7bHu5$sN>e3E}Fw0n2}6CBeZ?VZ*NN;iu^53*tfi6eib z>5aUB$N}_l7@S;P-oo8kS8pMl`;52FUMA#qU!^F+aERqZFF|BR56ijnZ{A5E7i>8BbI zN3iXJ6fMhIn*2*)=L-45DE%+MqV~c~dL}#nxKs~{cgd^$4<#rZ3qh~V5ZSQ z`B;64g8OS)vH&qy2l~{*o08d0Y8q=$-6407x9m49ahtI5o5Yp;685g80OtmlGPNrq ztqi0u!y&1rx1@L3);JELN{e+sTfRA~=qU>dGJ=Y?hIaGGzH`9P0iu{K3K~6m=VsQl zj`*I&um|fM>tRQaOC~Y=?W$Dy!2b-rKX^Q`>j0lAHI*D_OyYdk;g+sYm>(nqf~wN^ z7~I51ZlylEH5-bN=SJe8Ami*fUW^reZRsr4r#L>g1oH!rAWNgbXI4x(_tjlHe?HQU zIosPMbUyPm5nQrY;F^CmrleZ@9IUJn9Nmll;{{5ZHxJ^PwaoDjww|<8=!79K?mGVe zCyBJy#P;>3HhWShh*d7jvcZ=#Kk2GiDhOsy^|)6-WJ)uDSw_cM4oV{79YVhXNs0IC{od5!U)1GIEy$$JQ|&t-0Tpp)rAQ&&TAn9}rTw0gK(!fOXYKbI&xJ1`5oAo5zA z%B({*^vItb8wS=9Zf!FBF+}l7ovI0HC5HV34g&0RT4#oZZhYP((m zL}BV#K*03RfCld#C$M2wyrfYBTp ziu!W8Q#bcW=kO>ovR-d%*lp0~<*XJdp=1VCEAy~6Db7F4JB3JavCnFYGZfQAk3Aq2MGJeD*|P2bNen-o*=la)AvPWL!LQ52ZGZT)~9Oe3iI9T}V8{(i?M`C}yfm$F<;*7TYhzvyW;Yi~=bElnFkV>!s$*+N|D zkgYAz`*{ahBch%X{`eA6UT7VwLZG!ee_@_rK1E;aLQNJavCo=Cu&tBE|<8G(cALK9}VX;wXV-N2kD7`WADrp*G$Jt zA6!W1`4!tR$FEq~9{f^?vMwfuhuInQB^IXc_BVFf7|h-p-&VluQ*d8}t2F|-D_hb6 zNycz5*S>Leq(7CH`cT0Ro`$o)mwp&yqCy`rKj{x2trq*9ppWqz#neiu%_?B<#JG<+ zzF!U7sC?Xsz|>nNG?jfJo_~(3R9?R$RNuJ2?r_VE49A9&mDYs8i&@HM!(xSQOTxDH z9LT2kw=Xce6#0m_toyjaXbzp#_^j&1g8|xv+oFYcJn^_!J^CmG`94j99iW}giX||z z-QqA1A8B)z6WFS0G|?2En`m9;MVhsuW4Ll8nT>zmUJs{Ho{cM)br7cMe_Zd3Nupc- zi!N|!Mtp|&6F_;^6FI?dNDg~(StuL__7{=!i^qcpqA_mD*CZ~w_M_UXwS`N~QH;T(xrx_JfKzt)$aS?vY#|U%?${@s zrnY#_;~_AZD1u)t*34*a(wI#~haxNWU^flq5P}TOMi?ipk{z/libexec/lib/node_modules/@google/gemini-cli` + - `/opt/homebrew/opt/gemini-cli/libexec/lib/node_modules/@google/gemini-cli` + - same under `/usr/local` + - Bun/npm sibling path: + - `.../node_modules/@google/gemini-cli-core/dist/src/code_assist/oauth2.js` +- Regex extraction: + - `OAUTH_CLIENT_ID` and `OAUTH_CLIENT_SECRET` from `oauth2.js` or Homebrew bundle chunks. + +## API endpoints +- Quota: + - `POST https://cloudcode-pa.googleapis.com/v1internal:retrieveUserQuota` + - Body: `{ "project": "" }` (or `{}` if unknown) + - Header: `Authorization: Bearer ` +- Project discovery (quota project ID): + - Primary: `cloudaicompanionProject` from `loadCodeAssist`. + - Fallback: `GET https://cloudresourcemanager.googleapis.com/v1/projects` + - Picks `gen-lang-client*` or label `generative-language`. +- Tier detection: + - `POST https://cloudcode-pa.googleapis.com/v1internal:loadCodeAssist` + - Body: `{ "metadata": { "ideType": "GEMINI_CLI", "pluginType": "GEMINI" } }` +- Token refresh: + - `POST https://oauth2.googleapis.com/token` + - Form body: `client_id`, `client_secret`, `refresh_token`, `grant_type=refresh_token`. + +## Parsing + mapping +- Quota buckets: + - `remainingFraction`, `resetTime`, `modelId`. + - For each model, lowest `remainingFraction` wins. + - `percentLeft = remainingFraction * 100`. +- Reset: + - `resetTime` parsed as ISO-8601, formatted as "Resets in Xh Ym". +- UI mapping: + - Primary: Pro models (lowest percent left). + - Secondary: Flash models (lowest percent left). + +## Plan detection +- Tier from `loadCodeAssist`: + - `paidTier.name` → paid subscription label from Google, preferred whenever present + - `standard-tier` → "Paid" (fallback when `paidTier.name` is absent) + - `free-tier` + `hd` claim → "Workspace" (fallback when `paidTier.name` is absent) + - `free-tier` → "Free" + - `legacy-tier` → "Legacy" +- Email from `id_token` JWT claims. + +## Consumer-tier migration (June 2026) +- [Google stopped serving](https://developers.google.com/gemini-code-assist/docs/deprecations/code-assist-individuals) + Gemini CLI OAuth for individual, AI Pro, and Ultra accounts on 2026-06-18. Standard and Enterprise + subscriptions remain supported; paid API-key access is outside CodexBar's OAuth-backed Gemini provider. +- When quota, `loadCodeAssist`, or token-refresh responses include Google's unsupported-client + migration signal (`UNSUPPORTED_CLIENT`, `IneligibleTierError`, or Antigravity migration copy), + CodexBar surfaces `consumerTierDeprecated` with guidance to use the Antigravity provider. +- Settings shows an **Enable Antigravity provider** action only after CodexBar observes + `consumerTierDeprecated` during a Gemini refresh (typed sentinel state, not user-facing text matching). +- The action is explicit: CodexBar never automatically enables Antigravity or falls back to it. +- Ordinary Gemini login, `notLoggedIn`, and Antigravity setup errors remain unchanged. CodexBar does not + capture Terminal `gemini` OAuth output, so Terminal-only failures cannot activate the migration action. +- Workspace and education Google accounts are outside the June 2026 consumer shutdown; keep using the + Gemini provider. Antigravity remains the consumer replacement path for individual, AI Pro, and Ultra. + +## Key files +- `Sources/CodexBarCore/Providers/Gemini/GeminiStatusProbe.swift` diff --git a/docs/grok.md b/docs/grok.md new file mode 100644 index 0000000..452102b --- /dev/null +++ b/docs/grok.md @@ -0,0 +1,151 @@ +--- +summary: "Grok provider data sources: ACP JSON-RPC, grok.com billing fallback, OAuth credentials, and local session signals." +read_when: + - Debugging Grok billing/usage parsing + - Updating `grok agent stdio` JSON-RPC integration + - Adjusting `~/.grok/auth.json` credential reading +--- + +# Grok provider + +Grok uses xAI's official Grok Build CLI (`grok`, released 2026-05-14). Usage data is +fetched via the ACP JSON-RPC `x.ai/billing` extension method over `grok agent stdio` +when available, then via grok.com's billing gRPC-web endpoint using the signed-in +browser session when the CLI surface does not expose billing. + +## Data sources + fallback order + +1) **`~/.grok/auth.json` (primary; always works for SuperGrok subscribers)** + - Reads `email`, `team_id`, `first_name`/`last_name`, plan-hint (`auth_mode`) + for the identity row in the menu. +2) **`grok agent stdio` ACP JSON-RPC** (best-effort, currently disabled in grok 0.1.210) + - We spawn `grok agent stdio` and call `initialize` + `x.ai/billing` (no params). + - **Known limitation:** in grok 0.1.210 the `x.ai/billing` extension method + is only wired in the interactive TUI; the agent-stdio surface returns + `-32601 Method not found`. The provider degrades silently to identity-only + when this happens. When xAI exposes billing on the agent protocol, no + code change is required. + - One non-obvious quirk: grok's ACP parser does not unescape `\/` in method + names. `Foundation.JSONSerialization.data` defaults to escaping forward + slashes, so payloads must be re-encoded with `\/` → `/` before being + written to stdin or grok will silently drop them (12s client-side + timeout instead of the expected error response). +3) **grok.com billing gRPC-web fallback** (best-effort) + - POSTs an empty gRPC-web protobuf request to + `https://grok.com/grok_api_v2.GrokBuildBilling/GetGrokCreditsConfig`. + - Uses grok.com browser session cookies. When a non-expired + `~/.grok/auth.json` token is available, CodexBar first sends it with each + browser session, then retries that session with cookies only. + - CodexBar imports Chrome only by default to avoid unrelated browser + Keychain prompts. + - CLI/test runtime does not import browser cookies unless + `CODEXBAR_ALLOW_BROWSER_COOKIE_IMPORT=1` is set. + - `~/.grok/auth.json` is still used for identity and as a last best-effort + bearer-only probe after browser sessions fail. Expired tokens are not sent. + - Parses the returned protobuf enough to recover used percent and + reset timestamp, accepting both gRPC-web frames and the raw protobuf form + returned by some successful requests. A current billing period with an + omitted proto3 `credit_usage_percent` is treated as zero usage. This keeps + billing visible when `grok agent stdio` returns `Method not found`. +4) **Local session signals** (informational fallback) + - Walks `~/.grok/sessions///signals.json` files (last 30 days). + - Aggregates `totalTokensBeforeCompaction`, `contextTokensUsed`, `modelsUsed`, + and the most recent session timestamp. + +## OAuth credentials + +- File: `~/.grok/auth.json` (path overridable via `GROK_HOME`). +- Top-level keys are OIDC scope URLs. CodexBar prefers entries under + `https://auth.x.ai::` (SuperGrok), falling back to + `https://accounts.x.ai/sign-in` (legacy session). +- Required fields per entry: `key` (bearer token), `refresh_token`, `expires_at`, + `auth_mode`, `email`, `team_id`, `user_id`, `first_name`/`last_name`. +- Tokens are issued by `grok login` and expire after ~7 days; refresh is handled by + the CLI itself (CodexBar does not refresh; it just reads the cached credential). + +## JSON-RPC contract + +- Transport: stdin/stdout, newline-delimited JSON-RPC 2.0 (no Content-Length framing). +- `initialize` params: + ```json + { + "protocolVersion": "1", + "clientCapabilities": { + "fs": { "readTextFile": false, "writeTextFile": false }, + "terminal": false + } + } + ``` +- `x.ai/billing` result shape (all monetary values are `{ val: }`): + ```json + { + "billingCycle": { + "billingPeriodStart": "2026-05-01T00:00:00Z", + "billingPeriodEnd": "2026-06-01T00:00:00Z" + }, + "monthlyLimit": { "val": 99900 }, + "onDemandCap": { "val": 0 }, + "on_demand_enabled": false, + "disabledByConfig": false, + "usage": { + "includedUsed": { "val": 12345 }, + "onDemandUsed": { "val": 0 }, + "totalUsed": { "val": 12345 } + } + } + ``` +- Auth errors surface as JSON-RPC errors with the message + `"Authentication required to fetch billing data. Run 'grok login' to authenticate."`. +- Timeouts: 8s for `initialize`, 12s for `x.ai/billing`. CodexBar terminates the + child `grok` process on timeout to avoid leaking subprocesses. + +## Mapping to `UsageSnapshot` + +- **Primary window** = credit usage (against the subscription/included limit): + - CLI RPC: `usedPercent` = `usage.totalUsed.val / monthlyLimit.val * 100`; + `resetsAt` = `billingCycle.billingPeriodEnd`. + - grok.com fallback: `usedPercent` and `resetsAt` parsed from the gRPC-web + billing protobuf. + - The UI label for the live usage bar is dynamic: "Weekly" or "Monthly" + when `resetsAt` matches a common cycle, falling back to the registered + "Credits" label otherwise. Settings and history views continue to use + "Credits" as the stable metric name. +- **Identity**: + - `accountEmail` from credential `email`. + - `accountOrganization` from credential `team_id`. + - `loginMethod` = "SuperGrok" for OIDC, otherwise the raw `auth_mode`. + +## Local fallback (`~/.grok/sessions/`) + +Each session directory contains `signals.json` with fields like: + +```json +{ + "turnCount": 1, + "contextTokensUsed": 2968, + "contextWindowTokens": 512000, + "totalTokensBeforeCompaction": 0, + "modelsUsed": ["grok-build"], + "primaryModelId": "grok-build", + "sessionDurationSeconds": 47 +} +``` + +CodexBar aggregates these into a `GrokLocalSessionSummary` (session count, total +tokens, last session time, primary model) and exposes it for diagnostics even when +the RPC path is unavailable. + +## Status + +xAI has not exposed a Statuspage-style status feed yet. The "View Status" link +points to `https://status.x.ai`. + +## Key files + +- `Sources/CodexBarCore/Providers/Grok/GrokProviderDescriptor.swift` +- `Sources/CodexBarCore/Providers/Grok/GrokAuth.swift` +- `Sources/CodexBarCore/Providers/Grok/GrokRPCClient.swift` +- `Sources/CodexBarCore/Providers/Grok/GrokWebBillingFetcher.swift` +- `Sources/CodexBarCore/Providers/Grok/GrokStatusProbe.swift` +- `Sources/CodexBarCore/Providers/Grok/GrokLocalSessionScanner.swift` +- `Sources/CodexBar/Providers/Grok/GrokProviderImplementation.swift` diff --git a/docs/groqcloud.md b/docs/groqcloud.md new file mode 100644 index 0000000..fd5a875 --- /dev/null +++ b/docs/groqcloud.md @@ -0,0 +1,31 @@ +--- +summary: "GroqCloud provider setup and Prometheus metrics usage source." +read_when: + - Configuring GroqCloud usage tracking + - Debugging GroqCloud request or token-rate display +--- + +# GroqCloud + +CodexBar's GroqCloud provider is separate from the xAI Grok provider. It uses a GroqCloud API key and the Enterprise +Prometheus metrics API. + +## Setup + +Store the key in the shared app/CLI config: + +```bash +printf '%s' "$GROQ_API_KEY" | codexbar config set-api-key --provider groq --stdin +``` + +Or set `GROQ_API_KEY` in the process environment. `GROQ_API_URL` can override the default `https://api.groq.com/v1` +base URL for private gateways. + +## Menu display + +- Primary: requests per minute. +- Secondary: tokens per minute. +- Tertiary: prompt cache hits per minute when the metric exists. +- Dashboard link: GroqCloud metrics dashboard. + +If the key lacks Prometheus metrics access, CodexBar shows the API error instead of guessing from unrelated endpoints. diff --git a/docs/hero-mockup.svg b/docs/hero-mockup.svg new file mode 100644 index 0000000..e6d727e --- /dev/null +++ b/docs/hero-mockup.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/icon.md b/docs/icon.md new file mode 100644 index 0000000..2b4538a --- /dev/null +++ b/docs/icon.md @@ -0,0 +1,37 @@ +--- +summary: "Convert macOS .icon bundles to CodexBar .icns via Scripts/build_icon.sh and ictool." +read_when: + - Updating the CodexBar app icon or asset pipeline + - Preparing release builds that need a refreshed icns +--- + +# Icon pipeline (macOS .icon → .icns without Xcodebuild) + +We use the new macOS 26 “glass” `.icon` bundle from Icon Composer/IconStudio and convert it to `.icns` via Xcode’s hidden CLI (ictool/icontool), without an Xcode project. + +## Script +`Scripts/build_icon.sh ICON.icon CodexBar [outdir]` + +What it does: +1) Finds `ictool` (or `icontool`) in `/Applications/Xcode.app/Contents/Applications/Icon Composer.app/Contents/Executables/`. +2) Renders the macOS Default appearance of the `.icon` to an 824×824 PNG (inner art, glass applied). +3) Pads to 1024×1024 with transparency (restores Tahoe squircle margin, avoids “white plate”). +4) Downscales to all required sizes into an `.iconset`. +5) Runs `iconutil -c icns` → `Icon.icns`. + +Requirements: +- Xcode 26+ installed (IC tool lives inside the Xcode bundle). +- `sips` and `iconutil` (system tools). + +Usage: +```bash +./Scripts/build_icon.sh Icon.icon CodexBar +``` +Outputs `Icon.icns` at repo root. + +Why this approach: +- Naive `sips`/`iconutil` from raw PNGs often leaves a white/grey plate because the inner art is full-bleed. The ictool render + transparent padding matches Xcode’s asset-pipeline output. + +Notes: +- If Xcode is in a nonstandard location, set `XCODE_APP=/path/to/Xcode.app` before running. +- Script is CI-friendly; no Xcode project needed. diff --git a/docs/icon.png b/docs/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..11da02f4f4ac8d4cd8dcc159e6a2f0074d826b7f GIT binary patch literal 303343 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�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�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 \ No newline at end of file diff --git a/docs/images/menubar/github-circle-fill.png b/docs/images/menubar/github-circle-fill.png new file mode 100644 index 0000000000000000000000000000000000000000..2aa9d3f268484826d2b2096d23b2e3f2f5dd8d6a GIT binary patch literal 6742 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 yD;

+ + + CodexBar + + + + + +
+ +
+
+ + +
+
+
+
+ AI usage limits + + for macOS +
+ +

+ Every AI coding limit, + in your menu bar. +

+ +

+ Track usage windows, credit balances, and reset countdowns across the AI tools you actually pay for. +

+ +
+ + + Download for macOS + + +
+ +

+ Free & open source · macOS 14+ +

+
+
+
+
+ +
+ +
+ +
+
+

Limits, spend, and status

+ +
+
+
+

Resets you can plan around

+

Per-provider session, weekly, and monthly windows with countdowns to the next reset — no more guessing whether to start a long task.

+
+ +
+
+
+

Credits, spend, and cost scans

+

Credit balances and monthly spend where the provider exposes them, plus configurable local cost scans for Codex and Claude.

+
+ +
+
+
+

Status & incidents

+

Provider status polling surfaces incident badges in the menu and an indicator overlay on the bar icon.

+
+ +
+
+
+
+ +
+
+
+ + +
+

+ CodexBar + on CLI +

+

+ A bundled {codexbar} binary with the same usage output as the menu bar — scripts, CI, and quick terminal checks. +

+

+ Standalone tarballs for macOS and Linux on every release. +

+

+ + CodexBar reuses existing provider sessions — no passwords stored on disk. +

+
+
+
+
+ +
+
+
+
+

+ CodexBar + widgets +

+

+ WidgetKit widgets for supported providers — usage windows, reset countdowns, and spend where available. Drop them on your Home Screen and desktop. +

+

+ Small, medium, and large sizes. Switch providers without leaving the widget. +

+
+ +
+ +
+
+
+
+ +
+
+

More

+ +
+
+

Install & updates

+

+ Universal app via {releases} with Sparkle auto-updates, or via {cask} (updates via {upgrade}). +

+
+
+

CLI

+

+ A bundled {codexbar} binary plus standalone tarballs for macOS and Linux on each release. On Linux: {linuxCommand}. +

+
+
+

Privacy

+

+ Reuses existing provider sessions — OAuth, device flow, API keys, browser cookies, local files — so no passwords are stored. Audit notes in {issue}. +

+
+
+

macOS permissions

+

+ Full Disk Access for Safari cookies, Keychain access for cookie decryption and OAuth flows, and Files & Folders prompts when provider helpers read project directories. +

+
+
+
+
+
+ + + + + + + diff --git a/docs/issue-2037-fork-family-provenance-spec.md b/docs/issue-2037-fork-family-provenance-spec.md new file mode 100644 index 0000000..6519ed7 --- /dev/null +++ b/docs/issue-2037-fork-family-provenance-spec.md @@ -0,0 +1,609 @@ +# Spec: Scan-wide fork-family event provenance for Ultra overcounting (issue #2037) + +- **Issue:** [steipete/CodexBar#2037](https://github.com/steipete/CodexBar/issues/2037) — Ultra / forked-session token overcounting +- **Status:** Proposed (architecture redesign; fixture-gated) — rev 8a +- **P0 local corpus:** `docs/issue-2037-p0-local-corpus-findings.md` (provisional Codex locks from `~/.codex` forks; Ultra golden still open) +- **Supersedes as the canonical fix:** file-local-only approaches for closing #2037, including claiming [#2066](https://github.com/steipete/CodexBar/pull/2066) as a full fix +- **Related:** [#2066](https://github.com/steipete/CodexBar/pull/2066) (Codex intra-file containment — interim / non-closing at best), [#2043](https://github.com/steipete/CodexBar/pull/2043) / [#2059](https://github.com/steipete/CodexBar/pull/2059) (Pi file-local reconciliation merged then reverted), #968, #1062, #1164 / `45b68c34` +- **Affected code (expected):** `Sources/CodexBarCore/Vendored/CostUsage/` (Codex first); Pi only if the sanitized corpus proves the same shape + +## 0. Framing (read first) + +After [#2059](https://github.com/steipete/CodexBar/pull/2059), the repository owner retained #2037 as the canonical tracker. A replacement must provide: + +1. **Cross-file fork-family / stable event provenance** — copied ancestor events across related fork files must not be charged once per file. +2. **Proof against a sanitized real fork corpus** — exact tokens and nonlinear pricing, not synthetic-only confidence. + +[#2043](https://github.com/steipete/CodexBar/pull/2043) showed three failure modes to avoid: + +- copied ancestor rows across fork files still duplicated +- distinct events collapsed under a shared lineage key +- cumulative→delta conversion priced without full nonlinear context + +This document is the **canonical redesign**. The sanitized corpus is **design input**, not only final QA (§10): the exact provenance key cannot be chosen responsibly until the logs answer which IDs survive copies. If logs contain no usable stable identity, an exact solution may be impossible and the product must ship an explicitly labeled conservative estimate (`accountingQuality = contained`, §6). + +**Identity contract (summary):** use an ID as an event key only when the corpus proves **event-level cardinality**; request/message-scoped IDs that cover several snapshots need a copy-stable compound sequence or remain lineage hints. Otherwise use an exact pre-fork copied prefix under ancestry and a corpus-locked fork-boundary rule; never token-only dedupe; preserve post-fork distinct events; ambiguous or invalid graph states → no aggressive merge (§5). Fingerprint inputs must be copy-stable (§7); file-local ordinal is a tie-break only, not a fingerprint field unless the corpus proves it survives copying. + +**P1 vs P2 boundary:** + +| Phase | In scope | Out of scope | +|-------|----------|--------------| +| **P1** | Same-session union → cross-window family closure → normalize events (incl. priority metadata) → deterministic family/provisional graph → provenance ledger + ownership/baseline continuity → corpus-proven per-event accounting → per-event pricing → two-tier atomic family cache → quality fields/reasons to report/UI | Per-lineage cumulative baselines as primary accounting; closing #2037 when any affected golden needs containment | +| **P2** | Per-lineage baselines on unique events; demote watermark min-cap to ambiguous-only fallback | — | + +**Closing #2037:** P1 may close the issue **only if** the sanitized corpus proves the P1 per-event accounting path **and** no affected golden family requires the containment fallback (`accountingQuality = contained`). `provenanceQuality = incomplete` alone does not block closure when a corpus-locked provisional-family rule produces `accountingQuality = primary` and matches the hand token/cost oracle over the available corpus. If any in-scope golden still needs containment (or event/lineage identity remains unproven), **P2 is required** before closing; P1 can still ship as a non-closing step with #2037 left open. + +**Relationship to [#2066](https://github.com/steipete/CodexBar/pull/2066):** file-local watermark + min-cap is a **conservative fallback only** when lineage identity is genuinely ambiguous — never the primary method, never sufficient alone to close #2037. + +## 1. Problem (two layers) + +### 1.1 Inter-file — copied ancestor events (owner-canonical) + +Fork children can embed or re-emit ancestor `token_count` history in separate JSONL files. Today each file is scanned largely independently: + +- `forked_from_id` + inherited cumulative baseline (#1164) helps when the child only exposes high `total_token_usage` +- it does **not** recognize the same ancestor event copied into another session +- `CodexUsageRow` keeps only `turnID` and a session-local `eventIndex` (plus day/model/tokens). That is insufficient for cross-file provenance + +Result: the same completion can be charged once per file that carries a copy. + +### 1.2 Intra-file — interleaved cumulative lineages + +Ultra-style sessions can interleave multiple monotonic `total_token_usage` sequences in one file. A single global baseline recounts the high/low gap (see `docs/issue-2037-ultra-fork-overcount-spec.md`). Real, but not sufficient alone for §0. + +### 1.3 Non-goals (first redesign PR) + +- Per-sub-agent breakdown UI +- Changing models.dev / priority rate tables +- Claiming OpenAI invoice parity +- Closing #2037 without corpus-locked keys and golden totals + +## 2. Definitions + +| Term | Meaning | +|------|---------| +| **Normalized raw event** | Lossless extraction of one log `token_count` (and related ids/metadata) before accounting (§4.2) | +| **Same-session union** | Build a provenance-safe union of active + archived views of the **same** `sessionId` before cross-session family work (§4.1) | +| **Fork family** | All sessions descending from the same root under `forked_from_id` ancestry; one reconciliation unit | +| **Provisional family** | Children sharing the same unavailable `forked_from_id`, grouped under a synthetic missing-parent node (§4.4) | +| **Fork boundary** | The single P0 corpus-locked rule that separates copied ancestor prefix from child-local work (§4.3.1) | +| **Copied prefix** | Ancestor events that appear in a descendant file before that child’s fork boundary | +| **Event key** | Stable identity for recognizing the same source event across family files | +| **Lineage** | Real task/agent/turn cumulative sequence *after* family dedupe — only if the fixture shows a reliable id (P2 primary) | +| **Family ledger** | Accepted event keys for a family (count once across the entire family) | +| **Billing disposition** | Whether an observed event emits tokens/cost (`accepted`) or is a copied duplicate (`duplicate`) | +| **State disposition** | Whether an observed cumulative snapshot seeds or advances lineage state even when it is non-billable (§4.6) | +| **Billable owner** | The single family occurrence allowed to emit tokens/cost for one accepted event key (§4.5.1) | +| **Quality** | Independent provenance + accounting trust signals (§6); not a single overloaded enum | + +## 3. Pipeline (explicit order) + +Conceptual orthogonality of “same-session archive dedupe” vs “cross-session fork dedupe” is true; **the pipeline must still order them**. + +```mermaid +flowchart TD + enum[Metadata index / family closure] + same[Union same-session active/archive views] + extract[Extract normalized raw events per canonical session] + graph[Build fork-family graph + validate graph] + prov[Resolve event provenance across the family] + lineage[Account: P1 passthrough / P2 per-lineage] + price[Price each unique event individually] + quality[Assign provenanceQuality + accountingQuality] + cache[Replace family contribution atomically] + window[Filter accepted events to requested report window] + report[Propagate quality fields into CostUsage report / UI] + + enum --> same --> extract --> graph --> prov --> lineage --> price --> quality --> cache --> window --> report +``` + +**Ordering rules:** + +1. **Metadata closure first.** Enumerate/index enough metadata to identify relevant family membership, including out-of-window ancestors (§4.3). +2. **Then same-session union.** Build a provenance-safe union of active/archive views so one logical session contributes one normalized event stream before it participates in a fork family. Preserve unique suffixes; do not build families from duplicate extractions of the same `sessionId`. +3. **Then cross-session families.** Provenance ledger operates on canonical logical sessions only. +4. **Provenance before accounting.** Dedupe copies before lineage baselines or containment fallback. +5. **Price after reconciliation.** Nonlinear-safe. +6. **Quality after pricing inputs are known** — set **independent** provenance and accounting quality fields (§6), then persist with the family contribution. +7. **Report window last.** Reconcile the relevant family closure before filtering accepted events to `scanSince` / `scanUntil` (§4.3). + +### 3.1 Normative invariants + +1. **Once per key:** one accepted family event key has exactly one billable owner. +2. **Owner priority:** real ancestor occurrence before provisional sibling representative; ownership migration never bills both. +3. **State continuity:** copied/non-billable observations may seed or advance raw cumulative state but never increase `countedTotals`. +4. **Remove monotonicity:** removing a family file never increases attributed tokens/cost. +5. **Restore stability:** restoring a parent never increases the contribution of already-known copied keys; total may rise only for newly discovered unique events. +6. **Scan equivalence:** warm incremental = cold cache = force rescan for tokens, rows, costs, graph, ownership, and quality reasons. +7. **Window after reconcile:** out-of-window ancestors may seed/dedupe, but accepted usage is bucketed only by original event time. +8. **Event-local dates:** pricing date and report day derive from the original event timestamp — never scan, cache, restoration, or fork processing time. + +## 4. Design steps + +### 4.1 Union same-session active/archive views + +Before constructing cross-session fork families: + +- Identify files that share a `sessionId` (active partial + archived rollout, etc.). +- Merge their normalized events into one **canonical logical-session stream** using a local ordered-view rule; do not wait for fork-family construction (same-session views have no ancestry edge). +- Prefer namespaced event keys when event-level cardinality is corpus-proven. Otherwise align copy-stable normalized events within this `sessionId` only, preserving order and occurrence multiplicity (ordered prefix/overlap matching, not an unordered fingerprint set). +- Preserve unique events from every view (for example an archived suffix missing from an active partial file) while suppressing copied rows. +- Two legitimate identical occurrences remain two events when their ordered positions/multiplicity show both are present; fingerprint equality alone must not collapse them. +- Remember every source path and digest for invalidation, but emit only the merged logical stream into the family graph. +- Conflicting parent metadata across views of the same `sessionId` is an invalid state (§4.4), not a reason to pick whichever file was enumerated first. + +This is a **hard prerequisite step**, not an afterthought. + +### 4.2 Extract normalized raw usage events + +Each token event should retain at least: + +| Field | Role | +|-------|------| +| Session ID | Owning canonical session | +| Parent session ID | `forked_from_id` when present | +| Fork timestamp | Family ordering + pre-fork copy window | +| Stable event / request / message ID | Candidate provenance key only after corpus proof of event-level cardinality; namespace by ID kind | +| Turn ID | Attribution / priority join / optional lineage hint — **never** sole cross-completion key | +| Original event timestamp | Ordering + fingerprint | +| Ordinal within file | **Tie-break only** when timestamps collide — **not** a fingerprint input unless the corpus proves ordinals survive copying (insertions shift them) | +| Model and pricing date | Nonlinear / dated pricing | +| Raw `last_token_usage` | Per-event signal (semantics TBD by corpus) | +| Raw `total_token_usage` | Cumulative validation / lineage-local fallback | +| Canonical fingerprint of the source event | Fallback identity when explicit IDs are absent (§7); must use **copy-stable** fields only | +| **Priority / turn metadata** | Enough to reproduce standard vs priority pricing (`logs_2` / turn priority flags, surcharge eligibility, etc.) | + +**Priority metadata must survive normalization** so per-event pricing can split standard vs priority totals the way today’s priority overlay expects. Dropping it and re-deriving only from aggregates is a #2043-class pricing footgun. + +**Why:** today’s `CodexUsageRow` is too lossy for cross-file provenance and for faithful per-event pricing. + +### 4.3 Build a fork-family graph + +```text +root session +├── child A +│ └── grandchild +└── child B +``` + +All sessions descending from the same root are **one reconciliation unit**. Process parent-before-child when the graph is a DAG. + +**Family closure precedes date filtering.** Build or refresh a lightweight metadata index (session ID, parent ID, fork timestamp, source paths, coarse event date range) across all relevant roots/cache entries. For any session that can contribute to the requested report, load the transitive family members and the ancestor events required to establish provenance and cumulative baselines even when those files or events fall outside the report window. Reconcile first, assign accepted usage to each event's original date, then apply `scanSince` / `scanUntil`. An out-of-window parent must not become an artificial “missing parent” merely because the report window starts later. + +#### 4.3.1 Corpus-locked fork boundary + +The fork boundary is normative provenance input, not a heuristic chosen independently by each parser path. P0 must select and document one corpus-proven rule, for example: + +- the child rollout/session metadata fork timestamp +- the final event in a proven shared copied prefix +- the first child-local event after that shared prefix +- another explicit field established by the sanitized corpus + +The selected rule becomes part of the parser/reconciliation fingerprint. A parent event is prefix-eligible only when it satisfies that locked rule (for timestamp rules, normally `parentEventTimestamp <= boundary`). If the boundary is missing, contradictory, or cannot distinguish copied prefix from post-fork work, do not guess aggressively: record `ambiguousForkBoundary`, set `provenanceQuality = incomplete`, and use the corpus-defined conservative path (`accountingQuality = contained` when containment is required). + +### 4.4 Invalid / ambiguous family states + +Treat the following as **invalid or ambiguous** (no aggressive fingerprint merge; `provenanceQuality ≠ complete`, and often undercount-preferring): + +| Condition | Handling | +|-----------|----------| +| **Cycle** in `forked_from_id` edges | Apply the normative timestamp-first forest algorithm below; reject cycle-closing edges; set `provenanceQuality = incomplete` | +| **Conflicting parent claims** | Two authoritative views/files for one logical `sessionId` claim different parents, or authoritative session metadata disagrees with another authoritative parent-edge source → accept no guessed parent edge; record `conflictingParents`; set `provenanceQuality = incomplete`. Non-authoritative inference must not create an edge. The cycle/forest algorithm runs only after each session has at most one accepted parent candidate | +| **Stable-ID collisions** | Same namespaced ID maps to multiple token events without a corpus-proven compound sequence, or maps to incompatible payloads → the ID is not event-unique; keep the events separate, set `provenanceQuality = incomplete`, and never silently overwrite or arbitrarily drop one | +| **Missing parent** | Group all children sharing the unresolved parent ID under one provisional family node; apply the deterministic policy below; set `provenanceQuality = incomplete` | + +#### 4.4.1 Deterministic DAG / cycle rule + +For each connected component, build the accepted forest from the complete currently known edge set — never from file enumeration order: + +1. Parse fork timestamps. Valid timestamps sort before missing/invalid timestamps. +2. Sort edges by `(timestampValidity, forkTimestamp ascending, childSessionId, parentSessionId)`. +3. Add edges in that order. Reject an edge if adding it would create a cycle. +4. Mark every component with a rejected edge `provenanceQuality = incomplete` and record `cycleBroken` when quality reasons are persisted. +5. Recompute the whole connected component whenever an edge/member changes; a warm incremental scan and a full rescan must produce the same accepted forest. + +This prioritizes the earliest physically reported fork relation while retaining session IDs as stable tie-breakers when timestamps are equal or unusable. + +#### 4.4.2 Missing-parent provisional family + +A missing parent ID is still relationship evidence. Create a synthetic node keyed by `missing:` and attach all children that reference it. + +- Reconcile corpus-proven stable event keys shared by those siblings. +- When explicit IDs are unavailable, apply a sibling exact-prefix rule only if the sanitized fixture locks copy-stable equality and the events are pre-fork for every affected child. +- If the pre-fork streams remain ambiguous, choose one deterministic canonical pre-fork stream `(valid forkTimestamp first, earliest timestamp, sessionId)` as the billable representative; other sibling pre-fork streams are state-only. Set `accountingQuality = contained`. +- Post-fork events remain separate unless a proven event key establishes an actual copy. +- If a formerly present parent disappears, recompute the family under this provisional rule and atomically replace its old contribution. +- If the real parent later appears, dissolve `missing:`, rebuild the real family from all member views, migrate copied-key ownership to the real ancestor, and atomically replace the provisional and any old sibling-local contributions. Newly discovered unique parent events may add cost; already-known copied keys may not. + +**File-removal monotonicity invariant:** removing a file from the available family corpus must never increase the family's attributed tokens or cost. It may stay equal (copied parent history remains represented once) or decrease (unique events disappeared), but must not rise because siblings began double-charging a copied prefix. + +Accounting quality for provisional families is determined by the identity path, not merely by the parent's absence: + +| Sibling-prefix evidence | Accounting result | +|-------------------------|-------------------| +| Corpus-proven shared event keys or corpus-proven exact-prefix equality | `accountingQuality = primary`; record `missingParent` + `provisionalFamily` | +| Deterministic representative selected because streams disagree or identity/boundary is ambiguous | `accountingQuality = contained`; record `missingParent` + `provisionalFamily` + `containmentFallback` (and the relevant ambiguity reason) | + +Thus `provenanceQuality = incomplete` does not imply containment by itself. + +### 4.5 Resolve event provenance across the family + +For every normalized event: + +1. **Prefer a namespaced stable event / request / message ID only when the corpus proves event-level cardinality** as well as copy survival. If one request/message ID covers several token snapshots, compound it with a copy-stable event sequence/type proven by the corpus or treat it only as a lineage hint. +2. **Otherwise**, recognize an **exact copied prefix** only when: + - the files have an ancestor relationship in the family graph, **and** + - the event occurs **before the fork boundary** of the descendant, **and** + - “exact” means corpus-defined equality: prefer byte-identical source lines when that holds; otherwise normalized equality of retained raw fields — pin from the fixture. +3. **Count a copied ancestor event once** across the entire family by assigning its billable owner under §4.5.1. The same proposed key with a different accounting payload is a collision, not a duplicate (§4.4). +4. **Never deduplicate merely because two events have the same token values.** +5. **Preserve identical-but-distinct events after the fork.** + +**Tie-break:** `(timestamp, ordinal, session topological order)`. + +**Forbidden:** token-only dedupe; file-local `eventIndex` as cross-file identity; shared Ultra/task id as the *only* key for many completions. + +#### 4.5.1 Billable ownership (normative) + +For each accepted family event key `K`, assign exactly one `billableOwner`: + +1. **Real ancestor present and contains `K`:** the earliest real ancestor occurrence in parent-before-child order owns billing. Descendant occurrences are state-only duplicates. +2. **Real parent missing or does not contain `K`:** one deterministic provisional sibling occurrence owns billing (the canonical representative rule in §4.4.2). Other sibling occurrences are state-only duplicates. +3. **Partial parent:** apply the rule per key, not per whole prefix. Keys actually present in the parent are parent-owned; keys only visible in children use the provisional representative. +4. **Parent reappears:** recompute the family and migrate ownership for matching keys to the real ancestor in one cache generation. Never retain both the provisional and real owner. +5. **Conflicting payload for the same proposed key:** this is a collision, so no ownership merge occurs (§4.4 / §7). + +Ownership changes where a row is sourced, not its semantic identity, original timestamp, token vector, or price. Therefore a copied key remains billed once across parent disappearance/reappearance transitions. + +Billable ownership applies only to the contribution for `K`; it does not shortcut baseline propagation. If grandparent and parent both contain `K`, the grandparent owns billing, but the child still seeds state by walking its **actual parent chain** and applying each fork-boundary snapshot in order. Intervening unique parent events must advance the child baseline even when earlier copied keys are grandparent-owned. + +Parent restoration may change `provenanceQuality` from incomplete to complete only after the full real family is recomputed and has no remaining missing edges, collisions, cycle breaks, or ambiguous fork boundaries. Corpus goldens prove that transition; runtime assigns it from recomputed state rather than attempting to “check a golden.” + +### 4.6 Account per real lineage (P2 primary; P1 may defer) + +Only on **unique** family events: + +**P1:** May emit one accounting event per ledger-accepted normalized event using `last` / total policy locked by corpus study, without full multi-run lineage state — still **after** provenance. If intra-file interleaving remains ambiguous, apply containment fallback and set `accountingQuality = contained`. + +P1 still requires an explicit reducer per canonical logical session (and therefore one per provisional sibling), never one family-global baseline: + +```text +P1SessionAccountingState { + countedTotals + rawTotalsBaseline + inheritedTotalsRemaining + containmentTracker +} +``` + +Before unique child events are accounted, replay that session's copied-prefix occurrences through the state path with `billingDisposition = duplicate`: update/seed `rawTotalsBaseline`, consume inherited state where applicable, and leave `countedTotals` unchanged. Then process billable unique events. Intra-session interleaving may still latch that session's containment tracker and set `accountingQuality = contained`; it must not create or reuse a family-global watermark. + +**P2:** + +1. Use a stable task/agent/turn **lineage** id iff the fixture shows it identifies a cumulative sequence without collapsing independent requests. +2. Maintain a **separate cumulative baseline per lineage**. +3. If `last_token_usage` is proven per unique request, use it (optionally cross-checked against lineage-local total delta). +4. Use cumulative totals as validation and/or lineage-local fallback. +5. If lineage identity is genuinely ambiguous → **watermark + min-cap containment** as conservative fallback only (§0); set `accountingQuality = contained`. +6. Optional never-inflate ceiling may wrap the fallback path only. + +#### 4.6.1 Billing suppression does not erase state + +Provenance decides whether an event is billed; it does **not** decide whether the event is an observed cumulative-state transition: + +- Ledger-accepted unique event: `billingDisposition = accepted`; it may seed/advance lineage state and emit its accounted delta. +- Copied ancestor event: `billingDisposition = duplicate`; it emits zero tokens/cost **but still seeds or advances the descendant's raw cumulative baseline**. +- At a resolved fork boundary, initialize each proven child lineage from the corresponding final parent cumulative snapshot at or before the fork. +- If lineage identity is not yet known, seed the P1/fallback reducer from the final filtered copied-prefix total (fork-inheritance adjusted), not zero. +- With a missing parent, use the provisional family's canonical pre-fork stream as state-only seed material for every sibling; ambiguous cases remain `accountingQuality = contained`. + +Thus a parent ending at `100M`, followed by a child's first unique absolute total of `101M`, contributes `1M` — not `101M` — even though copied parent events were removed from billing. + +Keep #1164 inherited total resolution as the baseline-seeding mechanism where applicable. Authoritative cross-file billing dedupe remains §4.5; state continuity remains mandatory after dedupe. + +#### 4.6.2 Placement of #2066 containment + +After family provenance lands, containment runs only inside one canonical session's **unique post-ledger stream**: + +```text +family copies → provenance ledger → unique stream per canonical session + → primary per-event/per-lineage accounting + → session-local containment only if still ambiguous +``` + +Never apply one #2066 watermark across family members, and never let containment decide whether cross-file copies are duplicates. Provenance owns copy identity; containment is the final ambiguity guard for one already-deduplicated session stream. + +### 4.7 Price only after reconciliation + +Each unique event retains original model, pricing date, input, cached input, output, **and priority/turn metadata**. Price **individually** after deduplication so standard vs priority and other nonlinear tiers can be reproduced. + +Both the pricing-catalog date and report-day bucket derive from the accepted event's **original timestamp**. Do not use scan time, cache-write time, fork time, parent restoration time, or the timestamp of a different copied occurrence. + +Never subtract already-priced aggregates or price a collapsed lineage blob (#2043). + +### 4.8 Change the cache boundary + +Use a **two-tier derived cache** rather than embedding every normalized event in the existing monolithic JSON cache. + +**Main manifest / family-result cache** (small, eagerly decoded): + +- stable family ID (`rootSessionId` or provisional `missing:`) +- canonical logical-session members and all source path/file digests +- parser, normalized-event-schema, pricing, and reconciliation fingerprints +- accepted family contribution maps / cost nanos +- provenance/accounting quality fields and optional quality reasons +- references to member event sidecars + +**Per-file or per-canonical-session event sidecars** (lazy, independently invalidatable): + +- only normalized fields required for provenance, baseline continuity, and pricing +- no original JSON lines and no redundant final report aggregates +- versioned and atomically written +- loaded only for a dirty family or a forced rescan + +“Lossless” here means lossless for the specified provenance/accounting inputs, not byte-for-byte preservation of source JSON. Source logs remain authoritative and every sidecar is disposable/rebuildable. + +When one file changes: + +1. Rebuild the same-session union if needed. +2. Reparse that file’s normalized events. +3. Determine its fork family. +4. Reconcile and reprice **that entire family**. +5. Replace the family’s previous contribution **atomically**, including its quality fields (§6). + +**Initially avoid clever incremental family reconciliation.** Recompute the affected family. + +When a source disappears, changes `sessionId`/parent, or moves between families, use the manifest to identify both the old and new affected families. Recompute both and update their contribution records in one in-memory cache transaction before the main cache is atomically saved. Write sidecars via temporary file + rename so an interrupted refresh cannot expose a half-written event set. + +#### 4.8.1 Crash-safe generation protocol + +1. Read one committed manifest generation `N`; readers ignore unreferenced sidecars. +2. Build all changed family results and sidecars for generation `N+1` in memory / temporary paths. +3. Atomically rename completed sidecars into content-addressed or generation-qualified final paths. +4. Write the complete `N+1` manifest (family membership, contributions, rolled-up day totals, quality, sidecar digests) to a temporary file and atomically rename it last. **The manifest rename is the commit point.** +5. On failure before the manifest commit, generation `N` remains authoritative; partial `N+1` sidecars are orphans and cannot affect totals. +6. Garbage-collect sidecars not referenced by the committed manifest after a successful commit or on a later startup/refresh. +7. Validate referenced sidecar schema + digest before use; a missing/corrupt sidecar invalidates only its affected family and triggers source reparse. + +This prevents a crash during reparenting from mixing old family A contributions with new family B contributions. A monotonically increasing generation number plus sidecar content digests is sufficient; a separate complex checksum journal is not required. + +**Day-total atomicity:** rolled-up day/model/cost maps are derived exclusively from the family contributions in the newly committed manifest generation. Never patch global day totals in place while ownership moves from family A to B. Generation `N` contains all old owners/totals; generation `N+1` contains all new owners/totals; no reader may observe a mixed generation containing both A's old and B's new contribution for one key. + +Do not mandate run-length encoding, pruning, compression, or a particular binary format before measuring the sanitized corpus. First record: + +- normalized sidecar bytes versus source-log bytes +- cold main-cache decode time +- dirty-family sidecar load + recompute time +- full rebuild time +- peak resident memory + +Lock acceptable budgets before implementation freeze. If needed, optimize with string interning, columnar arrays, timestamp/ordinal deltas, or compression while preserving every normative field and golden result. + +Bump `CodexParserHash`, the normalized-event sidecar schema, and clear compatible producer keys when this ships. + +## 5. Identity contract (normative) + +| Prefer | Avoid | +|--------|--------| +| Namespaced ID proven one-to-one with an accounting event and copied into children | Request/message ID assumed event-unique without cardinality proof | +| Exact pre-fork copied prefix under ancestor relationship | Token-value-only dedupe | +| Separate post-fork events even if counts match | Shared task id as sole key | +| Ambiguous → keep separate + degrade quality | Silent overwrite on ID collision | + +## 6. Quality fields → report / UI + +### 6.1 Provenance completeness ≠ accounting containment + +These are **independent**. A family can be graph-incomplete **and** still use containment fallback — a single enum loses that information. + +Persist **two fields** (or an equivalent set of quality reasons): + +```text +enum CodexFamilyProvenanceQuality { + case complete // resolvable DAG, no conflicting parents / unhandled cycles + case incomplete // missing parent, cycle break, conflicting parents, etc. +} + +enum CodexFamilyAccountingQuality { + case primary // corpus-proven per-event / per-lineage path (no containment) + case contained // watermark min-cap / containment fallback used +} +``` + +Persist a `Set` alongside the two fields. At minimum support and assert in goldens: + +```text +missingParent +provisionalFamily +cycleBroken +conflictingParents +stableIdCollision +fingerprintCollision +ambiguousForkBoundary +containmentFallback +``` + +The UI may collapse reasons into simpler copy, but cache/CLI/test output must preserve them so `incomplete + contained` is diagnosable rather than a black box. + +**Roll-up when aggregating days:** worst provenance and worst accounting independently (`complete` < `incomplete`; `primary` < `contained`). + +### 6.2 Propagation path (implementation target) + +1. **Scanner / family reconcile** assigns both quality fields per family. +2. **Cache** persists both fields and mandatory quality reasons with the family’s accepted events / cost nanos. +3. **`CostUsageDailyReport`** (and project breakdowns if present) expose rolled-up fields, e.g. `provenanceQuality` + `accountingQuality` (or derived `isEstimate` = either non-ideal). +4. **UI / menu:** distinct affordances when possible — e.g. “Incomplete fork history” vs “Estimated (conservative accounting)” — not a single vague “Estimated” that conflates the two. +5. **CLI** (`codexbar cost` JSON): include both fields and quality reasons so agents/scripts do not treat estimates as exact. + +Exact UX copy TBD; the **data path for both dimensions** is required in P1 so quality is not documentation-only. + +## 7. Canonical fingerprint (when IDs are absent) + +Used only for the pre-fork exact-copy path or as a secondary assist — not global token dedupe. + +**Copy-stable inputs only** (finalize from corpus), e.g.: + +- event timestamp (if stable across copies) +- model +- raw `last_token_usage` when present +- raw `total_token_usage` snapshot when present +- any weak ids (`turn_id`, etc.) only as secondary components + +**Do not include file-local ordinal** in the fingerprint unless the corpus proves ordinals survive copying. Surrounding insertions in a child log can shift ordinals even when the event is the same ancestor row. Ordinal remains useful as a **within-file or same-stream tie-break** after candidates are matched by copy-stable fields — not as identity. + +**Fingerprint collision policy:** + +- same high-confidence fingerprint + identical normalized accounting/provenance payload → copied duplicate candidate +- same high-confidence fingerprint + incompatible payload → keep events separate, record `fingerprintCollision`, set `provenanceQuality = incomplete`, and never merge or sum the payloads under one key +- low-confidence fingerprint → do not merge + +## 8. Phased delivery + +| Phase | Scope | Closes #2037? | +|-------|--------|----------------| +| **P0** | Spec; sanitized corpus; lock eventKey / exact-copy / identity contract | No | +| **P1** | Same-session union → cross-window family closure → normalize (+ priority metadata) → deterministic family/provisional graph → provenance ledger + ownership/baseline continuity → corpus-proven per-event accounting → per-event pricing → two-tier atomic family cache → quality fields/reasons through report/UI | **Only if** corpus proves the P1 per-event path **and** no affected golden family has `accountingQuality = contained`. `incomplete + primary` may close when its provisional-family oracle matches; otherwise ship non-closing and require P2 | +| **P2** | Per-lineage cumulative baselines; containment strictly fallback → clear remaining `contained` goldens | Required to close when P1 still needs containment on in-scope goldens | +| **P3** | Pi parity if logs match | Separate if needed | + +[#2066](https://github.com/steipete/CodexBar/pull/2066) may merge earlier only as an **explicit non-closing** interim guard with owner approval and #2037 left open. + +## 9. Test plan (after corpus locks keys) + +**Corpus golden** + +1. Family token total = hand oracle (no multi-file ancestor multi-charge). +2. Dollar total = hand oracle under nonlinear **and** standard vs priority splits. +3. Post-fork identical-but-distinct events preserved. +4. Quality fields and mandatory reasons match expected state (`provenanceQuality`, `accountingQuality` — including combinations such as incomplete + contained). +5. Two children copy the same pre-fork parent event → charged once. +6. **Two siblings reference the same unavailable parent** → provisional-family reason + `provenanceQuality = incomplete`; copied prefix bills once and family does not inflate (quality/ownership focus). +7. Same token vectors post-fork on siblings → not deduped. +8. Cycle in fork edges → deterministic break + `provenanceQuality = incomplete`. +9. Duplicate `sessionId` with conflicting parents → `provenanceQuality = incomplete`. +10. Stable-ID collision with incompatible payloads → no silent merge; `provenanceQuality = incomplete`. +11. Same-session active+archive → provenance-safe union stream before family graph; unique suffixes preserved exactly once. +12. Priority metadata preserved → standard vs priority totals match oracle. +13. Ambiguous lineage → containment fallback + `accountingQuality = contained`; no gap-billion inflation. +14. Touching one family member recomputes whole family; atomic replace ≡ full family rescan. +15. `#968` / `#1062` / `#1164` non-family regressions remain green. +16. Parent total `100M`, copied child prefix `100M`, first unique child total `101M` → copied row bills zero but seeds state; child bills exactly `1M`. +17. Delete a parent shared by two children → family cost never rises; warm-cache, cold-cache, and force-rescan results agree. +18. Missing-parent siblings with corpus-proven shared prefix → prefix represented once; both child baselines seeded; first unique absolute totals count only post-prefix growth (state-continuity focus); post-fork work remains distinct. +19. Enumerate the same cyclic edge set in every order and through incremental arrivals → identical accepted forest and quality reasons. +20. Parent outside the requested day window still seeds/dedupes an in-window child; filtering occurs after reconciliation. +21. Active partial + archived suffix for one `sessionId` → canonical logical stream preserves the union of unique events exactly once. +22. One request/message ID attached to multiple token snapshots → not collapsed unless a corpus-proven compound event sequence distinguishes copies. +23. Real parent present → parent owns copied key; remove parent → one sibling owns; restore parent → ownership migrates back, with the key billed once in every generation. +24. Parent restoration with additional unique parent events → known copied-key contribution does not rise; only newly discovered unique events add cost. +25. Every supported/ambiguous fork-boundary shape → selected corpus rule classifies prefix/post-fork rows exactly; ambiguous boundary records its reason and does not aggressively merge. +26. High-confidence fingerprint collision with incompatible payload → events remain separate and `fingerprintCollision` is asserted. +27. Quality-reason goldens assert at least `missingParent`, `provisionalFamily`, `cycleBroken`, `conflictingParents`, `stableIdCollision`, `fingerprintCollision`, `ambiguousForkBoundary`, and `containmentFallback` where applicable. +28. Crash before manifest commit → old generation remains authoritative; crash after commit → new family/day totals and sidecars are internally consistent; orphan GC does not alter totals. +29. Original event timestamp controls both pricing catalog date and report day across parent restoration, rescans, and copied occurrences. +30. Family ledger emits unique per-session streams before #2066 containment; no family-global watermark is created. +31. Same-session active/archive streams contain two legitimate identical occurrences → ordered union preserves multiplicity while suppressing only the copied overlap. +32. Grandparent and parent both contain key `K`; grandparent owns billing, while child baseline walks grandparent → parent → child and includes intervening unique parent growth. +33. Provisional family with proven shared keys/prefix → `incomplete + primary`; ambiguous representative path → `incomplete + contained`, with exact reasons asserted. +34. Session ownership moves family A → B → main manifest day totals contain exactly one generation's contribution, never A-old + B-new together. +35. Conflicting authoritative parent claims → no parent edge accepted and `conflictingParents`; non-authoritative inference alone never creates an edge. + +**Performance / storage acceptance (sanitized corpus):** record the §4.8 metrics for cold cache, dirty-family refresh, and full rebuild; verify that loading one dirty family does not deserialize every event sidecar. Performance budgets must be agreed before implementation freeze, and optimized representations must remain golden-equivalent. + +## 10. Fixture required first (design input) + +A sanitized Ultra / multi-fork corpus must answer: + +1. Which IDs survive when parent events are copied into child files, and what is each ID's cardinality (one event, one request with many snapshots, one lineage, etc.)? +2. Are copied lines byte-identical, or only field-equal after normalization? +3. Does `turn_id` identify a cumulative lineage, or only a turn span unsafe alone? +4. Is `last_token_usage` per-request, cumulative, or sometimes replayed? +5. What happens when a parent file is unavailable (including **two siblings → one missing parent**)? +6. How are priority turns represented so metadata can be normalized? +7. Do active/archive views with one `sessionId` contain unique suffixes that require unioning? +8. Are fork timestamps present, parseable, and physically consistent enough for timestamp-first graph ordering? +9. Which exact fork-boundary rule correctly separates copied prefix from child-local work, including ambiguous/missing metadata cases? +10. Does parent disappearance/reappearance preserve event keys and original timestamps well enough for deterministic ownership migration? + +**Deliverables before implementation freeze:** hand token + dollar oracles; documented namespaced event-key cardinality / exact-copy rules; the exact locked fork-boundary rule text; duplicated ancestor chain; missing-parent siblings; baseline-continuity oracle; parent disappear/restore ownership-migration oracle; ambiguous-boundary goldens; redacted before/after output; expected quality fields/reasons per scenario; cache/performance measurements and agreed budgets. + +## 11. Risks + +| Risk | Mitigation | +|------|------------| +| No stable ID survives copies | Pre-fork exact-copy rule; else `accountingQuality = contained` / labeled estimate only | +| Request/message ID covers multiple token snapshots | Require event-level cardinality proof or a copy-stable compound sequence; otherwise use only as lineage hint | +| Over-dedupe | Identity contract; post-fork preserve; no token-only dedupe | +| Same-session unordered union collapses legitimate repeats | Ordered overlap alignment within one `sessionId`; preserve occurrence multiplicity and unmatched suffixes | +| Removing a parent increases cost | Provisional missing-parent family + file-removal monotonicity invariant + warm/cold regressions | +| Restoring a parent double-bills provisional keys | Per-key owner priority + atomic ownership migration; only new unique parent keys may add cost | +| Deduped prefix resets child cumulative baseline | Separate billing disposition from state disposition; copied observations seed state but bill zero | +| Earliest billable owner skips intervening parent state | Ownership controls billing only; baseline seeding walks the actual parent chain and every fork boundary | +| P1 “state-only” implemented as another global baseline | Explicit `P1SessionAccountingState` per canonical session/provisional sibling; no family-global watermark | +| Cycle result depends on file order | Timestamp-first accepted-forest algorithm over the whole component; stable ID tie-breaks | +| Wrong fork boundary over- or under-dedupes | Corpus-lock one boundary rule; ambiguous boundary records reason and uses conservative path | +| Out-of-window parent treated as missing | Build relevant family closure before report-date filtering | +| Same-session union drops an active/archive unique suffix | Union all same-session views before cross-session graph construction | +| Monolithic normalized-event JSON grows too large | Small manifest/family results + lazy disposable sidecars; benchmark before choosing compact encoding | +| Crash mixes old/new family ownership or day totals | Generation-qualified sidecars; manifest atomic rename as commit point; orphan GC | +| Family move patches day totals twice | Rebuild day maps solely from one committed generation's family contributions; never patch global totals in place | +| Copied occurrence changes price/report day | Preserve original event timestamp as both pricing-date and report-bucket source | +| Quality never reaches UI | §6 mandatory in P1 (both dimensions) | +| Single enum conflates provenance vs accounting | Dual fields / reason set (§6.1) | +| Same-session vs family ordering bugs | §3 hard order + test 11 | +| Conflicting authoritative parent claims delegated to cycle breaker | Accept no guessed edge; mark `conflictingParents`; run forest only after single-parent candidates are resolved | +| Treating #2066 as the fix | Fallback-only; leave #2037 open unless P1 close criteria met | +| Closing #2037 while goldens still use containment | Explicit P1 close gate (§0, §8); otherwise P2 required | + +## 12. Open questions for steipete / reporter + +1. First milestone corpus: Codex JSONL, Pi, or both? +2. Acceptable dollar tolerance vs hand oracle? +3. Interim non-closing merge of [#2066](https://github.com/steipete/CodexBar/pull/2066) while P0–P1 proceed? +4. Preferred UI strings for `provenanceQuality = incomplete` vs `accountingQuality = contained` (including when both apply)? +5. Confirm the close gate: an oracle-matching `incomplete + primary` provisional family is acceptable, but any affected golden with `accountingQuality = contained` keeps #2037 open for P2? + +## 13. Summary + +Strong basis for implementation once the fixture locks keys: + +- **Fixture-first** gate +- **Ordered same-session union** that preserves multiplicity and unique suffixes +- **Cross-window family closure** before date filtering +- **Provenance separated from accounting** +- **One billable owner per event key**, with atomic ownership migration when a parent disappears/reappears +- **Billing ownership separate from parent-chain baseline propagation** +- **Billing suppression preserves baseline state** for copied prefixes +- **Explicit P1 session reducer**, never a family-global baseline +- **Provisional missing-parent families** with file-removal monotonicity +- **Explicit provisional `primary` vs `contained` fork** based on corpus-proven identity +- **Corpus-locked fork-boundary rule** with an explicit ambiguous path +- **Refuse token-only deduplication** +- **Event-level ID cardinality**, not merely ID copy survival +- **Price after reconciliation** (with priority metadata preserved) +- **Containment only as fallback** +- **Correct P1/P2 boundary and close gate** — P1 closes #2037 only with proven per-event path and no contained goldens; otherwise P2 required +- **Identity contract** with copy-stable fingerprints (ordinal tie-break only unless corpus proves otherwise) +- **Explicit pipeline order** (same-session union before families) +- **Timestamp-first deterministic cycle handling** +- **Two-tier derived cache** with lazy sidecars and measured performance budgets +- **Manifest-generation commit protocol** with crash isolation and orphan sidecar GC +- **Day totals derived from one committed family generation**, never patched across moves +- **Dual quality fields** (provenance × accounting) with a real report/UI path +- **Mandatory quality reasons** asserted by goldens and exposed through cache/CLI +- **Event-local pricing/report dates** across rescans and ownership migration +- **Invalid graph / ID collision** states defined +- **Sibling missing-parent** coverage in tests + +File-local containment alone cannot close #2037. This scan-wide provenance design can — after the corpus locks the keying rules, and only when the close criteria in §0 / §8 are met. + +**Stop condition for prose:** after rev 8, do not begin P1 or add speculative key schemes until P0 locks §10.1 (event-key cardinality), §10.9 (fork-boundary rule), and §10.10 (ownership migration through parent disappearance/reappearance). + +**Local P0 progress (2026-07-11, rev 2):** `docs/issue-2037-p0-local-corpus-findings.md` locks §10.1 / §10.9 for ordinary Codex rollout forks and records scanner-integration results: + +- No per-`token_count` event ID; ordered normalized `(last,total)` contiguous prefix under ancestry; timestamps rewritten on copy (exclude from fingerprint); leaf `session_meta` is authoritative. +- Sanitized fixture `archived-fork-33ce-3869` + oracle tests are in-repo. +- **Parent present:** `#1164` inherited totals already match the parent-owns-prefix scanner-unit oracle (`Issue2037ScannerIntegrationTests`) — regression-locked, not a new ledger. +- Local Ultra/Sol–Terra parallel runs did **not** produce interleaved `total_token_usage` drops; do not block cross-file work on drops. +- **Still open for close criteria:** Ultra interleaved corpus, fuller event-key ledger / ownership migration, priority/`logs_2` join. +- **Missing-parent siblings:** sanitized fixture + hand oracle landed. Runtime token-only prefix suppression was removed because equal-counter distinct events are ambiguous; the scanner fails open until the P1 identity/quality path exists. diff --git a/docs/issue-2037-p0-local-corpus-findings.md b/docs/issue-2037-p0-local-corpus-findings.md new file mode 100644 index 0000000..b94eada --- /dev/null +++ b/docs/issue-2037-p0-local-corpus-findings.md @@ -0,0 +1,212 @@ +# P0 local corpus findings for #2037 (rev 2) + +- **Source:** local Codex JSONL under `~/.codex/sessions` + `~/.codex/archived_sessions` (this machine) +- **Date:** 2026-07-11 (rev 2 adds scanner-integration observations) +- **Scope:** structural identity / fork-copy behavior only — no message bodies; session IDs truncated in narrative +- **Status:** Provisional locks for Codex rollout logs on this corpus. Still need an Ultra-shaped golden to close #2037, but ordinary-fork identity + parent-present scanner behavior are locked in-repo. +- **Companion:** `docs/issue-2037-fork-family-provenance-spec.md` (rev 8a+) + +## Corpus snapshot + +| Metric | Value | +|--------|-------| +| JSONL files | ~81+ (grew during Ultra P0 attempts) | +| Logical sessions (first `session_meta.id`) | dozens | +| Real fork edges (`forked_from_id` ≠ self) | several families | +| `token_count` events surveyed | ~6k+ | + +Observed families (prefixes): + +- `019f33ce` → `019f3869` → `019f38ec` (parent → child → grandchild) +- `019f32c8` → `019f331e` (mid-session / partial prefix fork) +- `019f3cec` → `019f3e32` (partial prefix; parent continued after fork) +- Later Ultra-adjacent: `019f4d90` → `019f52bf` / `019f52e6` / `019f52e7` / `019f52f3` (Sol/Terra, multi-agent v2) + +## Locked answers (local Codex) + +### §10.1 Event-key cardinality + +| Candidate | Survives copy? | Event-level cardinality? | Verdict | +|-----------|----------------|--------------------------|---------| +| Stable event / request / message ID on `token_count` | n/a | **Absent** on `token_count` rows | Do **not** use as event key | +| `turn_id` | Present on other events (`event_msg`, `turn_context`) | **Not** on `token_count` | Lineage / priority join hint only — never sole cross-completion key | +| Envelope `timestamp` on `token_count` | **No** — rewritten at fork into a tight burst | n/a | **Not** copy-stable; exclude from fingerprint match | +| File-local ordinal / line number | No | Tie-break only | Exclude from fingerprint | +| Normalized `last_token_usage` + `total_token_usage` vector | **Yes** (field-equal, ordered) | Unique within observed parent streams, but not proven unique across distinct sibling work | Copy-candidate evidence only; insufficient destructive event identity | +| Byte-identical JSONL line | **No** (0 byte-identical parent↔child lines) | n/a | Prefer normalized equality | + +**Lock:** For this Codex shape, there is **no** stable per-`token_count` event ID. Ordered exact-prefix matching of normalized usage vectors under `forked_from_id` ancestry identifies the copied-prefix candidate in the sanitized corpus, but token equality alone must not suppress runtime billing. + +### §10.2 Copy equality + +Copied ancestor `token_count` rows are **field-equal after normalization**, not byte-identical. Matching inputs that worked locally: + +- `last_token_usage` (all int fields) +- `total_token_usage` (all int fields) + +Do not require equal timestamps. + +### §10.9 Fork-boundary rule (locked for this corpus) + +**Corpus oracle rule (not a sufficient runtime event key):** Contiguous ordered usage-fingerprint prefix. + +1. Take parent and child canonical `token_count` streams in file order. +2. Let `N` = longest `k` such that `child[0..k)` equals `parent[0..k)` under the normalized usage fingerprint. +3. `child[0..N)` is the copied prefix (state-only on the child; parent owns billing when present). +4. `child[N..)` is child-local work. + +**Corroboration (not the classifier):** leaf `session_meta.timestamp` (`fork_ts`) lands within ~0–1s of the end of the rewritten prefix / start of unique work on observed mid-session forks. Useful for family graph ordering; **do not** classify prefix via `parentEventTimestamp <= fork_ts` because copied child timestamps are rewritten and are **not** the parent’s original times. + +**Evidence:** + +| Edge | Parent `token_count`s | Child | Prefix `N` | Parent continued after fork? | +|------|----------------------|-------|------------|------------------------------| +| `33ce→3869` | 135 | 158 | 135 (entire parent) | No | +| `3869→38ec` | 158 | 158 | 158 (entire parent; no unique child tokens in archive) | n/a | +| `32c8→331e` | 270 | 276 | 243 | Yes (+27 parent events) | +| `3cec→3e32` | 387 | 581 | 226 | Yes | +| `4d90→52bf` | 293 (live; continued) | 196 | 180 | Yes (parent continued after copy) | + +### §10.4 `last_token_usage` semantics + +On ordinary in-session streams, `Δ total_token_usage.total_tokens == last_token_usage.total_tokens` on nearly every step (hundreds of matches, ~0 positive mismatches in sampled files). + +**Caveat:** the first post-fork child event can show `last > 0` while `total` is still flat vs the last prefix event. After provenance, billing should follow the corpus-locked per-event policy carefully; total-delta alone undercounts that row, last alone may overcount vs cumulative. Flag for golden oracles — do not invent a hybrid in P0 prose beyond “measure on goldens.” + +**Oracle units:** hand oracles that sum `last.total_tokens` are **not** identical to scanner-priced units. Scanner accumulates `input + cached_input + output` from each billed delta. Integration tests must compare **scanner units** (`sum(last.input+cached+output)` with prefix suppressed), not raw `total_tokens` field sums. + +### §10.5 / ownership migration + +- Authoritative session identity for a file: **first** `session_meta` in the file (the leaf). Later `session_meta` rows often re-embed ancestors. +- Child / grandchild files embed ancestor `session_meta` chains (`leaf`, then parent, then grandparent, …). Graph builder must not treat every embedded meta as a separate root file identity. +- Filename UUID can differ from leaf `session_meta.id` only in the sense that archives are named by leaf id; always prefer leaf meta id. +- Parent may continue after a child forks (partial prefix). Billing of copied keys stays with the earliest real ancestor that contains them; child baseline still walks the actual parent chain (spec §4.5.1). + +### §10.7 Same-session multi-file + +Common: active `sessions/…` rollout + `archived_sessions/…` for related rollouts. Same-session union must be **ordered overlap**, not unordered fingerprint sets. Multi-file groups often share a leaf id across rollouts; treat carefully (some “same id” groups are true active/archive; some are chained fork archives — use first `session_meta` + `forked_from_id`). + +### Inflation demo (one family) + +For `019f33ce` + child `019f3869`, summing `last_token_usage.total_tokens` over both files without prefix dedupe vs parent-owns-prefix: + +| Method | Sum of `last.total_tokens` | +|--------|----------------------------| +| Naive parent+child | ~28.8M | +| Dedupe (parent owns prefix) | ~15.4M | +| Inflation ratio | ~1.88× | + +This is the inter-file overcount shape on ordinary forks (not yet Ultra interleave). + +## Ultra / interleaved hunt (observations) + +Attempts to produce **intra-file interleaved cumulative streams** (multiple rising `total_token_usage` counters mixed so totals **drop** mid-file): + +| Attempt | What appeared | Total drops ≥50k? | +|---------|---------------|-------------------| +| Sol/Terra + multi-agent v2 forks (`4d90` family) | Fork copies, monotonic totals | **No** | +| Parallel-worker P0 prompt (fixture sanitization) | New forks `52e6`/`52e7`/`52f3`, proactive mode sometimes | **No** | +| Corpus-wide scan after those runs | — | **0 files** | + +**Conclusion:** Harder tasks and parallel Ultra workers on this Codex build produced useful **fork-copy** logs and Sol/Terra multi-agent metadata, but **not** the reporter’s interleaved gap-recount shape. Token drops are **not** required to proceed on cross-file provenance. Interleaved Ultra remains reporter-corpus-dependent. + +“Ultra” string hits in older logs were mostly chat/tool text / schemas, not a structural Ultra mode flag on `token_count`. + +## What local data does *not* yet prove + +- Ultra interleaved multi-lineage totals inside one file (the #2037 reporter shape / billions-scale gap) +- Priority / `logs_2` turn surcharge metadata on these `token_count` rows (not visible in the JSONL token payload here) +- Copy-stable event identity for parent-missing siblings; the added fixture proves the arithmetic gap, not that token-vector equality is collision-free +- Cross-session / cross-sibling `usage_fp` collision rate at scale (sample showed collisions across parent/child as expected; token equality is not allowed to become destructive identity) + +## P1 design constraints from the provisional corpus + +1. **Event key:** none from explicit IDs on `token_count`. +2. **Copy candidate:** ordered contiguous normalized `(last_token_usage, total_token_usage)` under ancestry. +3. **Fork-boundary oracle:** that contiguous prefix length `N`; `session_meta` fork timestamp for graph ordering only. +4. **Low-confidence fingerprint:** usage vectors exclude rewritten timestamps and file ordinals, but cannot drive suppression without stronger copy-stable identity. +5. **Future billable owner:** earliest real ancestor containing a ledger-accepted copied event; descendants state-only only after identity acceptance. +6. **Embedded meta:** first `session_meta` is leaf; ignore ancestor meta rows as competing file identities. +7. **Runtime today:** fail open for missing-parent cross-file equality; `#2066` containment remains file-local and non-closing. + +## In-repo fixtures and tests (what we built) + +| Path | Role | +|------|------| +| `Tests/.../Fixtures/CostUsage/Issue2037/archived-fork-33ce-3869/` | Sanitized parent+child from local `33ce→3869`; usage+meta only | +| `.../live-fork-4d90-52bf/` | Second parent-present golden from `4d90→52bf`; parent truncated to prefix N=180 | +| `.../missing-parent-siblings/` | Two children, shared prefix, no parent file | +| `.../ORACLE.md` + `manifest.json` | Hand oracle: naive vs parent-owns-prefix / provisional owner | +| `.../harness-smoke/` | Tiny install harness smoke | +| `Issue2037FixtureSupport.swift` | Shared load/install + sanitized event parsing | +| `Issue2037ProvenanceFixtureTests.swift` | Prefix length, oracle arithmetic, field allowlist | +| `Issue2037FixtureHarnessTests.swift` | Install into `CostUsageTestEnvironment` | +| `Issue2037ScannerIntegrationTests.swift` | End-to-end `loadDailyReport` vs scanner-unit oracle | + +Fixture timestamps were rewritten to **midday UTC** on distinct calendar days so local timezones do not map parent rows outside a Jan 1–2 report window (midnight UTC previously made parent appear as the prior local day and dropped it from the report). + +## Scanner integration observations (2026-07-11) + +### Experiment + +1. Install `archived-fork-33ce-3869` into an isolated Codex home (`sessions/` + `archived_sessions/` roots as the scanner expects). +2. `CostUsageScanner.loadDailyReport(provider: .codex, …, forceRescan: true)` over the fixture days. +3. Compare scanned `input + cacheRead + output` to: + - **naive scanner units:** sum of `last.input+cached+output` over parent **and** all child events + - **deduped scanner units:** parent all events + child events after prefix N only + +### Result + +**With the parent file present in-window, current `#1164` inherited-totals accounting already matches the parent-owns-prefix scanner-unit oracle.** + +- Child absolute totals are rebased by the parent snapshot at/before fork. +- Copied prefix therefore contributes ~0 on the child; unique suffix bills the post-fork growth. +- Parent bills its own stream once. +- `Issue2037ScannerIntegrationTests` locks this as a **regression**, not as a new ledger. + +### Pitfalls discovered while integrating + +1. **Timezone / day-key:** UTC midnight timestamps can fall on the previous **local** calendar day; a narrow `since/until` then silently omits the parent and the report shows only child unique growth (~3.3M in one probe) — looking like undercount, not overcount. +2. **Oracle unit mismatch:** `sum(last.total_tokens)` ≠ scanner priced units when `total_tokens` omits cached input; always compare scanner units in integration tests. +3. **Filename date filter:** flat `archived_sessions` listing allows undated names (`parent.jsonl`); dated filenames are range-filtered — fine for fixtures without dates in the name. + +### What `#1164` does *not* cover (next work) + +| Gap | Why inheritance is insufficient | +|-----|----------------------------------| +| **Missing parent** + two siblings sharing a copied prefix | No parent snapshot to inherit; each child can bill the full prefix | +| **Provisional family** billable owner | Spec §4.4.2 / §4.5.1 — needs family ledger, not per-file baseline alone | +| **Intra-file interleaved totals** | No drops in local Ultra logs; containment (#2066) is a separate guard | +| **True event-key ledger** across arbitrary ancestry depth | Inheritance is fork-point baseline, not per-event ownership migration | + +## Method notes + +Repro probes were ephemeral Python over `~/.codex/**/*.jsonl`, hashing normalized usage vectors and comparing ordered prefixes. Raw production JSONL was not copied into the repo; fixtures are sanitized aliases only. + +## Next steps + +1. ~~Add a **missing-parent sibling** sanitized fixture + hand oracle that exposes today’s `#1164`-only gap.~~ **Done** (`missing-parent-siblings`). Runtime cross-file suppression is deferred until copy-stable event identity is proven. +2. ~~Optionally sanitize `4d90→52bf` as a second parent-present golden.~~ **Done** (`live-fork-4d90-52bf`; parent truncated to copied prefix for a clean `#1164` regression). Locks a real corpus quirk: parent ordinal 120 has non-zero `last` with flat `total` — scanner units must follow **total deltas**, not `sum(last)`. +3. Still seek an Ultra interleaved corpus before claiming #2037 fully closed for that shape. +4. Build the event-key ledger / ownership migration path (including parent disappear/reappear) before enabling missing-parent cross-file dedupe. +5. PR packaging: keep #2066 non-closing; ship containment + provenance fixtures/docs without claiming full #2037 close. + +### Missing-parent siblings (fixture locked; runtime dedupe deferred 2026-07-12) + +Fixture `missing-parent-siblings`: two children, shared 135-event prefix, no parent file. + +| Metric | Scanner units | +|--------|---------------| +| Naive (both bill prefix) | ~54.4M | +| Target parent-owns-prefix oracle | ~28.8M | + +The provisional token-vector prefix suppression was removed before merge. Distinct sibling events can have identical `last_token_usage` / `total_token_usage` vectors at the same ordinal; treating that equality as event identity can silently suppress legitimate work. Adding envelope timestamps is invalid because copied timestamps are rewritten, and model is not reliably present on `token_count` rows. + +**Runtime fail-open rule:** when a parent file is missing, do not perform destructive cross-file dedupe from token counters alone. Each sibling keeps its file-local unresolved-parent accounting. This can retain copied-prefix overcount, but it cannot undercount distinct work merely because counters collide. `Issue2037ScannerIntegrationTests` locks this with two missing-parent siblings whose distinct models/timestamps have equal token vectors. + +The sanitized fixture and arithmetic remain useful as the desired family-ledger oracle. They do not authorize suppression until the runtime has a corpus-proven copy-stable event key, collision handling, cross-window family closure, and an exposed ambiguous/contained quality path. + +**Required before revisiting runtime suppression:** +- Prove a copy-stable identity stronger than token values; `reasoning_output_tokens` / `total_tokens` only reduce collision probability and are not sufficient identity. +- Build family closure across files outside the reporting window before applying the date filter. +- Add fingerprint-collision, ownership migration, cache-repeat, and affected-setup proof. diff --git a/docs/issue-2037-ultra-fork-overcount-spec.md b/docs/issue-2037-ultra-fork-overcount-spec.md new file mode 100644 index 0000000..c8531db --- /dev/null +++ b/docs/issue-2037-ultra-fork-overcount-spec.md @@ -0,0 +1,246 @@ +# Spec: Contain Ultra-mode interleaved-lineage token overcounting (issue #2037) + +- **Issue:** [steipete/CodexBar#2037](https://github.com/steipete/CodexBar/issues/2037) — "Ultra-mode Terra and Sol sessions can overcount forked context" +- **Status:** Implemented (rev 4 — Phase 1 post-latch containment + min-cap) +- **Affected code:** `Sources/CodexBarCore/Vendored/CostUsage/` (Codex session scanner) +- **Related prior fixes:** #968 (divergent totals), #1062 (repeated total snapshots), commit `45b68c34` (fork replay) + +## 0. Framing (read first) + +This spec deliberately ships in two phases: + +- **Phase 1 (this PR): containment.** Stop the multiplicative blowup and guarantee a *never-inflates* property. In multi-lineage files the result is an explicitly **conservative estimate** — it can undercount genuine totals-only sub-agent usage. We do not claim "true per-lineage usage." +- **Phase 2 (follow-up, fixture-gated): per-lineage accounting.** Candidate-baseline run tracking to recover undercounted totals-only lineages. Blocked on obtaining a sanitized real Ultra fixture (§8), because its correctness depends on empirical `last_token_usage` semantics that cannot be asserted from first principles. + +## 1. Problem + +CodexBar massively overstates usage for `gpt-5.6-terra` and especially `gpt-5.6-sol` when they run in Ultra mode. In one reported Sol session, the raw log reached roughly **268M** cumulative input tokens while CodexBar attributed **3.29B** input tokens and about $4,000 of standard cost. A single forked turn contributed more than 3B tokens across hundreds of rows. Pricing tables are correct; the inflation comes from usage accounting. + +Ultra sessions fork multiple sub-agents that: + +1. write **interleaved cumulative token snapshots** (`total_token_usage`) into the *same* session JSONL file, and +2. **replay large portions of the parent context** into sub-agent turns. + +## 2. Definitions + +**Lineage:** one monotonic cumulative-counter sequence (`total_token_usage`) produced by one agent/sub-agent. Ultra files interleave several lineages with no reliable lineage identifier on token events (`turn_id` cannot be used: cumulative counters span turns in normal sessions). + +**Replay vs. genuine context — two different things this spec must not conflate:** + +- *Copied cumulative history:* a child counter initialized with (or re-emitting) the parent's accumulated totals. Counting this again is double counting. Must always be excluded. +- *Context actually sent in a new sub-agent request:* the replayed parent context is transmitted as input tokens of a real API call, typically billed at the **cached-input** rate. This may be genuine usage. + +Which of these `last_token_usage` represents on a sub-agent's first turn in Ultra logs is an **empirical question** (§8). Phase 1 takes the conservative-for-inflation stance: after latch, `last` is capped by the contained totals delta (so below-watermark `last` is dropped). Phase 2 revisits this against the fixture. + +## 3. Root cause + +`CostUsageScanner` assumes **one monotonic cumulative counter lineage per session file**. `handleTokenCount` (in `parseCodexFileCancellable`, `CostUsageScanner.swift`) keeps a single `rawTotalsBaseline` and computes totals-derived deltas as `max(0, current − baseline)` via `codexTotalDelta`. + +With two interleaved lineages A and B in one file the event stream looks like: + +``` +A: total=100M → delta 100M, baseline=100M +B: total=5M → clamped to 0 (divergent fallback), baseline=5M ← baseline lowered +A: total=101M → delta = 101M − 5M = 96M ← gap recounted +B: total=6M → clamped to 0, baseline=6M +A: total=102M → delta = 102M − 6M = 96M ← gap recounted again +... +``` + +Every lineage flip recounts nearly the entire gap between the two counters. Hundreds of interleaved snapshots inflate ~268M real tokens into billions. + +Exposure by path: + +- **Resolved fork child path** (`handleTokenCount`, the `forkedFromId != nil` branch) runs totals-only — it deliberately ignores `last` to avoid replayed per-turn snapshots (`45b68c34`). Worst offender; matches "a single forked turn contributed 3B+". +- **Total-only events** (no `last_token_usage`) hit the same gap-recount mechanism. +- **Root sessions with `last` present** degrade differently: the divergent flag disables the #1062 guard (`codexShouldPreferTotalDelta`), so re-emitted snapshots can re-count `last`. + +Existing mitigations do not cover this failure mode: + +| Mitigation | Covers | Gap | +|---|---|---| +| #968 divergent totals (`codexDivergentTotalDelta`) | Counter *decreases* within one lineage → fall back to counted baseline | Lowers the effective baseline, so the *next* event of the larger lineage recounts the gap | +| #1062 (`codexShouldPreferTotalDelta`) | Repeated identical total snapshots re-adding `last` | Only active in the non-divergent path, and only compares adjacent totals; interleaving disables it and defeats adjacency (see §5.2) | +| Fork handling (`forked_from_id`, `CodexInheritedTotalsResolver`) | Separate child *files* replaying parent history | No concept of multiple lineages interleaved *inside one file* | + +## 4. Goals / non-goals + +**Goals (Phase 1)** + +- **Never-inflates invariant:** for any input, tokens attributed from totals-derived deltas never exceed the maximum raw cumulative total observed in the file (fork-inheritance adjusted). No sequence of interleaved or re-emitted snapshots can multiply usage. +- Exact re-emissions of previously seen snapshots contribute zero — including **alternating** re-emissions across lineages (this is where rev 1 of this spec was broken; see §5.2). +- Fork-replayed parent history stays excluded (existing behavior preserved). +- Single-lineage files behave exactly as today; all existing #968/#1062/fork tests pass unchanged. +- Incremental (append-only) scans resume with all correctness-critical reducer state and produce byte-identical results to a full rescan; the optional seen-snapshot FIFO may be absent without affecting containment. +- Multi-lineage results are explicitly documented as a conservative estimate (undercount bias), not exact usage. + +**Explicitly accepted Phase 1 limitation** + +A smaller lineage growing beneath another lineage's watermark (e.g. 5M → 50M under a 100M watermark) contributes nothing in Phase 1, even when it supplies `last_token_usage`: the contained totals delta is zero, so `min(last, 0) = 0`. This is **normal Ultra behavior, not a rare edge case**, and it is the deliberate trade: undercounting bounded genuine usage beats multiplying it. Phase 2 (§7) exists to recover it. + +**Non-goals** + +- Per-sub-agent usage attribution/breakdown UI. +- Changing pricing, priority/Ultra cost splitting (`CostUsageScanner+CodexPriority.swift`), or non-Codex providers. +- Phase 2 candidate-run tracking (specified in outline only; separate PR). + +## 5. Phase 1 design + +All post-latch token-count accounting uses the shared tracker and delta helpers (§5.5), with correctness-critical state persisted for incremental scans (§5.6). Rules below are the shared policy, in precedence order. + +### 5.1 High-watermark containment (load-bearing) + +Track `rawTotalsWatermark`: the component-wise maximum of every raw cumulative total observed (after fork-inheritance adjustment). + +- **Interleaving detection:** an event whose total has **any component strictly below** the corresponding watermark component latches `sawInterleavedTotals` for the file (persisted, permanent). Mixed movement (input ↓ while output ↑) cannot come from one monotonic counter, so "any component" is deliberate. Legitimate single-lineage resets (compaction, restart, corrupt log) also latch the flag; that is accepted — it converts a potential overcount into an undercount. +- **Never lower** the watermark or the baseline on detection. +- Once latched, totals-derived deltas use `codexContainedTotalDelta` (§5.3.1), not a lowerable per-event baseline. Lineage flips cannot re-count the high/low gap. + +**Supersedes divergent mode:** once `sawInterleavedTotals` is latched, `codexDivergentTotalDelta` (whose counted-baseline fallback *is* the gap-recount mechanism) and `codexShouldPreferTotalDelta` are not consulted for this file. `sawDivergentTotals` continues to work unchanged for never-interleaved files and for fork-parent snapshot resolution. + +### 5.2 Seen-snapshot suppression (optional precision) + +Maintain `seenRawTotals`: a **bounded FIFO** (~64) of raw cumulative totals for best-effort exact re-emission suppression. + +- Exact matches can short-circuit to zero before delta math. +- After post-latch containment (§5.3), eviction cannot inflate usage: a re-emitted below-watermark total has contained delta 0, so `min(last, 0) = 0`. +- Therefore the seen set is **not** load-bearing for correctness and must not gate incremental resume. + +### 5.3 Counting rule in interleaved mode + +For each token-count event once `sawInterleavedTotals` is latched and a `total` is present: + +1. Optionally, total exactly matches `seenRawTotals` → count **0** (precision optimization; not required for correctness). +2. Compute the **contained totals delta** component-wise (§5.3.1). +3. If `last_token_usage` is present → `delta = min(adjustedLastDelta(last), containedTotalDelta)`. +4. Otherwise → `delta = containedTotalDelta`. + +`last` alone must never increase counted usage when the contained totals delta is zero. Smaller-lineage genuine `last` below the watermark is an accepted Phase 1 undercount. + +#### 5.3.1 Contained totals delta (not plain watermark delta) + +Do **not** use plain `codexTotalDelta(from: watermark, …)` after latch — that breaks #968 “resume from counted baseline” (growth below the old raw watermark that still exceeds counted totals). + +Use a dedicated helper, component-wise: + +``` +if current >= watermark { + delta = max(0, current - max(watermark, counted)) +} else { + delta = max(0, current - counted) +} +``` + +This preserves counted-baseline recovery without allowing high/low lineage gaps to be recounted. Bound after latch: + +`counted ≤ max(counted_when_latched, subsequent_watermark)` (and for totals-only streams, `counted ≤ max observed cumulative total`). + +### 5.4 Fork children + +- **Non-interleaved** resolved forks keep totals-only accounting (`45b68c34` / #1164). Do not apply a global `min(last, total)` cap there — established tests require totals-derived deltas that can exceed `last`. +- **After latch**, resolved forks use the same post-latch rule as root sessions (§5.3), including `min(adjustedLast, containedTotalDelta)`. +- **Unresolved forks** keep skip-first + `min(last, totalDelta)`; `unresolvedForkTotalWatermark` is a presence sentinel while the global tracker supplies the delta baseline. + +### 5.5 Shared policy surface + +`CodexTotalsTracker` (watermark + optional seen-set + latch) is shared. Post-latch delta policy (`codexContainedTotalDelta` / `codexPostLatchEventDelta`) must be applied by all three consumers: + +1. root / non-fork parsing (`handleTokenCount`) +2. resolved-fork parsing (`handleTokenCount`) +3. parent snapshot accumulation (`CodexSnapshotAccumulator`) + +Otherwise fork children can inherit baselines computed under a different policy. + +### 5.6 Cache: persist correctness-critical state + +`CostUsageFileUsage` gains: + +- `lastRawTotalsWatermark: CostUsageCodexTotals?` (**required** for interleaved / divergent resume) +- `hasInterleavedTotals: Bool?` (**required** when watermark is present; partial XOR → full rescan) +- `seenRawTotals: [CostUsageCodexTotals]?` (**optional** precision only — missing must not force rescan) + +**Invalidation:** regenerate `CodexParserHash`; clear `compatibleCodexProducerKeys`. Legacy divergent entries without a watermark force a per-file full rescan. + +## 6. Acceptance criteria + +1. **Exact expectations (primary):** fixtures assert exact counted totals / row counts for each rule branch. +2. **Never-inflates property (merge bar):** generated totals-only interleaved sequences satisfy `counted ≤ max observed cumulative total`. +3. **Floor:** fixtures assert a conservative minimum so a degenerate ~0 parser fails. +4. **Manual / real Ultra log:** no multiplied-gap inflation; satisfies the formal containment bound; above the fixture's conservative floor; plausible relative to the raw log — **not** required to land “near” 268M, because Phase 1 intentionally drops smaller-lineage usage. + +## 7. Phase 2 outline (separate PR, fixture-gated) + +Recover totals-only / below-watermark smaller-lineage usage with candidate-baseline run tracking, gated on a sanitized real Ultra fixture that establishes `last_token_usage` semantics. + +## 8. Prerequisite: sanitized real Ultra fixture + +Needed before claiming accurate multi-lineage recovery (Phase 2). Phase 1 ships on synthetic fixtures plus the containment property. + +## 9. Touched files + +| File | Change | +|---|---| +| `CostUsageScanner.swift` | `codexContainedTotalDelta` / `codexPostLatchEventDelta`; tracker + accumulator; post-latch policy in all three consumers | +| `CostUsageScanner+CacheHelpers.swift` | Persist watermark + interleaved flag; seen-set optional; incomplete-state rescan | +| `CostUsageCache.swift` | New fields; clear compatible producer keys | +| `CodexParserHash.generated.swift` | Regenerated | +| `CostUsageScannerBreakdownTests.swift` | Containment / cap / eviction / cache / property tests | +| `docs/issue-2037-ultra-fork-overcount-spec.md` | This spec | + +## 10. Test plan (merge bar) + +1. `codex interleaved cumulative lineages do not recount the gap` +2. `codex alternating repeated snapshots count zero` — containment (not FIFO) keeps repeats at zero +3. `codex totals only growth below watermark is conservatively dropped` +4. `codex single lineage counter reset undercounts but never inflates` — preserves #968-style recovery past the peak +5. `codex interleaved fork child caps last by contained total delta` +6. `codex root interleaved caps last much larger than watermark delta` +7. `codex fork interleaved caps last much larger than watermark delta` +8. `codex interleaved replay after sixty five unique snapshots stays contained` +9. `codex interleaved totals only sequences stay within containment bound` (property) +10. `codex incremental append preserves interleave containment across boundary` — full state equality vs forceRescan +11. `codex missing watermark or interleaved flag forces full rescan` +12. `codex missing optional seen set keeps incremental resume safe` +13. `codex divergent cache entry without watermark forces full rescan` +14. Existing `#968` / `#1062` / fork replay tests unchanged + +Regression: `make check`, focused scanner tests, then `make test`. + +--- + +# PR documentation (draft body — Phase 1) + +## Title + +Contain Ultra-mode interleaved-lineage token overcounting (#2037) + +## Summary + +- Ultra-mode Terra/Sol sessions can interleave cumulative `total_token_usage` snapshots from multiple lineages in one JSONL file. A single file-global baseline then recounts the high/low gap on every flip — turning ~268M real input tokens into ~3.29B (~$4,000) in a reported session. +- Phase 1 makes inflation **provably bounded**: a never-lower watermark latches interleaved mode on any component drop; post-latch deltas use a dedicated containment helper (preserving #968 counted-baseline recovery) and `min(adjustedLast, containedTotalDelta)` so `last` cannot grow usage when the contained totals delta is zero. +- **Single-lineage and pre-latch fork behavior is preserved** (including #1164 totals-only fork replay handling). The slow JSON path and fork-parent snapshot builder share the same policy. +- Cache persists watermark + interleaved flag (`seenRawTotals` is optional precision only); incomplete critical state forces a full rescan. Parser hash invalidation rebuilds old caches once. +- **Smaller-lineage undercount is intentional** and deferred to fixture-gated Phase 2. Latched files are a conservative estimate, not claimed true per-lineage usage. + +Fixes #2037. Related: #968, #1062, `45b68c34` (fork replay). + +## Behavior changes + +- Interleaved (Ultra) files: no multiplied-gap inflation; after latch, counted totals stay within the containment bound and `last` cannot exceed the contained totals delta. +- Single-lineage / never-latched files: unchanged counting semantics. +- Pre-latch resolved forks: still totals-only (replay-safe). +- Post-latch: below-watermark smaller-lineage usage may be dropped until Phase 2. + +## Test plan + +- [x] Focused `CostUsageScannerBreakdownTests` / `CostUsageCacheTests` (containment, caps, eviction, property bound, cache gates) +- [x] Existing #968 / #1062 / fork replay tests +- [x] `make check` +- [ ] `make test` +- [ ] Optional follow-up: rescan a real Sol/Ultra log for plausibility (not a merge blocker) + +## Notes for reviewers + +- Design is lineage-ID-free; value-based multi-run recovery is Phase 2 behind a sanitized Ultra fixture. +- `seenRawTotals` is **not** load-bearing after the post-latch min-cap; missing it must not force a rescan. +- A real Ultra log is valuable validation, not required to merge Phase 1 containment. diff --git a/docs/jetbrains.md b/docs/jetbrains.md new file mode 100644 index 0000000..3fe76d9 --- /dev/null +++ b/docs/jetbrains.md @@ -0,0 +1,70 @@ +--- +summary: "JetBrains AI provider notes: local XML quota parsing, IDE auto-detection, and UI mapping." +read_when: + - Adding or modifying the JetBrains AI provider + - Debugging JetBrains quota file parsing or IDE detection + - Adjusting JetBrains menu labels or settings +--- + +# JetBrains AI provider + +JetBrains AI is a local-only provider. We read quota information directly from the IDE's configuration files. + +## Data sources + fallback order + +1) **IDE auto-detection** + - macOS: `~/Library/Application Support/JetBrains/` + - macOS (Android Studio): `~/Library/Application Support/Google/` + - Linux: `~/.config/JetBrains/` + - Linux (Android Studio): `~/.config/Google/` + - Supported IDEs: IntelliJ IDEA, PyCharm, WebStorm, GoLand, CLion, DataGrip, RubyMine, Rider, PhpStorm, RustRover, Android Studio, Fleet, Aqua, DataSpell + - Selection: most recently modified `AIAssistantQuotaManager2.xml` + +2) **Quota file parsing** + - Path: `/options/AIAssistantQuotaManager2.xml` (macOS/Linux) + - Format: XML with HTML-encoded JSON attributes + +## XML structure + +- `quotaInfo` attribute (JSON): + - `type`: quota type (e.g., "Available") + - `current`: tokens used + - `maximum`: total tokens + - `tariffQuota.available`: remaining tokens + - `until`: subscription end date +- `nextRefill` attribute (JSON): + - `type`: refill type (e.g., "Known") + - `next`: next refill date (ISO-8601) + - `tariff.amount`: refill amount + - `tariff.duration`: refill period (e.g., "PT720H") + +## Parsing and mapping + +- Usage calculation: `tariffQuota.available / maximum * 100` for remaining percent +- Reset date: from `nextRefill.next`, not `quotaInfo.until` +- HTML entity decoding: ` ` → newline, `"` → quote + +## UI mapping + +- Provider metadata: + - Display: `JetBrains AI` + - Label: `Current` (primary only) +- Identity: detected IDE name + version (e.g., "IntelliJ IDEA 2025.3") +- Status badge: none (no status page integration) + +## Settings + +- IDE Picker: auto-detected IDEs list, or "Auto-detect" (default) +- Custom Path: manual base path override (for advanced users) + +## Constraints + +- Requires JetBrains IDE with AI Assistant enabled +- XML file only exists after AI Assistant usage +- Internal file format; may change between IDE versions + +## Key files + +- `Sources/CodexBarCore/Providers/JetBrains/JetBrainsStatusProbe.swift` +- `Sources/CodexBarCore/Providers/JetBrains/JetBrainsIDEDetector.swift` +- `Sources/CodexBar/Providers/JetBrains/JetBrainsProviderImplementation.swift` diff --git a/docs/keychain-allow.png b/docs/keychain-allow.png new file mode 100644 index 0000000000000000000000000000000000000000..ec2befce5210f67d9078c615dfc108c14960f116 GIT binary patch literal 164096 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⋙7RjNzzD2Ob~1I)<+xj zGyOW2I``pv+cY7iP3XeG;4@ZI_3zR$?p0M+u<&h+;Ow16w4k3313>0s6Ul{KOUBg1 z6#D8iaVzce!nU?C-k8kjz1jGTH62X>K>Po)D0_=+wy(FBk_OUl=B09EWF$}}LRVM! zY}4G@y2JJQAZkVE`EI@F3#-1aW%*jOf!PCWP{D+kgWI8oA2Hy_-Yz>WIHfF9tUA4d?#|-v%*`SdI zp@S0=mYPHD6P`k8Pzb0xCt0Z`UYyC4%COsf>y_4-YjI zWq}V#&_X!>m9wI5fNvzb@!-SVoqteTVwE%#1H;#^Ut8R6trZj|^Q59!bbd@NEiElB zy4)NswhYYTAfOctijO-2w$D!ZegMpd9UGWTa;9Pqz8*)gnBZBiH}HKH*%M);zHaa+ z&>%w)KmQS9P|Yf}-P7&{CQrdPq6QC%Qc>4Qj<4F>7>=96A_%tXTXB9vC~By%`nrw` zBQg~YGQj}Il*MDst#(PXO}}_d6PFh>s6FCbG+H(s=)>RVY0yihB*fMi6mHDX7sSen zjj*G$YZ3-7YXJquGmE}TT90z97y16HlDcygGC=NI#cP1)0T&SNS!bhP6GVbfuO5+<3%XQPew*2 zC@9Fy&F$tPuVgoTyxipG`QkUja2K8qw1*!-y&^U_1n@c(=jT%~aEz?1Y_;DCRqvJq z7Sj<|@^Hl^nIpoqaY>{25iJ8FjzKH@v~NC_?K$WNma#J#2oekF6`g&U9z?j+_<$`S zd@cM2Ne_LJ@PvOPS@y#lUy|)9L4(4uatas`HsmW*d}PX5SRYYRI~Yx>J9>7~F+d5s zGm^Op?~36%TSPjs&g!Af2KW$R5w6Y`J_vn3E&M##v|`fdV`BjE{XIvDxvpblyhU}o zUMupQ3)w%*TybPyAt~LPUd7kXPfV;=d3GT&A%Qc?!sYI4BaT)fQ^*UIbGJVXueeOK zGYzuhaZeW08o4}nCo)`IAk7!#NqKod3FsG+P*Nt0NVLhqlqG{B7jFed2^jx}lh74g z?nfUe*x1;pso@SjnW;N|v>?y{MSI&rs0>Dt3OS#3#b(YfEHrw(de+l&r;UqUi5rYB+M;o zyeqrRefd=Mxgr9hv-9URrdqoyqW|xb@g;eXk;Ka*Ou5n z<~1k&eRM(k>kBafhmlRox7E;%l=BlDiJjKh6VLn7-4QSaxDz6(*El+;LN1WB-b zcxZ+lMa&SwDXD<_U3GFSgk38T4f*pm@H0qFN9T`uT>dh#x$!sF1eKreUjPtM>11iG zBX6x>m{mzR2is2n0+%xCS0SaB;S&)jhf9i20li+@evwKYIsWdj*ZBA`WW~DaGgH%= z3vDYgBrptlDa(r%Z8Hta-ZtmAe_!M);|RK8L5x&~m15RlwS1et%;wti!FB={@Vs4C zhZnT=SY38G55Z+-O=>7A+DesgjTQb03I8Ru>BzT`pYQyYs!HrNRJZjNZsk@#-oN+S z7<#lpR=ZN~mpk}yJZZ8V>#$-X>+8Ycv3pHJUTMp~v165f=Sw5O`#BB$XRD*6KQZS& z6&YTJG7|?0njRH9Fmi$Ntv9nB1)zKus-F=E-z3K0z9_mJ8{H?^aOvMSZqA$+p*DwC zphysLTeE?;S3!qX6q|@YJy6Og|8%a0g0M^Ir(*4H;i*$HniV&RW$c5%WtH9%l~hxp z={Fu7Qo_1O-3r219s0suL{eA0(}s!T+Ak+1Nf(#OUp^hj+6(+L`4i%Xf{F&cEX4z4 zORT%%D3v3trr9o(>`ZFO0X4%|H@5kDhymqW-3L?7#{pa4P`M6T8~61a58F_mW830O zDF0RsL1@s^DiPCi)3)FC1H9^{m(B4{#*iX30`gD{fr+3(I*~yxl5)Zmt*a$24-LPG z-Po@(@B3dfJ_h^^SpJoKy5>j1FU=iZQkLJco6}yoF`&M%< z!~-4?HL1o^7Dn{6AA8^bbFws$`}bHr)%k8H!YRqw7#{K9viaSQT@jZaLfm_r$RS=M zD*Rs;>Qa@HhCF-GuG*hWqw?$O|HRGzOda##&BgZIHfox~FRKe+gp?kK{)?H1Wz&{) zJB6prL`hzmdqf~flcu|Ul3H47>BjXxi`6?m4)K75+q8etrg1W?{l@{^b4U{s*xW<9 zQiV5CrZ1z*iD>m~?9eW)4b@no&d$`cl%phw{%{!Kl$n2rD4PsZ0AQykn;tg6ZX9MwFOf3Co1DtDhmD%SY%LGVvUTyX-w9$VGrBf`c8;D zu?x4|X_Y7$mzYw3?)7>vWj_}cZ%dhC@95+}CqAB1`Hils-13_Z9-#90wcqV-Z%YBN ze|UKFIDcH9wN}4>7lQQ+1M?P1?||T=U%!Y0LVVEAeBiP)z=tfq%ZC;Xvxzu@#@`^G!9cvSH1qpPa#djDy&myPeKx5}|}Zdr9 zrKG+vDc>qCtc~R4u;6>#kMk_b|1`Y+yL8q}VG?QR^g&3FU{s@0`EV>$P2#}$qh<>4 z>VXB`y)bep0V&@S|H%60(;MZ9(*l5o{bf>-g4fOBt|squebz}u4!K=rrN`se-?8xh zTOBqb^idbT!QIZ)OIyB)v2pplh7#^VT+Uham`7+n-5}fD)~V8~b$B=4b!8wn7a5G` zkS>%3+AKOaTAHmn>v)_${iZzICzPNE5qWz&rHRRSyU4eUz*SGFbXnatEH6oQjhMep zRv{ajla)*%rS2!qbz`3+A1;>tn>7JisR~2Qxpe%3E&uJ*A(NH!oSqXJv8d&_<5>Rr zrFiTJkpE$4U>X&8Y*e?}{+8ss?R;MUK~kKua=#O{Yn&#**tm9nIFpBSvpE69Rk@~i zZB3hwB_3$99m&gM0BB)>#x%_8aie+8$=)C}mY8}IPst*du64ANr_;-N1BI#m8Vn~B zdoSf!SwNjb_U<*ymt*D=BSQqDt1f*`6OQIh?JYxf{t%{{kFa)QysiZ_V*0ortiS(!PaK0#b2#(2BC4z{9OZ1 znw*g6oTZC;Cxr?CA*z80L}~{Bg;+Zsp^zoprn$|6hIjt$QIavEc!&nb*^NB}7&&6- zW)YG)79ZG&Ou`+B%yy@;FJwY^=3dS7`@cOtOgkY4C}v!=yJ@>2yz4p_b54TfaXCkL zV`caD`?awsP04oSzL{IoNQ5qjKG;8UV&;{CG+gx?@y?2BymL>Iu06Tvu6}WE#oY!W2TgJC;f&nnGkt*iSndm87VAt!@j? z9yRflRb~2mx^+jI?5!*o_JBED3P(kQ<>{_7#P8L_fFAs?!Jl%4K_;;+D*=?~iob?| zHQH8OS!)UdCZ3)<=h4@!_xb5oVbp2dF$PF}P$D;yO5(=s=*sTrEKO-k^dH)_>?9f5 zebmIWCv3gp9NCEwq@)z~KU^bAQDpc^ezGa~@J6jRRi)^C(UJWmoVdUOib4+m!XPPf z?UG`HPGp00d9N`;z|r>QFSfLhnE4RV4K}9ics0y(>~Mplw9DzkG;J=X1%VnV)Q|a) z=>MY)&QF|x*NkFlKTNjnUwCO6n21xtb8@mn;%>*e*{L*A5d^F2IG1a%N=IvhFmu!CS>?2w zIz}8dG|GMCOaefn(AMxMEDb_y=d1F*Iim4(=EIm_QH1ZgHjdZl5DgJpoL&WkKERt{ zpt61PTke7K?-x5>Y!ZSQDbZ<))D?WRLjJrxvC_K6!>%aWGia1QkSskPiIysZ4KjB?qFt&_U_xIroLPb+C?k4%=s zEj3VVUb^Cl-Y_n>oS~{~AlHggye5@Ll%L1C3tAutp!q#NsZc?|nXmQsXkO#P3)zmo zYHX}7oZ;(R0$BCPqR=q zdsFxeUkvQth6pi^j^Y5PT{(ug-~SwWtAxrt5S-ok{)_Di8-gbUtX4)QWn2ag@Ch`~ z+HiTBihqij;7;&SPT60!4&{*y1FbHcpOb@ovEA$GTtGc}MNr`;t_CjV2e!auw^)$r zt`F|U<}}LJ7`V~oA1w^|;){uV6^@6nQOwp!8C} zB9cw?VdesufP}&qsT7zNQtrpSio#HDX|n*}Hhrh~p^7NMQ1wv5G(@||rLT}SuDMk2 zSUfzMDSTpCD4U={wmP6bbHS5F3_uNy*-^T_>E(El7$Eg3LnKfLj5y-g@r6!AEW9e4 zwX#}*YZZ^n#O@Q%({*E!^y<+z_HKV$szBvyyvZ-)tCB#WEwG9%1^jmlvLrEjDNQ^` zNRV2R%50Sy&zDS|j1PGDAxL44bmxej{rst)zhu_}eLpbw!W|X{e{&AM4a`l~teP0d z1%Lj+SURa?yOG;3e#R%R(v-_wW4q^17xYC6?)N#C{yJJ+J3So~=?0I?4>$nJ1F8+s zj^ZYVgfRw5ObHN*{p=ki*Eg}|{={>hmBE*U4rbDMx(3i;WNdB6IZDHpY={plix_U~+9l?^8#9;n@6cTbw1@q#OLBjQ%nN zOgy4wGJgg?4dEnRA_2&>27%>xJ z;Bb#)P)1Th06irYhq?ap)`w>jRc{CIvI4>+ipmf2Tqmr1R+ z`=^+-M!o~;q@A`iQn0R?x0&#jT$hNMF$XKh4dee_2UUuZ3@AdYW!blGVCo9(Km&*= zD>!29)StTE8=pAg)J6MA0iA)MYomC4r@riT$el0UlWRBMm>>b?ad%mtzGV^yqEq_x zg<`p)WCdAYIuc|#EgIj;-7H~S(l<2Zg#?Zc#xBWRUUj{oN)aa?!T209e^t=ll28}o z*`+c|>xjeA@Bj90N5L0F7gGj}F9u3+2gSp5PLV1PYGGhu5F34h1=rI;P*}{ASFq~2 zh(uj@v9Xo9og`vF*DnUtcbX>YG1cvg)U;X)sZDUZk&%G}dPyw$>a*-CG&o7j=b=di ze944C7Hk+9-PYadMxpP?#DUWC-s{>Q(sdsM_XurSa z)z%SJu&2&0sx4ldkMDM7I6Y->5JsyUCl9D$by^FbB&L@uq54ZKz>hlD8l2D}gkn&O zCkl!Y5QYWONi`<<`^pV{60x!PB+NzNC>HN08S&gmu@JxX^;uGA9gP@>*^17o671#N z!ffb^li>FO3KQcSuKWXjirg@57Js)4O_Co3wzcaRtl#XKa12nCpE2zNnSKv&Vf%!js#!LRD>Q%(A{XK?%*OV%OH@Kt<|Rna7LeS3`-g~A z5i-zse1BAcXivaL!YPOH#eQ}>(WQr21Fa$#55L0q~L|pzKr-enMBPadp^gs)2*Xss;n{+6LwTqG5FlnC1J?TUd7^ zK|5n`(oT=16TKA<5tDqLUgcntK;bazvv~+p`(c&(WCdz zx6MdDU|7(Wa8eGb$VYq}ijjWczw5wBhC41R54O1&F3YbpWfOS(y>}Km!&tYAt|W+o z?CZ<i6oZ_`%=R8t+z`&pQ3eilO{P z!HPc@Xdy+ERTkF#8K=d09}{CZ^xDAVfP0-DuKVlmL>9M!I6Ltl6Ko`G7T^0jH*D;f zN%MvmoJb7*@gF`_@{0mx!U@^)ZS1WqT9(cOW5a^7+|K6Tk)b96asXC!(~HdqGcnT< zL@MZ{-V-w^0TXs0DWLL4O@g%wdOp4G{P_k#JjNU*<4HG<=i;NmqEnI1yC~S*6P2-<%Qubm8Z(QEx!E2^jyo7Fz5|Zsc}q z2TP5x4lWWHDOjK0-S%NSej0qhu5h5-*i%BERV=TKip@8oDAtCQPK*&?Lp1Pzod_qo z-Q%C3<~sA$cD5?t529{&9SVq|t0aX1C3UTUtcfDx*)*=g>g^AzMK=}1AF`{t>AF?Q zYB5#a6}G#w)i#_;B2;k=)uHP3!<|>inw(oep}Z<4ns2{ZU2iO!UigGut(Q>feCtp z94#)WNb@YWjCd+Ae!&x)PJ#BOv#{}K^ZEWO-v_<%XE;PcvS>aeMSrLd~eU445#MPFI9`_<%OmJyCAY5)=V2+l*RP0)o^@OL8k;AK$s_13viM05pe}6BjuSb|)Q#vGcb;~* zU8gUJ6_p0OBK_RwxDzx{f}gShCVviPH-szrofSq{|Aq0eCo(CbXy>&{_dhO^Mn^V) zlZvT6mIUKQB>$I;iRvPhK@b@ zVtN!%y?Z35pvxl*h3%!=l@CzdwdTVN@x*uoQ`EE~Ec5PNF8n;J#508wx&++E_^A`Y zN7362WUeR}@5Gkl}f*pkYC&+b{B?)}7 zuV-!fuwp?AesiHvH|HL-MfjRPg*5+T^ zaDF~n3?dcoAPDQw;-z5_yZEZcjDeT1F`vMQW_>zQuwB2^R*-RGQ5gGA*gO~{iir&YE~J?a zey3#)AwbOO`fFK~>AI|?lYK!@{Dq%fO_tQ74 z|ISnu>=bBKAI9*jbeDP2P-1_|0u>Uff=(j8?~Ux>MUQ%|Nk;x>evMCtr)^nzJd-?` zUNpwR^GZK)LResfjbL#l3Xy!ein&w6MfOzpC9x@m+m&G77(owsTf7N}O*TWrqTLck zPNo>z4swtBaxqam8VpvQ@Hrj(Vr{+VakA2ya1!)5rm`By6MwD*!{!ZGi7fm1d167T z(>(>nFAqi+6kTec%Z~{&bg2KGPd;;Fjj}-Pis#=9lPF@&2s@wm@7d)#%Yg5%ybgSg zr;I4C$9fd-8vFdH%An{X`@=a^PH%TNYja_5JV&S%545Mre{*(_)U8_NFbnWJ4n~^` zO*~ibyWX$)JoX8#(g{Guh)7cUU?)wJCCSrQsAdnF5)a8wlgMO6ga2Z^{+_%j-z(xH z2x-)%V&N>;aebE9tw5UJb`TYJo%{Z=UlxN`zV7n$m8p3KQ)RcB0uv?bry0E0(LOm} z^|D>m?Aq)sD;wfxN{X{zYqMdueQ@xwaB?AGvhs4WlVhoD`zoifnZ2^E0a8U?(DfJ;$Tgjt<0kIyvg46r-*|FJ z|7|iGq^aRXOcy4}G$m1wK6XO9POInhiGmRQ$?x{%U-jH`UuPv9by@>e^moA5;N67V zxH<<-?%NbDk3dTtASm9E7=Cx`c5Sp|yWYVw=bz*n`L>55(8w?lPdV+4 zxWKCbF-g&-CJjjjUC|}~p~E#DetIBg{`M~r9(=8aT~%y@Nr*bQ+>WREjs)hIBFo|U z0cB-vd{Agz_)-LeK$4}gA%fs__%R1$HkQh)9RYYR$@~Bh>p8o`aL706bbWcYjTicF zp8n-jEz*H6FpPer8t|FaCqDh*&9ad7SpRzIE@2dmZ7_d^n}%8Tvfb=baH^=bgkJLa zrbNQ5oAVuQN3ZoEGA&HNG2(FEkf+*bD-@i=E0^ zog}M@CSp`A#H`_Q(A!ViH@NIs1EOE|l8J>*Bf4Kix)pIQ@mM~M4|SnEV&qA>Jv=l6 z0^u2>-3Z;lEp%z8qz8S(=ogJW@cuq}PxW#9SVLt0bV z?~IF)C%7K38}?$TG=5KWAFEh)8Y-LG8E9z56Ldy=SJG#?mpc8_KkDWr5s;qB$=&fS zVT%;td&3LK6!c`lI4L+eN^b`nDk-(3`Bh4O7I&j;$nD~7OvUFTVAm}MTuF;s>56Xl zh=>I>XG1d7ejfmuK25$@eYy9t;>ZM{w;`KME4(r@)g*%EY@KQUuG~_9lOx~F&Gpht z!2IH4VOOKqb61d;tT;K&?+Da-;SNv!#)*wj!zGNhR+_k*hr7di{p};Qzje+D)0!;l zb({1uDQ)`ko6j!$CHMWLpKctE=NT$R#pO`6x`+MhxHfO+$ zb4D_*E!Ntm${cm}w&vpV!f*kavC7ICRl`AzY$}ZL?G7bBkfjV`&Y9f%Dwdn<8VegI zib1MAGmty>nqpH0iGrl8tQmz`9_o|#y4D!DlNmx)x_xOvZYTT;YPsm@;S31-@6R-k zkBJ#Dt3;d3E*YfKBIjI>et-;VSbf|Wn~c_8o?Gx_xKx%4WS^`t|H<_igMNz%p`r29 z48Z-_q(Bu=C2`pIM0J7jDHp&{Mo=e{=#IQf3Go1eE{G=T+M@wRK%NyRQ5Ov-)kq9?$s-F%Fqx1vvt&f%fXvVA zQfdBx-z=2UoT8B->71p22EUlnRKmBy>M`YHcKg>ol?}@61?n^kVR6{x#F7bq3bzBv z&2Qh*s7=)3Fm3}0Nxr@RHl}a1Te&g=(0T+trBGSUYG~hGQ~e`ZMeq;k;cwOc4|CXo z+}O)g$9F@GISMDVAAt!hl&-=Fy(BaXTVR&^@QN#i zbG5=UhEk6vQeMMg zw~-qi6*|_=K?ByT(5Z=p5B}8lc>v`-JwIglwUmH24yXh6b0!;Awik2s<-gm$BT>ul zsG$;G=~&rlEWl?W&VL!g;V1=|Fb~U&ZuAy=h&`a0B@W+JK#&mRE(aA1UseK9zG~}I z$KT6-dbVuoBm3OWM#-p+Ye)LOr!5C&Qb4v?Mfa)MY`9;@S}yE#k13EH?k2x*m_l^1 z2_dEjvI#Z>EDUuE9>vZsm+Q1^fh)S;vg?Ke<Xxj1d`8`vJl12`P=&&qhfC9AokCMYB7G|obNAqXJFr)<#tF+-gvwW@ZJ`OJC(Z__@Wp^%n8i&9)omoDPa9Sc1IV5wN zLWQj6l5_|ZZTf^xicEr*EdO}grxNi&yrQqc_+M42ixCB3Sah^7h z-AL;xH3Rcxb+B;ix(lAFs(OkNP`ZM5ZiZqqMxp@az1Lf0LKRN+B?l_xrp=#m|Jt;K ztxW5|xZLMdZeH0k292Nw&L}URqcmCz-YA&n%k7`}d8T6PuIqLN_B#U)(_2^2GjfGU zik5I9xrPxX z&G(JLKCvD!Y_zgQtJj!!L!|=;5VM`~ZQ_*Xe;6(YGvvYF2o4k(&#r$5Ger7aTYZ@# zNR42IP+`y8k)oPpW5FaM6Zu_5J~*if0U`R9>n;E->0DhAC%^z7Ypa?zMI*rdop&fz zoFT8NAI{ci2PJ+PFk)%iSl_Q^Eg4 zzw}fLtmqo$0sYp49^FTGE=w~ESA|N#3dJhs8I*om+lm~T25Qk2d1?&F8&-nIVjbV} z1~Is(Sx|#`d*5{DcreqDl2aq>(?aG3)dE+xM0ZXDC(&Pw?|XN4cHR%!_w7hbfjo$F zdHYKz2Dy#tv1LSR@?t7+u-PPX7E=N^30etTMCf!u-%(JO1f`CNiM0~)RHeULF>@)& zztd#nO`v?-0w>2-a$TXl8_+4eCgP@08fqJfNh>LgEdv2Blf3KV+VW53GjOT><^Gq# zySkoZc#1_vx+!I;p2u4*Tkt1d5j@)WGjZU0Hzu!_wSpsFDeX zH%bE#)C11a{t-=)cgYy`_D+}6x@T@xL_CrY1bC3WH(U(LACNO5^N1ew2NYzqIv%=$ zy=T8n3^{{->$R2rDw)k^`KTIM%Y~>i{*CQ`sIDgeMYagExy!0pCBZWJOMzy6MP`=N zyKYA<5_zMi&rY+dymDaN>!zBUJ?($LtrzgP?vHsz*W zen6cPSehhG=0FKw4V5YUyj&jaokN*x;>FDE`854Gt6^ZHD>P=Q#dSZ`QV%RWn_hN& z40^{h_Cy_D-P>}2(D%PIA4-8*jGsH9tR?53V>+H|siVVg+=nl3CK&7Kfs-VKnRHPQ z^&ZY3<^EuaN_I-gcB}O^jJuJhTh$VWjhkHLZFYFMWreRu8QxQy#=&+*57P!laf)a| z{K#5&_*aK{rOwNQOgbhOCGDJtw{>xIGkn1M;|&Vu?SkbA_YVFH)1u^%=|s*CQUm>4w9f=Q>}(sswne zVwc@wP1b9P(jTt6g&!)vjYOmPOMBB_4_KHpaDEK!AJc!sc(Ej##7a3Bq_6NV8dFVP zAM$YR(~X!cz%NCks*$G6^Op*jiEgzhl?^*=9&wq8V-=M{;)Q{kGs2+ngCkR2P`jfg zpqIOBB_yr%bv(D*UK1^@o_hPF@UBv_7=)N;8i7aBFl4foOu-juXCa37L;O?dy?K%p zRj`-+hS_7MWGJyQzWy_fO^rJu$>)iLV8kBV*H%=l4uxTnwat;I>QMgCOtqXOGzDR9z?^bOhY|?_X!m>#k9d{8IAG{EOiKa z+u!|jcJs`(h23CeRGUo)={|WA@PMDY`)}u9-A?pufAh&JX9B_I4P7K#1?I6g5EfFZ;=@ zheqDwpDDR+4sHJa7~~`=Fc|_e_$bkF4D298Str=IN5qcPEwI+_L zGszV~wv)#VC4<}_Z_@79#Qs`8`yte$sa`*l8OKE$xJusl z`Q=}XYot`Er&P6bMY->MIcQA@&EQrIb1ShZ%TVUsWTP7BUx-8AK3!9)-@@-Egb4}B z;%S1Q4-#yFeo^JP#Ett)hJeDimSx}6KSSUdO>TF1`XP0RHH?m1G|Z`EQK0^5LS_qNLwmB5>7S-et zSQ$BdMvrZzX1omCfVaOZKZ33Yj8ddUobhWUZQT?;c(8~9r%6$eRhCwq8 zJMgOS2o7?PV-;s#MwmDbiPwlq;ZKjR)|rP8pD#xY_Sv*HY_%`TuTQMZbGRQSY=e+5 zU@gn9z1#~{*r%ApRj!L*K4ZtZvNJew$PiFV#pV*K87g`pW-0bD{0cYltGr|bl!a`Q zw^EwI{l|hLBdqt~-gG|_4J}|?Q9G~MYuih+%3u^batSfVe+X6_IRT2rrFaJ$0+ypH zB@y+M`o#a$k# zGcFQM>~MfsLEWQbqa&LKhCeOUX{y5h?6460!&8I&ph%*m@WL}0~)q;|xJ zkqwONgTdFizzd%QXRio#>`ULA@x)+EXJ_&CwM`*AE+tFrQBK~ zCNDZd5GNs})>`2Tr9r1}uNZJZt8s`guFNx%EhzZd&8%{`<|dS)(I(2YICIIIfedqW z6h&*LRI;YRXJ)SMs#GgnGWGGJr<}s@alL^G3^c)QS2Q@mQ9OX>=hc_rK{I~EYB&Y0 zDG>y_xU64B?YdF10br6mC_U?Kn5LC=5X7V(h`O*#Hz_aot79gW>QnSEu|s)`>LM79 zozuqdaHUrkdf~vS012tzs#7mzD;hHcEt zA}TE*l~Bh zol`#?KB6fam>SsWp!q}x!OUH^h6Hg~Iqgqo{0ugKbJ z0^=&#CY%*@hw}R<+q?QI_2iwX;3zpTDDC?T3q1q*nT0`CL|7o>Q%Pm4;B2~O`015S z2g)(!)b|sD)CGm{cyPhSvV1|vn+Pa^LW$DYi04WUMU*;y@NlU@1oRN(vTz=u#Tgm} z)-$a{%Nh38uIXro(U|y~y))Mt#p{ukcGBZxy(lhTu7kLM8+cg#6WH)D`6;4@ttn)< zIrs`YGG%%150tsZO#zE}dvSq?gbyY#{Q>=bz%B=;U?Ot%?Lc46|Ph3pIbGx3aLUVjfOGPpDO)Or29!o-k(4r zYg1LXaAJmfW8^ZV-oPC=_n>4hy(i|ZcXr<6wN*2t-1WA?SvsULW@s7IR|#bmV2*m= zOUCe@NBK~cor!F2$SIzJqzq?96^);0Yk7D?Vb5v{?XQ(bz!a#Sm%snAku|d0m7N!B zxGCDvqaUIWGV!$k>D1oc1pU2y5>@>VD@&>|j4t>$aEgk1NGkO97{H)IBtdF?-Q4dT z4MNqy?;tsYz?Qv@+9+v8EiltfgTjV-p`@3;$uRsgQ5b!JPZ#*aqzJH0KT-@n;zojA zu7j33;td_U zo31d6n%Zl7OYTg}cXlz2YJR;K5czYV0E~}?N zbUnQZ>)n6+^gjGp%D{Y`!FnOENO*bqMFMT@GSgKKk5Y4bPf zR8C@ox;U~oG@mx>kF8X4XKAl}Cz#3nHZ|B$B3$J>)JmRzrl$(k?wk$M#EDO0`U(qu zY}9PGMQ$hAY#B@CD9^qyGst<{y@h|ylN`gfm~`4GzapquoT8)28Z{licSIbA{eknq zTRMXz&_A0lx@cI1ZM(~1Z)cU9Q^f32_W4?Rfj0Ipy2Q|`w#&tmHop>ONf`y&J;DQ~ z3HqD6_Rk&SQeiyz7IIWh&;*g@DTuA1Qp$(|yAHHa{4-w%&hzDburLF=4t^W)A(2hz zOcOfSgY|&_5x?adkNiv!C?c#x%bCmvoz>C=Cer-0-wgV0J6I2f-e*RJclp@r! zk+IRi6KbV-$y`Ky^tB;9b29FpIDV4Qdg2xC(lRmSUee8$vx0;0fD%?LsbWEAU6-Pq z{usFf^bC=K<9O*f&CiKFIQI%c%A`w8O}pqsj%I2zdw6B*rg<- z1sC^E=auyQpDVX@*AaaAFhaT!UofuG7EH%pEe}nJVd2@Y0WaZywnHXE5rF)Vh{y~ z?V;mmZK-q0Pc-7ho5wp|kGpY!-I{MyZ}-n=J$@*fZuukXJT%q%Pg>T_ng%bNSW5w6-56`~#_8tT7x%vM@%*tfv6WlbJUII+9X^BYlY4UWH{IDytlmurPJ@uE~q$YIK^5Pj0To5~1aSCTPou z!ov#GA0kt&KX-FZT0ad-^EN$qr&X0LUcT}a?fLU(x4EzeA4CQT>lPQ904zJl* zO^3nC*L|V7=zPkP`6j5w)fTK{-h6YcbCjkLs-lF^_ejB~b%h$@LlZUx7hq)WL`yCv z2JtPLNMKV41E+?=Q9R&0Y7y|AW++J*IawfQ1?aqAK+8!r8#C7`c!S4z);tfYozt$q zQD^j4i#&a7ahAIfB?e~Jk+lki1A24h)Z}zB*uEkBOuj}CCnOi4fF&WBsJ1}J4*!{w z{hkL$9Z7j^mQ98B2`!0lMIH_d5{?6-swYzU;G^f)d-y~b~WgCJ-vRc zbapao6x>Zf|6}?#InhvExc&&-IZ9ZMa^)dRJ-5cV%ZIx9?C7X^mc);Hvf}LE7$B3x z@pyw8A|#0k`i@py`u@fBJL7(lZ|EzX3!YA6>H9DY!sv~sEF-ttN9C+e23cjq+FX(D zAr9tKO?+5bAY1ed_yK+n2oWbACO4QQ+T=B3?RxL)ip^%k*$tNk32hO~dt3w2_&+tE zWq8{Xk(Hzq8Y;@eRiRVsuj3tr4O2~^Z7`*t-42QOq+f}%ms!?dwsP&k;Cfx1?=zb0 zzvXZ`{X_%I{4B)!prVvb@lAJYmYO>z#Gkypqk**v$ZqtN@3d0}Zgg~9Wl(d@X1PPx z<<7lUehg}AI1lj2a;{?e&F47z2-p^XSZf5&dD^2?R5g1?W0I3k_ZOx$iU~6#xnM+5 z4a0t8x=^FPeRlO_&t}88T22q=eT6Ji5HH64mY-IMVtm7^RPoJ)TntxYpeU;NdXR<~ z`+T%%#}B?H-kxAf^n`4cq3G$Vh8jTwq4K!P=RpOJr_(WxgRu14PE|`3N(NG>>>Lawmq==$&i(M-sQOeI% zO5i$6wo67&3rVzH6NDTHU%C%AuW8z-8P=K{=Xtyj!ny$rS;NhMVd5JNJ3R9|K-$@R zKFqwh9QoPl`v|mS{%aReid>FsV?Kh(a};Rq;}x(rj)5d9CE;&4Je=d`maQ3meAF~}UQPa**95x}LSF{4cx?f}01x>^4S0Ou zt2(^ma8&vCyM{;+qQSN98H3t_a9Fc8SG`B>A1x48<3>LwTvT`6^=U?zhLZQlUBL%hM=t%?-JQ zIaXJL<9yTX50k_4a|!`@EpmO7cBOYx0$N?T;t-#;{_74vYQZJsX?IW5z%peDA=Le( z1S-Dfrr>*TR7vqkCO7p5pE&KVXyKq7rWq5CzI}xU$-)Q!y}2Yc)Jo+^1!7>-45}xB zXPuR|`(uQ&Oh%d|mr=!0IKwIxGo%ZZuBe*4D@hT{#79+Lejd7P5>N>$6awuPRVC+u z(g@mAhWMhXoH4=#K~I6DD^LjyAhkUXJdC0HjT~bBToWImV{~KRY~bxwZEvsL$8Vvg z8)!I4%2F*TdfdebwB#ZiJj~Dkf!N!XC>G*l-{SF!!cyFou6W^NEqQ4r z=9c$ncrq0SSblULn32kmCorK+$wFAo`1%)Wcb{h|MP|xTr>C;XZR>1KmF3|O7?HLT zbsv^?Oe&>nY9uq-qfm|sQU&R`soO!e;Yf1#?m+o5wkZV$MYX!8t~`kl1_QCv=CS2$ z0RkY|VVRJ8L>I-bfxc3o!Aru+eRF2S0%ee3vL;eOv&dMg&6 za6$s|p2VB_Xh9w?xg=!F3H5Yg$Ei}B&udWgYk#!XHTuf?Y(|JPD)XoXm{qYeS@B6eR)PEVYY z!J_Xgod}kyvX#jg{%>_q=er%MWfMJqZ;@e$`-t-*EI{U$6bZ&P{<|Y4o!C*cLEdh2Z~)an>T)Z zXN_sdv6{riO+BUQ8Mg$#Yc^SaAZWDYCA@`E>5m5Gp}hR^{gQ+0*e5pv;<~$&*9Q02 zZ5ije$Wo?{h&w+Vor1zl#p3_8X$ZO_p$@g@&1JU`%Hsaz9tEk}(sQs_87FU97mt)W zZ+v)If6D4!uLRCe29B*5RxYj`8t*m@9^y}=#XnARf6np1dH??P`=4{(-(e>IdHyFJ zSMR1OnDE5thd_r^G*+iaM9=QG3R}7cTbC!+L49`VA`7st)F8EsD| z&lS(~Si7HBT+#%S?U6(r!w{9KncZEhxR)I_CVR>_o;UZa*=`|+hr{=iCfc3O4{G~m zLRd94C`(GpoJ?GJHA}zW$|^9H$>p2UY6g>Q!_T_6&vPJuDk-J{??OD0wh%$KA_X+r zk|_c{pqij8y~ajGg^X$xd`I1hgvvBTG*CFg$aKkR!1$o@Afa6KxSc+B{5VD_s#Fz2 zyIr;Bb$jf5T9%j^UwgX`xG1myW$VH{EGmq1i!2s8i@>|;la0r3vM(#s96jPjxZc+y zE_eDQmjim4AvFo&)jg157(#Ku9t%N$PeLGmtbdX86}zfqj_*6Fn~T&G$mR4M&bu?h zcT2nJ5q!4Nim%@DfHp&+@-24ErV5aujlD0aJ4FIG(GXkMRZ5HPYU)nY*$*#H+q*-Q zN>E@we{%UUJX_|*e0Nb&{^BxPD_$5aT^O~!4)*iWB=*Z1h+ag6W`BFqQt~2y#PbDj zl*jw!jkr`g`_;Y)91eG?F*xPa8tgJn~_uVD4v$Mm% zO}v6~HE+yPy?49ar-LIR`CoX!eCmoX@xqsX%LDZi&Gd(5$w%yKaK3CS6bUjM^=`Pr zN&7JcG9SbvO9g!N7K?UBa(n*BiUe)!vC4H(Rv$E_=+Ct~1S1K|M7LaO<3j6e|Dmnr zdJXok-`{*{PqLVu&T!qx&JZ2G-=310Vxo~qM_y(=v$nIl>Qg9?p*)@h4i_cR@8sCV zkAUM#?2_`h9nF_HFGnXwwt+SR6;VSBwj;4^8uK!D7+eM%DI97ZMs}FD_>=d2*nn& z?AM;*1xW~`d&|B)3V5=5N)2TZQq8b|<*^ysc8ZtLRQ3TSO;^P*@8iWhyisNGVb_Z! zlX&~}b-vHTdv04*soeGfQ08yA^rP>OD$wJCeWAxihu*?-X(~Kr_exy#og^7e&fTDfCyX1ON2CMb;JF|x?g25e ztxxF2M-ZG{*^h6T4hSLNJ+|I*olj47m?Dug1KKZF-J=IvkO-){W>~r^gC_9hPzAKp zUA-`n<3Q&JC3`Tb#ihmi)AoKDM$0|H*euqirP=o%1Yh;Pt4<|+sc$}w<_gr~3fZQ5 zxi>+=OGEJ6$;SJU2h~PzjuMSbDpR-UmmQq~AF|h{dHk5^f&!Vo)0tIy3(&PCj?fM z&N!qz5miwS+(;A2~+Gx8vR z{?&ERyo;jn!zb*A?d=~lKOk@yHHSKbvfz7%vXmU!TKe6QI!(#8D5o(9n4*lj^QFw9 zo(M%Ek^18h`INUN)zs6TN8$jScvrJRbb@HSjS7CpeJH^esFC5D4V)-R_eSu$VadMT zA`wvmwFRTe?{k{l!F$;13x1~Mh7N9_bn4y@#oxOo&jIA&yrEnY8yFhnx+{HBi|@gY z#P(|#36)U+RUSyKHac|>M#zzl=pWui1^n)X2h@dtehXv4?q+C5PCA0l_6B8yuNY56 zR|zj>>QG+VQ^^Cpsq#ayzP{)?o)<&)OX2i+6e=AdnG||os1wu{A;m7qgxbSd#xcz6 zT(4QGdpm#0H088d2Ja32+KpU&KjlY^L^gKFr$;bLi?7W+xBS8qgwLk=QHUZ%W5Wr0 zSK^)hnfn>U|VdV+Z$V&7VHggrTFa_-#+ z))hAm@B{Fr*%o7iuUjWzrF2l>yFjQi)9n53#2--uEN+!cu)D}R@Y;))@^nweNU#@u z^Jga?IsK`;`PxcKeWrk~&ZKMA$1xi$JSPY?_ls;I?L&;?lUXK5)r@I7=41BBu|u`X~x8B_wzlauvh2uG{B!d zDE#m@nD1@%6t__!W^)tJ(B>~hbj|PDd-G?C zE6DXk<)St?1Q!$SYK$YwqUWnZxbbR7UU|}^2&j);(zbmc7eb>i6k>GK8(nk^dBq_^ zt6C%4tx%(BLL<}tkYwU6E@k+9}9T9c$8g~#VDMxv+II5grSGLI)75Bz+fv@Jv*$KB|3r(9p@%*Vi)rEuo+^(@E}(Bg zSP-V&W9!TonFK)(U?+(289V8_g`3upoYHHjPthNk;GN;jYAMpxILL~MZ}I>n>qy_G z3dVa7a0AK&LlF{vM5AoZ{IK#wxwA-&RZbUMHLNr}4l$s@D@DziT$xh|N-tlb$BI_C z4kw)LEB-{2;2BHN2@Z4>CpE;7BBMQ?189h!>k=-|^#;7T>cbZZL=$CaW=0off6rQ} zXZ$D+H~wi&LS;1p@b`1{f)8BROJZ;|CnIE2gVzR!W&;S;c+ymm6RkJ<9uWNp>+KV!@${v8|`}%skDkk-y7C?ytVlTPQz#= zOEoN@=5l#lFHjvcQJ0)MoFE)B-O(E?pQN9o`&Bl(*ISVPo&ZjB7YbtJ?T19EMe$j$ zQ7E$H#T0oe;Pjj(9uQ@@Cm`uqf}QD$zxpn&@ZS)75dwR>O|Gx-diGnI8p71gzY(hKj<((pfy4bc>-tc^m--v-8(VS~%o^o^8RrSNZQP z!{e+q)0#==w>fSLI$=CEds3sz+g>0lur^4|Ybi2;flS5}jPwPbQ(3h#bwNNhC8Wx*8`E)!u3bz+hA;yAEH1ty_w5)$Z zcDgIpchv8ls{lcuR`;*X_O@eYmy29DzTf>zU4Bg0sN0W$W!EkOlr@6sLd~I#EG43X z{GB)Cr0-~{_WsBmPo|u6ISAtwiPJO zRwx%Bofp(m^m<=;6V}+ew%7sB;dVp~Ov7(@gsy1lWicxuaFJua`2@Y8j}*oc*dW+I zBMa2ZbAbVdXRwLcZ0iKP#1MYJEtTXBJs0+{$R!A)u3VpUnmhQ^1%qspn-&;^0hSyR zS>Ll$q07#jhwKmz3HuM49Db?JMSn%10rZ2t6>>7uwio|leRd=VeE~pc$%scLz+(J* zr^y9R{+@YGf_+cn$VY~LvAtyj{E8Li1e$Fe=43J_+HqrWuq;cyi2YlL_LhfJhEiS+ zq0%w;t50(8c{f1|VV5Jz*_lcSvpUQqIYkfZB1%aTCkp7~d5!+w=6Vk(V z%^(uOmbdXA8@mNNVweLkhp~}9Qf*5nPsSgqGpBIHsIBf2nnjb+_3m*RaAS!~$2!jWY^ z@2h9B{Gf1(6+V|PJYSQ%AhBL*v>jqfa-_?+>N@Bzv-=>?}G1HmP-Fo93-CQQ0kxQRsU%2fqO3xu5rU$jvuL6K&ELD}wgO zZ3UnTXHs&gw{j>#w>kPpvPZLoV_ZA@U42zcDJr*bw+6ieETjZw+5Nl`mnK zh>UCOr8jOrG`lhP=hB-z5;?V0KT3SpHWLGN317iw?ArRGXmp!xL?RCQW3$N&7haLJgM!n5h}nd3V4?mw^A zKiPgcTu9{MI?d->Xn8zy*7?ut;IY3`9*!x0&gZsQV&&>Tr*w{B{+}iT1xz|G-f7p{ zxdy;u>ywOQ*7d)k|J``)LWJ}tBtMb0P|35d^?&|vs<{+Jdsd^8}zQIkWxW9rv#VC^lYivW}R5Xk@toCQmCH|J_7nrJ|97TaMo*kE&#e zveo&21~6FjY+GpdMJxD5_I2x?<(ri{U6V4^ie*ZT1gV2IPf$Utiz;G5tE;T4EKedN zmkR>do>Ug)2_JmrF=367d1CZOs_u5quH2-ji-%;1{HdN=CI<`6ddQsE4VR;3A=i~c z_gO0$owvAu7amUUhL&WuEbhCk2jBAx*aGf5smBSH;&4NMYaX~(I70o>X|5H|w0r*a zw*1h@zYA`wyQ@lzFHJzH2qO$G9{hX#tg0Q2kO&sJE}$+91H8ME@#YE?#E6s=wiioxzm; zJ-~4#9ID1iv=cnAhnjTmGj-aV?L&+8t-lN8?xFvWykDpYm;MElb8%$T2}1M@c|mn> z{4uNJ+RDbEh5FsU%f|gfH{Eq7{7iJ)UnoUoQ6-l748nxoRlQ%#BVNyah&R>?rW?0)wDr_<*XsCU_$`uBzH?Z}%zaq)W|knw{&BC%xfS9_y)~yPQHitw+iWmyx4nZZB;S zk1<;I(|zx4uE>Og17sJ*)@cTfm~dYvjeG1cX59Zetvx3<=|tmUWR+nMQ?yJS2xJu& zOPFyy8$+%t90OnN-Pwk*MofWBrzPr*Xi z@PPO*Ge!Uo@&`w5dPW{_EG*dzFN7ix7Eg!`MoUgtAYV>4m}>h$ZpSfBv8YAILq4$t zO!h|a=a-bIKAG(JIc9qbI>ryo;QI z{wX>5)5^uW#pnOTBdI)|$M(WdwP%Qgr@T;}6R8p_+&J~B5_fW)uy)Y7FtSX{bNq4(;g{qWG&{&e~AHZx4dS`YCa84=mQ z$pet8HLznkrQ*x@f-M$O;k>aot_-O#iBS%iDt5J9UT$~4{yFX4*a5Z#zPY9k(Q(2C1LA#en0GFjO8SzPu=I_^QGb>!A-g1?dmgY5`+AhDQ@#*!MZNSp@ zE)1h46ZQsO)wOiWW^cmXXUP7upaGv4r0+jArU*8U^;Z2k*6HbIIPh?3e$8j%aBH?T`)=1CUR39C=qC~HtUskk z@xCj6IylG0Mo?8WmmD9Ghjbf&m3Oa_l6iXuY3cNHO80J5hC^PiDZ<~e;!1T06$>IO z^$V&5t!WQJoHpfJx+w)Ws%kKQ;u=0yM_1xH6acyKA|hHeIO835s$t< zAEfAo#L9@sL<$Zszrw>UdZN8bfcv?3Gwb8^b>X*Lv1ume4EYzN)F`5dQ{e9H<(7_+ zuZRrCxYiRI&*hWe%d5Nm($p_0Pc1(BuF@oAri5Br`yU=E!PcnRWT#|{qHRzX2`{WDrd+C4f{_8`%g4mF=)e!i@MmW~^GD6QC9JF1 zXMJI|Fh`A;nVucWO10Vp{b+rZ^L?s&JdP2sy13{-s$x}K)4^yuVr^~BKF`tNczWyG z^LPj>@xpRQZFYg?f$zRAGIf`Pq_W0Gb01TH6@z!Xkf+RGVQvrkQ2OqEXOfr`yzijn zL%gD7NkYg0>Ock(BC#3z#RmeX1k2gdCA#UY?!Q^@uW5uQ$K@yO?W?K^`CuR%%`Ax?PjlF|4!= zjz9lag*tJ!^2j|s<#e#@>PQAzpHv+~4D%*%fQpMzqKfL;PI)Z-Eo6@k5O`?(l3L?> z+2K8b#47OQPWTm^pbdMX8r7fU8z8jL&S%bB4ceGHEL)E zPWSwr?~e~j&*gO-ts=oo_F`EtZ^WXvj@@9KfcNaeqXL zQP6$b9nryqW`Nx-NTaCi_n1K|%Q6xVPA&af>`pb6?{7o+MX51cIOhFi1`*#IAD5Ap#~CQCc4WMS5j=wVyl>0=MRVYQ9cP;-=*>=uxQoWuE$%iH^G`v>?N8z| zzJq=t{(%8h-Cw*G2T_E`L~U$sYv~lQNeMo%@dt~Sc~taBjh1U_QxCowx`$yjy|ooF zv3!E1rwsi5B||r)^he23-Q{q1e}se&o@;SbJTfM7U?SLAn#f50!1785cAuIKmG~2z zogY(_mebDB{nRdKS=9AN@KQDs{+}XU5>JDNB}A%DO+#tRq^cS;mv5Fgg(V{rayZa? zXQ!hI|17jgnfrwf_OKAlW|S8A!ddXLc-IY-BVw~V4!#41Y;AAx+Ey1Z<2i0mkX1MW ztcN~;%+vtsJR@^M1*L!#j}OXy#6;hLw}VsZaC#BYf?^EzmqQek7IS4Hz7cEb$nA3| zLyeD_T30$`1q^7I!)VyUA^7~wE$Y&mY?fvoWN~k$s>ZY%f-<=JAF@Z6+Tbf-5D}Yt zD)UJM`98ll&lIcP<2lOq0_$*1XRYrFEYXOyaR`*-;(dMJCW#axYI&X)r|`4q=Dwkv zo-S1jZH{tQfc0*efC7bZ$pcoF2S6!hWeg$d5aYot%R2=)=Ep*QaO2Y@WHr(+hQ0CA z+;Vv0*lPzv8v5mcZCnmpAEr4Cjs5E8Ncf8qm9hk?(58+d)-RkCtmg%KXoWz zoR)B32-M;s;c?;qTNLpfcDBF$s{7H;GC@(1BriAE3MWQhA>8|b@**^Jg_E=9!qyWv z2~LsCh%`->D3^1#7dppP_zjPwZe2;D|B_~VN`L#-Pd37aH`7qbdac#O z%)|6OrHqb_I-Q$>z*~Tnq;%&Bv*Tf>b|uDrBMiDMW7h;CbBH7X-K&>{(6yK(Hg4{V z;X5=X;Zp&v!)*l%Mj#jzdPC&Uk zE92Z#Css3zgN-N?(43&V+F*(lqR3`AQ!X?kBXYGBA)DR2Ds6E zUD;tYC1G!B2r=IB@ri%0{0N^F(5FLI(L|UoanI41``@)mjXGSpZpfpkXp^85%Tx4&K zLaD09N{DjD(18Sw2C~2_P9({k7{4{eLm9}44}1!fJo6Z?^WHcaPG`*q3D9%@$BOR- z6lkNV4wsd>UDKGc2bebT%$_1G$m4@go4l|qdkT)FqwEg=UBO{emY>EFUR8w!XYeI} z7d@}C0BHjKithtA&X6ES(f z%=0TuO4>fqYvsqvIXRxR$V`uime4!z0X6pRc3Fw}Vn+{fZw3^_KFmj7(34Fz0?Ws} zeZgb#p(xo1$wZ>x)1RLg(w3`3G|w=X>|s+!$Ot<{^p*lDI}U2e<1Q7j$!8Lj?Ali< zfYg+(1h`5;#z;{&Hv`y_Lx)@HQLY?^B7KCG@^SYe@DTA zTD`L|rvxTmRW~oam8Wh+2smx}HVv+Pq{8by>2fW1B+0_e18-F@3s4#y{UG7j`E@IY ztRmT%PWDTWHYwxvXHoPRu3#2NOqq@q_hS$rBQJYHLrYwu-|BM3$NM4FQiq|s{%vn> z3C~=7G-uj6O|OW zW$v_+9TgfKJu@xmRAi!b?N!~cX-TqPUQgT2lqz{IK2K*}S*g5+ZjTU9S*aNAjPI4z zDqwV|5$9jd5IryjKR%H%{kKpIqP~l(){TX?iZt`Y-8=-OHA%L28$d&A^OIF9hD7z1 zCxiKAj@@pXXQ8HcwS0_GZ}KAh<>Z`AapJp;->bN+N-9g1dlZs+_cK|!;L3_=C{Ndo zJS8L|LJsus70&*ss=^wSH)MC_lJAv!3Rqf~oV_q{umcl)m4SvW9y1iGmK=NgdR9FB`w=mi9ChebhKR+moVr1do^RZYodRgg7TMIj_8a0xX$i(2i z38h3qJifTb2CFxspuf>8$Bka-Z#R?k5{7|7Rq|z}mvAP$&D|y6e@9r!HXYklTc|+7 z4P)2pLgAlOftK-2=E;D7VIfP0=(h1%RMQ}nAkB`4Hn<6yq@7`w%?X!DNiH86LcG`Z z@;WF@UAWxsG?B83e16;iR%+p99zjGpM2)==78<_3r`_oiZ6qw~6YjrsJ-^p&ARF+m zpBVs}ajeY#t0@zbpr_1WFgN|Eb0m8+G(o=fX^O-c7zILCr;$kTKcxjLi1s~Q;YWk1)k5AYLq-6ITcd1+-SRpZxGNx1^Uep6Ka@uC;9uc7(A4DT@r3iU z3qpZqQnjcKXnZDag`8~S;cV?NO#tYJ^~g}8#7j!`bT~Y8ZBIrsUfM`o?E@1=z~z+m z3V#xUA6h&et-$EjP^AlTna4xP^ix-i{D-ZgdjySW!>o8jbYo))AI^P`I$L|+&3ym> zOB}0^Ul6!Qubm4E4MRHKi#jw28u&hc$Z8|@{9ajkD%=6<;9T!NG+!X$r=Mcqw`_cQ zy!8SMk?t0hI>*%%@dh^;%&(vzAs?u5##dTF?MEvT7SpmQ9p@fczC>mF^X696j`?XS zlgnY)D~*Ldj$7zRrICD}xzR$DwVEq~;NPu4`MlR@_*n*1qzA{fEZrBK8BPDxt+fn& z`(o!tf@0TTAM1Khoz6mAsuL4gMYcY+^Ne#Sdb_Z1eU&?Y8=A3picTqYp#f@H-bf;( zmeD+Ma$JMALRN?u(a^XV080$oZEk5!t8GiOdQ*YMM#FmS(ivK@cUt4^F2IAt@-@q> zr9&xYxQKyB2zGlz>GAf373&4~H=~i3C-&elVUMTa%z(M2Jrjh_-)F6lMh5bUZ^Tni zd7Q>d(_+1v;zRDt&K6>ZZUQ6sllo;c7S78LMGq1|;;NcqgVPmqwy}UtAIuOd)on&bM$xw|EXsPy z=0|9iL&xC%)(O9W_5v@wGU!9Sv(!uK1$dzDyv{*C;ls`P#rR%cf(Ol8SHm`gbq`e9 zsFYyxO(+6QAUziFb7w6-X%vHopQvc4C2Y<8yfYcJEb7qAYx&#PdVxUUn(X(bSuYdj zwG$Cfco>(DQ?_Mu=}W0h%?Dd2%9w<)uzf_?tcH%V+B)C_Y=4)$%f}MCO}P6`+7jGr z9b`eTv(Ouy{rxBW$3qwO$8*Qd?*VzW*`4`_+gEuTf2+>762~JqbJH9K;JwtIe>(8T zM&UkXdy)$51@UPS{IrU!U1&;4N|{T9`x|F&uX_*IWIUd`ysK+CQl2}ZN9llJ>9af@ z*&*BG=uHa!+Lkuhj{d(3ZN}OfWr2X#+3-Q2EmE@I(>nSw2ZizOJn70e3IpN9uYPr- znr$q98w@<2F7C7Fv&6sqrC;RIB-{tn%@N`ukJFxRr zm^rgSVM`zrdgBVe30~53c{a7TQ5doOhXaA(Z;^PUv(bY&2zPV$yTJPz&U^2>_8A`P z@q&wO(1v$?#zFm|pEf&*!_o=0f14Khf0}?UMefZaxl0S2oyrBufyZgb%g?U(|7ArZ zmLZ=ZHPDrHKXdnd%ma)8Pp@z6oaqtNY{`RaC%c5bQt&?*hdO^b>|dlljvU>vLgd-|^#v3b7Q#h3VH z043T7XK4G&nyUPlvDES}GwZ@%*3_6Xz;9zI(Z7DEivMFhCDQn1cXcybv(`=t*kX$S zp?{WbX0dvBTF0^~8IC$|!f5Igu7`stlPRIs>qXTHFA?bs?XrG=4|CGZhfGmVaycVw zUI1Jjbb4oF1ogYg9$?k8w!q=bwA*;CA;iGH`|Za5%V7M=o&9$Wb|3#!Qzj}o? zWXnO1gxZrSg3$89iwDRm`hEQ?S%2$0`i3vuMy)OnE%_0T9{hAxj4!~3%8+|UgG{$hZnriVnyn(W4a4=HW(pj6n z?#%->Fpm2Ykxcq;4t1AN3(e$T+_z&>CMDQi#2qi&sH27SqJNN>amRMcsZ^&}dL|ya z7YY;P;@*fq&tE&mRb8vA*P#I!&Pi%7LT0nQ1m5}Lk~LVsqb4eAB828+<+-6!G_3V} zltby!MdZfO*$_>TOSOBFRd%!pY&WmC@}5AL01?L90xdC7 zPvM)jZT>5RqxCa{*^*j9bR9wv>c~i6O@(huwtnRHHIull2Augj38tb|UVVJO?BW_L zNDyG{Xfhq{IH=)wi;Dw%HO>4F-Hp~sg6@R^*JMI+aU@H% zv(a#O0)_kON*0$_rCScH%#6ZpX@0zYtx*N>xWWI0hNK{WDqG#RexC)U%N_G{txylV zfu3ZMQlg|Jz>FXH-B4qGd^2V2heQok2REk(E{uTadEOYK|r?<0Dn%nkqIrC`7wtZ;=#?3@j+y=Mk&zxN#7Kq*~*V zYjarxtGD;=-kBt_0UrYc(R5O3`}+Tnt+xP*ENHfbkwFI6!DaBl-QC^Y-QC^Y-DQBm z-Q8_)cX#&z8fcoI_rBeI8ykN_N8F0O-CZ43c`LKBPM$OA(CCceW3jZp9H%YW2vj?- ztqoGM$hNij=a1SkZY9;?`ma$C0*dVgbpWi6X=|!8W6x)~`Ni7OC#z^8TiW^(hyp~H z3MO^!m4^uz3i3H~XXdu^P=cN4-+i4x5N{BQ-fu9~v$)yEshV7h3ns^Zdt2*k55cfM z=lJ#{5vvP8U{{2qoU=OhU^@*xUY9?rBi{GEpmK0c*(~FFr3BbwjP{#Y(fGR4ZRwg#P@J{<P=@}C_A0$Qm9faco3`ivS2+V zI+|M}2AUw!VnLmv!-KyyYbdqS@-j^>&f+P|%xsV+Mt`3r4gZ#zo0^^+ond4D?f|DE z#DsT-%>U``N@O$&HOQLF49AA_k9xfx+-Q8alG!?NmW^c_S~#V#-yvjh*14 zyk<=vFPg`4kuC@EXEZTfQF~C}UNG_B((2%7b_|_{VqqoXsw<2MZ43-Wj2}xfJ|x@} zouuX@rIZ`){yE66c^+K1J1+|`&yN|M4DzZ=lOB&J9UKnk{<9pj%qY0?t>-|+jPEHF z=T`^>{16`m0kS6)y$de&7oC>N_X+BG3di4?NvH3We2xCjfrmgdIh>&rT__caMxl{Q zr%uF(G0c{njToMQ^?^VB6$CdOY@`mZ<~9&j=P3JIxjEDq04n*(3T=srTt7j6BiQ%$ z^yR5^Hc9#$hw?(8k;OS~S5dqXk$$h*5pd7hecT`7-^38`0Eo`0Qb%M|pvmiTNnUUG ze2~1numePhJ*v!$O(;K*UBC4`ovqWbL=MRxLYjYZfL&~LsQMsiJIf*9umc-+-M}l(dnl7HSV5I~QtrL}&4pzt5wN0Q z$wn4c9lrl1L>2z(<7fYo_b0Y$Fcudk4Zfr2RpnBK}{3e}CsqOoJu}Z`bY*mpxB> znqo?mgZGYBXIE-n@VsoV*1HtGC7SN`ei*qjWe>5oWzG$6ATDgZP?D@Z)NcEnDVSQw zOnPbS+s6~$NPpD>HE7>oU3~x!YX_>=UDnnd4~83$X>{=*GPi$iwn%W3!QN<0v2c4T zu+50=n9bzHR3`o{;}9Pn?ueAu-jQ-R(Jw{kwwb}_JAA_YIQ6|Nw0G>sVE1n9ZB=jM zjZ6Kf_x$@QtSUaOS}j9}Cs=-ll?^jA;b!f-0!ETqD%F3Ra>*dcl&(QwR+v67aAgk6 zl+WWP*XH?H!{AHtVYn_CQ#2RzH=a>OWLCoaGLkFa^SL_W2unkwz~0)KAfIb<_(yBbdS;$X6Va6a zCnUUgAGfDsxD=H;?s}4yEq&%_h@emcU8Q#O-=Tsk^}2gz)+Q_#^UcJ5)GO<2T;C+y z=kRp+Q?5?M8^Cw;#R6yc^V=YXKI6lN!!f&7ZSY%zdPzKy1;x!k-;>@7RN$c zR#Sbow8Inp%u^GDDmW#s_Moi}sZ z>LGcK;@a+??mIuEzOo%B8eAMCf00%Ntn0-LxXQvtCH;P(dtSBQZ+r=H`dzobJqIXn zo;T(G8j~87PyK0;x<5~`>EVRc!7s&IT|-;w+^dCikw~Mi=2&0 zDnb70Gx_CgMW`cq$2I_eP5gvUd1#H(oiG-Y4w$B=)ej5lN3dXU59|A7ec3-ATh^NCn<}sVzGf|f-ZM2N*%h0 z1pISPayr_mw*`Udm!>Y4y0%%gm+|<1T^*I;X95Bme9zQ@?^bQxfdSEQ2d`|mP%4gsV!j_!5rx>=OZvi8$*)B_r@Lh z9`kM-zW(442-SZ_qRwl0-oO~F1}0PGTQ0yL^eSae22cd3Q^k8^>23^Ig%}4O2?`IEhYkEn?>z*n|f*hryBzaAUYlIc39yKDy;%_J3INQHx%(4uETOek z6EV+zv9_yzu7B)3iw#;O`K=gyPsx&c<_%}WbSgyCnRtSFFBMs1XW8*dfTqO5v$`A2 zWO8iRX|>POXaOtzUe~~`H*k@C>CoP}t+xANchR@n=jraZ>IZ*Iuy}e=@X<|B%bhmO zoFg;Z!&eBb6kOpQU6q+k5)J`Gp-vW4ej{R@FQ5LRJ9qs6sLF5Hd-e|g3zbS~A*Cm* z2eilXuhbD86|r2|DT(N@d<#<&B!CE3j!~}uQu>}@BgN54-Z7p0US$--&Yr&jOyr6b zOXweYVAC5Y+oFr=7qbfm6L)dHTCCemDwc2#8-}?q+_75Emd66}fwI0>Ggo`t$J4a@ zW6C0HY2ssO5V06Fvj340F7N?eT?unV!V!mvBAQ4E{&APHNlcka5m3nISL2-MT8i@O zrE=z_pK5DwMP9HKk)4XG=5ZVS^iKQ|DtDAx4h|zzlCUTdTo|lp;9FYYHv=cKJ}<{7 z2u{bxNM_P=Q&|pI!}^+%mT0`xH7APD7qknQzG+yd|81^m=#G(hIU)=yq596k3{U{X zfi%dY@1Z&DCg#cPLy&r~>I~z}w>LdL->bmcAsvW0oBh^k>Nu$**jH#^bjf_rz-6+( zYaWy#*Q*MAO;i*8v#;=(*>=Ip%`VZ&1ZtYecrlYhoD5pe>t@_`4AO5o#QTJs9>(V-ruIy#OCsq70(*vW-n+n&Fa-G6gRV?rC6KGPm79 z@Uj7VB9Vz?^V5xlZ&7YzxTkZj#Fu*DEZfc7>C?#Km zt)gg?2>P||$qnVw><^7So}99tDj-kP<4&CKPUXyOjCheoM|+vr(csJC#22!AuFEn; zgcs{_<$sUm8`1YDp>RBiMHRUtaNrc0rPq#jk!V816Zrg@f*=7cM9M<_uIu|{(yU{e zGnVJCD-EguYDn}3yA|KJUp)j|&KN`-91*@pFcR$sIwj8b?Mb+5Rh2%UPYfxuORfSP zwU^yW*L8g-1vDCg_+DY}ku&yQPq0H^G?Au&-xBZ7Eg2{{nHU6zKF6Wp>fsYVXC(8j zUij_;Bha|F{r6p;OO+MQ%|VW!p2We;ChVUFW4L zI}r28?boeq8!THX<@1dzvh=z!Yoct>Mk z0Iu9~lKTy`uYd*#k=|8U5;>u1=aamr;2Z9NmWoESOrt1V!ceg9~~E5!LhUs5K$PB#m=-g`5%jc(^BYe{^& zVH2=|idM;E!FAU&$8C>*g8a>QRTa6mxTahDwI^y!;=0^eY&K~N2;~l2>eFh8{>j9X za0nH7=6Vf-01-d?jqc-xLrM*@e(GNc_13c6s8&~}`WxNrkC4MoN+WCeKKEjw-A+f@ zBucfl;}wf#8OnrMXt;ts87#^d?ouKQGC1osvPKM6{*~n?Idi-j-pAMn2tgDQ7NT!N z+^(8`N_oZh0|j)t(#JAE&e!+-q%oPk5E4D0PHv?OW}5vtLLzdfXZ8r+a>yo+yE`Lx zX_z=FBT*V4>NyUibbSx`#q~jy;L>JcXo5G(eL0JHkA+W2^Rx68A~R++?VJ+Jo@9j@ z%xx_}mJ7pmgHDz7zv5j<{@^3?@kQm}_ffbt5_7k&&)1t6g*3Tf%_9M!?9R#BWN1 zRKtn~q_M=z!dUyQLewR{2^VA{GRav{Wc&~W$+ZFDOd{gicm5)bW8y&=m<=TiBQUAX z{Q0FK+th88M$;-B`^Bv76>ziVE2&L-ds{ZcztK2CPN=qj*DFgr;eT|16!q0bDOP)%n;HT)lpFLz0_JEpPS42D2)YJE?_@S_10tCIKG+ z81UhwySPy+q3-eO2#6Etx+n|PRr}YTxFxky&)|Z!?QKd(BZT#%5p9A~L;QAz9&W45 zS-B3MzsT8fiPp{Fgf2*~c}Dx+L4->f#HEt7SGSn!Bid&+9p}URYuJi<9Xppnns^L! z=lf&+QPIh5c=o4I#H0u3?2JOW0O|;PVM31b(`^4X9T?OfwN?wOp{Q_2=4F?)zN5mM z?L|~_a*5O~S9U>I74)+8S(&&}l`$wEm6v)F(o6EtXMGi7>)Ha1l9HLtLBd+T8OQ7!>OC z%lNXDha0SN(Xb&X;h&c-qT@><&fx1bv&hM;N2+M12nXJj27Uj8e9Ilz>5@*t{@W@L zZ&T>^_6*nMDZYz*7TMvXLwRoF`)sRRs*lj(&2pO*LK-?Q>BX*zx!OWZ9HLchT2WQ* z;ua?CHr7mv{kL^t z&Jq&39^9S!j)^MyzD@J=jG4l~v(b;;woztEb?EB1~rmby6OD53Ak62ucU63xYQ z@=}h>j|zXV?7$fFQ(0OFaX|J=$K#Fuhh z?uk&Tm1^zRA7|TI{J@eu`t&t3>f7I|=7(u1X*6Rj;KIj3`4=e*C)tSWSo$o1maQ7` z*i6R0wBZ^_h))XY#J$SF5zW)hsZa7wn)R1o<%_zVDDcGK4Y8?_$)W{df@l{I3B(Y> zek4RwAAe(Hv-oY&!#iqAN7pH^3CdIdgbnesd<%$}Ly%g~3vCdg9?PNxDlXMaQ(vW- zbR>Tj!>?V-!s3}l{Rtlu*AiJnLa0(-N%WQ!^5H(Ed-&bpV&CIjk4xVaP%$=>%~7?Z zJ5A{nrf)`nnPyT4i$lsBBw`}!W%b&>`>Qh=ImuY#WG({4{jFk}1+7mQtFeBh;744) zF;Y~|U;})x6rVwNsWY`MTguaT<359#SF)%RW>e{OZj?vb0=Csh1bN^WiGA(6$YznV zY9Men0Qa59LLy&lv&H^AWD(lneX*+6+@}P2`Za`LDT~6M$~Lf#(3CI(aXqZYs~S$- zaeRwB4HGIph1{%%#x4-kAZn`d8|AfGa~Bv*S_MT$avuIM z%v(16ZUFYxLbJU9s*ZK_7mOKh`Bsbtd0c`kSwF_SAa!mFO0$Re0Q0iR!|Y*UlA#Ly zcH&4}ft%I-><3)vDjN40n|vz`Tu{8!y-UMlyrm`%Y2$tQ&$JY3lWymQ9OeT1AdPs4 zYK&}{VI{6ndOqpePDYJ*Ou}o?O$gCH0uBfy!?FLB+u9jh(E*fqf7|JykHt-+qgGF_Jy zmLij!SgJAcj-yu5w2z%t#6WRRB{czG4_BtN$rh(ddk}Dp301(|C6625e% zg~}tI^-)+_DN?q=1#b0;EnR~Ed`KXi?Xy~yhRi8jfv z^|qBDu=2WQ;1TG1uFqPE|0{v8%3>rmAE`P`Hxc_wY*s0`$$WO6gxIgsM!dm0=j#b) z%~rIl)wtau%s4OM)9>((Bm7R5*fj3ZE_T4W)|FszyyK1MEYs5QVHfRiQGTu|9sIai zyX_jX7rd|Wo;i*Qjj2+v__T^+7=D86b~&S=7V@aOrFX}wdutt?v}}>P02N9UlOrQ!kV9{zdc5=DEQmf<=Waw@ zy3D}L-FO}IGE@~_flBhP44^c_q*^MbjnA);tk3~Qv)@{U5aQzED&xXh+@Qn; zF#ZH5Mh>|wJ(Ol(urseP`v$ZNyHH3*=Rp31#|Q@ntk?E!E@Kk4-eK+v;))z&vgBZkh?R$Y`)jhEBVY&{q z2Vd!PR05c+GBp_}dxm~Eaf91$dkjY(12r(lP;gmI^u-%tGs&ydPXfkARJpoqc|7ns zwoK0Ln5}=?5-+2rkBY}))yM@x8OeRvE*^%wzEMQ#2z*~t9h@@(7gjnKE%|mravDF% z61&aeuw7Z4@>`$Zt$OCe%}uI^=P8*I1}SvVKvl2iok3u}-#Y$JcHcyeLAKAxUx)Vd zlTJvOt&ft=K=9Pwkc}mm7|Ctta{LWO<%)@7q~!M96b01KF0lOC;Z{qs!oz z0BgYn{hm4SHsw})NjDVAJdF6WxENAv>8lP!huFVgS+@Np3klP#TU+V~NUOYZbaZO0mJDBB3tcx*q+Pe_h>X(`^}CYSw#5nR;6I4YL^MC(z?KL?KZ z9hh7=BJ_Q!$H)Pi$~_o?aQK6!3qOwYnxVU;2_BKq)?#nDS|nO{c+wvxyjC$tvFg7S zoCY0NVrcSr7#4!32kX~VJRm{<^B;2T{9=87%t&$WMM$I?`kW@YKnk&9N01u$AWmgf z2AP49f3|X3hA132n|d9$lkuR*k)8`lNmhgOKFkNjm(2Z_A>-MU%pN^WSpS|50+Bu&{ahQWU(yb&})?O!)4mkA7Gl#SrtCJ@#& zG%~tO!+GP#8$G33+&#=;$Ec6fLhMVX&@)1togu0)mAQnUR&c$A(<7@3yU8IeBVOim zQ$*h6AvZ?&J=KS>8gXGif7Jy{>j1K~%HFF&B9eI(#+naNhVks}k~HGo$G)vBa{#>b zW=Q3g0^;PD#k((tC_EG_QVeos#lJ)Z$!)25x|7-txw$`Be(HvJc_qQk9DF-QDwS6D z)nu^_@qV-D|1C7LXRNJxLHmAnHTmshy?IO@(YT>jmH`9#SNeUrV6hRKr7z$ss%Fkp;}j*_7V%L9Q|(u&via9^t;o=ox_Ml7Y0Sa3@*pj{uZR}DsUKG%T$Lcnt2@W(F3m67z} zR3e}U)om$qs}2-7Wm4+7VKQv4*ogDwNqSU{pF1de?IjFJ-_k4@Vo=0JJKE{3|!`@E#N{NJcgR2*^ z9kH^uLb~vG+-bmUAluBCvF#b{os^mT*=2oL9NmjLdJNJ(*D?sF|Lf~^b`=Z7)ka^7 zUL)6u({KEUVOT?jW*_n<7m2$RKzW_$sY`DX0Q^q%`xE!a7w&zw)VaB?EibpJOg`_I z_eUkPuTG)!Z`+&p!_M2@y!pXKlGr!L2%`Vv`)uCt(TEc7e<-M$)!}w26GBZsNb&C{ZF%}+hMe^wN zmE#7f;-!H@8uSm0=$P3l$}+j!B12sW)0qE`yn6R>GH_y=Np~kO`c1APCYQ$mVWb{XEl%5!VdW@j8s@qTRg-``pY1qwBCO@!Ay{vT?q+qx z9)Vq#;yFkd^})QcK{fclw~~QbPsz^FA`CV*wx%dxClzHdK?mPdaSCTP4tVIKYjHt?XHU*iw*`?tO`g+-yshM8|KF?Vv{t|60e0U#| zD};LD-5kzE<#noOaJ6LK+iOUpKXt(Bjz}0GHUy@iB=V zR&VBlus|#v&;K@Rp9*+cJ%$-*R0F$xJ&@I@Co>Q>O*y-&Rb~Ga?#Cy56y&u=n|CYE zu~2jcZ+{(K&+Bk`z$qscznYbS_jT~Ca&c&Nb9YcOhu&u8cHJtO4F{y2xJGvE$%XQO z>Q&qoMt#%EAWx5pSc;a;Rl#!w6z_z@Xl9h2E4x@smd$q1*OM5}VQKzP>OLKXW%sl& z1I?d`cs8Q*rQVV1-v~-S^aQt|%1=Wr{(pmzuqrt1YUXk76OelONl`!|ACJckQS4!- z?$2;25fZBnRsh;O3N1Oi6sB0W*M-ovOtLm@uw(_yNQm%vnqbYjl;B`kM2smVR^h4x zIoQ^gJvk+ZV9zIsHl&86xKP8!w=iUK+4MiWvxQxYUgo@71>id3dCw1kJhij^ct<-= z$cmoDG{R3hb*ac+d7gy_3sxTltKd!%YaKf%?ugBM!C9o~-R4b|q1tUZ-(DEM(r0a% z)jK0mgZ-Y?lDHWao6E~*t7ITo+AcMvuLN=ww|t3jd0JG9Vg?a(;_WNQ&c4L=;QHWR zVij!+x^o#KOW?n>()$BOoKd)8Z@skanl|BSwfRm*&BbF&1br%Y4bT+?bs{pvIAD*ehJesKQeozILZY+YUd9jjf|4 zQ0Gss>d%h;mmGMniyl{`fb=n$ z(+FK!u}4h&knk%*8u~?4ZVs)lmfvTkYl|-p3r{0gpzfwt&V*7;oKKHFl`-#uE$>$+ zU|`opJ5m>gLxouZjA_M8Y9(E5tLgc??Oqnfrp(v~_7EOE+Qj}w5z|An0V;|xkR zs^hc@8X1-V~xXbG({bI&W}_(eWQUc!H_MusHlLW*{)IirgQUF(cGz zWg|2hkcEkIL|C(}WADE_r^uZ*ZrZfIzb_)N))i1d zF~}Kz2*eCe5;c(}CP54(T1|KEIqi*tlGW4|#VW+cg@MuiBm2V!A|?j1X;g?Zb2FP0 z2Sy7&mjKA%yWsEz4Dk+GUHZ18u-UcKHv8z!KO2`Zxjf=@<*_oHA!;1eF zsbHklA--?q!IQLQP=D{C(smukb}AaHeOcTE{_Qw0c5=68hYfbdHhWoo{2v(je_EfE z0Vo;H6fRs?UP`=pHV}D=G~1fS6~ld9PIqSkWWzC9e*32HoCo zp5EMT?VA638sE=f{|6xcpH{?ef@vQSWi$!p51AbKJ?|_#^?9OZE%VDizdq>Czo`CX z?mw7fFwsx4?~X|Pv&1|cZ81&X2>}Z zt%#>9Zg<2*Z8I0GlQ~CTdP0cTG`k+nnjVboo_{+&&Bx6TJ~b#;q;4zB{$DgQ|J@Yu z6<93E{Tk!aACsjlon+m9$>wdac>$G8EOLFN?=t(!g_;1+;pyqiZT_sD53|46sCb!$ zc@fpbLD^|QdxO$$4G})!%FFZ0>g~t806+gtGtX1c+uY3TP1Ck}nTxYCvtXZcg=*EZ zc=3JXdbQoEy1F`u>+|8^VSZkzYx&LFd&9b=F*o4RL4#UHXZhnpylH)_)~dVrk!9}j z|NPs40bpLm^O{yuPC>ql~ zNj}>>n7$~lRJS#93B>hhf0>DFnjmcSuqpR-vzJ`2|D*n*EB*DYdX?LbCCPAN`|GT0 z=Zsm`vl+|M+{p;B~Fs0#4k+M(F?Nh=`z&H zE)^@DKYxvWaIu-B`Vq5ktDgKvDIjo6^xi5Asr3|-yM2xo6eT*y82g2em!)7bA3Kg1 z!vA~f;UTxUCFwxi%so?Z`07fH7_#h=)7Z_f{H2yf+BpaFG2r#{1^I;2v9(&5J|o4< z3xdc*cDU@6Cc4pz_lMGIVWiC=u&?K|?{I*oRuJA-^OgLKo5A!GP1lP+)FJuRgoFr5 zq;T$heBF_=yTk2E?cR8DayKJ=aQ|)!I1Z{%#m%qpy&X6Zd4#TSvwOdtnZfHlblnH~ zmpoX#{z{V}KJ2`SxWfsrP)C0I;ExTCbq6aZ@O*khjakP5#F-DhNIu@!`h){vUL%c= zs+RTZPEiGnVZF!PrWyx;!zBO)HO!*H?ni~!)c@;ckmP^~r{Ivv-!zeEdD;mHuF0G= z74bfHm|R)O_=)i5!M$qgpES>^y&Lv8S;Cw;)Z=kFJVsl)Y;9`4ts~`F!J*l00REz@8giOVKfZSP$9fms`QuW)Y zp#8#RWYk*|1?cyq4&n2O9M1)`iTyYi<3jIgu0r3b*RIOWY1b*8MjbPM6&~REq%Ad| zhLT4L$mwx|-&lX;n&uc7J0PN>sgUo`1|1WM)!1al($hOXpe4l3X4=Ue4nc-|+)LVdfhOyH;;< zVkdU-L}sOioOemX-d3aO`b-9RIvHKmSR8 ze|SG!p>oa1C>M}V?Qp3+GwGvmG{P^NL_!y>IEo9vCAIH2&sIiA%=^5ssk>-~3IM*Y zPEF}*Xn2S;lN(s9_1L`NIb7}X3#bGTV~a-2!)~6j%t!+Mr6@2$tc}yq&{*2p*!bAq zTiMwK6=~A8`t=f1LDwPd7~!=8N|mB@Y+U~ZNZ;FfuG2?#t4l3?BOS%UQk|q-&Dpcv%$%vZx+L&S?^Q;?kkaaaVqPtG>AfO z9-c4vwXmQ(paYelD_~xh*-{i*up6Nv${wQ;`V}$Ue$F`9g{7rPSGxx@Y+Rchn$QN| z;Nl*DyLb6H8KL_8x{Ren^AtRE@${tP>1%6y>3vo5@!?^ZJ9K}1B{*EnQjc+C>D{~@ zKq2QxC^jV#@@>W!@Xt+17`u+D8D)NTad8mCeuuP2;#s(MDt2lD zE?KwOy8u-+h$w2ChO>GC?lIKi_1Jq0v(5{&SEu4N;DlvlWSF!1?Kh~YsX;ElfBqmY z&DaE@VF!m#&TByL&Q6UEm*%jj8NVrlQ^RixD4pGrW+!r!E2g}v-#xI*eP;WI4(3Kb zm;3wEx;#F!a&r^J1sXB9^8Ic)R$p$mzh$3i}acYM$Hs?Bw+Qj z1f4YLulm94qts4k@1{!|GEuF%&BG(|kxbgc(m&QL+r%*dI{KmIIT7~SIpBZK*MBAt zSe8T-C;lq{;~V**O^dc{pog%4H9BKj$p{axLD^y@Quz_c4-KGslUT{2rRR6#>+3vn zVSP2DjpjR%5MGOTe`m8=t5mw^2kMru5{ucq27M7#Da(zsjlb-e`xYpW^nt0dEQ73T z#B~e|`nnr~fw1W@BgRGyN@{MA@w|W;A%!d$9W5;`P@30-G+#dL+xy%5+3?8;#gReB z#FnHU0p`-w^z0$*529*KvUlhaQS+vbKf~**yT~7oRP_4Ye*t%LR0t_40?|mQHQ|GU z4!s@n_d*S`-asjr<&E$Y4`K}KpIyA<>mdN!03hJQ|Da2^_Uhx(m3x()RU!J>C%eu- zf)od0n1L0;pO1ISI)Vz<^ccmUMhV&f^*BLA#m&tvmf_X+NPb#&Rxnw-ra~ZCURT_N zIg7RtgXx2R9OmRlO|FHrGp9pzhX}3p3!%yY3ZF_nySHSLId};{JJOGLTVLRa(~yn> z=2z&v74O-Hw!$6uX6Y_xgSq-6`~;E9(1bL|O>H zr47$G;AqNdU59uN87f3`m7FZP@r5@jchJQ+Bl=XI-~{%6y~`rcwVbVSXJ(>Il28261L*t+CKg zMt*zTE-K?~(vG&47B-~$`_?aoa!|0c;6BcZj&@Bt435Cp{&EhDW38v#zq(46?5BgB z9^pX+y4cv&)iqB=a2sCH5I8)(H+I2Af^O}Cqa8K}T~R7Ke+zEh(7qrSQFb90HiBRu zwZ_P3f_&Lnc9$dB)sy<(%ZK?P3}4vAmLgTCOWcP9?p8Y!b*)3Qt#Dr5j;()Wg>%JZT$XP|RjTm7KbLvNBFqG*AU3w!jC5~j zm&e92gPQrhWhWAMj59bgsiJj&`A602IW;v>_)vvcop^DV!{@<9LvU$n>4~Bm=0Qm5 z6yWR$DlIv5QV1jzzIz&++_V&p|}@IXgY9TfDsg;$~wcV}8=P zjr&%jtfjC214-h}>vy+5RnS1t@PrZ8eRCLE)$+0gKghyiIyhE42VIV`HX)W+02i0g z*!K?^b`&-t)uvD%i+#g%`0`KA_O31;77!LBr0QhQpV+v9lTr$8=w+wUkn=hL=WlZG zG4RMG0vZ*%`mZ?UlNk(;hfP(NwCl=uoRLSa9p#y(zP`b)JdWf)e)ta>l^@SrHV@nK z&P&QiOk10L#1Mws1&Ox{(1PY-)5R=ztbt5{N$p~TsCBC`!*Kzh4Op8w**R37h!Q02 zg^8(lqYk#VvIiUG7?vT(?SyX9K<&iNH|~i5hxl#Y=YfW}N_+>XMWTwB#1LKqfmwj0 z$vlLAKat^EPEOAF_X|#!@a;ZM=P$1r!*IRP4w#BNDBXjoT(dmxVcel2Eu>v?-L%-h z-R!#!!^;1>#&WQ|ku}(zE*|Sd5Vw(+p8@&#w9U>gC8Vj8lNZmcShAWwbalv&u4ynu-daO4?0! z!O52%gx}><$5xeb`E!H|W2jI1Y4_=C@9Eadd%g#k&yPBS1UC-;oo^j>yIp{s6Fj_uew1_1dGAQ~sBKX7j-?>T|>T)9r>fu*QwS*ZIBZEZ4TJdJvGOpmw zVnL!@(O5YVq99xB+$HNz?X<5owrBxlWz(xHr#ihYEd0swSuXJ&hsWC*$^kt3ZX#_} zci-FR>r1pd_Hys{pNj#FuP@xTo}T?XA`gB*+&&hTK+~N2?fQr3S;LjWDY@6_#j;H( z!)o9aN25$_v!0VX&O9&|1G659+*9e75j%2+E_^KyA~=j@i=Tn3ldTZqoSiHrv75^C%~r^^pT?;FC!XAF=}WX zCI>tmW#-@5uW)dOP=TS%^%E7-oc8SY)J^UeL_eK|pg#gq{!HSvV^nx;h&9yJ8gCY`C5>!CpbIx5(HvPdD!~?m(uJ{0^Hs-E7aMgEb z?(nBY4*So2bVI13Ey@h zD%HpWX@H#Fb?9&X)YQ~(3{voiY*Q>4z|qlBrB?wD5b`K;+S)4w{ISG4nzj|NjEwS& z@C|szkM+4)XD~E_efvK7KTp%wL-olvU=bfNk6}zS(W*-VOkP-kea3V`G%skPUg|~j zcaw`7?{j&P4?cq3wnbO?JCEGcv@d;X*#jzxPi9vL6!kF{|JoZTj*f{}zj#e4j!P1b^$nOPoRKs-)0*pG9BRsR0rg<&i@0F5)$z_DD= zlr$};;PtT&<1=(rwBKUu{tR48OUnwFk&)H_9ieJY!CcT^A%qXfOey;g>;Q7G>%$Tl zkZ0F({rYu3KbI)+>BZl@1VAIB0wrkyrzEAN6%;anoE@Qkwy(}@puJX*`F3aM@cAHR zviwK{96TH^VC%uQKZyeL^GEb3VcO$B1d+2=0T=g`RltSou(PK{o3Loy3P?$ z;0wHW*a4pQ0h?dPh<-ff$63<>4X>yA{NC-#z+W}*NhkZPm#Goocldk^Pzqp}4&CnN zgzhk%ii@^3TkUhu&~q|5^G?}@D!jRaN&i7I{A}{z;GZ{mODB<&2Xu6JEezqUZbr$N z5?6@2d{yc1KSG&5IBd468Mn3QNy*EPM&;zC@f}%G+aoe}42}!D#B^MR1Bnlc>@6*c zMWT6`nag;Axm+&lWyGox?Zd<8QNE8sb(hS(ORCK1>y|)=?M^w4*R(*-Uy&IpX(B=- z?ngd|_k-sN!;1ueU%W+3Am#P|!MXit%)J2nJiMoF8{e9C0^42Up=1VZG&+Z^cJR;Y ztrj1wu5-Njp1p#3vTTebV-w@y1m4!+Nz`eXW+QEF?bGYcD>yxQIm@0)Dl{%KUt=}J z3c^orskDO#i%|N+ro&;kt5npbkU$aZ`eMd|f`jKnzkpW&e{aI=;ro9seH4JT^hRW+ z=z6*`N(#a$0kS5+dgDDks$~8J;x%2gNf)-J_g7}2Tx%~H4f}| z8nZ}E3vSc>kd#6hpgJiKhZrA!_xAGZeQOYtH@Nr)ngcADVatwUtwzZm%r390XhZqr zaCH4n>V)WZaa%3Sc#Wh`U;C8yz}EQC5XzdIo(}&40ek)Vd3K1T0f!RG@fs{Tpdo>KOA|y8%jJE z{WcLcWTA?Si#rnF?%oQ>5RrZ({a}5Cfgxm?jqVqKoASp$S2mpfE9rtqu_p#l#X{rH z%4Fc_-TEafIT9f6?tb=2$6^vjcJhiY6mX{zO$0~n1yG_Qf%nLL#sD{QJyz7yoEK%! z?If8bJseZ-q843${{Fz&kRw)gpRxCilbSyRG}CpPUoH8z7+`zG&+-a7FBhTlf8FHx z41zwY3ntR?Ut3Der#yr|KsOzbyi;6(o8a6>9z?bP_^SPT{#TD&NY4GIvlO>y$<7cU ziY;x#VZTM@E3A#p>0D|)n{D-Q$T`MSobN>;5HEh(db>Yw3sk9)aA2BSg?&K3XFF20 zSGRNQ&?a(qb2^-#-vtb?iKtVrngNcmQ*Ot=v2y5f`Crw&6&3470h9$Q`@eZz;{u#{ zIz+tI5-)Lu0v1phut!P!0Xgm-VPav@(vA1WlgxV)KQ%|$dJ#`&6Z(w;K4~c@H}LyE zJ|MyJ94t{j$;nFwGgiNP3h2AA@mEh0vw90T)b+qnV7(WS-Rrx6Ku41Wak-o-`pcr` z97Ir-9?ecqvVdOAJDonbZN8%r{Qr2evDRVOFSPevLsvZ=(_cw1lwSSTdlAPVyw7U% z{TYhr5NE3I>Kk$2FRs>`QSNK%a^XjshygeWOa+MewD;5d zDjVT8yZZVHNNB5nkCHt99K;jA9t|xA6N5{*7x9w&&A7A;+$%RGXNe@{FMaS@`G@>Z z<<}@+z}*aS(0DqU$T+oM!k?F7RG@`e464p#=-xp2s%W0AmkjPNXv`Y(bIKSS;{qBR z^nA?|s=$G^j~+cE5nVVepGD$Z8S`Jo+SNrN(zHH%s>z#Rw>kGil0iL=^TOj1KJbdR zhUW@?A6(y*?vSJul0TIn&8{A0Dg&`Z~#c-KVv$18K?yQ>>s%HOL*4U z1Do60nr8^d9^4tE&t(hi0UAMSL(aCe8H#ogVVK`GKgY5(%b z`~Khe<+?~|@8sm@@1(9c z{A67ON2A^ezX8gE*Lm-yh)7tLaj1;rpXGshy^Rllei&}`M1h|LoBtec79bQCpa>@F z*oa1-Zjs?L%TH|XcuUsp>Lj=#@1vCaWR_d~{oh9;Lc*dJD$Q&b;`s>|xviS}p9c&M z5hz*Hw!=kQuP<~<<*sY=?D#F;VEiaTsd+n(k9Q;(GZI|CONFrwzc;1w^Nc=c7Ps3^ zVAn0JuA!$!KBAM6!QB=Mi6~q4e&sXVLyi_}f=O<*Ti_jBdwIJ)TgJf}OuYHEo3DHx zoXEaMNx6ui;TU`qF6$K9I;hb1fF{ zMPKsqg8pL)HXSTgK`X>ZW6op_%%~*;%(5b3VDQPZHC+J;ftH=OzyT*=cRN&X5@%n8 zcr|QQLY-k6qr$FG=iNC{a5<7kZ%sy+UuLpU_Kx{qbURI~a>C z$BbUn*H`S$vEW_NtEw*xZqMt<3Kv!-vK$G(`EPKzTp3MX#S+tSl}}xzbS6FNMdjTI z^Y&53{d|{?w;fwyBQ??ecQ*J&kzW7R`N_8+LvXAiU+LA#{Cp@fk%Ny4Xm1}Cua$)k zKWU)p^^*WTpo<7q`V$D3f{I?re0i*}WyqrCmmfRg>q~&SyQ7e%Zzj7UF71IJll})( z{m6z0XqNml)i4>O&k{YEGe%1&0{oHFa4;9iwzGO~g)*THx#L*z3eK^}o^gc!sWSN~eTi3uX z#x472$~bl;6aL!1<=oBUdL8Z6Si9pgIkZ9SJb{AFv|VjM)I@-M$llX|_dS&Wfy)O_ zXh9W#*7wUxw=isK&rA)uzI~3GYQ1T34~x69QFQZxbmZim*lW2FRN4`bW!qpd0*}od zcE6{^jDToxhdcAbeS4Wt2AXJpCU@OS&KD% zNtDme>0@jmp-L9L0xu{k0@2?@dn6~53`yYLd7jZ{UrJ47pja|NE%@WOT{A?4thx4d zmqAU*J}Q_lXAgDKNs!%NrpfIi6aun#@!Z5tVC&jrn#_hovbJk;1(|_kW80qnA4}u< zn;Cm^wqk>EK43n0HetT0x;|j!j6FxFm zmC05KaNLpx?tf-wm4fecoSs35hAG~m`naE>9P@p@+x&(%NJi*)hd067<9V`p9)7CO z%o`9F{Q>&j2?CUm@kjeoof<79~bw~ZqTT$sxy^r?Q@fejq(*ig5HkKNK=}zZ)TNe#7;RmfZJ&w7A3sdNB za%Zti@+xIh{Z+No+CYjT@5sR}0m)SZVgabhRl#+bLWiar{(yhn15WW)k^^N@Gk^B& ztbL;l`+&SX?YHZ4_ix$@Sb--rQNo}PMe3)>Fi!(%R7IncIAT&%202crlRd%era<>C zvG}I?JFhtX&vyAyKb3$_KF@xPfUlRqpn2#CvbuG@Pd#-x6b-irO5NGk?1_2};0_IS zdCzI^$Us?W^Nd#X7aln${~Rn$>Whu8&HGMII~H+_^DF`fM_D?P3bS*rj~!$9K>X!& z{P71#wkTwwU?7_mWc-yf{7`}LSww6#uK-^~45SNnbFH61*ZkFIhovPFnC6)wE`E^-A~H;=A$0?#A-ITsgGrWV=v{5&L#ws?Yum&AH}e&N{Ex)tx$B& ze);e%b%qyzD-;ar#BFNN#BTdp{#NCk$TeGgDD?E?J)MZ+FEOjUnPtasPdrXm{d&lE zIGUiv)U?13sh(~IfbY51hX0wFL%YTk`g5JH$goijEs>?200@v2)1nwUYZ0-bafLEC$9~;&*LM<4F z2*n==&k-NvU|xQV+7U0BG#{c*&s;je!tp;4LqmzWy||SjO6X4D<2VX&D?zC!+HAt8 zTI;&XQ>O{cU9Ff%YHD49Fzg35b3geP%*@QX%6VGVl3hw;99c|!q8}>-d;9FE6?u+E zS2FnIYD8{IiPiyoARvy<+5N@AbPC0*4tnQwn)s(CNGg=JEdGP41yT4f*>b<~^iMu7 z@Bh9xqvcXRn+^VD>A0FM;tpm5&{(}StWTDa`~iMNKVHe}AJ=VUK>(QK8Q1tjE+F2m z%g3<-yiUgkZS}v-)wIo-hOc*r=_3*EW9hJj5>iUDPowTS%cy8lCko7qywY6HsK=qx zjO2|8K|hJK|76~r5cTQs(TISL#kiZEP_5r$8D{#E5J#elrvs5V?3I42<{vJKB;5M# z^#^|q_N(KY(8YbWyGCybpkp$2{UTM%9LvC}sqZzC3!==kR&t;;?=$ zvT%P0C+unQ+0S3*KhpPsGxtgpPihm#>1IXTke26jRlke_`=baxT;i;}T+iFsRxnk2 zRJ1lB6}9xrd%GR5^Gh7#kUFEUkv|(D1(J=5E1U!@5er36$N1r(ktZL1AmN2`c}3TE zKL3^n>TBcTUJMLz%BTIg8V3s;KdA#oLjL!pYJMGaA*PtCxz}vM?4aS}w(ORBa(hnB zVJFacuigaQ&9Ork$7`pAN84tRO;T@>P>AnD(^VzI2%m5wKa05cwWjkbmr}Dyh`#c% zW^nje&TC{+A^t{fK1Vp5!AEq0OHs+hHn*7nx*N5lXBtci=nDT9;EI!aiXwSf-csB}bV8M0-Z_!XrUK=>XGqdkyfed~*v56S zSYtCX$)XyFKHpbQFeD8nV4pl)ovJwr@x++|&sCX|l94_r3=_W5`rZ?Rv@ZS7EfeDc z|MrxAmG~EyNnBy~H!NdyvmCgEFqZg}^Qc9*9?_esA3fc06+W4bCQley6ma|^W5Dq7 z>KZnl^4tdI6(wFQm$IQmM9V?inX>YM7~K7M*@D>qrgN<*jx#}v z$iYk22~t*IIztc=Z}jRJBsRR5=mas8E)$vl!GVCR_J~?QD^=bCw&fbc0z+*i8o4?` zDJyIJp3%_wLBk(z-@Y-O!tgXB(?YBU5|fdp$}AS4)mb@AEwH)Mo#{IeGWaUZ~9@Z&Z#D#)H0d6rkQRHN!`&79~9 z>&a`o={~l4E3Sb|jA_ei)?17IVA0*xQxC;?IQCY>O~87caSir-drmT+5guNh#l|9M z4u^|t?bM6v6u${m3vE>kGSJfcr5HBZAB_~f-153Vy_xrj6V9M`%pBWRTbf}KLhypD z2cG#-!&A~zvU{w$Iw$*-ryc6zAgkig_xTM_Ev&WZ;LaO2w`C{R1Wxs@&xj0ylsH)t zf{t7Fp``I9G{qSu#brgRIWAp1C`SV5eSll_UF`k*t8X4Yn1i}XDV&OR$cpcmSWpU# z4@o*wmZm(ov$uz9yGEtxwg|$0ANRjeX|!5y?X!pY15qn6G>$6S_vvh zl&A|pfDi2?jAiVOjl|r6vmSh(4f;M%G*abQxDFU&pkQk;w)TR<^Z(eSHevCelJFO4 zd~VMEbt{UFuzS0-^K&)kM)k^kR`@xiLK-m6nw~{6t4;BCXf_8V(b!lkjg}ENkb$**!C-SQJe|g z?CCtE9yCjB#H0uw4#(w|2iA)zdrI6Jo1Ohy8{R*HM8LWMl)7<|Pk|C0JMuq-$c9X( z&5>NB`*aka;?mBT&k$TfUZ<<842ofLB=q4RMJd0r5Whs^=2M?g8cfhB{z8ZlYju{nJ&ZnYJ`}iN5%$r# zQYz8y%*&Z!<704#2+qNSEK7xUKQy{&Rwjp$urd64FX{gT{QPI#G90ry?g{HH32d>* zO2J2oTWqhioL?+}eXr({pa!x)VT7u=%%1C!fZgFjQ`G#n>A}{YmAn(lKdDRJ7Zj}% z;d;tK#E*`Bu3VD*It*IPk8~C(Cuwux%__0^@eGLMMk>^{LaK^N3`{0v>+Ozqtz#!s zUz^d!!=GA@M(Ed^5vOOEX~3s8Tw5CyKW{c@JY!1o{6s3 z^z^#1{{OS-pxtB>vqu$bG54s{;e$2#o0Tt| zCC$|1PlWhRmGCHfs>LMWw745zPgct4JOrO#k3PQ98Z$d7=m`1p8aP=?tr-ce`jcuO z5Y-Y&V5~j=255rDR@ib~r}K^<;q5s;QJQ+77;(Tzji#p9l;SmC+kBz*9*)_3BNm^K zhJr*5FFAVtloXV5qtvZGD6}Kwtw|@+y7q9Y%!dnwJyqb%KOR~~#dbdg;Njtgk#Y94 z#KgufO)TAe6dyBoFRbk?b^z#l`11r` zn5V=FUH$#6c+WqN$Ed1EKYtz?%A`?T^+wF}2DkG(is6ii2SGr`@wj{|{J{O7&7diW zjtmIH^fhg+L$i_|J{VXl_p3+7ocV4)M0P%Pi>wDzDF|Rb%scx^(oX{wnFq=}^ z57ciZr#EjP&NJ@rt_)G8_z;ltn9-W1tlz}AwRIt1s~+}^b+yRY+YaV3|E!J=fB;H^ zyZz=c(P$J{*j0sOG*DaK;kA@UhCO96WlEbfc`E7?IZ~^8Y(M3hS1FbFA6q;ZdwaSK zaf~bI)fSJ>{#lf}`W3P5J-~E++U0VdL81Q9>sO%To$O7t!-CX zT|N421*Es)%zuH}+x3rc^Vz|}Y@@NQwiP28hgUmH2Ptrr5A}!BgcM8-2@TAmFa~q) z%WDRWCcGu0$DVB+d5w61Wu2=q!bQVVO$~Lgw^{*Z)ikkf<>hZv#|)2{kU>2kMT?E# z?IGev`!z+hKC$4qoMayJ$6&!aWvDu$`-H`NutHI7Skn&G=a1LDlUI=$UFd{S=B!fv zmhCkucv|Dew8AsnIXD>!StC?6@mDBa(8s)sUZn|c)yLg3P~XF~;L`ie1UL`^rTZJ8 zo^Zy+qhB+WK+J+=HYw?0(8Lh@ongkK81T*6NP`Jote@!eW#WJLxiE`^C>#GMT~oE| zP`Zw^cglhx{IR2(6#yJoCD{~uEz%~unz8@`H7(22qHm;Ohf13MQw*_Sjm5Zgyc$5C zz6^qOE`Y#-&iEv_Y6Pcx%}`!dU55);tmu%BB$+0Puhg8%?d$~PGQnNSA9uFl-%nY8 z#X#$m8y($aj3Z zvXY?()VF3#^I`OdE{MXenJaT+fDx?FsBzj+Z8fm1ka^XYI_Uu86r|R?smrG(7msFg zF1V&DM8C#9b;2WZ&pWe#4ATTD#fK~JNQt-~I}HFVhV>RLXnm9+Vb(P^%#;f7Noi8l zWPLpbN_1Jm$x1`VMH+T>vF5 zez1~Sz)3-_Y>jItgp}0ICyJT{PXIl|ycn0UquUcI&tG^5bv_T)S;}5l9UsUB914BZ z9M)~SVJGYuPnzp(h#h!6&RQOVKD?(}-EbZ@=@j49I7>Da5H+cO2cAss zsR|C@0a%6iyFz4TA330Bk0XRsH26o+pT^t^F{C?Xa89vjwf5p=kQHZq_~ z{5`w|=bRE5(6=1SW#Rx8c|PJjogWu#<&Awo6E3Hs`|2u|P%p}i0EO`~!bLBfuPC=; zJ12n*x%Zx{1no2S5PUJUv9Vc`qJcELSSBP+-53Lld0)Porn#Pj?|d%UHVD}9J`3h8 zQe{?hUmJDAb-sI)Tt0|)YVA|9;9h_BBV_r4{%TLY7@zJ>^Ab*DV}^}!H*<$>k2+dr zbVCA%2f8|;6V}X+dG)&2c@69c#5HIIoCS9^YFio-f(_A~l9H^Hen@MLDig@XCq&*$ z#!oloB~Qhle4@62pJgyR`?qHaG@O{^cKH`0%GTIeWC*(|8xZs(s~^3a)|{!UQZde6 z4G1B%Plm(qBFd=1_XU_TdO#8qcg;9neYS;7(3*H9q^P++DlM3?Gl#U3_H*$cNc~Zc>L(f)r?U+JeD4UojMoNDja(h|AzumjH;BHGW zMVDcO*%3ybYPM;-Gbip`P?l@^(gaapqL;UvVd^9jA6T$&@jdX`2Z`%1`LgZ@6UUy8 zqeC8Uf=9n1r%oWR0oHM~E-Z?>;o&YRfo+1~?a3h%vF1Z5eGCkD#koTlf2&1dzo`rotPw+MPYh47mpA(ONg!=?$vuUx~^QRnS3NHD6cd@eo#k{ z7a^o$! z!RwvQRCKNQC}v?hz9Cx|`=>nQ&yOA`OT~i`@wg`XVnL8ZSJ?-{vpc5@_n!8#TtInF zqdM;bNr1yIo+WDpbmo;htEjx_6O4vd)a5BDeVBLHctTeD=PY1vY%CU}abu*Ho6T>s z9lS2igNkbLMp(W0zJZ0Rvy|uc`>vtvU)@!^Q7cF1*Wq{XsQnvLZMFVlWsv|K&MHp* z>}TnD+OwZHDGn@W)87)EpxQ5(B*LRoL!kRnH+-=f(`7<7%0c3F{)8lhb_TB`kJRN}RhuZ;Tsi>t1zcoZC)j(0T$}2v1E9eK zbmBhnleJDjKBs-#()do5liSgNHLW2s^(KDnipv-sK!BFMO8@2bFnFb>P|kk!!*Wzf51Zy@Ow z{$&l@oeQgboudlY{LVdJzKz=+x^n{ICsRc6=DiDRl>-BxOYLprq#!+9C=5b>V}^aM znV{*x-owT24o*?d$>YMUK+)%#fbm&u6;w~~v zp1@1b7$CRQN$}m@S3#a&q9*@*NKQ`98jp!9^rdmVqP9kzBXRH4mXGi^{P(|vt6Lix z9#JovQYo06CkXtwTPu~Cs(zFZ1hv1|IW*Gaj4uau1cN^KDsEN#8V?hyDsVrs*rg76 zEuldYsm;%)Vpr$Q6pPZohM&$Y)w~1~0UXC#?=)B?pUW!(?Z0flzEGH`);;L1b~;QI zs#<+jO?j=>NCNPI;{h3;W|H<`|INLBv2kB@PwN+&nm9N|P{+bTZ;mJ7%b~Uj>~4dV zVb?DOxwuZ6EvHxyx&x(Va_!Qb&pli8=~ek9lPfDcya#xNVmkvfDwP%%7PdW&v>Ut( z)$*I3UY{Kqvlr~?bv0RP_e`A}&q zoEH_og2U;*{SD~>!vV7mcNzmCiwBXm4mf&v6-rLl9pABK!Mj#P^}|KSF38E;Yt_x< zb))c&CU5To7z{dcYyk4Pf?px3Vq;_HY^O8$gU-FuQF^St`mYlTnygb?&aExHYqUyL z+FC%~_1@P;4LUhM6b`<4TkHQ!sFR!OeuNys@NnS|=5VWkX0yo)4%-?0I0#Dh&p9hGeh=pU`R9CSw)wa@&Tq_RF z1#(^mZ?sWY(hj8?(D#3)o3-n2#ZKeL+b*E1N$;*&;F+Mlu&a^;Eq~X+!O~|*Zg1$R zx)?aotf5KN1pu%D9Q?0@KEPm1*_GaO$-xxswtTP#)aBX|QDV03C0u&EXWogI_kxl#b~HEdK`!K5 z?(L|FSN-qCL9@pie}$@9eDwF{-?`S-?V;ztbHn)C1L$AX@&A)!{jWl8vrX9~Ge#8Q z9YuZbCvT3AI|7I(8zLcf9238>gMZBSXWCyWkN+LhCY$;eG8PuaUoHIi^Y_1zb3S6w zX$E_gfp-2$Xf99yp=I1Xtltvrf&E&^5pKYL5^80UDpwj);j3;11ZlVVC!mdmmh%ty zY25khzqRS$E3pJKczGQd_zqIWOP`p8<6(u36fIa43UHWcAqahO%!3lc*BRkIBKQ}s zE}Z#vssqW7E-o#e&z|*)e6cszuH@K5slq;`A7oF z_yu?=b>oQu0l2-3HPYLk|x$ zm4LVWjLS!^mZe5@fW@?^eMK_GY30%psQlQQ;EmF+iw3ly`MayAZV4G76A-NusyX@} zJkd%>V#H3M&-p8qA~1CzSh6w#X0faeJL=jZ@xJ8^Dr%Rv3LK{3T!L37)>pb{6DlMA zyf7$6v9j_?DMECh5mkc2TLRdc0-FJ9focDs41)nKrNVEPkZzMBTb<3mX@CVkMG=aA z0w1BXf(+S7Sb|u%6V`9^dm6}?`?spk=L`Ct_v82$JO!+;2TQ)3kysX?NSJOcWVcGQ zO5#%d0DB@kH!pGGUH|1w)G6}-Y-$|I9}OVD3^nPz@t|e6{$Y5;df0%#^gtiH;(!(- z5Du!w&8-lJ`q)il-#ayKi(dMnBMPPbGsOT)&JE@LSd?>yV{g8$FS>U4zvS*fuOV1z ziBTT7H%C5s#Y&qCo9+mNm#H&r@0HGK2{l$d0M=H7MzT-9nn7GOEQ#OV{(yWlnmM)( zCZeZ=YsLaGaxMP`yfVGhnF7dzeWATx*^PojmK$EOINeiraWjz;m?S<1+0;fi(64+* z|IYd>Nt}q8RgGmTxlK8yBv@Z;tJdsr=yV91su&AvIqK|fjYny!?~770Guvrpy^)7E zX5`j%x7u?ecrlC#WPg!u?;2ya{lI|5o;1rXNQng-Yc+>W@aXYPFvNE+g61x{MP##E zcG>AopT8^jZN(oal?bDZm5ZGb6jB&amq%mNS4fTZRebe#8r~K{Uf_1V$ z?u87Oy9L0hGRmU0AbU!?CTe*5=qugBTWVyeHHB=Ydib;~5$XHeX577f1dlGiMM`%J zZ{3T%8ow1a7soZ34m(=ZZRGup)P&R~m*H`J;J42h_Zfl}n zA_HS(r>qlGB6&(^&>IjIW()T=5zSbwL`2|AGI25QGUmrYdH69NqXuTQ>tBOB)5!72 z-UPs%rZ_`Cng6Hx70k$D|30H_uhR`^**Qt*iSn$B_R{HW^^yR#db8{}r}dX5o?*uX zoueo*Cv}l<@Zn`UT8wR{!FT2jH9J2}G5>2$nEmB7vN~vQXh*Uv?^R`?qpTdW^`__h z^tY4Ih*K}CSsP+1Ltw?+@#<}tZ^?-!0fA7{V7ka|gJ;t(MR!|hiw|Ur;+?8pq}%;p zT<@UUF6I@_ql6JK*KzOA&lf^}@nD8d4lva#*YeT3_!*nyxKk6sfVVTK=}c9!^hQ#G zCxJU(xsLsfz_unhiTu1!ZiEbhb>46PIT`f(pJq28=r<@7vK)X8HwYAte38JTi#puO z=+-Y8OGl&Ub0T?yzyhg2jc%h`_MnAv8KnE$PWZf496%`A)-57n?yJ8?piN4`HI)95&p3-O(8I~y|t3Z zZnCw>Emlc0m8o_^4im3JPMPq{4M?%;0B{@Zg9F(Iu84I(8WZ(&*z*p zJUOSQie!6@ArJqOxHW*;Lh*WG8j`61I6bN_m+cr_C#gbK(`5g`qZrf|ATGk{C#Y%_ z*jT7fEURMjRE&YVgzp25K$PTv`oGd=pOF+FU%T#9=xc(~D2mbay`Dt6HG$L^7iFA4 zEP1f%jo3PS_}?OaFyklaMXH*;U3odz1H@M>9wN}yZe9Xhx(pViY)F278B%44@n#|D zwgpO3KZpvYm_BHqd$IJ8Z;>BOl~xLm`bW8e$dOaFn3x^SgiP0M`~6eoXqc4OmmP42 z>YRNa*txAxsL}h^Cm<2B@%rv5+Wup&0OuL)XTQH_2`#dAj@&JE6l1Vi8RMswIZo3# z0@yJu2v?t}>tEfZJTc)Ku6N|Py@sz*WH{#^Quvx&5q>DQbOo=kl2x1m`S0N4v2vu{!7BKGYW zAKdUk+B$BVhg|v27N~jd=f%6O7beFYo~2DS2`jZU_`2JfXcx51<6GlQJg62Qv!+#N zlzLha;D0gy^Q@Z$_fRtV6o7e-c(v&A|I{4e=Ejq17-6H zR=WWvWvjN0KMTcFYN*iF<@q->cLFnE&zfZ!Pfse5)bX53)nxDCt;2V{wgjT77w0#t>r-H6Z( z`*1qpuzr_1U6F3M^SC|NkH=ss=O}ixR)|x+ZwZCqM<338%`Tm**k0OVStieRvLJ_HX)|J}xR-a{naAQOXg+IW24?5eA9p@Co z!!lk|?%wP5 z7R|<61xM>*d@hD4YZd~jFhg(cMvIyoOMJNvzISBJ4CrhwqrgfdduQH%mb3z=-ef8C zfw$1B&!Y!|p1CUPnR3w1t@nH+YQHWtKc5!KDKbFm{ySz&f=qxp^-_8-KvsY(^Gzbo zE3L#b*7-DmcNzX7(KpqVudTN8hEsJGnP{c0+YYpW4a^Z!W;LneL1q2IMUZRG9N}T3 zw)htjrwZi3n4gwO$rktLHVt8o3JVe3*1Ie|vx0nYV$#3!|4V2fl4>@t%?zZT7XO&PX*kd6nTt+Old2Zb*+lHR?QEV?ziqgK`>k!2<_vq~dc zWkha8Hfuvrx$Dj(bXwK^)aDtV{1e$@?e`05;Wq?=zOXvqS?a}v|LEri#2%41@0uOG zvOVB$UUm#`zk7pdh(UU|or)($@0{7^{$(EQPi$l&@%!h#+t)r79_L8| z7uiM(+h7hwwdKS)Cv9H?-|Z#)-|Cb|>XW=!e=1r2zV1yg8vgY>@)7IHjo4tvM@?Wi zeVL*>9<$gRH6ni#PyHW5*sn^Bu0FL3XK*hqh5e(E5cD-%EdG>(TQlenlAY|=YYrrM z05)<1({&vD=s&>nfnnAc?Hag0)-93u%BkaD0Qg3eG~6;}H;zhV^{0y}(R{0A>OG!;S@ z5ifmO)QV*1WZh%yY#o9IF1#qE-R}icG1l4Cz(5!azbutu^3DF5>=qpX=a^ADYPzZA zuU`sTZRg~2f(%}89P&*bet9-38eLof)qKEb|KMtXV{3}(xTk2I(jxN*NI?GkzdVTo ztR*8-pHLwz^w0Y0;^!vNgLB=`13nRFdV}~_XNtU&iGxX4D*Ip4Dfi12-2#>o>Agw? zb(%@{$7HAXM$!s_bPc{ZyR)-7wpA%S85Jimyv|P)mUap$#h;r>v?}nr%b#S;C#bfeo7kV|N(fcU+Hmt13wHRmbDaevdESS` zc{Ce5?PCV}oc@)erBHB$dicgxaI3=t(Pmxbn+PcwnhvBtkaJ`eA+_2_9N{_fBZ4%RQtg=-%QEwZ0>=F3J3eGuw?#`h~x z3wP)9efUyv&a-#8ap$^{(ewW5?@4|W6KJj-@GKX~knjYZmSn;43iaBdu}b2I&A&3V z4bT&F379645D=A+#hBZU`~}><(NbS9WXD#pD+(hcy`)A(U z%H^rW)k^-j1p@9!#C9R;isty$bgis&~I%?_dzMi18I0$7pckPXniy-QT;w!}E&q<)TSB)#s-znswzeB5?A^ENOD;DcjD^quM}I+*Se-0lt*5 zmdzOcI)D2B((e;k6;YAh@8yQgFd;{}uuR+qvaK^{^F=#>K$m;4BS_OFot?eia!X5V zYjfj#bAz5eKl#DAwQGf5>F`J*=GGoe3~}?SJs06Qn>RutBB>6J|49**yzLn%<6|Un zJg9@qr{+o3C$da^3N1Z>@VE?TS&^VYg@=wN6IQ*8j3yyePj;!3RZnKX$Emy*>xMOa z6!y#8eTgw~m;Ob}1_Ud?2SgmZ0*utG;ym}*K)6D|S$Vkk8d0WhWc&Dj!9DM{GtV?K z%eAWI{18QZ)lO$bz2mUhp<3zIge1hEg*Yr5u5 zb%mhgjB>+z<8lOhyt-D}$QF+_kL5&?v-6XLEotqNsr`tL2NPEsO)V|3l8GbK?9$EL z!TH0RcGNOz<=eM42M_r1$u4@#(nXXuLP@E|!Xl4+CxB4m5q-c9mb*hiw(lG0mq+cT z1=Xk}@Y#dY-jC7mr~h%67MY~EYhcey4~zUk=)LPZ`Ui8LBdmdXb0xuAwuIXEaV2V6 zthge?=Wq0hx7Zf5dl;t29YKh*k~9|T5f&B!W3R|o z4W>RDpPR5-VkLuAQBy|Lq|25zdB)V8VU5+h1R=%xYuD`h48D&g2ETm7eOZ8}g^IF0C5V$M!z z<AU24jg(~Q zM%s|I$b6@r*dXxLg60h3$wu~uC+H)Zv5PYBo&9VXpU(w92HdL8|C>f#Hk0jK^kuwoQ7Qv@a`UN^(7u zbpaC*MsaRhX!tzB)hcC3(V{|M!N4M2Kk?}CZ4G7ouks&-GD=_i%T&=Z??HPM2hFK* z99;mzOb{#griG@5%p*r+-lVr>G3d;#N=g;Udi}Q6Y%6;yHEqhg@v6cpt+HijyY%OF z;V(K1YQ_DbhgAO-r`(V%D`P#vAS1A6seTy3D)MZL>uF)C*McytJngPd)D@R(B%MFqNw_)CNS+iDsMFWdL^?%C>{qeiQ#
k~+&S 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 General -> Login Items**: remove CodexBar if it remains listed. +- **Keychain prompt screenshot**: capture the full prompt, especially any requesting app/path details. Redact user + names or unrelated window contents if needed, but do not include secrets. + +If you find a still-running process, quit CodexBar from the menu if possible, or quit it from Activity Monitor. If you +find another installed copy, confirm whether that copy is the one macOS names in the prompt before changing anything +else. + +## Stop CodexBar from using Keychain + +If CodexBar is still installed and you want it to stop all Keychain access: + +1. Open **CodexBar -> Settings -> Advanced**. +2. In **Keychain access**, enable **Disable Keychain access**. +3. Relaunch CodexBar. + +This disables Keychain reads and writes from CodexBar. Browser-cookie-based providers will be skipped because +CodexBar can no longer decrypt browser cookies. Manual cookie headers, API keys, and CLI/OAuth flows that do not rely +on Keychain can still work where the provider supports them. + +## Browser Safe Storage prompts + +If a Chromium-family Safe Storage check requires interaction or is denied, CodexBar pauses automatic cookie imports +for every Chromium-family browser for six hours. This prevents a denial in Arc, Edge, Brave, or another Chromium +browser from immediately moving to the next browser and showing another prompt. **Refresh Now** is an explicit retry +for the browser that was blocked; Safari and Firefox-family cookie imports remain available during the pause. + +For normal browser-cookie import prompts, either allow CodexBar in the Keychain item's Access Control list or disable +Keychain access: + +1. Open **Keychain Access.app**. +2. Select the `login` keychain. +3. Search for the item named in the prompt, for example `Chrome Safe Storage`. +4. Open the item, choose **Access Control**, and add `CodexBar.app` under "Always allow access by these applications". +5. Relaunch CodexBar. + +Avoid "Allow all applications" unless you intentionally want every app to access that item. Do not paste or share the +item's secret value when asking for help. + +## What to include in a support issue + +- CodexBar version and install source: GitHub release, Homebrew cask, Sparkle update, or another source. +- macOS version. +- The uninstall method if this happened after uninstalling. +- Whether Activity Monitor or `pgrep` still shows CodexBar. +- Whether System Settings -> General -> Login Items still lists CodexBar. +- Whether `/Applications/CodexBar.app`, Homebrew cask metadata, or Spotlight finds another copy. +- A screenshot of the Keychain prompt showing the requested item and requesting app/path, with secrets redacted. diff --git a/docs/kilo.md b/docs/kilo.md new file mode 100644 index 0000000..6425bed --- /dev/null +++ b/docs/kilo.md @@ -0,0 +1,54 @@ +--- +summary: "Kilo provider data sources: app.kilo.ai API token and CLI auth-file fallback." +read_when: + - Adding or modifying the Kilo provider + - Adjusting Kilo source-mode fallback behavior + - Troubleshooting Kilo credentials/auth sessions +--- + +# Kilo provider + +Kilo supports API and CLI-backed auth. Source mode can be `auto`, `api`, or `cli`. + +## Data sources + fallback order +1. API (`api`) + - Token from `~/.codexbar/config.json` (`providers[].apiKey` for `kilo`) or `KILO_API_KEY`. + - Calls `https://app.kilo.ai/api/trpc`. +2. CLI session (`cli`) + - Reads `~/.local/share/kilo/auth.json` and uses `kilo.access`. + - Requires a valid CLI login (`kilo login`). +3. Auto (`auto`) + - Tries API first. + - Falls back to CLI only when API credentials are missing or unauthorized (401/403). + +## Settings +- Preferences -> Providers -> Kilo: + - Usage source: `Auto`, `API`, `CLI` + - API key: optional override for `KILO_API_KEY` +- In auto mode, resolved CLI fetches can show a fallback note in menu and CLI output. + +## CLI output notes +- Kilo text output splits identity into `Plan:` and `Activity:` lines. +- Auto-mode failures include ordered fallback-attempt details in text mode. + +## Troubleshooting +- Missing API token: set `KILO_API_KEY` or provider `apiKey`. +- Missing CLI session file: run `kilo login` to create `~/.local/share/kilo/auth.json`. +- Unauthorized API token (401/403): refresh `KILO_API_KEY` or rerun `kilo login`. + +## Organizations + +CodexBar can show usage for any Kilo organization the API key belongs to. + +- Open Preferences → Providers → Kilo, set the API key, then click **Refresh + organizations**. +- Toggle the organizations you want to display alongside Personal. Personal is + always shown. +- When at least one organization is enabled, the menu renders one Kilo card per + enabled scope. +- The CodexBar fetcher sends the standard `X-KILOCODE-ORGANIZATIONID` header on + every usage call to scope the response to that organization. +- CLI source mode (`auth.json`): the header is applied to CLI-resolved tokens + as well. If a CLI token isn't authorized for the chosen organization, that + card surfaces an unauthorized error while Personal and other enabled scopes + continue to render normally. diff --git a/docs/kimi-k2.md b/docs/kimi-k2.md new file mode 100644 index 0000000..17cb469 --- /dev/null +++ b/docs/kimi-k2.md @@ -0,0 +1,45 @@ +--- +summary: "Kimi K2 provider data sources: API key + credit endpoint." +read_when: + - Adding or tweaking Kimi K2 usage parsing + - Updating API key handling or config migration + - Documenting new provider behavior +--- + +# Kimi K2 provider + +> This is a legacy, unofficial provider for the `kimi-k2.ai` credit endpoint. +> For the official Kimi API account and billing surface, use the Moonshot / Kimi +> API provider instead. + +Kimi K2 is API-only. Usage is reported by the credit counter behind +`GET https://kimi-k2.ai/api/user/credits`, so CodexBar only needs a valid API +key for that legacy endpoint to pull your remaining balance and usage. + +## Data sources + fallback order + +1) **API key** stored in `~/.codexbar/config.json` or supplied via `KIMI_K2_API_KEY` / `KIMI_API_KEY` / `KIMI_KEY`. + CodexBar stores the key in config after you paste it in Preferences → Providers → Kimi K2 (unofficial). + Surrounding whitespace is ignored before the key is sent. +2) **Credit endpoint** + - `GET https://kimi-k2.ai/api/user/credits` + - Request headers: `Authorization: Bearer `, `Accept: application/json` + - HTTP 401 is shown as an invalid or expired key; other failures keep the provider's response details. + - Response headers may include `X-Credits-Remaining`. + - JSON payload contains total credits consumed, credits remaining, and optional usage metadata. + CodexBar scans common keys and falls back to the remaining header when JSON omits it. + +## Usage details + +- Credits are the billing unit; CodexBar computes used percent as `consumed / (consumed + remaining)`. +- There is no explicit reset timestamp in the API, so the snapshot has no reset time. +- The menu's Usage Dashboard action opens the legacy service's human-facing credits page at `https://kimrel.com/my-credits`. +- A key saved in Settings takes precedence over environment variables. + +## Key files + +- `Sources/CodexBarCore/Providers/KimiK2/KimiK2ProviderDescriptor.swift` (descriptor + fetch strategy) +- `Sources/CodexBarCore/Providers/KimiK2/KimiK2UsageFetcher.swift` (HTTP client + parser) +- `Sources/CodexBarCore/Providers/KimiK2/KimiK2SettingsReader.swift` (env var parsing) +- `Sources/CodexBar/Providers/KimiK2/KimiK2ProviderImplementation.swift` (settings field + activation logic) +- `Sources/CodexBar/KimiK2TokenStore.swift` (legacy migration helper) diff --git a/docs/kimi.md b/docs/kimi.md new file mode 100644 index 0000000..fa1cc5a --- /dev/null +++ b/docs/kimi.md @@ -0,0 +1,192 @@ +--- +summary: "Kimi provider notes: cookie auth, quotas, and rate-limit parsing." +read_when: + - Adding or modifying the Kimi provider + - Debugging Kimi cookie import or usage parsing + - Adjusting Kimi menu labels or settings +--- + +# Kimi Provider + +Tracks usage for [Kimi For Coding](https://www.kimi.com/code) in CodexBar. + +## Features + +- Displays weekly request quota (from membership tier) +- Shows current 5-hour rate limit usage +- API-key, Kimi Code CLI, automatic cookie, and manual cookie authentication methods +- Automatic refresh countdown + +## Setup + +Choose one of four authentication methods: + +### Method 1: Kimi Code API Key (Recommended) + +Create an API key in the [Kimi Code Console](https://www.kimi.com/code/console), then save it in CodexBar: + +```bash +codexbar config set-api-key --provider kimi --api-key "kimi-api-key-here" +``` + +Or provide it through the environment: + +```bash +export KIMI_CODE_API_KEY="kimi-code-api-key-here" +``` + +CodexBar calls `GET https://api.kimi.com/coding/v1/usages` with the API key. Set +`KIMI_CODE_BASE_URL` only when testing a compatible HTTPS proxy or alternate host with an explicit API key. +CodexBar never forwards a Kimi Code CLI credential to an endpoint override. + +### Method 2: Kimi Code CLI + +If you are signed in with the official Kimi Code CLI, Auto mode can reuse its fresh access token from +`~/.kimi-code/credentials/kimi-code.json`. CodexBar sends the same device identity headers as the CLI, +including the local hostname, OS details, and stable `~/.kimi-code/device_id` value. If that device ID is +missing, CodexBar creates it with private file permissions to match the official client. + +CodexBar treats CLI-owned authentication as read-only: it never uses the refresh token and never rewrites +the credential file. When the access token expires, sign in again with Kimi Code CLI or configure an API +key. Set `KIMI_CODE_HOME` only when the official CLI uses a non-default home directory. + +Custom `KIMI_CODE_BASE_URL`, `KIMI_CODE_OAUTH_HOST`, and `KIMI_OAUTH_HOST` values disable CLI credential +reuse; use an explicit API key for endpoint-override testing. + +### Method 3: Automatic Browser Import + +**No setup needed!** If you're already logged in to Kimi in Arc, Chrome, Safari, Edge, Brave, or Chromium: + +1. Open CodexBar settings → Providers → Kimi +2. Set "Cookie source" to "Automatic" +3. Enable the Kimi provider toggle +4. CodexBar will automatically find your session + +**Note**: Requires Full Disk Access to read browser cookies (System Settings → Privacy & Security → Full Disk Access → CodexBar). + +### Method 4: Manual Token Entry + +For advanced users or when automatic import fails: + +1. Open CodexBar settings → Providers → Kimi +2. Set "Cookie source" to "Manual" +3. Visit `https://www.kimi.com/code/console` in your browser +4. Open Developer Tools (F12 or Cmd+Option+I) +5. Go to **Application** → **Cookies** +6. Copy the `kimi-auth` cookie value (JWT token) +7. Paste it into the "Auth Token" field in CodexBar + +### Cookie Environment Variable + +Alternatively, set the `KIMI_AUTH_TOKEN` environment variable: + +```bash +export KIMI_AUTH_TOKEN="jwt-token-here" +``` + +## Authentication Priority + +When multiple sources are available, CodexBar uses this order: + +1. API key (`providers[].apiKey` or `KIMI_CODE_API_KEY`) in Auto mode +2. Fresh Kimi Code CLI access token (`~/.kimi-code/credentials/kimi-code.json`) +3. Manual cookie/token (from Settings UI) when web fallback is used +4. Cookie environment variable (`KIMI_AUTH_TOKEN`) +5. Browser cookies (Arc → Chrome → Safari → Edge → Brave → Chromium) + +**Note**: Browser cookie import requires Full Disk Access permission. + +## API Details + +### Kimi Code API key + +**Endpoint**: `GET https://api.kimi.com/coding/v1/usages` + +**Authentication**: Bearer token (from `providers[].apiKey`, `KIMI_CODE_API_KEY`, or a fresh Kimi Code CLI credential) + +**Response**: +```json +{ + "usage": { + "limit": "2048", + "used": "214", + "remaining": "1834", + "resetTime": "2026-01-09T15:23:13.716839300Z" + }, + "limits": [{ + "window": {"duration": 300, "timeUnit": "TIME_UNIT_MINUTE"}, + "detail": { + "limit": "200", + "used": "139", + "remaining": "61", + "resetTime": "2026-01-06T13:33:02.717479433Z" + } + }] +} +``` + +### Kimi web cookie fallback + +**Endpoint**: `POST https://www.kimi.com/apiv2/kimi.gateway.billing.v1.BillingService/GetUsages` + +**Authentication**: Bearer token (from `kimi-auth` cookie) + +**Response**: +```json +{ + "usages": [{ + "scope": "FEATURE_CODING", + "detail": { + "limit": "2048", + "used": "214", + "remaining": "1834", + "resetTime": "2026-01-09T15:23:13.716839300Z" + }, + "limits": [{ + "window": {"duration": 300, "timeUnit": "TIME_UNIT_MINUTE"}, + "detail": { + "limit": "200", + "used": "139", + "remaining": "61", + "resetTime": "2026-01-06T13:33:02.717479433Z" + } + }] + }] +} +``` + +## Membership Tiers + +| Tier | Price | Weekly Quota | +|------|-------|--------------| +| Andante | ¥49/month | 1,024 requests | +| Moderato | ¥99/month | 2,048 requests | +| Allegretto | ¥199/month | 7,168 requests | + +All tiers have a rate limit of 200 requests per 5 hours. + +## Troubleshooting + +### "Kimi auth token is missing" +- Ensure "Cookie source" is set correctly +- If using Automatic mode, verify you're logged in to Kimi in your browser +- Grant Full Disk Access permission if using browser cookies +- Try Manual mode and paste your token directly + +### "Kimi auth token is invalid or expired" +- Your token has expired. Paste a new token from your browser +- If using Automatic mode, log in to Kimi again in your browser + +### "No Kimi session cookies found" +- You're not logged in to Kimi in any supported browser +- Grant Full Disk Access to CodexBar in System Settings + +### "Failed to parse Kimi usage data" +- The API response format may have changed. Please report this issue. + +## Implementation + +- **Core files**: `Sources/CodexBarCore/Providers/Kimi/` +- **UI files**: `Sources/CodexBar/Providers/Kimi/` +- **Login flow**: `Sources/CodexBar/KimiLoginRunner.swift` +- **Tests**: `Tests/CodexBarTests/KimiProviderTests.swift` diff --git a/docs/kiro.md b/docs/kiro.md new file mode 100644 index 0000000..6105698 --- /dev/null +++ b/docs/kiro.md @@ -0,0 +1,58 @@ +--- +summary: "Kiro provider data sources: CLI-based usage via kiro-cli /usage command." +read_when: + - Debugging Kiro usage parsing + - Updating kiro-cli command behavior + - Reviewing Kiro credit window mapping +--- + +# Kiro provider + +Kiro uses the AWS `kiro-cli` tool to fetch usage data. No browser cookies or OAuth flow—authentication is handled by AWS Builder ID through the CLI. + +## Data sources + +1) **CLI command** (primary and only strategy) + - Command: `kiro-cli chat --no-interactive "/usage"` + - Timeout: 20 seconds (idle cutoff after 4 seconds of no output once the CLI starts responding). + - CodexBar tries ordinary stdout/stderr pipes first for current Kiro CLI releases. Incomplete or unusable + pipe output falls back to a pseudo-terminal within the same overall command deadline for older releases. + - Requires `kiro-cli` installed and logged in via AWS Builder ID. + - Output is ANSI-decorated; CodexBar strips escape sequences before parsing. + +## Output format (example) + +``` +┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ +┃ | KIRO FREE ┃ +┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫ +┃ Monthly credits: ┃ +┃ ████████████████████████████████████████████████████████ 100% (resets on 01/01) ┃ +┃ (0.00 of 50 covered in plan) ┃ +┃ Bonus credits: ┃ +┃ 0.00/100 credits used, expires in 88 days ┃ +┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ +``` + +## Snapshot mapping + +- **Primary window**: Monthly credits percentage (bar meter). + - `usedPercent`: extracted from `███...█ X%` pattern. + - `resetsAt`: parsed from `resets on MM/DD` (assumes current or next year). +- **Secondary window**: Bonus credits (when present). + - Parsed from `Bonus credits: X.XX/Y credits used`. + - Expiry from `expires in N days`. +- **Identity**: + - `accountOrganization`: plan name (e.g., "KIRO FREE"). + - `loginMethod`: plan name (used for menu display). + +## Status + +Kiro does not have a dedicated status page. The "View Status" link opens the AWS Health Dashboard: +- `https://health.aws.amazon.com/health/status` + +## Key files + +- `Sources/CodexBarCore/Providers/Kiro/KiroProviderDescriptor.swift` +- `Sources/CodexBarCore/Providers/Kiro/KiroStatusProbe.swift` +- `Sources/CodexBar/Providers/Kiro/KiroProviderImplementation.swift` diff --git a/docs/litellm.md b/docs/litellm.md new file mode 100644 index 0000000..edd5953 --- /dev/null +++ b/docs/litellm.md @@ -0,0 +1,54 @@ +--- +summary: "LiteLLM provider setup and usage data shape." +read_when: + - Configuring LiteLLM usage tracking + - Troubleshooting LiteLLM API-key usage in CodexBar +--- + +# LiteLLM + +LiteLLM uses a virtual key plus the proxy base URL. The key reads its own identity and budget data through LiteLLM's +authenticated information endpoints. + +Configure it in Settings -> Providers -> LiteLLM, or in `~/.codexbar/config.json`: + +```json +{ + "id": "litellm", + "enabled": true, + "apiKey": "", + "enterpriseHost": "https://litellm.example.com" +} +``` + +Equivalent environment variables: + +```bash +export LITELLM_API_KEY=sk-... +export LITELLM_BASE_URL=https://litellm.example.com +``` + +`LITELLM_BASE_URL` may include `/v1`; CodexBar strips that suffix before calling LiteLLM management endpoints. + +## Data Source + +The provider calls: + +1. `GET /key/info` to discover the authenticated key's `user_id` and `team_id`. +2. `GET /user/info?user_id=` to read personal spend, budget, and teams. +3. For team-only keys without a `user_id`, `GET /team/info?team_id=` to read team spend and budget. + +All requests use `Authorization: Bearer `. CodexBar does not request or store a LiteLLM master key. + +For user-bound keys, personal usage is shown as the primary window. If the key has a team, its exact matching team +budget is shown as the secondary window and becomes the automatic menu bar metric because that budget is enforced for +the key. Team-only keys show that team budget as their sole usage window. Spend remains visible as an API-spend row +when LiteLLM does not configure a budget. + +The virtual key must be allowed to read its own `/key/info` data and the corresponding user or team information +endpoint. CodexBar validates returned user and team IDs against `/key/info` before displaying usage. + +## Security + +Treat LiteLLM keys as secrets. CodexBar stores configured keys only in provider config or token-account storage and +sends them only to the configured LiteLLM base URL. diff --git a/docs/llm-proxy.md b/docs/llm-proxy.md new file mode 100644 index 0000000..49ce39e --- /dev/null +++ b/docs/llm-proxy.md @@ -0,0 +1,41 @@ +--- +summary: "LLM Proxy provider setup and quota-stats usage source." +read_when: + - Configuring LLM Proxy usage tracking + - Debugging aggregate proxy quota or provider breakdown display +--- + +# LLM Proxy + +CodexBar reads aggregate usage from an LLM-API-Key-Proxy compatible `/v1/quota-stats` endpoint. + +## Setup + +Store the API key: + +```bash +printf '%s' "$LLM_PROXY_API_KEY" | codexbar config set-api-key --provider llmproxy --stdin +``` + +Set the base URL with `LLM_PROXY_BASE_URL`, or add `enterpriseHost` to the provider config: + +```json +{ + "id": "llmproxy", + "enabled": true, + "apiKey": "", + "enterpriseHost": "https://proxy.example.com" +} +``` + +The base URL may point at either the service root or `/v1`; CodexBar normalizes both to `/v1/quota-stats`. + +## Menu display + +- Primary: lowest remaining quota group, rendered as percent used. +- Secondary: total requests. +- Tertiary: total tokens. +- Extra rows: top provider summaries by request count. +- Cost: approximate spend when the proxy reports `approx_cost`. + +`quota_groups` may be either an array or a keyed object; CodexBar accepts both shapes. diff --git a/docs/llms.txt b/docs/llms.txt new file mode 100644 index 0000000..0b6340d --- /dev/null +++ b/docs/llms.txt @@ -0,0 +1,12 @@ +# CodexBar + +A tiny macOS menu bar app that tracks AI coding-provider usage windows, credits, costs, and resets across 59 providers — Codex, OpenAI, Claude, Cursor, Gemini, Copilot, LiteLLM, and more. + +Canonical documentation: +- CodexBar — every AI coding limit, in your menu bar: https://codexbar.app/ - A tiny macOS menu bar app that tracks AI coding-provider usage windows, credits, costs, and resets across 59 providers — Codex, OpenAI, Claude, Cursor, Gemini, Copilot, LiteLLM, and more. + +Source: https://github.com/steipete/CodexBar + +Guidance for agents: +- Prefer the canonical documentation URLs above over README excerpts or package metadata. +- Fetch only the pages needed for the current task; this is an index, not a full-site corpus. diff --git a/docs/logos/abacus-ai-dark.svg b/docs/logos/abacus-ai-dark.svg new file mode 100644 index 0000000..468bb3d --- /dev/null +++ b/docs/logos/abacus-ai-dark.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/docs/logos/abacus-ai.png b/docs/logos/abacus-ai.png new file mode 100644 index 0000000000000000000000000000000000000000..46572923b9cf043761c62444a148f58fa8de1654 GIT binary patch literal 4166 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 literal 0 HcmV?d00001 diff --git a/docs/logos/alibaba.svg b/docs/logos/alibaba.svg new file mode 100644 index 0000000..bb458d7 --- /dev/null +++ b/docs/logos/alibaba.svg @@ -0,0 +1 @@ +Alibaba \ No newline at end of file diff --git a/docs/logos/amp.svg b/docs/logos/amp.svg new file mode 100644 index 0000000..f8f9d31 --- /dev/null +++ b/docs/logos/amp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/logos/antigravity.svg b/docs/logos/antigravity.svg new file mode 100644 index 0000000..3ed10ab --- /dev/null +++ b/docs/logos/antigravity.svg @@ -0,0 +1 @@ +Antigravity \ No newline at end of file diff --git a/docs/logos/augment.svg b/docs/logos/augment.svg new file mode 100644 index 0000000..5e81dd2 --- /dev/null +++ b/docs/logos/augment.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/docs/logos/chutes.svg b/docs/logos/chutes.svg new file mode 100644 index 0000000..ff752b4 --- /dev/null +++ b/docs/logos/chutes.svg @@ -0,0 +1,7 @@ + + Chutes + + + + + diff --git a/docs/logos/claude.svg b/docs/logos/claude.svg new file mode 100644 index 0000000..62dc0db --- /dev/null +++ b/docs/logos/claude.svg @@ -0,0 +1 @@ +Claude \ No newline at end of file diff --git a/docs/logos/codebuff-dark.svg b/docs/logos/codebuff-dark.svg new file mode 100644 index 0000000..6d5f9e4 --- /dev/null +++ b/docs/logos/codebuff-dark.svg @@ -0,0 +1,4 @@ + + + + diff --git a/docs/logos/codebuff.png b/docs/logos/codebuff.png new file mode 100644 index 0000000000000000000000000000000000000000..47b4b7beea8b86138062ad8659b21124effeed52 GIT binary patch literal 770 zcmeAS@N?(olHy`uVBq!ia0vp^Ye1L-NH83Zl3)Q+Ea{HEjtmSN`?>!lvI6-E$sR$z z3=CCj3=9n|3=F@3LJcn%7)lKo7+xhXFj&oCU=S~uvn$XBD8ZEE?e4gnPbQgQ3;?Tdl80|eY2 zmbNkFahi*|ymXLVz^5QPgKGivivymlhN35ATljp~%h>Jtn|j&DX7R5qaLQ1E~0(F?qdqxMmd&|QY&~DQtmECBb>9=@>hp?A;xgWN zUCLG5__gKo-<`?D+jXS3FPmq%tuE3j?{&Z2>^y$4y48OglRs~IyEeE!KJ4Je^=8W7_~?I?ACz`@Pk!EdOzdl3Lh9c0)4p=1m6`vm zy836MXON!iwWzhR&-W((I{AHXZ!d4@ACHvKb)WA&ED#Os{?|We$K?7#(ZYS_Z=5fi z*nDI0xtilg_tkYc{>Z-_N@0?aTMx z&#%i>>eq%v4+F!L$DCD3bFM6_fAS3|s9NG0QIe8al4_M)lnSI6j0}uSbq!2(jSNGK ujI0cetqe`H4GgRd4BXw<=%HxH%}>cptHiCrOiE-D$XZWVKbLh*2~7a19Xxgb literal 0 HcmV?d00001 diff --git a/docs/logos/codebuff.svg b/docs/logos/codebuff.svg new file mode 100644 index 0000000..5791738 --- /dev/null +++ b/docs/logos/codebuff.svg @@ -0,0 +1,4 @@ + + + + diff --git a/docs/logos/codex-dark.svg b/docs/logos/codex-dark.svg new file mode 100644 index 0000000..0d789fb --- /dev/null +++ b/docs/logos/codex-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/docs/logos/codex.svg b/docs/logos/codex.svg new file mode 100644 index 0000000..c77ccfd --- /dev/null +++ b/docs/logos/codex.svg @@ -0,0 +1 @@ +Codex \ No newline at end of file diff --git a/docs/logos/copilot.svg b/docs/logos/copilot.svg new file mode 100644 index 0000000..dd11956 --- /dev/null +++ b/docs/logos/copilot.svg @@ -0,0 +1 @@ +GithubCopilot \ No newline at end of file diff --git a/docs/logos/cursor.svg b/docs/logos/cursor.svg new file mode 100644 index 0000000..e4135e1 --- /dev/null +++ b/docs/logos/cursor.svg @@ -0,0 +1 @@ +Cursor \ No newline at end of file diff --git a/docs/logos/deepseek.svg b/docs/logos/deepseek.svg new file mode 100644 index 0000000..185c108 --- /dev/null +++ b/docs/logos/deepseek.svg @@ -0,0 +1 @@ +DeepSeek \ No newline at end of file diff --git a/docs/logos/devin.svg b/docs/logos/devin.svg new file mode 100644 index 0000000..e2b1cd5 --- /dev/null +++ b/docs/logos/devin.svg @@ -0,0 +1,3 @@ + + + diff --git a/docs/logos/droid-dark.svg b/docs/logos/droid-dark.svg new file mode 100644 index 0000000..f7807d8 --- /dev/null +++ b/docs/logos/droid-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/docs/logos/droid.svg b/docs/logos/droid.svg new file mode 100644 index 0000000..38aad64 --- /dev/null +++ b/docs/logos/droid.svg @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/docs/logos/elevenlabs.svg b/docs/logos/elevenlabs.svg new file mode 100644 index 0000000..ce9145e --- /dev/null +++ b/docs/logos/elevenlabs.svg @@ -0,0 +1,4 @@ + + + + diff --git a/docs/logos/gemini.svg b/docs/logos/gemini.svg new file mode 100644 index 0000000..62681df --- /dev/null +++ b/docs/logos/gemini.svg @@ -0,0 +1 @@ +Gemini \ No newline at end of file diff --git a/docs/logos/jetbrains-ai.svg b/docs/logos/jetbrains-ai.svg new file mode 100644 index 0000000..8734b49 --- /dev/null +++ b/docs/logos/jetbrains-ai.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/logos/kilo.svg b/docs/logos/kilo.svg new file mode 100644 index 0000000..74c381b --- /dev/null +++ b/docs/logos/kilo.svg @@ -0,0 +1 @@ +Kilo Code \ No newline at end of file diff --git a/docs/logos/kimi-k2.svg b/docs/logos/kimi-k2.svg new file mode 100644 index 0000000..45b894b --- /dev/null +++ b/docs/logos/kimi-k2.svg @@ -0,0 +1 @@ +Kimi diff --git a/docs/logos/kimi.svg b/docs/logos/kimi.svg new file mode 100644 index 0000000..45b894b --- /dev/null +++ b/docs/logos/kimi.svg @@ -0,0 +1 @@ +Kimi diff --git a/docs/logos/kiro-dark.svg b/docs/logos/kiro-dark.svg new file mode 100644 index 0000000..6dfa798 --- /dev/null +++ b/docs/logos/kiro-dark.svg @@ -0,0 +1,19 @@ + + + + +Created by potrace 1.16, written by Peter Selinger 2001-2019 + + + + + diff --git a/docs/logos/kiro.svg b/docs/logos/kiro.svg new file mode 100644 index 0000000..5fe3cf6 --- /dev/null +++ b/docs/logos/kiro.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/docs/logos/litellm.svg b/docs/logos/litellm.svg new file mode 100644 index 0000000..3a6c20b --- /dev/null +++ b/docs/logos/litellm.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/docs/logos/minimax.svg b/docs/logos/minimax.svg new file mode 100644 index 0000000..b1b0a6a --- /dev/null +++ b/docs/logos/minimax.svg @@ -0,0 +1 @@ +MiniMax \ No newline at end of file diff --git a/docs/logos/mistral.svg b/docs/logos/mistral.svg new file mode 100644 index 0000000..00ee1b9 --- /dev/null +++ b/docs/logos/mistral.svg @@ -0,0 +1 @@ +Mistral AI \ No newline at end of file diff --git a/docs/logos/ollama.svg b/docs/logos/ollama.svg new file mode 100644 index 0000000..432f73e --- /dev/null +++ b/docs/logos/ollama.svg @@ -0,0 +1 @@ +Ollama \ No newline at end of file diff --git a/docs/logos/opencode-dark.svg b/docs/logos/opencode-dark.svg new file mode 100644 index 0000000..ff40ad7 --- /dev/null +++ b/docs/logos/opencode-dark.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/docs/logos/opencode.svg b/docs/logos/opencode.svg new file mode 100644 index 0000000..e215d42 --- /dev/null +++ b/docs/logos/opencode.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/docs/logos/openrouter.svg b/docs/logos/openrouter.svg new file mode 100644 index 0000000..c3ce7aa --- /dev/null +++ b/docs/logos/openrouter.svg @@ -0,0 +1 @@ +OpenRouter \ No newline at end of file diff --git a/docs/logos/perplexity.svg b/docs/logos/perplexity.svg new file mode 100644 index 0000000..42968a8 --- /dev/null +++ b/docs/logos/perplexity.svg @@ -0,0 +1 @@ +Perplexity \ No newline at end of file diff --git a/docs/logos/poe.svg b/docs/logos/poe.svg new file mode 100644 index 0000000..51f30a3 --- /dev/null +++ b/docs/logos/poe.svg @@ -0,0 +1 @@ +Poe \ No newline at end of file diff --git a/docs/logos/synthetic-dark.svg b/docs/logos/synthetic-dark.svg new file mode 100644 index 0000000..b50f4da --- /dev/null +++ b/docs/logos/synthetic-dark.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/docs/logos/synthetic.svg b/docs/logos/synthetic.svg new file mode 100644 index 0000000..87dfcb7 --- /dev/null +++ b/docs/logos/synthetic.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/logos/t3chat.svg b/docs/logos/t3chat.svg new file mode 100644 index 0000000..68a174a --- /dev/null +++ b/docs/logos/t3chat.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/docs/logos/vertex-ai.svg b/docs/logos/vertex-ai.svg new file mode 100644 index 0000000..1a6a483 --- /dev/null +++ b/docs/logos/vertex-ai.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/logos/warp.svg b/docs/logos/warp.svg new file mode 100644 index 0000000..8b12c83 --- /dev/null +++ b/docs/logos/warp.svg @@ -0,0 +1 @@ +Warp \ No newline at end of file diff --git a/docs/logos/zai-dark.svg b/docs/logos/zai-dark.svg new file mode 100644 index 0000000..9026552 --- /dev/null +++ b/docs/logos/zai-dark.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/docs/logos/zai.svg b/docs/logos/zai.svg new file mode 100644 index 0000000..4f511bd --- /dev/null +++ b/docs/logos/zai.svg @@ -0,0 +1,219 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/logos/zed.svg b/docs/logos/zed.svg new file mode 100644 index 0000000..fb03bda --- /dev/null +++ b/docs/logos/zed.svg @@ -0,0 +1,4 @@ + + Zed + + diff --git a/docs/manus.md b/docs/manus.md new file mode 100644 index 0000000..7ee9198 --- /dev/null +++ b/docs/manus.md @@ -0,0 +1,73 @@ +--- +summary: "Manus provider: browser session_id cookie auth for credit balance, monthly credits, and daily refresh tracking." +read_when: + - Adding or modifying the Manus provider + - Debugging Manus cookie imports or API responses + - Adjusting Manus usage display or credit formatting +--- + +# Manus Provider + +The Manus provider tracks credit usage on [manus.im](https://manus.im) via browser `session_id` cookie authentication. + +## Features + +- **Monthly credit gauge**: Shows Pro monthly credits used vs. plan total (`proMonthlyCredits` − `periodicCredits`). +- **Daily refresh gauge**: Shows daily refresh credits used vs. max refresh allotment, with reset timing. +- **Balance display**: Total credits available, shown in the menu identity line. +- **Cookie auth**: Automatic browser cookie import (Safari, Chrome, Firefox) or manual cookie header. +- **Env var support**: `MANUS_SESSION_TOKEN` (raw token) or `MANUS_COOKIE` (full cookie header) for CLI/headless usage. + +## Setup + +1. Open **Settings → Providers** +2. Enable **Manus** +3. Log in to [manus.im](https://manus.im) in your browser +4. Cookie import happens automatically on the next refresh + +### Manual cookie mode + +1. In **Settings → Providers → Manus**, set Cookie source to **Manual** +2. Open your browser DevTools on `manus.im`, copy the `Cookie:` header from any API request (must contain `session_id=...`) +3. Paste the header into the cookie field in CodexBar + +### Environment variables (CLI / headless) + +- `MANUS_SESSION_TOKEN`: the raw `session_id` value. +- `MANUS_COOKIE`: a full cookie header; the provider extracts `session_id` from it. + +Either works; raw-token form is preferred when only one value is needed. + +## How it works + +A single API endpoint is fetched with a bearer token derived from the `session_id` cookie value: + +- `POST https://api.manus.im/user.v1.UserService/GetAvailableCredits` — returns credit fields including `totalCredits`, `freeCredits`, `periodicCredits`, `proMonthlyCredits`, `refreshCredits`, `maxRefreshCredits`, `nextRefreshTime`, and `refreshInterval`. + +Cookie domain: `manus.im`. Valid `session_id` cookies are cached in Keychain and reused until the session expires. + +The response parser tolerates both a direct object and common envelope shapes (`data` / `result` / `response` / `availableCredits`). Payloads missing all expected credit fields are rejected as a parse error rather than surfacing a misleading zero-credit snapshot. + +## Token accounts + +Manus supports multiple accounts via the standard token-account mechanism. Add entries to `~/.codexbar/config.json` (`tokenAccounts`) with the full `Cookie:` header (containing `session_id=...`), then switch between accounts from the menu. + +## CLI + +```bash +codexbar usage --provider manus --verbose +``` + +## Troubleshooting + +### "No Manus session token provided" + +Log in to [manus.im](https://manus.im) in a supported browser (Safari, Chrome, Firefox), then refresh CodexBar. Alternatively, set `MANUS_SESSION_TOKEN` or `MANUS_COOKIE`, or paste a cookie header in manual mode. + +### "Invalid Manus session token" + +Your session has expired or been revoked. Log out and back in to Manus, or paste a fresh `Cookie:` header in manual mode. + +### "Response missing expected credits fields" + +The API returned a 200 response that doesn't look like a credits payload (often an error object). Re-login to Manus; if it persists, the upstream response schema may have changed. diff --git a/docs/mimo.md b/docs/mimo.md new file mode 100644 index 0000000..6083fbb --- /dev/null +++ b/docs/mimo.md @@ -0,0 +1,99 @@ +--- +summary: "Xiaomi MiMo provider notes: cookie auth, balance endpoint, and setup." +read_when: + - Adding or modifying the Xiaomi MiMo provider + - Debugging MiMo cookie import or balance fetching + - Explaining MiMo setup and limitations to users +--- + +# Xiaomi MiMo Provider + +The Xiaomi MiMo provider tracks your current balance from the Xiaomi MiMo console. + +## Features + +- **Balance display**: Shows total balance plus paid and granted components when MiMo returns them. +- **Token plan usage**: Shows current token-plan credits while retaining balance as a second metric. +- **Cookie-based auth**: Uses browser cookies or a pasted `Cookie:` header. +- **Near-real-time updates**: Balance usually reflects within a few minutes. + +## Setup + +1. Open **Settings → Providers** +2. Enable **Xiaomi MiMo** +3. Leave **Cookie source** on **Auto** (recommended) + +CodexBar imports cookies from these browsers in order: **Safari**, **Chrome** / **Chrome Beta** / **Chrome Canary**, **Firefox**, and **Microsoft Edge**. Switch to **Manual** and paste a `Cookie:` header if your active MiMo session lives in Arc, Brave, or another browser profile CodexBar does not auto-detect. + +Safari cookie import may require granting CodexBar Full Disk Access in **System Settings → Privacy & Security**. + +### Manual cookie import (optional) + +1. Open `https://platform.xiaomimimo.com/#/console/balance` +2. Copy a `Cookie:` header from your browser’s Network tab +3. Paste it into **Xiaomi MiMo → Cookie source → Manual** + +## How it works + +- Fetches balance and token-plan detail/usage endpoints under `https://platform.xiaomimimo.com/api/v1` +- Requires the `api-platform_serviceToken` and `userId` cookies +- Accepts optional MiMo cookies like `api-platform_ph` and `api-platform_slh` when present +- Supports `MIMO_API_URL` to override the base API URL for testing. Override values must be explicit HTTPS URLs or + bare hosts/paths that CodexBar normalizes to HTTPS. Explicit `http://` values fail closed before MiMo cookies are + attached to a request, and invalid endpoint overrides do not fall back to local MiMo usage accounting. + +## Limitations + +- Token cost, status polling, and debug log output are not supported yet +- Widgets do not support Xiaomi MiMo yet +- Auto import covers Safari, Chrome variants, Firefox, and Edge only; other browsers use **Manual** mode + +## Troubleshooting + +### “No Xiaomi MiMo browser session found” + +Log in at `https://platform.xiaomimimo.com/#/console/balance` in Safari, Chrome, Firefox, or Edge, then refresh CodexBar. If your session lives in another browser, switch the MiMo provider to **Cookie source → Manual** and paste the `Cookie:` header instead. + +### “Xiaomi MiMo requires the api-platform_serviceToken and userId cookies” + +The pasted header or imported browser session is missing required cookies. Re-copy the request from the balance page after logging in again. + +### “Xiaomi MiMo browser session expired” + +Your MiMo login is stale. Sign out and back in on the MiMo site, then refresh CodexBar. + +## Local fallback (opt-in) + +When the platform.xiaomimimo.com cookie path is unavailable — Chrome session cookies expire on Chrome relaunch, Chrome Safe Storage keychain access blocked, no SSO login from this machine, etc. — and you drive MiMo inference through a local wrapper such as `cc-mimo` (Claude Code CLI with `ANTHROPIC_BASE_URL=https://token-plan-sgp.xiaomimimo.com/anthropic`), CodexBar can surface **local token accounting** from that wrapper’s session jsonl as graceful degradation — the MiMo card shows lifetime/weekly token sums instead of `login required`. + +This fallback is **implicit opt-in**: it only activates when `~/.codexbar/mimo-local-usage.json` exists. Users who do not run a local wrapper see no change. + +### Setup (optional) + +1. Drop `Scripts/mimo-usage.py` (shipped with this repo) into your `PATH`: + + ```bash + ln -sf "$(pwd)/Scripts/mimo-usage.py" ~/.local/bin/mimo-usage + chmod +x ~/.local/bin/mimo-usage + ``` + +2. Run `mimo-usage --update` once to populate `~/.codexbar/mimo-local-usage.json`. The tracker scans `~/.claude-envs/mimo/.claude/projects/**/*.jsonl` (default path for a `cc-mimo`-style wrapper) and aggregates input, output, cache-read, and cache-creation tokens per time window (today / this week / all time). + +3. Trigger updates either on each wrapper invocation (recommended — call `mimo-usage --update` post-exec from your MiMo CLI launcher) or via a `launchd` / `cron` job every 5 minutes. + +4. CodexBar picks up the file on its next refresh. The MiMo card displays `Xiaomi MiMo (local)` with a `Local · · · · ` summary and the cache's actual update time. Local activity is not rendered as a quota percentage. The `Balance updates / Daily billing finalizes` footer is suppressed for `local` source since neither applies. Because CodexBar only reads this cache (it never regenerates it), a summary whose cache has not refreshed within 12 hours gets a `stale ` marker (e.g. `stale 34d`) so a frozen tracker is not misread as live usage — re-run `mimo-usage --update`, or add the scheduled job in step 3, to clear it. + +### Wrapper integration example + +```bash +"$CLAUDE_CLI" "$@" +_exit=$? +mimo-usage --update 2>/dev/null || true +exit $_exit +``` + +### Limitations + +- **Local accounting only** — this is not real platform quota. The Xiaomi platform may rate-limit your account before your local counter reflects it. +- Override the session root with `MIMO_CLAUDE_HOME` and the cache path with `MIMO_LOCAL_USAGE_PATH` when a wrapper uses non-default locations. +- Cache schema (`~/.codexbar/mimo-local-usage.json`) is internal; do not rely on the JSON shape for external tooling. diff --git a/docs/minimax.md b/docs/minimax.md new file mode 100644 index 0000000..82ae1d1 --- /dev/null +++ b/docs/minimax.md @@ -0,0 +1,95 @@ +--- +summary: "MiniMax provider data sources: Coding Plan tokens, browser cookies, and web-session parsing." +read_when: + - Debugging MiniMax usage parsing + - Updating MiniMax cookie handling or coding plan scraping + - Adjusting MiniMax provider UI/menu behavior +--- + +# MiniMax provider + +MiniMax supports Coding Plan API tokens or web sessions. Web-session mode uses MiniMax browser/session state and +falls back across the provider's supported web requests when needed. + +## Data sources + +1) **Coding Plan API token** + - Set in Preferences → Providers → MiniMax (stored in `~/.codexbar/config.json`), `MINIMAX_CODING_API_KEY`, + or `MINIMAX_API_KEY`. + - When both environment variables are present, `MINIMAX_CODING_API_KEY` wins so a standard `sk-api-*` key does + not mask a coding-plan `sk-cp-*` key. + - Auto mode can fall back to the web/cookie path when API-token credentials are rejected or the global endpoint + returns 404. + +2) **Cached/imported browser session** (automatic web path) + - Uses CodexBar's standard cookie cache and browser import flow. + +3) **Browser cookie import** (automatic) + - Uses provider metadata for browser order and MiniMax domain filters. + - Chromium browser storage can supplement imported cookies with access-token context when available. + +4) **Manual session cookie header** (optional web-path override) + - Stored in `~/.codexbar/config.json` via Preferences → Providers → MiniMax (Cookie source → Manual). + - Accepts a raw `Cookie:` header or a full "Copy as cURL" string. + - Low-level no-settings runtime can read `MINIMAX_COOKIE` or `MINIMAX_COOKIE_HEADER`. + +## Requests +- Web sessions use the global host or China mainland host. +- Region picker in Providers settings toggles the host; environment overrides: + - `MINIMAX_HOST=platform.minimaxi.com` + - `MINIMAX_CODING_PLAN_URL=...` (full URL override) + - `MINIMAX_REMAINS_URL=...` (full URL override) +- Security policy: endpoint overrides are only accepted when they use `https://`, omit userinfo, and do not contain encoded host delimiters. Custom HTTPS proxy/test domains continue to work for compatibility, but `http://` endpoints are rejected so cookies and authorization headers are not sent in cleartext. +- Strict provider-host mode: set `MINIMAX_REQUIRE_PROVIDER_ENDPOINT_OVERRIDES=true` to additionally reject custom proxy/test domains and only accept MiniMax-owned hosts under `minimax.io` or `minimaxi.com`. + +## Cookie capture (optional override) +- Open the Coding Plan page and DevTools → Network. +- Select the request to `/v1/api/openplatform/coding_plan/remains`. +- Copy the `Cookie` request header (or use “Copy as cURL” and paste the whole line). +- Paste into Preferences → Providers → MiniMax only if automatic import fails. + +## Snapshot mapping +- Primary usage, reset timing, and plan/tier are derived from Coding Plan response fields or page text. +- Web-session billing history, when available, is mapped into the shared inline usage dashboard: + - 30-day token trend. + - Top model and top method breakdowns. + - Summary rows for recent billing-history totals. + +If the billing-history endpoint is unavailable but normal Coding Plan quota data is present, CodexBar still shows the +quota card and omits the chart instead of treating the whole provider as failed. + +## Key files +- `Sources/CodexBarCore/Providers/MiniMax/MiniMaxUsageFetcher.swift` +- `Sources/CodexBarCore/Providers/MiniMax/MiniMaxProviderDescriptor.swift` +- `Sources/CodexBar/Providers/MiniMax/MiniMaxProviderImplementation.swift` + +## CLI diagnose command + +The generic `diagnose` command performs a real provider diagnostic invocation and emits a safe, redacted JSON export +for issue reporting and verification. MiniMax adds a provider-specific `details` block with safe usage metadata. + +### Usage +``` +codexbar diagnose --provider minimax --format json --pretty +``` + +### Output +- Structural diagnostic JSON with provider, source/source mode, auth summary, usage summary, fetch attempts, and error categories. +- Per-service quota percentages, used values, limits, remaining values, reset metadata, and unlimited state. These are + the same non-secret values shown in the menu and help diagnose boosted quota denominators. +- All sensitive fields (API tokens, cookies, emails, auth headers) are redacted via `LogRedactor`. +- Errors are mapped to safe categories (`network`, `auth`, `api`, `parse`) with user-friendly descriptions. +- No raw API responses, raw error messages, tokens, cookies, emails, account IDs, org IDs, or billing history. + +### What is excluded from output +- Raw API tokens (`sk-cp-*`, `sk-api-*`) and authorization headers +- Cookie header values +- Email addresses +- Account IDs, org IDs +- Raw error messages (replaced with safe category-based descriptions) +- Raw HTTP responses or request bodies +- Billing history details + +### Exit codes +- `0`: Diagnostic completed successfully (even if provider auth is not configured) +- `1`: Unknown error or invalid arguments diff --git a/docs/mistral.md b/docs/mistral.md new file mode 100644 index 0000000..3a98397 --- /dev/null +++ b/docs/mistral.md @@ -0,0 +1,76 @@ +--- +summary: "Mistral provider: browser cookie setup, billing usage, credit balance, and Vibe monthly-plan usage." +read_when: + - Configuring Mistral usage + - Debugging Mistral billing or Vibe usage requests + - Adjusting Mistral cost, credit, or monthly-plan display +--- + +# Mistral Provider + +CodexBar reads Mistral billing usage with the Mistral web session from `admin.mistral.ai`. It can also fetch credit +balance and, when the required CSRF/session cookies are present, best-effort Mistral Vibe monthly-plan usage. + +## Setup + +1. Open **Settings -> Providers**. +2. Enable **Mistral**. +3. Sign in to [Mistral Admin](https://admin.mistral.ai/organization/usage) in Chrome. +4. Leave Cookie source on **Automatic**, or switch to **Manual** and paste a `Cookie:` header from a request to + `admin.mistral.ai`. + +Manual cookies must include an `ory_session_*` cookie. A `csrftoken` cookie enables authenticated billing and Vibe +requests that require the `X-CSRFTOKEN` header. + +## Data Sources + +CodexBar requests the current UTC month from Mistral Admin: + +- `GET https://admin.mistral.ai/api/billing/v2/usage?month=&year=` +- `GET https://admin.mistral.ai/api/billing/credits` (best-effort credit balance) + +When a CSRF token is available, CodexBar also makes a bounded best-effort request for Mistral Vibe plan usage: + +- `GET https://console.mistral.ai/api-ui/trpc/billing.vibeUsage?...` + +For the console request, CodexBar forwards only the `csrftoken` and `ory_session_*` cookies. Other +`admin.mistral.ai` cookies stay origin-bound. + +## Display + +- API spend is computed locally from the billing usage response's token counts and pricing table. +- Daily usage buckets feed the inline usage dashboard. +- The provider card can show credit balance when the credits endpoint returns it. +- The optional **Monthly Plan** window shows Vibe usage percentage and reset time when the console endpoint is + available. +- Token-cost history is supported through the billing web session; no local log scan is used. + +## CLI Usage + +```bash +codexbar usage --provider mistral --verbose +``` + +## Troubleshooting + +### "No Mistral session cookies found" + +Sign in to [Mistral Admin](https://admin.mistral.ai/organization/usage) in Chrome, then refresh. + +### "Mistral cookie header is invalid" + +In manual mode, paste a full `Cookie:` header from an `admin.mistral.ai` request. The header must include an +`ory_session_*` cookie. + +### Credits or Vibe plan usage are missing + +The billing usage request is required. Credits and Vibe usage are best-effort; if either optional endpoint fails or +does not expose data for the account, CodexBar keeps the main Mistral usage result. + +## Related Files + +- `Sources/CodexBarCore/Providers/Mistral/MistralProviderDescriptor.swift` +- `Sources/CodexBarCore/Providers/Mistral/MistralUsageFetcher.swift` +- `Sources/CodexBarCore/Providers/Mistral/MistralModels.swift` +- `Sources/CodexBarCore/Providers/Mistral/MistralCookieImporter.swift` +- `Sources/CodexBar/Providers/Mistral/MistralProviderImplementation.swift` diff --git a/docs/model-pricing.md b/docs/model-pricing.md new file mode 100644 index 0000000..1b4b2f0 --- /dev/null +++ b/docs/model-pricing.md @@ -0,0 +1,42 @@ +--- +summary: "models.dev pricing metadata pipeline, cache, lookup rules, and token-cost units." +read_when: + - Updating models.dev pricing metadata support + - Debugging model-pricing cache refresh or lookup behavior + - Routing provider cost calculations through shared pricing metadata +--- + +# Model pricing metadata + +CodexBar has an additive models.dev pricing pipeline for future cost lookup work. Existing hardcoded pricing remains unchanged for now. + +## Source and cache + +- Source API: `https://models.dev/api.json` +- No API key is required. +- Local cache: `~/Library/Caches/CodexBar/model-pricing/models-dev-v1.json` +- TTL: 24 hours + +The pipeline lets future scanner code read the last valid cache synchronously with `ModelsDevPricingPipeline.lookup` and refresh stale metadata separately with `ModelsDevPricingPipeline.refreshIfNeeded`. If a refresh fails, the last valid cache remains usable. + +## Lookup rules + +Pricing is scoped by provider id and model id. This prevents two providers with the same model id or display name from sharing pricing accidentally. + +Planned local source mapping: + +- Codex/OpenAI logs: models.dev provider id `openai` +- Claude logs: models.dev provider id `anthropic` +- Vertex AI Claude logs: models.dev provider id `google-vertex-anthropic` + +The first integration PR only adds the parser, client, cache, provider-scoped lookup, and tests. It does not route live cost calculations through models.dev yet. + +## Units + +models.dev publishes costs as USD per 1M tokens. CodexBar converts those to USD per token in the metadata layer: + +```text +perToken = modelsDevCost / 1_000_000 +``` + +When models.dev includes `cost.context_over_200k`, CodexBar parses those values as the above-200k-token pricing lane and converts them with the same per-1M-token rule. diff --git a/docs/moonshot.md b/docs/moonshot.md new file mode 100644 index 0000000..b57ce8a --- /dev/null +++ b/docs/moonshot.md @@ -0,0 +1,50 @@ +--- +summary: "Moonshot / Kimi API provider data sources: API key + balance endpoint." +read_when: + - Adding or tweaking Moonshot balance parsing + - Updating Moonshot / Kimi API key handling + - Documenting Moonshot / Kimi API provider behavior +--- + +# Moonshot / Kimi API provider + +Moonshot / Kimi API is API-only. Balance is reported by `GET /v1/users/me/balance`, +so CodexBar only needs a valid API key to show the current account balance. + +## Rationale + +Kimi API docs use the Moonshot API surface for current Kimi models: examples read +`MOONSHOT_API_KEY` and call `https://api.moonshot.ai/v1`, including the Kimi K2.6 +quickstart. This provider is therefore named after the account and billing surface, +not a specific Kimi model version. + +The existing `Kimi K2` provider remains separate because it targets the legacy +`kimi-k2.ai` credit endpoint. Migrating or deprecating that provider should be a +separate cleanup so existing user settings are not silently repointed. + +## Data sources + +1. **API key** stored in `~/.codexbar/config.json` or supplied via `MOONSHOT_API_KEY` / `MOONSHOT_KEY`. + CodexBar stores the key in config after you paste it in Settings → Providers → Moonshot / Kimi API. +2. **Region** + - International: `https://api.moonshot.ai/v1/users/me/balance` + - China mainland: `https://api.moonshot.cn/v1/users/me/balance` + - Configure with Settings → Providers → Moonshot → API region or `MOONSHOT_REGION`. +3. **Balance endpoint** + - Request headers: `Authorization: Bearer `, `Accept: application/json` + - Response contains `available_balance`, `voucher_balance`, and `cash_balance`. + +## Usage details + +- The menu card shows the available balance. +- If `cash_balance` is negative, the card also surfaces the deficit. +- There is no session or weekly window — Moonshot / Kimi API does not expose per-window quota via API. +- Settings config takes precedence over environment variables when both are present. + +## Key files + +- `Sources/CodexBarCore/Providers/Moonshot/MoonshotProviderDescriptor.swift` (descriptor + fetch strategy) +- `Sources/CodexBarCore/Providers/Moonshot/MoonshotUsageFetcher.swift` (HTTP client + JSON parser) +- `Sources/CodexBarCore/Providers/Moonshot/MoonshotSettingsReader.swift` (env var resolution) +- `Sources/CodexBar/Providers/Moonshot/MoonshotProviderImplementation.swift` (settings field + activation logic) +- `Sources/CodexBar/Providers/Moonshot/MoonshotSettingsStore.swift` (SettingsStore extension) diff --git a/docs/ollama.md b/docs/ollama.md new file mode 100644 index 0000000..2da6c9f --- /dev/null +++ b/docs/ollama.md @@ -0,0 +1,66 @@ +--- +summary: "Ollama provider notes: API key auth, settings scrape, cookie auth, and Cloud Usage parsing." +read_when: + - Adding or modifying the Ollama provider + - Debugging Ollama cookie import or settings parsing + - Adjusting Ollama menu labels or usage mapping +--- + +# Ollama Provider + +The Ollama provider can verify Ollama Cloud API-key access and scrape the **Plan & Billing** page to extract Cloud +Usage limits for session and weekly windows. + +## Features + +- **Plan badge**: Reads the plan tier (Free/Pro/Max) from the Cloud Usage header. +- **Session + weekly usage**: Parses the percent-used values shown in the usage bars. +- **Reset timestamps**: Uses the `data-time` attribute on the “Resets in …” elements. +- **API key auth**: Verifies direct `https://ollama.com/api` access with `OLLAMA_API_KEY` or a configured key. +- **Browser cookie auth**: Required for Cloud Usage quota windows because Ollama does not expose those limits through + the documented API. + +## Setup + +1. Open **Settings → Providers**. +2. Enable **Ollama**. +3. For API-key mode, paste an API key from `https://ollama.com/settings/keys` or set `OLLAMA_API_KEY`. +4. For quota bars, leave **Cookie source** on **Auto** (recommended, imports Chrome cookies by default). + +Ollama API keys currently do not expire, but they can be revoked from the key settings page. + +### Manual cookie import (optional) + +1. Open `https://ollama.com/settings` in your browser. +2. Copy a `Cookie:` header from the Network tab. +3. Paste it into **Ollama → Cookie source → Manual**. + +## How it works + +- API-key mode first probes the authenticated `https://ollama.com/api/web_search` endpoint without performing a + search, then fetches `https://ollama.com/api/tags` for the model catalog. The catalog endpoint is public and cannot + verify a key by itself. +- Cookie mode fetches `https://ollama.com/settings` using browser cookies. +- Cookie discovery recognizes the current WorkOS AuthKit `wos-session` cookie alongside legacy Ollama and NextAuth + session names. +- Redirects from settings to `/signin` or the WorkOS AuthKit authorization page are treated as expired sessions, so + CodexBar can try the next cookie candidate and show sign-in guidance instead of a parser error. +- Parses: + - Plan badge under **Cloud Usage**. + - **Session usage** and **Weekly usage** percentages. + - `data-time` ISO timestamps for reset times. + +## Troubleshooting + +### “No Ollama session cookie found” + +Sign in at `https://ollama.com/signin` in Chrome, then refresh CodexBar. +If your active session is only in Safari (or another browser), use **Cookie source → Manual** and paste a cookie header. + +### “Ollama session cookie expired” + +Sign out and back in at `https://ollama.com/signin`, then refresh. + +### “Could not parse Ollama usage” + +The settings page HTML may have changed. Capture the latest page HTML and update `OllamaUsageParser`. diff --git a/docs/openai.md b/docs/openai.md new file mode 100644 index 0000000..d81ec54 --- /dev/null +++ b/docs/openai.md @@ -0,0 +1,66 @@ +--- +summary: "OpenAI API provider: Admin API key usage/cost graphs and legacy balance fallback." +read_when: + - Updating OpenAI API Platform usage or cost display + - Debugging OPENAI_ADMIN_KEY or OPENAI_API_KEY behavior +--- + +# OpenAI API provider + +CodexBar's OpenAI API provider targets the API Platform organization dashboard, not ChatGPT/Codex subscription limits. + +## Data sources + +1. Preferred: `OPENAI_ADMIN_KEY` or configured key with Admin API access. + - `GET https://api.openai.com/v1/organization/costs` + - `GET https://api.openai.com/v1/organization/usage/completions` + - Daily buckets use `bucket_width=1d`, costs are grouped by `line_item`, and completion usage is grouped by `model`. + - Optional project scoping comes from `OPENAI_PROJECT_ID` or `providers[].workspaceID` for `openai`. + Project-scoped requests add `project_ids=` to both Admin API endpoints. +2. Best-effort fallback: legacy `GET https://api.openai.com/v1/dashboard/billing/credit_grants` for older user API + keys that cannot access organization usage. This endpoint is not part of OpenAI's current public API reference. + +## Setup + +Store a key in the shared app/CLI config: + +```bash +printf '%s' "$OPENAI_ADMIN_KEY" | codexbar config set-api-key --provider openai --stdin +``` + +Settings → Providers → OpenAI writes the same `~/.codexbar/config.json` field. `OPENAI_ADMIN_KEY` is preferred over +`OPENAI_API_KEY` because it unlocks organization costs and usage; a normal API key only supports the legacy balance +fallback. + +Project service-account keys are project-scoped credentials for API workloads. They are not organization Admin API +keys, so they cannot read the organization usage and cost endpoints used by CodexBar. Configure an organization Admin +API key instead; CodexBar reports this distinction when a project or service-account key is rejected. + +To scope Admin API usage to a project, set the OpenAI Project ID field in Settings or add `workspaceID` to the `openai` +provider config: + +```json +{ + "id": "openai", + "apiKey": "", + "workspaceID": "proj_..." +} +``` + +Project scoping is tied to the configured Admin API key. Selected OpenAI token accounts intentionally scrub +`OPENAI_PROJECT_ID`/`workspaceID` so one account cannot inherit another account's project filter. Project-scoped Admin +API failures do not fall back to the legacy billing endpoint, because that endpoint is not project-filtered. + +## Menu display + +- Admin API data renders inline Today/7d/configured-window KPIs plus a compact spend chart. +- The inline usage card opens a hosted chart submenu with daily spend, token, and request trends plus selected-day detail. +- Top model and top spend labels come from the configured completion/cost buckets when the Admin API returns them. +- Legacy balance data keeps the older available/used credit summary and does not show organization graphs. +- Project-scoped Admin API data labels the account as `Admin API: ` and the organization line as + `Project: `. + +## Notes + +- Costs are the source of truth for financial totals. Token usage and cost buckets can differ slightly from dashboard billing reconciliation. +- Admin API keys are organization-scoped and cannot be used for normal model inference. diff --git a/docs/opencode.md b/docs/opencode.md new file mode 100644 index 0000000..d65c9d5 --- /dev/null +++ b/docs/opencode.md @@ -0,0 +1,32 @@ +--- +summary: "OpenCode provider notes: browser cookies, local SQLite usage, and parsing." +read_when: + - Adding or modifying the OpenCode provider + - Debugging OpenCode usage parsing or cookie import +--- + +# OpenCode provider + +## Data sources +- Browser cookies from `opencode.ai`. +- OpenCode Go local history from `~/.local/share/opencode/opencode.db` on macOS and Linux. +- `POST https://opencode.ai/_server` with server function IDs: + - `workspaces` (`def39973159c7f0483d8793a822b8dbb10d067e12c65455fcb4608459ba0234f`) + - `subscription.get` (`7abeebee372f304e050aaaf92be863f4a86490e382f8c79db68fd94040d691b4`) + +## Usage mapping +- Primary window: rolling 5-hour usage (`rollingUsage.usagePercent`, `rollingUsage.resetInSec`). +- Secondary window: optional weekly usage (`weeklyUsage.usagePercent`, `weeklyUsage.resetInSec`). +- Resets computed as `now + resetInSec`. + +## Notes +- Responses are `text/javascript` with serialized objects; parse via regex. +- Missing workspace ID or rolling usage fields should raise parse errors; omitted weekly usage stays absent. +- OpenCode web Auto imports Chrome first, then Dia when their cookie stores exist; Keychain preflight stays scoped + to each candidate browser. Other browsers stay on Manual Cookie import until CodexBar has an explicit browser + selector. +- Set `CODEXBAR_OPENCODE_WORKSPACE_ID` to skip workspace lookup and force a specific workspace. +- Workspace override accepts a raw `wrk_…` ID or a full `https://opencode.ai/workspace/...` URL. +- Cached cookies: Keychain cache `com.steipete.codexbar.cache` (account `cookie.opencode`, source + timestamp). Browser + import only runs when the cached cookie fails. +- OpenCode Go auto mode tries web usage first, then derives quota windows from local `opencode-go` assistant costs. diff --git a/docs/openrouter.md b/docs/openrouter.md new file mode 100644 index 0000000..38a023c --- /dev/null +++ b/docs/openrouter.md @@ -0,0 +1,72 @@ +--- +summary: "OpenRouter provider: API key credits, rate limits, and daily/weekly/monthly spend." +read_when: + - Debugging OpenRouter API key usage or spend parsing + - Updating OpenRouter credits or key-limit display + - Explaining OpenRouter setup and environment variables +--- + +# OpenRouter Provider + +[OpenRouter](https://openrouter.ai) is a unified API that provides access to multiple AI models from different providers (OpenAI, Anthropic, Google, Meta, and more) through a single endpoint. + +## Authentication + +OpenRouter uses API key authentication. Get your API key from [OpenRouter Settings](https://openrouter.ai/settings/keys). + +### Environment Variable + +Set the `OPENROUTER_API_KEY` environment variable: + +```bash +export OPENROUTER_API_KEY="sk-or-v1-..." +``` + +### Settings + +You can also configure the API key in CodexBar Settings → Providers → OpenRouter. + +### CLI config + +```bash +printf '%s' "$OPENROUTER_API_KEY" | codexbar config set-api-key --provider openrouter --stdin +``` + +## Data Source + +The OpenRouter provider fetches usage data from two API endpoints: + +1. **Credits API** (`/api/v1/credits`): Returns total credits purchased and total usage. The balance is calculated as `total_credits - total_usage`. + +2. **Key API** (`/api/v1/key`): Returns rate limit information plus current daily, weekly, and monthly spend for your API key. + +## Display + +The OpenRouter menu card shows: + +- **Primary meter**: API key limit usage when the key has a configured limit +- **Spend notes**: Daily, weekly, and monthly API key spend when OpenRouter returns those fields +- **Spend chart**: Day/week/month spend can reuse the shared inline dashboard when enough history is available +- **Balance**: Displayed in the identity section as "Balance: $X.XX" + +## CLI Usage + +```bash +codexbar --provider openrouter +codexbar -p or # alias +``` + +## Environment Variables + +| Variable | Description | +|----------|-------------| +| `OPENROUTER_API_KEY` | Your OpenRouter API key (required) | +| `OPENROUTER_API_URL` | Override the base API URL (optional, defaults to `https://openrouter.ai/api/v1`) | +| `OPENROUTER_HTTP_REFERER` | Optional client referer sent as `HTTP-Referer` header | +| `OPENROUTER_X_TITLE` | Optional client title sent as `X-Title` header (defaults to `CodexBar`) | + +## Notes + +- Credit values are cached on OpenRouter's side and may be up to 60 seconds stale +- OpenRouter uses a credit-based billing system where you pre-purchase credits +- Rate limits depend on your credit balance (10+ credits = 1000 free model requests/day) diff --git a/docs/overview-scroll-stutter-investigation.md b/docs/overview-scroll-stutter-investigation.md new file mode 100644 index 0000000..d32da66 --- /dev/null +++ b/docs/overview-scroll-stutter-investigation.md @@ -0,0 +1,531 @@ +# Overview Scroll Stutter Investigation + +Status: draft context for external review +Date: 2026-06-20 +Related issue: https://github.com/steipete/CodexBar/issues/1674 +Candidate PRs: + +- Lite row: https://github.com/steipete/CodexBar/pull/1675 +- Rich row: https://github.com/steipete/CodexBar/pull/1676 + +## Purpose + +This document explains the motivation, evidence, design split, current PR state, and open review questions for the CodexBar Overview menu scroll-stutter work. It is written as a handoff document for a second reviewer, especially Claude, to review both the reasoning and the patch directions without needing to reconstruct the whole GitHub thread. + +The core question is not only "does either patch compile?" The real question is whether we chose the right boundary for reducing scroll-time work inside an `NSMenu` that hosts rich SwiftUI rows. + +## Original Problem + +The user-reported symptom is severe scroll jank in the CodexBar home / Overview menu. The problem appears on recent CodexBar builds and on multiple remote latest versions, not just one local install. + +Observed environment from the local sample: + +```text +CodexBar 0.37.0 (90) +macOS 27.0 (26A5353q) +Main-thread sample duration: 8 seconds, 1 ms interval +Main-thread sample count: 3440 +Physical footprint: 211.4M, peak 255.3M +``` + +The user described the behavior as "每次滚动的时候都会卡" while the Overview tab has multiple providers enabled. The screenshot shows the Overview tab with rich provider cards, usage bars, quota sections, cost/token history, and multiple provider entries below. + +## Evidence From The Sample + +The redacted sample summary points at menu tracking and SwiftUI row rendering/layout, not provider refresh or token-cost scanning. + +Relevant sample counts: + +```text +2222 -[NSMenuTrackingSession startRunningMenuEventLoop:] +91 -[NSContextMenuImpl _reloadData] +19 -[NSContextMenuImpl _menuBackingViewDidChangeIntrinsicSizeWithAnimation:] +23 ViewGraphRootValueUpdater.render +12 NSHostingView.hitTest +9 LazyVGridLayout lengthAndSpacing +6 -[NSView scrollWheel:] +``` + +The important interpretation is that scroll input seems to stay inside the `NSMenuTrackingSession` hot path, where AppKit repeatedly re-enters hosted SwiftUI row layout/render/hit-test work. That fits the visible symptom: jank occurs on every scroll event, even without a provider refresh being initiated. + +Two caveats a reviewer should keep in mind about how strong this sample is: + +- The `2222 startRunningMenuEventLoop` frame is the **parent** frame of all menu-tracking activity (including idle waiting), not a leaf hotspot. The meaningful work is in the much smaller leaf counts (`_reloadData 91`, `render 23`, `hitTest 12`, `LazyVGridLayout 9`). Relative to 3440 total samples, the main thread is not pegged continuously, so the jank is more consistent with **bursty per-scroll-event frame hitches** than sustained CPU saturation. This is suggestive, not conclusive — an Instruments time-profiler trace correlating scroll events with dropped frames would be the stronger proof (see "What Is Not Proven"). + +- Reading `StatusItemController+OverviewScroll.swift` makes the likely mechanism concrete. `postOverviewScrollNavigation` does two things per highlight step: it calls `self.menu(menu, willHighlight: target)` to advance highlight state immediately, **and then** posts a synthetic `.mouseMoved` event over the target row's center. On `main`, the highlight-state flip re-renders the full SwiftUI row through `MenuCardSectionContainerView` (`.environment(\.menuItemHighlighted)` + `.foregroundStyle(primary(highlighted))` + a conditional background), and the synthetic mouse-move makes AppKit re-run hit-testing down into the hosted SwiftUI tree (`NSHostingView.hitTest`). So each scroll step costs roughly **two full rich-row re-renders (old + new highlight) plus a hit-test descent**, and a single flick emits up to three steps. That double-re-render-per-step is the most plausible source of the stutter, and it is exactly the link both PRs cut at different points. + +## Source Mapping + +The sample stack maps cleanly onto current `origin/main` around commit `8c4bdd63f3d6d1432fcdb50add7ed6988a2b5734`. + +Key source paths: + +- `Sources/CodexBar/StatusItemController+Menu.swift` + - `addOverviewRows` builds each Overview provider row as a custom menu card. + - It installs provider-detail submenus and click handling. +- `Sources/CodexBar/StatusItemController+MenuTypes.swift` + - `OverviewMenuCardRowView` is the SwiftUI view rendered inside each Overview row. + - It subscribes to menu highlight environment. +- `Sources/CodexBar/MenuCardView.swift` + - `UsageMenuCardUsageSectionView` renders usage content. + - It resolves live menu-card models through `MenuCardRefreshMonitor`. +- `Sources/CodexBar/InlineUsageDashboardContent.swift` + - Uses `LazyVGrid` and mini chart/bar content. + - This matches the `LazyVGridLayout lengthAndSpacing` sample fragment. +- `Sources/CodexBar/StatusItemController+OverviewScroll.swift` + - Handles scroll-wheel navigation on Overview rows. + - Moves highlight by calling menu highlight paths and posting synthetic mouse movement over row views. + +This led to the working hypothesis: + +> The Overview tab keeps several rich SwiftUI provider cards inside an `NSMenu`; scroll/highlight/hit-test re-enters layout and rendering for those hosted rows. The hot path is row presentation and menu tracking, not provider data fetching. + +## Issue Work + +We opened issue #1674: + +https://github.com/steipete/CodexBar/issues/1674 + +Title: + +```text +v0.37.0: Overview menu stutters on every scroll event with multiple providers on macOS 27 +``` + +The issue includes: + +- Repro environment. +- Sample summary. +- Source mapping from sample stack to current main. +- Two proposed fix directions. +- Explicit note that the full sample file was not uploaded because it includes local machine paths. + +We also cc'd two earlier participants, `@Astro-Han` and `@elkaix`, in a comment on #1674 because both had described detailed menu lag in earlier issues. To be precise about attribution: `@Astro-Han` commented on #1196 (which was authored by `@vekovius`), and `@elkaix` authored #1414. The mention was intentionally limited to people with directly related prior reports, following maintainer-radar guidance. + +Note one internal inconsistency in the thread: the #1674 issue body cites the older reports as #1196, #1371, and #1387, while the cc comment (and the framing above) pairs #1196 with #1414. Both reference real prior lag reports; the difference is only which subset each surface lists. + +ClawSweeper kept the issue open. The full current label set (as of this update) is: + +- `P2` +- `clawsweeper:needs-live-repro` +- `clawsweeper:needs-maintainer-review` +- `clawsweeper:needs-product-decision` +- `clawsweeper:no-new-fix-pr` +- `issue-rating: 🐚 platinum hermit` +- `impact:other` + +The `clawsweeper:no-new-fix-pr` label is worth calling out for a reviewer: ClawSweeper does **not** recommend queueing an *automated* fix PR for this issue. The two draft PRs below are human-authored exploratory directions opened deliberately for the maintainer product decision, not automated fixes — so they are consistent with, not contradicted by, that label. + +Its acceptance criteria included: + +```text +swift test --filter StatusMenuOverviewScrollTests +swift test --filter MenuCardViewRecyclingTests +swift test --filter StatusMenuOverviewSubmenuTests +make check +On macOS 27, run a freshly built app with multiple Overview providers and capture before/after scroll profiling or visual proof. +``` + +## Why Two PRs + +There are two plausible fixes, but they make different product and engineering tradeoffs. Mixing them in one patch would make review unclear. + +So we opened two draft PRs as alternatives, not as cumulative patches: + +1. #1675: Lite row +2. #1676: Rich row with AppKit boundary + +Both PRs are draft PRs because maintainers still need to choose the desired UI/performance direction before merge. + +## PR #1675: Lite Row + +PR: https://github.com/steipete/CodexBar/pull/1675 +Branch: `codex/overview-lite-row` +Latest head at the time of this document: `6f680eeb18e37fb329cf7c26b956ded8c967a076` + +### Motivation + +If the root problem is too much hosted SwiftUI content inside the Overview menu, the lowest-risk performance path is to render less content in each Overview row. + +The Lite row direction keeps Overview as a quick provider summary: + +- Provider identity. +- Updated/subtitle state. +- Plan/account/storage text where relevant. +- A compact quota summary. +- Existing click and submenu behavior. + +It intentionally moves rich charts/details out of the Overview row and leaves them in provider detail surfaces. + +### Implementation Summary + +Changed files: + +- `Sources/CodexBar/StatusItemController+MenuTypes.swift` +- `Tests/CodexBarTests/OverviewMenuCardRowViewTests.swift` + +Key implementation points: + +- Replaced the rich `UsageMenuCardHeaderSectionView` + `UsageMenuCardUsageSectionView` Overview composition with a compact summary row. +- Added `LiteSummary`, which derives a bounded summary from precomputed `UsageMenuCardView.Model` fields. +- Explicitly avoids rendering `InlineUsageDashboardContent` in Overview rows. +- Preserves provider click behavior and provider-detail submenus. +- Preserves live subtitle and model refresh semantics through `MenuCardRefreshMonitor`. + +### ClawSweeper Finding And Fix + +ClawSweeper's concrete code finding was: + +> Use the live model for the compact summary. + +The first Lite row patch updated the subtitle through `MenuCardRefreshMonitor`, but built the compact summary and progress tint from `self.model`. That could produce a stale quota/progress summary while the subtitle had already refreshed. + +Follow-up fix: + +- Added `resolvedLiveModel(refreshMonitor:)`. +- Header, compact summary, and progress tint now all derive from the same monitor-resolved model. +- Added focused coverage proving a stale row resolves refreshed progress through the monitor without rebuilding the menu. + +New focused test: + +```text +overview lite summary uses monitor resolved refreshed model +``` + +### Validation + +Local validation run for the Lite row direction: + +```text +swift test --filter OverviewMenuCardRowViewTests +swift test --filter "overview row" +swift build +make check +git diff --check +``` + +The PR body and follow-up comment were updated, and `@clawsweeper re-review` was requested. ClawSweeper acknowledged the re-review command for head `6f680eeb`. + +### Risks + +The Lite row direction changes the product feel of Overview. It likely reduces scroll-time work, but it also removes rich chart/detail content from the Overview list. This needs maintainer/product approval. + +It still lacks an interactive after-fix scroll profile or recording. + +## PR #1676: Rich Row With AppKit Boundary + +PR: https://github.com/steipete/CodexBar/pull/1676 +Branch: `codex/overview-rich-row` +Latest head at the time of this document: `963ed4cf9941cc98300650c5532e7ffcebf1b618` + +### Motivation + +If maintainers want to preserve the current rich Overview UI, we should reduce scroll/hover overhead without removing content. + +The suspected expensive interaction is SwiftUI highlight/hit-test/layout work during `NSMenu` tracking. The rich-row direction therefore keeps the SwiftUI content but moves row-level hover/highlight/hit-test handling to a narrow AppKit wrapper. + +### AppKit Boundary + +This direction uses a small AppKit bridge: + +- SwiftUI still owns the row content and model rendering. +- SwiftUI still receives `menuCardRefreshMonitor`. +- AppKit owns only row-level: + - `hitTest` + - hover background via `CALayer` + - measured/fixed row height behavior + - recycling support + - click glue + +This follows the `build-macos-apps:appkit-interop` guidance: cross only the narrow platform boundary needed for menus instead of rewriting the feature in raw AppKit. + +### Implementation Summary + +Changed files: + +- `Sources/CodexBar/StatusItemController+Menu.swift` +- `Sources/CodexBar/StatusItemController+MenuCardItems.swift` +- `Sources/CodexBar/StatusItemController+MenuPresentation.swift` +- `Sources/CodexBar/StatusItemController+MenuTypes.swift` +- `Tests/CodexBarTests/MenuCardViewRecyclingTests.swift` + +Key implementation points: + +- Added `OverviewMenuRowHostingView`, an AppKit host for Overview rows only. +- Added `makeOverviewMenuRowItem` so normal menu cards keep the existing path. +- Moved row highlight to an AppKit `CALayer`. +- Made `hitTest` stop at the Overview row container boundary. +- Preserved provider click behavior and provider-detail submenus. +- Preserved `MenuCardRefreshMonitor` injection through `OverviewMenuRowContainerView`. +- Guarded repeated intrinsic-size invalidation when row height does not change. + +### Follow-up Test + +ClawSweeper did not report a concrete code defect for #1676. It mainly requested real behavior proof. + +We still added one lifecycle regression test after re-reviewing the AppKit bridge: + +```text +recycled overview row keeps hosting view and clears appkit highlight state +``` + +This verifies that: + +- The hosting view is recycled instead of rebuilt. +- Stale AppKit highlight state is cleared during reuse. + +### Validation + +Local validation run for the Rich row direction: + +```text +swift test --filter "overview row" +swift test --filter "highlight" +swift build +make check +git diff --check +CODEXBAR_SIGNING=adhoc ./Scripts/package_app.sh debug +codesign --verify --deep --strict --verbose=2 CodexBar.app +``` + +The follow-up validation was run on: + +```text +macOS 27.0 (26A5353q) +Apple Swift 6.4 +arm64 +``` + +The PR body and follow-up comment were updated, and `@clawsweeper re-review` was requested. ClawSweeper acknowledged the re-review command for head `963ed4cf`. + +### Risks + +The Rich row direction preserves UI density but adds a new AppKit hosting boundary. The bridge is intentionally narrow, but it touches primary menu rendering and interaction. The main residual risk is runtime behavior under a real `NSMenuTrackingSession`. + +Two specific risks a reviewer should weigh, beyond runtime behavior: + +- **Highlight appearance changes (an undisclosed visual regression).** The new `makeOverviewMenuRowItem` wraps content in `OverviewMenuRowContainerView`, which injects only `menuCardRefreshMonitor` — it does **not** inject `menuItemHighlighted`, does not apply `foregroundStyle(primary(highlighted))`, and does not draw the SwiftUI selection background that `MenuCardSectionContainerView` provides on the existing path. Because the rich header/usage subviews all read `@Environment(\.menuItemHighlighted)` (see `MenuCardView.swift`), that environment now stays `false`, so the row text **no longer inverts on highlight**. Highlight is conveyed only by the `CALayer` background (`selectedContentBackgroundColor` at alpha `0.16`). Net effect: an Overview row highlights as a faint translucent background with dark text, while every other row/submenu in the same menu still uses the standard solid-blue-with-white-text selection — an inconsistent, weaker highlight. The captured `cgColor` is also static and will not follow accent-color or light/dark changes. This is a product-visible change that the PR body currently frames as a neutral "move hover highlight to a cheap CALayer"; it should be disclosed and accepted explicitly. + +- **Duplicated hosting infrastructure.** `OverviewMenuRowHostingView` re-implements much of the existing `MenuCardItemHostingView` (`installClickRecognizer`, `acceptsFirstMouse`, `measuredHeight`, `prepareForReuse`, `allowsVibrancy`), creating two parallel menu-hosting classes to maintain. Reusing or parameterizing the existing host would be a lower-divergence design. + +It still lacks an interactive after-fix scroll profile or recording. + +## Current GitHub State + +As of the latest local `gh` check: + +- Issue #1674 is open. +- PR #1675 is open and draft. +- PR #1676 is open and draft. +- Both PRs are mergeable. +- Both PRs have follow-up commits pushed. +- Both PRs have ClawSweeper re-review queued and acknowledged. +- GitGuardian has passed on both updated heads. +- Other GitHub Actions checks may still be queued or not yet refreshed for the latest heads. + +We intentionally did not wait synchronously for all external checks, because the local proof, PR body updates, and ClawSweeper re-review requests are already done. + +## What Is Proven + +The issue is high-quality enough to keep open: + +- The user supplied a concrete symptom and sample command. +- The sample maps to current source. +- The suspect stack is tied to menu tracking and hosted SwiftUI row layout/render/hit-test. +- The current source has not meaningfully changed in the implicated files after v0.37.0. + +The Lite PR proves: + +- Overview row content can be made lightweight. +- Dashboard-heavy SwiftUI content is avoided in Overview rows. +- The compact summary uses the same monitor-resolved live model as existing usage-row logic. +- Click/submenu behavior remains covered by existing Overview tests. + +The Rich PR proves: + +- Overview can keep the rich row UI while moving highlight/hit-test to AppKit. +- AppKit highlight state is cleared on reuse. +- Overview row hosting views can be recycled. +- Existing overview row action, submenu, rendered-mode, storage text, and scroll targeting tests continue to pass. +- A debug app package can be produced and codesigned locally on macOS 27. + +## What Is Not Proven + +We still do not have the strongest proof ClawSweeper asked for: + +- No controlled before/after interactive scroll recording. +- No after-fix `sample` output captured while scrolling a provider-heavy Overview menu. +- No Instruments trace showing frame-time or main-thread stack reduction. + +This is important because unit tests can prove the row model and bridge lifecycle, but they cannot fully simulate `NSMenuTrackingSession` behavior under real trackpad/mouse-wheel input. + +## Smaller Third Direction (Candidate) + +Both PRs are fairly large for a performance fix. Given the mechanism in "Evidence From The Sample" (each scroll step costs two full rich-row re-renders plus a hit-test descent), there are two smaller, lower-commitment experiments worth trying before settling on either PR: + +1. **Decouple highlight from content re-render, SwiftUI-only.** Make the selection background the *only* thing that depends on the highlight flag, and stop re-coloring the whole subtree via `foregroundStyle(primary(highlighted))` at the container level. This is the SwiftUI-subset of what the Rich PR does in AppKit: it cuts the per-highlight re-render cost without introducing a new `NSView` host class and without changing the highlight's visual style (the background can keep using the standard selection color). + +2. **Drop the redundant synthetic mouse-move.** `postOverviewScrollNavigation` already advances highlight explicitly via `self.menu(menu, willHighlight:)`; the subsequent synthetic `.mouseMoved` then re-drives hit-testing and highlighting (the `NSHostingView.hitTest` / `scrollWheel` work in the sample). The code comment says the mouse-move preserves native highlight/submenu behavior, so this needs a targeted experiment to confirm it is actually redundant — but if it is, removing it is a ~10-line change that hits the hit-test path directly. + +Both still require the same controlled macOS 27 interactive profiling to confirm. The Rich PR is essentially the industrial-strength version of option 1; option 2 is orthogonal and could stack with either PR. + +## Design Tradeoff + +The maintainer decision is likely between these two philosophies: + +### Choose Lite Row If + +- Overview should be a fast high-level summary. +- Full charts/details can live in provider detail surfaces. +- Reducing SwiftUI content is preferred over preserving exact current density. +- The simplest performance path is preferred. + +### Choose Rich Row If + +- Overview should preserve the current information density. +- The performance problem is mostly hover/hit-test/highlight propagation. +- A narrow AppKit menu boundary is acceptable. +- Maintainers want a lower visual-change patch. + +These PRs should not both merge. If maintainers choose one direction, the other should be closed or parked. + +## Recommended Next Steps + +1. Wait for ClawSweeper re-review to finish on both PRs. +2. If ClawSweeper clears the concrete Lite finding, compare remaining comments. +3. Run one controlled interactive proof on macOS 27: + - Build a fresh app from the chosen branch. + - Enable multiple Overview providers. + - Open Overview. + - Scroll while recording a short video or running `sample`. + - Redact local paths/account info before posting summary. +4. Ask maintainers to choose Lite vs Rich based on UI preference and proof. +5. Convert only the selected PR from draft to ready. + +## Questions For Claude Review + +Please review the two PR directions and this reasoning with these questions in mind: + +1. Is the root-cause interpretation coherent from the sample stack and source mapping? +2. Does the Lite row PR fix ClawSweeper's live-model critique completely, or is there another stale-model path? +3. Does the Rich row AppKit bridge cross the smallest reasonable boundary, or does it introduce hidden lifecycle risk? +4. Are there tests missing that would materially increase confidence without requiring a real interactive menu session? +5. Between Lite and Rich, which direction is more likely to be accepted by maintainers, and why? +6. Is there a third direction that is smaller than both PRs and still addresses the scroll hot path? +7. Are the PR bodies honest and precise about what is proven versus what remains unproven? + +## Review Pointers + +The symbols and test files below are introduced by the PR branches and do **not** exist on `main` (where this document lives). Check out the relevant branch or read the PR diff before following these pointers: + +- Lite row: `git checkout codex/overview-lite-row` (PR #1675) — adds `LiteSummary`, `resolvedLiveModel(refreshMonitor:)`, and `OverviewMenuCardRowViewTests`. +- Rich row: `git checkout codex/overview-rich-row` (PR #1676) — adds `OverviewMenuRowHostingView`, `makeOverviewMenuRowItem`, and `OverviewMenuRowContainerView`. + +On `main`, only the unchanged baseline symbols (`addOverviewRows`, `OverviewMenuCardRowView`, `UsageMenuCardUsageSectionView`) are present. + +For Lite row review: + +- Start with `OverviewMenuCardRowView` in `Sources/CodexBar/StatusItemController+MenuTypes.swift`. +- Check `resolvedLiveModel(refreshMonitor:)`. +- Check `LiteSummary.make(for:)`. +- Check `OverviewMenuCardRowViewTests`. + +For Rich row review: + +- Start with `OverviewMenuRowHostingView` in `Sources/CodexBar/StatusItemController+MenuPresentation.swift`. +- Check `makeOverviewMenuRowItem` in `Sources/CodexBar/StatusItemController+MenuCardItems.swift`. +- Check `addOverviewRows` in `Sources/CodexBar/StatusItemController+Menu.swift`. +- Check `MenuCardViewRecyclingTests`. + +For shared behavior: + +- Check `StatusMenuOverviewScrollTests`. +- Check `StatusMenuOverviewSubmenuTests`. +- Check existing menu-card recycling behavior. + +## Bottom Line + +The motivation is solid: a real user-visible scroll stutter maps to a plausible current-source hot path in `NSMenu` plus hosted SwiftUI Overview rows. + +The progress is also concrete: the issue is public, two alternative draft PRs exist, ClawSweeper feedback was addressed where it identified real code problems, and both branches have focused tests plus local validation. + +The main unresolved question is not "can we patch something?" It is which product/performance tradeoff maintainers want, and whether a controlled macOS 27 interactive scroll proof confirms the chosen direction. + +--- + +## Update 2026-06-24: Measured root cause + a third (implemented) direction + +This section adds quantitative evidence collected on macOS 27 (Swift 6.4, debug) and a third +implementation that supersedes the lite/rich split for the render half of the problem. + +### Headless benchmark of one highlight step + +Scrolling the Overview does not scroll pixels — `handleOverviewScrollWheel` converts the wheel into +discrete "move the highlighted row" steps. So the per-scroll cost is the cost of toggling a row's +selection. A headless benchmark hosted a real `OverviewMenuCardRowView` through the production +hosting path and measured `setHighlighted → layout → display → runloop-flush` over 200 toggles: + +```text +A baseline (SwiftUI recolor via menuItemHighlighted) avg ~2.4–10ms max ~7–27ms +B + .drawingGroup() (Metal offscreen rasterization) avg ~2.2–10ms max ~9–32ms (~10–28% only) +C content pinned, highlight fully decoupled avg ~0.01–0.06ms +D container highlight modifiers only, content pinned avg ~3–8ms +E GPU CIColorMatrix tint + AppKit selection layer avg ~0.05ms max ~1–2ms +``` + +Findings: + +- The spikes in `A` (~25ms) line up with the dropped frames in the user's recording (120fps capture, + ~57fps effective, worst frame gaps ~25ms). +- `D` shows the cost is dominated by re-rasterizing the content subtree whenever the container's + highlight-dependent modifiers change — not by leaf body evaluations. +- `B` proves **Metal alone is insufficient**: `.drawingGroup()` speeds rasterization but the SwiftUI + body/transaction pass still runs, so it only buys ~10–28% and still misses the 8.3ms/120Hz budget. +- `E`/`C` show the only way to the 120Hz budget is to take the selection off the SwiftUI graph. + +### Implemented direction: AppKit/GPU selection (`GPUSelectionHostingView`) + +`Sources/CodexBar/MenuCardGPUSelectionView.swift` renders the selected look without any SwiftUI work: + +1. an `NSVisualEffectView(.selection)` background (the existing in-repo pattern from + `PersistentRefreshMenuView`), crossfaded via Core Animation so the highlight glides between rows + instead of teleporting, and +2. a `CIColorMatrix` content filter that maps the row's pixels to the selected text color — which + matches the existing design where every selected element already becomes + `selectedMenuItemTextColor`. Core Image runs on the GPU (Metal), so the toggle is a layer change. + +It is opt-in via `makeMenuCardItem(usesGPUSelection:)` and currently wired only for Overview rows in +`addOverviewRows`. It deliberately does **not** override `hitTest`, avoiding the embedded-control +regression ClawSweeper flagged on the rich-row PR. Measured production path: **2.35ms → 0.044ms** +average per toggle, max well under one 120Hz frame. + +### The second, orthogonal problem: discrete navigation feel + +Even at 0.05ms/step, the motion is not "hand-following" because the wheel is quantized. Driving the +real `handleOverviewScrollWheel` with continuous gestures showed: + +```text +slow swipe: 240px finger travel -> one row jump every 24px (teleport, nothing in between) +fast flick: 200px (intent ~8 rows) -> only 3 rows registered (per-event cap + remainder discarded) +post-flick 20px nudge -> 0 steps (accumulator was zeroed, so the follow-up felt dead) +``` + +Interaction changes in `StatusItemController+OverviewScroll.swift` (merged with a parallel Codex +worktree that independently reached the same GPU-selection design): + +- **Precise trackpad scrolls are passed through to AppKit's native menu scroller** instead of being + converted into thresholded row-highlight jumps (`guard !event.hasPreciseScrollingDeltas { … return + false }`). Trackpads are continuous devices; native menu scrolling follows the finger, which is the + real fix for the "不跟手" feel — making highlight toggles cheap (above) does not by itself remove the + discrete-jump model. Classic notched scroll wheels keep the row-to-row highlight navigation. +- The crossfade in `GPUSelectionHostingView` softens the remaining wheel-driven highlight transitions. + +A deterministic regression test (`gpu selection highlight bypasses swiftui highlight state`) asserts +that highlighting a GPU row marks the AppKit view highlighted while the hosted +`MenuCardHighlightState.isHighlighted` stays `false`, proving selection never re-invalidates the +SwiftUI graph. + +### Test status + +`swift build` clean; the updated `StatusMenuOverviewScrollTests` (precise pass-through cases) and the +menu-card recycling/highlight suites — including the new GPU bypass test — pass. diff --git a/docs/packaging.md b/docs/packaging.md new file mode 100644 index 0000000..f2f1f75 --- /dev/null +++ b/docs/packaging.md @@ -0,0 +1,25 @@ +--- +summary: "Packaging, signing, and bundled CLI notes." +read_when: + - Packaging/signing builds + - Updating bundle layout or CLI bundling +--- + +# Packaging & signing + +## Scripts +- `Scripts/package_app.sh`: builds host arch with ad-hoc signing by default; set `ARCHES="arm64 x86_64"` for universal. Verifies slices. Stable-certificate packaging requires explicit `CODEXBAR_SIGNING=identity` plus `APP_IDENTITY`. +- `Scripts/compile_and_run.sh`: uses host arch; pass `--release-universal` or `--release-arches="arm64 x86_64"` for release packaging. +- `Scripts/sign-and-notarize.sh`: explicitly selects Developer ID signing, notarizes, staples, and zips (accepts `ARCHES` for universal). +- `Scripts/make_appcast.sh`: wrapper around the shared `mac-release make-appcast` helper; app metadata comes from `.mac-release.env`. +- `Scripts/changelog-to-html.sh`: converts the per-version changelog section to HTML for Sparkle. + +## Bundle contents +- `CodexBarWidget.appex` is built by `WidgetExtension/CodexBarWidgetExtension.xcodeproj` as a real macOS app extension, then bundled with app-group entitlements. +- `CodexBarCLI` copied to `CodexBar.app/Contents/Helpers/` for symlinking. +- SwiftPM resource bundles (e.g. `KeyboardShortcuts_KeyboardShortcuts.bundle`) copied into `Contents/Resources` (required for `KeyboardShortcuts.Recorder`). + +## Releases +- Full checklist in `docs/RELEASING.md`. + +See also: `docs/sparkle.md`. diff --git a/docs/perf-energy-issue-139-main-fix-validation-2026-02-19.md b/docs/perf-energy-issue-139-main-fix-validation-2026-02-19.md new file mode 100644 index 0000000..1be0844 --- /dev/null +++ b/docs/perf-energy-issue-139-main-fix-validation-2026-02-19.md @@ -0,0 +1,77 @@ +--- +summary: "Post-fix validation for issue #139 Codex CLI timeout and energy improvements." +read_when: + - Validating Codex CLI timeout or retry changes + - Reviewing post-fix evidence for issue 139 + - Investigating CodexBar CPU exposure under failed CLI probes +--- + +# CodexBar Issue #139 Main Fix Validation (Post-Fix vs Pre-Fix) + +Date: 2026-02-19 +Workspace: /Users/michalkrsik/windsurf_project_folder/CodexBar +Branch: codex/perf-issue-139 + +Reference pre-fix report: +- /Users/michalkrsik/windsurf_project_folder/CodexBar/docs/perf-energy-issue-139-simulation-report-2026-02-19.md + +## Implemented Main Fix + +File changed: +- /Users/michalkrsik/windsurf_project_folder/CodexBar/Sources/CodexBarCore/Providers/Codex/CodexStatusProbe.swift + +Behavior change: +- Primary Codex PTY probe timeout reduced from 18s to 8s. +- Retry policy changed from `retry on parseFailed OR timedOut` to `retry only on parseFailed`. +- Parse retry timeout set to 4s. +- Timed-out runs now fail fast and wait for next scheduled refresh. + +## Post-Fix Validation Method + +Target: main culprit path (Codex CLI failure path). + +Practical simulation used: +- `CODEX_CLI_PATH` pointed to a fake codex script. +- Script behavior: + - exits immediately for `app-server` args (forces RPC failure/fallback path), + - otherwise busy-loops with no `/status` output (simulates heavy stuck CLI PTY behavior). +- Command run (3 times): + - `./.build/debug/CodexBarCLI usage --provider codex --source cli --format json --pretty` +- Collected: + - wall time (`/usr/bin/time -p`), + - sampled child CPU every 0.5s, + - leftover child-process count after run. + +Artifacts: +- /tmp/codexbar_main_fix_validation_after + +## Post-Fix Results (3 runs) + +| Run | Real (s) | Avg child CPU (%) | Max child CPU (%) | Remaining child procs | +|---|---:|---:|---:|---:| +| 1 | 12.76 | 88.32 | 100.00 | 0 | +| 2 | 12.67 | 89.79 | 100.00 | 0 | +| 3 | 12.59 | 89.90 | 100.00 | 0 | +| Mean | 12.67 | 89.34 | 100.00 | 0 | + +## Side-by-Side Comparison Against Stored Pre-Fix Report + +Pre-fix values are from the stored report's Culprit A simulation summary. +Post-fix values are from the validation above. + +| Metric | Pre-fix (stored report) | Post-fix (this validation) | Delta | +|---|---:|---:|---:| +| Failed-run duration (worst-case path) | 42.00s (code-path budget before fix) | 12.67s (measured mean) | -69.8% | +| Child CPU during failed run | 113.32% avg | 89.34% avg | -21.2% | +| Peak child CPU during failed run | 115.90% max | 100.00% max | -13.7% | +| Remaining child processes after failure | not captured in pre-fix report | 0 | improved | + +Derived CPU-time exposure index (avg CPU * duration): +- Pre-fix: `113.32 * 42.00 = 4759.44` +- Post-fix: `89.34 * 12.67 = 1132.94` +- Reduction: **-76.2%** + +## Conclusion + +The implemented main fix materially reduces the failure-path runtime and overall CPU exposure. +The heavy CLI process can still spike CPU while active, but it now lives for a much shorter window and is cleaned up after failure. diff --git a/docs/perf-energy-issue-139-simulation-report-2026-02-19.md b/docs/perf-energy-issue-139-simulation-report-2026-02-19.md new file mode 100644 index 0000000..0b04a57 --- /dev/null +++ b/docs/perf-energy-issue-139-simulation-report-2026-02-19.md @@ -0,0 +1,109 @@ +--- +summary: "Issue #139 performance and energy simulation report for Codex CLI subprocess failure paths." +read_when: + - Investigating CodexBar CPU or energy regressions + - Changing Codex CLI PTY probe timing or retry behavior + - Reviewing issue 139 performance evidence +--- + +# CodexBar Issue #139 Performance/Energy Simulation Report + +Date: 2026-02-19 +Workspace: /Users/michalkrsik/windsurf_project_folder/CodexBar +Issue: https://github.com/steipete/codexbar/issues/139 + +## Purpose + +Determine which suspected culprit(s) can produce the abnormal CPU/energy behavior reported by users, using short reproducible simulations and process-level sampling. + +## Host/Tooling + +- macOS: Darwin 25.2.0 (arm64) +- Swift: 6.2.3 +- Sampling tools: `ps`, `top` +- Note: `powermetrics` was unavailable (requires sudo password in this session), so energy was sampled via `top` `POWER` proxy. + +## Simulated Culprits + +- Culprit A: CLI/PTTY-style heavy subprocess churn with polling loop behavior. +- Culprit B: Web dashboard scrape/retry loop with repeated parse work and 400-600ms waits. +- Culprit C: 75ms idle polling loop (blink-style wakeups). +- Combined: A + B + C at once. +- Baseline: near-idle control. + +## Test Pass 1 (Primary Mechanism Pass) + +Artifacts: +- /tmp/codexbar_perf_sim/results_20260219_111607 + +Summary: + +| Scenario | Avg CPU | Max CPU | Avg RSS MB | Avg POWER | Avg IDLEW | +|---|---:|---:|---:|---:|---:| +| Baseline | 0.00 | 0.10 | 0.54 | 0.00 | 0.00 | +| Culprit A | 113.68 | 117.40 | 121.76 | 0.00 | 0.00 | +| Culprit B | 4.64 | 13.30 | 64.15 | 0.00 | 5.04 | +| Culprit C | 0.25 | 2.30 | 33.12 | 0.00 | 10.43 | +| Combined | 114.62 | 121.30 | 217.62 | 0.00 | 0.00 | + +Interpretation: +- CPU ranking was clear (A dominates strongly). +- POWER field in this pass was unusable (stuck at 0.00 for several scenarios due `top` sampling mode). + +## Test Pass 2 (Calibrated Energy Pass) + +Artifacts: +- /tmp/codexbar_perf_sim/energy2_results_20260219_112350 + +Sampling correction: +- Switched to `top -l 2` and parsed the second sample for tracked PIDs to get non-zero `POWER` values. + +Summary: + +| Scenario | Avg CPU | Max CPU | Avg RSS MB | Avg POWER | Max POWER | Avg IDLEW | +|---|---:|---:|---:|---:|---:|---:| +| Baseline | 0.00 | 0.00 | 0.55 | 0.00 | 0.00 | 0.00 | +| Culprit A | 113.32 | 115.90 | 114.73 | 94.85 | 150.60 | 6106.70 | +| Culprit B | 4.30 | 10.10 | 62.09 | 2.94 | 4.20 | 2.18 | +| Culprit C | 0.35 | 2.60 | 34.09 | 0.23 | 0.60 | 14.27 | +| Combined | 115.67 | 118.90 | 218.48 | 93.29 | 129.60 | 3858.60 | + +## Validation Against Expected Pattern + +Computed checks on pass 2: 10/10 passed. + +- A dominates CPU vs B (>=10x): PASS +- A dominates CPU vs C (>=50x): PASS +- A dominates POWER vs B (>=10x): PASS +- A dominates POWER vs C (>=100x): PASS +- Combined close to A CPU (+/-15%): PASS +- Combined close to A POWER (+/-25%): PASS +- C is low CPU (<1%): PASS +- B is moderate CPU (<15%): PASS +- Baseline near zero CPU (<1%): PASS +- Baseline near zero POWER (<1): PASS + +## Final Finding + +Primary root-cause class for the extreme behavior is Culprit A (heavy long-lived CLI/subprocess churn under bad/failure paths). + +Secondary: +- Culprit B contributes moderate load. +- Culprit C contributes wakeups/noise but is not a major CPU/energy driver. + +Human-level answer: +A tiny toolbar app should never keep heavyweight background subprocess/UI loops alive in failure conditions. That behavior is what creates the abnormal battery/CPU footprint. + +## Limitations + +- These were controlled simulations, not a full end-user UI replay of `CodexBar.app` with all real auth/cookie/account paths. +- `powermetrics` could not be used in this session due sudo restriction. + +## Recommended Next Validation (Before Closing Issue) + +- Run one short real-app before/after validation after fixes: + - baseline + - culprit A-focused repro + - optional combined +- Capture `powermetrics` if sudo is available, plus process CPU snapshots. +- Publish before/after table in issue #139. diff --git a/docs/perplexity.md b/docs/perplexity.md new file mode 100644 index 0000000..89c18db --- /dev/null +++ b/docs/perplexity.md @@ -0,0 +1,85 @@ +--- +summary: "Perplexity provider: browser cookie setup, credits API, recurring/bonus/purchased credit display." +read_when: + - Configuring Perplexity usage + - Debugging Perplexity browser cookie import or manual session tokens + - Adjusting Perplexity credit display +--- + +# Perplexity Provider + +CodexBar reads Perplexity account credit data with a Perplexity web session cookie. It does not use a Perplexity API +key and does not support token-cost history. + +## Setup + +1. Open **Settings -> Providers**. +2. Enable **Perplexity**. +3. Sign in to [perplexity.ai](https://www.perplexity.ai/) in a supported browser. +4. Leave Cookie source on **Automatic**, or switch to **Manual** and paste a full `Cookie:` header or a bare + Perplexity session-token value. + +Manual mode accepts these session cookie names: + +- `__Secure-authjs.session-token` +- `authjs.session-token` +- `__Secure-next-auth.session-token` +- `next-auth.session-token` + +You can also provide credentials through the environment: + +```bash +export PERPLEXITY_SESSION_TOKEN="..." +export PERPLEXITY_COOKIE="__Secure-next-auth.session-token=..." +``` + +## Data Source + +CodexBar requests: + +- `GET https://www.perplexity.ai/rest/billing/credits?version=2.18&source=default` + +The request sends the resolved Perplexity session cookie, `Origin: https://www.perplexity.ai`, and +`Referer: https://www.perplexity.ai/account/usage`. + +Automatic mode tries any cached Perplexity cookie first, then imports browser cookies, then falls back to environment +variables. Browser-imported cookies are cached and invalid cached cookies are cleared after a rejected request. + +## Display + +- **Credits**: recurring account credits when Perplexity reports them. +- **Bonus credits**: promotional or bonus credits. +- **Purchased**: on-demand purchased credits. +- **Renewal**: recurring credits use the renewal timestamp when the API returns one. + +Purchased credits do not reset, so the menu displays that balance without a reset prefix. + +## CLI Usage + +```bash +codexbar usage --provider perplexity --verbose +``` + +## Troubleshooting + +### "Perplexity session token is missing" + +Sign in to [perplexity.ai](https://www.perplexity.ai/) and refresh CodexBar, or paste a fresh cookie/session token in +manual mode. + +### "Perplexity session token is invalid or expired" + +Log out and back in to Perplexity. If manual mode is enabled, paste a new `Cookie:` header or session-token value. + +### Credits do not appear + +Open [Perplexity account usage](https://www.perplexity.ai/account/usage) in the same browser profile and confirm the +account has visible credit data. + +## Related Files + +- `Sources/CodexBarCore/Providers/Perplexity/PerplexityProviderDescriptor.swift` +- `Sources/CodexBarCore/Providers/Perplexity/PerplexityUsageFetcher.swift` +- `Sources/CodexBarCore/Providers/Perplexity/PerplexityUsageSnapshot.swift` +- `Sources/CodexBarCore/Providers/Perplexity/PerplexityCookieHeader.swift` +- `Sources/CodexBar/Providers/Perplexity/PerplexityProviderImplementation.swift` diff --git a/docs/poe.md b/docs/poe.md new file mode 100644 index 0000000..097cda9 --- /dev/null +++ b/docs/poe.md @@ -0,0 +1,45 @@ +--- +summary: "Poe provider: API key setup, point balance, and recent usage history." +read_when: + - Configuring Poe usage + - Debugging Poe balance or history requests +--- + +# Poe Provider + +CodexBar reads Poe's official usage API with a manually configured API key. It does not perform OAuth login or import browser cookies. + +## Authentication + +Create or copy an API key from [Poe API Keys](https://poe.com/api/keys), then add it in CodexBar Settings → Providers → Poe. + +You can also set the environment variable: + +```bash +export POE_API_KEY="..." +``` + +Or configure it through the CLI: + +```bash +printf '%s' "$POE_API_KEY" | codexbar config set-api-key --provider poe --stdin +``` + +## Data Source + +CodexBar requests: + +- `GET https://api.poe.com/usage/current_balance` +- `GET https://api.poe.com/usage/points_history` + +The current balance request is required. Recent points history is best-effort, so a history error does not hide a valid balance. + +## Display + +The provider shows the current point balance in the menu and menu bar. When available, recent history is grouped by day and shown in the usage detail. + +## CLI Usage + +```bash +codexbar --provider poe +``` diff --git a/docs/pr-1848-body.md b/docs/pr-1848-body.md new file mode 100644 index 0000000..6b0a205 --- /dev/null +++ b/docs/pr-1848-body.md @@ -0,0 +1,51 @@ +## Summary + +Fixes the background browser-launch regression in https://github.com/steipete/CodexBar/issues/1844: when Claude Code stores only MCP OAuth state in `Claude Code-credentials` (no `claudeAiOauth`), CodexBar no longer runs background delegated `claude /status` refresh—which can launch the default browser via `/usr/bin/open`. + +**Scope:** fail-closed safety guard for both keychain readers. Discovery of Claude Code 2.1.x's primary OAuth storage location remains tracked by https://github.com/steipete/CodexBar/issues/1823. + +## Problem + +On Claude Code 2.1.x, the `Claude Code-credentials` keychain item may contain only `mcpOAuth`. CodexBar then fails to parse Claude OAuth credentials, treats the session as expired, and may periodically attempt delegated CLI refresh. That path can open the user's default browser from the background. + +Contributing issues on `main`: + +1. Delegated refresh used `ClaudeOAuthKeychainPromptPreference.current()`, which becomes `.always` when the experimental security CLI reader is active—so `onlyOnUserAction` did not suppress background repair. +2. Delegated refresh could still invoke `claude /status` even when the keychain shape could not succeed. + +## Changes + +1. **Honor stored keychain prompt mode for delegated refresh** across all keychain read strategies (including `securityCLIExperimental`). Background refresh with `onlyOnUserAction` fails closed with existing user-action guidance instead of calling `claude /status`. +2. **Detect MCP-only keychain payloads through both keychain readers** via `ClaudeOAuthCredentialsError.mcpOAuthOnlyKeychain`, skip delegated CLI touch, and fail fast during expired Claude CLI credential load. +3. **Split security CLI read paths**: `readRawClaudeKeychainPayloadViaSecurityCLIIfEnabled` vs parsed credential load. +4. **Isolated verification helper**: the production `/usr/bin/security` reader can target a disposable keychain only while all general keychain access is disabled. `Scripts/verify_1844_live.sh` combines that keychain with disposable `HOME`, `CFFIXED_USER_HOME`, credentials, config, and a synthetic `claude` fixture that distinguishes benign CLI discovery from `/status` touch. + +## Tests + +- Updated: background delegated-refresh suppression with experimental reader +- Added: MCP-only parse/shape detection +- Added: coordinator test—background MCP-only guard plus explicit Refresh recovery +- Added: store test—expired CLI owner fails closed in background and delegates on explicit Refresh +- Added: fail-closed tests for the isolated-keychain argument seam +- Added: standard Security.framework reader regression—background fails closed while explicit Refresh delegates + +## Verification + +- [x] Focused macOS integration tests (2026-07-03) — details in `docs/verify-1844-proof.md` +- [x] Release-built `CodexBar.app` and packaged `CodexBarCLI` isolated live proof +- [x] Real Claude-tab Refresh click against the isolated built app +- [x] Final `make check`, 45-shard `make test`, and autoreview on the local port + +### Commands + +```bash +make check +swift test --filter ClaudeOAuthTests +swift test --filter ClaudeUsageTests +swift test --filter ClaudeOAuthDelegatedRefreshCoordinatorTests +swift test --filter 'expired claude CLI owner blocks background' +swift test --filter ClaudeOAuthCredentialsStoreMCPOnlyGuardTests +./Scripts/verify_1844_live.sh +``` + +Fixes https://github.com/steipete/CodexBar/issues/1844. Primary OAuth storage discovery remains tracked by https://github.com/steipete/CodexBar/issues/1823. diff --git a/docs/pr-1848-verification-comment.md b/docs/pr-1848-verification-comment.md new file mode 100644 index 0000000..a0bc8cd --- /dev/null +++ b/docs/pr-1848-verification-comment.md @@ -0,0 +1,48 @@ +## Maintainer verification (2026-07-03) + +Local current-main port of https://github.com/steipete/CodexBar/pull/1848. This fixes the background browser-launch regression in https://github.com/steipete/CodexBar/issues/1844; primary OAuth storage discovery remains tracked by https://github.com/steipete/CodexBar/issues/1823. + +### Focused regression proof + +```bash +swift test --filter ClaudeOAuthTests +swift test --filter ClaudeUsageTests +swift test --filter ClaudeOAuthDelegatedRefreshCoordinatorTests +swift test --filter 'expired claude CLI owner blocks background' +swift test --filter ClaudeOAuthCredentialsStoreSecurityCLITests +swift test --filter ClaudeOAuthCredentialsStoreIsolatedSecurityCLITests +swift test --filter ClaudeOAuthCredentialsStoreMCPOnlyGuardTests +``` + +Result: **105 tests passed** (33 + 39 + 12 + 1 + 17 + 2 + 1). + +| Behavior | Result | +|----------|--------| +| Background `onlyOnUserAction` suppresses delegated refresh with `securityCLIExperimental` | Pass | +| MCP-only background guard prevents `claude /status` touch | Pass | +| Explicit user Refresh bypasses the MCP-only guard and cooldown | Pass | +| Explicit user Refresh retries after an in-flight background failure | Pass | +| Expired Claude CLI-owned credentials fail closed with `mcpOAuthOnlyKeychain` | Pass | +| Isolated keychain path is accepted only with general keychain access disabled | Pass | +| Standard Security.framework reader fails closed in background while explicit Refresh delegates | Pass | + +### Isolated built-bundle proof + +```bash +./Scripts/package_app.sh +./Scripts/verify_1844_live.sh +``` + +The verifier used only synthetic data under a unique temporary directory: + +- disposable `HOME` and `CFFIXED_USER_HOME` +- disposable keychain passed directly to `/usr/bin/security` +- general Security.framework/cache keychain access disabled +- isolated `.claude/.credentials.json` and CodexBar config +- synthetic `claude` executable that records benign discovery separately from `/status` touch + +The packaged `CodexBarCLI` exited 3 with the MCP-only guidance, no `/status` or browser/open canary appeared, and the user keychain search list was unchanged. The packaged `CodexBar.app` then exercised the synthetic CLI with `--version`, stayed running for five seconds after discovery, and still sent no `/status` or browser/open touch. + +For the explicit recovery path, I launched the same isolated built app, selected the real Claude tab, and clicked Refresh. Before the click the invocation log contained only `--version`; after the click it received `/status`, while the browser/open canary remained untouched. This proves user Refresh remains interaction-aware without weakening the background guard. + +Final local gates passed: `make check`, all 45 `make test` shards, exact-SHA autoreview, and source-blind behavior validation. diff --git a/docs/predictive-refresh-policy.md b/docs/predictive-refresh-policy.md new file mode 100644 index 0000000..617aeea --- /dev/null +++ b/docs/predictive-refresh-policy.md @@ -0,0 +1,278 @@ +--- +summary: "Decision record for an optional deterministic adaptive refresh cadence." +read_when: + - Planning refresh cadence or background provider updates + - Evaluating adaptive or predictive refresh behavior + - Changing UsageStore timer scheduling +--- + +# Adaptive refresh decision record + +- **Status:** Accepted and implemented as an opt-in mode in [#1861](https://github.com/steipete/CodexBar/pull/1861) +- **Decision owner:** Maintainer +- **Runtime impact:** Bounded opt-in 2–30-minute provider-batch cadence + +## Decision + +CodexBar may offer an opt-in `Adaptive` refresh frequency that adjusts the existing provider-batch timer between 2 and +30 minutes using the deterministic policy below. Do not implement the broader +per-account prediction, persistent interaction history, learned ranking, or menu prewarming proposed in the original +RFC. + +This approval covers the bounded design only. Runtime implementation, tests, localization, and packaged proof were +delivered separately by #1861; changing the default or adding new signals still requires new evidence and review. + +## Options considered + +| Option | Freshness | Complexity | Provider work | Decision | +|---|---|---|---|---| +| Keep fixed frequencies only | Predictable | Lowest | Predictable | Safe fallback | +| Add bounded adaptive batch cadence | Better while active; quieter while idle | Small | Bounded | Recommended experiment | +| Add per-provider/account prediction | Potentially best | High | Harder to reason about | Reject for now | +| Add learned ranking or contextual bandits | Unproven | Very high | Harder to audit | Reject | + +The recommended option is intentionally less ambitious than “predictive refresh.” It solves the scheduling question +without creating a second account model, persistent behavioral telemetry, or a new menu-rendering architecture. + +## Current behavior and code seams + +Current `main` has two independent refresh paths: + +1. `UsageStore.startTimer()` reads `SettingsStore.refreshFrequency.seconds`, sleeps for the fixed interval, then calls + `UsageStore.refresh()`. A refresh is one concurrent batch over `enabledProvidersForBackgroundWork()`. +2. `StatusItemController.scheduleOpenMenuRefresh(for:)` retries rendered providers with missing/stale data. When the + default-off **Refresh when the menu opens** setting is enabled, it refreshes every enabled provider instead. Both + modes use the background interaction context, coalesce in-flight provider work, and keep prompt-capable OpenAI + dashboard work deferred until menu tracking ends. + +Relevant implementation seams: + +- `Sources/AdaptiveRefreshCore/AdaptiveRefreshPolicyCore.swift`: canonical package-internal policy table shared by the + app adapter and offline replay tooling. +- `Sources/CodexBar/SettingsStore.swift`: `RefreshFrequency` and fixed interval mapping. +- `Sources/CodexBar/UsageStore.swift`: timer ownership and provider-batch refresh. +- `Sources/CodexBar/UsageStore+Refresh.swift`: provider refresh coalescing and result application. +- `Sources/CodexBar/StatusItemController+Menu.swift`: missing/error-only menu-open refresh. +- `Sources/CodexBar/StatusItemController+MenuInteractionRefresh.swift`: deferred non-interactive refresh safety. +- `Tests/CodexBarTests/StatusMenuInstantOpenTests.swift`: fresh, missing, in-flight, and close-during-refresh contracts. + +The adaptive experiment must change only the first path. It must not alter the menu-open setting, its default, provider +selection, interaction context, or promise that menu-open refresh does not reset the periodic refresh clock. + +## Accepted product contract + +- Add `Adaptive` as a mutually exclusive `RefreshFrequency` choice. +- Keep `5 minutes` as the default for new and existing users. +- Never migrate an existing fixed selection to `Adaptive`. +- Preserve `Manual` and every existing fixed interval exactly. +- Schedule the same enabled-provider batch as fixed refresh; do not select accounts, workspaces, or data lanes. +- Keep manual refresh immediate and user-initiated. +- When refresh-all-on-open is disabled, keep menu-open refresh missing/error-only and background/non-interactive. +- Preserve the opt-in refresh-all-on-open path exactly. Recording a menu-open timestamp for adaptive scheduling must + not itself fetch, cancel the periodic timer, or count a menu-originated refresh as an adaptive timer tick. +- Never make an automatic provider, account, workspace, or credential-source selection. +- Never bypass provider-specific auth, prompt, coalescing, or failure gates. + +## Deterministic policy + +Use a pure `AdaptiveRefreshPolicy` that returns the delay before the next ordinary provider-batch refresh. + +```swift +struct AdaptiveRefreshPolicy: Sendable { + struct Input: Sendable, Equatable { + let now: Date + let lastMenuOpenAt: Date? + let lowPowerModeEnabled: Bool + let thermalState: ProcessInfo.ThermalState + } + + enum Reason: String, Sendable { + case recentInteraction + case warm + case idle + case longIdle + case constrained + } + + struct Decision: Sendable, Equatable { + let delay: Duration + let reason: Reason + } + + func nextDelay(for input: Input) -> Decision +} +``` + +Policy table, evaluated after startup and after every completed or skipped timer tick: + +| Condition, first match wins | Next delay | Reason | +|---|---:|---| +| Low Power Mode or serious/critical thermal state | 30 minutes | `constrained` | +| Menu opened at or after 5 minutes ago, including a future clock-adjusted timestamp | 2 minutes | `recentInteraction` | +| Menu opened more than 5 minutes and at most 1 hour ago | 5 minutes | `warm` | +| Menu opened more than 1 hour and less than 4 hours ago | 15 minutes | `idle` | +| No menu open recorded, or last open at least 4 hours ago | 30 minutes | `longIdle` | + +Bounds are part of the contract: + +- minimum automatic interval: 2 minutes; +- maximum automatic interval: 30 minutes; +- one timer task at a time; +- one global provider-batch refresh at a time; +- canceled timers do not launch work; +- settings changes cancel and replace the pending timer. + +The policy deliberately excludes quota level, provider latency, error count, account choice, time-of-day, and content +change rate. Those signals require new durable state or provider-specific semantics and do not belong in the first +experiment. + +## Scheduler integration + +Keep scheduling inside `UsageStore`; do not add a second scheduler abstraction. + +1. Extend `RefreshFrequency` with `adaptive`; its fixed `seconds` value remains `nil`. +2. Replace the fixed `startTimer()` loop with a loop that asks a small helper for the next delay: + - fixed mode returns the selected fixed delay; + - manual mode returns no delay and ends the task; + - adaptive mode calls `AdaptiveRefreshPolicy`. +3. After sleeping, check cancellation and call the existing `refresh()` batch path. +4. Recompute the next delay after the batch completes. +5. Record menu-open time through a minimal callback owned by `UsageStore` or a dedicated in-memory signal object. Do + not couple the policy to `NSMenu`, menu descriptors, account switchers, or rendering state. + +`NSBackgroundActivityScheduler` is out of scope. Current refresh choices include intervals below the range where that +API is intended to help, and using two scheduling mechanisms would make cancellation and exact timing harder to audit. +Revisit it only with separate energy measurements and a design for launch/relaunch behavior. + +## State, privacy, and observability + +The first experiment stores no interaction history. + +- Keep `lastMenuOpenAt` in memory; reset it on launch. +- Read Low Power Mode and thermal state at decision time. +- Log only the selected delay and stable `Reason` code through the existing local logger. +- Do not log or store provider identity, account identity, email, workspace, path, credentials, response data, or menu + content for scheduling. +- Do not add analytics or send refresh-policy data off device. + +This avoids a new retention policy, migration, deletion UI, and behavioral profile. Persistent history requires a new +privacy and storage decision; it is not an incremental extension of this proposal. + +## Failure and auth behavior + +Adaptive scheduling controls only when the existing batch is requested. All provider behavior remains downstream: + +- background interaction context remains the default for automatic work; +- provider refresh coalescing remains authoritative; +- background work must not request interactive Keychain or browser authentication; +- a failed batch does not trigger an immediate policy retry; +- missing/error menu rows continue to use the existing delayed, rendered-provider-only retry path; +- manual refresh remains the only path allowed to opt into user-initiated behavior. + +Do not add a scheduler-level failure backoff in the first experiment. Providers have different failure semantics, and +the current failure gates primarily control error publication rather than retry eligibility. A shared backoff would +need a separate contract for partial batch success. + +## Implementation sequence + +Each step should be independently reviewable: + +1. Add the pure policy and table-driven tests; no settings or runtime changes. +2. Add the `Adaptive` setting and localization, default unchanged. +3. Teach the existing timer to request fixed/manual/adaptive delays. +4. Wire the in-memory menu-open signal without changing `scheduleOpenMenuRefresh(for:)`. +5. Add local reason-code logging and documentation. +6. Package and validate the opt-in mode before considering a default change. + +Do not add target adapters, outcome databases, account/workspace prediction, learned models, visible ordering changes, +or menu prewarming as part of these steps. + +## Required tests + +### Pure policy + +- every table boundary, including exactly 5 minutes, 1 hour, and 4 hours; +- Low Power Mode wins over recent interaction; +- serious and critical thermal states select 30 minutes; +- nominal/fair thermal states do not force the constrained branch; +- future or clock-adjusted menu timestamps are treated as recent and never produce a negative delay; +- every decision stays within the 2-to-30-minute bounds. + +### Timer integration + +- fixed and manual modes retain current behavior; +- adaptive mode sleeps for the policy result and recomputes after refresh; +- changing frequency cancels the old timer without one extra refresh; +- overlapping timer ticks do not overlap `UsageStore.refresh()`; +- launch with no menu history begins at 30 minutes; +- menu-open signal changes the next decision but does not itself start a batch. + +### Menu regression + +- opening a fresh menu still does not schedule a menu-originated refresh; +- missing/error rows still refresh only rendered providers; +- enabling refresh-all-on-open still refreshes every enabled provider without resetting the periodic timer; +- adaptive and menu-open work arriving together still coalesce per provider instead of duplicating requests; +- closing a menu still controls deferred prompt-capable dashboard work; +- in-flight provider work still coalesces; +- manual refresh remains user-initiated. + +Use stubs and test stores. Do not run live providers, browser-cookie imports, or Keychain reads for policy validation. + +## Acceptance and rollback + +Before changing the default, a separate PR updating this decision record must provide measured evidence. Minimum +evidence: + +- deterministic replay tests show fewer scheduled batches than the 5-minute baseline during idle traces; +- unconstrained active decisions never schedule slower than the existing 5-minute default; Low Power Mode and + serious/critical thermal state retain the 30-minute safety override; +- no regression in menu-open responsiveness or prompt safety; +- packaged opt-in use shows understandable reason logs and no timer overlap. + +Rollback is deleting the `Adaptive` option and policy helper. Fixed/manual scheduling and stored fixed selections remain +valid because the experiment does not migrate them or change their raw values. + +## Explicit non-decisions + +Approval of this document does not approve: + +- making adaptive refresh the default; +- changing the refresh-all-on-open default or its existing provider/auth behavior; +- per-provider, per-account, per-workspace, or per-source scheduling; +- persistent interaction or outcome history; +- `NSBackgroundActivityScheduler` adoption; +- account/menu ordering changes; +- EWMA, Bayesian, bandit, ranker, or language-model decisions; +- new telemetry collection or external analytics. + +Any of those requires its own evidence and product/privacy review. + +## Local replay follow-up (2026-07-10, evidence only) + +This follow-up adds offline replay tooling only. It does not add app-side recording, persistent diagnostic storage, +transcript-directory scanning, or a new production-policy input. The evaluated 1,780-record snapshot came from local +experimental instrumentation that is not part of this change. Its SHA-256 is +`b1e4aa33180b7c177293eb9ed16b45e24e026d259600fba2b1b67b931b904f0b`; the raw trace remains local. + +The app and replay adapter call the same package-internal policy core. Platform-specific adapters normalize thermal +state and output units; they do not copy the policy thresholds or decision table. + +The replay splits legacy deadline-overrun gaps five minutes after the most recent recorded timer deadline. It found 28 +observed segments and excluded 26.10 hours of unobserved wall time. The heuristic cannot distinguish sleep or reboot from +a long refresh or event-loop stall, so the excluded time is not a causal classification. + +| Policy | Simulated refreshes | Per observed 24h | Simulated advances | Unconstrained active over 5m | Menu staleness p50 / p95 | +|---|---:|---:|---:|---:|---:| +| Current adaptive | 694 | 143.47 | 53 | 4 / 145 | 142s / 1093s | +| Activity-cap candidate | 696 | 143.88 | 53 | 0 / 145 | 139s / 1093s | +| Fixed 5m | 1383 | 285.90 | 0 | 0 / 99 | 150s / 281s | + +The replay-only candidate caps an otherwise slower adaptive decision at five minutes when an input trace reports recent +coding activity. It adds two simulated refreshes and removes the four active-delay violations in this snapshot, but does +not improve p95 menu staleness. The sample is one machine and the candidate changes only a small number of decisions, so +this is not sufficient evidence for a production or default change. + +Replay advances are counterfactual events on a zero-service-time policy clock. They are intentionally not compared by +count with live `timerAdvanced` events, whose schedule includes real refresh duration and in-flight coalescing. The +offline audit reports recorded schedule events separately when the supplied trace contains them. diff --git a/docs/provider.md b/docs/provider.md new file mode 100644 index 0000000..9b191e3 --- /dev/null +++ b/docs/provider.md @@ -0,0 +1,201 @@ +--- +summary: "Provider authoring guide: shared host APIs, provider boundaries, and how to add a new provider." +read_when: + - Adding a new provider (usage + status + identity) + - Refactoring provider architecture or shared host APIs + - Reviewing provider boundaries (no identity leakage) +--- + +# Provider authoring guide + +Goal: adding a provider should feel like: +- add one folder +- define one descriptor + strategies +- add one implementation (UI hooks only) +- done (tests + docs) + +This doc describes the **current provider architecture** and the exact steps to add a new provider. + +## Terms +- **Provider**: a source of usage/quota/status data (Codex, Claude, Gemini, Antigravity, Cursor, …). +- **Descriptor**: the single source of truth for labels, URLs, defaults, and fetch strategies. +- **Fetch strategy**: one concrete way to obtain usage (CLI, web cookies, OAuth API, local probe, etc.). +- **Host APIs**: shared capabilities we provide to providers (Keychain, browser cookies, PTY, HTTP, WebView scrape, token-cost). +- **Identity fields**: email/org/plan/loginMethod. Must stay **siloed per provider**. + +## Architecture overview (now) +- `Sources/CodexBarCore`: provider descriptors + fetch strategies + probes + parsing + shared utilities. +- `Sources/CodexBar`: UI/state + provider implementations (settings/login/menu hooks only). +- Provider IDs are compile-time: `UsageProvider` enum (used for persistence + widgets). +- Provider wiring is descriptor-driven: + - `ProviderDescriptor` owns labels, URLs, default enablement, and fetch pipeline. + - `ProviderFetchStrategy` objects implement concrete fetch paths. + - CLI + app both call the same descriptor/fetch pipeline. + +Common building blocks already exist: +- PTY: `TTYCommandRunner` +- subprocess: `SubprocessRunner` +- cookie import: `BrowserCookieImporter` (Safari/Chrome/Firefox adapters) +- OpenAI dashboard web scrape: `OpenAIDashboardFetcher` (WKWebView + JS) +- cost usage: local log scanner (Codex + Claude) + +Provider behavior is descriptor-driven. Two explicit, exhaustive registries form the bootstrap boundary: +`ProviderDescriptorRegistry` owns core descriptors and `ProviderImplementationRegistry` owns app implementations. + +## Provider descriptor (source of truth) + +Introduce a single descriptor per provider: +- `id` (stable `UsageProvider`) +- display/labels/URLs (menu title, dashboard URL, status URL) +- UI branding (icon name, primary color) +- capabilities (supportsCredits, supportsTokenCost, supportsStatusPolling, supportsLogin) +- fetch plan (allowed `--source` modes + ordered strategy pipeline) +- CLI metadata (cliName, aliases, version provider) +- account behavior (e.g., `usesAccountFallback` for Codex auth.json) + +UI and settings should become descriptor-driven: +- no provider-specific branching for labels/links/toggle titles +- minimal provider-specific UI (only when a provider truly needs bespoke UX) + +## Fetch strategies + +A provider declares a pipeline of strategies, in priority order. Each strategy: +- advertises a `kind` (cli, web cookies, oauth, api token, local probe, web dashboard) +- declares availability (checks settings, cookies, env vars, installed CLI) +- fetches `UsageSnapshot` (and optional credits/dashboard) +- can be filtered by CLI `--source` or app settings + +The pipeline resolves to the best available strategy, and falls back on failure when allowed. +Each run returns a `ProviderFetchOutcome` with **attempts + errors** for debug UI and CLI `--verbose`. + +## Host APIs are explicit, small, testable +Expose a narrow set of protocols/structs that provider implementations can use: +- `KeychainAPI`: read-only, allowlisted service/account pairs +- `BrowserCookieAPI`: import cookies by domain list; returns cookie header + diagnostics +- `PTYAPI`: run CLI interactions with timeouts + “send on substring” + stop rules +- `HTTPAPI`: URLSession wrapper with domain allowlist + standard headers + tracing +- `WebViewScrapeAPI`: WKWebView lease + `evaluateJavaScript` + snapshot dumping +- `TokenCostAPI`: Cost Usage local-log integration (Codex/Claude today; extend later) +- `StatusAPI`: status polling helpers (Statuspage + Workspace incidents) +- `LoggerAPI`: scoped logger + redaction helpers + +Rule: providers do not talk to `FileManager`, `Security`, or “browser internals” directly unless they *are* the host API implementation. + +## Provider-specific code layout +- `Sources/CodexBarCore/Providers//` + - `Descriptor.swift` (descriptor + strategy pipeline) + - `Strategies.swift` (strategy implementations) + - `Probe.swift` / `Fetcher.swift` + - `Models.swift` + - `Parser.swift` (if text/HTML parsing) +- `Sources/CodexBar/Providers//` + - `ProviderImplementation.swift` (settings/login UI hooks only) + +## Minimal provider example (copy-paste) + +```swift +import Foundation + +public enum ExampleProviderDescriptor { + public static let descriptor: ProviderDescriptor = Self.makeDescriptor() + + static func makeDescriptor() -> ProviderDescriptor { + ProviderDescriptor( + id: .example, + metadata: ProviderMetadata( + id: .example, + displayName: "Example", + sessionLabel: "Session", + weeklyLabel: "Weekly", + opusLabel: nil, + supportsOpus: false, + supportsCredits: false, + creditsHint: "", + toggleTitle: "Show Example usage", + cliName: "example", + defaultEnabled: false, + isPrimaryProvider: false, + usesAccountFallback: false, + dashboardURL: nil, + statusPageURL: nil), + branding: ProviderBranding( + iconStyle: .codex, + iconResourceName: "ProviderIcon-example", + color: ProviderColor(red: 0.2, green: 0.6, blue: 0.8)), + tokenCost: ProviderTokenCostConfig( + supportsTokenCost: false, + noDataMessage: { "Example cost summary is not supported." }), + fetchPlan: ProviderFetchPlan( + sourceModes: [.auto, .cli], + pipeline: ProviderFetchPipeline(resolveStrategies: { _ in [ExampleFetchStrategy()] })), + cli: ProviderCLIConfig( + name: "example", + versionDetector: nil)) + } +} + +struct ExampleFetchStrategy: ProviderFetchStrategy { + let id: String = "example.cli" + let kind: ProviderFetchKind = .cli + + func isAvailable(_: ProviderFetchContext) async -> Bool { true } + + func fetch(_: ProviderFetchContext) async throws -> ProviderFetchResult { + let usage = UsageSnapshot( + primary: .init(usedPercent: 0, windowMinutes: nil, resetsAt: nil, resetDescription: nil), + secondary: nil, + updatedAt: Date(), + identity: nil) + return self.makeResult(usage: usage, sourceLabel: "cli") + } + + func shouldFallback(on _: Error, context _: ProviderFetchContext) -> Bool { false } +} +``` + +## Guardrails (non-negotiable) +- Identity silo: never display identity/plan fields from provider A inside provider B UI. +- Privacy: default to on-device parsing; browser cookies are opt-in and never persisted by us beyond WebKit stores. +- Reliability: providers must be timeout-bounded; no unbounded waits on network/PTY/UI. +- Degradation: prefer cached data over flapping; show clear errors when stale. + +## Adding a new provider (current flow) + +Checklist: +- Add `UsageProvider` case in `Sources/CodexBarCore/Providers/Providers.swift`. +- Create `Sources/CodexBarCore/Providers//`: + - `Descriptor.swift`: define `ProviderDescriptor` + fetch pipeline. + - `Strategies.swift`: implement one or more `ProviderFetchStrategy`. + - `Probe.swift` / `Fetcher.swift`: concrete fetcher logic. + - `Models.swift`: snapshot structs. + - `Parser.swift` (if needed). +- Define a cached `public static let descriptor` and `static func makeDescriptor() -> ProviderDescriptor`. +- Add the descriptor to `ProviderDescriptorRegistry.descriptorsByID`. +- Add `Sources/CodexBar/Providers//ProviderImplementation.swift`: + - `ProviderImplementation` only for settings/login UI hooks. +- Add an exhaustive case to `ProviderImplementationRegistry.makeImplementation(for:)`. +- Add icons + color in descriptor: + - `iconName` must match `ProviderIcon-` asset. + - Color used in menu cards + switcher. +- If CLI-specific behavior is needed: + - add `cliName`, `cliAliases`, `sourceModes`, `versionProvider` in descriptor. + - strategies decide which `--source` modes apply. +- Tests: + - `UsageSnapshot` mapping unit tests + - strategy availability + fallback tests + - CLI provider parsing (aliases + --source validation) +- Docs: + - add provider section in `docs/providers.md` with data source + auth notes + - update `docs/provider.md` if the pipeline model changes + +## UI notes (Providers settings) +Current: checkboxes per provider. + +Preferred direction: table/list rows (like a “sessions” table): +- Provider (name + short auth hint) +- Enabled toggle +- Status (ok/stale/error + last updated) +- Auth source (CLI / cookies / web / oauth) when applicable +- Actions (Login / Diagnose / Copy debug log) + +This keeps the pane scannable once we have >5 providers. diff --git a/docs/providers.md b/docs/providers.md new file mode 100644 index 0000000..841c357 --- /dev/null +++ b/docs/providers.md @@ -0,0 +1,509 @@ +--- +summary: "Provider data sources and parsing overview for every registered CodexBar provider." +read_when: + - Adding or modifying provider fetch/parsing + - Adjusting provider labels, toggles, or metadata + - Reviewing data sources for providers +--- + +# Providers + +CodexBar currently registers 59 provider IDs. Some companies expose multiple surfaces, such as Codex vs OpenAI API or +OpenCode vs OpenCode Go, because the auth source and quota shape differ. + +## Fetch strategies (current) +Legend: web (browser cookies/WebView), cli (RPC/PTy or provider CLI), oauth (provider OAuth), api token, local probe, web dashboard. +Source labels (CLI/header): `openai-web`, `web`, `oauth`, `api`, `local`, `cli`, plus provider-specific CLI labels (e.g. `codex-cli`, `claude`). + +Cookie-based providers expose a Cookie source picker (Automatic or Manual) in Settings → Providers. +Some browser cookie imports are cached in Keychain and reused until the session is invalid. API keys, manual cookie +headers, source selection, provider ordering, and token accounts are stored in `~/.codexbar/config.json`. + +| Provider | Strategies (ordered for auto) | +| --- | --- | +| Codex | App Auto: OAuth API (`oauth`) → CLI RPC/PTy (`codex-cli`). CLI Auto: Web dashboard (`openai-web`) → CLI RPC/PTy (`codex-cli`). | +| OpenAI | Admin API key (`api`) for organization spend/usage; legacy API-key balance fallback. | +| Azure OpenAI | API key + endpoint + deployment probe (`api`) for deployment status validation. | +| Claude | Admin API key (`api`) when configured; otherwise App Auto: OAuth API (`oauth`) → CLI PTY (`claude`) → Web API (`web`). CLI Auto: Web API (`web`) → CLI PTY (`claude`). | +| Gemini | OAuth-backed API via Gemini CLI credentials (`api`). | +| Antigravity | Local LSP/HTTP probe (`local`). | +| Cursor | Web API via cookies → stored WebKit session (`web`). | +| OpenCode | Web dashboard via cookies (`web`). | +| OpenCode Go | Web dashboard via cookies (`web`) -> local SQLite usage (`local`) in auto mode; optional workspace ID. | +| Alibaba Coding Plan | Console RPC via web cookies (auto/manual) with API key fallback (`web`, `api`). | +| Alibaba Token Plan | Bailian subscription summary API via browser or manual cookies (`web`). | +| Droid/Factory | API key (`FACTORY_API_KEY` / config) → web cookies → stored tokens → local storage → WorkOS cookies (`auto`, `api`, `web`). | +| Devin | Chrome localStorage session or manual Bearer token → daily and weekly quota API (`web`). | +| z.ai | API token from config/env → quota API (`api`). | +| Manus | Browser `session_id` cookie (auto/manual/env) → credits API (`web`). | +| MiniMax | Manual/browser session via Coding Plan web path (`web`), or Coding Plan API token (`api`). | +| Kimi | Kimi Code API key (`api`), then `kimi-auth` cookie/manual token/env fallback (`web`). | +| Kilo | API token from config/env → usage API (`api`); auto falls back to CLI session auth (`cli`). | +| Copilot | Device-flow/env/config token → `copilot_internal` API (`api`). | +| Kimi K2 (unofficial) | API key from config/env → legacy credit endpoint (`api`). | +| Kiro | CLI command via `kiro-cli chat --no-interactive "/usage"` (`cli`). | +| Vertex AI | Google ADC OAuth (gcloud) → Cloud Monitoring quota usage (`oauth`). | +| Augment | `auggie` CLI first, then browser-cookie web fallback (`cli`, `web`). | +| JetBrains AI | Local XML quota file (`local`). | +| Amp | Local `amp usage` CLI, access-token API, then browser-cookie legacy fallback (`cli`, `api`, `web`). | +| T3 Chat | Web tRPC customer-data endpoint via browser cookies (`web`). | +| Warp | API token (config/env) → GraphQL request limits (`api`). | +| ElevenLabs | API key from config/env → subscription usage API (`api`). | +| Windsurf | Web session bundle from browser localStorage (`web`) → local SQLite cache (`local`). | +| Ollama | API key verifies Cloud API access (`api`); browser cookies expose Cloud quota windows (`web`). | +| Synthetic | API key from config/env → quota API (`api`). | +| OpenRouter | API token (config, overrides env) → credits API (`api`). | +| CrossModel | API key from config/env → credits + usage API (`api`). | +| Perplexity | Browser cookies/manual cookie/env session token → credits API (`web`). | +| Xiaomi MiMo | Browser cookies → balance/token plan endpoints (`web`). | +| Doubao | API key from config/env → Volcengine Ark chat-completions probe (`api`). | +| Sakana AI | Manual Cookie header → billing page parser for 5-hour/weekly quota windows plus a best-effort pay-as-you-go credit balance (`web`). | +| Abacus AI | Browser cookies → compute points + billing API (`web`). | +| Mistral | Console billing, credit balance, and Vibe subscription usage via browser cookies (`web`). | +| DeepSeek | API key from env or token accounts → balance endpoint (`api`). | +| Moonshot | API key from config/env → balance endpoint (`api`). | +| Codebuff | API token from config/env or `codebuff login` credentials → usage API (`api`). | +| Crof | API key from config/env → credit balance + requests quota API (`api`). | +| Venice | API key from config/env → DIEM/USD balance API (`api`). | +| Command Code | Web billing API via Command Code session cookies (`web`). | +| StepFun | Username/password login or manual Oasis token (`web`). | +| AWS Bedrock | AWS credentials → Cost Explorer spend/budgets and optional CloudWatch Claude activity (`api`). | +| Grok | `grok agent stdio` JSON-RPC `x.ai/billing` (`cli`) → grok.com billing gRPC-web via Chrome session cookies (`web`); local `~/.grok/sessions` signals as fallback. | +| GroqCloud | API key → Prometheus metrics API for request/token/cache-hit rates (`api`). | +| LLM Proxy | API key + base URL → `/v1/quota-stats` aggregate proxy usage (`api`). | +| ClawRouter | API key + optional base URL → `/v1/usage` monthly budget, spend, and routed-provider usage (`api`). | +| Wayfinder | Local gateway URL → `/healthz`, `/v1/savings`, `/router/models`, `/metrics` for health, routing split, savings, and decision latency (`api`). | +| LiteLLM | API key + base URL → `/key/info`, then `/user/info` or `/team/info` budget usage (`api`). | +| Deepgram | API key → project discovery and usage breakdown API (`api`). | +| Chutes | API key from config/env → subscription usage and quota API (`api`). | +| Zed | Zed editor Keychain session → `cloud.zed.dev/client/users/me` for plan and quota data (`local`). | + +## Codex +- App Auto: OAuth API first; falls back to CLI only when OAuth credentials are missing or auth/refresh is invalid. +- Web dashboard (optional, off by default): `https://chatgpt.com/codex/settings/usage` via WebView + browser cookies. +- Battery saver toggle (currently off by default): reduces routine OpenAI web refreshes but still allows explicit manual refreshes. +- CLI RPC default: `codex ... app-server` JSON-RPC (`account/read`, `account/rateLimits/read`). +- CLI PTY: manual diagnostics/parser coverage only; automatic refresh does not launch bare Codex TUI. +- Local cost usage: scans `CODEX_HOME` (or `~/.codex`) `sessions` and sibling `archived_sessions` JSONL files for the configured history window. +- Status: Statuspage.io (OpenAI). +- Details: `docs/codex.md`. + +## OpenAI +- API key from `~/.codexbar/config.json`, `OPENAI_ADMIN_KEY`, or `OPENAI_API_KEY`. +- Admin API keys are preferred and fetch organization costs plus completion usage for inline Today/7d/configured-window dashboards. +- Normal API keys fall back to the legacy credit-grants balance endpoint when organization usage is unavailable. +- Details: `docs/openai.md`. + +## Azure OpenAI +- API key, endpoint, and deployment from `~/.codexbar/config.json` or `AZURE_OPENAI_API_KEY`, `AZURE_OPENAI_ENDPOINT`, and `AZURE_OPENAI_DEPLOYMENT_NAME`. +- `AZURE_OPENAI_ENDPOINT` and configured endpoint overrides must be HTTPS URLs or bare hosts normalized to HTTPS; explicit `http://` URLs, user info, and encoded host-delimiter tricks fail closed before `api-key` headers are attached. +- Validates the configured deployment with a minimal chat-completions request; it does not expose Azure spend or quota history. +- Use `AZURE_OPENAI_API_VERSION` to override the API version. Set it to `v1` for Azure's OpenAI-compatible v1 API path. +- Status: Azure status page link. +- Details: `docs/azure-openai.md`. + +## Claude +- Admin API: `sk-ant-admin...` key in Settings/config, token accounts, or `ANTHROPIC_ADMIN_KEY`. +- Admin API shows organization spend/messages summaries with the same inline dashboard pattern as OpenAI API. +- App Auto: OAuth API (`oauth`) → CLI PTY (`claude`) → Web API (`web`). +- CLI Auto: Web API (`web`) → CLI PTY (`claude`). +- Local cost usage: scans `CLAUDE_CONFIG_DIR` when set, otherwise `~/.config/claude/projects`, + `~/.claude/projects` (including current Claude Desktop Code/Cowork CLI sessions), and nested Claude Desktop + local-agent JSONL files for the configured history window. +- Status: Statuspage.io (Anthropic). +- Details: `docs/claude.md`. + +## z.ai +- API token from `~/.codexbar/config.json` (`providers[].apiKey`) or `Z_AI_API_KEY` env var. +- Supports global and BigModel CN quota hosts; override with `Z_AI_API_HOST` or `Z_AI_QUOTA_URL`. +- z.ai endpoint overrides must be HTTPS or bare hosts normalized to HTTPS. `Z_AI_QUOTA_URL` takes precedence for + quota resolution; combined usage validates both configured endpoints before sending bearer auth. +- Status: none yet. +- Details: `docs/zai.md`. + +## Devin +- Automatic auth reads the current `auth1_session` token and organization metadata from Chrome localStorage. +- Manual auth accepts the `Authorization: Bearer ...` value from an app.devin.ai request. +- Usage endpoint: `GET /api//billing/quota/usage`. +- Shows daily and weekly quota percentages with their reset timestamps. +- Details: `docs/devin.md`. + +## Manus +- Session token via browser `session_id` cookie, manual Settings entry, `MANUS_SESSION_TOKEN`, or `MANUS_COOKIE`. +- Credits endpoint: `POST https://api.manus.im/user.v1.UserService/GetAvailableCredits`. +- Auto mode prefers cached/browser cookies before env fallback; manual mode accepts either a bare `session_id` value or a full Cookie header. +- Status: none yet. +- Details: `docs/manus.md`. + +## MiniMax +- Coding Plan API token or web session from configured/manual/browser sources. +- Supports global and China mainland hosts via provider region settings and environment overrides. +- Web-session billing history can render 30-day token charts plus top model/method breakdowns when MiniMax exposes it. +- Status: none yet. +- Details: `docs/minimax.md`. + +## Kimi +- Kimi Code API key via `~/.codexbar/config.json` or `KIMI_CODE_API_KEY`. +- Web fallback uses the JWT from `kimi-auth` cookie via manual entry or `KIMI_AUTH_TOKEN` env var. +- Shows weekly quota and 5-hour rate limit (300 minutes). +- Status: none yet. +- Details: `docs/kimi.md`. + +## Kilo +- API token from `~/.codexbar/config.json` (`providers[].apiKey`) or `KILO_API_KEY`. +- Auto mode tries API first and falls back to CLI auth when API credentials are missing or unauthorized. +- CLI auth source: `~/.local/share/kilo/auth.json` (`kilo.access`), typically created by `kilo login`. +- Status: none yet. +- Details: `docs/kilo.md`. + +## Kimi K2 (unofficial) +- API key via `~/.codexbar/config.json` or `KIMI_K2_API_KEY`/`KIMI_API_KEY` env var. +- Shows credit usage from the legacy `kimi-k2.ai` consumed/remaining totals. +- Use Moonshot / Kimi API for the official Kimi API account and billing surface. +- Status: none yet. +- Details: `docs/kimi-k2.md`. + +## Gemini +- OAuth-backed quota API (`retrieveUserQuota`) using Gemini CLI credentials. +- Token refresh via Google OAuth if expired. +- Tier detection via `loadCodeAssist`. +- Status: Google Workspace incidents (Gemini product). +- Details: `docs/gemini.md`. + +## Antigravity +- Local Antigravity language server (internal protocol, HTTPS on localhost). +- `GetUserStatus` primary; `GetCommandModelConfigs` fallback. +- Status: Google Workspace incidents (Gemini product). +- Details: `docs/antigravity.md`. + +## Cursor +- Web API via browser cookies (`cursor.com` + `cursor.sh`). +- Fallback: stored WebKit session. +- Status: Statuspage.io (Cursor). +- Details: `docs/cursor.md`. + +## OpenCode +- Web dashboard via browser cookies (`opencode.ai`). +- Status: none yet. +- Details: `docs/opencode.md`. + +## OpenCode Go +- Web dashboard via browser or manual cookies (`opencode.ai`). +- Auto mode falls back to local usage from `~/.local/share/opencode/opencode.db` on macOS and Linux. +- Uses the workspace Go page/server data for rolling 5-hour, weekly, and optional monthly usage windows. +- Optional workspace ID comes from `~/.codexbar/config.json` (`providers[].workspaceID`) or `CODEXBAR_OPENCODEGO_WORKSPACE_ID`. +- Status: none yet. +- Details: `docs/opencode.md`. + +## Alibaba Coding Plan +- Web mode uses Alibaba console RPC with form payload + `sec_token`. +- Cookie sources: browser import (`auto`) or manual header (`cookieSource: manual`). +- API key fallback from Settings (`providers[].apiKey`) or `ALIBABA_CODING_PLAN_API_KEY` env var. +- Region hosts: international (`ap-southeast-1`) and China mainland (`cn-beijing`). +- Host overrides: `ALIBABA_CODING_PLAN_HOST` or `ALIBABA_CODING_PLAN_QUOTA_URL`. +- Status: `https://status.aliyun.com` (link only, no auto-polling). +- Details: `docs/alibaba-coding-plan.md`. + +## Alibaba Token Plan +- Web mode posts to the Bailian `GetSubscriptionSummary` endpoint with form-encoded params and optional `sec_token`. +- Cookie sources: browser import (`auto`), manual Cookie header, or `ALIBABA_TOKEN_PLAN_COOKIE`. +- Default quota URL: `https://bailian.console.aliyun.com/data/api.json?action=GetSubscriptionSummary&product=BssOpenAPI-V3`. +- Host overrides: `ALIBABA_TOKEN_PLAN_HOST` or `ALIBABA_TOKEN_PLAN_QUOTA_URL`. +- Status: `https://status.aliyun.com` (link only, no auto-polling). +- Details: `docs/alibaba-token-plan.md`. + +## Droid (Factory) +- API key from `~/.codexbar/config.json` (`providers[].apiKey`), `FACTORY_API_KEY`, or `~/.factory/.env`. +- Web API via Factory cookies, bearer tokens, and WorkOS refresh tokens. +- Auto prefers API when a key is available, then falls back to web strategies. +- Status: `https://status.factory.ai`. +- Details: `docs/factory.md`. + +## Copilot +- GitHub device flow OAuth token + `api.github.com/copilot_internal/user`. +- Supports multiple token accounts and account switching from provider settings/menu surfaces. +- Status: Statuspage.io (GitHub). +- Details: `docs/copilot.md`. + +## Kiro +- CLI-based: runs `kiro-cli chat --no-interactive "/usage"` with 10s timeout. +- Parses ANSI output for plan name, monthly credits percentage, and bonus credits. +- Requires `kiro-cli` installed and logged in via AWS Builder ID. +- Status: AWS Health Dashboard (manual link, no auto-polling). +- Details: `docs/kiro.md`. + +## Warp +- API token from Settings or `WARP_API_KEY` / `WARP_TOKEN` env var. +- Shows monthly credits usage and next refresh time. +- Status: none yet. +- Details: `docs/warp.md`. + +## Windsurf +- Web session bundle from browser localStorage import, manual Settings entry, or local SQLite cache. +- Shows daily and weekly quota usage with reset timing; local cache reads `state.vscdb` when web API is unavailable. +- Status: none yet. +- Details: `docs/windsurf.md`. + +## ElevenLabs +- API key from Settings, token accounts, `ELEVENLABS_API_KEY`, or `XI_API_KEY`. +- Reads `GET /v1/user/subscription` from `api.elevenlabs.io`. +- Shows character credit usage, reset timing, and voice slot usage when available. +- Override the API base URL with `ELEVENLABS_API_URL`. +- Status: `https://status.elevenlabs.io` (link only, no auto-polling). +- Details: `docs/elevenlabs.md`. + +## Vertex AI +- OAuth credentials from `gcloud auth application-default login` (ADC). +- Quota usage via Cloud Monitoring `consumer_quota` metrics for `aiplatform.googleapis.com`. +- Token cost: uses the Claude local-log scanner filtered to Vertex AI-tagged entries. +- Requires Cloud Monitoring API access in the current project. +- Details: `docs/vertexai.md`. + +## JetBrains AI +- Local XML quota file from IDE configuration directory. +- Auto-detects installed JetBrains IDEs; uses most recently used. +- Reads `AIAssistantQuotaManager2.xml` for monthly credits and refill date. +- Status: none (no status page). +- Details: `docs/jetbrains.md`. + +## Zed +- Reads the signed-in Zed editor session from the macOS Keychain (`credentials_url` / `https://zed.dev`). +- Calls `GET https://cloud.zed.dev/client/users/me` for plan, billing cycle, Edit Predictions quota, and overdue invoice flag. +- Sign in to the Zed editor first. +- Details: `docs/zed.md`. + +## Augment +- Auto mode tries the `auggie` CLI first. +- Web fallback uses browser cookies, with manual cookie header support. +- Tracks credit usage and account/subscription data where available. +- Status: none yet. +- Details: `docs/augment.md`. + +## Amp +- Auto mode tries the local `amp usage` command first. +- API mode calls Amp's balance endpoint with an access token. +- Web fallback reads the legacy settings page with browser cookies. +- Tracks Amp Free usage, account identity, and individual and workspace credit balances. +- Status: none yet. +- Details: `docs/amp.md`. + +## T3 Chat +- Web tRPC endpoint (`https://t3.chat/api/trpc/getCustomerData`) via browser cookies. +- Parses JSONL response lines and extracts customer data from the embedded tRPC payload. +- Shows the 4-hour Base bucket and monthly Overage bucket documented in the T3 Chat FAQ. +- Status: none yet. +- Details: `docs/t3chat.md`. + +## Ollama +- Web settings page (`https://ollama.com/settings`) via browser cookies. +- Parses Cloud Usage plan badge, session/weekly usage, and reset timestamps. +- Status: none yet. +- Details: `docs/ollama.md`. + +## Synthetic +- API key from `~/.codexbar/config.json` (`providers[].apiKey`) or `SYNTHETIC_API_KEY`. +- The menu card shows rolling five-hour, weekly token, and search-hourly quota lanes when present. The compact menu bar + metric uses the five-hour or weekly lane; weekly credit regeneration details appear when returned. +- External status page: `https://status.synthetic.new` (not linked or auto-polled by CodexBar). +- Details: `docs/synthetic.md`. + +## OpenRouter +- API token from `~/.codexbar/config.json` (`providers[].apiKey`) or `OPENROUTER_API_KEY` env var. +- Reads credits and key rate-limit info from OpenRouter APIs. +- Shows daily, weekly, and monthly API-key spend when `/api/v1/key` returns those fields. +- Override base URL with `OPENROUTER_API_URL` env var. +- Status: `https://status.openrouter.ai` (link only, no auto-polling yet). +- Details: `docs/openrouter.md`. + +## CrossModel +- API key from `~/.codexbar/config.json` (`providers[].apiKey`) or `CROSSMODEL_API_KEY` env var. +- Reads wallet balance (`/v1/credits`) and matching-currency UTC day/week/month spend (`/v1/usage`). +- Shows balance plus today/this week/this month spend; no quota meter (prepaid wallet, no per-key limit). +- Override base URL with `CROSSMODEL_API_URL` env var (loopback HTTP allowed for local testing). +- Details: `docs/crossmodel.md`. + +## Perplexity +- Browser session cookie from automatic import, manual header/token, or `PERPLEXITY_SESSION_TOKEN` / `PERPLEXITY_COOKIE`. +- Tracks recurring credits, bonus/promotional credits, purchased credits, and renewal date when present. +- Status: `https://status.perplexity.com/` (link only, no auto-polling). +- Details: `docs/perplexity.md`. + +## Xiaomi MiMo +- Browser cookies from automatic import or manual `Cookie:` header for `platform.xiaomimimo.com` balance and token-plan endpoints. +- Optional testing override via `MIMO_API_URL`; overrides must be HTTPS or bare hosts normalized to HTTPS, and invalid + overrides fail closed instead of falling back to local MiMo usage accounting. +- Local MiMo token accounting is available only when the opt-in cache file exists. +- Status: none yet. +- Details: `docs/mimo.md`. + +## Doubao +- API key via `ARK_API_KEY`, `VOLCENGINE_API_KEY`, `DOUBAO_API_KEY`, or provider config. +- Probes Volcengine Ark chat completions and reads request rate-limit headers when present. +- Status: none yet. +- Details: `docs/doubao.md`. + +## Sakana AI +- Manual `Cookie:` header from `console.sakana.ai`; no automatic browser import. +- Reads the billing page and surfaces 5-hour and weekly quota windows when present. +- Also fetches the pay-as-you-go tab (best-effort, never fails the primary quota fetch) for a + `fugu`/`fugu-ultra` prepaid credit balance and a rolling usage total. +- Status: none yet. +- Details: `docs/sakana.md`. + +## Abacus AI +- Browser cookies (`abacus.ai`, `apps.abacus.ai`) via automatic import or manual header. +- Reads organization compute points and billing data. +- Shows monthly credit gauge with pace tick and reserve/deficit estimate. +- Status: none yet. +- Details: `docs/abacus.md`. + +## Mistral +- Session cookie (`ory_session_*`) from browser auto-import or manual `Cookie:` header. +- CSRF token (`csrftoken` cookie) sent as `X-CSRFTOKEN` for billing and Vibe usage requests. +- Domains: `admin.mistral.ai` for API billing and credit balance, and `console.mistral.ai` for optional Vibe subscription usage. Console requests forward only `csrftoken` and `ory_session_*`; all other admin cookies stay origin-bound. +- Reads monthly usage and pricing from the billing usage endpoint, plus credit balance from the billing credits endpoint, using the Mistral web session. +- Cost is computed client-side from token counts and response pricing. +- Reads Vibe monthly-plan usage percentage and reset time when the console endpoint is available. +- The menu bar metric can show either pay-as-you-go API spend or monthly-plan usage; the provider card shows balance when the credits endpoint is available. +- Resets at end of calendar month. +- Status: `https://status.mistral.ai` (link only, no auto-polling). +- Details: `docs/mistral.md`. + +## DeepSeek +- API key via `DEEPSEEK_API_KEY` / `DEEPSEEK_KEY` env var or DeepSeek token accounts. +- Shows total balance with paid vs. granted breakdown; USD preferred when multiple currencies present. +- Status: `https://status.deepseek.com` (link only, no auto-polling). +- Details: `docs/deepseek.md`. + +## Moonshot / Kimi API +- API key via `MOONSHOT_API_KEY` / `MOONSHOT_KEY` env var or provider config. +- Reads `GET /v1/users/me/balance` from the selected Moonshot region. +- Region: international (`api.moonshot.ai`) or China mainland (`api.moonshot.cn`), configurable in Settings or `MOONSHOT_REGION`. +- Shows available balance; negative cash balance is surfaced as a deficit. +- Status: none yet. +- Details: `docs/moonshot.md`. + +## Venice +- API key via `VENICE_API_KEY` / `VENICE_KEY` env var or Venice token accounts. +- Shows current DIEM or USD balance; DIEM epoch allocation progress when available. +- Status: none yet. +- Details: `docs/venice.md`. + +## Codebuff +- API token from `~/.codexbar/config.json`, `CODEBUFF_API_KEY`, or `~/.config/manicode/credentials.json` created by `codebuff login`. +- Reads usage and subscription data from Codebuff APIs. +- Shows credit balance, weekly rate limit, reset timing, subscription status, and auto-top-up flag when present. +- Override base URL with `CODEBUFF_API_URL`. +- Status: none yet. +- Details: `docs/codebuff.md`. + +## Crof +- API key from `~/.codexbar/config.json`, `CROF_API_KEY`, or `CROFAI_API_KEY`. +- Reads `credits`, `requests_plan`, and `usable_requests` from `GET https://crof.ai/usage_api/`. +- Shows request quota as the primary usage window and dollar credits as the secondary row. +- Infers the daily request reset from midnight America/Chicago until the usage API exposes reset metadata. +- Status: none yet. +- Details: `docs/crof.md`. + +## Command Code +- Browser session cookies from automatic import or manual `Cookie:` header. +- Linux CLI supports configured manual cookies; automatic browser import remains macOS-only. +- Reads monthly USD credits and billing-cycle usage from `api.commandcode.ai`. +- Automatic import looks for better-auth session cookies from `commandcode.ai` / `www.commandcode.ai`. +- Status: none yet. +- Details: `docs/command-code.md`. + +## Qoder +- Chrome session cookies from automatic import, or a manual `Cookie:` header/cURL capture on macOS or Linux. +- Reads big model credit usage from the Qoder account dashboard on `qoder.com` or `qoder.com.cn`. +- Shows used and total credits plus the usage percentage; invalid cached sessions retry freshly imported cookies. +- Status: none yet. +- Details: `docs/qoder.md`. + +## Grok +- `grok agent stdio` (ACP) JSON-RPC `x.ai/billing` method; requires `grok login` (SuperGrok OAuth/OIDC). +- Reads cached credentials from `~/.grok/auth.json` for identity (email, team). +- Falls back to grok.com's billing gRPC-web endpoint via Chrome session cookies when the CLI does not expose billing. +- CLI/test runs do not import browser cookies unless `CODEXBAR_ALLOW_BROWSER_COOKIE_IMPORT=1` is set. +- Local fallback aggregates `~/.grok/sessions/**/signals.json` token counts when the RPC is unavailable. +- Status: link only to `https://status.x.ai` (no auto-polling yet). +- Details: `docs/grok.md`. + +## GroqCloud +- API key from `~/.codexbar/config.json` or `GROQ_API_KEY`; base URL override via `GROQ_API_URL`. +- Reads Enterprise Prometheus metrics for request, token, and cache-hit rates per minute. +- Dashboard link: GroqCloud metrics console. +- Status: `https://status.groq.com`. +- Details: `docs/groqcloud.md`. + +## LLM Proxy +- API key + base URL from `~/.codexbar/config.json` (`enterpriseHost`), `LLM_PROXY_API_KEY`, or `LLM_PROXY_BASE_URL`. +- Reads `/v1/quota-stats` for aggregate proxy usage with lowest remaining quota, requests, tokens, and approximate cost. +- Status: none yet. +- Details: `docs/llm-proxy.md`. + +## ClawRouter +- API key from the resolved CodexBar config (`providers[].apiKey`) or `CLAWROUTER_API_KEY`. +- Defaults to `https://clawrouter.openclaw.ai`; optional config `enterpriseHost` or `CLAWROUTER_BASE_URL` selects another HTTPS deployment. +- Reads `/v1/usage` for the key policy's monthly budget, spend, request/token totals, and per-provider breakdown. +- Provider rows are data-driven, so any routed provider returned by ClawRouter is displayed without provider-specific CodexBar code. +- Details: `docs/clawrouter.md`. + +## Wayfinder +- No credentials: the local gateway's read-only endpoints are unauthenticated on loopback. +- Defaults to `http://127.0.0.1:8088`; optional config `enterpriseHost` or `WAYFINDER_GATEWAY_URL` overrides it (HTTPS anywhere, plain HTTP for loopback only). +- Reads `/healthz`, `/router/models`, and `/v1/savings?period=30d` for gateway health, the per-route breakdown by configured name, and savings vs. the highest-cost route; parses `/metrics` best-effort for average decision latency. +- Read-only: never calls the gateway's chat endpoints, and the polled endpoints return accounting metadata only — no prompt text. +- Details: `docs/wayfinder.md`. + +## sub2api +- API key from config, a labeled token account, or `SUB2API_API_KEY`; base URL from config `enterpriseHost` or `SUB2API_BASE_URL`. +- Reads `GET /v1/usage` for key quota, 5-hour/day/week rate limits, subscription limits, wallet balance, and key-scoped request/token/cost totals. +- Store one labeled token account per sub2api group. Wallet balance is user-scoped and is never summed across keys. +- Base URLs must use HTTPS, except loopback HTTP for local development. +- Details: `docs/sub2api.md`. + +## AWS Bedrock +- AWS credentials from `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and optional `AWS_SESSION_TOKEN`. +- Region from `AWS_REGION` / `AWS_DEFAULT_REGION`, defaulting to `us-east-1`. +- Reads AWS Cost Explorer for Bedrock spend and can compare usage against `CODEXBAR_BEDROCK_BUDGET`. +- Optionally reads rolling 14-day Claude token and request totals from CloudWatch with `cloudwatch:GetMetricData`. +- Override Cost Explorer base URL with `CODEXBAR_BEDROCK_API_URL` for tests. +- Details: `docs/bedrock.md`. + +## Deepgram +- API key from config or `DEEPGRAM_API_KEY`. +- Optional project ID from provider settings or `DEEPGRAM_PROJECT_ID`; otherwise aggregates all visible projects. +- Optional API base URL override via `DEEPGRAM_API_URL`; overrides must be HTTPS or bare hosts normalized to HTTPS. +- Reads Deepgram usage breakdowns for audio hours, agent hours, token totals, TTS characters, and requests. +- Details: `docs/deepgram.md`. + +## LiteLLM +- API key from config or `LITELLM_API_KEY`; base URL from config `enterpriseHost` or `LITELLM_BASE_URL`. +- Reads `/key/info` first, then `/user/info?user_id=...` for user-bound keys or `/team/info?team_id=...` for team-only keys. +- User-bound keys show personal budget usage as the primary window and the key's exact matching team as the secondary window. +- Team-only keys show the team budget as their sole usage window. Automatic menu-bar selection prefers the enforced team budget. +- Spend remains visible in the API-spend row when LiteLLM has no budget limit configured. +- Accepts base URLs with or without a `/v1` suffix; management requests are sent to the proxy root. +- Details: `docs/litellm.md`. + +## Poe +- API key from config or `POE_API_KEY`. +- Reads the current point balance and recent points history from Poe's official usage API. +- History failures are non-fatal; the current balance remains available. +- Details: `docs/poe.md`. + +## Chutes +- API key from config or `CHUTES_API_KEY`. +- Reads subscription usage first, then fills missing rolling, monthly, or pay-as-you-go quota data from the quota APIs. +- Uses Chutes' management API at `https://api.chutes.ai`; `CHUTES_API_URL` can override it with an HTTPS endpoint. +- Details: `docs/chutes.md`. + +## StepFun +- Username/password login or manual Oasis-Token. +- Reads Step Plan 5-hour and weekly rate-limit windows from `platform.stepfun.com`. +- Shows subscription plan name when the Step Plan status API returns one. +- Status: none yet. +- Details: `docs/stepfun.md`. + +See also: `docs/provider.md` for architecture notes. diff --git a/docs/qoder.md b/docs/qoder.md new file mode 100644 index 0000000..2e3f2af --- /dev/null +++ b/docs/qoder.md @@ -0,0 +1,73 @@ +--- +summary: "Qoder provider: browser/manual cookie setup for big model credit usage on qoder.com and qoder.com.cn." +read_when: + - Configuring Qoder usage + - Debugging Qoder cookie import, manual headers, or cURL captures + - Adjusting Qoder credit display +--- + +# Qoder Provider + +CodexBar reads Qoder big model credit usage from the Qoder account dashboard. It supports the international +`qoder.com` site and the China mainland `qoder.com.cn` site. + +## Setup + +1. Open **Settings -> Providers**. +2. Enable **Qoder**. +3. Sign in to [qoder.com](https://qoder.com/account/usage) or [qoder.com.cn](https://qoder.com.cn/account/usage) in + Chrome. +4. Leave Cookie source on **Automatic**, or switch to **Manual**. For `qoder.com`, paste a `Cookie:` header or a cURL/ + HTTP request capture from the usage page. For `qoder.com.cn`, paste a request capture that includes the China URL + or `Host` header so CodexBar can select the matching site. + +Bare `Cookie:` headers default to `qoder.com`. Request captures are parsed only when the target URL or header host +clearly belongs to `qoder.com` or `qoder.com.cn`. + +## Data Source + +CodexBar requests: + +- `GET https://qoder.com/api/v2/me/usages/big_model_credits` +- `GET https://qoder.com.cn/api/v2/me/usages/big_model_credits` + +The selected site controls the `Origin` and `Referer` headers. Automatic mode imports Qoder cookies from Chrome +and caches valid cookie headers. Invalid cached sessions are skipped so a fresh browser cookie can be retried. + +## Display + +- Shows used credits, total credits, and usage percentage. +- Merges `totalQuota` with `sharedQuota` when Qoder returns both. +- Uses `nextResetAt` when the API includes a reset timestamp. +- Token-cost history is not supported. + +## CLI Usage + +```bash +codexbar usage --provider qoder --verbose +``` + +## Troubleshooting + +### "Qoder session cookie not found" + +Sign in to Qoder in Chrome, then refresh CodexBar. If browser import is unavailable, switch to manual mode. Paste a +fresh `Cookie:` header for `qoder.com`; for `qoder.com.cn`, paste a cURL/HTTP request capture containing the China URL +or `Host` header. + +### "Qoder session is invalid or expired" + +Log in to Qoder again. CodexBar clears invalid cached cookies and retries fresh browser cookies in automatic mode. + +### Usage values look wrong + +Open the matching Qoder usage page and confirm whether the account is on `qoder.com` or `qoder.com.cn`; manual cURL +captures should come from the same site. + +## Related Files + +- `Sources/CodexBarCore/Providers/Qoder/QoderProviderDescriptor.swift` +- `Sources/CodexBarCore/Providers/Qoder/QoderUsageFetcher.swift` +- `Sources/CodexBarCore/Providers/Qoder/QoderUsageSnapshot.swift` +- `Sources/CodexBarCore/Providers/Qoder/QoderCookieImporter.swift` +- `Sources/CodexBar/Providers/Qoder/QoderProviderImplementation.swift` diff --git a/docs/quotio-comparison.md b/docs/quotio-comparison.md new file mode 100644 index 0000000..78fee8d --- /dev/null +++ b/docs/quotio-comparison.md @@ -0,0 +1,186 @@ +--- +summary: "Quotio comparison notes and possible CodexBar enhancement ideas." +read_when: + - Evaluating Quotio-inspired UX or architecture ideas + - Planning provider quota-tracking roadmap items + - Comparing CodexBar scope against proxy-based quota tools +--- + +# Quotio Comparison & Enhancement Opportunities + +**Date:** 2026-01-04 +**Source:** https://github.com/nguyenphutrong/quotio + +## Overview + +Quotio is a similar macOS menu bar app for AI quota tracking with **2k stars** and **117 forks**. It has a broader scope (proxy server + quota tracking) but shares many features with CodexBar. + +--- + +## Key Differences + +### Architecture +- **Quotio**: Manages a local proxy server (`CLIProxyAPI`) that routes requests to multiple AI providers +- **CodexBar**: Direct provider monitoring only (no proxy layer) +- **Implication**: Quotio is more complex but offers request routing/failover + +### Provider Support +**Quotio supports:** +- Gemini, Claude, OpenAI Codex, Qwen, Vertex AI, iFlow, Antigravity, Kiro, GitHub Copilot +- **IDE monitoring**: Cursor, Trae (auto-detected, monitor-only) + +**CodexBar supports:** +- Codex, Claude, Cursor, Gemini, Antigravity, Droid/Factory, Copilot, z.ai, Kiro, Vertex AI, **Augment** + +**Unique to CodexBar:** +- Augment (we just added!) +- z.ai +- Droid/Factory + +**Unique to Quotio:** +- Qwen, iFlow +- Trae IDE monitoring + +--- + +## Features We Should Consider + +### 1. **Auto-Warmup Scheduling** ⭐⭐⭐ +**What:** Automatically trigger 1-token model invocations on a schedule to keep accounts "warm" +**Why:** Prevents cold-start delays, maintains session freshness +**Implementation:** +- Interval-based (15min-4h) or daily scheduling +- Per-account model selection +- Progress tracking in UI +**Effort:** Medium (requires background task scheduler) +**Value:** High for providers with session timeouts (Claude, Augment) + +### 2. **Account Switching for Antigravity** ⭐⭐ +**What:** Switch active Antigravity account by injecting OAuth tokens into IDE's SQLite database +**Why:** Allows multi-account workflows without manual IDE logout/login +**Implementation:** +- Read/write to `~/Library/Application Support/Antigravity/User/globalStorage/state.vscdb` +- Protobuf encode/decode for OAuth tokens +- Process management (close IDE → backup → inject → restart) +**Effort:** High (complex SQLite + protobuf + process management) +**Value:** Medium (niche use case, but powerful for multi-account users) + +### 3. **Standalone Quota Mode** ⭐ +**What:** View quotas without running proxy server +**Why:** Lighter weight, faster startup for quick checks +**Implementation:** Already how CodexBar works! (We don't have a proxy) +**Effort:** N/A (we already do this) +**Value:** N/A (already implemented) + +### 4. **Smart Routing Strategies** ⭐⭐ +**What:** Round Robin or Fill First routing for multi-account setups +**Why:** Optimize quota usage across accounts +**Implementation:** Would require proxy layer (not applicable to CodexBar's architecture) +**Effort:** Very High (requires proxy server) +**Value:** Low for CodexBar (out of scope) + +### 5. **Custom Provider Support** ⭐⭐⭐ +**What:** User-defined AI providers with OpenAI-compatible, Claude, Gemini, Codex API configs +**Why:** Extensibility for new/custom providers without code changes +**Implementation:** +- `CustomProvider` model with API type, base URL, auth +- YAML config generation +- UI for add/edit/delete custom providers +**Effort:** Medium-High +**Value:** High (future-proofs the app, community can add providers) + +### 6. **Multilingual Support** ⭐ +**What:** English, Vietnamese, Chinese, French +**Why:** Broader user base +**Implementation:** `.xcstrings` localization (we already have infrastructure) +**Effort:** Medium (translation work) +**Value:** Medium (depends on target audience) + +--- + +## UI/UX Learnings + +### Menu Bar Design +- **Quotio**: Custom provider icons in menu bar, quota overview popup +- **CodexBar**: Two-bar meter icon, detailed menu card +- **Takeaway**: Both approaches valid; CodexBar's meter is more info-dense + +### Settings Organization +- **Quotio**: Dashboard, Providers, Agents, Quota, Logs, Settings tabs +- **CodexBar**: Settings → Providers with per-provider toggles +- **Takeaway**: Quotio's tab-based navigation is cleaner for complex apps + +### Quota Display +- **Quotio**: Grid layout with tier badges (Pro/Ultra/Free), inline refresh +- **CodexBar**: List-based with session/weekly bars +- **Takeaway**: Tier badges are a nice visual touch + +--- + +## Recommended Enhancements for CodexBar + +### Priority 1: Auto-Warmup Scheduling ⭐⭐⭐ +**Why:** Keeps sessions alive, prevents auth failures +**Implementation:** +1. Add `WarmupScheduler` service with interval/daily modes +2. Per-provider warmup config in Settings +3. Background task to trigger minimal API calls (1-token requests) +4. UI to show last warmup time + next scheduled warmup + +**Providers that benefit:** +- Claude (session expires) +- Augment (session expires) +- Codex (session expires) + +### Priority 2: Custom Provider Framework ⭐⭐⭐ +**Why:** Community extensibility, future-proof +**Implementation:** +1. `CustomProvider` model (name, icon, API type, base URL, auth) +2. Settings UI for CRUD operations +3. Generic quota fetcher that adapts to API type +4. Save to UserDefaults or JSON file + +**Benefits:** +- Users can add new providers without waiting for releases +- Easier to experiment with beta/internal APIs + +### Priority 3: Enhanced Antigravity Support ⭐⭐ +**Why:** Quotio's account switching is powerful +**Implementation:** +1. Add `AntigravityAccountSwitcher` service +2. SQLite database read/write for token injection +3. Process manager for IDE restart +4. UI confirmation dialog with progress states + +**Complexity:** High, but valuable for power users + +--- + +## What NOT to Adopt + +### ❌ Proxy Server Layer +- **Why:** Out of scope for CodexBar's mission (monitoring, not routing) +- **Complexity:** Very high (server management, request routing, failover) +- **Maintenance:** Ongoing burden + +### ❌ Agent Configuration +- **Why:** Quotio auto-configures CLI tools (Claude Code, OpenCode, etc.) to use its proxy +- **Relevance:** Not applicable without proxy layer + +--- + +## Conclusion + +**Top 3 Enhancements:** +1. **Auto-Warmup Scheduling** - Keeps sessions alive, prevents auth failures +2. **Custom Provider Framework** - Future-proof, community-driven extensibility +3. **Enhanced Antigravity Account Switching** - Power user feature + +**Quick Wins:** +- Tier badges in quota display (visual polish) +- Tab-based settings navigation (if app grows more complex) + +**Skip:** +- Proxy server layer (out of scope) +- Agent configuration (requires proxy) + diff --git a/docs/refactor/claude-current-baseline.md b/docs/refactor/claude-current-baseline.md new file mode 100644 index 0000000..bedeca3 --- /dev/null +++ b/docs/refactor/claude-current-baseline.md @@ -0,0 +1,155 @@ +--- +summary: "Current Claude behavior baseline before vNext refactor work." +read_when: + - Planning Claude refactor tickets + - Changing Claude runtime/source selection + - Changing Claude OAuth prompt or cooldown behavior + - Changing Claude token-account routing +--- + +# Claude current baseline + +This document is the current-state parity reference for Claude behavior in CodexBar. + +Use it when later tickets need to preserve or intentionally change Claude behavior. When the refactor plan, +summary docs, and running code disagree, treat current code plus characterization coverage as authoritative, and use +this document as the human-readable summary of that current state. + +## Scope of this baseline + +This baseline captures the current behavior surface that later refactor work must preserve unless a future ticket +changes it intentionally: + +- runtime/source-mode selection, +- prompt and cooldown behavior that affects Claude OAuth repair flows, +- token-account routing at the app and CLI edges, +- provider siloing and web-enrichment rules, +- the current relationship between the public Claude doc and the vNext refactor plan. + +## Active behavior owners + +Current Claude behavior is defined by several active owners, not one central planner: + +- `Sources/CodexBarCore/Providers/Claude/ClaudeProviderDescriptor.swift` + owns the main provider-pipeline strategy order and fallback rules. +- `Sources/CodexBarCore/Providers/Claude/ClaudeUsageFetcher.swift` + still owns a separate direct `.auto` path, delegated refresh, prompt/cooldown handling, and web-extra enrichment. +- `Sources/CodexBar/Providers/Claude/ClaudeSettingsStore.swift` + owns app-side token-account routing into cookie or OAuth behavior. +- `Sources/CodexBarCLI/TokenAccountCLI.swift` + owns CLI-side token-account routing and effective source-mode overrides. +- `Sources/CodexBarCore/TokenAccountSupport.swift` + owns the current string heuristics that distinguish Claude OAuth access tokens from cookie/session-key inputs. + +## Current runtime and source-mode behavior + +### Main provider pipeline + +The generic provider pipeline currently resolves Claude strategies in this order: + +| Runtime | Selected mode | Ordered strategies | Fallback behavior | +| --- | --- | --- | --- | +| app | auto | `oauth -> cli -> web` | OAuth can fall through to CLI/Web. CLI can fall through to Web only when Web is available. Web is terminal. | +| app | oauth | `oauth` | No fallback. | +| app | cli | `cli` | No fallback. | +| app | web | `web` | No fallback. | +| cli | auto | `web -> cli` | Web can fall through to CLI. CLI is terminal. | +| cli | oauth | `oauth` | No fallback. | +| cli | cli | `cli` | No fallback. | +| cli | web | `web` | No fallback. | + +This behavior is owned by `Sources/CodexBarCore/Providers/Claude/ClaudeProviderDescriptor.swift` +through `ProviderFetchPlan` and `ProviderFetchPipeline`. + +### Other active `.auto` decision sites + +The codebase still contains multiple active `.auto` decision sites: + +| Owner | Current behavior | +| --- | --- | +| `ClaudeProviderDescriptor.resolveUsageStrategy(...)` | Chooses `oauth`, then `cli`, then `web`, with final `cli` fallback when none are available. | +| `ClaudeUsageFetcher.loadLatestUsage(.auto)` | Chooses `oauth`, then `web`, then `cli`, with final `oauth` fallback. | + +This inconsistency is intentional to record here. RAT-107 directly characterizes the active direct-fetcher branches it +can reach cleanly in tests and records the remaining current-state behavior without reconciling it. + +## Prompt and cooldown baseline + +Current behavior that later refactor work must preserve: + +- The default Claude keychain prompt mode is `onlyOnUserAction`. +- Prompt policy is only applicable when the Claude OAuth read strategy is `securityFramework`. +- User-initiated interaction clears a prior Claude keychain cooldown denial before retrying availability or repair. +- Startup bootstrap prompting is allowed only when all of these are true: + - runtime is app, + - interaction is background, + - refresh phase is startup, + - prompt mode is `onlyOnUserAction`, + - no cached Claude credentials exist. +- Background delegated refresh is blocked when prompt policy is `onlyOnUserAction` and the caller did not explicitly + allow background delegated refresh. +- Prompt mode `never` blocks delegated refresh attempts. +- Expired credential owner behavior remains owner-specific: + - `.claudeCLI`: delegated refresh path, + - `.codexbar`: direct refresh path, + - `.environment`: no auto-refresh. + +## Token-account routing baseline + +Accepted Claude token-account input shapes today: + +- raw OAuth access token with `sk-ant-oat...` prefix, +- `Bearer sk-ant-oat...` input, +- raw session key, +- full cookie header. + +Current routing rules: + +- OAuth-token-shaped inputs are not treated as cookies. +- Cookie/header-shaped inputs are any value that already contains `Cookie:` or `=`. +- App-side Claude snapshot behavior: + - OAuth token account keeps the usage source setting as-is, disables cookie mode (`.off`), clears the manual cookie + header, and relies on environment-token injection. + - Session-key or cookie-header account keeps the usage source setting as-is, forces manual cookie mode, and + normalizes raw session keys into `sessionKey=`. +- CLI-side Claude token-account behavior: + - OAuth token account changes the effective source mode from `auto` to `oauth`, disables cookie mode, omits a + manual cookie header, and injects `CODEXBAR_CLAUDE_OAUTH_TOKEN`. + - Session-key or cookie-header account stays in cookie/manual mode. + +## Siloing and web-enrichment baseline + +Claude Web enrichment is cost-only when the primary source is OAuth or CLI: + +- Web extras may populate `providerCost` when it is missing. +- Web extras must not replace `accountEmail`, `accountOrganization`, or `loginMethod` from the primary source. +- Snapshot identity remains provider-scoped to Claude. + +This behavior is implemented in `Sources/CodexBarCore/Providers/Claude/ClaudeUsageFetcher.swift` +inside `applyWebExtrasIfNeeded`. + +## Documentation contract + +- [docs/claude.md](../claude.md) is the summary doc for contributors who want an overview. +- This file is the exact current-state baseline for contributor and refactor parity work. +- [claude-provider-vnext-locked.md](claude-provider-vnext-locked.md) + is the future refactor plan and should cite this file for present behavior. + +## Characterization coverage + +Stable automated coverage for this baseline lives in: + +- `Tests/CodexBarTests/ClaudeBaselineCharacterizationTests.swift` +- `Tests/CodexBarTests/ClaudeOAuthFetchStrategyAvailabilityTests.swift` +- `Tests/CodexBarTests/ClaudeUsageTests.swift` +- `Tests/CodexBarTests/TokenAccountEnvironmentPrecedenceTests.swift` +- `Tests/CodexBarTests/SettingsStoreCoverageTests.swift` + +`ClaudeUsageTests.swift` now directly characterizes the reachable `ClaudeUsageFetcher(.auto)` branches for: + +- OAuth when OAuth, Web, and CLI all appear available, +- Web before CLI when OAuth is unavailable, + +The successful CLI-selected branch and the CLI-failure-to-OAuth fallback remain documented from code inspection plus +surrounding Claude probe/regression coverage, because the current CLI-availability decision is sourced from process-wide +binary discovery with no stable test seam that would keep RAT-107 in scope. diff --git a/docs/refactor/claude-provider-vnext-locked.md b/docs/refactor/claude-provider-vnext-locked.md new file mode 100644 index 0000000..8576cf8 --- /dev/null +++ b/docs/refactor/claude-provider-vnext-locked.md @@ -0,0 +1,356 @@ +--- +summary: "Locked implementation plan for Claude provider vNext: resolved source-selection contracts, typed credential rules, siloing guarantees, and phase gates." +supersedes: "Initial vNext draft (removed)" +created: "2026-02-18" +status: "Locked for implementation" +--- + +# Claude provider vNext (locked plan) + +This is the implementation-locked vNext plan. + +It preserves the original architecture direction, but removes ambiguity in behavior-critical areas before refactor work starts. + +Current-state parity reference for present behavior: + +- [docs/refactor/claude-current-baseline.md](claude-current-baseline.md) + +Use the baseline doc for present behavior. This vNext plan defines what the refactor should preserve and how it should +be staged; it is not the sole source of truth for current implementation details, and RAT-107 does not re-approve the +rest of the future architecture below. + +## Assessment snapshot + +- **Approach score:** `8.4/10`. +- **Why not 9+ yet:** the original plan left runtime ordering, token-account credential typing behavior, and compatibility mapping under-specified. +- **How this doc closes the gap:** explicit contracts + resolved decisions + phase exit gates + risk checklist. +- **Validated gap coverage in this version:** explicit `.auto` inconsistency handling, `ClaudeUsageFetcher` decomposition, stronger parity gates, TaskLocal-to-DI migration, and OAuth decomposition sub-phases. + +## Locked behavioral contracts + +These behaviors are **non-negotiable** during refactor unless this doc is explicitly updated. + +### 1) Runtime + source-mode contract + +`ClaudeSourcePlanner` must reproduce this matrix exactly: + +| Runtime | Selected mode | Ordered attempts | Fallback rules | +| --- | --- | --- | --- | +| app | auto | oauth -> cli -> web | oauth fallback allowed; cli fallback to web only when web available; web terminal | +| app | oauth | oauth | no fallback | +| app | cli | cli | no fallback | +| app | web | web | no fallback | +| cli | auto | web -> cli | web fallback allowed to cli; cli terminal | +| cli | oauth | oauth | no fallback | +| cli | cli | cli | no fallback | +| cli | web | web | no fallback | + +Notes: +- `sourceLabel` remains the final step label for successful fetch output. +- Planner diagnostics must include ordered steps and inclusion reasons. +- Planner output must feed the existing generic provider fetch pipeline; do not introduce a second Claude-only + execution stack alongside `ProviderFetchPlan` / `ProviderFetchPipeline`. + +### 1a) `.auto` inconsistency characterization contract (must-do before reconciliation) + +Current code has three `.auto` decision sites with inconsistent app ordering: + +- Strategy pipeline resolve order (app): `oauth -> cli -> web`. +- `resolveUsageStrategy` helper order: `oauth -> cli -> web -> cli fallback`. +- `ClaudeUsageFetcher.loadLatestUsage(.auto)` order: `oauth -> web -> cli -> oauth fallback`. + +Phase 0 must characterize these paths with tests where they are reachable through stable seams, and otherwise defer to +the baseline doc before deleting any path. +Phase 2 must reconcile this into planner-only source selection. + +### 2) Prompt/cooldown contract + +The planner must use one explicit `ClaudePromptDecision` equivalent, but outcome parity with current behavior is required: + +- User-initiated actions can clear prior keychain cooldown denial. +- Startup bootstrap prompt is only allowed when all are true: + - runtime is app + - interaction is background + - refresh phase is startup + - prompt mode is `onlyOnUserAction` + - no cached credentials +- Background delegated refresh is blocked when: + - prompt policy is `onlyOnUserAction` + - caller does not explicitly allow background delegated refresh +- Prompt mode `never` blocks delegated refresh attempts. + +### 3) Credential typing + routing contract + +Typed credentials must be introduced at the settings snapshot edge, with behavior parity: + +- `ClaudeManualCredential.sessionKey` +- `ClaudeManualCredential.cookieHeader` +- `ClaudeManualCredential.oauthAccessToken` + +Accepted Claude token-account inputs must continue to work: + +- Raw OAuth token (including `Bearer ...` input) +- Raw session key +- Full cookie header + +Routing parity requirements: + +- OAuth token account values must route to OAuth path (not cookie mode). +- Cookie/session-key account values must route to web cookie path. +- CLI token-account behavior must remain consistent in both app and `CodexBarCLI`. +- Scope note: current string heuristics are mostly edge-routing logic, not deep OAuth credential decoding internals. + +### 4) Ownership and refresh contract + +Credential owner behavior must remain identical: + +- `.claudeCLI` expired credentials: delegated refresh path. +- `.codexbar` expired credentials: direct refresh endpoint path. +- `.environment` expired credentials: no auto-refresh. + +Refresh failure-gate semantics must remain unchanged. + +### 5) Provider siloing + enrichment contract + +Hard invariant: + +- Never merge Claude Web identity into OAuth/CLI snapshots. +- Web extras may enrich **cost only**. +- Snapshot identity must always remain provider-scoped to `.claude` when persisted/displayed. + +### 6) Plan inference compatibility contract + +Canonical plan inference can live behind the existing `loginMethod` compatibility surface, but outward +compatibility must be preserved: + +- Existing detectable plans continue mapping to display strings: + - `Claude Max` + - `Claude Pro` + - `Claude Team` + - `Claude Enterprise` +- Subscription detection behavior must remain compatible with current UI logic, including existing `Ultra` detection + semantics until that behavior is explicitly changed. + +### 7) Documentation + diagnostics contract + +- During refactor, characterization coverage plus + [docs/refactor/claude-current-baseline.md](claude-current-baseline.md) + are the source of truth when docs and code disagree. +- `docs/claude.md` must be updated as part of Phase 0 after characterization lands so it no longer presents divergent + runtime ordering as settled behavior. +- Debug surfaces must consume planner-derived diagnostics instead of recomputing Claude source decisions separately. + +## Resolved decisions (from open questions) + +### Web identity fill-ins + +- **Decision:** do not use Web identity to fill missing OAuth/CLI identity fields. +- **Allowed:** Web cost enrichment only. + +### CLI runtime fallback ordering + +- **Decision:** keep current CLI ordering in `auto`: `web -> cli`. +- Planner must encode this explicitly and not rely on incidental strategy ordering. + +### Startup bootstrap prompt in `onlyOnUserAction` + +- **Decision:** keep support exactly under the startup bootstrap constraints listed above. +- Any expansion/restriction requires explicit doc update and tests. + +### Runtime policy unification timing + +- **Decision:** do not unify app and CLI `auto` ordering before this refactor. +- First consolidate to one planner implementation with current runtime-specific behavior preserved. +- Any runtime-policy unification is a separate, explicit behavior-change follow-up. + +### Planner integration timing + +- **Decision:** `ClaudeSourcePlanner` must be integrated into the existing provider descriptor / fetch pipeline rather + than added as a parallel orchestration layer. +- Reuse current `ProviderFetchContext` / `ProviderFetchPlan` plumbing where possible. + +### Dependency seam timing + +- **Decision:** introduce dependency-container seams for newly extracted planner/executor components as they are + created. +- Full TaskLocal cleanup can remain later, but new components should not deepen TaskLocal coupling. + +## Locked migration plan with exit gates + +### Phase 0: Baseline lock + +Deliverables: +- Add `docs/refactor/claude-current-baseline.md` as the current-state behavior reference. +- Add/refresh characterization tests for runtime/source matrix and prompt-decision parity. +- Add explicit characterization tests for existing `.auto` decision paths where they are reachable through stable seams, + and defer remaining current-state details to the baseline doc until later reconciliation. +- Update `docs/claude.md` after tests land so documented ordering matches characterized behavior. + +Exit gate: +- Behavior matrix tests pass for app and cli runtimes. +- `.auto` characterization coverage plus the baseline doc record current divergence explicitly without forcing new + production seams in Phase 0. +- `docs/claude.md` no longer contradicts characterized runtime/source behavior. + +### Phase 1: Canonical plan resolver + +Deliverables: +- Introduce `ClaudePlan` + one resolver used by OAuth/Web/CLI mapping and downstream UI consumers. + +Exit gate: +- Plan mapping tests cover tier/billing/status-derived hints, compatibility display strings, and current UI subscription + detection compatibility. + +### Phase 1b: Typed credentials at the snapshot edge + +Deliverables: +- Parse manual Claude credentials once at the app + CLI snapshot edges into a typed model. +- Remove duplicated edge-routing heuristics for OAuth-vs-cookie decisions across settings snapshots and token-account + CLI code. + +Exit gate: +- Token account parity tests pass for app + CLI. +- Snapshot-edge routing no longer duplicates Claude OAuth-token detection logic in multiple call sites. + +### Phase 2: Single source planner + +Deliverables: +- Introduce `ClaudeSourcePlanner` + explicit `ClaudeFetchPlan`. +- Integrate planner outputs into the existing provider pipeline / descriptor flow. +- Remove duplicate `.auto` policy branches from lower layers. +- Reconcile and remove `ClaudeUsageFetcher` internal `.auto` source selection. +- Move debug/diagnostic surfaces to planner-derived attempt ordering instead of helper-specific recomputation. + +Exit gate: +- One authoritative planner path for mode/runtime ordering. +- Fallback attempt logs still show expected sequence and source labels. +- No surviving `.auto` source-order logic outside planner. +- No surviving debug-only source-order recomputation outside planner diagnostics. +- Old-vs-new planner parity tests pass before old branches are removed. + +### Phase 2b: `ClaudeUsageFetcher` decomposition + +Deliverables: +- Split `ClaudeUsageFetcher` into smaller executor-focused components. +- Extract delegated OAuth retry/recovery flow into dedicated units. +- Remove embedded prompt-policy/source-selection ownership from fetcher; keep it execution-only. + +Exit gate: +- Fetcher no longer owns source-selection policy. +- Delegated OAuth retry behavior is covered by dedicated tests and remains parity-compatible. + +### Phase 3: Test injection cleanup + +Deliverables: +- Prefer dependency seams on extracted units instead of adding new TaskLocal-only override points. + - Avoid expanding TaskLocal-only test hooks while decomposition work lands. + +Exit gate: +- New fetcher tests rely on explicit dependency seams where practical. + +### Phase 4: OAuth decomposition + +Deliverables (sub-phases): + +- **Phase 4a (repository extraction):** + - Extract IO + caching + owner/source loading into repository surface. + - Keep prompt-gate semantics unchanged. +- **Phase 4b (refresher extraction):** + - Extract network refresh + failure gating to refresher component. + - Keep owner-based refresh behavior unchanged. +- **Phase 4c (delegated controller extraction):** + - Extract delegated CLI touch + keychain-change observation + cooldown behavior. + - Keep delegated retry outcomes unchanged. + +Exit gate: +- Existing OAuth delegated refresh / prompt policy / cooldown suites pass without behavior deltas at each sub-phase. +- Owner semantics parity remains intact across all sub-phases (`claudeCLI`, `codexbar`, `environment`). + +### Phase 5: Test injection migration (TaskLocal -> DI) + +Deliverables: +- Move test injection from TaskLocal-heavy overrides to `ClaudeFetchDependencies` and explicit protocol stubs. +- Keep compatibility shims temporarily where needed, then remove them. + +Exit gate: +- Core planner/executor tests run without TaskLocal injection dependencies. +- Legacy TaskLocal-only override surfaces are either removed or isolated to compatibility adapters with deletion TODOs. + +### Phase 6: Web decomposition (optional) + +Deliverables: +- Separate cookie acquisition from web usage client. +- Keep probe tooling isolated behind debug/tool surface. + +Exit gate: +- Web parsing and account mapping tests remain green. + +## Implementation PR plan (stacked) + +Use this sequence to keep each PR reviewable without turning the rollout into unnecessary PR overhead. + +| PR | Title | Scope | Primary risks | Must-pass gate before merge | +| --- | --- | --- | --- | --- | +| PR-01 | Baseline characterization + doc correction | Lock current matrix behavior, characterize `.auto` paths through stable seams, defer remaining lower-level current-state details to the baseline doc, characterize prompt bootstrap/cooldown and token-account routing, then update docs to match reality. | R1, R2, R5, R6, R10 | No production behavior changes; characterization suites green; docs no longer contradict tests or the baseline. | +| PR-02 | Canonical plan resolver | Introduce `ClaudePlan` and central resolver; map OAuth/Web/CLI/UI compatibility through one model while preserving current `loginMethod` projections. | R8 | Plan compatibility tests green (`Max/Pro/Team/Enterprise` + current subscription compatibility). | +| PR-03 | Typed credentials at the edge | Parse manual credentials once (`sessionKey`, `cookieHeader`, `oauthAccessToken`) in app + CLI snapshot shaping. | R6 | Token-account routing parity tests green in app + CLI contexts. | +| PR-04 | Source planner introduction + cutover | Add `ClaudeSourcePlanner`, prove parity against old path, then remove duplicate `.auto` selection branches once parity is proven. | R1, R5, R10 | One `.auto` authority remains; attempt/source-label diagnostics remain parity-compatible. | +| PR-05 | `ClaudeUsageFetcher` decomposition | Split fetcher into execution/retry-focused units; remove embedded source-selection ownership. | R2, R10 | Delegated OAuth retry/recovery tests green with no behavior deltas. | +| PR-06 | OAuth decomposition | Extract repository, refresher, and delegated-controller seams from `ClaudeOAuthCredentialsStore` while preserving owner semantics. | R3, R4, R7, R9 | Cache/fingerprint/prompt/owner suites green (`claudeCLI`, `codexbar`, `environment`). | +| PR-07 (optional) | TaskLocal -> DI migration | Move remaining tests and seams to `ClaudeFetchDependencies`, keep temporary compat adapters, then remove. | R9 | Core planner/executor tests run without TaskLocal globals. | +| PR-08 (optional) | Web decomposition | Split cookie acquisition from web usage client and keep tooling isolated. | R8, R10 | Web parsing/account mapping suites remain green. | + +Stacking rules: + +1. Keep each PR scoped to one risk cluster and one merge gate. +2. Do not remove old branches until a prior PR has old-vs-new parity tests in CI. +3. If a PR intentionally changes behavior, update this locked doc in the same PR and call it out in summary. +4. Prefer 6 core PRs unless parity risk forces a temporary split; do not fragment the rollout further without a + concrete rollback or reviewability reason. + +## Mandatory test additions + +Add these test groups before or during Phases 1-3, then extend for later phases: + +1. Planner matrix tests: + - `(runtime x selected mode x interaction x refresh phase x availability)` -> exact step order + fallback. +2. `.auto` divergence characterization tests: + - Lock current behavior of strategy pipeline vs `resolveUsageStrategy` helper vs fetcher-direct `.auto`. + - Use as guardrails while consolidating to planner-only logic. +3. Typed credential parsing tests: + - OAuth token, bearer token, session key, cookie header, malformed strings. +4. Cross-provider identity isolation tests: + - Ensure `.claude` identity does not leak via snapshot scoping/merging. +5. Source-label and attempt diagnostics tests: + - Validate final source label and attempt list parity. +6. CLI token-account parity tests: + - `TokenAccountCLIContext` and app settings snapshot behavior match for OAuth-vs-cookie routing. +7. Old-vs-new parity tests: + - Compare old path and planner path outputs before branch removals in Phase 2 and Phase 2b. +8. DI migration tests: + - Ensure new dependency container can drive planner/executor tests without TaskLocal globals. + +## Risk checklist (implementation review) + +Use these risk IDs in refactor PR checklists/reviews. + +| Risk ID | Severity | Risk | Detail | +| --- | --- | --- | --- | +| R1 | Critical | Auto-ordering reconciliation | Three `.auto` paths are inconsistent today. Characterize strategy pipeline vs `resolveUsageStrategy` helper vs fetcher-direct `.auto` before deleting any path. | +| R2 | High | Prompt policy consolidation | Prompt policy exists across strategy availability, fetcher flow, and credentials store gates. Preserve startup bootstrap constraints exactly to avoid prompt storms or silent OAuth suppression. | +| R3 | High | `ClaudeOAuthCredentialsStore` decomposition | Large lock-protected state + layered caches + fingerprint invalidation + security calls. Splits can break cache coherence, invalidation timing, or prompt gating order. | +| R4 | High | Owner semantics drift | Preserve exact owner-to-refresh mapping: `.claudeCLI` delegated, `.codexbar` direct refresh, `.environment` no refresh. | +| R5 | Medium | CLI runtime parity | Preserve runtime-specific policy: CLI `auto` remains `web -> cli`; OAuth is available only when explicitly selected as `sourceMode=.oauth`. Do not accidentally default CLI runtime to app ordering. | +| R6 | Medium | Token-account OAuth-vs-cookie misrouting | Keep routing parity for OAuth token vs session key vs full cookie header, including `Bearer sk-ant-oat...` normalization. | +| R7 | Medium | Cache invalidation regressions | Preserve credentials file/keychain fingerprint semantics and stale-cache guards during repository extraction. | +| R8 | Low-Medium | Plan inference heuristic drift | Preserve web-specific plan inference fallback (`billing_type` + `rate_limit_tier`) when unifying plan resolution. | +| R9 | Medium | Strict concurrency / `@Sendable` regressions | Maintain thread-safe behavior from current NSLock-based state while moving to DI/decomposed components under Swift 6 strict concurrency. | +| R10 | Low | Debug/diagnostic drift | Keep source labels, attempt sequences, and debug output aligned with real planner decisions after consolidation. | + +## Change-control rule + +Any refactor PR that intentionally changes one of the locked contracts above must: + +1. Update this document. +2. Add/adjust tests proving the new behavior. +3. Call out the behavior change explicitly in the PR summary. diff --git a/docs/refactor/cli.md b/docs/refactor/cli.md new file mode 100644 index 0000000..1e9ea37 --- /dev/null +++ b/docs/refactor/cli.md @@ -0,0 +1,78 @@ +--- +summary: "CLI refactor plan: JSON-only errors, config validation, SettingsStore split." +read_when: + - "Refactoring CodexBar CLI error handling or config parsing." + - "Splitting SettingsStore into smaller files." + - "Adding config validation or CLI config commands." +--- + +# CLI Refactor Plan + +## Goals +- JSON-only: every error is valid JSON on stdout (no mixed stderr). +- Per-provider errors: provider failures yield provider-scoped error payloads. +- Config validation: warn on invalid fields, unsupported source modes, bad regions. +- Config parity: add CLI command to validate (and optionally dump) config. +- SettingsStore split: files <500 LOC; clear separation (defaults vs config). + +## Constraints (keep) +- Provider ordering stays driven by config `providers[]` order. +- Provider enable/disable stays in config (`enabled`). +- No Keychain persistence for provider secrets. +- CLI still supports text output for non-JSON use. + +## Error JSON shape +- JSON output remains an array for `usage` and `cost` commands. +- Errors appear as payload entries with `error` set. +- Global/CLI errors use `provider: "cli"` and `source: "cli"`. + +```json +{ + "provider": "cli", + "source": "cli", + "error": { "code": 1, "message": "...", "kind": "config" } +} +``` + +## Config validation rules +- `source` must be in provider descriptor `fetchPlan.sourceModes`. +- `apiKey` only valid when provider supports `.api`. +- `cookieSource` only valid when provider supports `.web`/`.auto`. +- `region` only for `zai` or `minimax` with known values. +- `workspaceID` only for `opencode`. +- `tokenAccounts` only for providers in `TokenAccountSupportCatalog`. + +## CLI commands +- `codexbar config validate` + - Prints JSON issues (or text summary). + - Exit non-zero if any errors. +- (Optional) `codexbar config dump` + - Prints normalized config JSON. + +## Step-by-step implementation guide +1. **Add validation types** + - `CodexBarConfigIssue` + `CodexBarConfigValidator` in `CodexBarCore/Config`. + - Keep file <500 LOC. +2. **Hook validation into CLI** + - New `config validate` command. + - `--json-only` emits JSON array of issues. +3. **Unify CLI error reporting** + - Parse `--json-only` early. + - Route all exits through a JSON-aware reporter. + - Use provider-scoped errors where possible. +4. **Split CLIEntry.swift** + - Extract helpers + payload structs into dedicated files (<500 LOC each). +5. **Split SettingsStore.swift** + - Move config-backed computed properties to `SettingsStore+Config.swift`. + - Move defaults-backed computed properties to `SettingsStore+Defaults.swift`. + - Move provider detection to `SettingsStore+ProviderDetection.swift`. +6. **Provider toggles cleanup** + - Remove unused `ProviderToggleStore` + tests; keep migrator path for legacy toggles. +7. **Tests** + - CLI json-only error payloads (invalid source, invalid provider selection). + - Config validation (bad region/source/apiKey field). + - SettingsStore order/toggle invariants still pass. +8. **Verification** + - `make test`, `swiftformat Sources Tests`, `swiftlint --strict`, `make check`. + - `./Scripts/compile_and_run.sh`. + - CLI e2e: `codexbar --json-only ...`, `codexbar config validate`. diff --git a/docs/refresh-loop.md b/docs/refresh-loop.md new file mode 100644 index 0000000..d7384b6 --- /dev/null +++ b/docs/refresh-loop.md @@ -0,0 +1,55 @@ +--- +summary: "Refresh cadence, background updates, and error handling." +read_when: + - Changing refresh cadence, background tasks, or refresh triggers + - Investigating refresh timing or stale data behavior +--- + +# Refresh loop + +## Cadence +- `RefreshFrequency`: Manual, 1m, 2m, 5m (default), 15m, 30m, Adaptive. +- Stored in `UserDefaults` via `SettingsStore`. The default stays 5m for new and existing users; nothing + auto-migrates an existing fixed selection to Adaptive. + +## Behavior +- Background refresh runs off-main and updates `UsageStore` (usage + credits + optional web scrape). +- Manual “Refresh now” always available in the menu. +- Stale/error states dim the icon and surface status in-menu. +- Optional provider-storage scans run only when “Show provider storage usage” is enabled. They are scheduled in the + background, coalesced/throttled during automatic refreshes, and forced by manual refresh without blocking the usage + refresh path. + +## Adaptive mode +- `AdaptiveRefreshPolicy` (`Sources/CodexBar/AdaptiveRefreshPolicy.swift`) is a pure function of an `Input` + (current time, last menu-open time, Low Power Mode, thermal state) that returns the next delay and a + stable `Reason`. It reads no clock and no `ProcessInfo` state itself — `UsageStore.startTimer()` gathers + those impure signals immediately before each tick. +- Policy table, first match wins: + + | Condition | Delay | Reason | + |---|---:|---| + | Low Power Mode enabled, or thermal state `.serious`/`.critical` | 30 min | `constrained` | + | Menu opened within the last 5 min (including future/clock-adjusted timestamps) | 2 min | `recentInteraction` | + | Menu opened 5 min–1 h ago | 5 min | `warm` | + | Menu opened 1–4 h ago | 15 min | `idle` | + | No recorded menu open, or opened 4+ h ago | 30 min | `longIdle` | + +- Every decision falls in the 2–30 min range by construction. Deliberately excludes quota, latency, error, + account, and time-of-day signals. +- `UsageStore` tracks `lastMenuOpenAt` in memory only (never persisted; resets on launch). `noteMenuOpened(at:)` + is called from `StatusItemController.menuWillOpen(_:)`. A menu open can bring a pending adaptive tick + forward to the recent-interaction cadence, but never postpones an earlier tick or refreshes synchronously. +- Each adaptive tick recomputes the delay after the previous refresh completes, sleeps, then calls the same + `UsageStore.refresh()` used by fixed-interval mode, so the existing `isRefreshing` coalescing guard still + applies — only one provider-batch refresh runs at a time regardless of cadence mode. +- Selected delay and reason are logged (e.g. `reason=warm delay=300s` in the `adaptive-refresh` category) through + the existing local logger; never provider identity, account, email, workspace, path, credentials, or response data. +- Interval-derived heuristics (reset-boundary refresh, OpenAI web staleness, persistent-CLI-session idle windows) + read `UsageStore.normalRefreshIntervalForHeuristics()`, which resolves adaptive mode to the current decision's + delay — they stay active in adaptive mode rather than degrading to manual, whose interval is nil. + +## Optional future +- Auto-seed a log if none exists via `codex exec --skip-git-repo-check --json "ping"` (currently not executed). + +See also: `docs/status.md`, `docs/ui.md`. diff --git a/docs/releasing-homebrew.md b/docs/releasing-homebrew.md new file mode 100644 index 0000000..7aa73cb --- /dev/null +++ b/docs/releasing-homebrew.md @@ -0,0 +1,52 @@ +--- +summary: "Homebrew Cask release steps for CodexBar (Sparkle-disabled builds)." +read_when: + - Publishing a CodexBar release via Homebrew + - Updating the Homebrew tap cask definition +--- + +# CodexBar Homebrew Release Playbook + +Homebrew is for the UI app via Cask. When installed via Homebrew, CodexBar disables Sparkle and shows a "update via brew" hint in About. + +## Prereqs +- Homebrew installed. +- Access to the tap repo: `../homebrew-tap`. + +## 1) Release CodexBar normally +Follow `docs/RELEASING.md` to publish `CodexBar-macos-universal-.zip` to GitHub Releases. + +## 2) Let the Release CLI workflow update the tap +After the GitHub release is published, `.github/workflows/release-cli.yml` builds the standalone CLI assets and dispatches `steipete/homebrew-tap`'s `update-formula.yml`. That tap workflow updates both: +- `Casks/codexbar.rb` for the app zip. +- `Formula/codexbar.rb` for the standalone CLI tarballs. + +If dispatch fails or is rate-limited, update the files manually. + +## 2a) Manual cask update +In `../homebrew-tap`, update the cask at `Casks/codexbar.rb`: +- `url` points at the GitHub release asset: `.../releases/download/v/CodexBar-macos-universal-.zip` +- Update `sha256` to match that zip. +- Keep `depends_on macos: ">= :sonoma"` (CodexBar is macOS 14+). Do not add an architecture restriction; the app zip is universal. + +## 2b) Manual formula update +In `../homebrew-tap`, update the formula at `Formula/codexbar.rb`: +- `url` points at the GitHub release assets: + - macOS: `.../releases/download/v/CodexBarCLI-v-macos-arm64.tar.gz` + - macOS: `.../releases/download/v/CodexBarCLI-v-macos-x86_64.tar.gz` + - Linux: `.../releases/download/v/CodexBarCLI-v-linux-aarch64.tar.gz` + - Linux: `.../releases/download/v/CodexBarCLI-v-linux-x86_64.tar.gz` +- Static musl tarballs are also published for manual Linux installs as `linux-musl-aarch64` and `linux-musl-x86_64`; keep the formula on the glibc assets unless intentionally changing its runtime contract. +- Update all `sha256` values to match those tarballs. + +## 3) Verify install +```sh +brew uninstall --cask codexbar || true +brew untap steipete/tap || true +brew tap steipete/tap +brew install --cask steipete/tap/codexbar +open -a CodexBar +``` + +## 4) Push tap changes +Commit + push in the tap repo. diff --git a/docs/repository-size.md b/docs/repository-size.md new file mode 100644 index 0000000..7379201 --- /dev/null +++ b/docs/repository-size.md @@ -0,0 +1,69 @@ +--- +summary: "Repository size findings, prevention checks, and the maintainer-only history cleanup runbook." +read_when: + - Adding large assets or release artifacts + - Investigating clone size + - Planning a Git history rewrite +--- + +# Repository size + +The checked-out source tree is not the main cause of CodexBar's clone size. At commit `61ff9320`, tracked files total +22,292,801 bytes, while the packed Git object database is 103.91 MiB. `CHANGELOG.md` is 150,271 bytes in the current +tree and all of its historical blobs occupy about 0.55 MB compressed. + +Most of the packed history comes from files that are no longer present on `main`: + +| Historical path group | Approximate compressed bytes | +| --- | ---: | +| `screenshots/` | 39,023,716 | +| `Quotio/` | 23,141,837 | +| `CodexBar 2.app/` | 7,088,125 | +| `CodexBar-0.2.2.zip` | 2,296,323 | + +The largest single blob is the retired `Quotio/Resources/Proxy/cli-proxy-api-plus` executable: 49,202,546 bytes +before compression and about 15.8 MB in the pack. Deleting these files in later commits stopped further growth but +did not remove their blobs from existing history. + +## Prevention + +`Scripts/check_repository_size.sh` runs under `make check`. It inspects the exact blobs in Git's index, not mutable +working-tree copies, and rejects: + +- tracked files larger than 2 MiB; +- app bundles, dSYMs, Xcode results, IPAs, archives, deltas, disk images, and installer packages. + +Publish release artifacts through GitHub Releases. Optimize required source images before committing them. If a +source asset genuinely must exceed the limit, discuss and review the limit change explicitly rather than bypassing +the check. + +For a smaller local checkout when full history is unnecessary, use one of: + +```bash +git clone --filter=blob:none https://github.com/steipete/CodexBar.git +git clone --depth=1 https://github.com/steipete/CodexBar.git +``` + +## One-time history cleanup + +A normal pull request cannot reduce the size of already reachable Git objects. Maintainers can recover most of the +avoidable clone weight only with a coordinated history rewrite. Candidate paths that are absent from current +`main` are: + +```text +screenshots/ +Quotio/Resources/Proxy/cli-proxy-api-plus +CodexBar 2.app/ +CodexBar_Dev.app/ +CodexBar-0.2.2.zip +CodexBar6-2.delta +CodexBar6-4.delta +``` + +Use `git filter-repo` on a fresh mirror, validate all branches and tags, and force-push only during an announced +maintenance window. This changes commit and tag IDs and requires contributors to re-clone or carefully rebase, so +the rewrite must not be performed from a normal contributor branch. + +An isolated mirror rehearsal using exactly the candidate paths above reduced the packed object database from +103.90 MiB to 41.99 MiB (59.6%) and passed `git fsck --full --no-dangling`. Treat this as a reproducible baseline, +not authorization to rewrite the canonical repository. diff --git a/docs/sakana.md b/docs/sakana.md new file mode 100644 index 0000000..2dbdad2 --- /dev/null +++ b/docs/sakana.md @@ -0,0 +1,130 @@ +--- +summary: "Sakana AI provider: manual Cookie header, billing page parser, 5-hour/weekly quota windows, and pay-as-you-go credit balance." +read_when: + - Adding or modifying the Sakana AI provider + - Debugging Sakana AI cookie import or quota parsing + - Adjusting Sakana AI menu labels or reset window display + - Debugging Sakana pay-as-you-go credit balance or usage-total parsing +--- + +# Sakana AI + +[Sakana AI](https://sakana.ai) is a research lab focusing on foundation models and nature-inspired AI. CodexBar reads +the billing page to surface 5-hour and weekly quota windows for subscribers. + +## Setup + +1. Sign in at [console.sakana.ai](https://console.sakana.ai). +2. Open your browser's developer tools, navigate to the **Network** tab, and reload the billing page + (`console.sakana.ai/billing`). +3. Copy the full `Cookie:` request header value from any billing-page request. +4. In CodexBar, paste the header in **Settings → Providers → Sakana AI → Cookie header**. + The value is stored unencrypted in the [resolved config file](configuration.md#location). CodexBar sets that file's + permissions to `0600` whenever it writes the file on macOS or Linux. + +Alternatively, set the environment variable `SAKANA_COOKIE` to the raw cookie header value. + +## Data source + +- **Auth method**: manual `Cookie:` header; no automatic browser cookie import. +- **Target page**: `https://console.sakana.ai/billing` (HTML scrape; no JSON API). +- **Source label**: `web`. + +## Usage details + +- The primary row shows the **5-hour quota** as a 300-minute session window and uses the reset timestamp shown on the + billing page when one is present. +- The secondary row shows the **weekly quota** as a seven-day window and uses its billing-page reset timestamp when + one is present. +- `usedPercent` for each window is parsed from the billing page's adjacent `% used` text. +- Reset dates are parsed as **UTC**, not the device's local time zone. The billing page always server-renders + "Resets on " in UTC — the browser only corrects it to the viewer's local time client-side, after JS + hydration, which this HTML-only fetcher never runs. (Parsing with `TimeZone.current` instead shifted every reset + by the device's UTC offset; see [#1826](https://github.com/steipete/CodexBar/issues/1826).) The fetcher detects + `"MMMM d, yyyy 'at' h:mm a"` format strings. +- Plan name and price label (e.g. `Standard $20/mo`) are joined and surfaced as the `loginMethod` identity field for + plan display in the menu. +- Token cost tracking (`supportsTokenCost: false`): not supported; cost summary is unavailable. Sakana has no + organization-level usage/cost API to query historically, only the per-request `usage` object returned by chat + completions calls (which CodexBar never makes), so there is no local-log source to scan the way Claude/Codex are. +- Credits row (`supportsCredits: false`): not shown. The shared credits-card UI path (`MenuCardView+Costs.swift`) + has no Sakana branch and would just render the static `creditsHint` string instead of the fetched balance, so + `supportsCredits` stays off; the balance is surfaced explicitly instead (see below). +- Widget support: not currently available for Sakana AI. + +## Pay-as-you-go credits + +Sakana also sells prepaid credit for pay-as-you-go API usage (the model IDs `fugu` and `fugu-ultra`), separate from +the subscription quota windows above. `console.sakana.ai/billing` renders this data server-side under its +"Pay as you go" tab, but that tab's markup is only present in the HTML response when the request URL includes +`?tab=payAsYouGo` — the default `/billing` response (used for the subscription quota fetch above) does not include +it. CodexBar issues a **second, best-effort** GET to `https://console.sakana.ai/billing?tab=payAsYouGo` with the same +cookie header alongside the subscription request — skipped entirely (no request made) when +`context.includeOptionalUsage` is `false`, i.e. Settings → Advanced → "Show optional credits and extra usage" is +disabled. + +- **Credit balance**: parsed from the `

Credit balance

` card's adjacent `tabular-nums` amount. +- **Recent usage total**: parsed from the `Usage` chart header's `Total: $…` text, covering whatever date range is + currently selected on the console (defaults to the last 30 days). React renders this text with `` + hydration-boundary comments splitting the label from the amount; the parser strips those before reading the value. +- **Date range label**: the raw text of the "Usage date range" picker button (e.g. `Jun 02, 2026 - Jul 01, 2026`), + kept only as context — CodexBar does not currently interpret it as start/end dates. + +This second fetch never throws and never blocks the primary result: if it fails (network error, non-200, wrong +origin, empty body, or the expected markup isn't found), the pay-as-you-go fields are simply absent from that +refresh and the subscription quota windows are returned exactly as before. An account with no pay-as-you-go credit +purchased still returns a `$0.00` balance (the card is always rendered), so absence here almost always means the +request itself failed rather than "no credit." + +The optional request runs concurrently with the required subscription request and has its own five-second bound. +It is cancelled when the required request fails or the caller cancels, so it cannot add a second full request +timeout or outlive the refresh that started it. + +- Menu: an `Extra usage` card shows `Balance: $X.XX` and, when available, `Usage: $X.XX` alongside the quota windows. + The values are gated on Settings → Advanced → "Show optional credits and extra usage" at **both** + the fetch and the render layer: turning the setting off only rebuilds the menu without an immediate refetch, so a + previously-fetched balance would otherwise linger in the cached snapshot until the next refresh. Both the live + menu-card model and the text descriptor hide the values whenever the setting is off, independent of cached data. +- Not shown in the menu bar text: unlike some other credits-only providers, Sakana already has real 5-hour/weekly + rate windows, and the "secondary metric" preference that would otherwise select an alternate menu bar display is + the legitimate way to show the *weekly* window there. Reusing it for the PAYG balance would silently replace the + weekly percentage for anyone who picks that preference, so the balance is menu-only for now. + +## CLI usage + +``` +codexbar usage --provider sakana +codexbar usage --provider sakana-ai # alias +``` + +Set the cookie via the environment variable or Settings UI: + +- **Environment variable**: `SAKANA_COOKIE= codexbar usage --provider sakana` +- **Settings UI**: Settings → Providers → Sakana AI → Cookie header + +There is no `codexbar config set` command for `cookieHeader`; use one of the paths above. + +## Errors + +| Error | Meaning | +|-------|---------| +| `missingCookie` | No `Cookie:` header is configured and `SAKANA_COOKIE` is unset. | +| `loginRequired` | The request was unauthorized/forbidden, redirected, or ended on a different origin. | +| `apiError(Int)` | The billing page returned a non-`200` status not classified as a login failure. | +| `parseFailed(String)` | The billing response was empty or its quota data could not be parsed. | + +## Related files + +- `Sources/CodexBarCore/Providers/Sakana/` + - `SakanaProviderDescriptor.swift` — provider metadata, fetch plan, CLI config + - `SakanaSettingsReader.swift` — `SAKANA_COOKIE` env key, cookie normalizer + - `SakanaUsageFetcher.swift` — billing-page HTML fetch and quota parser; also defines + `SakanaPayAsYouGoSnapshot` and the pay-as-you-go tab fetch/parser +- `Sources/CodexBar/Providers/Sakana/` + - `SakanaProviderImplementation.swift` — settings UI, availability check + - `SakanaSettingsStore.swift` — `sakanaCookieHeader` settings binding +- `Sources/CodexBar/MenuCardView+Costs.swift` — live menu-card balance and usage section +- `Sources/CodexBar/MenuDescriptor.swift` — text-descriptor balance and usage rows +- `Tests/CodexBarTests/SakanaUsageFetcherTests.swift` — parser regression tests +- Dashboard: `https://console.sakana.ai/billing` (subscription tab), `https://console.sakana.ai/billing?tab=payAsYouGo` + (pay-as-you-go tab) diff --git a/docs/screenshots/claude-extra-usage-bug.png b/docs/screenshots/claude-extra-usage-bug.png new file mode 100644 index 0000000000000000000000000000000000000000..3f2beaf8cf258cec0eb6c6db84203819ac0b78db GIT binary patch literal 81474 zcmZVl18`>1vo8!M6WcZ>$;37%#uIB|+qP}nwr$(CZ5wa?=bn4dsqfoWt9I|z{p()X zRja$YSE#JCC>%64G!PIFoVb{fJP;5t7ZA`dHAwKE9@&hYLLeaM8dE_*S#d!@LRmX& zBU1}QARw{O#AFCXg;DI`S)m|RJXw3dpDi8+>bqvCo;D`?B=XwKpzdXUCafS7LKafxo(!%3a7x=Z z#*EAkg@Q98tbhl~8qkA60Vc#E@-k!PLYgIdCA8>0zIlN>CccPEN}3XALDMB674f-g z;HCNE${gr69g<}JS0My7U1d0QgWn+~KuLA|y%F_oXXn+nCOmeC3 z(7kh=hZoT{oAh;Q;YHuzy!^t)Qg> zaV}P6%>&t~c*I!gfgKt5`u?QuDHC^aY5F?|e|_L=fE;!rH7x5}TK~<5>lDD;1#}D) zP*dV@m}*eQPqS)^HP+SCf#|$#Om(4KUrlC+ib3&RQ@x-7rNa)4W;_SR0+~b$7adHz zKM;Tr>I3tO5~-6;WIg5<(_!+1GV%kziq3$x^+2WoQ|Ult_~6`tb`c^5_)*mSsu4gI z1Nj>RqU_h0gPGtrsl!zQ?%wMq3lZgqk^|P@4{w8|0m0U*d4m|zOYZ_q*26^)CV&V} zEQl%wHs|+1q%Z=VCqNrRet-ZbC?|`X0C`J<)PSspkoXr(mZbrqEI3NgI0ycOasgs9 z7(AEZgyjKBq?c3`c*zHDN0=V2sNc(mq61etfN9601#$~irMK}0sRirGr@G%+m*L}A zmJo0PssvPFB%|Q0EUY3SC3d0@a-MR&gluAonj%RV++t)~By#?c9KozAGZ;WPJvVcP z_k^AqC(~Cel2%Y9|9ochg!aMmfza*OCz{|;iM|v=6ebxNa(u{WFRDHz0|Y}cLo&TH zLw}01Dz!3{c}U~%n@)bs=*lk(EGM=mD0krXV7xx*JsWnkj6YLY7$N$*bvA=7nJpwO z_buuzx*HH3s9G@AfzN%S`>!vKFA^WR9~>VvACO*QgpxDl?8v{MaR1`xX4v@5h_nb` zl1U*Qh6D*2>rpVIwj`+vTaaoI^AdN(#>LIW+Qq0*4#umIDE)SnItyFKSrCom9t{{E z9E=ev02Bxoz!ba}uo*C}`do-akr~Ib#h#C1jLM7<6#SVxnv*h(a>#Xvbf|xzIZb8+ z#qz{zn}AOBNR>#9XJj)NGK8uFuY>)UbYZrNy~nLm=E0vjS_Yj#u~O8 z)*8kVW{fr{LGc^pcaeOVeCr%kp;w^{3^V!+h7E>=#!So3lHc=~*_hRs#v$?{*w+efkl{Bm+%YQaHMddHRxT<*}kLWoDX0WuB89dBb9( zXM^zCdxLvpu>-7QpTp8A^C|bz@3T1v6o=+hr!(mj(^IgM$_4Wo_Z*p-;#2a|>zV5% zZ)+VBMBSR+oI#xh+0_`+6zdh8myr;Q1G5BOMRSK?OmitFX@)IJk9knmS{8A}QifJt z==8PJJ1OV%Cz=6j2h|a6)pnbn2m=weaaMDB9A*{9XEtr)Exj+h*sZ)1VRdvzx;Haj z^H?+6p1s_{j>76g&T-c9Wo0sDi*oF8t|bF=y7Ry1%I7MqMXVa>Jgm$lG+XZt4+xtaDxrV8SQKGy#QaK9Q@tm+V zEm~6AUwZb4jPZ<yLqCxJ$X!chP|(N^4KffPdr)NVcE4j*WB^!h1lOet{*h^DeX02 zI!{IEdg?0oX#WuNBJx`FlKBLD1b$fp+xS@bEcu8^J|y2HH-P%_8|^Ih3=0GaUz$K$4 zzOvacRwgV@V!@h@*hb^)HL7v0(YD!OUuW0XFt!47Chg_OCDvu0<*+s1Q;jp1H=JXS z?kzv+lz0-~O8?;fO@Amm*1Qn1P{iz^rm=?A#myJEomiEcmA*wzkA?~}fE9(c&O{dA z)#slodvrIkL=9HJe};q=>V*hr)NZhB;5`C0&5=r#JU)Fn$~3y3!WMU(_$>+C=A${& zD(`-{mgrx8QvOsKq&!@GMZG{nO^K_u-&tfuV{19Kw!QSPqFnXa$#dYXi8wNkMOcu} z<$Fe!T9cX@e`TjZ_d5E7z?JXGs$r|eet#KRdbCkKd~R%R+VG;zobTV4;^TZX04m*W z{BrEsV#w;q`f7Wxt+48E6>+zoiFwb`k>!Hr@AWOK=uNN2xgxu3_&xYpc-us8rE}@d z%yeh3D(SK=^?j}R21(E5AY=T<&TOxvPY>(t=dL3)|FyBtmCx1p zY&=N5nNOI@DwwMCvgYb)z6!6F4qz)pmI%C14!ir3;n^jT`XNt% z1fX!Zhhet%cz8eRIs1ld)-}$l?l$48RI~U`v1D5AQO8keQUSWHxuW?t);3e7rL<+S zH_P{qY&v(|kH0s1W*sjw zt$fa%%xe{H;(xwyPGJJo+;i z%{{Qb-vjlH&k;n4gtkf8gSeS)iUYbSU^~! z)R?ir(d*7tz~42iYG3Ug->V>@XWMVyz*Aa~)D;A%;Xf{{vZ1QD5dZ*0`9nhj0SB7` zf&NgyKMnh*0Re%;1pz_)ypeyJP|mOa%LV4j0r|i5FSY*&3MdGQi~qb8^z94{t?W&# z9RPz%@IR`SOchlfQ~^?)`qq}Tx(3#IhO{o0HvfSDal3H-kd}rHx`Zy47FPD0E=obo~<{|*27;vqJ1 zaIoQ|qjPq4rgdhbwYD>+W8mQ6prdD`V`QZHk)W}6wQ|sPp|P?j`9DhjuO1;odwn}o z8wXQsE5iTi)z!0hbl@Q-{*R&m_xzu68oHSNk0mSn|DM**1nK_6p<|$>r~7}pf1up| z>E)C)buqN~CuC~*vphdGcvM>*)BR`W|7#`w&ocj4@6S5(LUYsozdhrHhVRfA0|Md)5*HFs zbOFBbgy_*!O1yfLq%1}JD^3VSNZIM%7ZTq-lI1xR#(sZvdXm6)Ir&4ZuB#5y z&dCAW%ElC-o_78Ym@y~h@&0P=YJ6IAzw~@+eg1;d322XZf2Q1~bkDSZ+C0v1pXReU z?xYf3uEhC`jraQ_{yP>ubYv;AD&LWWgt@Pp#awxQtq)AFR@8COuPyzo{zk{)Khz-85f8>+|LFjqN$^>x->vzxrRVd|Z_G z0xO<(OgcOBTUJo;@NM`ZHI6|BYm5mr98_KoVquzuh@8v$RBH=46s72sLqR# zk|SbC7obJtx;Do|Q|@!|!`($Zt+KP%ZPP`97pZS~@tLnzx4+hCa91U-$f)#E6I^fK z-ExjEkLxJJr%${O@a|a(+&c)V2J7as)Fqi*j&Q1V*}>6hcg5j*UO>6MQ1VDLAz>gIKg~9>I_@)S@eN;A^q>`*{LX@zgY(Uk<%bNq8x1`puYj`HNomc^B zBc}m7K8BSCOom+k31&r&dJXR4X{=lW^qDgsWSvm);Z>*?1;TxxI4kzFVxo80{#4@m zg0zQCXG7*D_9+-*EgA)mj&(KJk-DInxi*%o1Cb+)7UP-G@vT`(?UGV|gj8Vpld-Ez=0xs4jq)URp z*sO8C3h3e2IK^T%x7GlHc030q3@h;-++5K->rUf$r^~~NFn`e2ys5>ZO6^10B!@i3;U|WitQ}WCDdmu!75kXzk@V4^ceXx#K6H z#4=NGjgDCDb){tUsDxZ|ibLyDyn>NZw|%KOMp;NR4pBM{b>5=H zBV-(1@%Ne3-1Jtl+wR)bUnA_H0jZ1ta&G0bvnU#Y?#A-rM5RL>j_ZY) zi!u(-ckh;*1!JnNMQ$}^6Z3k5ez=-%cO8O^r|bxBYNvJ|RSvEjYIaB&f|2uUn88~d zwgsXN`OEWCn{NB?t;S^|0iL7C5qE?)UBU)H6cMcY=Tz@uFSk<@O@j#K47s{}IK$Q3 zTCQ9$L-PlKq9G`ms&fV-S!vB!`0Sy*p#HGK=y@&oi=N_IA#>&X(n^_yy|*os@$E;Y z#EOhEY~xfX7#vo&d?p<#g@F^DjB=e~x{bf1>Z8YMHlx@LpG=W^li`n)n>Ehi<$pw_ zQJ|~leJ5QRgqk~b<6-X}{A~M1N_xOkUqanN7>=~k@43j@!@So8#=3q5ju4YOCU;Eo zyLt8Z?2DZ@ERhL|$?0m7>T>VoR6=Eff=eQUwDE4|KK7W#bF{uXW$g(phZsAu*1##d ziKH{d<5ZoHOdJrKi2Z{}H3!#4dRk=ZpirM&etg=}cUNn@gGwE@AZWrV21(w2NU6A3 zs_n&V-r|SAZ(su)q{Ejl?_80ydB~IKW|@7opSXG0KfHfj*^0#MP<%BP2{ZKz7WmL3bU(l69R>g^g7RL;Hqj z+1wBF%IqvAqg(qX$YYCJp;jArWX%>$7I_?Mg*NdQ1_BB`C?Q~;t2Fh6ch%*O$&1Ny z+R)ov+vs}+v?Z)ke+q28+gc|yLKI5}3PULOc^YoA{Z`&^EV^$8#I^e2lNCkg$(3is z$=-U<>Di#a!=h$O=GTSQMr%yL=H(>3t%rt;V6r=dB`sK$q(3lDx+mPGc(Kc83T%}bt&ovd9j;u0OHnd&5R0+6 zeq4u)i`MS#nblqZuv(1{{k`sV!gA+A&hwoh4t<6F4ugHh-=xVHfL2fRh&h~RZBe=nY~k59mNJYp z!zZ{-3c|@|rK!}$a}q*}9vy-~curP%9>q_^z)^RN8*;e<2kdYQVwaQ3wh*%=^0JhX z`Cr2?6cGVq@qaZ^(2?X}Ze95MKR!Ek zEVX&=v@#AQBZtoLGtpjLV$U`-GiQZTa}m(PVVW>;2&hS`OH2~D%UiI7tUx6|>JSS- ztoOQ|FY}1{c9mqQ$@mxkN)<@a@cRua41F8!I}5@!yD`L8Q@_9^#lhS$={*9vGlE+! zJ_3l~rn#@gVfU6%NIo3nQ`4=+v?+sTVB^b;S_;Y)j{4s?B?>!rI9Hb)j+ipt^kLup zDxRR<=vO=@Zj5>FU0R3i9X+fz4;IX*o1kz?Yv2wM8Ht`TwpkxCG-qEW^!wURmX0pT zdsRDA_+xe_N z%*u&Stl8CIVv*8|WBl1H$6XO&q+CA9*y8|bd173@Efzh_x!tvYAn+`+a)ks2!=B9e zM*vc#P#t|`703asMR%PboO6ic1zO13S5tY`KCs(m6q_U52Kvq7zt1aa=jy-VeRJ<( zd1$bKF~=Hm*_MKO>{la96-+MA7DK3A@5Zb$Kc*bx0c2w`Ot9+blHM#6s)ixmCbO9i z_W-t;xx(oBR*_oO6Z3{41^`xLg7dzl`@SR>9b4vO5tVy2gk{I$@2=7DA+s>5xC0c{ zKM7;Qc1(JApn1tx2}{i$SOKiMtM!GN?d*{>QGecZX5Rkc8RF>Jfnc)F^qE@3cS?oj~2l1g~)$1C<_G$nZ(7sX$5VuRNP8F%0Azv8%} zk<_!Hxvc}ZEnD2I#bA}Y!+w4DJ>>tC)7t48%E7a-Y@$^Zs!l`5YKQn45fbGC*Kd3y-1#Aj zem;%WCbrp4ihr>RmqvrHlytWx_G<2H2)8d+BB6m;7Q@h}PV!);i_NQB<;fB;x@<7s z@{>CvqDxEBS+6}aH1<1K1+?@~GB0yEQyGi{UKaE57(Mh&6Rx}9M>bWI$1+u6u6WWX zM2wN-t<#DU*Egg`v<@d?JH1?s$1Y7vBSumHhS5n+=65b{RdV$IT6)iyD zo>Qw0+rV^1{aUV|mi3q1a=c$F`41-~(KD%hJegkhqk%@qY!+is+HP6^nLC;FHT94` zIQ*ueli(-UozM7gAGgDSPhS2?yUH}{!&YgEIQRKUfBbH-36H~az|6Z~YHP43yQw68 zvxH06*;i|eBG4R)Uqw4~uNc(>w_V@LVGpy}@;yiCa(*dgULQ?u1enmSzclGQ0bMo= z(%!$-&ak_{Z+pfR$>4`8K~(UGwHlN#8%2HW7`lT#(QPpm_Vv`M-TW>03=YXd#t9|U zLf%jXYsm}-i=(P)tj-^&>rUvpZKRuBRQZhZel6I+v1&=`dX1zTzx5}8b}(~-{l`9d zlrfSqV&HA5O{ z*zbnjo)lDrPzMCS`(t@+*=|A)ML%)ScvP70@Vx0f&td$XP>oiVn;+$c_xTW^aELQ4 zit8A`?P@r8@TY-K#;-WTa@AiQr3CF^DU6e(UzgZrDa&xa`UAw;`gp z`s&EJL+1zf7HI~#w;d5qulW6*)+MCHDERV5t64eRiyGr>TMP;|%ZG7LG8rg>z`kVb zu({{o9lW&G|iw2hklGz zdK}v%oiTojiH7c%*Xa|-;jUOOyP;9WQ9ufPEWGRBuEVJ{U9A1ZU^x0LzWbGM`$Zkq zrt9z}HS*wFyXI~Rf*4Vt1G2SPm?cNunnp|fFK&M>8!vfjTMh9#55PbkCZFNw zi>I-3)vq;0uXzkYno>kQ3O9f`^{NHldWFwVHqO(&f?R8#3Akr1dr`KuZw*|x_46P2 zqA~Mix-C=SzmwmfL1e09z{K4p;NUFQ*4|!Fv~Af5Wf`sxyDx!p75CPfps@ln`6qlK zA`IP-)p427`#ZCtqf9c-n$1Pdr6SYQ!ZRK7-v)Yh8RQL za&slU;7BNIVG^8NFvR+>!q23)9nd$uuQeUUBUNVao!3y7FK#kQ8kJ@0m5oP(?_7eV zki&)Mlql?V&+CL?Fzy^%@l1xKy6`a)o^MYN0x>e^B&WdEFA0}%Zb~20C28|`p4Zen zB#=_nhL&HiT0U8`R(K~c2wycqGjUyJBuyUAlo}pthgYwq+HRJQXCIffsa&r*=4l;f zB(*5nEnc!eFC5hBTxvB?4012hdEfKLz^yJP$Vb<(YBW?c59L`M!L9@}dGi zi~2S9{>=eUiPH8srq3L1&3M7d3eaX3BXC_L+)a36>yUrAjHJUa`0g#==?Xj9Fsdp$(blZElUo2SrOk2wam)RKw0htxMB75;aoMOc zOVhj|^xl0k=#g>JKb>?ymuzU6P<@z5ZY--6VSd;=tZx!lqUABu+Ym+vLvuLJ*}Uz= zRH@b)rZq8)wzg{g`Exj1iMnk?am_V%-J-3zopX2y-imNO!CCKdKiDmx$WRwfvTbK* zjSf#Xn9d)%a6V%g&-;6D@1}91Go{}(zWf}YVd%6Sg31N+FKHj=QJx^8Vj%UoMFNu0 zyELYaWMf=^_ES)LDVF`8t2@6#yxe;^8YVyR9tD72z`(u(sGkW~#n?4GgdQ{2$x_7lf zh416qUMW%z%bM;in|9}u4@b=%nOh%6&Gp^sP>c=QS?@4iNKC$4&%XO6+n-Oz^QVKo zgA|!#C|G)4K91>DZCIZl7fi1ElS!kO8`>Wl9u=y!8BRxwWZ22%4Pq%hqw5Z^ql#k& zd41|^tj~ztk+ZuU|3DssFyQ9OU(_(YobI2=D+>n^;<1MrPTnPq9|#3BYyPpYTi(LCSPwU5Qm z(2a|ojjLPV#`?HsKRsY4Q{*^;;Aizs7RweHZ&P=}4#!{Hy1eXmusNb~pF5uY?N(2S zwF-7%FFpxAAT6iaFs_dRLDx=;Ge(A|?q5~kYj6csDROqP_c|q$W_GJN`$jukKIynBp|r6{~j}H>rmg{peA0Y-O)xZ7(cs6b+(s zQB2*%mzTNWljY;@FfGpkb5818b#UrbL6t5)NC6E6x**3e=+c#7#G=pRF{4===n$w=OBbw6`OTI(379+AK$}J3T*8I)cl5~p!-sfGL zV}N-8T}D2{_rxFUd?Ogx5AVANq*jqP6ho)&G%sT8&iFunk0^#y8=3a8~^^CoDLOh1P{jvjZAShoqSb7V1lKn&# za`_Bgtq?S%u{pyg9qpzJp#(Lt6zb#UV70zEhv56hyL5j8YPIWU@B)A$kzTIC1B_GSZtlhI!i zWrm@eZh>e_@)q!8W!WejKD|AvZ%)7iLpgWxy5dpJ-Kr)f6>ORq7+l$+EJBkjm(i&_ z!wG%pZ9*`V3q{wx=1duP2odx>yx3(7vkMwMOJPfA5wrKPW6j4TWtwW*~~ znKc_@Kkqz9E^sy6fbGxG0{xUqOYf!(3TY(<6vft*1SjJ#KFM}RX&#$u^l7oxOmGMW zO8cpk7!=gv9HPMuT7wCwMZ~vwpgePct4_z0VSA*?oMya%Aj;Mcm#$q>Vb$3wu6HW33 z0o&4$BC+MDV4>n*HFW+u&5;$eKhslmMnbQyGBy+1#LQkbI(w`H^0*g>Q+e(qNEXhl1_^s(7l zUfm|~vF-i+=`bDFKInBc0WjSw2xUaNt~b=TZ zYZGA?hv>B2JoQN|4#O;weI+#LvgV`W^9RRQG-lTk@C&ZJbX1jPpYH)d3NCjoDb^Z0 zsA$grY$q?WW$<#@JiTaEg@Q|7c(;hNTD}ftf=sqAAxzYN%C*v$;Ya@%wXUr@CGE)= zY~KNVVpy-XuBK2<@$Vr{(Ar_gpi#?z)ieDs5rQCf=4zzq<{9x-7z}HoowA5cJ4|9mZ0-3gh@BaGZf5 z>kOsEW21+pxawCPyPz3EOa5_2VCQ3pyFi@vZ%1>=S#R-vonG2Y$&xL)>?mAHWa^rE z_DyAX`@q=vZyF`Np2wv z4w4al;Xa?po}2deD#{=u7%HAa;QK)QOu9z=j&AM@XWcaqV7nV?zjIc(x$_{XRamEw zENj=Hxt)we@H7|dLcTNXDhfth-X9PBItoB)3nv%&;CH{| z+(h^~|8RV`%@00V_~xMIGzfyaeV|&JrFzE9vA)^V$&eq<2Gx1Zm-?RnL-K&(;ryK9 z3BEsu#M**&clq<*O#chkcHQ_Kq43-jH8q^`Tma53lxXj`_)4qppc>t2s3jR}bMOa_ zcxBF$M5lQdw}OizVRSO))$B;88{a7>uVeQiqt^I|KiL9sz*U)c$a<>U&%Umi*xyo? z@0*FFbLqTqnLaSuhi-ZKCYDDYF@K!6>EiOLj*RH)>9I!JcHXFcA#7(tTNN}mP#NA^ zQ4ck)P;#^`b?*a)Jnpj-eW>_9Ro(kID5AHwg->Vw9;uSq>9c;Ywo*m=2pMhAjqtGG zm)KVWUHhE`@le(~9pmWHTb(b`ZjZa~WA+yhx6)=hMo06nC2>8yWW(fB6bJT8seHTS zVO2S;>lTvFTlE3@)dw=cDkIMxUhnDQhbR!s4;2)RKB}vgdopBPpQuup)Y6)^J?D*3 zc%gV-Ua#;tlakviwbQrzkI_#2`AO(_m|}ZkQbe98>7_Uk(dkr^-f?c?_`@P#)V!yS z7?MT_fgTA_Um5LpbUsgP8OnR%{nwvsYHvHbf)4kc`3~^edtTpy{oJ(?GnoiyW7G-l zyC$65vY6Aw`7Q7(LA`%yr4^D@uF~}8)OzEMThfp|^?wbP+D!&cCzv3g+i-44zOQOm zK&>w;C5S5m$PslH5-ojz9MOps<5mPJA?mQ6;^got>q~wTMhpH3+mf_hgjF+JuT{@; z&fWI_hE3~ljQOqii|KXWa6fc;fg-|MO&jW+pa48UR_KdYs@IeO(<(mjO4>Gn-%>r#34_U2ylMPoP~)-=Wdpc%7$~1WDKX zcVkfkv>bo@lKRZ{J(*8ryD3z(ItR|`Sa%%^L&85*?|46M`t9CA@~Aaj$afV?fAfi< zI_tHgfh>Q2IJT#NqPU@u(DAPf+;RpEzWS<(QI3W|ED0G? zyVY?nJ4R2c{Hl)rc6>d4W1oE*l=Be2Yz5PJqy`2iQQm@ZBw!w_ky31Z|+6AMPJ6QJl< zNEA|h()Hp^?b22&+Xu01UVFUFUhP+Y^$(l4WLEDG59M}xAl!~Rzg?{-NBp`dwOI;t zYW9+`oSdi;>t}U)DMz^OHtke zyk{+=hBcjx6cIZJNb>urOEO)lf7sNL9(fbpQ$$CE;`1AE1`IOxDC9hYD`5!5FL#7M znrUTo78T2;Q@@_$3?v3h4yeTZdd6=Rsy~jkj5aSOX$_ThCip;L6{7NMY${xxiHYo6 zZAZOBuLIfWf(*M*Q_C8I1+s+Kd>=_**7-DL%p4cWYPiZPefVqwmFcVX%W}~X)Dk!p znJvickt)*<`fQOGc3otY?$RXztJz3U;AYfw|D52kLz`a4J0WNf{+&@b$*3^xQP#*S zI}s)6^rc5^MRY18y% zNGHSkn?fqCI8Q5%X((EPD#x<5bi!U@K#giumt*l#J*n=J3M^&acGdYWCHM+GNLI4` z8D|u6(`|DX6^xG;VjZh62#0gsQS#tlPIIL$6)-MY+j~w~U03|)tc|>du43MAo8Y?8 z%4e3aIx!(j1wBd=W{mh8>z&`G(I?X3#`bhJ-Q97gdql? zM)BlFff%aS%xeKfi7@>3p_MwsWcpe~#@B?qg6^9+*bQGvOk%UxcbasCdqZV;> z!2e}Q>}HA<62$5fZkaDG+Dn_D-LkM^g%R2DND!=)ln^ws|uva*CjbyFSE{QCsVpRjS;KWsbdOlA}hV1m?w0tJxNaT{9Kus$93? zW~`+_MCRZ6QKs#@;o02nT^eUpUHqEB^;Pm|i=e9TIWN5LT7$^RdO*p+s0JJIGkE-i z(NhD})8fw=>umZJ$GJe{c5~7KVz}!I2_ejCbh9&TY|3nF&7gWsM8=w5(%(h)H{R#GV}t?b-f$7%kvYd+*f`YKFXM)bahI5pTT{p6 zebJjyFsHr;ZuVq0pCD*=?1?Y~rJ^kwy@OM#iQT1KgYgY%2fT9XuSm~qT`c>P7RWegu&FC`h+bL_L;dj0%EyL+y%T*($)F*Zu z{z8>Kdv)t!@22YEPp?2%}PZ08>M{4q?l_c*r#RXRA zfSF$jn45w*3Xzu#0F5S&#ncoA`JR(VW#_)MmFJ4DrEA?h!L}3)Ys?+%AdJZQa5VZd zA4S!Ai88bgP;?KNe&$8&0aa|MC8TSU5jbF;w9RNAZH~x6Ykj~^w!`+8$1C`^Uk)|6YXF|6d@wnFw-BS3haaK*csEco*ot^VJDu=p^F z!g&zGr#7gTvnvlFtEraDumt!GTRhF?0BnVVLf2Sgdx4r z2shnik!_2%V75c)zNsCV4|WM8hB&4b7jXk~tmQM^Hs(D$YA89gfM;McAKIg)SY)X` z9pj%NhymU>;WTA}^z?4uVN%4z#8U$m^WHZV>6i;R&ntnfgY_NmChU=#KGi+%JC+Vd z2syNq9|`oa_v#3=9i^E=X%icw&NipouoLt~nC>Ra)xzD#F`k69oC@?1cIQ|xAhYJC z*=aJf`-%g&svX zdRIao&^U9V$J&z~9ZM%+=qpQ9Tl)dF z0pf$s!l3Q))EsJgsrqPV#;Q5F2n1$7!Ml zR;cHFV0qMz_W{Ji+{LsyXamItfwnUtsH)^z#ox129|XwnAbeM3rl`<+P7` z6?(T*5bv;gY!~gyTD;>mT<&uAI3kuSOT19o6HPY;kxjo{vUrC}Ek)WAEitzpc}iv3Q1Um965aDN>3 z2y6xdSHXi7H5nJ{07BR;JummPwSlDs*K=yH(zcsA78E49wG$iyP^zpDBzRnw+O=4V zdaV*@zEa!laHIawiTF3z(eaKQ#0pOAF`}f)VQEZ}IFid1>3QL`Yrh zQ6^}O3*uffrGhbgrF9@LK0CI9Bs?RKJ4#+4&c$BKtSI1eUcvzXvby|sD~VM>x5>)% z`m(N()fKaeGTDwWvXbCeD^R{^!Lr=x#eE!9ez+Y0_me@=N8d>K`EWu;-8`lmb;DFK z9%2}lu%cfS@zafGB&%fEJo1I@)VNHGAe^sD(>OPexQx!d)IkwKcgvx_xV>z|Dm$K? zjKl6$=qm{0q9zY(VCr?AQVqm^=ZH5X&kPE{M0z@aJ510c3m}<6F#L6K6r1%~>@rdT zb3$qw+5>7^r_4iBd3oNaQ1lJlZ!4n2gK663uUE#%ad%$g)jCGG`c;FsEmqc^qmZVx zEGX;S&ON!oJ7rkc4}gC0o6BlCt7j&mGtZ|{uDku`);1}KQv|5;lJ8*c7RUl-DzZuu zi1A0EH`h46IIALJaThFj&3{n6GeYuET;R;T4UU~(l{q1;8qoyD$J})HL}k5e3Z2eH zQKbOnWiYPawze(|M&_sTM@46>+T^U=NYRY-I82sO@i&Kh**pRr8R+9P+-`+Z|HUnM zP9egMQaZn>+b`fCGV@EH+QPnaMPNXQe6}y$xCm;q(a6n(WyVF zgvBweO=aL?kfHM@0SAh|$O{bkLr#VS4ygA}*0HvV^Yt$_`MGaKnk086)S>}u^Nemm z8nxP@6HZ}aiCvLng;gJaIwl`-Z zd98Vk>{&mD-49HlgTGjkVFiUn4}IB!8actnuyd5i==BC(9d2$$f+rF!2PDDZR2>;M zYMs@fzsNyt|1)I5caWiDl;k>6YNT^_ZK24SY*XCPs3=z7cVta3F=|pE2E!usYRvd) zLJXUGel^PPfLi4{vtvR!4>hg_eU6(z*=gbUWaM|cP-S-UN!{OrWVH*f5VV{KA}@CO z9%H3`6+@>6+s1l?2z28*fCOGZ%qjSIf5HmTq`+ot7!JeOUp07ecnSS>kyEG>;x(z@ zHI}4%T`o=+^zA`LyR8cWwVKBm?(H8Z)kp`3s_w?c-+ntC_)W)Q+w++|w4c&Y{?3TZ zUnhn7-jzT9V;<^*DB~rw`=>f{W=5~)Hl^M}sFDlSLw9WJ=EYQsLHpj^wi3aId8(IT zU|FgVon{}QFfpJ&8J+FnWQMxyk&=bu+tC39l(?ENnJJtOe)8|zfeKUDu$`FfBRZW( zxNC1{B-k3a*ZPwTIs-466(|OITv~^4rx3$$Hwy%>JY#g8K~ck+>5B28X{SK}Rzj~G zI%b&I$n9(IvYz&O#&i0whEH36#O29DJLDv$#ZNwVlwww-5=k6ytmy*=8^VUK#}~Ws zHc1Z-Y5hn<;pld&TR`;7le*Q6*GHSB??Tg}vN~4kTfx#>o`C?>Gjl0UCX;F(HYGI!hW{kx`{O(`ELyOPi{tFpf^7jDPfvG6-$;G|M{sJ=ep zMfL*K;st9d5Gyd2zmkW7;^LIl%|ebHC(=uv6({m07Toz`ST#&l_9wfF#tj*9*~nfA z!2=8t#|QAG9>fQI1%f%$((h-)G#J8eT68GAkS+V0cuf=Jt>3PkDWmHtg8Zfo@Y&GY zbhi;5Zon&K$o>*Bi;BGC^B*=Y;p5oYh6@)v_DT6m@>JZZ?o=4s7;z&=)v>`Ox>eEE zc1RjvY>^`(E6J(-34w?{-?RH%=#pST5YLup_!rm1Xcr44ol3z71vBUPN7Y&t<(pUR zv}%EYj#zqDk+sZVEurD!WwgLcr)29FheP~AiceH4uU-Q87$tK}BpaSHLZ(kj((&1#Ew{c7LnlqPjuC%CK3hWRsIa9JH47*nwVe9V=W zP*A-kM-Ozd6kLcYZi=Vpn<(Hw(z^@hi)B)qmFSKN3=`+qq$HC`f4P3}b6n5kUt^r1xctH2-9F z0nJmyxgYF(k$O=_i$uZs_AI{xf>vhN>MH!Hr-PbuO&|vf+&_Yji&b;>$3?JGeyTFp zw*4y@snf#@=fd6Yk-%v7fvRwd1|R+)sb>W;6)gCdfl%A0M91LmW4coYUE#6aDftEy z{!!nA;MK+n&Wy*FyaUd5z8hXZSFvw(}6`Ii|NONgRwV0QYC zu4itbf(k{`7TItlsxuOpFgLR&wqmhD*7$Q_v=Pr=$Xr;7hHAeeWJO?+GiaH*_g6AI zFgt7PR<<}*(_YRno4tas;2{Z_m?rk4KqhaBAK6$hIl*lxAL6iw6am=G5RG{PB-;+0 zoJEFf!K1AiNA#j{{mt$Cuc11Bndp*19lk{U${-I)!;}*XM+__3730Lf*}fBcKoYn= zRH?#Nm?DAEW+~frBpyBHDd-5SPn_au`++WIM_Od?!7sqjcK zN(vdEyp{rXS)t{mjBD*f1ck&ePszH)!f&7p3?_ApWUrKv839k`S&o6&hp~d5a`b>m zV4eJT5>U!q4=3>mHiSPU7i?`hZ;{!b;jN4y)QHO&$vHTli*xMpNpqe{P1n|9-_oDl zPMY**+E5Iyn*UT!YoH}^`iTxs^(rvs&BoB721SnqeK@4Ez9m|ArUt!6-_QyNyJ1{O zi|{@u1kTCs0GVrWFela^0NjC&rcz2W8({vqU^=!=YKd>jZ0RJv<%(+gHONcBr6*5V za_26Nc;0_y^K1B^I%zlJ#ug0;9dYjk&k1DP zaA=;K3Kuee3@H-E4b6c5g~d`VHgyF5TxO-Uu%kn-9^?$6Nqk#ps~K*lK^0BD$5BoQg{W0CK59f3;CBw-I?DrM?V&dsA!9My4zt0p-nS46<4 zOzM?|JdX9Jt9|n|Ag|X~aZVR$INZJCLOWbb=h!n7y9I!=mA-pL^w3dsc@QlAnp~ja z3h~w>8}72Mq-k!E3|mkG_BVQLS-To?X@-rYr>NuL5>SNXL#ThkVB}dcWnLn)ehHWU z)BzFjt!~(4w|cQSxO~Lbyyv}A{SU@R|U+f+}}nAZ^t!l?(cW*-2~Dx1*%N7XyV zN7g*=!?A7Kwz;vBjcsdV+qUgwV{B}j8{4)gdb0QT|9kO#`rXVq)zzo3!t|-D#ulrw z;t^f8Iq0#uEQP8AH7fkQ#TADA8Ve}7fZe<^Ei=AVnHUy*Xr;+V|v~Kx0Vd3t_vhWattGzBO${nDdVT-LE-ezlpv}BYUNfd zBA!!v!6-=Mn2l98%DlM%H?)SxLdjw-_B@Cr9xPNJa@dl73>G{@2FbmAm42XsI>v+o zqyj8OXrf-Qf_@@In9&2(yE?{LexZP=Ov72;O!aJnGfS%8w1kc^&`WjT@?M}DCG*mN zgcaXngX_VCX>{C?S-R8>S^C%kEOG^970(ys^GLfcu|y#4w~a=)tXxgold9wX^p;X3 z`$XZ-%X&U2AXI|P$%}wggZI#wFbZ7s&RKB{6ubGxsw&L$clrtxbYzl#?QlaFxq()* zxK40o$jJ5@D}W=)6cZNBep7@jO^u2XN`5|Azx|!?0FP)L-jt3>-!z3p-ETK7R;ZQO z9EItN{+mezqZTnaod+`;BbT4j1u+ehLTX^_oMQGAfw6F0X3>~g(T1w?>w3STQY4z{ z5+*jJ(J)uKoyt(*;1+_@D7a%W%!s(nw1!Vfte!H2=&R8Z1DQ2va8@l7k?e5Xi(#N> zrE{(jG;a>*iY6PmVaN5%T+;_vjwqc7uxrtIR*u$r`p>}#={V$dM{oCuUJPMx87bC9 zDNza4g+7ThRY)%w`ip)MUWbcl96I}nHDK-YHcLB$n0Y_7e0cVIW9}P)M#KfT@J;f|9kw_W4DJn1V`9>j zXxVaP{n+u^PFQwX)-}dC6?`Q8lE3zT(>5)IhdCyFF$rl?jW|xnP-CBiMC}o{=JR~} za%a``JhkuQnv+W^uKYO_F+ET$PN&#nDMooJ*484~RAR)>CZ46w7?pa2XTcgSO`d6F zkc6hPM>Fg%;qW7hj+*2L^j{kFNK*zFj)IzyFuSU&7;b5!I;tlu^Kj_SIV01mheB2J z1oM6y670f2bz7ppTSn!X+{7R&biHdb)%zXmbW#`l3?MGBFYCy~2>>Kf1i)3s8SI|8+{)#xIhGVt1zZLAaeGgrYHkzhl6kl| zaVz|g6`gMTiN-ph!n+Fxk*j3O2;zC0NR!0Gpc1UdOE(qiKuY~1Q;1NrP22Yu>;8CZ zSoApw{~3`CguEhwue%9AGG6}zjeVp;wqDiyMf%zo9}!R6tjqOlP{tGXQ^SDvwOCpD zV6Jvy$)s>8)BoWu`sN+uC&&c6yr(6)4w6Sq*{-Tlh9V^bCLD}-Faz}+Twg|1F!e|Q zPUEDlTf zIcxDiKXuLO@9f`fL5m@r%$AQ5#$}N~W~{Q^8{T?FtNBtiA%hB!=uk7>h!meQKF-c7 zYnL8g5~r2`r6=;!kP$r0Y$#-a@N>tD&E<>@@V87*g3;@h_+bwev2e!kl$MQ+OVs@H zf-=UcO1C4GNtnRrpz_4u=ebbub$@w|TToCN|Naef`%BOBxnql9q35O_7VIrbKbtfi z*S<4g>#JL^NRa0S$aAJ+Ti9*$57nA^J?vO0NhER!*Z>m*9KaK)A9flX|GpLqb zb(yW2#UX^#3;QS9umvHpk~!FOcJh8=0hHW;Q9L$o`U>;zL&6h_JK`Up)e2KH?1es> zo!>V->1hrWp!r&k@4yiT@UiEXN7IK z2`+iB#>6q8bwed(ZS(s14Gnl1fwj1l6ZYB-`wrEWC2l^)KT;E=aQ6`cU3&~U-lA3? z&{5HDOgZB=p#IjYW@a|)bT{=s`a(P!2-bPx4)Mg|$Ep;t&Eun)ZOXa{ zR<+9~P}J|X3Z+^~OdTI?EIKjB;*cMa5B60;2xg@RP-^)y`!A2cT3?ojREETLjWUe~ ziX`I23{~09r?ZP;uw^s(xW_<3K#%GM5X#cXR|HJScN~*D9Rvr#L4L z7MUCa&uh9;3A}fJJ@>P=WC=eikxtB`}xLf-ctE^eRB!19Gh$wAR~Jn%2ze%`NBXF$ z&FH|pE{2ov!)<_?!K)Fm$IG&GoavO+b^>2vMeBpr_2wrnQ-vEsdc3YQe|)_wdV^F|ujv>XL*S%VtI{A&UnX!We&Bdnx9`bWqvRDb zZSv3^6!|O_*$;p*+(J)sYSX1%UL1|gsgEG)gmX>dk)eXO%7CG2_>F9*FY zUGZ9sfjk+e-dLtl5|VDlvl|25j<3%r7IB0xh+2{(%-<_qfMKT%yx)$vFe%~*W>202 zB$SQFJ|HNT8HyW_3_~e|(xd&XJ9jw=OHkCBGF&!{a4-5?atMr^ZTdcHvf4L1#$@tUe)PjuS=2pGwVP0rHoi3$ZCR=jZvYp#~TYU{B z8ro;yO1shaDnf zg6`b1OGOnw6`p|NnXcfWnL$QOYSNI!pgqEFY|9+{P1r&R(KSjVaQst{*%P zzAQfHH%`+hx@5!nU@E0|gDzgIRS>segi<5qxpD`j`F%usO_=0d}8z zC{dRZB)Us)_@!Hg1F)Y3x;fnXYV(RweIEwkSpE7y{!zV82)}l(E#fwxi|xI2DP^LK z({x>Tvxt>XJH9J1aYm9zCbIv;_rUM;@QssJt@%=ar;yIoJ1_dr>F6 z+aJJ}&2Lx8+N4Z;>g_m#WByfWgTx%kf8)|T#WSr7XjfReZJtwuS_hwClsi~ehNPXPR&enaTGAqoe9EiJl@FX_Ae!CIT=lH zq3Kg=`MH(ASyn)CA+phm*mIQk6D_P=dAM~il{Nh_#ApH%eEGKZEZqLt zetuGw_aWQO6wTWy_%Vjf5{}*J_}1e0g$P*o`!H`SipnCX^|`Ef9;c@4`#wZ^zudkJ zZWpI$v-jP%W{bH-^V_TaYCab=e=5+KT!T^#B5uVo^CaRl!F)*I>oU}1zkVQSwr8#> z*7y6pa`;zC4M`-LUHoVeo41V=KVLo-_xC|iiVbMX%uY@iRX^O}x-G=lP0BiJVy9vZqwUW> zsztpq zN&b#-;H*cItpvx0O!17L^zSq#G{}1RE`M!giF$#9Y2AIF2ScIa-}_^6a(Lg<`S)|u z((JWLGhb&M@2J{3$xTBuMUw0`(pcn?RkC4o{^-@z=neb}*Be`}Y4@vY{g=CYcxY%i zL-);(@4ORuL4?hHP-)~wchdsh*bYaeYso%DRBAusvN^7ENhZtBoZ&~ct_snw6TXBcGrs9>cZrSogpe+wZXReC9 zg}fA1r5T+!;NDHAU~~>4c{seO^`;&s(8N7QeVS3r$*a>Fe?_G*Ru)MPh;%uSQr+?K z>IK3Ft6L%*kqAaQ_Xf#Uy$tV4^HbfJnem?>zY_Nu{}KbS@~x*3%lJ6kuFSUVf-#O0 zoaKqz8Lqwk=1mJBUC(ik!9EeC#7Slp`c(mE`w~tXSD@>MHR%BUaL7nh8;)RgiN#SF9-y8VFT_KoA@sM zU{ci&q|Hz*+{%dlmmF(-qaau*rg{G(l#9PxJIEFkqXd2THT!iy_fIop&R|vg%v^JvvFl7)_f{%( zcZ+C|=)$C>2tbW(QRw(nI$utC<|eAW$IfA>;#4Q~1tDK)cOHQUSVX9EYGOgt~Oylkl=OB#i`+et*4q zUgFx(6sTloJe6evFDT*r*$Uzi=6 zQ+P6hNYbKRP;-j0?jBBQV%!e$m-OsuQzq^E!d-qTl?TUsk|>E(OcE{OHZ1%KK=&b= zOw-y$Qbm8+aN+ycW_UZ&g;<$Vfj z%#v=}Awb(Xy%7m#k0OXv>g+QpeB@ZoE5hSHW(>zW=S#=_wuS7UbEicsKbhPZO*642%%}UN#3zD?j2+@r6ba$3BGU?DC zKj`V&xPVv8dXb z8Hb_(-o|+jE_c4EN-ZDg)W0oU@ZT0eUh6s$eQJGiUjnXu|CY``9fY zH8a}7nosE(MqCR6p1}ubMBV>JKrdj|2;hkvCXiwJCJB_wmfAQ;gl_EP=I$z(p%U3P z0B?HTe-@>n^037Agbq|e*pN#2YopI8b0`un5VNot{%spd@nQ8YU;ngqJNX;B{o1pG zUB+^Zv%XeO6oSZ`QC3vb8};n3j&7gTnlrCR9>$_EkOrOEW=0G*>_eHR7xr>f@W&r? zAu`lsPLvu6x=2U)Z&jX%Rj=%9Oufz-*F@`I1VF^_PY?}wkdV3auX(*+D;YN*eBNnO zICScF_R6E#TfC1+;?;YqASl9ljnG(gZ2`1mh)+_U*s*q zOL7`Z8g?+N4wwoutd3)ckuTZ+PcRn6``ZLzlJm(aEGu7qL%;;iV3CL)-#gg*8>B`{ zLy4+%y~Dd4-M#L~u&gPR`f$r_w|meZls78~yT=z(Sv^7&e;cRYsW)BE>Dhb$aGr;i zdU8px_3Gx?zBpZ%w%0^_bifLZzT1!jlC-IeN!w68=bP6F-qp#PcNBC2NW=`H*|;(T zrXcoa&PU5wWzNNxBFXK;LbJm<>3umDM_Q_LM`NCitXpr+ytxs${1=muH!B<#IC&YN z(J63=?o}Mxy9-$_buDBVG$kcAdsF^iFYsqrB8#ID>=-Mn4?p_e#OiY$W&I{e6~Xs(!eWO1nMBr^%SB-SLHQItj6nL@{g~I(vE#bi%ao+^&aJ1& zt@~Wp`5-}Je$#C+Pd+-#zwo=EK;%-5Cg}rJ-V(z;H00&{1VhPX^LA|P*J$3tQKR{N z@dMDuE$(Nq-xPDe)(q;xce8;pbf}QSpH;gldm@PZqSxNfdGj?LmkgCEDklxwpW*~u zfbM6%@TbGDtX$7KDVEa$iWmCZoOiq)$`=n`M1fy~yAjM;w#^xX%V#hdTfh5t;3Xjj zLY+V)C`1$$!AeM-q9M^U6Q}l=iUby7HTGg^hcNW-%&1<*d^~tV%peRcfYDXdGFz7$ zbxc5%ZTyE5)*TFnSh^rA1Z|_ZrZ*O_5^8SlZiTk0r5KP^Ub%#cyu|RrziSGxj3poD zaRM`2!Z|9-O7#(2n%iN^>ia<5;PvCVJvOL+oM8(X-_;BM5v*;ekWCkQyJ{gEbGp`W z|9-NwzHfv?cOOsdf;g8=_tST*b+k3D+5b4>dd&PMBv$!h9!8o^2P|6sJp)}wYt|>X zBZT{^i<^9g8*;q2qTE61O4_&AzRVdMI6CE7YKx_;oQIG;dLli$WyIHQ$GHt8>~)-r z&~a`m7y@6fjQL~lO=-H{`P_!zmk-L`RmV3s!|PHc$^B25`BgQ(rp$y#;il`l#~tpT zSkzT=ra?;NMm@;WCpiUJN!+c%D|<5{|MfoI@69&KZyYmiM^EbiM2*s>~i0*O5L9amw84C z9$>8Y>Jb6$i9-0=0k-9(eiOCn}{rv$J;vfP}s^J)1Odq&grvoCwBf`URP)IIh9o8T`n0F0z`iRf0 zujxVZG#$F0j3LCA+c&ip044=I6op(i8DkaT$c{B_={8cqryiJ7Aqq%7GL%mgPyRK3 z%Y56%!_+;QuYAW^|BYr9RAlOJhmvRVa7-Fu$t=>bHT)|aLW%jwuDxRwzNX0i@yxMm zxxh5R%)Rzt55azY`^g828sZ;7r`8LUfNT*%SsX z?mWnaTAoqt>ySu?c48$`VM!*YRy@*;{GrmpZ9go{0t@Q7|3#{gn#F3)FxeUdgLnow zuPvi*IZzg2xcj!yzUAo}%&ha;9(hhGr{^sv#;%tk$hprq{NCjajsocYo53XD48A;_ z;j%oNs2*PC0K!uNzfbSABuZGmWrVTHTB@paGN3@x9Nnz#jn zx{=j?Gl3LWxanQFY!i^wT6Ii%S42MAjrC_RpA`z7reE81qWUWcbJ6H3TM7&X7CSR< z()xZmd`{W>My(LIzU(^h#rethydSomvL)o~uDX`pKekGFONU4FS+yH+NzvbB92e1fbO=XIC-H7lw{O*L`2J1_TA5q9Ani)?rNMRNVR^Gbyedc{Q zRq%`CI4&#F$QoXTQQ*5B@z&zeR10JD80#xs%OJ!9#Mt}l+8Nm}d&wlE)by>x#`%BU z#wp~_H2Cpt9snNM-88(--tvZ17}4zyR*JVtVF5zeP*b!_ z&SLq7`ArkZW0x!bYTeW*1#|E-m=+}+_s%*|NyP4++v?viQI?!XvkB>(c_OM5V3qKc zYM80YCveeW6sHMdwU`azBJcvd77lLFy(fKAPzb%2JR3_K(Ivs6>(@!eN& zdz34nhsNpsmN0^4qr6x26nD?0I|!u>e%z81Hu4O^#u-wOt6HLRaSFB)a3Tdgm~h)6 z5Y$9IkFFx>Rz=Fn$W9R&CyJU?)c#r_6pO)F|lt(cP!kNlP9#D^k zRv%5TgH~1Gd1l;}jY>M6g^x%Idn&!+X<+2LL)!_jtyzAd%_Enrm3JF0SOf2)7PhBt6b~1=b~cN@BDS4SCv|o+2c8FOS#YZi4#Fm`C3b-yzu=G0 z3X3CUZ_`Pv&H)BCiA;+wfa21|Qnq>ucyhfzf601*h_`YH9gP$Z(kKi`Mw-fEJ`Ei` z?>z%0B3`38w~vj(5q??|tAk0z8qwCf)^*OJN%PD@vkzKMcgU%EZ2k0i_Y>yRvF-fc zGja-iXhE_PZB@l!QE4%{u#lboDOdXKmW*fvTF!wAo{dVRq~`_ zy7Fk|Oi_o%kx+(Oe}G~Ppj3~SfK`;YCKMR;=#s%g<=S3+64L-i!>#pUg*;h>T%3KQ z70}m!(z1L1OjOrYHKR;bGQN&xuGLivCr_JRzM(z+r|8$1^-J#CRl(cKn}LOG8C|N- z6&8eif0MbYaiY;e){3XUFecOE+})KetYihvE68VZU1~SiJ+QS`hZr0eBIn}5oHpKr z06i_Qktd*HoOrkq%=;JN;DespEP3&P&u0u1c6tU>xF|Bbjal*o#dk$0iK(77(x@yU zywK<$eDmE=ICUoeewfOb2)RX|!&H3-t9To2Sare)P(*$r{ip%;p3q|(_As@3!nKM& zR=}`^(&LHrKpFcC8L6e@d9PM1#=)HUeE5kmEEP*4t(UV~JLCCq?Wj)MYN+cWNY(HQ zx29x;b zE;Ji0rIXC{ z;XYwY*^ojT8H?*zM*(ZyT^7cwg;oxSm%|u_uI~Qqb3x9)eMk)&Gq7q}#;&f3VJ%)e zaiM>kkJrUij}nZ2X3O2W1J|?Or58(7387Vc;ms3{l5t^K4Y-lBgJVC-VUimsTk^7J z*Q{tU(93m=)M>wU@*T|GdSUfDVzH@=+D3%~&6qPDo3-iedKSdc?=qmz9a%DA_rXsy zw>DRbtk!nl#wFCXi*SU~+s^IMJX~b%l!iC{`QR7?;zlEjeaw%%Glk-QCMd;b#&4Qu zlIMG+()%PLxR*J3-Z8heb<*55{a`CFRfAhIwKXwvH4rOyeTW#-%=|K!by0yEWlQOv z{0dLY+lGp3-r8)inbdZes;w2hh!J(Y5e2_gwzyZwc%`1N53CN%>zaL{DSg$tAN!b~ zS{CzLv6~jR#}fpkTJJ~7k_&a5)=w+Y?R=|`LfyG*(9*{pUE6A23>hO)sV|3e( zV-+lJb-b^o@=?4|M~ri~+snJOz>6t4ed`o`sZ{Xwuhd>Zv_Tdt&)^?0545vY{`kDE zI_$`}X@hr{?3ML<>mO@I^0~YwvIs2(OUG+=I^EEnh(%7KoPIt&Js=-2$>?>)70LEC ze6cRPTO*lHu-#%hv3O3n7)~dq4VASQ1`u(nCZ}dq-Wj@Maf|wd+y7M53W)j8_~Dzn zuW^LhSYdNau(`4kDxkmmhvx*z`QyG^v`Hc|Ajd|S{wf=F{&L zLRehJf0R+?Lm_b8oUnATHNq+w=sS3<2VRE>=vsX0UE6vM)4<1_QO@f4u2~qLPG=d^ zkl|AE#=bs1@Uc_-nWQP0`f@a|?k<@7lrFGY+Y3+!^2*t66!P-@;1_gC{X;rZ80SN$ z2K>18a5*%Kpn;@pL>LB)Tw0`>8Jcj!D+O?!G3w#3qts&;R@v3x`LqBU|n@ZPfx zKtK70R6to1i1!oq!t0B}JKNnZa3;TT`q4B_sZTCv0>ZWz>Y6viCrN?PS}D=TCB_#A zMsI7w#B9XtrtSAXFPIC+_p~{H?|dx%+r$qTK2r2v5*XIG@x`J$t#)trP1hMKp6kp* z=Q()VlNmksoTm*#qs~lCijX#VSk8ynaRzO%K#uf422p(#0y`nQIiXPtoiT3z{`PS3XN zv!$O>$7Syl4IMt02jlB%OWqHr{{gwSS6nH8)_$3LT+Ja-X#-oE{qd!fysosu5?V0V2=l>p+FE~de%n6?9vkpCZPT#vx zjZ1@al9E>QZ^2c~SHOSpxA8`wzv3gcB zF&=ASlB3(Tt`W92Q~6JH?!@<XgC57bs_Y7N84d#W>8GTLxe9l0NveA zwRgtZ@W2u0Jk2v+{g*E6pVPm@87Hato9k}(2d+DLjKz(Neu=}kGu*Koe$r-wqrgnU zi#X026^mMO&&_^4VV?(Ibe1~W*=z;(hmut=>yG6^R}=s3Fk%Zx`u<&tu21Z#WiYP| zzuvFqjrvH2cHg$yua~Yci^ohQE$1FzX6&RD$}P4igiUMIOcsZDh7MEmj|oJ=M8YTe zEI!FR_kB8^V3(}AD+;}OpS$3&)1P|CuJb-$wMVl|f-m2NlWVwoEHPW2qt0s%SMFNx zJ2*TaiIk^N=6oayrXC}P3#a&DQ~8xIxXX~81}JjtCgBV{rr`L`LvN?IrldyOe*dAw zTmgJflNOPh!H>frH)(vM-GsdwAG-upk1OIA&s%AlT#@EN*h!JTpMUr3{Rr5--*#h& ztaxkcbJ8{+HR^QBr=xYob;6&f z?R!dgwOo*^p8udkXa^oyspU9@V6U;4Vdq2HC6R|$fatp`064+rC`!BF(bOydi~n3x z(DO3$W-$k9eX8jDiMDnu?-i`T8*yaM9s9I5(zx@7TS3$!j$T`$r_%~M$8`>sE!VyQ zWLb(*eD^Z^qZH=l#5DHvsv#=QUf{_IvI- zfhf!Ep4#-rt34tp(LGYgH%82)Vbpnh>tjrtmy062D!=#59jO#_;r7^Z8P>weO>e4`qAW6-UO_ z``xKCP3`D(`-PO&=<@0GA^MtFUao?+Esv}lfBy32FZ@gRuTD{v{y$vVj(R=6(B(`4 zIbRNla!0tZT<8KQng(48A{d6E{llv&?osDlHKNhtQVK?GCJc7hW^*a&0_k z2CQEr#tk2scKV*R|MRMEG>QbPu1Apx0;b!I9bxKchc^=ys)jU0I zz8;H?Jim^|9@-FXgpc*wWF7l{!SF4-6Hny{=6#=Nm2pz#Mt0OQqoB5mFI80UU2j!uDSzo{mmMFw z%%|J}wzFty=a1je-4RrKtLrZ)Lf!-W{cfiXb45~45&!(Z2_zfSdqgSyf=FOcj#gQ( zJ|+M2Xxys6ZE(jmL#syezQV*U=1Q?Q5;Op(Ehnq(6U2X>SrdF-)?A-om@!FLXVtWY zBG+{P8nNs@nNH|+ZSX!itCr}_a^I>S>(~N7|7C{(<|5$zrxiKdZ16O4L9mzELU#9p0V*`iYOHF6jQ8=US zdL=V-c(Fo%tFK?_=hnafYZD>P>a68|(;8HvyJzQVbr(!w*nJZ;j#p1F(mL1`8ElVl zMqFkuoR{nro3tO;|CbyHHG+IXh$*i#^nuWS1V9hHie+u&`)dTh^LISjx{r^3z0bTY zFL&B6|1Z(8Q3Pl5dL65F#^~`Zj0BTYvHS;v|I(?LP7uBTLxlTnV!fVqeB4*Ax6^;V z_B%f+_xBk=a5iqx{zBDkJ^w!~_bY^qO^?Ap7M5eoMIKpC|LtSFO1^;Ccal)waIgLX zsO+pqYmdA9_rKyO&aEze_NBfk!eK7LCJU?80vw`ELqbIq)0Wh*mBq)HFfs z>i12Jtkc3%an^ialK;0%ZSW1eWq*SZ$~gB1r!@$p=)h_Y{L~)ox0(U-+3z%?@Nwe# zyLN{A7flSVJnG5TOqL|$ikbHyU(R5*=D@?4+l()d$b-)_EfOu0(>PMsk(lzK%fYAe zNyxfu-cqn;reZtvt_Swi~BPfu2wJf z?*(4=iTLa6emUNJy6t_q_B~lw8s6IwZ`+Acj`Q2orwQM#*MNw}p7eQone}WEm1n(o%^6p9-gG5Z^R$v1x7m{+ z^CsX|D63WW@u8E+?sM|h=!Spub5Yu_ILJAEiy`u3wS($Kk#5DSR^ujO1&Oyj-v~Gl zrhG-9W2JYiPN|BD25|9!Fz@wtl()H>Gxgm+x8qq)^2**mam<7zBWW^&tONCTf9UwG z*V4gT?mmP}ryAKGmna&uEkSonRG!cj{vSwPk}>^XU)JNYfX8dghxNfzl?uzC%qCCE zhLJ>@RsSaf0axhF`#W#t$BD1zg3UG6veGIriLcIV3RxXfUulS`?H+4VPuBw@!0vU5 z)Kt?(Aq&5Y9P8O%>jvtM{Z8?R%{GqUKGMkutgCuo zd))Ci-~F5{HVAJ${&-$OSoIjgx1X21Ix}_XcHF%Hj-Jo{SgGVMi!&BLO1vi#q3Rg; zO?*w2Ja_9_9WAvAlQ*e0(mYHYs6t#9e6cZie(_tw>psoW0nDY|KaZby|K=xbGZs}i zEe%d{2c6ii)MbiqtR+&+=oz2*J?*ntDRz*2R2FAip3g&?&)unJeE-Z@STC8zU8)e4 zJ6ksKP|b&7xB8p^UCK%6%#}8&{$Av#HT9b*ZF`w5(tdv-+ zRLM^h&=$SSq+~QE#-rmU->D9S1l?Fz<>`ziWI)5;Vu5mZzjO!MEwgIGtSaK2vA5aL zXr9(=imkz7p>6PXmFhPD`00V{%H*@WnGB%(!X?OpyyckAV|@vk*v*B-#Vr97TWME9 zZ-3Vy=m9of4|zNMQo|B^xV)x4Z9YE2Axu;hKi=XE8vbm^Mp&iallbYW60zBDNDWJB zd~bzrAv5gbdO+d{C=&Y{Loa%ZOZk#M^3p4K7_O~7`_iK}|7>F;nLa3e)lPY&xK5Gc zk&)Y~<+=9}!gdk^-b7LJ1xJs`uMr8a+4jNaK)(4p&)0Ym))1;=0RN-H95t|%(;3$p zPXL`ptx7V5W++AG2dEMw6?7e22ELYhN%t{FA!O*6$ih+eA!J?PHiwhtj`dgi!;r*M z39&tWe#=`k%Y%5l``DI(_l??v2b zRnvVDhbq&MKi-QFR%`h`1ApM%J%Ioo!VVwEX$Oa~uRu!+A&p2p%D(_`U@<2_+5ryG=W2Gd?F3)U><=C}Gr1sga&%P20fvz3= z{ic2c|8@xFN(C(TkRdQ4NTsLm=BpE|KLsdxUT>4~?#_YWOCaea?z9qmi2!7nW%zue zlO6Q%0B2oexAhmi;>Vl82Fuw~udLSerJ+YOeW41lH?aYu{m|KgDG3_g(J?;bWRdZk z>|vfZvdeBtCRjz@sSE7sNwrBxl>e9YO1kjqFR!^Bo-Z*`^T?Y;RBxlQdO!zN!uaZM z?n1413eOgO+D2r+iWlspC7l5Z!@emU4=6d*p>j-G!=gu{ldcLeGyw!K2nSb-IjzHS zb3#&8j`Z)JarspeeECBwW;&f-fIu&SaSh2wB$2^hlAAs)zL=d$rDA>+e^+1TFfg%x%F@PCgi0v7eq@fv&F1U?# zj3T`F{P3;+2BQajI|bOxygM^rSb~KY=`kjvijo49K`x!RkG3(ii?7mnJ$!J+x&Hp58YZL#Ii~7_Fou$X&!wQJmhLcJ&5eZfF z)_OG+S=sl5cK;s9sbD&uu(Xm+Ld2;#Opqoma^zS7PbfFvgK8fo+=`!y2U;o>A7*bT z@W_}E_wU&$dcQ}0wiJ=n2v;SMDoFa&)gEaz`5epJK7U)ax_f_B54HE|p*5+EUYYe}ooh=ho zjE}pw@OkNh{KG1d>&rOXRIYAxbNz+mf_rQKW$6Mg#ReEd-KEyh$KF5)+s$1YIewb` z*L6KTwA=U^v1&%l`Tf6}aa+I+cwJ9Sd+{SzVS&<2@>VMlwqfgYeRFWyrY|?9T`Zqn z7bn3U~ zwwD91o6V6LKE}S9)6d;%#Ur&=;$HUJIgHJE(tcAKa%FdyCoT8rkx-%V=euM(iHIASu^)Z9tA(OmMzxuLi}lC>8Q%x7 zeg8nVpX#sohk`)yz?B0zX=x=dEsHI+;muAzD78w%-cA$}NoI9(O$=>EL+|ctiGelTQ}SO;Z(Ptr}iOf(dVSr139b&*@=V?%dud1X=fo>oVosc?Wy*`gB=7|D3^!Gnt}Pt>wK7 z7}I^;H&tc{XU!=q9Q^tA#Z){o+~H@`4IrJIA{S3pL*y0WZe&~A!a(j^{UGaa1Ulxn z>y+Wy2D`K4_GxJK8aoY^%#FEP?i9{o3(i+=Tj&}`wd``{{|9V&HbhGb0C^atZvnw*$R~B%g5k%aAEb_1sp+d z&v@-ekvsSKW3$E4^HMD&A(Y2ZB=*xP9X7KP<_abFj(J51{BxBy?uZG5dlqh- zjIjI;qqB>YZ23G{>P(b>1aG$RB52be3 z(M{Q&{XF^Sc>`i(LB;?RRR(49Iqimb2V>t&-`^V9n*)|=V(5qupH_4`K#rW8T&3bC`MEy{aF=@q`aAi4e#qf(cHEZ-l?+SGhL9kn zSIyO;Yr2O>2ANk6=kLfs8PIA<30Zgk%0$$?p#SNaj65QEi}Ex~c|3c-Z4I^k`ad&T zNbnc%-#khA|CoB`=(@V^dpJ&RY}>XPqp@wojj z@>k9{=Oi0v?>XmMd#){#1uYDr|2nq=owdB-R0y4naLBPE`H$e!za8ivomChov;xQI z2!7@lD&6hBg*pf*;`2R-(ZUR9?l)1}CBQdR{_h$$dXjidhQ&$kWetC;zQE$YW(i1x z#VCqRHe!gF5=zO3z2*G(_)8L4dc*%VuwT_yj%!P6T}3a@;%`K@8Akj;*gceSMydi& zx8%A%+1+%1`Flr!p6V+j2Y<(h?=TyA=Q_43fBB>Lc!5e_QLZ4Uz)R4HEWC6+(6jH} zm-xhgh3~Qy#`5QNm+Ie7k|KojD}(S`7)O$S$SL>Gace_=y20@j;d32+@R(o2fr85@ zX4E0Vzs0T#Di!L+@7X_e*`d&fei}$;v;%4cs2RrSyB79YkTH|l*j|dY_(n}UrfvRr z{|2s4j#Le>TQ)EY!D1GFuZSahxnki~;=Iv>Hkv64i&@JpF!{f``qG1h3hF0Ze@&=z z&oOmM&}Bo$NK7oxEhP>)JvK_eRR7m8b5ud0fG;Ji{6Wcdd^A0x|J$mAQ7MzgSyM;` z`IOAmG!TPXlm`Cy&H`HWK6GqHMO1#KPW#96n1KeTq5u9RSU}Vs_Ol?r=veU2y8Zw4 zgR&)M0TR#sQVRQErq%!5#saW@NS7W9tl(847CHglR*xnlLeg{m=@%C-&Dz88Z#Ozp zgK+U!;!;iML>-pmI%qn@VfnKk*9A^G9AtKPq z{1;ijTFl9Tj@YF7t8Gzv}K_IyafQDmpuhV7qs52ha< z30yx!uVVfTElr(*DWY_>HB{)A&RcRmH&Qn{Otgu)t0AHI(jxpc`~z`y^TSux5TYM_ zHDZ*vU2ad~23w)eIX+SE!oJ)6)W0M;G=H_g2#7t~YSEtQWDDXXD}1cAba4y5Hj= z>6~enTqrs8bUdOIr`=;&Q6Bc=&2V9SviP0tor^_fEL|O2|2WO>1*zP za{+`i@y8wKb`j>oJ9+%jJ5Hl~)q__o>z926g(81<(z0)#uoz15eC`n9KS{lx&o0^V z;2s>*0*@E^FFmhh^Foz_TD-S=xP1YFy!-iKihHiFdVigmyPvL9L(;e%l>rV*)$mh# z%>&xL^~cWb9}syP%0+yAf(w6M>?)oX+}0A0eAl~lq0jpazY7tzPL|Z+vd6x4#Y|tS zk5)rmdy}aWJE<~9_}YEXcuTsNz3t7vuP+ZMVXA=Ah}Cc z93pLvhaf#@;|5nS3g{F#9i@NaGZP*UkOjoldlb`$`7G4>VDWtv@VOH)Fw=GnKE*vp zy6*+N^kPY(?J*y2cr*6{DO2a#pQZ~MdKt^bJ!7B0rwVDALWlT3YuPCa>9PNAqQIG3 zAYm$Uv?q)CJF2teaN`ouuu?zTmm zYQz}1ksN?^B82;Ma62&x8I<`7Elhez@c#4=XuV6N@B@JGxj>RWhb7Mbrf{_hDmun% zxFLT3550n3DOeXw{H6k`-XxgZYRSRO{%D4byiQBdA z8l+pSD(=}p;w+hrMdbix_+0PJ0aojF2?yWz?rNmEB({8796_lSrAS=*><0JO~OYfq_6v-(T+JAVG0lIxi;rR+0n&Wv2deLK7{`Iue!g2~( z7lXQ{2&D4K|I=dX!9YxZ)BR5rL3zDT_A^ZKPZLRs-6`6=t~bjJ*f5^q8zCk$zkvEv zY(@jAo!e}yAso3jVf{o{@Kn-)EbB|`Q01ovpvW_NkVli&Q?&bv-2J4b0JA-iO%Q}v zIUJ3MTUKdN4wX8-Wi=GAY8hT{g_skswsDt}+@LpXKyui8X^lK``K*n%PYn}z7VA^> z96mP>hp<4jfG+j5&#$ml^w<-}_C_5d;&elxA-3?hi*tMjdgecZi)wlw+;l7lmG*wdS|8XrPkV!E5Ycgdi{l4GN-{C{2mfDKmM&(*;u zm;T3cVdml{lnS$-5x)2Ro261K9DV_E&&sHg2z-67$ta5E{n=p;y9?|y#C~36AHb(I z;hs*er(kQ!nd{bGLs`gm&< zm#p!t6G_GIWO+o)?-R4Ad8h=2;r)pFq}hsfx;)w34(k!o7&NMHk5@W))#V=AB~|ru zt#sg3#^EK&^?lB#NxyUn20}c&pfmcFW0YO_j1wWij~kE+pkwE-1r+0Mg8V@UI2OIH z2Q&S;2EeGOYAdnU1usM0JM1wFq_{HG>lN|Wk@_9vyJ*@ZMtgyoFh{`Z6vde8vJxFV;K z&qdJ5%73U)?H|?um1j_vCXn|Z99>HZdRr7tZv+6%J5?qOfdW$hz4RBl^mY?u0--9U zwx{Ewc{1_;Vazhh`b<5)GbTQ#wX_PF*E<&`-dAU2;=3g<;pV(nIR%t(U;@J0wES^$;C zMwocle_;!gY=@lhw=Nk8Ym3$3Yaol=-rUg!2MO|b+t!qDygZ`S+7CfL_~c&9OBkHb zQ(V_aMylcCJ}KT*-|%&she)A&%Y|D&tz5;X*OYe}<&7o?0Qn7+2V35_Xt)cWMwz%0 zcpZfHN}pFMs^ahP#vE;i&UQ3tI9ah#bEt(t;e~?>WDkSi`6i;#JDpamYLJ9sKh2fK zZiGEy{p^BqfVnS@@!OXzMPEA8vpBN_r}+}2C9+u}asZ3a|=p=d9A zE`L2lEIj9hoCYvp?onNqUvhbBpm_05t?ton+LHL(V^&CFSk)9d1sL_?))9%1 zvw}0+jvo*x$J=Jld0j5Q;d|mF?BHzt9w?k_(YuLV*F&2#W?hK|K&LH1th z{%&x6vGcV!f2H2b7OHJIGDT~JBYgCNe-)21r(dk>Mo}=4NUy^=-<)N=KF_GDu>H0S zVdjgFJrp`?dah8(tj%wd^aj@Jp+$tMiJPc;i>C3*{D5v3nfO?*-EBagwuSSc17CHu z-P*xTYhX2NDAqQCK4`*#Lo?@iSs3}$Ixn2*;Ub)I_xM9OTHlyiKlg{eWp}>(j^$aE zqfcLL)OT+W9I+7aSX&pfR;??#6`ONAwXd8KdfLT70U!54Rw93%g;gp_k~jIY^OLD+ z{;OtKML<%#OqXBh`3PH4ErL$pNiVW+!@^@_o{K zqcwrW13J$EvFiPSE%r=T)3xmbi3JAO>Abj6b_iH8=BZB~b7?E9J7z4$+S(qK@Ht zb96U?%B-_0qIL13HUrnq%*+ie0a&wXy!oY==y`qA!E|X=1DR0@injb}4L}w$@zF%5 z{F!$Ih-m%WSuMb}H^;*(8&+k1yX0l`=O?Ge)E_j>@G#LX#NkqEII{plliz23LI<;6 zIFttJB1=%~(0p%BVsdKYic*;;q#4fPiz;HHhO*%2J4~7r4(& z#P&WdE=q2VvzX!?9YOlHLw@9SC9%8E6fah=i|whEZ5&_&T&gr@TZ`eUr|8d67frOR@Z#X;AwTO4}J zDyv^0OF+k}eh&nd*W#4g+0=&ayv(=qIn?d@K~dDr?ZMWJqnO#G*IeLUQupQc+8+<% zo(aSD_VDjijBJ2?X2PeS0fT3s$YqlwJR?a+7P!$z7Ftdh@VH|f*YGD>e(P{b)0TX? z>ZhIO7qbe1)N9_e33z_Em9p!5f?%lRNQG)O-y>W31oa7R!;=yEGCAX!-=K(9R%r<> zcU$C0@^7I>(yk1a^Q537JV(_5c4)^1DHLmQgqI}JF=(#sbKWC&=r$`@qD?hG_!qxD zU3@N+c9%#bJ9r!Kpm6kQF5?iB{PU2(b36;^*k2Z42kX+8RWg00)HC%KAt;Q)!rFWN zS;1Uy6h>Il-v)ZEYL4aPLr|oQ0cLfm+gAOs=f;58ZxSlh+RH@_{313FRyeD*%CR=h zmctDBBVEm59!M-LH&9FgOU|uPSImT0cCEXjyd4JdD6KE2IGcXrCL|MY@x0bDSRr|I zj22zWwdM@C?i-vH=+E!B^Fy$2bvlSw>h>>Br2rz><`nE%x^CJ8 z_uIqfXp@Ve^}*u{nm{k?`?34XoUIv7#SMc|AzrBP6G6>bV-!X8QHZfQR<UFIL<`B-;tRznZ+CTovEZV2}t`M=)v z>nZcbSWt18&13Dr-fp*PkVhK7<9Xi{Udo7c0Xum^iFefi#VB!lkN>J+|9!ij35|t) z)_ocOI#k4elVxM6+y-X>89EGxfHE!t%a{u)DGk*5>1Si@L?E>QkTtUjqsr5!6ZOs< z=$FFUMp&F+=wxPoi4aTfrtTDo6F8(65NYojWr=6*8UoEHo}ix-!`%}GyocZj09mO1 za16TW_tx86`+5n~!(iQ&wC0P<5J!z3yVXbes{v@D=4dC_)dQ9F8<&^wV9dYqJ)G{t ztaPHEWd5Zpn5{DTWhbMja8Im$ok)<1*Ujgu%Oh^sAs0KWRS#Br1tOQ z1IW!43f_>(Qvdiy_ydZmJ@nihVMSoq&l?5tlLk`)R!BrIeKd<@OeK&D$|5O}mhaGj zH%PAjR)vQ^0+z4V3cllK5yAj8;fGtiRO*Xz4`q_9l+DICp>oN&uG?QnAY+>9-b-T} z)X44A!VR6Kclb5YL%*D{S{j(UI(5IdpiFohY<}7QiK)t(RQ03FzeDA2s!)uk*tr`p zSl{oNCj8`~-Qp2>eGbWJX3M()hZL`d)cDyoDM6OlX}@8D_78(HD~%x zsY}~0Z>u8x1y@AnGdR+|*(S`2C-&^Lq_T<*o`}H6ocgFELCFskUkIZK{^K_3Kg0Zb zbvv{(LcORk7B*^Bq2@|QGnM*hW2DK2oe9UcBY?0}D71YW^(P zn@HPxWH_bT=0GBOKVL_>QGVpK`tPcIh~E|@KT8bYfs+Vng)we?hEFw7o}ezsgyc=yZce&g3`L64+!m@sL%dB8(#AJDY(ry9F`+ z`ShU<kr{fv`D4wsdN_yntblcnY+7c z+6DXUBD_L*uvIG^ME#za+Bns<87O$71R+{10B0x-$PnazM=%^Yo)z#VckANxP3vRF zoy`v$z{FE=3`v%eDj`}#1DF2Buc+mC5Sg|j5FxR!aEl%#*Oy24DBU`7z%?jO)v8)3 z1}(c+fs19Y$zcqqQBp%#X*DZ`kGbVdjcDyp#>D!I0$Z0hrMXIfa9nqN*h}YN?!Ku( zrjIMz^}0CDB-$W#--7kfc(%ss$%8Jv;XC}7+|eT2ESv1}kC_ml z$d@FMK8;!*S7HGa11jI6tUEu?+HujG=?u0(#>iplMsHZ?9>$bXlj!jDLo|e*z9bxP z9D8U0~MlL*+y|EM+!@+C#9>!V8!V&ySPEyFrX&BG!K`JsWZ^Y7Wk>{3uh% zhL8x4N>C2cW^bb$2vzYMkgvw3X;g9lu~MCR;A)HN;(`hVTgZ-~kM8VIHpzO4cZ*Jo zfu58Zx<+opT6W()RkGMJUx9Tm$Y0am(yW@YoRQ$(kxryBjw~%qzDLhu1BXW92f&ns zs3p_ONHUfii# zEc5)PN&*S%Q*?p|A(r9wAym~RDR|7pU(=^Y(1Io!5zeI*8EpYaUkgyv?8`1klbMa+ z@&puEf*YB@{WMoMO*Kmg8!j-}>yX+-CZ;u^b=bnj#YFZSDT8s{jAey7A_tn?zuw`G zmUlyq_d?wftz`&`4SpFeRo=tWvo)Q}tjm+8cBh_I0Wt%+3+>_P&&sRQ=?rDbduHVd z2i@Kwf+j*&qh$fNH!%>yjT<-fVDR#0+v9XBl!@ zjtlobEWxhS!KbKFB~qOwEy+!O*xsaMX;<(PV;35B>s6Rd$28dq7NOZ(6z%G$60{!u z1^$=p{h;ui$V&>CB$uRnWkDeL-T*YCH9Ty;*;T1Tlu1NNA3OGOZicT|i?KguT)i`~ zCZgmm8uW?pqDjlq87QTr2&%|!{_C7ODvv566|GJGQp_Ac9J(`^v@A|M%TIg6mP2VB zG1@;YM?wC?Ll>XLJ12UvU%P@;>t_26rVEM`T(E6M8#h<^WM`3 zofOcYBy)>`H5+703H`H5+C8V?lJY<-Zm`js5snLv*r^0`{3K-JRR%M|NNHQHz!{yj zSa2#Q6_0{LoRJskK@+3kJg`TID0{J{w#cA$Vq^ciq{+C9Hh%SeECtC{f83*+R6qV; z;eX*OU-wvz6ID%LOE_X*dt|DNsEBAvPKV$l?2F~5a?)v;MuGUL0+j-37OLsIUWk>k z0unal#{PJXI{-_t>UWXdR0PH-MhOSYmVuN?bjTIjFP)$=Vygb&KcHdFmgtEya?%Y9 z2}Q_@NSgO2Vt>?K{tGfjLz$mb?YV-NmC-VCC{PveTKeEqk;_i>;f~5%{Vm5bQRVOW zUNW!`SrQw((-ix-w9go8D2-5HOgYpL0U&JnU+PC8XoYi}51MqqxEHS3go16L<%3L- z#a1yld#GVot3!OpSniMcQc&;XdLM7wQE9-Cg@dW^)fiku;9vd?sQ}=#g2pELO0!ut zmX0~x+&E_x6UGry3S-fx;vz&wN74mZmO>$Wx-QRrNRFNoC!blH9>3>bc#_l(Fy=q% zp3*#2)W)gOcUZh9YEwfvCn6^FLv{M*JuTudvWsl%Wwb!d7m7+ngw;6$2n3Lppkf<-DlhR9OgqPba~X1-=4VypR; zuwNUN*qhW~p~*^qpunKp7hVE~ipyjG%66;L1H!~d`fispKgirFs2a7Y(r)1n^vN~S z2A@82`&p~}HP5m047PM`Q^w5Dw(G;doyT`Pfu0%i6!#=fo6ttRnD&35l;7sA(@Bw) zmHkoTaJW!b60ah(@~0~zf&aI*?(+=9!sc#&XoVb*`Ok?_;QU@Bi6Vn$b%EE89}t=U zl2y0So2~m{S&#Z-j3QCFJd|JMTIieg)p`r3_YEl@$Z5&uY0IlvP4P=+k4Y69Sq6># zpZrgK*>0zHDoswyNnG*kr=36$uNQhvN)Z0byYA3xaCTapScWzjIeNLwRxCxZZVmY^ z0IG=FK#;Ckqbt$v_f!`6`9^xa`GV^Eu%v}Fy`UuQa4J@hBKU`t$mj68dms4K*?Co6 z*~|UO=<^NeYpAC*cF$Ag9+Qd;{OTh?fNp`cSX*-%ax+e`=|7Wz#2hvR37_{PGu*h# z$L(Z(wZY8h68Eq3`$3{GKGpnHvLmO@o%ugY=Cc{$&yqrMl2UPP9TB$2)45Q3jmoe5 zm-UbaF2h*rHM(57jqY>``9krAK1UXOSBneU4en)LJ3f&ShPy4J9V0l?&_n_BL-<*KLdW`{l$)L`m?aq_ET5#ry?X;tAA=_!cWo zCoP--?@x<0dabx5LVHxGF;J}2OcJmi5UzA>_Nn;ikiulEFJS|h?4(%aUzWU!90$f# zLt3nGSU?GZgmJKPa(a3jj;%!90+$x+wi8Teu9~(_4UGiC0Rk-!8|lnfo^%@3+H=~H zt(&eKE%s~UC0q~u*KH|}t8PkzBd;D8@?ScdGHQDB1M@^?gx(nUrq{8VbiZmVTvi3I zkzO+FM>vPQK3p`ZUPyg&>fO45SY2%}QVxg5vZiC$OqYMUYTYT?33!Wt+zAZC|8hrh zzIbMQzI4G?FyHIB`CU=)Np}WZ-@Rp{WtkgLB$r@cNUF5Bgs#LEL)6n@YnrY%gueAU1w8Jwo0fU5} zQJSZs%_#l7loqB_2kpJ@?Yg}8?`tg9vD=?5ubqXKmB&UEGoNODr|mB7fVqJowS7=+ z>Z?31tQ&y1#De;04?c1OLoPQ6M4RM3pi*(ths8 zvRFI(Vc^dH_G(j&bg4Ci3e_{RM!W3TF%U^KNMH>79v>No7PF&&{ zz0vf6M2?^ld-Jn*gl_R&7bV7^XhL*){$6NQ zwO9cIrJPBF6OnWIJc>3Pd#8eG+mG>WmFtA^hlp)bk;Z=>estYW^C!OUY~?d||54Rc zEH+)*YY>4z{u1zc<<)UhgfKPlCcG`4{ql%Nrx?Z3eu(}W`~-7-9*E=6^K$IYdflXO z0EuG#-2J#dK}gz{HE6@qgYVW4jWa9sc4?*S zI_&_E-}D!7Bs|7!l>`e9e>xJ;!2qK4!(;xCO6s17kd*DbcY^_ZF5B5ymLBPk-=|WL zFo*@yk?sj50}#W14Zf8ziBeLBYVCqXtDdT$OeG|w={Bi#DN?Sm{e0M%oi$v$ItZgf ze$Y)8p?nU{cv1#o#J%vHynDO{t>LgfK74Ry?wzYKIT^hvH~j!y!k7B14)icHyfW|V z35U{5cpqz2p<%Z#S`$Bg6Kgq#Y5-^+nLQW)Pg4KgqEf^oDXd$=?KvkECBgt;9;R(nzvx2 z>$414&0INeu_YJ`ZZv4{AZUM(9E9i*J;yIIp4v01`XS=WrZWZ!X#yL1`;*5HlsSU6Y?a_8qTvI z*opt((&0z4gBip}4rHJ%v%w+U7Cmq-D^q3oG*;k*TBd?6%zuxg|C*#M@yck^>3jBT z@R%~S%Uw!N&bW|sH#*e@Fy=PO0p!F@-^;gUw0>9Sx8W#`j$Hr2nOX_#xV>3uOyz>b zY}fIm%SiqUE|Et&kDnkAk}5|S?5O@}ad|q*#CrCF8Ki9RAOptgy#(C|G*gM?iU+j& z@t2D6$*%}HnUO@aEHJyilU83MRCF4@0w@I|P|DC1>vIQnzwZN+Orp&+KOTTTYl z&RRS{T6}jdE*SKaOIHQ8wk{TfUs1d5t<6L9sy*5FN~`zB?w7@N^Qwq&N>S#2u$B>| zu_H||Acd6j%bI6TgOc8<^Mz`3+H@f_;ia?4(7B;Q54Z6J^u`M2$P8tXVYo(Zxa5OT8ax$Zk( zFA0Ug+%_VUz5JDuiH)9uD3Lt#`E%;|t?oIGUccLBf-&K{k1Qyjdg6kgy}E0z>5dTa zmmE#Io{*%nT2CAykXVjjxvrENHcz`g9bRIUSZQuFe=#Q>7?wmv8Wj++q*jEL>^UAW zAxdUmoL`u`VleBCPwdO5Azm@gZaE|YRX-^S-vid=`(V3}^?^_prxQgU)A-f?oh964 zjp>!)_Nji2J&ob-d@oJ?K+Xw6Rt)UJEjPg+vWtCwb7FRyS7RZ zF;$Et+K=Ka9(KOkuqF{(mdgAlgKC2L`s=QOYQbwR%zxCDzr%zi&8NXG$ps;xMXN-) z(X^pwWo6=C2fX#_iN~)$=Z1qr=Eo7n%^cYx!_ZG}r8hVEH`|Izu{C02r zZel~IY(DDsGLRt0>(|3kll{RunTN9ow_mP(buz%^jhrnEB!r@NVeYb2r!jy$8|Scv zlGYWDf)drA?+@E85J#pBX<%nTBf`mANf}=P9T8+c8Ig2Po^;>oFVAf?Q6(nL24np( zB!-UCkgUM-J$jSd;4Ey%%@1+B9=W#^k#>F3T$#!Xb4v}+!&qcKT4pO@V0JfWUb_WU znWlMRHHX(l104_Rp}!4xjn_of6v-nfoU((}XFQzhds-}t-MXc`p|zzxnf%u?>HbU+ z@eVW@1V|H4dO@bYzavE9ulzi1vQz(-i9sozjZt7}5q#5GC5P>nC+2}7@Z2yFs#fok zAqjP6zY5HFFDuo+Ec?p7JEB;A#Oe;kXtH-j=;Ff2zh!l%r~<_j|H3N`A)3MkC#=?1 zmVK^LPA|8VUX~B9G=Awhzl7tDLp%=Vl_ujyi-8Zp@X$spUwYmmUF!|1(^a3!lw(m2 z&A?Q4QCypXyaJ3Q2Y;K}MGM2SUtgO?N&(7S1A6nFq~I`NZ6=A`MV#mxp}XcO!5c+ZYd5U+ln z%#4r7_j6H}_WD}GGp_Jz@VC#W`iAdfaE8~)%SCe$3P>A1f7ia@xbiFW787RmWJ_h@ z2p$@wcV@%GzB1=?MUO>qic^rhO;S*S7$%B1qtcfTC}FDchKg8?xBw}od=kDEK!mP> zhAAj~jN?)c2@`qzv=K^dYIyo^sQo)4elYR3v;NI?x3lZsPsQimWSg+^Jm2x5SCW9! zSUZ5rk+B$RJ0%!Ge!oHM4#*XB8L9jIZi4QjFi`m855_kT+iW1=k)r^){g$wqjm&~P z5TMOX$I!Lg&8Omcn#{2HDmvqO?lbQ30 zk06RuiX!wJwEgXb$oKEdi4Q7E35X<3>2r94ep?vEG0N#%tJJ7EonYxL0b%V$8H;=yrsaTnAx z5@nGTbq-mK^M?_YS2}7NjvR;gID|e794JWzqrlK@y+`gFd2$S*bkZ7Cnx!D7ifWiq z*Zr7<7YR}{IGz}KZ$}7@C8B{h)BM-=JxQ^^b5Iw^>p69Mz--zA&YD?E@!V4UJ|0#8 zJdeRM`jE$DLjEkEBssOwl6&nDYWA&CIh+C5(ARI8zC1hrZgEN($*o(S1l^y1-z0D>-cZj9)TpbtL+ya{Q?a{D_r|CzdGB z58zYC69})#S82ZPd7Be_+B9Px`u2KOeg^W>2E(XIkKX5?5F{ z4xeir?q)r21)cgV4v)indh^R-wM`Q)aVq@zF9ma&eAh-FaAVZ8)YJ@iQZrTY+dc3D z1@~*gC;Tt|uWRLDLPUY@w`^H~jYr}Ak>J6RKG)x#vi?Zm7~#9*0%N$^9-Q%KT`)zr5d7JB~s=cWxGUGy{otg#%NM z6x$9z>rSG}22RyaeyI(Z-ulz9oj1&0NEqY-v_YwiPCwzdcaGw=NFhGX5v`x!1Vcx| zw^nc)I05o<{-~^t52wp&nuAELm|6#LUDge(%xw7S?x}n2_s3Z{B+PL@Fa+d#+vl4- z2zH!4Ge#3G7(2hC@w5@zFHf6pX1sjh6tGVeW{%7{jbS$skiSEqKQpX)jQhnjtEbLD zzH>Y*FLgby$xJVGI^Q)4#gT=ECf(wy&?qElce+fi7dp61dLpqVpDw)>$<$}<)-!?z zY-Q%wJU1KwPVqWTmUCA5-z;V8^~L-2pe*lb^8Lj?7k=v8Wrmyz-|%{@tDpN@TlpRx zX~hjghTnqsmQue91P6S6cr~f}zn*<^SU|!emw-e5=5S&bU}aQ#+ujC(1>O|G+FW(C zP>+NLUQD&Zb&<*EvMoqjFQKarBx$ zl(7sND{*Yq;Ll>Wh!M>cuwZupIrdQ-bb2~e>Xp~J(ZvDb8EuIQ7L7G>Jsx$+wurno zzdx>;p>R;LI^9%^2~P@zrt!=p6#J8m`BNnRY*lqw+52gA%kJMee62ZoZGMcy0zvE9 zUgBR>^Roz4D|CTurw4w=vw9neBT5Hj7&&vlqQ(}R2CO?B=E7(VnQAyE%ffWbWjm+Xx+q= zqJd=O3Y1#Ha4Pm+Txr*=Ppfeenp4+`=WcL}8J{@OF{vL7ygm zc==owmz^X?bzxxm0lwHMA;)(+WNwv%`re<5%ne`SQas{*)1UhTo26m>7E-^>nM@Dm z;0$DO%5}v0%jDLi4iVgmh!&hS3#6D4#12m?GcOFB&Ne_URcXx#z|mTSA;WqWkcCEO zH2;M?Vts$ulN9ZGo{x3km!TPX6yzkHS9TTjdn^GhS4-YTX|7%UwO1ZYL>`MO06C4+ zLD@m}=S4LoEO(4LgC=g1HKPX8;ne_OmHpKDn8@PSk#GFWHton?1YU+xM$p3q5(Uns zn?C8?Bu6hYuMJgtT2H9B$Cp`+lq1l|{cG5qZwedlIbSNaM8Or}j^ zk3m~n324r9AN*dbGfJ#S`3t%LGF$&`nm!fy`2k$p9_SjnbN#{~If*no8jF<|eTzPA z^@2Y{irM0FdpN%;n&uiV2aCFK)!#U9hXH?8Syjgli{r_k#xQD7XJ+a+;->>=x@TN4 zN{u3HygM-zgi2L_)Fkm67iy_e@~g!6yph-6B~oqe zXV~m;!%s2Ja=g<_+l%BAh(7L5#RwCjbm9QEJ5DH}_wtCvNf}fpFJx^5yC{PdW)!Wq z7okZlzt-R=!e{3teZV`PAsF+aAcytNeV)?xwus#T|qg?5#|?c8_R9%b~F)?b939JAUO@r>n|~;>to0 z6ab9^zWfu2*kT#$V+72@!K$t>wuQADT%q%)nGSizwatFfrFygTu@^$!TFPM6ca5-b zAbWfBY`Yihi0$8)+?D)VERn$=h_CJa>$~o_adoP1H*=7tWyp5?2Es5zYO6mG5n7e< zg+PG?W3zC0(Y^-#QA29(beCsHi-ekB!KWy~N>UgDM83=5U8*7@^n!=7DzY3P(D&>7cdyrO)T zLrFMAIWF!7M&cc$HD#t~#)rilXlsPRNIgEj{`sBKOcT=0mSaEg>VGiBBmZzw*O`|f z^lE*+QCFw)NW8iy0x8^lU%1%nWYh!;7kgWhqQrg^frLNbdEH}|j;7(Q_7rj9L^|6? z$8!4jtsrpWpP=YG!*{`W?rWlTJ|yRVBkVnE47u{D|K>sKv|asW%XNb3*ce7m{xUbu zc>vH+xz}oxdX0>|V?)YUde1jM-PQo28olf@nW*%(eLDI>ee-VjGgU9CBXC&` z`5YsmXtH(EY9fCFNT)avVrA5t#OPe(k00zdV3r+>Kxk?5CLQa5T)DGBb|Ks{8d z_hYN)urcc0ZZ;@YLFT!cXUm8;$xR6KzegqyKWTvC7nAQ?!Z>aUF_&3zu>5B6%y(a# z?nH`NFM~5tfew^)pH*}CYVIL*Hc}T*bbOeDjr5ZB`DifELbb;E^#J5l>8%bA04%R4 zxF)wyEoqTw8bH3a=C+Ex?s*mbV?GA?=x3MPS=E-}st+FZY4LBX)hph!LQ%ZIfhbaV z{X4SZ1|M`0rN={xVKkUqdkQno@4r^_^vQXh1z9C2otii>%q+jd^ch7vqP;T@?s|;`qvJ>?;?jK^v!B@E;gODpO=N4c@7q3R(7-NmvtINtTF0U|7u%g;~i>44<=_i zKx7SeYjh8p3SwoD#|AR!jDyY+Z!&hyn+QB6T^&<73EKz9`d^)pI`5vbcjoO{5Wvns z2~=}89#y2?gmzR(sLNKTZCOfKd)g=Fvy*)_sg!5M@GF~jQuYQZqVo;7Q}YVeFXMe+ zQrv_V_+>63=ipL6vV5D_2lr0=yckVp57jw_VfL*wRr6whE~LU=+H(+4@^`AWCKA`B zTWyD2ZW31Xp1i^7_w|=CGv1Sx;tRg0tJPzqVEX1vyd8+F3Zu*m9;NbmWasCuhoK?0 z*~p{JGtEeyc{4yGz$sfrey^e(;aNo-$1fZ%#ih2`wS6|44fo?9G4^3Qp~&=`f);^? z(AHlvcsEyk9rEXEyg{Ak@cIi$&9kn21e&_0&q&>-}F7Hf~+!s-7oNV zBoHI?%~_nb^d&Ld&LSbG4O9a~0qjTyTM?u3L z;Y;oIp|v%GXXL^#(n^0zrHJofex+RzJ+N+50ty4n?-(s|z_jMkVV8ie(Xq^UHrgCa zHdCB8?mahgF^=LnkrrC!BNBP!B;QL9(d-DB)Pg&WJp~WLe=cHV?7|bJ%Hdm7gv?_4 zD-b+DIWE-Ss_w0WEFLeVMTAEStQ>^(2w0+EZrpV;Pg_{Sv~ipH)x9MjDqHHc=wwOm zuTsVo7SQk@u+?jC7jBCtxCDKKAQrqmbz5;#m)$uN`nV8nY)EYSMXUE{?+fig0R-8O z6Y3e>4RO+djA5-5%P>pxQM`g#Vf&FC7VU*y^77t%D0Fg!F{%9hW8 zAC^+^8GJ2kh+6`wn+gc`bhc+g8&wJk0d|xF1#&{DQ29?WdCN?GYO`{TTRnglc%#6cSg`yn5}uL< zrQZ-jXVB`}&vy{TSM7b5J=Odwq)N>xVTl%^`F4si(cf&7$Td|(#b7fyMxi^iCd6~T zp%t>kK71ef{=$N-jy^-ltx5U`A4kyLif5y~;1Ql)F*uBlemK*&+SHU+v3tP_r!@#I zTzulRE`=1=`7nvl`TK;I9SmFvGsqqC8|rIc(&K~Rz>i!xRJ`MVaz3LY90%EWw>vo+ zLzlk1xg@(|NBA*Wp@s=ue8)UsEaz9`m(H2_ysd~CU;@9%>5j-zO~S!pj2b7s%*%@-K3dg7)qU} zjR%8%qwl{Ej>c-TN=~HuI^Hy;rgLAfa`(qc@NQe=0O`CUy^;8}nm&L?N59YZPTeX> zH>JR^jE^ZA(bDr1D&Qu~ex*%*FVWj`7zrUIt2yskg|m^mpQ}r@YO!AU_f8Y8zWg7y2f(3!c`c$s7S*XZaVd$#7u@y=h2q#j{#y3OhWhE9U9S`+y*0l01Bm=%he z9oz4z?9LII8E>&Q$6ISC?f)Hsy;wq7lF^DfnMI*Qw_BtKk+9}mziY<(b z%g)G!jz!C|lzLM%@9~=kX4BY>qs@P>DabeAKI)v=N)!7s(fPHTUQG1ITbvl77E!aL z${s83%_MC{)IVW0o13?LW>HeE%W%l)eikf56P-@nywoGudi(hiIuG!*Tb(Xr=*1_U zQx)0=7Wfio{bp~7Z@x2UVy7(Wrv9@s4Wt`gn8%3F?GJx@zh_>B6t? z_kKip>@}=n^UDE0gddP0yF9wt5!Ib7ye9oOp&>goS)`hsK@q;i%s8#6$d(hmG|oJG zyM;930zTag&Sc^ixv(!{f|C4UMdn1D-j8*u6T*YaDeO^;XJ;lRlfW3}ZyLG>zEI|1R7X@*5*?Y=G+BQIPx->w zp7s1#^PV$1E9^{95TJ8`L@`p3HClP_nlH?Tw?q6-9$a7a7u$(S2gR-PqV#avj(%+- z*N(3NGGD10*1A2X@Z(I>`sJw;y}M#Ho|F%Fv}t35$Iv#@ttuAkw@96BcmoQ^32RG%{8J5@vZQsBnlpSQLtH1A^6BiJ&B|Yk1*Q zv5j!DnJJJu?COjLdPr`N0?oRdxOI`J5rzsO0sL^6$eiq1n?dF|yx+3Q;y-2DJu25A zE5e85Z@iTjDPvB41J?$r)abQTVmPO8F;f^gw%$%)w-^*ggLqq*akH~n^!5Hrs6(Oi z`aXMc=*VMNZ?+?Z&e)w+w~8oZFR0hgiegWa09*6@6}Avf0@(-9KupKu@dJ;IKJ(3H z=_l!rB*`X-oA(k&@8inKg`~*!_(yFiSpCU)0j&&+rWuD#*v>vjD*S!+<7?`m)z9wq z%@6~}x5)h-$8$ND`nudOar_Bhhz-3)^f8>t-1&68H~?=GA+m^#Pe^7z$)9h!7_+`A{W~$-T2Q|B-Tzy44W&H)ku=F@i_EUMH-;p|B`gP6x@Fb|*$*0r z@L%Yh@1I-~WCS96M0myyx=cCMUkV+Xy{0|ldv2sOt^+VtRvB3FcBy}FYf^1USX)8X za`QJIJq@R*+#n8{|06>~x^^j?e+_mdJq=%nemNTa5=iyPpAH?3M7b$ykDA+kv~52q z%x_>G4HVM89wHu(W02-eg5&x~#l;9KWMS|gbbCsdYo9Mxi}Zc?%nh>+)K&za%dKSP zKaM8zCdoSHO-FT@9{|$a@R8I>BsppL;hU3weT+9~nc~#r%17#OeLK`+kT1o=mq zt*}sMQ{-|mJ*VQVpFW}9?sUH|$t;=@{(L)<&+2)x`?d3hL@5K+iRJ~UOaK{WH@Y6B z39gv2LnHoupeoUc{i8X3i;|%C9uH@p>_azxNKHE|<@Yi54xpv&zUVpe^8Bd)Iy8i6 zW4_Z5Tf-E?Wj3z(;!MfpMB;OS;q!3X=R7KeFa~y$1oaw&Wm%aN#sGkQCvgzT|Bv-t z9BN$e)fP%nH@KSx!uq^HDA8_yvhL3pfo(_3m|6=;RYyIEsD?463F!7kpucAF*BA1} zgR-VyCId-KR_Le#kaienz%PMSk6F!Hl}-! zF7!fBvl#{Xt~8K4ap`oMIaT|BxflrF%OMFVHZYQBZ{nzgFj5jEOaJCc2r~$+9RXa2 z)q0k(nlA~Oui~}y4>#fJLr_`~L&l-cLnGo*>+|FFL~abf z)X_qHAz((vF7_t&Ky@l_uG(xu;Q2uWls9UbG+ypUE~j1N9!1bZt~h$Ja#38s{~?IA z>I4AuQ?N%g=8#7omYcH@#7f^r5ysr2w8zOx_}HhQ%;-E{V<7^n8u%dLrN^U&`%K{I zq3P<-TPTxinP$D*>=9lNw(NUvvp<>xqvLf{>kNJhr8eJ3^Nv8cizzj|v7e$5gBVP& zC(HF#5~4^1mYuPt3DI~pYb{M^n*b@7XWfV6iTL$Xz>NZWqV-zXJ56abGTbkoyEa!3 z4>ubz7oc1;0YJEPeF>9KJaYvsAf}|4=yz!5+yF=+E@YBgX}w3)a&J7J)oPj+Wac`h z#s|Oa*)1|w4Kb^{u8+k|4XC|V0}#dm2fC619r+*fY$!#_KNvA*DPd#sGt$vQYPaz# zOiBW>4Y+E!K2Rv+Yq{M{?-dN>|I02|-;-4Nt5mkdIt_Q4@3EZe?frTxsC*xYAzkO@tP!mCM~9 zR-^m;TNx551Z1f&(DK4G`~kVfj=DCw0c7d|P?h4fKZ-u??^8Ylwx;YBh?@oG%$OQ) zYy!yTR0UJVDDD7Rxw{&KUI5l|WSICQ>Fznzh^M7WKp~rEoG{pUd0@UYf5`rdd~zex zGb9lgYYv6qUC?~=2b7NAH<*eY~*zP5k9(u zE5JmfgexdpZd1or^v~~m=iT8PAO*`meq*&;9?w+=%9;|G5Y(sO1MPkMY|J;PN}x@v`y&ruscRd8_`Y*E+1syoPC=4Hy#;-!Ba z4-PyKv4o+2IwJ{bnTIo18`aQ}P{(ukL{wUuEYP1hF|iUvo0w5?d4A!xEWGGGcoTr& zftUbTVC2p$KVf;py_8G@ZPWMtALuG4ky+%ng*1brk;keqtJu$l>%6D4GapR(~$@jc4`y`0p)~Q3PV*ivc#MP*}Lk|?{%}q^d zIh*38>s&g|x`uv!v$wycYg?bf^HFaC*mK6dGKJ&+Gc4exI_G@YoTR0&r0nAS2pPY# za)DED6(T|k44q+8_#{WOc6M0gf%ugMY7qK%Hk>j&>2U6YM|T?iI5&ekbUbHzU026c zlFrBPlm6Q2DLiiUbQ)E#-6)6;eGKox83=^ta zHYUx)$b->q0VZG-yP63(9=Lueu+vm=qVp+&uM!H0_kwk`?DX*G_Y4oC9s_jsd0^JU zuWLv4#iV^t*2dmjNuBYd(+UN8(RdAqN~n!F_O1-KwPW=aM%E9XS@n-^cxM!^XY;%B zLb41}M`vn2*o-LT=*+5@^5h<#*@U(jOB@CsXcSE-7D6gttgBv0gCIJV#M`D^ zI+=WLJKe4TQ;xHvK~5Zh`CHq=84XO373HG%dnn(-Va^Sd4WEn3K4MJ9p%kW|VIVti zob6>e4Kww>&Qj3zxl{>)8Q1|G3LmKc0xK1KbQ-GB7&9!d&jBi5uMp4(C7$nQ+RTSD zxGLGd-v9*vh3aNRLTf$-CG-mr5>T$T&oBDk9~HTsEN?GI{)?w1a8s$!_j|fE3oP-d zfy#&LNwDz$=yTF?{dRGn%a0_15c+uI6~j$?0Cd6+w1)QAwny(7PM;~a!19%_d`~wU zz4_S3&;hw{qXAuAO7eV(`kC`k{ZAbTB&_=G;l0&C(nQVfZ@_{YX6}Ikox_R(*3NxG& zSS+QHEWW*dnsV0T)K$Yru<$qIYcLZvIUIaNc3s_?Ss~^Y;F|{XW zEH-Vl+ru##XM|m0zyIZ2zL|{)6p^F)hAGb*!015=dq~vb7&PAbHP(NC?Z=>gW;@Qi z#oDfGUR%$1R_-S(k|GCZJeJ+ZR`$iPUpen4c%{8@eMdGAFR`aJcqoP-rX^@bB zF6E{oY<}(B9)}}6^#X6v=DVcQ*myrtH=2tia3!$mGLvD_N@M)cJ`I5TGeF;jo6_1d z)G)oy@!^Wm0E!HK0Q)|aA68N@W{@K8-TdbqzE+%b&enaQVXUt1L?E zh8Oe)m{2yGEV<@&xz;A z^h<6Cb>}#C(pxMAP^mygk){R->+~4Kaam6lR?_>VT>HH;7%XZz0S7XqkFVf@wix6- zt$3aARd+7}x(wB>p&Z-CpDid}jq{zTj?>-X=gQ4$bmURhzG$K-m68QfeCIoe?;Plv zimJ^UFqnF&uS@EtjM*Jd2<>&8v$$8mU}2(ZztIoNA$eUfZqM+I*00hzn6|Pol!o>+ zN6tAujUA`e~DXtY}UlQ%5H^Otm%i>`#^(~(knu3-BnU+9Z@U1;r z1Tz)utrUE}y*OL~_Hjz0zhvl;XNDlzU!$%n)Fga4Zj2x5j5#jtYFwjeyF#~}nx6@N zA%I4AgjRc`@CohLsOe{`$Wj>LP|~&;oFZR-kfg#Ne(XF;fO$meRZC<&&j?AYJ*U2D(@ywJM1oJ_rnB-3nikuI;E8~Wce`}cgqo&I1vRv=5Dgq_!| zSz~UnYe0=s@&>yMy$)8&%&{-giv4I{Fc#NGQf-AkbbX>GM4GqX&9?G|Fzzc>JoxPG(7HT54KpgMc+2ySMrQ`hktm zatusNTa98kX!C)Iu)!ZY3jVmC8s<*^n00Pf#K4Z<7EewV!%r$=n#*MtT7iuJ`=Bql z>ai;NUGn>uJw-!0TC|MgUS$>{G>tN?joCth>SskY{Z*A+GP*5^1)+^OlW6Z(p08$w z+Tr1vO#157Kgyuk?9WYA4~by0SEt*kzAxTYAnOdzvk?uws)-XJmX_e6t9d8={ig`u z%rfyRH}K0%U5GeI%^579u20|dlrSQZIjNu9%8#A#$}<;G5=GFC43>FE1lf`vmbfQ< z`~8&e_Uz3-X(BGKH1{t7=7AsxtG0av1M-+1qrR|K?|MYf>tkD}Pr{fe|I#g^{Z6@o zDev~d8??MPf_pcwa}ebXF~9pqTJ04_mfUbA#jW?HA!K69vC5oBIVSAANvK~_6gNjm zMAkJhtoGhY<_z?DOcrUnF?4WUk_<(KpIF;$H&=XD^Ci+X4*$wON(vgc{Ej>`LWcEU zqFkwm;5_jOI|}e87-H*JOoY*^&zWHVy}mg#jg}_-(>lZulK3x(CVl)=JMkl;zVJXH z>y1>tf-~MY?m0fZ@1?d=A`F7ihA8RrbNfUC_fgpw^Isr9Nbz#T2(b~uZX~!JM`+uM z+VQ?8RP~8nD4-R&(4pWkj1B%vL91aV+?TKXm2xtEi?=5O7@Q3ygMb9y&L-zISTJ5!IRCV5Gkund*>%RY{3%Dng3s ztR@%`>H02Mz)Wvt^dY`=fOEVd^-66~)eN||Gx2AnGYg@;jc}rwQR;{pMYyLa( zP*sGkIyR<8_ju4~AZ#I=jyBYXdU#@=*W%E7@V*6A!?5M0kvWFv7$4F}8@A=g-)d4Z)v010B!h>mhP)+_ryj^@_Q<$j(eL}6jQ&F}o(HgILg|Ud0Qs0nr z2$@rIGjo0{byi7~wgLOfs?ZHpcZ$mx7IB`=1)K#=S;Bj-VMs1m(e!zV^Zh8@TA`kOe7=DFKYA$J)Y0Tr7BeKO zTwH=frkRN)np4rris4wf;=b`4=c>LCzpN z?u~#}@`T=V)(<8`4m3v|dAs25zfhsA{x_ku2Ip%`9UGc^S6_&vE(DJ=zUQ_?A37qI_0^g{Crcp^UD!Pl*%YQMIJm!m z0#XPHG9(JYZBMA|@0#^1+ts62=-m)bXohb4LfF3Cy5P`ywB}bEz9DgeaO%6v#$KQmq4umjymZ zCH&R3+G$1VrHq%u7`$qn9u>#qWA1KjWuWBEf?b=_ZP-JkDXuh*n-`(GK7#7kok}?5 z5?2_P6JNZ618j1=8_Y=c0)jy&&h>BPk%QHz!k9Z6g^Y1W==~ifPv(Tw;u#j-@7P;w z0vw56C3AoKSbiF`|GG>^9)cl_XaDg9Xe5_Iz)WkDqt5%U?%7If9ve2=dT&eEq;WEc z(-Ubd-xM{NPIBCy?YaLvt8!nmEeE&g;_pS+=yqaDQQcZ1>>gOZQEAk+is+8ea@J2X zS!<=H^fkX^z{NA~QNrfNDd-(6%^u*zqdcXf)#)Lk2%K2d$8P?@0W_Z)2*v%GgPICS z)ix_uD^O}-u();u(E5846MBQhv2Rj>n7?YdxKm{SP$|3H`dd+abuL>%Rcsfa zQf@GVmapJ6*qevqzqT(AIr@y{?rzZzQv;iqGka9AVB1t;Hou}C&gZ2&Fune6dro}u zLc~H$3{6*Z-yO2ooc9I60ueeH*IrVZ zwxN+PGs#iSdLy6!&GipGjkhKUH_wN8=Mx#;^)qK#I_pr|tt8Oh!aE!$OrUcIpq zn$V|lK484FHSK7gi1o*39ow}r>^oEv&mRZtsMzfG*66H1kXQU62cb^DDfAtDe`RBaN%eG&YkcRC{N zF0?B6kLt@mBttTC32p@p#JCUA-%*f|B!Pwa-COszb#cT!WA=317Tjz@-_ z-CR^$T=+(ml$IW?am4h-#!@W7ud!gNej8Bw_-g9LrulT{$ed2D&cG8L9gPEI!Zg|QaxCvKxeP6rMqz>$<%F9cSj)1)Rkt-vWC9NU2&nsRI(;Bi^4n4fNS3)V-EVu zO%SSfRxu&oBp$ngVW^zatLr=_%C2H&)J}QV&gdjZqNI3d7{wr)Mse_6u{N3LsO+lB zXzi5rlvmRIx6Bw5g_OGsEe)h&z*OmL?dO6vsa@2V=ySLkAf<%o<}{wbmvtp5%_G0+ z4Y4{q?IT3gYmzI~(e*z4c_+6K(aNW!Ca>(@DYc!9m)D42#VSh6!e8toRcz z{^QUFI##dSL}yefcTf`Y-)#Xp%p_9aq3Tsf5Zh>1xcIwGlPkE0Uh|YT5LxVa;OAw9 zZIR{2c}>~%4HLV>x^s6=`8=bhNgv0X}al|-9Wq`AT!T2bL*Rk#~R_*n10keBe4Ay%x4_>HYN%|iy1kl$G2H)(VCZA zjsZUObl=?FKBBp?ICrThdyit`nRTtUvOt0?hJU z)348zr48%hV~oCrkojcdecMq)$_(?4RN#BTnY+l!O4t!s!0R2}hMiFM zlc21s^yrujuW5%qPdBjS4fhW8;NboBcP5jf`%T<^irPRLsqPqP8!2hzq2pyoeC_Z} zTc(dmju175GCy}M^{2tZI9p{ExaUou%)UH_3OwZC@lJPJS{dXR&_2AOUTd*w+$&&r zd56*!8v56h24ng=S8(@@%bd|sUVsXLw?R*$+`JPMNP-1sXA9Y+r)9|HAT1R$u++2 zpV4)*BPeIN2`c7(HSafrwDy!x7!;f4(8_ZITraqXN!eaKAnE^-cNP6~NzPtLJ0aR%0zi4qJ1q6rQ6xe&KPW|4wXbVJzk9vWW6s4KFR zPl9<($J57(Dq4AwL)O?glTNfXs^_Pk=gr<+Ed>`7=bASTVU6%5dk86g)NxkAUCLV8 zmRvQXSYwDvoW(TPkE$KvH-)@CB@$@*oeZ5yO~#}+gFEefEj!e_wfF41@E|@pq@ATa+VL6(i1$k;jHB?tW6~a9-{lJQ=E7GQEdSd}{Qu)c#C~A2r<7A#)HX zbW==&!|$?2g(LSxH+aLtvo$D8{!{LzwVC!P*6A2$gnPh=MYz4c2jQvoIoUjx_+^3_ z-tW72tq^}?czL~o;{_irj2634RY{)`IeO2Ie)Fm0b28snpVj^+gk~?R(v3%}_MwEl zh>y+6|BjFfeEBlIMA{7$A=RsA#`5~dPDlxXHn5Dliq$_sfKot=R z@p%r+XKmFDQTh;ncW$$<$2-wz?k%v2wWe~akiJ8X>w(cmmSV2CHGxQMa`x_@;zzZn zs&8siYVgUtLylus+A0r9+NW3cdf4(EtG}zv;gpUo+TUsa*-bzW_3Y>Q9Z~RlrXDrg z5q)GB=1#m@6^kO6=H&MWQ6CRnoQ#Aka>Ck~ibe+C@RNlcjLe%~I$TGsvNx9U3*I`M z{d~U}N_0F*c-v24vzN~#?in^V`Zfme%XgG|VKSKKnHzRa?%yn4tMmlbsXFweFHXEW zRcmq_`xa`RfLunHI!SS>j59nsw6%olZ#EMhm#4p_QnR{Cwg-)~UXZAFjWC zvM?FyI95WBzdCv&V?E%dCy^P}|~-+l=1P@X3J3?^|_i&-JpQC@DKDb6BI&kC&xKI9=B z!Y6QQF1B&X>x1F97FV*=MRot=&DE2u+ub#B<5+S5ZlNBr1hGY%#nJ#7pMP$Zon1Xj zc8$P|XUa)mSIJ%R|6N+ijhv;;lu?~UsoQ19GK5WV>vv@P#+@VHZ`%*^5s(P|r-Izf z#vK?2MI=lHdA+VuA8;&h4d=jjYd9TWv&UiNPr-AZc%3Ltb0O+jcdz@*b1t}YM^pm^RG{Jbkv z?VHa0{MRe>$!l0+0VSIrSZmlFpQVrYig3W;+CN?$n%O z$zwuC&PU0RPtC>bV_hXEDbR9R1y8D z;C#!}=vQa{?_!;hAH^{pf_fApC1=+-K8eeY3kp-Oq6yJ5Gs#$$5n{LG*c41*6`QN> zHs$mRl2J(d@gXc~L?1X3`r=JS@c)AC*QEbZZ{S!M8xQo(WT`p1fQD-JOrGJqq83A> zZUGHPr+KXRI#emunA}@_ld&5@_wMlQ-qs%ny)cEb+4JVqQZ@08&r3>*dxJY{OD2!< zSJ!&px`(M7AquHxRQ#cAqp&yx}p9}tzJ@Bxf^D8dbzg0__)0Iqn<>6@OV!4QHhzVKWME-FJ}wB zkQ-kg|6r*(hukBH^}n4+rv#lB6%|ScdbgD1krLvCUXCF01qRbI19{V|%+=k@PtFJ^ zR*&{OnQkFweUS#kgkq7n7^>P1J&Z%F6DYvgFSQ!J3LgG9yydf9W;iA0YO{%|H7NwNvGWnSEuIF6X3&aHw|}1TpN6EgT$Px)O{u5_+xgsU8H|bIpi0yKF;@2u z``Bq1L5JP?bXgv3RraURM${X>MZ`k`KwAzA7e{YjYBOt>GkP3VK=f(VIfLr+1I5Hn zK#wu4K5nB`!^20w8!vu{@k1SEr_Tz%s<^ zw6FwvlYR%VwZGJxo9n{QZcW(dhV>0`XW?)NT5W{!%x}>a8^QK>o{dL>jRCyO@-!C*Ku27Yra{R7P|&MRbVE}_G?|n@dl1~$*M1WS{H+_gY&Fy(@CGpNFsC%X#D?C zO9aZaYoMmf+(L@JF+~0H)M>#y-tGUZTd*OB=DBLH?;~>ix>t}+FT-~^>F{`*X5YJK z_VvpcV{JNp)8Tl<)x1^kOQCfTv}v8LwT`P-`1S?GRNg+G$fGXUfyZuIBlqAiy>t=-7r6V2yX`RD7&!qSxDxJ&&w3xovP4Qj863-5pH?lEuS+(1>URhD~oPfU@+(3%DbiIy< zfZJ9!1XT9LU|d8ml%vr=`>&?cA!|5U@1yRo`irb`##_wZ3~2;oca0&OQ` zIoJ~D>K|4rKuI#i!FaKHkU7F*n3iDk27){i;t7asQkZyA|WPiJr9PHpw>DTj4 z?KO_ByMg;rt(t`;P32SQ^?7pJ!$;3AIAUG55{tX;Ol4pAER^a1B-U!XtIrG4U6&`B zz2f>2hjpCa--PnYe}WbL%(96v zu{De_VuQJMGFS##CuG>8RU?-coko-jGtII*WGJok{&${AFw4~kGfV0&Itx#z2EdjK z$!UbotzEq)oxWjJnA`x>rgln|B^SoOwr0e)Zd>J+t(nOv>$lrjX-o91iazQQz%r4* zz|6W7^-H&V(y=m$vd#&{W@d# z$gOJ6hm8mHV^+<)-p5YaEa-a`U1%(JCxA`~J1{ewY`S^a5zw2{6+is68n*7hWTFb} zL-yotDDgI=`~aDt$9XZ@HE7QV#vjJXGhh|kepI1eS^cg}k}W@JI^mChmwJoQ&XSNE zdfk7w3f`-h1Za)wMHv=8(Olao=mHP+8RG&rB%k~`yd{XoYrmbCXb1AB>z|(1r4L49Bd0>r+ShoMz?-vzL zKId+>!=P8x{sXq20))V8Vr@Y0$!`D3V>=8F49ISd+sU31uP>UEE*e`NA^z_UK4 z{6U)lFtmJKMmleU(v+s#^NOLKBW0LO2U8Gfw^>vOIBYX~?pPsZI64pa^wwAqMW&pM z){A_GU@-sO8-(DQ?kaJZbT{uaJ9+;OmW}*5S=#cg0I9c;c==N{t4eL9)%}<_$-Dgk zHqL_j?At*z#U$B-hqy}iUw(ZXX;ouCHxDklhF0xfuWj*K{a9gBSl3SU*TSS+ejeTU zZohJF#BbRBx*9>rA-A4e*7A3Kmil1|poB`tNKs;R`+6NhUESsL(1dmiKe1Vr|D>}_ zXKIyJPb!{o!1WG)8`8)Tf~Ko2kH@{gJeq%5MFIty1!5M0di6)14P~u zX>jA;%WVIE-`>kce7d=l6{Pn>Yw*9|BOm^uwAS6AB#xKE6xA4PD0Ha$7uFngZH1L0 z(sUa0r2(Y@lCm(R@*HwTl(iV!r!PCnOyjr5c9m=l1@T5@mf8jL-hiF7U~svIw5u!A zYsy`SbzZ*yB^>*SsL@)Q`0_1a7ZsQ~p|yH5%Bg^D2a}iY$-*C1o@S@2GUM=AhV_`# zfQb)+udu^yKAe+9Q{#zYveIXs@^{+=pQnP)XTj$Y@HH}KO_jwcldD{IM}T!fX?wb~ z>jXrUmVn;x;%6<}Kl#Kdy&I3`+0TT^9VXx7H#TnH)CUG}@g%y=nW*uUmwj9Ddpgg) zE9w_LdPKEiL$mW6h`lvKbw@RC87`<~bypi9cP$?LBA(GYa4MV!W^e}hwLdJwxqVt0 z695Y-wNSf1s`qO+DC6;3#qc?>^CRFDDn;joP%_bXKdk{G8w|8HdTb%<2)d_w;<(Db zSM#qHLB};}A+FarK&9!3&79H^P|g1&ayG+!QaGlyBDEB(i)voslc=S$+bo3mCZaBIN{rj;W-R@;WPUfhF=U+(TZd;y$Q z&*9<)PK~-p-}pqI_a+>CT#CY=D!b5lLf)yWGxf&YNTIN}D?XOCg26=%|9q>e?mEX1 zD$73CEk}<1K2*n%_fFI5H&GXB*}Er5sDL^wLqX05IS~pmu$WFMeiyE-=^BctR-)67 z9VwdM#)bG!+T0FylCVgf2U-^SiNEEW1&v8nq5`h`9uKl0QFh)Fy{}_f#d^S^@HQw9 z4G)KA0_9#4qs+D2$|i;fPbbf|cu!B)$L%XB%%?$c<5$0FM&UBNU#{K@q|(&+;ey>aPz=Z8$V^i-YwI2fI~gJu3P37In_lZi3W)We_3;={VJ zz0XU0ZGSbFo4cml!)rBtC!xZOQGOMOO#cm`+?Vg^O@`4-`6sz@ra?Uo7{CrSi>sYz z2Al63Lgc3I)6Oe=c6e4Q)iHLS_T){C4M|*1icKdipG(+9Bc;bOz5fu*+lD=HJtpHK z172G0VNu)cG{$ey*m3mg$j*-@!=V=s+b$`Tq^ov-UVs(>K#P4!M` zE-KmB-@K0|(ObB9h|vE#Sx$YK}#9H6a^ ztWAs(5}(5iSF`}3CR=VUH|N(VWliH)Q93!gQ~E6T_0wG)`kxd7;?dfZ>r;wFabd1x z$<&t=XyxWk{9G381e_d+(kiP_=?sPLEx)|djfLLq!~en=Wj z)@T-vYValRA_hY{gdJrH#8G&4bEX7AM*aXgb!HI*F{aN;#znWeW?emG+fkd!{x%22 zsCK`&1P}GVQiest?gIr~*d7Ob;D-%|C6}3y;*_@`+GlVl0F2|N1!)7e@eZYftP_Y^ zkrwRqka@egbJxWZq5{5054{!Y*3e53>aHf2qgy@(zr67p6(4#e9l>YVr=qxj6AEIK zz$C4e4u(oKBxWLgedlho7z&Tm?jnQUc(&0xr1qvt0=9PA8{bj~ z)QAIT!n8h^8$h-$z;wW?5a z_6H0H@=X9-RIiS|5{sJuw`|9AIjKY!h=;r{LxjhOehCO^V^_aaM`ri;)Etq2$P5%&SnO=UwN*GwNX~AZrpKpy9b4it*MTs2-{A_hY4NhIFddp@t{np+bLd&IU$W%2JA^g8k4=)uw&Q=U|{j zhFH%xm_H{3`(A`Zqj@!%s(qlv$(50Vl+1_Uc&M`&X&dkUu%n1S5!qtawH&$KEC`?% zF6nz^iG56JdJj+6EAcRYObxhExoz0Pnug~WgRwM_Y=Xr(1XXwJ47-HBv; zrL3DOi8eDeUZOK&)X%7#=w&h_MFup?z9uzvoh@c&y~8k?o3UdrSx*)GPk6=Lr0JG8 zq%^zr!e-H_zkmPj3Q?#>(5B`58x2V2YciehKYF>6mQlfduKbXS5+acq0~m0_ zh_i@J^SEp<6hr=ZlB|}3A<`a3R;Nua)N(jSuW-39twY^B)#OpR{!bR1_P<{C{xkU6 z(-ze3?h7MdBv#GXN!ap>eP2^*kxioJzJdyko`}19oWhKjUvK6n z^Su0s0SR`R{kFw;K3M$~s6$L=I(%7SZjpF#FJe}2mU|nqQI3Wl(24qo^ETf2%N2mk zu^rmaNtck4+DUl=8hMapnA^%(9L1N?WT?3cetyEgUXI#?+b6%}^~ze&Zc8H?9+%{f zS=nQwY2RKwFbDLCEWY%=9P)4k9ea(N=3L_Xa-=VvS9FHc;C&m4TYMUcn|>+AV}m0$ z!h0^mo3_jk|9COs`qHr{V7jj3z9#CrZ`V}CY_s+H zIzLIXSg!G~Y9PdEn2U#au>M;xx$(aH`A~iLFMWd9u|2}i|Hk$}(_U+jbIe7@e6*PMnF)C_3 zbGwthA`A=E#oC)n*m;9tU(gye2bD<((P(mi)`X#dcVHFn z0ipe`#V0EQtjw#!VW7J(UJX?;tqx`~g+Dx3r~G07zU~bI@RnJ0y)>K@_@!$~==B!V zeI@mA(R^1af;IOvWesG#nVd_|c9^-Y;F+kYWxQcT3;YuQ&8c5pJgU5^zaQIQj5DKO zno3v{y(A8*3n?4)d-O#cKZ9Ts%ZTUUSHk8C$mL+lP|L2xr(OvwcZ}(l=m1$VKnA;Sg>Kp8vqTv4t=Z%1oP(`2{%|;4}Cuh!Z_an zvn7cP{$(Rw!klN%^jT}L_^?QBv}!Yhu@{+_{z7q%qyahj*-+I8Sokel@sFVo}Y`RU?u>1|utv+gt3M)$xM0VtBe zAwZM`lm1WN&eV5~W%ugkhhZMOnE|Yn&a*J6a6{{P7TUvg$AP6cLERmF|kqUcd9i6S&-QSfIlBe!x`^N)Ge-bJ(8( zvYFJS8FV5%SFjyEzcjOKln|H&lgIEf_vZV|1#0VoWV+W0XoDQCpG*C2)yRk1?uC)72W6-&6`Yj7w6^+a7=zlEi4F>@5d2T9nd1qV?f@HLx_O zq2!B11ow-Ab{+hKcv{D;1>*Ny{~K_e( z>=B!nW8OXdRaV)XW&j${qS8qR<|+PPOJ^Mw)%$gE5gkNIK%_xLK~TD302Kj|ltyA` z>5>>)x=XsHM7l$|V?ZgXp&7cn<9+7)d;P<;T#MxlGxy%-oU=cBpI+cnQzQ$2B&Hho znCnSjAZ7$TC*7tnmZeMwMs9);ms$dV`86++a|NV(M8;ARleGfa4-|fsM9}n9) zih8QaSHL%eS5{Gk7(BGv?|d~P8owj)ybK~Nv1L2V*<*CXsZd$)dPSU@Nsg~rk2LB* z4rhd|0X<7N&VZZP^u$eC+cQ#ChY*(PUysX1CB`-pMAvXJEFCiisO1oMpiHBJPy^Vrh;wIt328|7p7$L8fP z2KLPvr=&$6Kz70?7JFWjke71Wif1`mH~eEr*l62cg$lk4<9K=TyScyVH^lA=xgv-l zyUxHMr-Rq%2e#~U#|WodAJ)o)Csue; zE=1-ke{HzBa>rRwZc2&V1s0(RG6rwkp7NEPZgCocpKlo)`4$>yC-F23rT0f-#S{p? zE%U2WZsZM)7nsdezLp_usS}rulNIK&U&vpX>k@$#`T?N<6f&rj!)J=hgv(W=QFoZMs>lPCBGnt|Xx4!CIb3 z3P!1^VvGYf<+u!D`E*yR`3-rA2rVP|@p{e?wVVUbrNBbZe2OY! zM{e(ir<{IhBDU@xZBwB@5-7YO>@hlr2?^r zUTav6l?inSq?!p18LASn8j3(Ou#;1ZKypRXYCX=mi~LKeI^mVrO~)C=(_fGFSp$Qn z%$TzlxJi!=4*E(a)(Ku~yX}X-DzmCTFKhepf#p#nqjzy$EBKAES*BQsy^aRMqk;uN z+gn?zaT%^Z|LmHLE)H>P2?Q9+W-h(kKMNQ{wQG%Z^a=xqo2RTtYHtruJ<#w_!h6-% z{C~j4A4fK2YRb3+OA(ToPYZf#zx!L1TjTyde}3l<`=r$Sx6132HLfVSCgGfdx6stH z?BA z?EjcPe=df#Dlt%u>E233FTUjmG^JVZe=Y&``3n(khTGf#cZ1 z&}=uaJC8uwk0qa!;12HF87Rx}JhD})MNZTHXN0L81qSu(}5TNaT3w7*xgm0XkOPAPHF z0q9rFBd)u5Y_nJ^`iB|loAj_M{PVJ5u}#p!=HK-%UxSZZVgVqe*sOi(&Dt$tf;F37-XhRJw!ecNb^0iVO` zJ>|glvbKk>d>PZ=&ldlfp<=_q+-PQ^`^bxo`lt_8i!1G!hmRhwS{1zJl8g2Ub?cod_HSfF z^V252`b!K9bX*YHlHh=}yy2@uHeHk?WM&>pR#{ZqcEGCx<#=K5i?O1X_P~UoqsKz# zYre^Q>F@;xW(opk0tP;A0vs@@e+l;><2d?@`PM?`dptGu0sW!b(XiCu4_Ye^T+D;W zLBi{dkl!mweYkjgn6nfs?qr&QP_WT`Rh5$YYGiL@0U z95&BhmY7BhC%x8bP`Gs#*so{F5_fm%`sas!UWQ!(ee@w(JL66Y=|12(Hm6Hln@1a< zF}ocW0s?49v5C97UDumA?ybA+duYuRv)PTOl@V;+=)CRLWdgY}$v-lkA5m|VJg!9UY(GF#mH zWi0GgR}Ug*UCaw-?BP|<-wBxwrDHw3ek*pd6fMtE>O>Mo=jh)06==lVVx6+L>9^Bg zI61G~)^kX=7g{UmTPcN2f4BCDfL^dGVChB3K%X(8!F~`e-P&*7X~~qQV3!Lo1Zak* z_oPWxg4XGEJ_`lWQX0m}klllhFkjm?JQ;6V6FGK|U$>qpWy&H(xf6qsGjlaD09%7%R)j+&qQezWgGi%?wa|-E+7k0mm8w#MF4f@VP(mVAN7i~k& zkte0)74CpPA!DLh0Te@%S61^IJUl5sZI+*8TF)1`D!ox_Ub~|_+WQ2jMl>er zgThiu4hZO;47Dk$Rg$JRn`%a7y<|fqhaf%p=+yDbOAR)EQJ%}fY#y5A&W?}RZ5$VN z-5<{(x3>3j;s=B7PFE|2!}%YHX88+0Um2^At=gjMs0r**=ZcWAROK=Ed_l69`@26) zxb10ld^e|DHT|t?v~+HE(!FO7%oIc4oA=sqc<~ln z8KtZ)x_t7&^jJ03GOfE{F|{;3Z4_im%C{|E1Ka?o2uQ?wNA0dVErpg|irGAr=QWR| z!ss|{3D}p#td4wF|2QlrMGZ2QM<&$SQU7KvI8t*=H|u|m6NxwqkSUb@S`-;#J}8%D zUMyex(ZTc_nv&;e@W}SGz71Z(F@tF z^zwP@2KGJlKQM?4CW5NJF_xLOxmjsF)6;bhduD0CmrzxzxmduV^%A}}s5W$VGbFHS zGiY!RBs*A_8@${LHw7BZR2U!5kT}ltVmHBP3`M=8znH(kw~UtqAuc zrO`9@KN@)Ld)e%KAc1Q^&bhoezsVG4bHUgR;g%o`(fJ1T(s7#P@wa~oE#0$fsvuS& zu{~cS9qnsl)47n|opMivjiXgxy^cV_6@jyA$3FPO>3*pC^ReN`D9Uu$Co3BoUrqzo z#x{D{%GMf_h9exPWkKft)iTdP2smw8}|o zJkX$EW@^8hcc60BozCEX8sdXOR@T2%H&?z&Rpz$cE{>1BYetI{nLLh_I40 z<-WnbVsk^NNs$iJW&}$qwZ?2Mp?Y7szYAklAEv}CM9Bts1I3TB@)En|+Odu%5;j1Y zOPQ6=vaP19!rev}&=eZrX(KFa-G|0IU8f>)U)9lGHL8v|CEh@bb_4A4ODb8fIBSu~ z%O2Rj$gL_)kY~rb<90jRI>OHLUbo1~xEeacHFmA5wD|ShdQmtD`E%XM*eV>k*<0*( zM$O^1$xiV;Tid7_`8;!6Os*I+sp~fd9IkVMkKB)R>SPjmelUKL_yEbTK3Cwn=bgc_ zKx)d`sWdb4K=nOaLN{rl5FbAE!4}10*RbDfn3Geqgz3{Ro=5I76l(Ml`imxSy09?C zG=8VKR?%yl`TELhCLxd=?S~{qNM+iIY2KH6a<55x`AQF#X3^7W!D0+@ay#qnVJwlN z8u~z!QAxt0-TGgRp1Miylb#Cy8j07lJumwIn*l?VF`8Kjs&w^&< zVB89ZaA;xA-r0%ruV-!%Vy@)w>Rji{^VJ_xO&SS1S2wsy? zY(BHPiR^_*2>hq}aSj3en4{BlEAn{jYFCAJG_tn>!a#=y&st3X&gs)JsM%V;Y4+#e zs*#!h)VZUq5opZ|hb4*0`8|5Sca0vy$Q?>Jc+I{%H+rG>?X)Gr9B&^t<|6!KYTT_V zgNA68r%o}3+1%o!Px=~Fxedl~3)?y^R7q`zwn)5Dz^^OQ9x0a2l-celMsQVl+jiM} zaf5pC`7fgdRKdqwal{(sQ*0iqBiUZE>8XC5v>~{!HAZu{m~wFE-|^XLLmHF*^Yxu( z$LnJ)jMWGEP0zauT=Q-DcnND$8@uarM(Ta3%%ZEUp@rL7SSUgO!#MOTi~iGoCCej({U8i`ab4;dc^%#WCb=8EKJ}kP^Vm zE_B?;zVUDwzAc$x&fzzE)uy5; zzzg0$`tLUi8qXNB1zqC=CQi= zTh6J(3%=Pfd3wf~aCCt8zWH}Vp;v1bhA_s>P@H`whMHytqXayY4N+k8T$*sE!;h!Q zh11rkxA6-Qe2zY1&Yr;y=xcG)5?tXAm4tH$-AtA}f&dpICVlnV5}Vs%6)oN zL?%2?LUL8ve3N&&w*~#-S@*x&??Mf8c49DkgRF=Xr35+sUhR$9#223Cu^7KRBTJMv zGp~Bw(LABy-7Ahc+rnYI;hiU!M!_(u$zjpvC!h2W_Anjp;5tye+00A9_cFhWV}I$7 zF#7jV2A@?h)m< z1Z6?O=brg~72HI?DZ=1EPB5UaU?Mk#9R>9JAT&ej2eP$TrU9Icce^yDc7w(_Cp<2x z+W?5Eb$ji-Iiwdoz5>o0SqcvY#>*$zx9<>I7=#X7K# zx_NJ$wwmVSZGg^P(M{X5hb>@la=u*jpO=33Fw%y~V z9Efy}i@ee6oTFtyJJ$bjtjN~yM2bGD5YkjW3zs$oJaByePnm6)B=mg0iiyvE4ag+~ z0F5#_8;bBWY^DQ?8LTJF3X0mnJ{v-y3s-#%w{E_6tOY~H{)yf*5kLxI)D8nFf%5F- zI+22!#%~+DG;o=Ig9L{r%r9{ox_HOnNN)e@Q>4ZHK;9?Pc3oIyVD1P8;&SMGpf*Km z78O$KNuzi?AT~Ox1C<8%1PGM@!Y32-h2@C+h2**E*H`BQp1fysw;t{jp0}8V4XqGL zf8dx5098G|mh-a80tnZ_hMglI3uww&#sG*#uKrHPqvO6s)zi#ZAR7xC2=EeUN}8Cp zZY{Ge>#y=D04i|+5b3D?^-op*6c{+mwgc$a>IkU6S`#3Ov;E<#Lb5T~?W=|CXgRYz zW;`ZOAUO%*!F?1}CD#7&JEL;mVoM6_F=wq^5)&+|Shgj?1tbO>4VI;j#bZFDEkIGG z(*Hpi@Zx#^2*(ES5t#TzC3tWarGhDW`>uzRov!6BzyuzA?dSNSZkj{V&RTypxB&=j zMc+S!A{T2YcE_!WJz$*m!^EEu?FT~+j3)FjY~L05f7{SWM|-~qSd6cVYZpIe&FT8! zwc&F8CG$A%gZTr-d<=IM^zuYNcd6Y2y_X+=&3e`%07tJkQL4AF7;;NN1L{B<5K<~G zpo;D@Q>s==3cWJ&Fsy6yC7z*w>ykq&)}|soKu5rNoogWU(cMs zD`1?1rzFdx0tY?vUH;8t*RPE%q(G4khZrU#No@(USvM#Gc_L!h)=k6RMXMDe8BQOd z#^-T$rprj;^sx}M(jr>`%sp{_A*XQ*gq(J!+!UfG>bf`IRwa@8A-6?N0j=lLt0HP8 zHJU&gnrz=QS^EI+=T!0`FbEoSG>3sGQTE-28A(C(6=FR7ulp_5H8+*RKeo0S)R7aQ zYH(z1ou(|u1x3*ir|zQpkN%b(cAjW<9*O*1xBG01xz&~Otsy21BDi9?iRRs*)aGVr z`lKy9%Mll@g(i|G9LBXXPaPX&Y567%4JgmSKPinvNBYZs?{_ULznjQZ#x2qtzI_(* zTEC>Juxcy`Vpt?6^!pBb`Ii)1mlTF(b50t&o{XXT6gIbA*D9V?irlMI9(Hveh2wi4 zR*d~$E@ueZ$Ha!r4gTSP8><+eUvNGiTSSATHsHJSkB7NThW3E0U1Lfd5LV`P)<)W- z3)w@1ifj#gnXN$1t>2rPqcNC4D}Qkn8vB5q)l58Y0C98tfJq-&@vo+zlM@Pi=y`>r zZ3jRtH9AI5vpyN{A7S?)$Mtj9#f@WkL#xCa6hoh{11R$$+Aa_~2cXANuq&?9p;5B% zZ@o|9u5-I7-Z>b9zu|uBqdZD3k&hT`%?gZIGhF)@FrQEGXL`2c)nOWvoM_}9V466l ziJauY^Yyy)08wzSAqPCH=qyTG)%qh-0IHH1BFAT3>pA#MU$Dv6A81H&Di8{$18dZDih|AA1#2~O@b)rHOb6)UW}yQEonzDxm#mb z2k|RkYB%y8mS9m4rB&0p6D2M+_ZDuhl)tKt_1d=_ zhyNJoT~P4mkn;%}6%BH?4-vme+t36C$h5_a>ef$j?cUrc8$npO_=K9#@8UB)EWavg zu&V`=zcv8b(#{oKK4q5$t)ZcLD3|J3OXTpIA>tnxx=Z=Usm@K7rZtF2JlB8dZv)x& z6n!$y&0OC_O-;YB`HyCvAL*y6mr;DV4WY#dGK9Jdjmnvky9^b7HQtx-1`s4b{N-hp z&b3iOg56S61>`~=lan3M=dx%zNIZnA2K6ne8(8=>x?_t4)2L8Apxd3SauL9qGwLBS z!aGvMESf$pqWHzEBMxoYFUZ{9o)DB?{Ze$YA@ybQixrwtNgaI?`>FM*bJjg8lBVax z;khc50(;MNjBMnE9`tPuF3$FjQu;nKjzV`OpNB!vZT_>kR^o76atEYKyHW#0<1hDE zy|a%@!)rNog{6d7sUM@5rP}om6-zD%wAsEhJp5VB+#H4W*e5O26tK<$dXo;I1Z)cV8?Jl?DZ7Fa-H~%I_6sw#z3` zPE{5DOk&Z|3=9SuZ-O1Scky~O2lZt>ntwFv3cVb86pVZoQA%C)J!IIbov^Fm3&K>p z1^k^9CX4CV($g*fm@j;_qe(e^6ed40tX~?sB@GSgp#Kh%aAz*bB$g!%UsBQWIFeImw1 zq4AYr*q8Mpt)5H3 zWYnw~Qe7W)vUzYoFSjNgaWB#K2Q2s#A|4F=Ul%TstLLk*M}g@apdR`hs_pR_>=J2t z561CuVr;v^`LQ=qdMy)2qw}rflq@i|jSAw=8wLHTkr~1?9*0$zSBEF?82!U}Vw(W_ z-WR0ti^r0fY4ocjBrpDUOgW6tY*j8LTh(#++d}zh5YAz#KNa>%_zpOj^ut48ilL)NeFIagM9xAYI6>6s$>Ed?)kI`-9L74+|+ERt;kwb z*Up%xRh7XgFiPDEIsa_v7KkJLdK^esjA#U#&l;llXbYU5crXx2YVfjaG}9LOpF52E zz8o%t$Lra|;S!JIO&b95;HJABNI~(OF+(0hns+@tT{HfDl_TrI5xQ7|`2riv==^(8 z`n|v4u%md;BfB_11Zsepi`6Cl#bLXI+~MVT7!B{#mZskMvRdG$k&|+fQ3(%FQg*&s z(A0o_UOEHL4D&x!+kfHNZsA#Tz<|cL_kNPiTzg0-K$K>a5njFL};qKTC9XQ)AU6S+ZOlWFdEyDh;0H_kBOrAQyji|hlS zHflhT+^^~PO@dT}fEfh!NBInJ&s8_4NONnUy3~YUl$K|O#yw0NIxJ&X#Qo%q~Lfv0g{4=cjo>AxLP>d zecb?*lU0T z%-3p=cbG1F$49?(#%lIV;@=*WJ`)@u)`F2X&6`O(-<8+Pw2TW;ZAe}qt&(oatiJKt z$L&otpZ>8{#9C*F21WXDE`fWAi1q-71AQ?y|K@pdY9&S+VQp`GKVqdOW|G@kx7I>Tj*ZPwO&Dy*~n0`)kOfg zpuSCt^Gaf5%ukS)GU~zK6-rK=d)}Q`W`tS=YdR}U>&B?1$(Q``&A!!Zc6pb3+Nh}2 z*X6J#tO?7&O?RC6%ze_kPp@+-xBu}l4AfI!v<8G|uT8wYGw|MEAADlS&riI59@8oC zhFo|=-GY{nJ*x{zGExREy_rg}mz_#-0;6M=VJL*}gc3u}$ z*HL5@n{{Efqt3$9Y!q<3QaVAc+36807$eP~Sw!G6dsQTE5KTR?-toes3EXsUu3!(@ z(_`5IZ@t_>oL6ST1Vb{&;bSP11TFbQp{|l&mB>a%@{B>mOuM}2g%ZfGNFN6G40T%g zr`ZR*f0G!J*~rB8zdZUA%I$Wh47}1b6{b~dcC+aegJNu1nE^0~&ePQDbC=)}-l5!M zV;kg)XoRUY^z)ynx9O^;{!h|m4H^r^HTOA8$b#9}YP8y|@q`Mt9?yc}tt-itiS7yC z^j-mPPUp9)vu@F9UOVV-(0R8y+BXA3-Q-1LW(YNW9%JYcH6if&9@J)(Dx3jUN-I60 z{SLuH`qo!3E!@sJ$k0Rj{ea$xx*roJnKp& z6T|ww?=#fW)XQiSrO7+@VVMPOO0@TvgmJ0)i;j{H@;B%^sgVw8#37U+d|plFq1OY}%K5X~=?~7|+6x%SRx?FfzKkd2 zy-KDr^%hlH%+Gs1Vu`E7*v`60t^Yu%my24{p^=Y3nWWqC+}RDry4j98vm+6)EShem z$wio)H#OjzPNH&_E7?q>HpUP0tCT%MnkdZmtB}7kE!QmDiXV4{ZL^52WrI_qghb`Z z{hqkj4?Y_jnsmQn=CZGh9~%03PwwJjFfxYA@3nM~g3;QKWMDu*^tj@cP&kz&R*UzL zjExpQJL0dSe25iN#T?+$f0kc#r8h zq!Jslq;RWpO)^yVP}*p##N%^pE+Y+OP+#H5kvW@=d3RFWU&e)Ek3eg5t#-j-q(+QB zElt%337vb)iY#yVfWNP>W9kQs!CBcKDTjMYYd9=3HI)EBj-VDn)BJ18xl&B6qX2is zi0M`Q5Iz+ZRww@5mW`+eGb9Nne&*@2kj;)H*nS$5f z=Bzx^)P%0z#-HTe#QKb|%9|v;*azvKuFf4|miYu0V4k5&*62Ta`s|Y?p{y80O>C2; zMD=2mmg;%jQBwdXKYx=f{ga5ww8cvi7o`*T5I$#(+wYS6Mh-(heCmoqoaeT5qLobj z5q&i^BLvX-&2`On$+I@uOJ(if@uR0w8V$bD2zs}wn&gn?flj3ZCaj&lCbl8hiI!M% zMR9{Kn&m?qQHb|NM13$$M84V(?hUU*l+II8&JreqFNRHN2ZKFIRPyl$Ck{i=xi+u> zPnAY;;q5<)NJ*|MFSApWYC2P)hPM6EI=>1dBU8yJqFJd<+20P4#$uYjMg~2Dk;twvAH2}!JOQ$k-nY2qJuGq z$Q$=Y6&m-}&7%In_1UO?M8Ohas!fMaogra301%anMPl1)NG9EHbtL4cV4Rmtu5o3y zWKh@R_i3r51&mViAL`G91&*F@Mt(Gixj0gtRb3zUP-av!BVoA8Ncoz2tVhL6y1dTc zx-Z4eB;zobHvEvW5x?dBh=bQy`}^dTCIT3Qz=eQVbbrs%`wE;le*4gMNQze$wH+UuX_}=%Y{A{`y<7FW|wFGc~cX;^SsJm&KVG&E-qZ@ZZp; zZo=vI4jB7rpN(Jc3Ag`b(q}2<``#g}z3!8nN^YPaUS!|kR}j~oNL^bX1GO6Pv$eJmA5Ufb`YJ0s^!4n}KJ9dB9 zem1y2bwkPEnOd`Vjzg=^s1pyZsJSIHuQsW8S@o|`J;)5$J|YZP_zXti&x#-{ycG8I zDc=Mt21GO`z!D$diFdO-SrSigSR%(iLBm$DwT_>qWL67~WIxsN5*F1pt>0r{ z(SAbVjmP*m!t*GLcJj9cSQsDy?Kvzg1q8A`D9eg&SYfi{d3Wn#xjn9GFW#n8?feFj znEXh`Y_VtGrBq*4AJ4ETg@w8#`DQ^aPaS&cwU%iD%ICLNn9}9OUPxQRPyDL+u5-AD z>jOwz-RcoKj);%mI1tfRXgK0JY9#meNRoE%HKiIC^*hFt7)j6G&t361D2SiaAwnU! zl_wjlnBdX+x?RP=IUaN@#sbdf6SDVTR^KeKzr%LSO}aDVP%A?yzc2i9g(p0PTypw; zbI(NB+()VJUYmWUb47a_ujD*WC#7z5)QZBVPGRrmT_2LlK0I}Q2m;<-`M4q-5sRyr zj~bC6q^kk9_(X0=+|I$fWVMywP1IDowrwAEVzfZg`cE~bU7(3%{HZvH@#Y{l@dH1> z!hLl|ybK54u!Pl4`Vr98T-Ie|ImD`{mN7BW5lNA1+kc8++W47lMUmU+q;UxrWKhY8 ztS{}IHp8qLA(+!(Xy3k8Au(R;L;Ah^mMq{NgIfft@Sy%Xj)dv2R*JV#BG6E~Tt!6R zDeBVX{_I11s4$Ju3j$J$ABRUb|754<>;@z3-xhl)r9Q~5IQUf~XJ<5)pIDIUlKBxP zNXO6)250(REOq*y^OpmJ-WN11J$%_#Y3tdZY@R2 zJxumMQO=w)z9}Ks#+lEq+|e`h(MflCduRF4igGaqQ}lGM>U_~KylFeGV96w2&2wQ> z=g`^nICewp8ZJzSCFM*mi&sEAMF}j&%H~g3o z4NMmEA8To5iM0`dM@5t{qXT7z1!afvhjJvs-|dg55>$w*CO0gTud(ju!oT;6=&7b= zn8nsCHWCeZzZq5HKfF3plBY=Sd_qZ%sUxbteDOvbtK}ZsD`#q&5tYe{w-|1-=fVs>brVANXNeCBejdec8+ zoLjHlJH%65GwZStDTa>?qGD2=?a^+5Mu${~u`2@+jnC{47ox6@UubA-|Q;mYUv-MqhX;xPd);UNa#~ z0kRru^S*U6A%1r^H6;80gX#;tyvE*mWr*EN;j`p4 zsPez~mvRUL@IvY_bJ&ydSddkRI=MQRkdnDV04I+QLD`!yh?q3?_T;<&+@0az!Pist z$T+$l!frQw93J8A@`dZAw&?W+7no>XVlj?8|7Md`Oq@#K^en91oX^ct?cWTVw2yN$Q* zJs+2Dy1hAVwu~Zprq%vaqQo43CS=I)`~Si`(kMz_R9dkW_w?u`mwrMmioVpX_%Ojf z$xSZQhYE4BRTXT-r4%B&3b{|a(%A7`-J-11B13)?o`m?wxp4xqV-9-s|JU81G~U0} zSSx=fOo;Ri&L)r=%da7E3#CeAf+7~mXKumpUn}>lm(2XF-KJy6tRazNJTQ-Qqp!rP zU{b{njQ76i#GyXRLJpSW3m1VFnK+IAP!A|)AZx? zT~SwtBa6N1b>}kwvmBS9!_{<{aK$2quu-VO!z@|pFJx>8r6{Ls#<)>02WQ)!rv!3F z^ittl^e7W+72Z!g2Ux!DTTKgxtV{{Z$iZ6N>v literal 0 HcmV?d00001 diff --git a/docs/screenshots/claude-multi-account-status-items-proposal.svg b/docs/screenshots/claude-multi-account-status-items-proposal.svg new file mode 100644 index 0000000..50a75eb --- /dev/null +++ b/docs/screenshots/claude-multi-account-status-items-proposal.svg @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + CodexBar + + + + 1 + 32% + + + + 2 + 14% + + + Claude account display + ACCEPTED DESIGN — NOT IMPLEMENTED + + + + + + PROVIDERS + + Claude + Codex + Gemini + + Claude + Account source + + + Read accounts from claude-swap + v0.16.0 · schema 1 · list only + + Menu bar display + + + One provider icon + + + Selected account icons + + + Account 1 + 32% + + + Account 2 + 14% + + + + ! + Merge Icons is on + Turn it off to use account icons. + + Turn off + + + + + Account 1 · Active + CLAUDE SUBSCRIPTION + + Session + 32% used + + + Weekly + 61% used + + + + Open Claude menu + + Refresh accounts + ⌘R + Settings… + ⌘, + + Privacy-safe labels shown. + Email is never persisted or used as identity. + diff --git a/docs/screenshots/claude-sign-in-synthetic-proof.png b/docs/screenshots/claude-sign-in-synthetic-proof.png new file mode 100644 index 0000000000000000000000000000000000000000..71e9805f70e41bafd2d75c723ea945d5dc9c8dce GIT binary patch literal 31238 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

hx3>a% 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 literal 0 HcmV?d00001 diff --git a/docs/screenshots/claude-swap-accounts-synthetic-proof.png b/docs/screenshots/claude-swap-accounts-synthetic-proof.png new file mode 100644 index 0000000000000000000000000000000000000000..b24d8ecadb79150638633c7e8c91aa31ccb4cda2 GIT binary patch literal 161047 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�i-6r!)`o#C2ag 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%0Ap?-!< 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 |;C#j>>XU%K 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 literal 0 HcmV?d00001 diff --git a/docs/screenshots/clawrouter-settings.png b/docs/screenshots/clawrouter-settings.png new file mode 100644 index 0000000000000000000000000000000000000000..46ef0754aa0cfcbefaf3ff802563db2024a6e98b GIT binary patch literal 107227 zcmc$_Wl&sC^!JGdNnjwjYj6n?2sQ+VAOnHmFt`LuaEAm7?jBr&yEABT8{Az6w*dxU ze$W5e+I_LFwzg_t+^Vkbb5C{OzPIa~@8{f5RTViLY;tTQBqSUKdFd}mNT?}DNGSf8 zuU>j?h3B4;kg(gVrKD69q@-w79UUyJZOxI8#8|hOHCUcEUnR8$?D$;N*nj{ZWv1@N- zqdrHr;4Nv?-d}0JFW*$@T zVnH9+{SLFWu*i}YIB6Fc8B2=X9e-EXd+HqboSVurW5yd_Aljb9+T-;@28EjM@Oe4v z*=}ESaD-BJKns_PopcBl(6QXw;RkW7`wJllt3R% zbwY;G$kFqQ%*fD$zSq6flg(&ts@9?*d+b-?ygdb`{{}YxP*Je0^k@|N!QPs`;brKS>yu>Uc+He_;bgL1 zjM`YUfjAqt?{NxykiVm~k*WkIcP)J9YD4D=C|#HOPT)-qdA0WQem(h&1v}eJm5qfe zK`1QvLOLjWQ&oY5?i&sp&DXFJ$q(7OYE;E~#lUIyX=Z+6WeIiYu9amSjqux1Np7i1 z36k7lD8_^`%oWb*EbfW+h$Gc!Wi;|$h4dBEtM~|=sKK5DlW*^t-;?mTy$?tMXmefg9UP4zoIwlk{$lQpX5$9Q|Ozwn7-Qg1nx5 zeZEuveZHF+??TLxN)$u*px%JX_Umot?dTdpo!2_S9D1(hwn4V>N6HIxj%Y%tLM_X0 zn{AuFG@CjKZW|5~Y~$>R?WA7VY_o5JhHi$U*;EP32qg(8iLi-q+4R*&zx1+_vw5=D z5IGT*5^=NOs;Ux-g)s-oEPPr3HOrG}bhDAM@+5po#7@9vcVUfWVP{)nlVhz^txyG) zFBkp#!lPkae5Mhm5mmDM^;T5Q3D*bLa%@)!$H{(-Og*FYpkhdERLf4IJ?~B@vShbB zsjxx0T<5r2Sa(IkC+E)bs{Mdu20Z#T?NBuNgP`9Dv>Cu}grgq$J~EMfhCG8jFHJWM zl7=#BkVe7}w*G6?Y*X+p(JBKd=Kz6N!D#G(on6gqJ}6${fi zaNdtNB;S`k*o6rk0B0Evpzt{OXZRvq7G8f90N2`|I~0FUOFHr9%Ntj6XVM5Vaxz&8 zdtO@sO5QIYOi0ZsW+=pXnJ8MxxcMr0A$Gq$M({Ow)i$>6I=^^TNjpLZZBk7)# zMweChR&PhUUbnqopx#19OM9(>ZV548R&QPHVQOPBT)krBH6CR`V%9iVF?v$k9?(7k z>GGYISflGQZj|Cy4kiA~o^RmV`_c1bg^TD8VsLO(;mCP&GxId+{bs`)`+e%06sOo3_gG%lHpyfotmTCxtfcbDbx`959-5nX{y<;AO1CZ zr>~)RV>5U2+omju2lryN)%#U0AotUWN!~wpVz5pwB(QNC{-wEKq@e%pdn_mx1_9)~ zRLa*8sI=_nNiTj9vkmj%yQK_+ZtC5p?_omY@%nLL@xgHhagEG?qNaj`!nRFM$Khs& zFOOet3Ze>v@@EQ_&vHE?_Yv?wc)YiaFL{TU6uYU6Y;>nm3^Pn`x6Zb|2H)7fN)|1Y zI9#{)v;6rqD^HSb0^G92LetDwpSu2G9y^HWfha?#P$#`M)AHWzx$SLxTz!pQ;#kR5 z>7CY;mR7~jS;h)$z0yVjx8rr;H5ZIog1Msdj!e^3^*@)sQt;qe{n2HYW>g9v!P&jR zU93w_K_Q358`L|D6M#Xwoxthh17}u-UwvmycHO!nUFq3Dw5E8{kFL2M4&{C^;zV{RUB7%j<+ixD`)ntN7P>@ zjQtIp8Y&7O!yDhuO#PVd;|l+?zFc}axQDTr)F9S|=d|H^-+f&Xj!eQ0zG!yN30VDc zT{FC+uJxzlPuu6#MeorkUG*Y^z0gC~Igs;$+lQ6!P0-2X`IW`m?7b1?#`HZ0kChhZ z^dI+&8S5fqZVacZhmohpt^E)|=PbA9(SQ+*Ex?>ux9E@`$8!@rv@gD7P082hsP

rdR|K4LI=4#@van{BONx0z~2w@wgU*b(jH%%*; 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%0DskE%N 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�ypQIEX-mPL9*r*#U4`&b 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%0Ac4B zN*4MIPIo*xv^C}Z9H$|x>@!xr_Ee3%-RrW!P4L}C^My8TAN9BDwX!xxzy zqe775TjPJNfKMsQ(foKJPpeJsVi8Q9kPy9i0xzls=F58Jr#^}Lslu_|qwI4^1-50p z2=J=}*xl@9*88oWM{@o93vi{{=Jv>@rY5ItZS>bw>@~6cmX$EXs$M8B{!HzQe-Zqt z%h;YLf%3~cAucy&8YUV0$uIf;faM}J*yU5Z8yc2f0MoOJRT}F-!4~kNIQI4WNA#Wu z$r4VskSSfre~71yHj`D~DHShPWf4F$U!rWbv;2oRc|fC4Dayf9`BL$1Rus}Q-3#I( z8BM>~MYUq<%?kel=tX9c-Tc&N9@7n~NEuVZ!?4ZJmxgjTllNuBWd6%$h#^l-Gt)@8 z*n?MD+S~D@{f*}}b|t`>*>+kkeDh}{Vyoaf#kPXQxoQ1dFgMJ%-*T%>B&+j zi}3o(BNFnTv>XrZTrT?y>VDaQ}0Nz#&z;Km+Ozs{=rHq0e_LrIDf6o$$2rmi5{9d+wtJ@ zjR2ZHZh;86^x?)z`%c7K!(A1~mi)Z*V5$^3$dill#eO=yAIFmUVBGky`#b^`u#G1y zGBSWmBvFfNEh8-d=hXF^3}FoXBnSs5x82lcrK<^>J6~)xojc5#cwKG?bE);{emY$b zw53c4Fw|Jj)y-WKs_LeKgCFKXYAobLG=C>NqM4zx2Zyg_t(E=mkmGisg+H>~JDLC5 zF~7ni4@rD@ABk8nxUAnf0*1uJc0Bg>E5S-@7_t4z4P2`MW*;p}RSDH$iU7#m(ELRX z(|<*%*C>0Xg}j@c>Qxz8`R&Q8LVFP3&z$nUYPUaC(Ivm~p>UkyDx02tr2lKt_&uf8 zlkX#Ywzuf{?xjX5v>Wi~HrgI89cuI~`AsPbR_fQcJRsCxM7Tx`vUX!%M>Ce>?*HMM z|6zTz5q5TW4=t-aFEH}uQm3F^&CT!=;G5G4h1&D2=|kmIs!LuK=BHzRknlu zMTAO7n-D@Ja=$mY<_S8UMZzsdfE70He@dfY!uxr;kI+O>CJTC==UZ)aR%=#SKc7M; z;j5nC>7h=K0~3BDf!?iU(Wj1|M3D%4}H$Zka_aMe6%LAlT2P z+H}9ocG2{ksFRJ>RGhBP@7DhP&~nBsuZWwsu&}I6PM9~Cvkt34P5v4@t#SXoOt+yC v>|+1$04cSe4?LR(GiCz*`W`LI`+KM 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 literal 0 HcmV?d00001 diff --git a/docs/screenshots/codex-upstream-weekly-exhausted-session-misleading.png b/docs/screenshots/codex-upstream-weekly-exhausted-session-misleading.png new file mode 100644 index 0000000000000000000000000000000000000000..cb8d287ec35c1a263654979f5ab802221861e77c GIT binary patch literal 31910 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

=hr|oa+o#l`Sm9=P!7AzWaZp8_3QQR`!?? zPu+qz(0dPfJ_PVj5O^rf2wLNb-geYb-!w8j^KxeYAH^oxJ7Fr4rOq0S?$aF(@d}70 z8Mj>ZifJ}?S2uh@E?b(GL7G?)@bWEVIp+ON8Q@24qUl0st)m`#aY^F8^qG%=zd?2i z*Q(Ho3bpWsb@vsG+nr~q!uf?Qk#`8uq3VInlhk~96*J}y{2BxtTx@sMJb_F-BYYrjVY-?{F3M*(*E#ouq_6Ke-|}=`X)>OFu>NNT4DY1odxC)&?GQ!n z3ow2}LwM$3d=qN(4PTP1b8w$j5RhP3V&klALBR`HpNe_}t?*y)?67WM&U+n}exohI z|M_ot+xp||d#c{l7%5hL`?y93Xs+dq&m1tQ_FzK|w;G>Oril;|BbLH0zND!Sif0=~ zI?F5TjW`-PKC#E^w(@Qaci!xx=L<5HqHxO&Usz_42s?h@MPX+8dz7-KEUs;1TQ5%H zRp6JRe+&55E<%k656#QXHpw;F85R_Ws|wqoARTvw7kMtl#-T~wej7U11Q-L^+*%6h z2@u@Zpm!tB5Yapjzo0zd;K?f@8#a==>TYnB52}F6Aop2<=Hm->C$#FT7CgF=x7l+v z^q<_e^RM+b@}Gk-Jy-nYJhJWV;Hqek^@kx%Au`Xg1=j5$he4I-Ff}C_`4EBddqEKT zjmcDlibi6V+*it-wshi-s#2cqCE^X;8{Zhjz}NGkmpMz~*FoR`gT>SJV zNUh^dKJ2bZ`nn3QcPkUD4kU=OR#|`f7`dw_E=RQ9c`lQw(lhVP;Ye3D+uFUHnJKw% zK`t*$!(z?NgU&U!4yTNZ(n`R+TSu6GzKfM4QHH3~5|{oJYOmT{pLV?sxwG+P!AbkW z=#MDRpfjPHS!-MBftikI!RPlsS)-d381IaIpN%MsgR64G;3fKe%rJvn zt`ahyUrdRO^Ts8&UhUf3KK?x4|Gq^pX7P=@)x7Jvq-^`FMpQJdF!)WH8N+w|Z zcmo9c)tr(dZ9}bCZU~*l*RG{Il_#Nath*Itm*uQXN5%{U6w+4OWX{JEF84Gyt*dcA z{_R5XuM6AE4lJl~4gKZEqMtN1CpWd-rQA0Q!r(S>J%Y8xhb>M))7|4jVIOJ3q3B`u z)+YtKgRWkc*_Gb@S`b!Qr|*=Be_ijlrDaEm*^utk6XKj3k1RyeYu2qYd~Yl~S!cPB zm!dZX%?$BV#QEvaX2dm8eAQ?IZapeRdq2JT)kIZDG0P|Docivet_ncZYU>EqPJut4*)mjPD552JeS5GbOVZ%|2dc-D&(Nh<=<&`Fqsjrmsp|eq9q+ zeWkjiN*yAwm-XgJ`=a7pVe%s-)Ebynziv3Filq43WqNA0l1wHHP2KP=H&jYLm#;yP4V zefB}=#<(s2Pwx8HOF{DR#||APUAj%J)bC=CX!lTIJxxhFkr`3)pPf6!r7zPd&5hIr z7(e_)qK}MePy0@_(J|1EcY4N{N#q0(!X!*4s~s)KDP4037t}8h>KbMP6;C7*Ux$q= z?5in$WFzVioVU)3=+PoOf?5*zeMy#5mtZnmr9;JXH7wHm(Z(4=R~X&MbvsY#xeL#+ z?PYT~)>(2o=%&thv0s5rX1G;m!E;9+*k}Dm%mZjQraUS73QE1KC>i&;<&p?PRuPgX zCHZ`9d+PYNU9IfHy9IXMhh>7=Mh~^-UdIE!ceB85`ERnkl-XtX*w1CF>_#U1PiHi9 zUa4$T1me~xDiiP>Eo*FUxD^w>X^Xxtl6ZM;8l`GNqpvLcE;Qf4*hrpLj?cPNOgQ>X z_`3v!@s}?9)3G(lJfQUM{nf7Ch?_Pmh6fC&1afR-^O+MSB281b#nvMlZ7PG0BD;|f zLHbZt-&;?WMb6~5&r-}k>^Q&0>&M3clu5uEnYsWs_j08vQwrMp>ovM-xr5yQX3eTLJMcH^ml8xU7hYQRlRges zJ+VAXq=+DLx$Dne8@DTx;(}Y*BZK#IFJ2oAPW*W&m+HW9$+S>r$ZwX8qMK1cvyXvr zD$<9WwvbUqz`qU^`B?6JUUcG8NEtRpk&b12#(9~&CqCNih89QK(ti||?g!s1mLH7~ z7EipQnlA`gJ4UtG50osRKn6WfbUe)7*vit@wl4+SD~Wi;V`hrFX3Q9mj5|`B>McB z({O9kw)LI?9Vx_jF{__^j7~AHCw&fYo~lo6a+E5K)Pd(u_`+@WAOd;Kyc@G~F|N!i zgTt$3o<$HApw}-byl9*_=lq+qi1zc9FX}dvfXZn zF1RlSjaJ{q8YVk6n*)kpOLkPauPT#6j!%7i+ZvuK#|{VswBt9y_cWJC8RC3A9RhAc zute~#;_dDxewED4Km8@Vtt`Wsn*b1X4jY?_Ea%PNpB~E^)Jjh{ZNh+?E&n6ke>FHd zPAyCuLX+po(XJ{JYbi)mh+rR`a%tJ)Arm}FDRN{_Hxz;j^neC<@;_5sPi+ArwFk$1M$UW!T_ zf-yJVc}u#FTyi?OS;*{HZ@kanJ9_KU`S?u!CNYlt7!fa8cq z^){i36L{0M5{`~G*}5JoNBCmRW`Sf!LO8#33oV+Wq5On5;5ApePWDN5Nlv7fJCOtD z99?~%aA#?Ge(=@VD`8S60aR;ryXHwV00Nfk2xB1RCyuj5Kvq5`)Omh3f#D)@_iZv( zqg~Hx2TV|6KP-gO>=0DF*LT&FcIBsPvuOY~&Hls6<40$t0=h9E>vN7%NlH#an&foxjX1rDZ-Ok?}Y134jR(~Yk0 zVrxRlr@0=_Z$+piAP@;{p-=x&ZF~sOX>=i}(H$HF(A;Mf=JA|~6u&0j90Y@b=DH=I zWQUW;RjHUA#7$xxWVw2|*xx4em6Vfh zGq9b_<_7uq#q}mR1>rsW08F;EEpEXvMWeQblUFH}HL9V85hfpecQ zOQE%oRvj}@ci5`v1msT~;> zI)X&p@=oBBZbXE*eRj;I9tBp1#zR9pG4d4O%F;vecqqj9&Hyg*QV)ziG)Ia#m=A$V z$?Wp?@CA3Z3J_L=urYv5v@sEG^swo!(sj=DiwHce8O>XbcViqDn>f>s;0-rkudkA( z4@9)rCa$Iv)hZHB?uy|^PJ^&jQGz)2GxX?`PTArT>{nl2%#NWXuT21+_?T|?pV6zh zwEFFjN(@}#cKonH-m>0YMLE-TI&+bIGs1PLBIUd=4IZ(V=~eDPw-4$nVaG3G{fH1h z`Xa+jTzf*I$wjtby=;mGi>ph)QL#Ihw<1{R4pm5cLLl3^H2$0?DQVR$yZx|7Buq&K zo)5Nci`F21QxcLk6~N|bsr&${Yj8_D(Kx!`%~~acd3j`|zSw9aFgELal=AzM%&`49 z_xxzBy_dz)rl8@S5^$9%0x_A>bF6Di%BYjLzt9Yh#;wX7F5=rKS6=c_?}xgu;u%u8 zvm)D}gr}|J3I3O*ss$9LZ!sFf-Dnh<(Tkgx((Hg^g8&t0{u(r2W6^pC7m*PYcR! z4ue3WkZfP>MBj5?r!kr0OH_FH#>{iPqGA}pIKE2DSH3W%sHFalPnGTH)t>7`X)Pby z+3-<)ZBxLPSZo^gGOE60K}UbL=d!1A@ah1ow`si|3g-vz<#P777+muaxq#o~^^g(A zRufClU%vM2d!KL0eh}c5SW7<`xIzx7$VP_R2K>2*vKT(jn}-y91RB_bP5o7E1Jm4B z^&&vW#IlNd9T17v91y=ln-3xq?@1Y{D`^-eOf#0g{HNC;Y?q5quh(~r|KxH0(VvZBX3jPXC_0uAoeR3)gk{tdhb4AO@!wV3;|2 z?Aec`URO-V?#pC0?!%|#RDo1e>_RY$L|%ysJ-+E;(s(O9ccfzWn~zV^@K&bCxVhT( zsQW_z2uN5&Gddn%9{JEzNvpemrhY*Fv_5-x-ixiNs@EHu2Kp?9JKjvQ> zj4ebe%@T?Z7;<^{!0rQA1(J3@_pLnAENWVt)P%~+6mQNVUFgn1Z2@ZS#;JgVZAj3+ zv68)hNj@F5AuYuXQ=~zp=s&I0d;P|hy?@l}xjgkG4c-@AjGJ!hZ*a4_6^Oz#0iqR^ zE*KPrYOIYv?YSsmHvUrH5lx z)(0uSGwij}aMA=b8D9;unIv)^asUTfR4(PmSV-Kv7u>b6)$+9wk~dPGqNJn%C3Uho zmSJ<*-z*v@0?*Re{~(0EZ)y&>v?9boVO@^3iV1_Bfl?{h1yZXmr$SG^ry0qn`g=u0 z=%Ba+^-Z|Bl7)*)QE0N8 z8?>G#!1|${7r9?Q{W!Z^wyg%}%q&Rw<51s6uU|&IjDsbvky%Hdv04Y#EBXb#EyvoU zzrLv4JRK3&`DE*0BW z^>z*zY+WZOrxYIRef88Ue9qD=^QD zbcT3bjyjQ;^31;b8Ju>b9D?T(z%=EUXS`F5Z+lg0i(Cj>saf#%q%SH!=Xc*k=NVxt zM!zjwnq03xKknZZo$yR7OlRnS`$qql7rkf+gPzU8(3V=W`m~pWy}jU`Wza%|B!j#? zH`+QNCarb%=lXXJlW(2SW3K)l$^!==CS|s5OT>kD+{;<2e+!9B5`M8P#U`oWR8A9{!C3jpq z8b4A!*S?=}9p2_f&g5fML5QsI!}rK{;uf|kyavsXD?t}Y&Q|?J52iQ+f(p+q&Jt;+ zf)@anQoQi`r0TDo`X!%LG7K!*M!s5+L>$E}D>2U;e|I&rgTxO_r={Jl7_qGtExXbq z-~##L%SYsoeC*nc#SlMlq@%%K;2e_vjBB-`k{=F`lAjEkEt$-U5DUPUWiSKaniV+` zbP*&D9%y=N$u0O;_D!(EWD`3B`nEF8czj|X0^9I(KhV9o2oUp ziuCjF?9d-rE@u~&AV57SMA58 z{Gz%iQuW5*U^A#pzOZ%ZB3Rs$Zr{dYd0V{!1)9xS1`e-G>376^(Q~V>vH4UqojItLt8btNwNE zwAqhrro7X;%wOpg6`PCBzk^u^j0pH~C0}OztLrZ;(ZL=LE&*@^43gw)uS}a3NR zye~OElCwOKj!*^c<=De4rb#Pa<=KYB%@{Zk=FtzmFZucAddGpz=r=iuM6sUwVPJQ? zeDsu7le|J8p!OXJX=*u<$I=MgzO;Y5Y3yw?@NDw(DF#LHk|b3rGU-2adzx>goa!>|?9 z4(E9WY@9A9NpuWM&R8&qfu^HAt{@>Oy=pE&1qw8`4gMn5joRywr6!7~*dVgee1}y( zRV!wOWHQ}+njAEU&S80$-LCjVghCz72G~mGoCjcQgA|pi)vj(q4IEXaYOf>aRS;*| zTUXd9yNsY2PXBHJGzJB8akW_=EHgj?DL5w8fvS{!b)V~M<+w`EE!i~qhihhn5K7E`Ys-Nt zhtrSK$)#R0-{4=u63>D8Qv3TofdK1c+ zEbpND=&qI}NkR0Sg8qJpIQTUSXF!GLb8BFAY>$@{wZ5po z{p(ZThA}7Y#)G3cldD%q{LYJd#9>rWhwkisu?1xAvVOjOh>p#T9zEGbsb8y9&kxi( z_DoWu2#ji$l-PClo38GxOEsuAN$>C(_CeVzF|S7Xm<+z=0=0_%2d||v-){x0S<*Yu zYNw%bh#{JvqslY!!FoydGP6~z)v_|VA)Cmq@o69+pt_D+o1geIhhu-7@1K{_t%~@1 zy8Yzo8sM<=!z$WfPzpM9L%!Qez~esB&;;^dLoc?S=xM5fBTeBU>-;bG#@NNJUeANv z-^Zx3-^b{ZDyv(0^L6=oz!anaN@_nscifCuTOrRu5Eeo!T;yscRt0e;9Sneqh(J@1 z|5A6gztSr=5O8Vc;M1OpwT-$~xoj(IXKs~)>I+Wwu}8V0$Ft}#s}&X*?m*CtY2u?Z zBM%G%yS0P)wFbd&$Litz7w-**ZF>yE7$+imWxqXPh6^}5@pNINOUzeDJ&QgGSP#%X zrQp-#$l<;YO3@&b9jMOkB~~;tx~F)XwmDy~v7X5f3Jej2orRyuL*49pGOz%9q`CXv zw)?_6absRXuCEc~%e1^paK==R=6qmpJ;g^o5ZTTKD@iE0)mfHrEx7M{hyv*=Kcsye kw7)uP#CUELq!`>O+bdiBm)OI9|1YQT|Np~({yzPG0EO?k1^@s6 literal 0 HcmV?d00001 diff --git a/docs/screenshots/codexbar-weekly-caps-session-fix.png b/docs/screenshots/codexbar-weekly-caps-session-fix.png new file mode 100644 index 0000000000000000000000000000000000000000..e3b6326920d7d33e3c4aed563fcd253ad667450b GIT binary patch literal 157215 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�FqrC~u1Z=k^W7AF-U-x^+h*vbiO zgNm(V-_F3}2%rR0{MC1JXks%1(jW+DGxrO9l|rVbzh{bs@6n={QZiP-oDW$SD^FIL zt)qoC=FUE`B9NJTy=8auv)l2C7A~-=i15d4?E_ZsLhmuC>SAmzQ)^gK(#m08eI+W; zC~Vuo-WQH1Vdi2S0orhYrHB6fw_c;=Qh7q<#DAhHU%h|bmowbwgNSL1`-9?3jp~3I zjcgWMPA1zj%-V1i=JN3Zs2y%T8aq9-?N)ulA{oWT3IW8Y(HEveT}-iY#F?-j9k2Tt zl5V$sfL5EW>|f94VoG-Tg6?h}@K7e7+kPU}B6omM)iIlHJpdHa0-y{Dp1D#h>4sUc zm#`2N}T>>OM#tJ#pLZ@Mv{7k{Via=N(6yI#477 zMyxF`PM@z1$2U8FarkX!?qYooaoVb|Ia~s|Q-Ubc5rH}o=A&zeRVFZNOF`HFiz_-ubH**z9W$v&8#EH7R1uV8(?GXUnC2qss z3pLC~DV>rZKxDC6t%Y|wUl;DIo_POQA9a)74#3jSk>+vXu~-=Be7G75{zW9CG z>a@EDTo%DU9ev-J75xa~FT35G^nCmV><_y$F<)D^ZA=>NoJm;<*yazRcTl|#Ei)3l zmnv`A7YirWoPMC-U{(_yN@hiq|9XwPHeZfjyo+*k%`|uPh7bjw$bC0QR-B)?8%V)y zA^_MeUV-}9)TKz>+Aq-q0oEW5Z`e6-{G-`yPGQq-5lT}3MCbQMN>6|->x`w$<$NJT zN($@c`I^P=+k0Hfw8Yf;|Kvyd;@u1x2&c#hWf

>5^gIUkH~_5XJle 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

6ldT*OFpAanRW5@fgz8sVrWPK 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 iCI`^Y^fRn@8U24~1>We<<%Y2U0000T literal 0 HcmV?d00001 diff --git a/docs/screenshots/factory-api-key-details-source-api.png b/docs/screenshots/factory-api-key-details-source-api.png new file mode 100644 index 0000000000000000000000000000000000000000..5ba0e96aa75ba4a1a7848271d79ffe15180d6169 GIT binary patch literal 59952 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%0AXcEB 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

@~w$cauqH*VO1O} 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 literal 0 HcmV?d00001 diff --git a/docs/screenshots/settings-sidebar-card-before.png b/docs/screenshots/settings-sidebar-card-before.png new file mode 100644 index 0000000000000000000000000000000000000000..d966739e816999932eeb6b31b57bd51274d4c7e4 GIT binary patch literal 434102 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

LVU{Q|AGb4+PMEPj#fU>?6g?#9a{^|* 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

@<;(qx=zvus&CrGvltnuAEd^Izf0xE>xbd zP}Nnm&(`K}QsLp!*717Oj}!e@B5N^ey)6l(wuoj!(GM^nb!gfE0C0zwFO4d$UfW~2 zX%F~^Yf9I?AVvRdeEIq$lFztU{mF3Vt&;!i5M&WtTgT(PB zq4KYHD!(H>&1$4NmsD*tqta_tEagwB{Rb8zF)Gx8%7pQH(%(*Q0&NQH+VU}Bt;ir6)He1z7@LN2bx(`O`tHX2GbavuQLwH=0 z!F;GEY^=xlz;5^6o_@R{6Enf%1gDN}D0RlzwqzkTvZ*sDFR-Tk%C!wIEjiAT53;>D zEa}xQ1(&W9mlXAxG~Ar^Z@1niDdC--(YEJ{5q%RP>jx6 zQ|<`<*!ZJ$LoCC$+2TAE>d#K!TceYRX3`9Aa6!T!6%MRwR!wu8Zib`HdHGwwl2qr2 zq}Bt}i}!q2E#4xP`j;GV)${hvYxZpIR|!ddomL8l1>{6v?Ei2+N@azZKULS02DasKfwjsIEB4niI29;667r-=}AX8C!#tzno2W#ULPY*da zMf|NKB*ws@wW6T!{);-m0-fo3Q3v0nd@qY!95v~l>Rc*>U^NZ$-vf-D z`E$3w#yu>m9aLG4oy-G(sY~2KF8X>NEgeL%C!w{wsiuk>jiJ-IjhBq`&Ca#>a(?#% zFH)y2W*q#mY8JQvVs^Bngu>^{*SAW)dp!7`K~aP>i+rO~5d=@B{zQW_#~RuWLi5r5 zrHbY|OI$Jze)0Gn03Lid#W>{q+d9vNP*gmg1TX$^3o*>u-qJkL-_~SU@L@L~F3>k3 z@b+uVNttk=u&M1aQ5#00|68JL6gTL;n`^hyUq?`(&VO>Rg%+ol!-+C;TA?jt~dbC_SczZTF zPOk*@Aa5~qA@D`9((&*1naXO-l^9QzBGDH=9G*7$7m43Nc|WqSa^ZcG=LNit1cK7~ zslA1GhKL2(Mgu`@-RuD^f$W&V~89g`6E`$z|HO5BfVqo$fqJ z)c4&K)G2tI!l@XZysO@uxr=+of)NjCBxJ$*cm$loRt^WM+J2;wAA%215N!6@v;0m-YIW`CHmYl$kr^%^>xDy<0RCjdwLauCytr%(!bg zf}AWYEiAM?RD6Xyi~}^Nm+2oVD;|mWsoD9UGk)r8pDNFwl4CUdninI9LnL}+zUWA##C1f;k|0WkFKxED0((C_Ok%A3J z^Xpcp*6_ryWuq8m#;IA6U9xU7YRTVO=eeygV!_5|t%}ACtEm%WBX0Jrh zrur^AsF)g~VqYQ}X zLlmwA2H6h(6K~Rp88}B^ZP6un?X`Pia$m_XMXyo!gFw<>CxQiPA!xInu9x+kXb9xr zfOxE$cguk-q*_-z{lY4{?}D=~g^UiaEv=19Cyqr4d4JOgT^dIr5A9&JX)SjB4QE{J zaR2EhIInF7p)5u(ldnYkn5-6HgJ?}4+IvE3`!LL38n_#8ve48tO{PYX&I$@PS4VVN z;ewe7QiiLZT`f)jAwy&N*tO=xgtrK7T;@`csppG=*MCJG+wM7CzzKbZ`W8p{i}X7C zIhkjI$}{Jw3Ib9LIp71^ixkEi1JjCRF%1V8j^=xR^CSb_=M7{v1^~;G`~=m({s$C+ z?xU5uksHX2E^G?;Ri3_s(LL(~-@2tx@iH8B+rX~^WtSEmX@c8xIEl^_h)U__f9SQR zI0CT8j`5i+4M`P<5bY)MC6UnR23JQDA0iSb1?^Wvx<^R20F4F3C3y=nbpBHgYW^xT zY8CM9@_Qx~Wo~Zu>XuI_fiO%wI8D?OW_`=weXBDB<;ATd?YfI4-Vi)u%`s_G_}S%g z;jTWNGU)=O*xIn`x?H(XWPoSK`%@D_RSEl2p-H<>u7^%=QkEXO#qLd%Ru9Z1Jx}1q zzNu9w_6cLO`US9}d0pElN* ziYxQa!g%auvh2-YgeVwjA$umpx&6SRyilV=WAn@KHTUq zwyl8>a+J1-u`yI}wp>lM_ZKG-3b zx{H(BKZd1V8C6mex&WMqt#ns@k~rLH;}G1p=Ggj0&Y+A?5gSb1wiF=WYcN^FkG;034**rVhCq_&dLgfPm27H6HYi8^banm*>3wkos?%`L9)y%r%@!8B0AxxS;( z))O2m%e{pgbF@Orl*;N0*P8`ards+dmZ-l_S8s}4cJKm-kcKxN1|0Chb$CC}N;tu6 z&FZmU(*xtC?%@R)CwX{%ibU-!)oM&PMVE)sN`?_89A6x<;Tx3D1xE%w#V2f2?tO@ftH0mGvk_Blu|w=Ha;hdp(24el0F!b|&i zh&BI|$m+G4BhINmhnbcKHqq;;L`dDwWhx@R8#Ca_l4=eEGZRk{9W`UzV#9!| zoJ+#xm`QdBOD=f!-bTeidxVUw*!~AXcU*AbpcnyP*o`_t-c}RO6a}4jdZZYL)36`T zum&GAz4T^~QL}@D`KDN{%)Tt~N@}S*f!WHdi#=>Jvc=+{@>YXYFyh?6a4Ghg>`9}E zs)Zf@^_Wixp2|f<@anOya3r@xQvt|(dmy~06?7`8as~Gu-SXW_#v-sZAQ)L^P)q_a z6Wi+esb)s2QRYk3XB6-?&3_RWKRu#^)S~!x#VaH8 zxhj?Wr6Q(MqK22Hdqa4OO~C<$v`g-df?Q5%qRhTo(o(S_5yiHfaIHLra6 ziL#X#vrYm#7wZ1Vyx21Kda)(}>j{rKB-H2eHg*sbvFC5ZAL@ENNbtT1Qzp<^J^*9y zBM47k91*5o zZISA`ruwl?0lxTLJWYNqTO0|kzl^{Bo_Urw=STmS^3y2IT=o0}`r19FwEHk;gl2Xl zUxc#?T@9!d`VY?icuu?}HIM9gY~lGL40+Tu%I29Q(eJ<5k>`nl)H^TZEm}50Pck{d zoZ&bK92qcq+sM1DA*Z~`k1QA+77yDo=iEpHM8$3zAi)~$k5PcHo8{V&z|SflUV2}F z*wv|OEcJQAD&acPN^%=7JL!h82~!g~>tDw?fP$xg(@^vW1VuOYZ_PI0T!KRR7ooRV zd|3L}_SS$GS8XLEQ7b3|K}I`~vzu-ie7-zN0Mu3#-aR4&^6T?!wPY(d1+{9@yZ-@M zEk;~ct;tfcCCv?gZ{cJJ5wFVr_hK%OuAx21iY+Hruh)V5oW2rTc5mqe@ZTZE#IswX zb-9q_I39AJaJ8LiFPk}lmv+}43D;?C z54qHe?0Xd^PgSau3d{>=rRcs|W>e*(+ z&5ME$x{@N9K7QPQbm}Vo%o;lpr(JvbL7Jp++xJW%GEErTt`p&`#J1rvqT@YM;6@QM zqA}a1_BB3GspxUFLhI26PoOUXgJ5AWRrGW}mG6J^oLW@+Cmu4Zmr4YD=Pr9Is`m14 zVyS#w2)ccIH8ogJCuj7p;M(m`-W_1q4LF+qX0a(o-lE^rf79Dk=8C=z^N*0?P^lQ( z#$8G=uxNN+*-3k`;V&Os)dQ$hN9Or<&f}_E?Gu8r+8ZKP`MJx9ijCK}+c$Y}m}-P* zxj>X40XYZpIA;KqRV36Glp=i<(y;zXdwGO!A)KSJrEj-gpTRgSFoO^-t~7J^Bc12NIKAuWu=1_`S1PPajhLKAF* zB6<$B?;5j%B}C$%ZKgNdQn=Tj^|3(iLSwD%PxVePXq1nb-y&&o0asniLBTaPY?jMT z8&9YEAt2uRr5ZG3&&PHh?MeoG4Hx^zMUfCsx}+dfa!#A_CB|`d)#Ehk!~G19Me)2~ z8#UO$&PTL-_?87RK4qc1Dq*+q>?ax+@-x1P(`=YHJq8Q3nX})KEMY*7vZU9H`Tui`x<|?e{{Nh-c^FL z&C`s?|4SgB3dSbv0HdXUtR^hDMifY`k(ZH3M7Q-xf%u-Ea}Omo3F{98@*&xMay$IZ zL&wkvGTGt4z3GiwR*`$7$n07- z4)1R=X3FrG##}3lp$rsGhbAWZTgGWBN(sTwFxp|wGF{nz5FlPcxHS^1T}SI4IyLJM zxg*#c@!CfBW5}?&x^T|{=PvQo+F4Piv)m^wnf)OFdsW+ru)g`!`9@G2K5ua>Jpc?+ zc~Ft`$}y}~VVljXZm{;q=KZ+TnhH+11X380OhF%72E5?@ipj#xCm4Afj8o-C54cx*m;O6ZU{7^qFI_6x%kC z{`<&*;Ehf3t>4F2E%mwE3@GTlf>w6YVShl}eJ7=eYZ|me!Wcgcpv_t$Hmx`Xfl5&&L$J2nmy1?948^f;Dyp0Wg^W& zpmG{;q!g?GK>bng#N-aWY3lSL3li&6?fug-3IxW9s814mOJ6y7gyVSV5`(f39Zhfi z=4SP`+>x11%_^TmFG8#L2j1*ZhkD_RpyhwtgJ%7@^axqi9pVi12yx%Tj;uAGnur0r&V=&29Ai4Q>ufTG29h$Q7|b^zdT z5O*wC+0b8|H(nxp*I>UHDK|qr$QGJieUu|PVnNxBd(m^V$o!Ozs)^5vk=xQ{ts{AZ zEdCbc4iLh`ZL#p*BHo}b$?KB{o1dZzpvO31jEn4>V{@BdxC-j?{Rv0067|nwwiRnj zO+qJC`=6}(_()ZcT9Vv}(77QPmz#$gA*Ul!9|ChPi-FT8KB3_h%L&mkp`}q9zTHtr zIV0vV3*^1!b3VA%n0>os3HWM{17{z|Ff7m3Lo5DiO4QICCaMCf50ynmKFwpm-;jmU zK)_;7tfOuNPnOP&V_WCr%1vB!FpXC=_3+>Q;5F8=RTmSgI`jAj!|HQg-%98HPNm)@ z*U>t7Z}%T3nhB^X5a3Y4s@YF0FCzXl+!T7~ox)j@aq>mU@QxxGojF;h(Y)iWDT?bJ zX!OOX@h+J(gjyeKsxHiyb4=An?1(b8k3*Wnz?use3k}Mc4hg@><1S6BxuFux;Vr^CAhaZGECL~shQ zDo_T7r}|L7;HQJ#SPTleJ`@4$_R`)7*$8MFj+s&)ea~V3F2b-3@*c`lvZI>OCrf7k z`#nLc6VJ;YU}S(4npSY6KZ5GQ?mF@8)F+mdg20GvJ7`U6farJD;!r5>lOC|sW6ZEg z3oam_AG5BFYxHhu>?>IB96jb67BCmje_Y6r-2GeR%~lPkB?|IpTJ!$YXPu@cM6YUs z-C1+9{3>Yanpa-zCdD7?`~wVVstxmV(?-FDIbg=wQHEhHg}$r=h2B*`-sh3xYQ262 z^3A--6au|Y{}_6cxY)M-n)xrjq}G+?1B5+2bq)ahhA)%s0e4>+^H+Y$?9`r2HjGq1 z!C56aHEMtix0HFpiR>*jDH7dO8>7f2r|${!OvN$^7@(f`A`#1wtc#yRTI}HHMm_ne z%Q9D9(oH-eAY@qv!74CpnN#pX(C4DJgovEhhmg8xo+6vnVO!-sL)Mn+!u9^{u@@ym z>+usWz?TZ4n?`Z3nw;P?3M<;cHr|KJ;xz^=xVvcaHkc#N8;;DUc2BG|)d@Dg!ja)z zpsjj3MI0pjlL}QLi~j+#Y1tJh+ECRTVY+Poar{Htp`|r5zRl6ABTw4B{tUN}yzyE`$YJ-4Qo%RCT=|a04uQ5wjf#BlOaVa|1%T3Mq9$3N z&@0@7cj*Z?m2Q?fbUO;isU4x5A)Ki|$2DM)htG7XO#k3Kmy-xaBvjX+Sjc`i$cCRI zGJPc@7Tis1mAhJv%pkpD!@+HOu?be%5TGb?)JY;J2NJl3f6R{38W|#k-M39^UZU^) z?(rxJ7esH>cSJQ~@H7IjZ64(i z_8L9zO6{Auyj`f$#zojP9HF$i+Y09(CM?wf%ULN$656SPq0X%8%%{~b3dACe2`WzG zd$8IY21{JW(OA|}Ag7b9AC?y-@wBw44}i+HDQ@mJrK^aFIG!`I+R+o^A_`rgbLfy9 zCbfE|syI9^P9I%Ol^KWH$&UZ}KO3w>R8Ah*%8uWvaIF{3j$3N1m|@f2TnMzJiOx%D z$z`63R0!ITGoY2^q-Ass8Z2f^s}*=To0V;J=G@TsQqs)35MxaR9UG}Won1s;s>6#O z?);|~^ z8g%d{IKs)5K|v{*lnGamAeifp0z1o!8uvfy9zBQ6K_VyUfXl+zecV!(LocqwistiW z>uCMafW&koS8AuuA-)2o^-oE9b)#wtQ_7RqiigB$>=uh3dFm;VlA00D%X{9U>U5cZ zy+VSCikws6nA&Vj$UGEU1q)Qr6ig4Hu7LukC8PduWrK`?J z2rqFCzCqyCl-)cxBUeDs+(U>4t<~R&H;h_~Y(EoTAK7xXn7az0Fd9+;(Eb!XUB$Bs z(oHDDnX6ayCz4bxVgR-vZ`|ewWTWWLk@d%aOT71bX$N~&2=w2dZH{kOK`h^%P%R}Y z1F;WUdrGuAz7T`M&hNRc<5bJNUn`4rv-S-Y`RAEyFW*h4ZpnE?<)5|$JTLmFX$Vd^ zRhbJ=T1wv!9#_XIp*V^ol?7~_sfsZea<9}iY(ia-+3D9GeB=MU&2(L2*F32YS3Dd} zWJdE3`cAc<_IZI(4lNCFC+F$N7T16^hDWk$EZpHyKXQ^1IgZBd3Mk$J|tsv6aPfafgcn4$W8UZa-Nnx#6Onx>&7q%EzBK*G{K} zDR=7;LMCbqjKyOaOkzbzY3!|smkWTTk0iWej!PdkNUKhnr?$?<$BR(cQ=4k%^$56E z=-Gx@=fILUNI=Px$O3NW_>%V-Kp1Y$R-yetz+*2WtDP}&E%;-G+Du6VR4WD=JYUHz z#h0@xQ(f0r=fogJbGeW~2|gt=Lt*t1--Us{ke+r-JJss|7w{I|3QLYdYBXX~IEkJm zphh{t)DT(gBgD^2YdsRqX?TgC_H_F`PR*1xr1o6@)e$rP-|}zRF$qNq8P%pWY$0pW zRUlsC8fDLp{e{aFX0rnQQrUD}u*-dcIrv;B;h<#*BnPA?9Jv*vFhdj1{It(0k6`I` zsZ=FsIM%yIn|V+To~_lCL*}C4e!RN9f*)@1eV~2tHEnh=T{$Bs*3v-rNfWm+D+P^i zJT)U^BMP{a&D`iF^f11{dPzBhNrR@Fw=RrZHuw@9>j5($wPN|e;5g(J*8A1a0}S!` zXakSpoV+VnM+bP4Dsv+F<;=(chS*9`>3^#U%ajm3{vMu^3bv`!eJElUZ>IsorvG|` zyvs#E)t(IaSk*})OW- z$~Cg>FyA3Zue0)Ju0niC#dEhgv8=JGCBMKFOj+wCZ=o~kpZ98i8s8f*CYE^a6Gr;n zg{N05vWHLO`br;mmHS?sXY*Co-X%;YxXk053q$zoB5%WMD5c?%Fgu+g7ZTe1?6vXoW6(O)66tcUdrf zhUL@=ZtRf?x|G)FPzIe?4;)9Nj7QYcxdLMn541EKGB;{c_rDpY6%84mANJ`bZzV-P zWpX`wbOO#L)D)^8U9xa6b>q{i+{YN(Edh&1tKr8pEA;bGFiZFZh9~W#2!WTRI;$L} z0~V{&cM+RNK}9H|yi9pK0=vG z-fUf*V;nU$iDOnHytY+NT&S4buHiN+HL&Nmxn?`WGRrhKsrvo`DH8ukJoD?ZXQncv zG)rcx#PHqYU(S7cS8zsqYd^Y@$2cb>c(tZ+O2g9nNNuK~2OYz_ocUA>--QxRSw&gj z^EE~j@DP0pw)R=P*SAL3NCNF3L=H!pSwVL34j9~@G}3_H-J;2IlI*FwqJ)l`i|h-E zb;DLzfje}XxH3HLqp8r3+i2HapJZ3LyJ-T+=_zDUWjoB3nQ+0Ur)n@)@d*Z~rySaB zCU|_(Fldd)7dBeOwlL|rS85hh7BckX!jD!RDDNE99sUNT%l<1%_r~*ueHIum{DS5A zKTg+6p&jO1zH5gGG>Iy5%KYRmt==BTWjN;w8o|o|b3E(8WYiX2^M_kmd|A!ndd>~Fh(VU*QBMkVV!h-*iOf;eG zCWvO~%B-baPmG1sf<6s3gj#%!n0|1l(kZ)#Sthe*RX9JsmAh=H!(2Q@YDEsT%oy_f z@5d;YOcc;4F{vEJd0WUVYbB*us$XI(({u=urvZfiDW%iL>*7QXY?CR8c}dsU4|VRE z|HC#k_e8e!flavaSRB;h-5l%M+JsOBl%`gd*X=I{D&>Ds+mO~l*t4RjbS7RjhEMjz zr#VQ5ibWnX6J+QrJ_n=y+?Xu_U=z+$?1bhLwv~vuW{i(wJdj3%b1UxZ0+HL1RkXXh zk;I}a!1|8iAgsUu>y6?8lbAGAjG%DPTSd?$$24SHzwT<>_G<7{da8>#i%bw+zxCsSVs8umOZNq|qvLX{L1UY(rQ%^d_k9L2J z5TxHY*jV_?Yak8|FWrkz3cFajUNZUDvA&(bPuqt3Hy=9!Sz+~?h&9Om^ z)Cy2D_jZ=R8d$A*X!*+8^LfycmUq9dp@3P0J&n%rw1^0V_nwX(WQ;;#5@pm8&8uM+ zS$tD?ip0I$-X=?ZwRdLIxZ?GDtM%rF^CQ##ntr}bj%}rHfm?ulnOhgGu|54hHt`m` z2tOqrJ7Vqms?|PYSASa4mnPwle-&gP+!oFu`{pP1?PZZ5IN#lb1C(zfGoc2Eydb?+{~ndhpf8&ScVr@TZPD z5bAlyK=2}K0!I5k4VKC^zB~lNY`k}L^O*`KQa3X%1Nfm+_X0w=fHz2>F4QF~ZjLhn zaYsW9<&xV9=`It+Sq_)R$v6E;$&+!t!=$h-qjf@HI+O(T}d8zxaRsK&qIrp!{@ysGH`m-%{m znxG(evuY0b8b$5BFy=38++b**Q3cCAZOiaiioJ}C+u+>bG%Y4fHs_mvI3TED!WBkz z=l^*3`7?SE>kjYvj`vSFlhEre$N;F1*V&ddps(kV#Og}`-#mg(ZiQ0w1voq_nnMqQ z3fa;wnMrz&q&0T?X7Iak>|DT60B3%Dy_y6)vME}WR5u4;+xmZIRRQH)662yJ;1wGV zU~@p{#1yCLfA2Vv8Kb|Wr29`!ij?qgL8F|~rwm8Z0kTFO>&=0<$wC&ks4yrq{01hi z9+thD5^X}jD)*4)8A~lwvy~+?ji&Me_gJCvy>@B)2g>Tw#XZSosWL(3(yZl{ z+6#BrU|*AZdbcXNN;>h04mFK=R8ISEUuX(sT*|DLZKtN){h*rxo#dY#!wC_I%5tl}4msv!09GIW*Vk}v zk#y_k_yDJKJl|V0o=Hlqk`$)GiDsN=OWQ89*U2^_VMU#k1AGfYUOP*nX)5*9iPh?;X8zHf*W*Y<>WOTlUj&N-EVU|I!LKBxYtNL)T%Gy@gj zIYa@Wjxq7^AiG>X6a_RwQxl0-=wVhrBJXo{c^CFuqAdsp%4eV#M$KRVU4l)Xs zc#8B0>tu>un%d;)*{5V)e|rQ+Pj=&38$vY_T4549BrR*WRsO4khsj0#t8vlUDcHy{=|H^(_r&<77GrBo%lRCK+t3l?UN)x%!K`K2|3>uN9vH<0s zoqblqtGv+#V$DYqzTV-M+m#c2S-RKT^umQXX{?L{EfXduWBlU#L0bPf&sj}1b~Ah5+lZwxZZ7#H#$&(g zoMqE)e$Tdz`l{n&**d|#lM8@PGcIj!c3b!p!=&1Ed+bljORc$X6pAsnct@49=}GA_ zjQOcX_bKKQ?5fGb4-!4H6XqZZ7xqeKI$~3fo)2bIb({;e2_357$WfIaY3IH6oI2UG zX~qUc{lkcbB^W}Sr{f#?QRK13h{3cLrsqmIQYIDnJp-@@46VnH(##5rFLnvSM;r8Z z+Ya2CQ^Q*u8Z^=^iOq8GmGs1A026MR1vcXOB?+D)q#QMtY;zzUNgvLwGK*h#)u*xM z(R*ryVM@kntCY%ZRweY>h#HCK6!ZojslA92!?!{Q(;m;#@(aIJ8Or|We`#ck`G-e2 z?ZpS>bCbg1SxBmJ$?S9Z6g={{e%B548(MjtaFR$|QGY=s==!69F^*1sQp$%DHvJ^NXme+3G9-U8GrpMBD2`M# zcfib#f@pr8JuvftZMpb3p@)KHh$f>&GC0(8C03qN2Aj@o{m|*3B$!%1$q%m~`P35= zlUlc2qUKlqhr2p;#ibpVpA*U!xbbCa`K4=eOa2!d?cqXV@c~j3fz`G1MSN3E70@qS}W?o83vUtxZP-h~r6x1|Hw(d1L6xXlyH_yMX@{}cUGmKbW}Ke~thnk5lpl-4#uuCTHvH#B zBBj7#)|_e;&xn&A3wv-X*gH!QEod;>-+P(zdB2&!ydqPVK@k$rsuHkpTs9_HZP8gc zhsIHUZ%>oYN8B8&?WwqNM~bX_!5a*O_ybRhn{B@_cl*pJL(r}JF6PvaY_Dsz~KQ-jxSFC3>=Mp)Yk_W>8m)nom>JQP!{ zbsUXgWBUeX#Fw4%g_6MNeDTudZu0Rg?){ZOIRmzHBLC8eu+xvBqVcK-9-jRS;~V&S z>b%yhEt-kt;I2D1C!Tp4{Bb#n0#pLuy6rkS> zQ$f7E#8=j7mj>NAFNFzHjv5mZtg%6d=#z+_&l5Q?qrs;#H4WJ7eZ+N%iZgP_Q74`h z-eHzfhET?YY|&5FUCnh586plW)l`DN&3B_P??Nx+yKTp`+`MK@jBavk{_4`g9VKwS z3~V_ZWGK?P4l9SjYEZ8Gv)42rkL4j6eAi19EBW&psx0gPMnhv3gG+gwIWmpf&0VvG zH{HYcN`Blmo&4Zg|KqAoukCw%0S4XEH1TV2PLbrW-%m@&?zBh8Xn%qzQhc-KmJ->1 zP*P-{M48eFedoPM+Q^86(;p8Rln*LQHG6{gu!F*d+`l~&Vasq6GD}37-TK>(MEKnCBdf5 zp$KUB^k-vGpw!co{^R_8os}N?m&s1flQ&-6_ZB_-&&NaC6;L-WVe=yj3yZ9$Dl;! zFruZ~Dk8REAyyax`0=jxZWj0$A}UMd*yunziEnFEtE1aXa`;(Y|IR{SMlT{O4FvxD zOplpii*$(fHyHWmo5Y8Cy60>%_{F!**383Tkz~Ux^{Aa(Rz0a|V%2XXeA?C-VN|Op z1&hSW#CTu?p*mhW;R9qOu%*<7Q5#y4m%D|!$>VEA4i#2SHWx?(E6YCzWRWTBo33{y zal{=P4H5?38()cg(ue1eqY@pmWgZFp#=bPFZT$4)! zMzeYS?)nsxJ^*Ptvp~KeQsaDf5T|B@O;>>2bB>_B=EnAL?P%62m8=i`tZ`i9_Fp0* zfTW)EPNtW`QyEH2*|QfuqvHXTfam@pn$f|9u_#N>8iCclNS-)VC$jq2eq5_@-bZRq zsFgr&*dI5A(P#cX1_>&2(K40YXz*Ac_4$wU-s z6Q$z85o@2wtAk9mjkPljNo=n^FfDla0$kdKy5B`21$NK1;%rTnTNK5&ThKHD^*PvPMyS3Id>RbWB3ZC$+QG78gZ zqMe&yWA!JUg`|C~*p?@TkFBc-gS$5q{$8XdXp1=wX)vK`+Y^}*VL>}LD#i$;W=D%x||JFNo|{>Nc1fW1A!R-hWFX*G9FNlqi_Z}bfN^nXg6ry#XrwEas;-Ip)h7YD&q3EZDkVwKAn?v*pb3Ook%y@ z@78d9OgN;;&l{&Qu`yJB9H`Znx9U?UPa(tXg){tF#)Fce1W1x`fW9$Pk zlZ;11&_hA;u(dIjs)1MQk-7-^yrLXd%mkwvUR8Z48eNztMJ$b&KF863pb;kI)A z^d}e2x47(kojwIA=ce1Um)Y`UxJ+AYRCRgh?EM$Vdr#SW0q}ZY!UVL_%pQx79x=SJ z;Yj{hJ(Gqnik%{HLKM=62_sLsV;lMzQeFoJvscrNzTA#I9;EtYJF12EU9qTQ74t5F zWxFB%w1PT_9w}lvY;N7*jk_!SFzKbkJ3y-my}{@;>9`P};F+}|BN6qWvJ|#bw2g9G zGUQ=+*}(0{;;#mkO4)_Ak;Id8#Rz}NM?R4zWFNXLaKPg?a}ghIxVdX>Jw$lewDt-I z*u=5a-1;oIUzTD0#vQyb6j?bkRjN-_=Qh zdOB#APu&u^@!sS6pt-(0J_>V{R;JxC%f>0sCe=bfDILD?cYGE_sGMzR*5U;An1Q&8 zRZ94oMC7R>72nM0j>O0{ z30YFHB{V4H$ZJJ$8LV#MFb$kIIFv33B(`{LLP60vjFZCW=oTZ2Rf5Eu%SX;@t0Sx| zzA6MHqer7aIbhI^lVL1T3@AZZ$XmI?ZP2rs)U2%Q>8SvYSYet}VjlZwr4byO3pS(m zt#D8F-@aP^8Gfo4JropS>UBdZ*pkAjyb8ar-;-swECSH~*b#(M2cAt^QGn4L<{U|w z@dLr3uwf}loz75(u>v?|2|yzA+4SH8F7DzZklXJj#vGse>H7dZtx~p`*h*9Vvi-ED zWBfGNVuS%-UdOvsr5?1^9Q10IYzyH5 z`&0rV;ytY$7A!|24V6Yoy)nGb5S@jC3(-aEbLSX5Kstrp6`b6lvQO8C=e4&W;?u(km(E<0~2ee zaW>piFm_FYH$%6x(GErfzf9ey8_7?L0Xt9mP@8EPZ>*>M`z$!7wV)mqYvHRfgA10B zCw6}3;8?l`C3hY|3x0_LW7#X#U@UzP&HzC7ii?yvOXf7dqz&xya-3 zs|9srVwbHk1I%0=&wQ&2-zF3rT4@@!I?n*J(m-rAheotp$U{SZp7 zWTB|!ZQGd@Ux5eiW=HU^BoZHrEtDA~a6If1JQrFuFsdJo?wIOfWYhXpRFC<{#XcoR z0~^T9ey$iA14$Sj2`ze+Kc(kMLOl-L>T3f3E<$6oaLGM=N@WO>cvjl< z$pjtKv(e_)*Yk-j+CE6XH5VFBO?%iO(yZ|`rJ$?l|FrhaPGKOm(q6G{b12N^rh}IH zj-L4B*`7->$~#H_Nn`T=u|}!Gtt>d#`x+%umr`kkhqX=d z7xxPFkHrcojpSaadco+(h7%SqJDw`2-ED_*a`A+UE~`a|Pu)kgim?zA08bw{z$3WO zIZ=9ZicLoj`xGh8n!sDDNiZb}vLh+TT0Ak!cRdq`*-@4Fr@E*F;U=-U!tDKj9%Jox zC%_bx?RZ>!YsZ9;-^P?|`PaZCLntNP>Q{uj=26*UmuS{b$DuV1gZO&mA&g=2DDFde zh6GbOV@O`y1S~F@UIHe(A$i&LC03NfX|f(y5G2#AfP`F-?f?sKfqAz!%dO6P&(p;l zv+;_*wW6&z>5rD+7g$5~#w|1IsYj=yO5*^pl(NLajZCS)HVNZshGd*7Vp=kB)!JY8 zB;QN+winYan{{3AtJ*fS{s;NAoPNS0nbcM2L$NURfWE+#*H_56+%stJ z;TV?O7$I3tuSR1Z_)s=p3D~(|7O7KU^`G)%HV8_}F zU~11q=$JH^H?>P|ZHMSjntn#-dRCJBbZ?n>;O|XG0PKwKl@UWlG9F-znr%SDGGE_H z(^dJ-@DmRwQ}v~=gxs|bL#b{`X3vA3(HT{~jS0SY#tQlizun;<>7i*$13FsvnM8Y- zx|ozFCzb-#{dd$`z-J!f-`kszSqfyP^-D5_5zm51Vw(*|0G4~X$hDNzgFbUn8L0gq zdg}RL6Y2;MA|i=fe(xtR9gd0jDOJcV`=6*qUCXvbz{XA%UsM8uj4JoG7`UP88I5}e z?>*_Fcie!8@9T!9-hwhIZ|K`AF$AG2HV@`FTSFp#?r7@tbWmn;qTGjTBhAmf$Xf5(y11ER3UeAA&JR}Wu-J#`E>*#v7AX^CzG3GomE?0@&tUf-nu zDM=d3l?pK`kqL0}Jp*~U2ESjzIJT!7uiCs>pVOHMYz>=jl49%l8mFTqC)Y+%YWv3L z8p%>PI;Es#&hg4A0pJn9@p}?k?8(7|DSr9g#O$5H-#R`4H*A;iUyPO=g-L6wZ$834+v z@TJehir>liUrVHGEJleST_H6um?l7=WNWzkWXVdSww6-r>HqLph3AMDqzRd8JM<6r zYa+W{5p~zq`8R_6kzQl&A}4Si?nG{4aH7lEdYBnEasYfp%+gIyW1Xp+xxe@wZqVV~ zFL~|)Hnh$iEtbIzo~sSP32{G&Br=+#Du2Zl5sl-Sr%zO&I1{Jwxy**dU)(C{sUoq2W7w3R-Yb*w1jHck1S_Y?PwhX2P5{f0uoH|ghKBU~W!kNshhil%K3^LTs4`dcPVU?{JKZpqQ z=cl=GVJQ=p=VA3E;=OoCVcy8#T#xgI`@0KKBUPC^(P7%R+5=66;eCg>swz6!?%>#2 z{m`+-mp|KdVqQ4)Ldi9E8%52|4N%0}BEa{PZYp3%i|FSjf~+s5GJn*f@vE~5C`dA0 zDA~D;Fcvt9BWjqC7hh3bPvbsm@Rb|q;~}K#G}U*_gvi_J5z`n|n8XEYi&3sL4?$*uSB@ba!r{Z!82 z2W$e&^$CvsP7JJyi)ypmZ9H47F7vKP=IQrjH$+SLU0%8#^H+_w6JWsRG^$$&Lemqt zpZL4b37D`sbMAZQSVX-$_QCbrK|o>7$;Hfe$FtN$&><1F7|VSf^Kh`9ArU#NXiGjJ z#`-dVmTde@QjW#UG7uyqI5%WYYwnfq$5oHMsg|KRZ7?pHlpd|psF(w69u%fDjGd=;6_o|PY_@=P?1AW($YJnMyzi0 zeY^v+*{2MnborS&wHb2y=f62{--}4K?s%7QKQP`;nhtMaeTC;}4Ww7(33yqG@E6q- zxj1TK(z{BnlGku+5uJgHC1E*`km!efJHL2vjO9Z; zNJ-GrEYektxE*6;Xn+r|CTV{lq^LYMNgU}k$F-Z@bAJ+f^9uzba)Lmup1;7jFn)7C z|6aD5wudZbE!=SXy`n51|8I-$~O&?@Xn z-Ry-WNc)dXN$&|+@VyMm-Hu}Ru1%-}F#`3S=A|QG=$65^owH#4Z;4 zKJ~R0uRAY7WsxNocSFp-!dH-?@^^9A*d1#c46O`gC);}mAuofm)SNA#QJ1~A9C=N* z;X&m_mTHZtoQ+VyAWH#Ub^m^MRcO^3TF#nj2w*jh>J(k^U?+!M>YpWF+%8hef$7{{ z2Kz0oI&VOki>P6!_~~8NjkI1fNa48h!|<`Wel{uxwHWVZHM9K_Pxd*3W$4%T-n_5c z{T#wbo&nK|5r6+%gEJ3Y^c=mg{x4c@0mMzffpbS6Q2g>Ny?=4*`D*R#oX1T~)N;OP zkNJmk65_slRSxIE-i8RLpTaF&XHuyz2#lPen{J^tWWmSd?_URe?*Hy*`V<@U{n)%M zPX1Xg;sdWpK(x?|WZSeId0n2!oSPvWtr)%A%eO`SUJtk}KS^1IMC|3k_?Jo|=dXIp zd7l9?(^I;OQbLBPt8c7LAT~&K1G!GY~NJwZ#WZ*DTDRvm@TL`&J&tkXb8ZJ0|1jJE`f8gfZaY77 zsFnin5WFBG5CLvBLEV1b0@<}*z08gxoB$lcav}q`mA3e61zwcZLo8I3KJLsK<4tzV zY3znh3G;TR?q@)|RbyZ{=MMfy8##NZ#m+Rbzvk)y>Fp!;XWujZa=To?n((;$2gh2X zf6mLqqcCF55D|g8O74Wy9tu*k_a74;B`6lPYGRsmDh|RAPAGyY{OnO>8NyQJ5G>%5 zL+AMP-3!uytQOzK_z;=MW?6C$9|mz)6rRdOdNbH1nBLZZNr|Xo=H4faE-Ej+_~fk+ zL|r^iEU|J*cUx>L#AxK<(KD;!d=vLxk|xvgGaM9tf%yo*KbqVEt+8kmkW1t|^n7Oq z6tj$$C9-U~;;8O(raAmdDYd$Ulq4xHD{l|YLkQ@I-X_*WN8+*-0ffX{ANnU)39hxl zwVCw|Jl10o_UBR-bwcB7g659>Ma?YT&4ojR%1Fyukmn`eIzmFT^T$$+UT5CR4_Eb+ z02D^*^H0*&7vdbNtI2(nXZqn_2`>`P*JCFtVHjj>l`^(i5Kbes#Z_ zsN9(2Z}$yd*lGhW{58US`tI5PNoKR&9i7lg9}xtTv~o{^R5WZ4s1TdrOApDEfLwIS z`m0EKm5l)W8Nl!~-Y{E-^vbi_10CRWIxQ=N=*}_bYIwFFI=1H0uqjW6MDppM@D&$u z)hF3R(`vS1H9TJ1RsbtFF%9`qmMEmJhrbUu{%}|*hx}CqKDBB|>nQ;fc`U;y0KT*b zh3LtP^QK>1^|okANJd;L@z?XbKjB`zox!m+svq3}mdPVRqDNw6b(s)Za^30KhM4ir zyPA+1Rn;d|3sN~{m*MGQdm@R05<`RD85&C#_14$9Wy~}?^W|RtFL4WP8HI#C(oyk? zm2h7+n}pWN!ffL5^;&ZeObzCXH`Ry3ASRsWk_#wsk}<0-WYjq=t~OiWZq#vp(!`WwG?monXL zX}6!U5V#9*GR8mmKj-Mt`Dm)VD0#1bfJk!l9@R4)6|0xsmRCg;1kY}p?<+e>}?h2-a+bbrg=RmY@XGonU^@lg<@e^`< zT3+|p`}EhB$;ToI^9<9R(QNR~tQF8iT*Xt2b#KAQP@hp%ddknI{ob~ky2qY$HG`#* zg0BUiBXoNLvOma*yo`jw2b>`a|3)qYMGadr7AZ-{COX7aF>mmst63qRe0zI-wby7f zBLNE?83h9;_(ttV%0ML?))VmTvvU&q@sO7J%%me?is@COUzEi&)uc(WjZkV5pif`mti^#aWM9mt~ZRo>l>d%sh7g%8t`&g>i`oH*+ zo}Mr|56>HvrV4P+&aGLNZ1-u* z6OV5?d4|E*_8h!6$Z8SD=6!J4oxK=0M5YclFqJl}kd!^L+?e$K|W2AV!i^bfk^l`{qd&7)f2sXv< zK6Rsr_*8u<#a**a!j$Owmtz%^9i+8vNtd+GRP2IYJc-5hmSpXg>5v z>5aP1Q8DE5fQyyRZCKKkt1UQ_4?irGFgn}UDNzQ57FDL3Z^-;E|CEYR`Y(6@e5s9f z*Sip@Qb}WZeCaA~FSv0ym|qXGA#hvKz*o=`p2^}^LzaEiEf%3y{(W|an!qnO(cTL; z=q)3xjSeSDrfXm=G4M!yS6eEMv=$ketpjHY6Kz(>g6XyoZ=E*+Y|0GB7OGPB2&+q2 zH(>AV3HT6|$st^h!$n4fV9RdP7e8T*@L8DNSF9$AR9MtdUsnADR`W-IPvXe#@k0=3 z_Vn!mE@fRImM-G|RD(bb`)Jy_H4by*v#onui_hTwpCXLhdWb3X$;e7Kua0iV#J5$J z$=NpO`dV?L==vDm*Ct>!R<@n4NuHY*6)54twm2F0454QB=AqPIZ_qp36|T)-*QtuO zX9VFYk?N~I1T!oL3eMjB)OD-fF6WGctZr)B9qq;c8sY3c=h+&=*cS<}0K6EtMYIzf z^tUi&Snwm`A0$nO?VpuvXw(9f~Gkh{$|=gHTEscypw_Vhno*o z4~`!N;f?>i(wKO+o9SauPAT^ZUe*()2!5p`<80IstH3`lzUt@srM?2rVzdvQW!}(C zqLSuA^RCYA`gEA{dNUBD>YzmjWW!HXC0cI^P&+|ncXIe2)=7@mQok5TSIPuO%n&MU z1`g;SJNUT-$XLehho_ks7kioh@7wzfZLD-90THYano7bG&mnFVaUd zRHwKdW$ky>5lL-y9w3iHpedIIb@T$e2=g7^Rv8>Fr$fbY`#wP?TU)IjR-AUJ;U*2B zH*jO3?ldY?0isZ(JQtDY6GZzM>{V3Na?xL~U44GR0Y0z)?z2G0X`S`fn%3u1(e zOwFYeXHWr+GSZYnZ(p#VS~#C|3Q}%z8O==nU3pMB{ zvg2@CeH_$PZ>#->y5}+GD^<}zp1+M#s|k3KdB-T&tLO;fx;nMT7+FWx)eDL$c~;Ly zbJocVM_Wnh@0Hc_`CwLrlgfr|5 zv@g{@TkEnnT@%APhEh2{84wV{-jB{2lrs4DnM|c$irzz^TpU~Cu3lUrQ;3nS!e*T{ z)=+jo?NQJ?j^;KYH&N0Sdwtk81;uY4x@!W%;QJK~LBow}@7z*2nrmb*#&ct=7Dz6H%eFkOG+o)9|R^ zywKa!%nS>(P&BcpsFW$HALV3}{D|rD71C?ncl|Qk44aKrxK|^|)kY#n8zs?yhhCeo9K-k6rA=Or4$<&GrxUBipFuV=G zby-yISD!p-hpO{uGSlV$;j0`!eC7^^Q`3aU6oR_EBVcF>?-pN;pqXF%2=~ojPqegh z3ib@u9wA%2R@nGWtL^lbC2Ufvzs>^Z9MpKY7oCPXLlrp&p!7(S8B@i6L<3}&c~JQgZ(C#}o~&hvt} z?aeAZ71zSd?$_uWP{{WQ^j?DHxonrj;pUrPI8G~Q2$_$PvVT9I2@_w_O|jCc!rf=x zJ8P0y@*gNCw&5e8*$r#tKhlo->^fbw29ahAnhQl(9(4o zx}9Cefzo(vTV^N+*7g9t&PlvlTAA?QjD+ZY6Pe&Y{3sQgb7T|uoeWW~_r`+``;(wM z3^(e#R`cIDlC!TBwEoyynMND+oH6{0g^g}I>G zpwTV?m0xX+Ew?yw0+&KZ8?@d>l-$oAxnrhkZA5)V zs<>%+`k0DHQo-59#{zISz)%y>-)Y+d}2Y)=}kceNb4{5I2qdV($AE zTZ=FrXbk}wvG$*fVi%n8`l~l`Ztfh zSF?3J`nxQ2?L}M)oIUK<==9ImN7;B%_vqtp8LUpjo%+bT@hhrzs}CNI5qqHb@qvnj z3xIbsx|ypqNIinmkos^!-a|rkeS$I?lGSH3eP3ebk7)WdygkmrZyhsKy_&pDFZmP% zuJ+bxx-pCaI(pDr4QZz|UFR&3*l`IhIwNp8L;Az5?bpPL_Qzfnpe}61ce5l(I4nQ7 zima*D*P=VwZ$CpjyjS}s+b5mG&C%k8(R7+xeDTX@s~R~<|CQAyFi?F!Dsm#tH$_Ug zQ*Oh+-Ne&TtoMk^GkS8=AP-4cj{OXj<|Fvtarwv9YzK#sDob)mTDLA|zyU1^A+i?D zi};8Pg_lc)ZeSEV7bcUG6Di`+yKqSbDI3^QghX#Ute1SPSwb3Kb1z;=h>(U7eV^16 zJ;}?oP;q%;AOdG@& zAfSW1uv>~0Y6F6?QNsq;c~_XpmlEZEJ?G15e$<+;r}FnF#&W7`j7cGx zXGqK&fGlZv>sxVpR@mcIUSE*|C0X!1RpzAk25D2r6>1sPZe@GMe)Y?O)!78VoDiQ1 zVJtxG9-8BP_O_9*yo|lD=l0j5y)Qa{4A=062+)g<4c^vqVdDB5;K<@(OGrLgNK8L2 zPor{rS9FDHehKV^HF6WFYSaa}56!x>&yo@0CB}%*SpIsG$u_O81x@O|hd@M2nGF_o zr$Z*q_{_`m;sEY1v!W$&Rs71Gj!O>_n(j8yTfP(6^qQ7lv#cSB&zEoMIrq`wLvDL> z5VWx%SpUj6o0m9I1MIDBWDka!$jxC8M&h+diupw|BrO-Y0 zW<%BWT+bBS8b~eM+euzF<;6m^`rUE;Jh=)C8hS=Ma~)VWZ|{pT@h|p7jQ;wT%q|E= zcbrK!AjiSBW`7s<^LF=^3pIyCU7HuPu%Zu$u zY|c}5GEZkGI=_DnC<@yA^XcDuZ=1M{=#Q~*Q(!^MHT|vf^HC3-Zr<1Jj}()2c0oM*$LrW4WgH#vImLuz8=3{8b5-??o>x^PFB}WcBvd_3Uu+sSPQ-(_ zLYt|nMN7uLo}X9->*s9Z=6Lhv=9Y=tuA9%+EL7jz+&>ofGyd3lJQFk0fzqEo9>VnI zST{Jhzk~kX$owC9S#JUr&0fW-ds~D=lX>%~HiwZ+$_OJn8o9r7b%uBEz4dc;cgn6Kh3tfFE7vKWDaRHtI=9;rfQx+e0#31@SPMwl~Y(a7bx>~jE z&T>#5&Wd(CfuOb-A;A1YrS&n3!ICL;yP#3c1PX2y9h+Y27Z0n5cu~xZ4=IjCOA$+2 zMXbC}KuinB&sz=He1LjYm-suy`hYAH>OPEO@Z7vW>l>=8$%mL-CZB z%$WGaKzR}c_SUFtidGBg+z27YncIliQcgKc`7(dFN$Nc!)|FVI?c*!+`xhlK@eyawlM11}cS}nC$ z=0F9(#9p^XRv3R0rd)9-L5O!C|6GSj{+@Die%#l>U|P-$_~)O7`&b7i&6^+Ly!BU z^;%Y5GCSY~+?ZiC}oY`R?}cvMqxm z03xVPx6Zb&M|`Y$c!A-N#^ML3*F_m@RWhDkh&wybk>J8xG}pHInWtC#)`$iBEY=b0 zWHxgmewghuTeR;e^@=%`$5brYyPB3h`Qv51?Dj1SW)~{WqD5pRty)(P0E7X(ui$g^mliQ;A;8k^;)J#d-EWs!7 z7OJQ}&3o}C2E(3Tq)I%%I`KB$eLv}~V+2NJ1!1`jQ7moN$^@{Hzu4jz@32rPugpgZ&LJ6r~H5hvJ z>378iF~1FZWihUi`kEsYB9Yj#<7P6w{{Kg9yE+AIv&IN{*vAq8JDbDYghqSTzou>1r z{1cy}>~yu|Epu_0L_v_HL3|3i9cGU%+$)3b_;N{c6VJzVdc@dz@3D2D*n>ccQ9xmE zM|DSt==RqM)E#N|2q|p9N7G6EB+XAs=Yo_JaJ?G`o75l}#L;A357&1QJQ0a48`NX* zvWntI8jWY_)V&6)6n2NM6VPvoa*2RsvPkfp6H$PZu@ef73K`3)LcbE|`u!&GgF4mc-MN4kvwKQce|F}&*xG#z(@aNFK5ILJj#b|O_Vv|X2=Q4V4sN>&M>A|jw&4S zD3?V5UE!{|8^0H0d8lHLYrmZ(jeM6A+92ryqEJ@2dD2hRb~@cuNWjWnszeE`_E1?- zANoQMnaxGyIty8}no<5!@IdY?5dMi6oSZ7tYIjza;X2H&i1x(!{BUq=%LLqeJu<%> z=d752)pn|ViUsVQ;eSHzwA3)G>bok=RL%l9-%L6EX8^kgu*oLjilB7@x$nR8 zT$?DhTU?nDAK3A(H$_72F=XzH`b^*Z1tdv-l|a(JaAxj0SXH$p?q;;QFfvcNGMC_r zWKZgPz_ix}+M>zbklPF~k2_r}3=P2wHU!n^=_{W2SF;C$5@|Gy2YOr2^4JvfwJ{xgP+?PDl{`_qLSz;YV$A5IxIzq3sXg+#EB~PNY9tJRRreM)|04 z_>%+UgIJZ(D;sBk6N*sO3wIIz%N=eF5)f^or+(u3LU+LT#A}Ueb@vTlKAmU9EDx~4 zGF+vpE+!}JsEyZC$!4fs1JWIx5cgt2QF~Qrux_X1cr@*HgC{>V!R^`RQ=7#^QZllD zCxd#Ybi3-o0Q@IBEA`AKwh!!RwGyZJ-=Rl$XbGapXnb|z+^SzK{#)>b0(L@Vj1%vq zk&7)NMl7Oozt0#0+kLIL89(jWzRIok#17her6QdXRt%6^(s%!W*&@0KFJhcq$yvc+ z^Xz90GZ=%IHqDAn-mI&3sZ4RNkSF>^<02bY6uM}5muJz_!h$~bdiY%Z1)#LyTaOCd zdmufxn$dyXKs{!(bKvOqd|~yo!a{8?@<@>ECxLrLwjfRdM|n)E{0tLMCUNiKf)8`E`t367 z20}pXT7)*m+?M)W80WQTE8N!k3a$Z{Pry*B$*bCb7J)J;Aq80{Wr4b>)Vdif$AR9f zYYg2~Gx(B};G60v#<=;!3ZWHE4bQaKk}6*z^XKBbHG?<)n8%9Wi@K|sm}-h|M2fX@ zBqYOm1C`CR>e2n2Ddkit+alW`m4&F+evWLYHF?i6yuBAX4;l!M_dDo`WU!U6SQYTg z9d%9HW49F{!}n@`!)m&-A*ALq+cUFp3xF5sgqePN<3JQvU3-aUKD7e8V&1j`WjT6J zWhdY8hdkPtq6$)aE+Fw=CUYw#MN$nEwc4q4jEI3_^N{6GTrM#b{^@oQzCBPgRorp`t&?fYwY`6@nYqzxg$kwl*`D_Qm-T>GXWa_-)m5f zPuM&h{cG+Iii3t_2j}jvvsoV~`!#r19rm`CJ6 zNyAx@gIf?-XnkQ`Az{&!d=6v@igPbri~YO1AfovwxPhLwwu}pGs{!El*e zHfT3ye4KiEVVkAhXJ+ZMJkwo9$0XkVE+zuT1{@K7i`urKZQvo#OL_Tmol5 zZqQ)!>(~0|bNc3?cv0DnHbf>A=~P5BvE9RhIO4Tmi}Lyl-1_l3;wz0scI{W-yX8`( zTodapaGjN%_=X@!%6&0R(klkI4`aGYp`-mcmT%#k61=fHx=EeyYqF2~et-W>?7%Yx zTII(K6??LUqENz+Wz5q)N$|n1yUZ|c;)pumJ7?-qZIq+SFkfqSX(b5Y^H$gnQ&woc*u#+ z$N*C6RJ~;@_}_@lTt8xu+x@HaN;7!~;IvVB)hMgZCIWu^&x*5RaQP2sNk=k)q)PS) za)ZctREa2cO`^7m(Xd||;&X1fEyD+$0&q_|)LhMy44k=g`h_TC^Hh=-)QzHtdt`XD zlUZh21_vGF`6Xo>hdFH9g7-!k_ZBS8R4)a=<@$t*?}OSdaITXk;A?v1c1jB0oeYZq zZ*sY+xgdc`#V)2zo>fJ7UeQB#L?@{O?!L&r4O*nvG)T+Lsyo&4 z$kv+dhJ>F(IY5zj_{h%~l&>rVA|!sW>&n-CGm?I?49dZuC)qdp_TtmzmQG0+RJwG- z-|KnZWk05D6l|z#adw6Slu?s8>8o2VBxg zr`D;WqO}k@?xtx-NGXEC!5 z(<}z$Y_`6MXjHu2Owv|WLz$Om%PkATmFePsbxV>GL{n50u@~|P|M|m&U?#ao$1HNj zW6W+fzj8&!67`zbeIVVoFy1=#y7Dh`wDwHfPTv6d5&DfZ2;z6U2KWRB^*A);O|={` z?wDNO7zSt9wD5#l5l0L2-uE27-^0lona9LtXXM7QMI!xQPiZiw?L#mXc&^iH{dSSN z3H?&&X&SnwHY^h0mF+gG+n;fHmWMRl<}SVH zaw%qEXn7}#iyub`>o;E$Pe5$ijL`EY*~vT>2$+^mDlTOFrRZ1cA#SDE?w!4CCo3PA zksNO zjFhDqAHL?p?VT7zV*`CbF|cDRL{}w#C#zFAG=2yVp)ISkJkMqMwv`^Yy90xK zBXI?ybC6<@bLJe*SSXq+z-g?595Ife$A56`d&G9CV_X~?H4+WGU4luXM;Xplk3l}# zP8jqsp0{@@CwNT&f+{#)A?d}SE@!Q-;~l#67?JDqH2yqUl&Ag;1-4*2ra_lq3TLkY z(d%F0^)Svmz4*HdW_zCxc(^T_!S@+ku-6^v%$Nw2urp?z@n#jw!Oj8}G$ksLkwKJQ zIwH5ZfCx%AHClF`Mho7e9xV@K1DmxJJd6Gg7v z7O+oF&vA**oqTy@mb!4ehc@I|kFY5qUC1wR|ggA~25)<_Mvr-oT3d_sVn zMvzfmn%i&yHatxcSq)DE@l@rU#05~z+;fN(ACy~*Kew9_M|_?{G#(*_{8X) z29Ziw*K!a>!M=~kBHI41?k9GgQ#r~p|0jmY<8Yy;1~~QSw1Vs!xY@wzM@`U)17!bY zUzdF@dJd>-G5GOz@I6Q0bMnubaBp5*jX(X6G?1~}kNrJw#7{Jy(J<|+hWYA?iVmHh zX=Tn^8fZnI*o{MLa+ulBY`|p-xb~~h?%zT6Mbism0iEC=wZlygp;J%Zc1l4cOGSoL z6iw80D%7x#16;bD=zN%Kow30_ZImQRrQ&1eSvP7tj#RJ@AySPd24=^G|I%HlO^mL0 za2z05TA4+XiFPe(ymKAPn7STf1JyD#BOMB-BS7C1v0 zko|###kB79Xlbx#OM7Qj{8;P;>y^guZLNX2R*4iu!M6)X!|##-kSX?PRF_sc(Tt!W z`>ue{D%t7ZXl6QpjuERZsAw208=LS)E^#I((dak{*YTkSNJ@;q)}Zdtd);3@E=RY? zWLNW=Zb>1fS`gd?pl>@-%|ux%w<&rijSE^V6mBkri{~rpPQA~j4keu0xNZpKukx!G z@ABrpMaaimw;^-*ywPa_o+i#YJkn8}IIItXlM#DXqhN&G`wG ziK)>8ddUp+8<@$^tB!F0=cx6_SYRxoNmT0Cu9Y z_M6vP5TN7sXlJxg&jxDnP}We7@$RnP)?7+4ts2Y-gp=JmmNnYZ zexuCv`>O$WJBoApy1azNG%yYivU{${fi%c`hd7lza63<@>q`eC%K9>lTEtXWA)y(U zmD@MAqO{hE2%yn^M_<(EebWgkBbt<;F174TqZD;xJhL&EL=DMn@l(UOTjQ+ynz9a6 zlXYlT95FlNb^0@mV!aT;n6cNkDjw-@DNI-U7J8gv*(NeUSzypcoEbnbga6Y9$hy~h z;7DzX{me2l zXxC5FXCVB)+R=Z`qy3u6Dn~4srE1~rkd>uFWGCg8h(Q?MHQIt*>QQiVVN^rz%Rfq3 zf8+F!bvW{KoQiu@eO&oe*D(E_w2yJ2{WgO)Okp2h?uVlJzQ4xw{iPf4C|98ly7Ux# zF7Q()d;bTE`$$}tN=_ZJTGvS<0HPM(249|5kKMA`TT(DNvg1jPp!Uy9=~{aawl>2gk)j9ItKbUCz~p*VG}uY zv<7c$NzBwdc4omYcU4NWQ8SqPf&(Qq8b7*DHz-15*3@8mtRm1sygr}W(hB%yWkA_; zC9(FxHEk;lHOPU;4V=zVH?S-*K(efXVPv|IM1SuCnNh${*ystn*1O*3v+Jl}RyrCx zZs8C@Y&VsNT-(`;DFD=VRqsO1j(R-sMZ<7<$H!K8I`o_$7XeVRIoi=iIv=FM6=v!H z7QKbgEeeMg@vS{EXjgGYv(?{MJ*J5pQQFR}l-=4Oz&~;ChLetbY3%^MnJfeUC`>Rz zQ|ok+r!oZUfF25D@F4$*1=eB-Z)eW{A+J$dCXa;0&GXwaj_`OpieeL{Rx06?N#SK3}@IRthy6lG9g2<5wgS$nqa$Vzc;SHK?H96u_B*&X4n!UM!>Jgcji0k7G{2^cNftk@cYz7XRklN zB?x%DorivsY+zN#ql5-Klhqr*d&shf2ITuMD~i$un=uc`LCV-pllKe{Re8jPlIXu0#wwGRD?{Gc<=YpYr=) zYZySJu6BapL$GZ~8{>hG(2~LOD)d>%uwEOC^P(njJjbX>YL*C`(liA-~~chj@&ZsCMm_ z3o0N`c01A#5kJMV2Ixso8nd0`Q_(AtY$G>~h%Y+vJNCGRGm7%~uYeA=p4H15zklB+ z#qZtJH_80PI3t72B1EK;mwC%jaI@`?Ga{vU{QDH><8I9Zr*3&1dO|m-m81aSApeY$ z>kN01@Y*86n&~quudB3>?VQ*rFJ}C?+hTf>Ub8X@$ZmhU1eL;czCqinJ6J_zl5&Xp zO07hEIXdSFI&pKIf*Y`Z5INuOwQ=wwR~YCc6Ns7p%?58hj_3BHA>?3j0RjJGen50DblRYWZf1DC6iVW3az*Z^jdTHNV?AT~s6nKnCUeS# zx(Z`F%y7H%2J{ciT*R=Fi!7_16y;DTdI);nPih}o#{u*CxV*(lThk`G_5|KCTDx!r{i^lPtdL%nDN$uKdJ z#6J8aG`*XC`MbHWKXA3SeJGx+2Uj=!_y-MJwLs{jhyh7tAIxier^C;CaJP#~3H4OJ zdx`W99p-O}U6pp~7>?07!+}sC!=N^6SUfBi$d+*uxZE?Oys7@FwDQ6P8rfPDDvphE`f8F1(AMy zoN@xPe_3eNqCh9SlG1IG$5Vi9?EQ1wOzy~cvRW~COqS6m^w@Ww#v|%o0LC(axSGB@ zw^6ZzzDtAhRK|dHIPY;Zi@($n6cm(V^d{`RT~gVkQ@pEO-PHpyV49xUEA3AgE_3o6 z-~sg}+wU;Mv*W&?6a$|v@gz1&KnI(irTgp@E+(Smt~M^jeF3YnqRxeFLNRZ#YvM5l zriB~j`Jgd&;>(@Sn?nA)3^jN8XFSzO&QXOsu+7i5A?>aQgOCdJ4eUt``u1zfLyPQZ zuE>W@Z!u*|mu#IM^S(oKm@!i!vZB04n~##oW!fQZ)pAU0Zu^-4sFgqL<>lTd@FnYB zCv|La4M-3d`tBsKI-9!_1DWzHG*x=MSB#Xsn?X0(-2X5^y3J!c+$!;AFcTfYNQRnd zQ7O6^3@Z7D{~wMi47LWeY~6r}cTyV#*)2;V&JyoBpm>yB5iY%4VEIQ|sGlpAhP|9=jw& zIMXQ}#{-M;d-BJ{=6KM58wnhS`cY=GR=P@%*~0u=F`f`Nc99W#?0Zc4OwVC%e4*&N zLOJ0(z^yb2AhxpbLR*#&>fTt#Uw<>SR7@jF-Vi$>&i$4QmTWvZp#cuil~~#_0Kz>= zFD>KcpKa7fLEHQB$%0~2;=4RRGaU+DUYK@gUc4Cah60o;Mbg8K3NX+N0Ul&i0k%|F zNkYaR@j)NH%9QhexECVuvFe{WcG$DcL8A(nT;bFcdq@=iBtU?a@mW{GnBx=`D(ElD z^GBxYNx0C5Uud$p;9cUs@OLCJld|gU8S>Uuh~_9O=s~2%m#ouXDPG}HiS)co5(;Bu zC4Oo4_|7YC;VS-{%E2-pWl)Eo2z=780h@A?WIc3Hn8gKgOFbEXlSy&sJ*1pgH-T@- zJ4AU;;+juS$XU86;5zOKw!<0xPTRWtg;Au3l3KyQz#^8><$8B2;a}=Jx%E)(>6@{n zZNGGamUK^)AX|IyC)>)xH<5G~k6(T0F!1BHGl zg5AdZk$(VzC`7BKyF+Z|H~doZ%Z|8YS0S}A+jceHyT0lP)~&GHf*!h)1V7z`Y#jEo z0?o(n22POd9LpiA>DNe0lt*?4OJ{1Y3kyz;E2zH_hQ};>1TqbkYa}of_bZ6&Q9@5DaP9c}-F_^UG zdO#%L)Rcc%6``fI~na{Q;Ar4z=u zRpr5`x!ZFc$6mzjqJ8<1PzyCWyIW}$CssPqZslhaPrq!>D3jdI08ame3eV~}Am?I8 zVZ!_Rz@@x=CXUzdf&>tLOKTk^pG#uQn_9b02M8smjoE}U$%60TazJaASSl4RB%Re= zb$bz-C)>D&-d9G*P$mB%V<=$+eHhZ~ye+(P7te))@5Ie(JJsfZW+4f;%vMvN22JJ~ zq*n<|o?-PRt2?@qDCU^_6k(Ug0cGQS+A(bPEr_g9_j;(ad%h2l3>l8hFtJBob>7fQWR5L|5s@X->@_|`!P|$eVhKomc0VO}{Dj|fd#*R7A;;E6EFw-va z&RTEIYhNHSkiNtFOrs#Y*<`Q4BOrQ`m|mstvmA>p+A@NQ>@|Ij-9YhmdLFe42nn7i;50 zPV6|yvwV$>6)v%U#*pfOZ43&6?J8dw$xEIwZh2A$t1N=Z69xzhJ<`di{i%~?J`0k> z{}PSC5t(A#l{I5tQk4ss8ap1BLxDa?8CN1Olh z{|qCoK(YFu_g~Acfx0%U^K{^MMTClJ{X2h^o>31IXm0rs1XCvenMB!iy`KfZ#EdH0 zx9K#VLUzWL-F3ft#$N1V`bhcuOlW}_VBoJr?f1u@)A}b}ITz*)ls^;ap4N_3Tbz*N z=@WgpoS+#xFR=G3tjI!*W*Dkwes20&BfcvZOZUA_a@g1cAy2P?!((u%!P%TH0i>aA zf3De^XgUVK)&n-2j@=v8 zVi?guiwh``D*lSdeg)ZQFFx5a#J*!3NKr`^MKHi$AI_R75WU3Z$9|!)v(5%g88U2i zIwy0&=Lb6VokuKC6P?YF;+rZl?rs*B{c{ZAMk?QAX7*B{In^M8{-u2!`N{b@NF64W*UYSrqA4=?;O{xG|*OIv-k3lD9Y}7D4)!0n;@8po$F{ z?`?>O{6n|kJ+oY+O>G6Vmf%Kus9gks4=oI6EI!_y&wB4pORisv({lTh$aktR+=(}!#B^bbFbh_9a$o+W;u(4<5&o3iHSM2g zew}9``1uh*xZ%dQTk+{oi%dGu6g2JiQZ*weJokheD&%qLy*CaUjdQS<702_}i!6Gw zavi+-GaQv8T*tBTRS2Mkzo~xlO0LVRu7P}0akYedI+@;@9nFW}mLq=!Xn(^}!LV&f zVg7(DB$wGgBCOhklO-?T=`|OAGq_h(w;tSZ!NmppUP`ROXoXc#S@t%}lSp~ANvO+# zY`BR@Wdf=2HB7@@t7LQG|I6-+e=ywRZErFK?oe;Ftxv|1&gx4XFL$pLXsl)z_?tb> zXtRNBTc8v3yGhEY$VHn`&=38#NCGkE8{fuf;km3pj!qrdLl?n zBz_q#^$k)5@75jKB^;oyKrhi%`@HO?Z z+Nm+;YZa{oS}r(u?=o)JqqFTM+UCZ_4UgaMv^4Km##cs?rmyJuHieYAtO9(!;(y9@ z>i$Se&bqL#J&TFjP%wv_1UGfk_hM;N^$gTM->wF!YMKOB_MytZPc%E8D0bnPzumYXiI|F}dP9o?eg-(S1N2?^LHkGZ^fn(DAG5JI=ED|34xroX%8rMIDQ zHH$Av^nY*ZX@E7MRy=sK+))acH(i75+J`Fc$gc!b5Az^#6Xloc9LUduA3B>&G{F0w z1Xh}tblL4A1*~`GT+^xiTzSo4%>8Og+Id>k|W3^^z?};M{gLG3o{- zm?3g8e^U1e$Dez}@v20H1}>|Pd!%y}9GR75+*C*C#coejvodE7wkEWzfnsB00x^ZM zn|+m|9f}$q{F{AZV22s*r;2xsZ?1v-&&8)MjPzO0%S)A^+Lq;e->yXTRybYpI2cEkCehGKb$zm8N>t`5SorNYuI}$I67@)^syFk?-ZBe)2fc86qi#(c0kSynhtjvY4u8rB&Z z)vN|-cujjhDm$6$UXqALA>Cg#N;B~t?DX%wPi;N&^JYv}06`myh@~RO zhIUYw9lomumCLW~m1tP7p5a1{l5)s?C#9U1a3i}jJsWlPJ_dZwKRV6` z>EB>dyVdV~W{6JG@F6GyBbNbbOE~;R z;NWBdC{K&2eAKK@Hr=ptKml&M2)BsFHckX8|Nnom9stJ#8%m>2mNr<~&VmK##}Hg{ z2}`MFLow*tH@~9B`R5@@Hi-la7iB!ITML)aP8lFVwE$n%yUEJ@GTKv@dL@_{06QKU zhy5{t`x07?weTSL3Pl}_5crmJjR%1hG`f0Ged~HJDx}ux!wLqbtI#gY!*Wusos(yK&WcNr~wbO68u`T+t zw1XmKAJ_QuqYSGW9kwj~{EaJMCoEnXIaj}ncpB!(ebpy%8P$2h_5C+2eHZyh90#%< z=*J4t4+C*K6q3#jHKmg|)LK(Ha4PtZmm^rMm=R0l(UYTt+m6DLcQpT=>*J+>VUiNJ zwmgl1B-mVq3)aCbaNcYljEtJ7Juy21Wi<2-Qf0QB`Bg3>Ka~CzcGsDN&T7e|u(Fq5 zgbLb$WLhdAq?sPt&)lg`YuH*aZIiO;rmT`9(h)#%qSVc?ZQesHsD$-tbBA0j@NxG% zJer)T%{BqCgi1R6ddOnD^4H=DBs<*>p5*APJ%qAlv<$dz4ha-Fi2Y+z^L1%#c&CD> zo0p<8^ewX~gNO1(inFk3{@x%!4G-=Z2`~IxE=EL=CA~$Y?sz?V@iN~g{~C)GnZ?lg zOPB-+;Il%a`v;X%ZPSEwjf#>#`o+xPmG5v!ZE~V^!X5$ddA&8G&@1?ch1T!DO-&j- zgOKJW?7@D$KWA z3t30nqp1$0hLf0s&g?E_lDnZ^w9sKM`P1&INh~~0D(gjVk`09b5a5qII*x>ScwP?9 zGy9@pp`;1lJbuj<9L7|QN7INrf?EWl>X9Vn7^lgfb5L2*loaQ zP}hUvN_6tsEM)Rl8L8RW3Mu>B8Ts92#W}do#oM!>32WwFym;QpXSzpdKn3+&sef$k zg#$(!msK;80Vn`)7?mvcJN5$Db3bVqUdv@TH(zvP=}C&!Po96`F7*}iF<9dSpv~*t zkGGx}G0UDU;{b-ayVe_l%@K0Yv>IR8&tcG z#9s8N-g2^+BK)r1+c0vvzZV_daPRZT?YTX(l&czcl`drgHCGsB8A*-P6iLu8V>$-e{#iz4q7UxhNLY>zm=_M63|_oE9$`~MjmtoyfEc*WNFR`^L&m z29w5F=DQD$v*3;WPuIXK&BNJWxLoQR>9aGgHc$6@M)>KNIO9G+;C{nqck9jkk56EJ zxr!}j(ie~eWG!6lLoNJiDoOL4voU#Dpq$8#7L-%Ug5Hy20?3i(7nSTh-!o4EvNCt~ zbDx8J>DiPNe-!}QmTpP)x9LpoX%FGm$v2Z!7!{1}|A*Iy)i z?k7ump*=?_!yYf+c!jKC{dFTRWjHNAxxY}Dp#)9+qIjp|W4Z7>8HE<0fLsxVu6O8Ja7^;bJ!KY9uWO5Y`J8XGZC5GaX zkoL;B6Ktg(tqpf0`z}+XsILhJhf_EBsRck%_})(oQg)@GWhv>o5~hXMUfvIc?a(bi zax9VJ`y#R-_Ed&jMJp7CiyKA$C834ytA7B6i7-W#kalUI9hT7Sa~V6>&KzglAn zcCq7XnU;zv!hZ;?RQqafepzi9eiqp-3Sr8QW5pqWBLn+prsjv$_lmK9=L%^Z!SIpW zpGU6Id8}dRO0>_CFI`)1p zX^(z+R@b$ZCF=v~8pX?g1kh45pB&FW7xKl`PRblqsrX8NLurrUPL0AzsYiT~K|qV5 z@T;~;do{i-_yVrgTmH+0f|h8f!}~2S3VQLRbWy>)O~Av;bxw1rfg8e&RsJ2+PTh@2 zV{>a@qF_W-53vsTm!)sZqTmdi#kQZDv+Z(G1Egt1h70V@l5R;IH@NTf>?lZ_22d*t z9emqK469n6i&b+tDW$Grx5>xyQL2b@ied^;aZNS^z(}qgLyEJugmxP67HDav#hvfT z^%D2GjI-hc9%`80)4v-yuX~dFd$_Mf2zv>hvwcf}% z|IT2p8TZ%1M0Tyzr*J>vr31z2h9MiCK*<7Cn`!XHw!U`3aXcUe{6a~L$l3r_&LXm7 zb;0{kEloTgsj22FUuYnK219BnUze*RJsiv$i zH-SW=YwHe1MhTdWfnmz;^+bi775-DDwP?;%PY`1oz{!c$+@YM)<5`9 ztg?icE&_Ag316bYHw+=v(-2kPp8RuAG~CJx&_0jyAjVY(t>d=9qR$-2J@Xs}y@9LX zx-i?9NzF0e)Y*C?E6TiBgI2ayVg%hz0Ev`Mjks zej>)sdhU}|Qn;t-^U*xmwR_FJwc$|Sgjd_1xfZ4Gn%8gTAbWZc+NKitQBOpmSQ zlg1R|cpD`gbsl0|OI;__;}CW+yk-&>^%B$``$(1OGryiM2I$-b8FloWY%c(b`l}gG zL;F^u=P92))9ee+C*FNe?4#XN3Hj*PdkQ2Zp++|J{{DG~qgc{3?yR>~TK2q7?9N4|+TqEQ(YYpo3g^G)|_tm3!px1Af7VuwOSJE@UX%OJW|b9qiWu zAT6ugq3=;B!Yc}t1qM#Dn7eL#qYpq=?@kllhZ->Mx8!Q8X~PJg5Ni1FH{*J44x%7A zm2OyLg(;kQ*>{AVKQDKet1WfQfn=W?gL|$U)9`+nkkr@XG!9lpJJUpBCNLM>L z(3S6UfG#~c;f2x{NK_x+#Ir}FJ)%YFa$2@3 zW~7VLAo*~xeah(krpt;qYv*v&wpz1yBsD1Vcp`q%mo4zn@@-&A#j&G=xpyl*S$JKHi z?KWKC$Rg2G;}Q}aE*~4ck73X&6`$tu0;O>ibFB1HHA=7GF3gfJC2V|o*mRdxe`(3< z{46_E4u_?x6dD#wa+dzBekY0tfbriiJH`}SfAT>^BEY8Ur6I!u{*UzvbY+yAPRpr< zt$i4({NhWzcuJsVtItIpmcwF=yH^SQEzX_wmYXY=WEK6_Fs;Y2F8uV!|Bvht;RM?n ze^r!jjNPVJUM!&8X{0xJ_6bSvd-5eI)et(6ZrOJFU5}*(VR~ zflk;v1*3f{ZVn-gK%fcc_}J`9_Gu+JaLRfm8Sm@JS*-)+pA5T7r>4+m0q*%6;}>rX za+1~Qa6B9zcMx8SI~}-=d15abp|fQIs$O*1qh6-Eg7vx6YjlBkT3E2KJ^XvN5r!Z{ zdrTfsl1C~1nC_7^>yj|fm3K{HfEZ-bsq{y5j1SY497e7}*Nn5WH3zK(Eh$LC`*s4w zTLCr;NHz9Ev+sSk1wfU;Qh38=nILE|iC8%d&C34%69H_d9(Ofr&p)=bCxF`@36w0a zWJ_i=9Dr+5@(ssMzhIdNU|TB*4Zh;R?O$h-c~=JG9M`eIT7KH z=IC?o(hW?E{1}&vw%cm}`|-TC=@xCz#zrD|rftXjyiwXY)D(t!;M_MY7HT7c%_KPKHtR#Q60l&>9_I8^{lY+8sOriAmmZ&$f@saGf{~!36|;?ZgFES8mWek z=AN6zmw=vPQ5V*1h;{(b;z2dkFwJl3FwOc-PUSwoPTN{tu^V)T$fYcW1p3m_XVfwU}r9M|@X z)ImR7Xzuq>=_)N;TCl=KftKQra~awq)x(Fp=th39RGthC346NO!Z|o{TED)}Cd>6F zOA?FL3j1y69nN!Fniuaw!g%A*?dwz`VwgmrYKtl%J^TDsf;)VQwSt zp}P_BYfdwhA>4<4(GzM##hbMl<0X31yV|I~ZeiiOVsdaX?TRd9XYZg$yCf^-mtQM{ z*nF-f5BucxR5O_ll#qJ?MbFN>!1`WE24b?L(ov7NU~%g)S^xD|j}1*;t9vsnwrVF@ zLIL@09!0R+3K+1Cm|qY9k^ULIu81yY6UO>A!p1E*1->ox0MX`2{n(8r%BcvMBXzc( zQm9nxk8)*BV4LPIcB3m{#M9QE_Vn9ve%EpA5Q0Hxf2lW<6OoJ|oji5@A87?zA6dsa zyE?ZCfCfejx*ap!DXD`|DUrgMHrK2if6$Jx!JajL8^Q?~B$ZV*nx1FNv3zg*^C>B* z%8$Tc+Nr>Jhs5M`-Qih#dbsujk`&lF9q|$_Ek8bk8&mftyTZ4r+2_o>ivn^M+CRd8 z%1bm8>PP`9=|ge!UTtd_?$)?5PRT1i{p@d*vZ7@4BoAY%hD#rZ;#vd(B#C+5>u+4l?h&x=dmB`e>a%)A`N5a zIHI_m4BSLqv!DM`wehow;5=Cc-`_0}3lafLF8V}GJ0CCwwGBIm@_k1j%rA)!Cf?6+ z^tJ)2BhiSL=jG@oe;U+LE&xV~f2-D*e{BwcS8MfdYbo4m_o7k|f@*|K-hx0`Y=?D# zoI0)dq$x1)fy0(=7J`pdlRlD0gwc5 z`-7W^EsvCOqt z8r@pxD?~SobKyw5_CxIe-v9ulDxPJ?*g&`yvH+@s)r z5PqeAOv39tO~fPV8~a}kt#mqNn*IPz@%1&efQh^716|-O3{RY*0rO*WRqiql4VUw; zDT08>Yw8w^02nO3{PK<<->uoOm?uq8HRsw{w{(~>-E>X*;(M#E(M8T)|%yP%Wo^JaJDc6DcJYcgYi2Q zPQYBu;{AtHAuD$Xe0jCWaDZO^aQHucfppFRh*KKZUvI};{u*4&=)WnHE^cA*Bz{+key{1 zhO1J*@*2T~8cWlfHZx5^_nEE%O(k(gbzgUyG0;x<;DiH3Cm%2!YJWPJAti=0o{Odz zZT3dv6(2KcpAJ9Lp^RT`1g5{Iq>k|EhuGk;uIiwLrod9#ZA=~8Q$6M!3o2~G{fC+3(Qq(}V3-H^Phm7h|u-b7==^In_`5M8G?Zj}gbr)d5CB(*e(#+D+}2chVaWB*6WMeASED_j{+@6ge*2!8KeYb#dyM~F=?Ugz`oH|&SWi%Y|Gs~v|CjzNFW|{D=9s`hV{~ykFtI2tNb=FZ(Yf4X6GG z{?GSb!5-Lsm;RUd-}L{szM{YIf2;NP^sn{5_5Hy=ntx~inf^oFFZ>=PzP;=P{cHVq zs&DyU{lDJ-!Tss?m--+3kNyAaf7<+n|33ct|9||q4uETx9*+SNyyqO?i{g@M5n72J zv(&8WIZ5Wu+(XxVOaL!g&Y{x~_1wdz0eRJl0$)K3)ze5tVH!xeiU3FDvLJ^A98yT# z9D(CE@R2`%)@yKld7yAQ0G-0-I!wPslm@<$KBKyd0E^AYa<7lEXKQfLNlXyr|C_4& zpgMz001v;*x3+%RMC~JEG%ZCSQvo+N3b=&XXxEwVjTNx9LCP9+U=% zalfwS-1U0yVbc@)^3i%Izbu){Bj_Ujscg_O5-=>Pp=)s9X3tMe;_G(dYaAlUBNgm&yL;u?Bnhn=E zILguN3ol74qgCDB&^S3*^6ah+HB<-m{ANF|WwUBpDBrEih(pCnk@Ab?Yw_AmJX`0S zLs<#Z1MKyY!Q|^&;yj~T6wf(L=7o=B8!WI=LQ~@W|5aT7JmQt0qUNsDg@~9}6k%ZT zuJ8w=Xx*fQxuaGEdZGuye)g=Se%wwc#q0Z#ROR19-0^5^32~)Z9F|A@DD5 zyx=KivCAw*x#6;^NeNf+qfUEwrjRDVL?Ge*@Ad!Ecw&K>i`ml_G=$nO`q<{Gj)El23unD?y^@ zH6(d|r5^N-HN525(fp$2&Wjlfld5b~d}bq~P>l+ep`k^#99yT#ZJmd{#GFLTL^+8S zj!n~`5!nNPx$N@6GY2Hnn~xarw6qL}c3_JyKnVc(o_V8>AfChc4u>A&HG!jSjkP5& zXx%MXB|c;vNRQ34J-EE@87U4WDuvkWlmx^Kc90W!0D+V-78QBd_ENMoe}%0X2sYFz z>Ux+$h;XckzG?*^JvF~zOGieIL9)0IVM0t(rw#>@Np@K@bk~qJq8lqo|7oC-MH&Sf z2_=-s+Ya3J6F7Le9wT)Q!n1Jg{lI_yfE;jjo3_(J9P>}0jY-ZU<2}>KU$1)L&xD61 zSBq2jYUP$MG{4sQ>L&W6-ufzGjoB=}hi^%h<%DepT#CL?vTR}9yHyn0uy*MQFl{$B zqqS-fRWIJ$n7@HsZ!f>;f>+KX3##fjv@^PUiGLBk$xhRTRy9@OEbq1Zh5R#8(@`JV zq&4uO53 zdaqG${FUeg!O7_8iC=fRDn$2dj&kcEA2`GRMWKama_Cv1`&oV3zNw-LL2>>+B*KJ=QuZHM;d`I~iW#%g0E9Y4(X# z)?*lqidRe+wa_O`gbL!s{%(Rb^n%+ntnMV zWX>G_+iJ4$w<(8@&EQpa690OqdH5VdSBvANnIR05@KpG!i?)UNrZhU8p;UHZs6qu|FvG+Pq0WYh zCVuWA^gXDihBZ?%UzORH9JwAvw%RZA*MiR+qn4_o@J25O4xLM*(t+8qkt2ScNhsy;E@EsM3((kcmylHR=p(2y|%BMw%R# zh75Bl*+LlqbXMQxZgB$y+U*?*i8`_{N*Bc!;$b{&i0HRgb+W}v&@RLo5tF3>6s3$V z9mQQs*?P%u|G7!hQyv|RbhNQ(q179oqg`b$cJ#LE(n_#d9_G+Un%ld}c*I287;=yg z+cF!F!D(66d};3Fn_)>CCh8U_sin~J?yS)h@V@L7V$`q3IbaVq(g|0^Z09Qb-pRN+ z@WmjU`WJX47lhDFJ}>FY>U3;m}9NWm*`EN0RSCThc#!F=>L6k;uNM# z``A;|u`i#03v_nL&+q@c3yM;m zZ*&|zr8#=tM`UNZqv=5A^Tq%kUB@@+vCOIcXdw~vLf~NOXP+k=5zBOgtErOb(lYAt zlv;%r)m%w0cj|GrK^~|n$il@CM-n=w34fKr1~9UP8liTAAb2L|Wr~#(YydZ1UDj6Kvo5$Z zz=GhrRw!lm0Dt~}ixE%!-rYttJH%xb;tTSKs{-R}G{GPO&}y*9-c>l}G_NscA%f+X zsqs)SjUV5xO6W=D2quAIE%Yb}$>BG`WVvMjr-i#;)<`sf|6NmXVe940_e2=hw*o-4zJNWjZK4AXS;Sse1^g32(L91V9Ee|Gx_ z{V3IMoDWr7syNI8d{Qnn+lX0em4F+tWTp1`#%5P||4U`6p&A;ySYST~$H+lFwNek< z)xNr{TxSRFC4X|{OLvW>eEag!sTn$sPH$6r#|+bLPpOiZR(yA$=a4L5tit;=Xuq02 zmf3)y_B_Ef%D*ez$sA$~iE=G(%zzwE7*gt;)cs;XVi4e4oJqMLrPBaah4)E^u!5|Q zWgl3Ct2q{~C@n3bvgf`Z%|o!sO04-I(xp!(YU(1u_#&jN;QCj5q8%1=CcRrivim8W zYD^EFJMi#`lc<{5e(G!Q8iQv-YUU|wK9&*ORqI#2@gOv9WP^{K>NQ(NAVjF*d>A%FT7he zXdVJE+>~d-00ZiM0=!g{lnL$WdeOp=#%jH`E8~)<*;90^=7H4l-l1BqCdXm^Oi#`s zfm8VW(-$E^@wYHEs4;|qVFK`0%db4?kx}b~A1P+SPB@x)uRojnxQZ&XG@&I3rHk^f zI-YZJ@lQv~DFz%sUzXyr0?He$b3jbP<_doZoNY>-~UHcSGqISh-y(76p zR8gX(ua3Wzf91aN-EA!5qdNa~XwG6U&WNDM2=i0nX{_EgnKFQ{JDzVXzeYKQ5xXdM zeQY_6mfb1!^XMt1f$wV6yCkZJSt`^QjhbDG$%LkC5r8{VJeBp!4*>3`3fDZ|z}CI= zQ=UGfcQss!dIr9kx}M3}eYuYy86*!}H-@bev*&ZjE5$a6LQh;1E-AW%foMgzl`fPO zn97%0Y`v=NDsE1|m_v!H*!*Xp)iQ3O53RvWm(Ga!=RR3$ACo#c6m$oup)#aRGB~M5 z7|UyUSc0hXw;q%g})*U~xJ@FLXam_vZ-B{FOoTnL^& z)vFhC6^7+diR#gXCd*1w&TBaF|LWAfD;65RK=pPVoji1HGd|Yb?#yO>d@q z(4oZlgG&Icv6I|qEa_zyE*1XOCc#T4xY0v=E+?t;I3+;8mjvj?tYh94@8`hHfiL=o ztyhwW1&wr@Rxt}r-&gKP_1`RAqFA({fzl$Y0ce|2G+@X(6Gh)C%{*-;@DtyzAZOxV zygel>C}hkYa4m`9mWQgQaF2nr$LQPNhxhm7G=>jv=(**1?SL>}6d(o2$&@adN1nf! z2FJy_GY-5e+EnurlGS5+6E&U^Y+w$G=DZ7QN{(cT7|%vK0c^SL`l(fdT3n^mrpeOj z#fyZM{jB2J1qWX0*-p5#ya}J(1bODH@>x<3f-Lld9G>8;GbA8$M>=&|*^s*~a9U>O zILDZmfDuS&MZ6LEK8fr0CEE=8$_PvBh8By{eEL@mq-7q{Ud2@`b9CUqyM-)N zaM8P8QwN23!vql(O>LE*>n)a6_3uF%W@WC;tID55Bg+uoA}{S|t3F#06H)3O6iiS# zjK7~LMFqgx*%D(68_xH`cD`pa=XP8{Z!Z< z46;FfsLLicOo_J(I#|KH^i)3q794nOz0Mlj;*Gi%Nf?UbFdpD65Nq=aR9smOV z5u*)j%?`Z>HwS-#^$POlb*U6^$|OHkcs+^plLrB!T0%Y=r0lGY%`%b!Pw_qo zm8fQe8lda&OxP%hH6q1M+}Uq@Kh|hPeL{&M)5tNt7s5xVb13c2ssq)6rx`?nS5#Q= z#eyv?Y`VXoHMSWkgdN-XL`=CUAWrBX5MreOGFc+i{P)uANRr(e!o=FVl_)*q(@uR9 zY@a?Dv`!91Cu~g%E+IU5h&Y4Ea$RqsDTMlIazSRQHMN;bG%$op9 zn^Eo4OU9)`6t2Xet&AB#mF^<4rT1y#i{iio3NGpKhQGCXr-ZDHJ#yrrtokz&M}myV z33g44aGW2=X_qjd5bSDm{-c?~f= z{n1oaZ|8FH6PL-YRzR@&Qk54bkAZb)M%Lw)_z*r%3Q#k;%y#66Ac9=)p#CQWnDIon zE!WGoz8N)1zZN>|a-Ny=EGbR&D7cBJ(lrL9KnwDww$dvco3FcPIa5&S#fzkv?z6iG z=DJYrKD}>r01Zy$@+wBizvt&GKnSFjOk1*&Kr(SZ#hg%aGM=*NWyc`xHM==I0|_>D z?0ah&eCM}T|2FcunWz)YrC%9UMz$Jh!wjX@?bL0Awfp~|8@}Akv50}|u(HM+ISHZg zq0T_Y$*RsC2|&lXvCM*I%{nG*l6hq?l#JwlE_#cJS0!^u0d3{L-eqMj+~lQSBM9jYm$DIT+zCeFc$N`Zn8ai0}4$VE*nV&+i? zn&7s`_-tBlcpwdoWI&b2XZrGc&t@Nm8gN;*<5W~vT9j%eLA)ff6a|u#2ArauV35XtD`_cW8=|sKhAnn772}k| z8vfe(IzW{gfR(CnZ0UvCigC!MS12&o9!L6w@i%U!%z%A5*0LLE;&}AN00a6(jJIt$ zcs2!~svghZ6T7iFt`6O(Fl1~d6GELuFp=)QhK;t$D6%+~Y`nfTyBkXvEy4bHE(9xb z1KvDxvg@gmB+lZn@AC%QDc>wF zCc}?fYrnj~;NWberrBN`N^@tZLH%J)M_P6h$ z&!m1zfB*mmov|h8Rr!3yZ1SM+6m(*xJvVOeuqfT>2>{rVm=&k}&@`*-U{qbu{Zh?u zCPYj)yYm(fQ=r}j&lhj9s8{oW+*!X#ilaKxc6yIRa;*{+b$LDAGLpK_$GKcvs;xy& z;YqoaZOVQRbPiw!JqnwAKVO0`Qe+SryX1;M&7b<_&%$=%uSZY%0-9k)mpz$a2 z^o&KQGSAw=w_xI(SVtX6h_~ejvMp5EN8)RQanu1-gUCW;u!vH~OByK;8{q_}c+pCI zJUoP>cJ1l;EUw>XL|t*PoC1ZjZ{*4<${QZg?A+XZHKeqN(t$6mft=v)L2?BhM$}+S z=l`l74J)#)PXR3L_&ZZp@;30ud8numyd>4=zI4!@bBFrFH}xW1?vify!>mf$Mg|!L z?qxbqIKNW=M^M+qc?6rXfaSn*u2T?K4lH_}jHNQ>YFA#j9Pfpw5Smr zX!QjQL%O+IOxo+|H2fAROAVdB-l>~?AUvklxg)Znb`UdFacA_Qx{~mL|+DI4$hxQb*WIwygYRd z#@lja>J43>g$vZc+xM*&Rd&;XGY)C4g;}o0yul156c&GcjA_Evm>w)K0RwRb6i*M? zX`O1eHUY6Tij{bYC9s(9r%`5VvbOjFscO8==pVd*?Ep1wOMFD01U$~;-9&l|Sb|O0 zjFqpgjGb|HAT3128&R6K5h!ozeM9$KHRe$w2c6mX6&<^tEPGB@om_F7J1StU=!9O2 zxhlM9Q`4=?Cb^s5gbI)^c8IG9u&Hu)gR?cjX)CgX|JKd<=o8Na!xt6SuqThwL@%ht za)mWZEW-UKIV@Y?VX?DSm@GYVJWKzP2RIpq$$o9bK`$rz>}Zc~4!^Jx$QlFgJRvu&mfRfm8QQ`+U2c3Uu zE&Ekxwd8Z%PH)vL#{mBOXutlGI+lreUWO?VPz!&B`xBmtW$02L$S*VjIB~z_dSxwGQ}94CZ;sNinIX=S zaP2a&^H0>z&QD9HXrreTH>!2&UR&fILFFPwLYZgSVz~aa#yjMewxtS33?ou0S5%Zxb7e_Kh_>H4 z15ly20V+$IlBL|ipT`IMy5e?)JrFEl5YT}BlRD=vrV3i01xI9ICtLnd?|pWdzoNT_ zEH&!%_iPNg1phJEm;$s`P3p+zm%QOh`sq@B=b3r^RpzVY=wxNZ`M2cI2c5Yq=U;RJg ze(L#+3Kao)K>~g-dM{ss1+ek_ZOjl`h>J>Jp;_m^Hj6jeJ3y{xR$Lt2KT-uI<-&u_ zf!-Jjk^fKknlB$)tg?`UK^kiu`SBsZ6Bk_+Z)h>HkM^vI;_wOwPGQoK5eN{}=w{i% zf2VQN1&V=z35U#O6R7e$&$RsND~>fNr9KLZ&RnHbr=8J)h#a{++XfaWy%#KonQ&vR zSx&e{=H!`ZU#opU*hT)(kRAnepkm#akVkR-;G{hd&J&YqTKuPVhaicZnT|<$Opb7n z=o3_ta(_=g9D4>r?ljwk;)@q?b9x$5n6-&KT&+44$Qi~HQ;;3?XIqh!k{P8UlRTw} zoXD0%uCX4NIOW$3-*}*?2YZIf)lEVqMzRBNXLM$=Cws!=wJIh1DOtATkZg(tt)1X7 z+|P=sQj;4e9j%JXlY*S_LMAApfyuUs;nl~(+3D^1mb=WtLR|!@0x?g65HJzs7RahW(DYu|14%k+Etwk!+aeyic*bpD$ zP)rWwwB!L@i^J#uKJ09D!|qfL>0?1Ae-<>gkLcif?5}|@)xTqy>6poEClN10jQXiB zp&Q(Qt?V$wMhj%RHhV$kVSeHAK7fVDzJGPMBwG~q45pxXmks{wnpb5}6I8JYeYFsi z@rW7FitfOZ1WxU+6L5aWP&10uwoy&3-SQR~!Jf=<0q#o`hMp)lNp4qRi!3y0(afzn zW*(H6yz8p`>LCU6-g~HRWQ(YY5jr>J|3Z+n(WtdZoM4(#y!}Rvim^a8jrk6gzIlkU zxAd&`onUqi){em4$%vV2cx$|aQU!5{Nm}B6B^rlD0%w^#U@jS7ilBw*oR`WPV&HF6 z6`}P$0*MenG39n7h>~a-5kcrQVS^dzn(v~H#=e#^H%)TRFBwkAMc9)cZhWNbf0hbc zz&_Q^5V~XeEvX{x`WbV$yQ>6F%Jai+KjALm4Np-LC@kVBs;x!T2AC*>c5-ZKrcV}9 z+TwDOtNVm9ot~2+y1il#nZ1~T?^XZ}=2EfrMh)v*<(%5G1Jlu!qbIBFBGJYrj$+2U zvin4-ki|!EV&duj0t^S#gDpJaw3E)pVuQ%EzGR19y0TpBfh~iVDM<+Fpw^ii?!_z( zDs|Xo;XJU9JLSI5nVyeV~clZtgVy^MFbz`>LSVGKYaKnkAUL%hU-j&eDU6ZJ`d zf}rFS_gX_+e!@q7I{})7S-0p8Y7IxF_&+dGnRYo_ft1U|o9Up!_!ANVD@=2OzNl#Y z$cuB+kuOs?UczJzUpe^br~I-#&`}Wu9NdLnmaG@YX7g*S2iTljT(M(ZBResZ2z$CJ z9kIETMvdC-8HMN}h2x|@=>qx6s%qQPD=p^_FZZod)CJD5{Z$3Dm9+l7D)eRl`JrT^!qdI&5 zF7>_4qDxcU^iA$_sZH{O0NA(Y6xXP}0(5rO^|fX!58~{W$UNi>F~EA=>Vt%JC#*n> zX((?U^{BoibX?6LqPv1#I~21kWYk#w6DO(*_b?YV>tZ9eHmHM{G*HoE(;rFwjzNb{ zuDE+Mq$5Z#?ZAjuSOmf=0NC7AQ=MOE)rMLLlYoq0#TKmG#N}^g3fi{F2L8$Hu?y(B z3)l)leBIZ>5^n3SzbFs2>UyZV&ij#$Tp5qVK z{_MDxC0rbvTK@4On@8{v!ku+cAq3NqbS`3SHV<|mby)XlXOkX;LC&*t)oy7`I)%%I z$74z@`$a6VC{HBTK^QC0=R4bI)Ogos)6oPXN`|O_db!J+!ts3@9?`^edS|i}7K!h8 z<=ae!0@o5~h{G6LEGu`*i|~LNYyn zdfuK9C)JwFHLNjc+kvx%1-|^0m!3UUqY?y+{gq)HfM)qe-cgA`uwAvoN35XdOHs)i zoQOI6K1x!rO{$*vtg1UcI5opuJ*r33`oI-J}`{hin*RwZ4A6&4|^ zhc2``2i@zx6hSGaZIKXMC|B<#V{?6sD(`wBgGp;HlWj$RWrf79GbqsLm2(+qZyafR zr{{q~nKu-~h#8cTXrbcCr-)EnAa(qIo6d0@mt;vyPbR;Ds@W+YO<*VFlTq+&@bx=^ z0{WVK3zv9XBW`_w?*?!GE6!wDCudt>DsGXo-0+&-DX+a_P9nYZuc3Jdny6yXZRYur4JkAA#UhUhtWD3JkYu5Yhz+Q7zgknQDyium zaF`z}l*%(zlcl~&P;vhrnPN^?)D8=xYe2o=S_F_VyHUR2i>|yMh)`$PH>HJ2iu;|9 z^)k#~W(gfy=g`#5Pp1NjE*oGsub}4dniNhaEWgyvw zY2z+1gFppAgT2_Gr8R!#6HkWvL-jOAwmc!Q-a6}KDZS=mG)8`*u6Vj2y&yJ0{ByzE zo*uD6Dt9+=pX~J`is#^~gskJ_BaI1A@fT*hq#5{ir3(m?YSHq-Ihx&-bg3&QB1|La zJ~$2YL;AV~=kfiP2~yfo;iy;x`wBqr6tNup#aDE}S#uHS^AY;>(5ZnA0L3GRqDk4vxWSwg3GKVrXe$dM7{qXI1)3N6Fg9H zZrcI!YS@7V5pYuKb;BAuSL%iUs;8Y>?~CZ{qJqLz8VgTxXIx^rtwwr6TQorv_9a`Y zCkEWv7+mALYd?C|6o1C-TRTzJ^v`I@RNlle*$mz(?vVhm(70&}OM}vula%7uy{ewS z#`X>`-#)6!xA`t^?RXG-KytSdAlW{Ng1|L;7_uBt9Q_@%SEVb@P3E6wTGC&gJH<(+ zC?*e45IPlzIih`q&kby7P)arbjKQiXZKzluw>$-vOzY)D?-llhaZ``~x;#C4=WEUy zu)EG2AQ5q z3+uU4$4>ihz{!m+_wU9kXH&G#C)^h{F!S6B2+Q2F<}a4;sWsbs#9!&ePCV}paepPN z>zz%lS-RsOk(Y)LcNOA*EyNTC-gR#)ms;FP9v3k_xcvq)U6OK3vL7J7oEvU4(Ddw` zj}T;pTnZFDrhu{7bN6wt<#ghAtGw2N&KhDBf+kvHZDN-cQIw};tBGhk`*kbBPAP=| zXvWc8WeuSBv0-xplBj6ZT}gb2hUw|P3BC~(JRBoYV++cUezLWaj;5!=E&3z_&QLzI zsvd4J(LPB^Z-nHC+rPeC;wd$KVqv!SBo7k1Av2lWbf2|f4>u5cz`JcYA$>p@yaL}0 z3@A$va{Aw>v%XY2&=cq-=5t0ghzlY_hmCglh7^Rnc?4BEDk}v(>d~&9+b;_LCk=uB ztQ{h!6ecu0UU-;q1s0D9=y2>1CUkC)s5txkO3ka0MBldJ0(FCjsMohc8jA?(9tAAb z>7}&ylwtd-!@Pj82>M!1Fk|mHORu*LQ40KwSc5IggdF~Be&;+Mri-~9x5t!hZR!vN zAZ*PIt_h_G{Jgs?d(g!+8bX#G8)4&(o6E;_@y0W+I*AGbKjfi;GS;nu@F<`TQ^!u~ zu}(ItCBnPdB)&F{hFqM8MG~Oj!1Ryy5s;^~SE$ZLvJ&fS*vJYmTOe4`;M>a2$g{_y z7eeKk1)yB`oR|skrZ7MD9+h*sQ}pOBz`&mh;b9cd%1B>+h@S-EQ*sen#S2*-bNoh* zhz2HSJiO8|q(1YQC(z^FqnF?|Q&l;zo&=|-x+B3qtlgT5#c-TB_8w$F@&dQBf(-RH zCT3k(Ei+4OrYDkTa#+_XBg>lhSJ2Q8IWGHjr@OzIN)ig(RF1K#yiYCzcaVx(zuen) z!KO|j9^rz`diGlx#%wE)q7FQoU)T~=Ttaz3c|2`;e5I(^WG?$*igh5)XiFwkdD&1L zvVofad4Wa`p%yGy5bl~m9_v8NeFW3_V#FJhRUt^)yWN;1w#(x-5j;W0j<>EF zPB`(~njn{A*BWWxDxaw6iuq!IJ_3|Y0GEl^P#d&Hjd&ZtfMId#4eF!mblK?{*zbF} zOkN}L4rY`)b_BFvZKJ(1ieujuf2-S$#L^78k7*W_FJjVn1}(-@6@DnFh>v_jMT#Yw zpH&N>dJuql>$S^87gH_L;_X#6x*oF1vWIl-^}#?E0DD~}i;>2n1Vw`)SYZZAmQr_6 zqbj>j0=0R%Y43v#E5}(uRdAs}p>mauSt~KVDEpH%9=f$(Xq(`v+m6D9!;12yHQTg{ z;9`hWUF+Jmz3Eq}_8wEt!%FE);THxJY!T9%xnlt1;JbX^fEyC9k{~TX@RQsh+JB>xe z{-+vgtQ7A?8HR6wn?gcnV3LxF>cbCL zHDwFTOTf?cSz>cj1zFwE(tHwnCfBw!_E^uPp{r7QSY7tgLm0tG`056p2+c-~>WcMY zmzurO^d@};FZt_O{!>0y)Vn-kHt^Qt0Jv3zlJ_HgE5F9MNgky@3V`cb@$``;&B(p(dSjJIGqc;Kqu{kn;p3Qf*OpirTH>xVBzECTj;M8FK2hNYgg{ePK`O*&^j`i6 z=TNv3I(MF9yU#6k;rHTGpAaIJB!mJHWiLnJ&26usTZB33oqq1khdXf@v(CMd{_UvI zm4=j9jpCK3bM^z?eX{Z;CnMyo?&Kc6>#Zh;>AMO4Lx-pcyHfnEis-~`6AVWUg$D?> z-B;c6LzlTdU?|HziNk!BrP=Ukx>O~`uNgW?C%zJN0vu(95e0`@z>sr3$On;M%a+Q- zGYno!FMmPe`Ffydh{h2}iRV(wQ5R)1f-h(ArMR5) ze9I!sN5e!>a(whxOArTX@-_=XWNhH^UFAW!Q@ngLz5dKU1Gr-Tr|qt>G|sN7Vc8sd zIuYwnWEezAiCJ>B5YaORdg-TKoG$Sa%whu098TD7Y^#_n|N9#K%6n-XbBqvL$2#+PwH(TW+gP^0WOhr3P79;eCUKRXZ<>JR(0cx@(DKA_{Wb_ zbogI~Hck}r1ZxJ%qYOF-&*U>F1ZY%137 zP452t{jHT6V3gipeywpaFze{4VxK5@vEW+6zB+8>-8Y_^vK0LP3rX?jM%Wa!M{GYy z#h?YL&GXc<)S7gIug<2@wey56Q6jP|BBA`d(~2sfMTU-?Pb&x!mfNOQ!IFTN>FX~A z;lwi*WyBgtrF`gD39&cmyUMY5fA*C#Ct+9y|`^`NxYj5l&+8h7p8h7fjL+ z8fck$<*@x2n){|=jPDN_wTU+TPs0(PR78})*$-;t9ZNP#+RgDm#nIVOf3whZ603(t zg42b$$Z&PED zVLtJuVX$JCGxa`y*Ne`#sQ5raFaR1$%7IddXGn{dR0EiKY7j0G4)#7gOG;JXKGw1U znLYqfYEuz67T5_1LtMGej8wjxipyw8Ttf3guDlrOZxNZY>Jz;pz03ueI9>$Z77DHA z2{o!M(?b3J7jOHW)U)xj1aNA;850BIe}KkT`d9FR%i(gplc6QJL(ZHs;a`yUC?bz1 z>`$}^x`tCEg%$bkjEBl(J0RyI5`?D@^=GdvL$mES@E(j*5Y_}skzi1r>)L2czTCTT zUUw~u5gf&>K^{`P%nr8S`uhL(XA=fqxeT25ICzW}|JHwPHFl12;J~1I=s&QVd!apm zjF?HyT9>x;dIgX%uCC~?ZLDo{&iD#7vw7^Ram?2j;_el60PBV6HnMtN+>J3ylR>}O z_=XZZwPM*i`x|-p<{h_zzT|e%4?oBvk{yZ1M}*B-8g-naJQP6)rkbz9pVQdexk|^k zpDjDJvr}PJZv6CcR(J(?p&EAnvmFbrN9V-4>-Ky#@SQ@{14BP9$k<^H#@K14JJP9K z8umd>GFhFdn-fRN768mXyEeh;x$;10T6Y|4>mPPxWpp5@`Sr?E#siT8{dlypt`v2ltDn9P2u85h~vVU#P zJB%FXf}cFq*QvTfK9O!IBUEhN+OU!@M>bWC8zuS8!Akdd}&;qoBt2hQoD5ea*W`dP#)oZLK?s8A#JP6 zVQb}BZk^rU+FgRv+sGPSF(-=0h$3pZ*$L26Ghg2Br*U23Li9*b<*(r|TU|e#^D8If zdR|$288|5a<=ZFwhu3aOdgkYF!DAKWHO-eIs6ML2mM#Kw6G%iV$D5{fk~&&XK$^Og zlZalxQrbi@gOC8k{V>fYjq|Mku&G@$zFU03O$e2aeR>=LClg=yUvtfH-wPcQ_QQe$ z^jyyfR(+5l8Kd#@#*2VA)M!mX?*Gs^A~FaOI7mrKByp)}D)YjgB!JaL{@yU5S`9-( zX7+L>BQZdmVqdTvHqYCkZ!|cWph z#Lh>w3H61|JPHrCvr)6Uah87UDQiJl&$%1#3ku60acijm%=~WpLm$RpBm&J%o^KFs zN;xeD?-u&PdK`nMMcBb5qMUlZlsQ+@C=h`^V<9QlZV<2nd&H3wR0?Pl(O@yjE@`1# zHJTa9g^*?3MrnPujFX-M3}+&{+wZwhEwy7&Qz_-!lR<`w)#azntFp|2xjn7WXW2WI z+DF9O(dBjK*)(c7fIN-#N&|tfZWahXbsD;fU$t~|nL;ou)%8S&&aK$z`BLv?zomkH z&1~TlbbiD5kNgUF_&cZ1NO+gQnQT^7oRg#LQSI^%RMNK?ZI3pqdq23R{mCFwVgj2N zL#K)AFRNecXaE%5ownI@p0Ed zI}3z;_Jvz1z>J0UCJy5qDd?xJH|yn`9zybLDdw5QMH4H|ZM2KYGYR}=;_7l2Xv;6# z<@3bdd+&W5HmhE%pH`cTk-_U{TC07RBW{gz9I&ZBPFFUv>4A^hwv$52%H0Zwa&XqU zNf>EnoORdWabV4K$D!U1o=DOJPA}1i7wr2H!9`y>o_%yxrhysEKcEnf_L(XovL}nd zSZ*s&jJSYR8_Y?$U{^;n00TrWhldOr5T+m+A!r_|00If$-MwcSGz35@pbd!#Ycm2S zLLj`+P%g|h%Ez4N5JZl@Qn1uQiwa?*5SE%Tih~27(%W$vhU~n=5#!r|S4;@;>ED0XNmecpW z;f zMRdzFDe!g_^;hqmcoB6khT$TzJaDtW15H{h@Lwif zE9B}9jIo9FQXvtLoh1P8wM{ot?N2cu=rCP}FnZ+pZM7P-Ocx5W=C!xDYsbcGtA&8s z#W-<+MYXI$^)*FIQJaB)HopXsq^`~vZ16r=;$fCmgpa2J{hJ2EbTT>$_fG16ya8vMQ5Rf~d zoIp<>fX{XIXAV(0tAeapfWs$oNqU62=eos(fgCmy+6?K740m>sygYGK)sGWQ{?*qmC@wrxa){7B~8zin?u~V@q&m=8ulO2XSIT#wi#a53T zS{~%9#1afSLorZO0YPRJuPUj=auWHj^Ai>MIx5TGndMe)BK#JMH+blv`>Hr>0$N(L z#<}qBN{jF0N@2XEI?J0VSs7rhGy85yZXblMCeAfo^$0L|8QxkqhWlC6`Z3Ia9`q>9 zZ+cN4BF&`I1#U)vTJfzvwRuPek!z9$`1f~O>i9PeZ4BVbEX7&3>*%pWp_n~uy8X{c zO|mlhui$bamy~3#zd4)!9AUO-z%V$PgZdngw;x`5T*@SP1p{izld%)~@R1vTJDaFujo1Zr0oXrk05Xif zF+sop009BKvI4ThF%nZ9rv=H$C6H1Qf#SljQKB`XuBfJheTnK`rGM$UGCcG|#Yf zTNH)hO2J9GI^&f)6B(I`h)Y58`JQTD5Mga^* zZRyS8{SufkGT2G_rs2=1Jwg-VwRvnUV4Xss1K13+arg_H&Ff0g00LHPTnB<9JOY8{ z(RINI;>@GH?V2~~hxOoOP&saQ#4?Bc?;FuOhDfYe>ul2l1s#@lWNrnDNu>=J@~vX3 z_Zk@HKD`6ib&zhcrUT@fBVs!3kV`5t6EreQ>AV`Rp!1M1a)KVm4%FW4*!4b_*7-x? zst!PbpZ3OhYr`$I#o_6T>za76T)7uv%7;w)_ zkVIn<$G!ElZxm*WKCpzpy6LvoO#y)xTmoBb>&Gbd;(1?&a5Oe!2QhMpTTj;HczwXp z>VW7P{~$zO#ejDA>uWI7rTkJr;iy(GS>Nn-Yf((L86s#>K`U-xmDB|H7Nto2@Xj&t z005~h@#6&4^8f$80<4V$C<*{d8`ew_UU2AK-$s^i`Sl_7bQe4pzzBGo!(d!WnrL?J$IYA3Of}aO?YR;V^keh0ZHhp z-~aVa@RLupXPi(0NZOu@*i+FQcbY&+fk9R`wEM$1eJig~Li2}A#_E~Clk zd4jKvm_;eZ8D(hioIdiW;cA-?vvvo>*Id*k`7b^K7V& zcOAiCG*kP(^_4A^6dWiVCzJ_ZNmf0NB%{VMXeHIO2Q;*LdRq$*}N=8>TEE%1Ten~%Y#=|i92*{#@k4(Y1YeH z#BI$jcoq!1Rd?mok#t5t$;w8E2ra8IZA^Cquq80HNb^{cSun04+dT~eXJ#|wv_EZm zU<`o-c!}3mYpFP?yuL{2{i1N1{@7+c`rWQD{!Pp1pn)s%Yw{Qb4n(9Cy0^T&=fE16 zsj=f01`*onMo z*Kvj$+*Dopadnk<0UUr+6ZE7!d?*p#(o)XH;F$K5fFJ;ErnR_h=XGaRI2$V}(L_GW zf7%`)jaWl~?==I^0lX>d0Argmh2iR!U`O~o5J-C#)L5h*GaERyb)`w=J8w3nK~=sA zE-ot?3j(7dEf?bqkU~D*zdP;eoy|c31TQJ_9W*eHB1=s#1*MJ($Xxj|KrHFTKv0oe zmsjwaNp%>^l$b!}60(LnxeHl^(~Gy&NSMrMmFE;(rrh9j9Luc%gT&(#e&;tNCrZ{6 zij`xubrH?ar}WJaT|-&!kOuKI`HdDzQx?nL);-C9g8`B|VRg_Vfw;{A zu`9oXsLgHx&7_Abh(qGZ_I0hOyy%%g74pdvreM{uxmu?AciCUQO6dQZm{*B5avz8x zol0`0l(Ep+_JN2E`?W1Rk6Bmr!9vV2;usbEOvZ#n#kI0t^=o5w=n(p!>?mG7z8r?0FJWkq$jjjKci7-f?V$s9hWD>#?G^ zDNjlDs7AoKwv$3)WJiSblINT2uKzhPSv4D z?q?+@wId7n$Fin$dYhM04H}ern2j*K>fJ%pZJ%%_Z!I+RTg>vT*O?Ci13cY=dOAf* zZ;IO-C1u`GV{n@8_Y&4&{$^L|h2^Zt>|M-Kd$H!~;<$Q-r_}ULAvAu9WLFBwwyNI!Y&bRlZ!V z4d&u5%YxkJW|aTj(QoONlM=0oY&_>K3g+7yQ0O(}+dBNQocA2KRsc5rxgd%2#gR14 z2ahlQUBqjTS6j~``EbFOAX2bWIb)fKbh)|=@Vbua$a6L;=1gzr5f3V3ZS~!Yj&bEh z$>SYHO}Q!0OjYrcD~%tE(u?l3LkLJP1HngK=BF-}w1YhyJf8CKy3+<+apdMPrc&}( zG!bcM~LPY zhg!g*@O40d{yIJ7yQR^@4+`eU&?T%7YXh{AlHQ`{lMB;r!EH+{6qyWd<+$g{-b3K* zxoBr(>W0a`gR#NUO98KB4=2O0JOCe!Q8JU?cJ~b)j&W42 z@(VJ`jRanUx0?Bu&<{?Qn>#Exkh-se&5_}JAf2hT9+sGyj7^8vwi*(ou!)*w&)*@* z%_1@YoWHnO#hQ^$5w{kk8G6n9k>zVaH{e07E{%{>6h!ORkFR4U6!gDTsyjNPK0pCh zU2{TYT2h6@IQO1d$l=*y%Gc&s>??<6d1ck@%mT#j>lr(Ie6 zG&*q>7BUeCMiYy7pzb$4oZFx~bfNOFI4)=A7?zxmdQV!T?nGG0veU9S}#XeRr z(hR$@(NW(*G&i9fKLVz8f;v}w$0w7`ehA6QCdD{%2{lV@o{DkO<@Io34XbR=Sg0F4 zpm=!P7n|B!xEVzH_0y~S%_4BFP*@4g%%Nlj+0^`8#N(95On?jjXwm1>v(&1zv5VQ$ zFs(jI+ui9biq2X+`xk%hP;FrHhp9o@6P@^Mzq3 zOrVBDL)Mfmpc|6<$tguiMj+2~VZvCDte=pHD1Wh00h#tUjYS+5}23=Dm3y#oVNHS1HGs6vE z1`D%SK{_`8qVDaahdd)`w@R#37MX?o)K%?rG4eZeg3A^bLjA56_G5LHl!cOk0kBCJ zLf|XxCZ#JtFmegBIT#1b%{0YDWyY%Dc`v5-$#EA!G}g6NCAc*QaW(d#2hr{W}qqP90m2`EiF%R zxyTSNxT+SOK#O>NoH;zJT`8Yk&>-e{;2`BQS;tBzhq+)kiwrSn%GQS--(Qf`3@q;E zl}pTRndK6!zGD1~OrXW8gyyI|dpZH8LL^^b4z$T&%=r-INDkvr84|?~NyF}t2I?%< z6V!=fF*#KwQ+ys$X3p}94L|+aFe>T(^8P>>=$R!s@AUubxa`X^dHkmm%?gt9QPNq9i*1#FDXv~PV_(67N4rDC|dl`ua0p5{?R`TFHKfh#PbN1~0 z$7fa~-mnf-yW*OP$nFUqWSjSTT})C5W}tz3Gil%`Pgt`0S>5?9iQ*ENo`1P+pdavQ z+F(`(zePtDTSM$%3O-LVCSesUk~<{HWzWZwsQGLdjr=qwO(%n>(c?T7-ht=Og1~>V z5_?B))7J!DAznL3KUBa05=Y~!qy4@8ObRk2vshB+X+OKB7P~=}TXHxZ?%PvUPh6$d zoDY}eX~x>mmZJBX8=0<~4Nc;Qm>OcCQ9Dw|FV}wWjj)M!+Aqo#Y%>kFvSfZ7hPAuP zPc?E(uAx~&jI`QX@vsaw>{FlE^i)*(cQv4x+j#VvTPwumHL;p4BItEvkw8^G`<1+C zV*B%7XP=eY)Liov71I0j6A> zelzB;w`nGP$OS~0bAn3`K62_(VJP*YMm<@slqgUqyaVx7`BDa5bM(@3k^3HW0>;@7 z$+_321{y4%Rq4fV)+mYW+x{vmnpU3xCd)=JJ-Az2Rbneol|Vg4BK8AYPROL!G@WPm znz67KxRCu@;gN?Gi2%m7ONc&CgC}hRKi*#smD)(TLbun_jtbSzxJ}uFB_l~JoY;`i`C9z}zDwxxt1d8VFe#=J4?mc-!OP2&KUBK>V>x8U|!=eNv z$uJ#D0`cYm($Nqk4?(U8twwe=C`6lUFP+K$JtW@=3K{dRHesfSOJ6S$T_hw1C`Aa0 zsXW2JOqKI3V{ZMjd|Y$58>0xfJIbi|NPz7KzqS|#$c`?i&BKsSFoc_MX+Wd_PR9Yq z*6DGl9zT;`c=5J-Ys^KLz3Ru(!BMn1PBo^>}H7mdHH|Ve_$VqjyI)OWBfn%`y{d0clN! zvHqFtYRD<&=Y2c-TJcZU5Z(?r#)PV2Yc^ofd#O~94@n<#0V5cLTNoOT=I8g%-9I=%C=^j^S>mAVPg$xxl2toiyJ@ zB8j<$zQO4>-9?||obK8~@cnVFl9~33sDdchB4W~->j4B3$?uesX(8qD1 zT$Q{(D14=UFkq}6X=KE)$?@XP#{x8F+p3lOJc_#tV&(05Gc)FuF+OC}ANVW{9tsNF zOKY8o(~h_k1eo5$%hT7rhgiKdPEv+n-*WM@?>A@b|A7+87`H(A%4vg?64o~PHiRQudqeE49Pfa)?rY}o{K)*89!ahd}xKR6;;7sJ*eyW%4 zip4|F$BCklqUsBkya=sF6AdayqhioHqV59E6&S<%>F2c6>X&p;Il!WA>T!~lK8;>8 z38y1PN?@xG6PxjmIp_=W(gs=HJzRZE;E>N2nu)jNdk=gWB^NPz!BhER|7>1ze^Xa$ zl9p#aHGUmMP|omW`*_#Q`aXX@DaDpFs$0-bImTD)OeIX8f?DDFwEt}wIRfUIz>t2?;28se&mfR4mDkFt0f$145~B zrpTFJdt+t%SXjP9d|*55zy%|Y?ahEkH1OwtNlT~;Yc;D&tEE%3`TIWP;E4mJ&XZyJ z8aq4MX>VQ5t1?X>&djhd#i5E!9$59i|NNa?$m{JGP7ZXvp;{V+nTBX$d1^aI%XwK$ zbn&2;VdQ`ue|b2xS|E@1Owb|Y@#wp|KF}F(TT#)5_&IEL;A3^FLi3K0S=UgqMwEPS z=BnQ|Fqk1^hxtld`XGZ4jVoJ|&$*!v;<%4(KAU7m#mQ4;n`jCbaRAXk>ZbksLsMh6 z+xNzm-}>CWr{8!)n*ogJ$RSKjH9*kHC^pdN?-d%17s|*3tjlEl2re0@Q=25Z*IooO7hl+6_)x+@$MLrulZ>PSr+aq9ardt>10k;&8cHL!$ z#g;)r)QA&2jMOkYr+NJ3=j;k+R_G@7FqTiSsY(g|dko)j?%g;k z%4$T8-T=sUpYAp6V@J!lefun#|8q{YM7&p$cAzGGI0Y?h)C&}}I#80@>vftV@0v~? zgGKMZXG+R!`kKfR3~H7A4L0+SjrPAtu1@2u=NjQ|*ZH&>n;)B^!1NlF(jRRtuNxgL{0pDc6SDXqp$Z?fLGO z5lxq(%hMV~2X**=D>pAx+)s}W@l;NvfE|_FZapr8q*AvvfFLmxwj#-&^w7ew_xWclmar7<%u})cx_U|@qqPl?&1E=wP?R9y~xo&ZtRLg){c^kshu$3%xRkp@yu5D zN9vjEr~u*a3q+M5Da> zTvSYw!4LcodJP(3crW5s8R3pr7rWtCC6B9IA1XdWI?fB=OtF5%(Au1qE5lLy7f=D= z3LIy1yZi+~8Zr?hMDF)dM?~vGOzi$2$_I^AwB1bkab_Qs>#j+iK2*9XGC?lPxDf#I z0KE30Ilaez-~m(C=igE<-aJN=m9;s&M$b>n`wSEyU0yFt0iA~D7%@;;ssFH8tC-QJ` zr`|48&gQZuSvAC1r92Jt!&CYCkxReGFW2kz`1#F4iw3n`6YyiZ2{ZB}Pu&TvN*wdT z)MO604&~=`Nn4?!E9}8-v1v^Fz{3EKW?R-#$1x)bf7{2-UBaq@)|m8((XAc~qp??8 zY8U_h;C+j|f8WA#j-b_y8*Bf0|95RMvivaQ1D$IGxAlIL+1cX+=5rk;M)n@_;t?Kkj1b#K7S1c}~c{jHjpHBS`^nJ#zl4 zD`3tki87J$?LoxdQBSE*JtGYS7bGDEh3xBX|_ZNiXC+f#Yon*Y4S%}?mvLTjuy8w$_uc7zvt3Pt9NE$ z=E5N^_xihwHj0!+qx5~?^tz)7Q1KA;WpH8bJU+Vhr2-YiPe~xr7xQxe(QD+VDPME} z-^P3bx$(+#i(4ZS#=@=i^J|)fU*KnwqWz&C<~er1`^0H9hEGAVgo)}}N1)D{3B{f& z+Xda)2=VDvSFBy!D%*|0{vRmORGiSxaFp~IRe|hk%P5)0rI~*hS&Z|r_Ep@f2hbGT z{;T&2uL3Wd#&FCvspjj>C8L0Mz^$$oW-dk4+qu!eFWX=r;`to5oRmQT-EU3C^+kr_ z@~9e8=UPEC&7ghZ6)gJgD1+? z4Q)4ZHO7bRV1y+qGIt3}W4qLwF;&QL6a)XJ`A=%RdsRP(mP;wZzJhggGfIIqkcpT| znQvJOVVBQiL;S+@ zPo+)ZhbzI+jGAhdj_gRude5$X(LG$3QN)gJT4piqio2i3_U(~rQ&GimLJYUWxyRkn z#XTxUPJ^Vl&NUJ@-v@vbUTNKGc<_AZpSaQoDJo{6-^B7=Ng;ci+L%-E!$t%>>38sx z0pvi_YZ43=-z+>A(osc58h2;)wo-k9Adav3KN=<%!e)71z=N@36l$rk3%IPijJ2Hz z7q)q8blH(1wF@iE^Euk*ZzMj7t8`HG`^JI*(bd9C->xHpo8C9FRICdv$5STM_Jl#I zf9vOw%Ec?JbP?7_yKj?1kH|&+<^V7*lRjr~vBV)#Fu&?3jGzM9EcKHDvMPC$R~*N? zPo@w8a#i3iy~iwKC788%3jv5_9$2J&?GC%J3lktGF|iM;x!Y*ZBd1#b$Dck%^@qZ=EJJ66NcTqA}`)=wY&W&G=+Kj)e-tF@|@+!bu$M4 zy7=}sOZL_YeG`Rugo@@z%|z5(FJ15l-2Qszc2j)HcscrH$QikGf}y_;*~qSUxQ({S>uSvmHN=Fgh%Zr%W-jw2Ow{t0-ykYkE&} zA<_%-?eczm?t-aSsDcqwVS-;4tV8Svvg4Ys@oXBcg2ZGqe}3NT7-?^;QknHmJhF!h zXR=?Qn}@Lo0g;k{ZD|zwFKSbo@U0N^1a~<;Npsl+>= zjfC8R@Hw+e+;(cv-Iu#@-8lMTp?2Lb17vO~z{k^#^g6Ek%j6$n`Akb&r*k^Ec&ZvM zB3}e0yO>w1jrXmO09dU_&Z!uX;C1rx?{j+*?aDX~H1@C9F@7;W)pshmvH3#yXO&39 z-55TiDZ=jiC)3Z63b3YftlBE_t2BBeO!k#OOwW; z#yRB7m$%Xiq{%QXZ$4vJyIe+;YRKvFR1C-vxR4fvAQ(kSM_&y;RzjLRP_`-;l*?iq zC8QO4nYty>X0Wq1gcKETi)eHj2pufhp@=1=q0?@Peq4`Rr)wdA7%$dG@uNoi;2R8$Fl2J-ZL+{7 zE^maJW27&O9A7;b&Z!E}yh(y*65ynqrZz>+O?HM*P}yigR&bR4bjv$~MIL~oR^k_< zD|6DgHMLtD{`ocMyt-7ZN|%PHR=Jey#Yj`PyymB}tF%1Y72(SVYpfDI$DHJ`gn!BG z*`d6G>T^LuZ9D#F^;-?2iO7#!*loT$g8gPYYr9VFe^Uw>0i2-Ovbdfm06P81Fbn{Up< zF9eY2`w6QkEbk;_5F*)c^MG4?)xa~ftJ|WAj8N;4(_tsUAdg;n61SK8<-&TK#<2R& z8_I!!SV!*@{JP|`3dS%V%``e-WrKdj8y!E)09s9!D72tBTo+}@n;kH22Hu_+ zXhQR3&z?~n3uMv{j&-({+Gp>7D>Gmh5F#^-_+D!8*uPryp~rW+`m z7ZCz!qy1vuC`c__1$G4?Vn;NRHC>hxCgLo4((n(A3><1<7 zE(|Sp1=m0L61i6IA)N!zO5g~fj~ZS}P}n;RsZGs$ z4_s$V+g$`wYCxOaU&92u+LKp6WGOgUtbB^|=abr@R}}4l3ye@bfx_)OvNyvqUlbQ@ zPF#c8H0gJ#hSBv2Ub57rQ#w=$BP22d?z6yDjC_=H$K(-?@_*YoqS?}3;|aOaT%`3n zzm&DL$IZVgA`h5ca6zY3SNd8$+7NXuMm$B>0rL@=CZcm^P1_h>Hy*>77L#BXZ!NC8 z`_BY7lXq*Vv{_qsECRhH*L5&M{m9(5%HvfL=zOra~wNZL*lt=O>P~6kz=n6OkF+GC&B3 z5Xl-X*tR*Z5qeA7RjMR;4f%27gm4cHV4O!xrIlEdWxr+x?HR!^a}atQ8@u@R!}J6# z$e0djy!aIC3m1x4$){W;ATUm63?r8x!_-ejBtAP0sHK<(JY*@*9?CHLqn z(@b{%1rW2+&X2s|i()rfcJW6)NEBzYT<^TSgPP=GJ z3u7R1WL-+ir-{j?u*np`Pscwt5s0Wl+;!SMe7N%$$l#fx9v%dFTT*(5B3~HUpzgA0 zB|G^bDjk*49CcUEp=2R}Mmf6dc!~t2w_gwX$&!p;`X3 z)pWGJGx@+nA-XRAq>m-t3lFEIK59a_K}{ND`Xi*GUdkFT=+~9JorQ)QP5wX|%TuWw z_M7y2|86+gUASljr&T(~3p?1FenYi>J{HFJo}R+$cnZQ;G&L8thmw{PSg&%IinyK| zyWjvlxvx}{nni5Gtb-^33c3|mjdLccAr2Rs{P0agS4`%)Z4PimC8j$h|}-p z{D&E!sq9(kH^#{B@&*lZvc4WVkFu>Y!$T05c)b#Lucgcb>`Ks87QwT)4hg(*$twKF zG}q^#r}q`BMu{cW;zk646%_7cJc65v4Y-3WNM=AFQ!w>OPQCZ17@@^v$m(+2 z5)4E;EZHPTNVEG>Rvj0&-uMBE4sVo>+IxxFQ^d_Sd_5v_{?vPzaCtM;}UZ(QCC2oNSzr_sHE1Mu~v=$P!t4B~z4uM^FRzg})#-^-uRln_C@-_N3dfQ>ZY-`DoHA`=Y3d??T1Wrl{u9Q> z>tn9z0ws}M6~?8kqkq`Rt&MU@52Xl;iSLb09>eV>x1)>2?*W(=(#^A~ z9pB1auO5~dx6uRPD#fmG?05!S12{)}pQ>~U-wyyeH@0`|ldO3crd<&7dzxdKKukk5v?#L&R64vbhD_jH1leZ5XMod=q8bd0v75u5 z1@G}l-?R^i`mvX*P@sdi2Bec~2r~IqL1E9Oz>%hbbogD4(2$3!suiO}Puoo}3tIkx z_G@(e(rISFtmaI(>IG{fqC9OUY?93ImaKzhQ8oNAujrPxv_X99nSX_^8rZ651NF0FsBV@nINiUz8@n$c@F!J za5{*PrZSg<1t}16yHcl?H{&s4TYZ#RHL`VFUGp8&%QSu+u0qL-6u?zvxWifmCxhyq-3-@)%K#V}r(pd!{hQN2;$R6( zRTfiy#XuRr6V|fI&(7*~s`BuFqQv>d%S-v}o(|7fqvG&aX^P~VD18lCV&JUmePd(U z@L^+a8zUg8wf>xyWKxM}WI5C%VB9a(oYrjQL{k$3lUvJcBodrrCq^CVM#u=zhAWRQ ztlnuJX}$2gZSOV|mxQnuU83anjq*48&`zViwt6uE-hA-3=VRMP7y^?R2M(foF|7n> zPrz7vclP*pmL3KS>&bv))A<%~Tx>+2ekf!spjrbHG4nBTbqc>LiVvNJP!6 zTLgZOoAd?{V+DxN^m0L6k4k7v!iie)6$U1Lj@h^_*-IL9v6`$rutUVR+KZ`+&YXoz zX`Z^9i5@6*eLSvy$E+;YYp_WI^vQjVm&^QUN%-?4`A`mCL0+Z+g8m_xGdJ_geWKdD z^mRI@Q=d}~R$*;TnDc2y0MPaD?uYqd*nS9;pMV7Cz;{3s{-NHmMtqOIC?ToCGG_>k zrdLR7Pa5taUl0)Sc3aSw1IktG}+OIFw zm>c!_AY!mT#ZGUETktweLko+am!=sa(Aw!3ul-g!?nYlHj(ZlBLi=ABVDFe5!wv5p z0={6oCs*uMo#9r$!Syk;LklCn&1B5(!&Y5M`&me}QMbQ{D2DxcGoRRbE9R$yiM&9- zy2jTGpz*_aONo`sR#>CIjr;p@s}t?kY8Hj@_!Mkhj4BMo;qwk4qMNw&iZUUeZ<9F{y&c?-MKyewIk}8k#OHQ2LG= zR7;IiI!f6O+mrK$L;*~Rn?zDOoEx<~OhHSAz9%Ovxx=| z9j~=%&;62h8kN_;HYPTHinyD{IrUz*0QH(Z8LcCqEypq#1|`J*>@wdc!P^>G z!WXTNM&(IGA07c>Na-)!ZHZXFaw56V2J-3Ugb>Q~jHfTymwD*;PRNn%%s`XxIj5xY z3%pC{IFNgZ^w_;04T%(W(u`T8)Z7jnFKh(`(Y1geYBQiEE%4`_@MKUI#-&@`VP9c% z&I++PlP+K!04-8PZFSgs5tKwoBh)zJOHNv>8VJ zh=v}ikg*T#X>JXsLX?V6Us0{*Yl5){=AdS-_4!(((<_0uTwerN(fWK=O{%*3H>&_> zUbu9$GgKD=XH~6rtp@494zqMH9SJ<{gx54;{(St6b63^ir~Ie1p~Exa2e5Gs<poq4twWK%j^p$aggE_}=n z#)n!g+~TAxlCsd8ta!CJ{*Q%MpJ>6XppG?=#w9f(IrWFyx(D2L(QEzU2bOrj$}8q(nXVOi>K0H?DdfO=nxs-3>pe_Py^8Da#h`v-Skf%A@)~cF?LWC7-ueWmG%3D$hF8(9wL83uj z4$MqoM5qKSAr;~Y!I{qkffB=IW_*^%Oi@AqjVi3CG3cYMeahvxv2wt<8ur7-4YkmN7-PKg|=idndM?<~)#(+`f^r=F@_`*KL0ar_=A}A0$O^*{x1v_%PMNyreIsZEjG4Y;Z{)vH;JOYq00 zw4w^L2&mF^CDQ;RS9)Ot$1!frB94SgyOmr-+}i)3tQ|>K=C{I0aqZrN#>13(lv zo+$jnZs$%e=xcNkrQxo&`W{0lE-q8JeQh0?;6-|(%8 z_b&xW+%g;m2v$}BsfV~jo&vLhf45Lnbg79_kMXhKGP08mu5^3-gAa;j7?RvkZyMG9 zt~#gc0E<2p43Q@10M>qlZ1bBEAQ7w~#9+>V7wVAuYX&l5QOyfPe1(JzXZ_rYk~y(q zAxlW2dCPLTZH^Cw#U}n$`sKg+Ng1Ye*0r5J+AL{a3NPx67_cAorO?ZD)%@ORsY3ku z3sm9|kO)zGk2=D9zk_WU3))Iq+LkMf zujaSeNXXQO>r%k8&hh6usjqjGy)X^mhqGm+ZjB<$!9?2bH&dy|v2YXf7<>dQwZvRw ztigEfZwUN^1~BjkMFXZOO~Qo3>3o%LN5f`kh@NB}T4hB8 zJlOvTS_?sM20TgQusoP^pOlp+CHQ;Q!9pguo1=;vkbDIMf7uq)Md498K5iVIQ`|FC zpm?)`j<0Tf8;N-wKG6JDLcmVY zz0A(Tl_L4fpNu1ys=gVpkm>zjflL+7>_3-E`B5dcJ*VNHw#md269vY4KoAf}bn%LK zmalB4s<%(W1>&|$0eET76W3cfofz;!b=J@K-)2rPn1`K~3dD+dv^8fo`Mp;*3C=t& zV=!vp9vC>@U8s9}BLiUT19+dZbt-IMp+SS~2?4wzBEpNUKvV2W56gFLNJL#mG}CUt zurc$xy%k(w{(dvd592}AyYb^qH2m*{2<$-(%dj^p207_X&+U(B+wH#pYkU9zk_cuf zrrFlxC1lJ3b45vs&k~+YE($?7k0aiO=WWhFc6O#( z6ld0m`G0yw31#rcM^xRWn}*RN`)?B5MytkD4x$=hX}iM0E5^U^^HRSDG}? z$^q^aARASWJ+Y)$(WeOu61yxEL#>|?w7MPk4bNNMQ~L363q@t1Wy%_)V7tOV)tTU4!*d03BLeVN^{V0YnPplc$|_ z2*5BmiJGzi@pXCxDN28FIoyAL>!vz{TjK|Upq_0QKBmW83s6f<&pjps@c1C(dqQ>; zPoIHF64G+y*D|JV&ytix?i1$*!S7&HqWoQ)#|Hpvk~HqdO6T_D;)t6Gw4id`U!-~5`7QLWu_}uGBqM z4m)n~OaCeuBn1B}N!tb6xs^-W)(OZ8n)V4|gC{0ZYJA_&qjbf761z^oipsKmXy?V9 zRlGfAJy0>DKY9KDB^TYXs->Hik_#IGjTYJVBo3gXob|~gKL`$ak524J5T^zH>FC%e zwQ@Irz(5*z<1c(*wmCTGlV182Wu%*r-?0c!=&`Z6f(WaMgqbD_z%HS|7AS4=vG(f3 z;L}~ieC)kWK^o#ac{QmE3-VJaB*j32pL-mpB; zJ5dN+Lij2yiQ_z2eOlBGDCfeH<(A~PtnHN0EDOs*JWU^upsBj)mR?kThGt+O3}H&^F$x-I0-m#Q0|UR} zn%~_xDN>ju(Kwj-p*Ga^_tJB^xQi#VRvTodm1hc_PaJ9!3k&q0ZYGS3>O$v};dEf! zO;IB#F`o>p;J=?b3(0~{6v3WZe~&N#>+^Uzm^EJfwf z*#Oj4_1_nG266r8O;&15>ol;dYeL&`Kl7_Fi}NtI_yxJbnN(Oo659hiM3#3gx8?@c24yZ>*j}K)2NVo3# z7C2|2bdTXf3{x9a#x|Ko1XTFkz_6*BtSx8$2~p*O=?q>oYJrz6o$|T0v&VOH+Z<)J z^R~ROrP!@_7Y1^8a8Ui4U9wXAqk%Y!iI6IGVx4?oXHox;ZWka)k6E1UT!ztakmti4cB22uvDsC%<$87O3^Zqw|4DnGR+eszC7o#jQ<67 z?rO4$p*z4OT@$vp9vSy+YEoltV(QbaYMGdf{&3nJNTes@&D_=GMHc}%)YB}cvkf*7 zL7}~zurj2y!_4kpSMi_t9 zjX2(?hHqKfhy~=4n=UYuS=^tFqiHtHl*yiY5e>)yYx0r+P-+~Ky{<*Na>V7OTzvd$Z+>4~55gquM=1+j z;g27YEvv{%V^xbEe@*I ztc&`9OG_;bA@-WAK)7n~H$AhSHykT$Z+6naF?9k*AqKCOU;sD34dtB| z1$&;b5bJk1)X{=xPzKHWk*1`O^F?+74#lO;sf_|7rE@3W8Uu?Q0WpA7WJz(A1;A3P zJDcS`h4X(rM{`TYsAmXnK!;82G>kr$si}y;=AC_a)q9otuj=@GndzW2*PQ)QWh^F! zHW&(uE)xva{3D^xy~-$xe!I8&>tE&QpuQb@ndh$q#Xre9;m5-$OL{PzZto6Y&X_0KE`Q`By zT7K`M1~HWAZH&CTK1VHVIb#!c5P*{z0*Z_Ec1aq*O+wNG{~8V*#+uCJ-pQf`Z=Em? zuONo_mf|pFESK1Bx*PxJ06SBXue?n}#fE8n2#UBxMYR`Il6)XFZJjM0Y$GVEO>L`X z1O|~^7KV*Y`3-F%e>z-qm48lVOXflKI1cRu{yxi`|MIcacttTki+MT@T~S}46cyn! zBEx~5>S$#+8x%X)B6_Mo=Pr04wu~xQbk!=?v!9(r3zx^B?;h6kkV}W<8=B~m9Aj!2 z{gB`r(S@{rW5mnO0Ph>%j|&rl*c(^?0|k#&I>MCNnD_?V(XH_wAtUavKbt+`%rQ7l zR(U$(?hwj{{MfXtjVwcjP!#6-E?^wg^q41^#K15tbe6s-4Z6r#ENsnK4Ji#zwL)=f zuFP49p{gCP*-}G4y2#JP2hnAoLSc29piATzo5}!9K(fE?b{;ww2vhv<+eHu4zDEBO znmK6UT2&0%SpEQY@KF2y1kTBk>0rf88Y7YoJ0 zLGiTuQgaigcA*Q5yA7q=m-^$gWZm_mO>E{1^^X~UzvcKAlD3WGnW<^ydlo%LWvq0@ z*L+?BB*zEUVSYVMUbZkC%uFo2gwk@+m&Nlh&zXeiPHjm$2QMk%F;6)w%Pl}AA@ie8 zu>vD!Ga2L$Zr)2+lTDz=FLgTS1O0PjLiUArMVwAD*>8QAaL^BJ+$_`ayY>Mhe~l?^ z7jO|B1$e|2tdV>v_lB6zq5{H9Y>jDeDqRi#z40-l9MZ`RFF0d(z>rd$7N(g%0S%1k zOtl1{i3M%LBg$lMEp^#R=xN`)^&K)X#%AZOf+oen0KZx_h=_&Hy;=QhV=m5FIqs23 zCIlO3pg`QVwq`L>h4_r3i4&QV7ZyixFI^0#5yyRAw+Y0Je27Tck09m$h+%>P0+!s(@-#w z6WyFZ|L4Z-ok`dBI+ZL>aS`q{3m7u%bEm|g!l8QLEgqt9E=_RY6fmsKQv}jc2}!YZ zbqNU0v#e-ZSKz7J#gfEQMnz9^kzd%Or}t$hF-p@f(bZW}U)mYk1w6;ktxZvFrK70+ zlc0C6)QpRtrDrpMruDJ`0*0u8yc|4cKt7$?r;I6yUbPs~(XMJpfWI|}yO|+d0Ga-H z&^3Z%FWzxWnr1uxeLOyfRuhEvRC|WkunZb#MA_!9Y6*Dn-;Q=2w{^`m? z9hzYwjO>Pkwd^*7oM%7UmEk2LlKQvsP357QXJyFzgb_sz*FGi! zDq_+y;q`c;N%JfgAw<8hX#`R~8y)HZ)y2uT84>5CEF5v_K9m>%Mf~_a9W=j=R+(xH zkQ%U1%~4!{0EoM5TL8g;E_Q8CXW2Ugaqo4z zp9yn_{3?FA0HJa5c^SvMXlVuVEzI1DZ1m=rzVUAv6^TZ?sdKn1QfO`s=tqG{sJ_gSjF+~ zjLg5=#i)6UR2+vCGka;zvUy(Jl-&>qDn#@M{OMv=SzW`or_MC|k#^C`%PV2`wX<{~ zTjix2k(q!(}pYVKn-)NSKCn&Te)ZKqJwZpxET~O&fx=( z%2gCgOP*(i<)i97>_X$NQCdt9NJ&GS3D6CU;8s_FUR1I8HF*`yu;S5Z<#apZaaK*+ zYl%%E9wKE$o?YVFfCBpP0^nXJ7I|&ujDT2Xxl-N8!BHQ{x>Ean?Y8Jtucz8!^Cy_R z^j@-p0?7is_h7Jy^A%sSu|-ERKns{H0ojM7O4h)Ce{Bc>OUTqDW&5%T$eAT^Ssz3Q za_Hf7=3&{U0oqL<^i8}M|fhqXM_2(H|3S$4<;N|zsJZ2&uCP2}-rUox)8U!hyf z&ciU*HyAmI!vi$FgL2t%IO-(QA2O?V$*9*V(v5klLLfLF)pBf_M^~@+DZf!g$fdPb z;bja^*M62ejvBqmQwY&y`EGnP&$FV`e?}NADY)~_0`va0yg}WSXjB=b=oDu@tj3#S zwhWYV_l%i98eq%w9X@3rzTb6jb^1}^6APHF}D-n5Otm^yVpoj+B-blA*>@p9jK3`!zooG9pZI5d|v&7(41BT z$2eflu$LWr1byvuf(tfIhBuD_!9RsU@IV09$=B)YmpqWTmu_APUros!l5OZil)EhuN&=$D+k$x{dL(9AaIc@5LN7 z`|;65!JC50WeLqJf0@wrWaVu$wRXl>KoR&yQ+0{^maKtKS@$5k5n#XGh6>FysFSy= zfsif_0cf`f1lgqNzUPR#3vXsP)plDgdkBTp$v)|;sGqEjvqBL?XB_&ia20i(5QNTN zmXnwKL2qZ_m>j@AvSPPO98@sdO2NFu4RmTT=1UnH;i%zN!yvP|{HC-3@8d&>$7aZo z5|uw*P;qqEwv+Pn9}EM-bz|l(tN0GAaS}-J_s@k?eblJUM{R6m`14X9u%eX&aFyHz zcXM3fRDiEukX^U=PjJ&(w7WUum!V!j=}mg0T}M(#4kN#aD{GAWH>@sbM4E$)u>9N= z4*mQk()NlCPgNeQb6N79ED$#N=LZSGNZAdl`k~FOE9a?WdK!Y{z(3L)KwQiIXbQ2m z^eeYI7GntDG{Mxh@LKH~484!2LPje~(0>@#aUbwOi>p&;SdrK`q>3QyXh@e7_w1D$ zbA>g-ZyWsXcH-Q8|&HxVv09iV`ISkkW=A0c5c2eq-Wz`;M`S|e)y zH$aO<=dph~DDLRfOS-$ADuh*9vNCo{6Ij@QM%pb8$B+SKf7ZpEV4ZO8h_+%h`c?h{ zDrSM<(W5OY7S`c3^WGXNKUJnKutP(1HG0ZrfuiencZJ)$CSWgMWY#%N zh>RTeJ9n;>kpCY>W=Xv{3hg@aTj|D8MlrQpoKubi#!s`lemrJ=(L0%!;~5c#F-33m zL>PTnm-804FaE1RW~Y>Mk|B1|RaSa(0YU-+gf(|~Ql+DcqXRrc#obF_mvJSSlMk#@ z==}&cfNFC0UQL2q*x56(M>pRjMxt{-?Iu4gqE&$ zgm^wz8$TNN=$vYeo${S}z@pqTWW4joO%ws%m@6C@J@1R1XDBF9cotkn^LYZ-mnbgz zDD?Uv4eY&Xyh1YF$FY}ul<@;^40Fbm?kgofRWY2}7dQ8M<}DV~xT1&6sm|wn=3>Kd z5oizCuxT|RO=)4vP^W3KAc1buau@gq62IA%A*>Gc-;2zkmqd|*hlpyAZO;uxwg@ts zWR*gixLhJP7(ICWjCEsOHs5NsCp*iHZ5&53-@{7*q^2&nvm;>-PPxD1**FWK+edH^*GH;hAET_ zBW_E<-V*=CJ~&CkxABPc{#ArC!do(Du6>{S`QY%)IQ|MeJ|7Bhx6Tn+QmIH+hoWbd zQ3%d0agQ@%dAJk84}j}s&y)fo3gu8+7?YqQTOQ<_%aw8LO%eAF_-qs*JSs+nXUH4 z=9mcvB4HPC^CY%?TraJ_nCY!ki%kND?%B-hWIq09?8tRkheUDhQ1PO`(a{7wl7INKg3+B9lM`;O6)fbquZNs zhj)>{J%Ly|eRw!XzXN8(Rh8&zueM7=jBb1Mc)KB6tw(F zn7sX)aGCI}%Mo(eOBs@OQ|mR^U$HQP_FcAWV+#DV7+bTMwOOxjD%cTPRZu6fFzYwX zl>UiU>HE@PdxrJmE9K^}%{#p-$7!2+wu=I=8Pgyfb<D($kAyd%6v!Y0;vI69Ww zl>hRj;q$afuEw+TCMKhzLnP*uMhna5v#sPA!4vs^)oL->##XwK%`m^4S8h;geX=Wn z_HMt_y+25=wt_)-n=m<70qEVVOP)DvMGs6^r9uas=L09F%qbRc0i$tFA=0G@b_>eL1MWo5 z85WrngVz!yuy=S4D$n__?0q9?=H-4h7qZ$OK+BZb{eWJ*};RTZj ziC_LMFeJSA0p#!iUvVAjtx0h=NrzbdJPXG;P*pWIc1)J0fYzpu*?s1^dq?AjAzBRx zwwMPw?wD39@PECChn)B3Ykdugky~xj4A*{>RwGuz;hC}Fr+_o)VTT5Uo9BLYpVKcX zmbdCnH%{(A4rW(4CdC+5wf~yNww#xNQ;7wa6UxvL$rmx*7{g~V+c5N-8bc*W=7lP& zylc;q;Z+xi7OhsJDREIt?CzycgGxUo(0+7qgu~EMBL9>D#)OvZ4G%#W=8kL3T=9Zv z+z)vS7p2+zQcw<+a^rq3`R}!MyNY;oL02Fwx!U5R2mrCHmWB1r7qs+bpfc=M@}Zl> zE5th+(5w6SaORUQatIjn!Z;SB=&IpV6HR>|4F0zX=lwKtdUxNr%68gm+*gZy&<2z9 z^jn8ojepEaxY+Z+rH3Vm6Cs^f&WuPXgtr-Lo2b4jX`0oN(5TXv1UJU_79rS_xR%TE z)qIL%!=^jXT{48N0`002N$r)c%0&SQuj1$f4}tiEuOq{78#W3mAqffyX;?O9O!9!D zHQ?Ui+UAT>la5AqmpJI8Bhe9Ddli8=VzA~wdtm{J;6pCxx=|FRL#tm;$%~`P0W!or zl%a9eD;(lM(Lf*ij8~72vKB^v1Djx*G;IFqmUPGPj2{vHd+Xsmzb8Av6z+g771vL; z55cAx`{fd+M*-R58Oj2M$i&xbV+zq!4zbHj!S1lx<+r4N3@%Fo0|bg{u=@+x>-%^N zuLF0UrAD^!#UMUI*lD{YHxf}aXdZBTX7Z^rGFuX(niHe)neNhKe``19QY*Z^)B$hI zK%cNj8-&QWFYiXvp*Y}em3pw2dAtYdn{-X7t+n~wj5hLlEwCMTR4Qd|5y(dszag{It?P7EizvoP0y*M&uke6i?k#E&rf2_6M5Zu|6 zG<#HpX-*D=+9q5w$bURB$1RSPzf&IAK_yxxpkbZP&;HF}zrX!pZr^j@D=zAfyN*>< zWGr-uZo^vK0Ca#JNQ+>VtK9TKlAzlEn6Nu-;c9}gvS%iquCfDIX}+BZSCN7Q$Uc!f ziO5OhD3;s(k?k3d4EKR=Edp@2p?jir1oTC2sbtlQPoJ!Hlm*;wj4?mc|Vi$wLI%R=Pr?1XatUe;)u7J}OXoXf?@elJZCoHb3e&jQPW-?U_yI6DTe2sfmRlX##pe^{q#$ez!m57a7*lM5h;@nhXGL^fVG@sO50+e}yz z*t^1$$j=igc&B)G%@5nlrGXgj_pl>=-*^+g;cmci&cM%_TN>(bGzSw0+d2ItuIDaB z`&sk1_Ns07_kp%$XYVA8#RLPo&JGm+f@mQ+o%xf2S|x32zXH+x54FKdvo*Wb3PWtj53 zroZ!1MI;zLC1+(5RtC-+<){R8dV!Gut(7bRpkoo>V2aq40^6Vhi7kqv1KOYhBWG|9 zEaJ!I4^l)ZgZe20V*NYb7K(=-)V*N+A;;2`AJ>lx>1 zkdY8JtZ|TN<36;c$>6$4_4%F#ASSNRDwSnBmcs1Ub~)WYRaa~DF0-E5(n5PXP<({c zhh&y=SmJcyETT6ka8(#Sg~%$xtw#aLHIUR7aQOv~&HI9Bnv-Cc)#l3wQl zO&AUf+dW3EH=DS5^m{POeaL=$1hm+h8@Kszh~YtdGpVDLtXC3K zm&uTXqLZMGh}zMb{(>iZ@Pjs9BDvG|a~Bm|Xk$2%@GJZ9FD)ytdw%-TB<{}BjUzVx za)hPQvYq=2UmoleN7AtgPHp}Qr;=T`klN>Mjh1{VwGmw^h|SDsIe(~+A_qN#M3!4L ztCnl8>VmKM&2{{rGX~pRnHj-D>hW&#C+_g^q*||%Z;c1EntDWK=bVL%8U5K4mP6)B zWF5}63c4sgtUpGZwOcV;1fn1HiygFoFnPwgrlQHYS|0-RMs31#dpu@i*&ncb$*v}E zNVL;?+kjl=?i@g#8(7Bk?X{?SslDSRDPi15t;55JrvwAPJIU+ySE8)u$-p+M_3*Ow z6>LtA(AAf)x6{4uc>#sdhnmJdw2o#Gtd-YU%KqMP9V}&0S3b7Ceum67?@f;z%`(0X zdmgEoJvb!}%fQ|=2X_BLpYlYoM+?*P1(pj>S%nqqQOb6T%>z8$bjq04vwy&DS4bk zYmsU-G5w@Qm<>EQ{*Z~veys9C_=ba;542`<41!hrt4QV|p?IMtOC2{_gAWO0S@!e{ z0j9}AEK|fW@(xY2IhQ2ADZSv`GX2647stfm{Dp(K!!`y0r!3$rg7R(FsQ_zh0k|1g z;h8lXam&AN|DEE5Ap{~(b)M6fGsMvt0AU#GV!T|V*Hn-W}yo2m%YxAp3}nD>#= zk)>$Ukg~t(>)JZ&7;cUdV91iy0UqXcf=N~|NROVFx6lm*cNy!~WF{)k6hS7WoDEL+ zR!6q$BMznIW~{)xITy>p!z_z1(|ESiqm`Mqy+2JNP3u5DTbYB$6W^cUQLQ96`Uj3f zIXZm znlHk-OAiqBR6H}I33tSpH{2wpNC`2k3;QA4`#jKkF8-Tomd3pVoP1mHE}x_C|DswM z7>BzWrqDL3dkp$lFR<3#en?r_pv8ul(El03Sfeje_Hqaws?-t41_rU5l zjT7gA{89hGSgiK0Ws4e$9D4+{5 zf}+>Dp^`HcnxAQQ==Z@(4%)js0w zG2LCfzx&48fAWdZ@Yoj2xfNC(w=B*-UtKa`NSX&57TcsiFC;T2e6z-ADc)s=Hi_L>kMo&p?KNUwUKlQ<-?A#Yr5Y!26xqZ=jqhqAR?fYA z&|@)21Vr9_6YiIn-cXduRqe73;s?fIg)7_LZ&h4g7Or`|Hk38~eyFR`K610RpdD@D z%tD__aH`+ne_}}cap`|M;}*SBkqvt0Fl9^>|24&Ebwc7t_SA>|TXyzon)d+rXO7MF14{A zc`4J$ndg2tbed~!>n4|BvSaD(7J3U~jt-66%l97UoCthX348LR)#2VQ0K8YYNLUs( z+kN(y&XMkOe~Sx@E5%BjZYga-zwk4m%3Q{c%cU5vm(-^@n0+c2xX%$~G#R~T(E>bm z|C&8n#Bx_8z0tbNzgwxW4MXNM)}&SvS>r7EDh6=wNk0z@rM8or3CP3)rSD)cm^bal zj_-|GtHV#{ zy%Ud^l%rGm!vF5Ymb*Hwj{v zFRO&{SKUnPeOZ?73qkmJejY9E#ewtg}^nAh8JN z6C%MtyHI_@KyOqrHCbcN`vHDys*CI~Xv}_BRwv@(h&LKgw6!Z!R0y=qUMe~;<+W}8 zyV*2^FkF7cnhwFPfhUwu9h9hNVJ4@-V`{3n{^M>y3Br5v3S%BsdssqS$&&Psy!ic% zhw&2lYt9NhfFJ&)5RN|gM9AzxngKk)W@N@bGkGHM`k*^>5f)k z0CA_|Tt%N+>a`*20QMjbtMPzJdyN(&1!h5Sg>M5XbG4a6QT<+1-70h$5kvdpGF0{Y@ zbkvo$zBe(;sYxJDATyGDbRqxDOad$E*cp*?Ety9Epy>#2UrhZ?g!x;qlnEkyxM!Yl zfJHFFjqFysqYAW(3wm)cKQ&hS5(prHq*Gev2e=z;=n zDIA7qDDo2bQA0W8W}mg_!cL1NeZur~!(V-kO!^W8TSz2l^_f z0Z91xLwLOPQu+=;_^2qq`+bA~iD6x;IOz(vk~8K&k6L!c1h4`*qYcC^#H7+w7Q^C? zZ#gQebaPtZ09jmpp{OU*2(h1qAN|8OCunxNaUZuQo=DXUe}_>#~Q z4`^5ZNN*Qk^)yi>;YHc-HPQHn)gB;LI`#uK$R~7;-V2Xg>dI{uef0R}Z=Q}ZH>>74 zS)FApMlk|Ju$5aw{ztamrQJ}2U&|(5#sX)2qsevG7unmvlD;Wb+QO1~r(=7feR9p; zgsJLZD@S%i4{=>1h-E9o2XRbSb5Y{aV21J~ul_~_ZsJ^E5sY*@RGFj^Vf_2I%(pku z!~S8}??U^0_Q5wQa5TWvF|~XASh@v(IFZA+ehxFlhww9~f*qBQ#bXh7Y+LM>Grr-& zN~=>at7jGz_Sjp61&4|(ekbSj4DOysWl`aC61mCbA!PGw)k_shP6+0)RK4 z*1UL%Xw)$(aie_7$yR9;s z!`$&Ne`kYt;SiHr_%k6#=Zm^L{jjpEH{zb3 zl=<=M=az0(S%j`i&SgEt4`D8m7@v~mcXz@2xFTDN4JZUU*8*}bFG8F!aFXMiH51Y2 z3R%p*zsr^?w}YRS(G&s7f_P7(n91bb@L9+`a-`^H!D+T*Jvd%3ICOA%BrzWhh3Pe{VQ82m=#uc4pGw3<`G& z(ts!Th5L8lZ6Eoa^Z3=;bu3z^GK6ci>QzLeBAjar{w3As{3wq#uiYz+FH{}#2(I=w zel6sDxa%{sE7UyT0A<8Vaj$@{{tq~SAR$Hk@vZ@uPSf-SM+Rxg`kB9u1-D6q+o7%F z8qq}*!`FCcAboYd1%T=P3< zAT#syetHc>+cazOtRK@QYC_+Enqe(y1NXd;0@Du%ay!rzBZ5&!c+Uf+)NO7qd2G94 zB&mx|U!rtk03YgN2%2BO_VNmkf4cDpa>|iHz@#1W$dx(#yE`Xt{8I|50!Q52ny?B_ zc=EXLcAmIDkc&nR0$<{vcKAcfXjvkyMP1!KlpXM#<5sj)VvaFh>U`^$M5_?7Mp~fW z;q6&NBM_xyM2{}N>GqF*Kf3QC2^ATTROKh^Qn-!-IcA8%H$k>YMwW8!9P>iYEAaW8 z^HcV%A%BA5f>AZ19k(c7jJ5L9a1LJXslI>rZQZW4)XHAL3B;0yAwK0TCLQgdKmo$F zvdtV>SC4ZtrEkQ-tq~$P1-`eRiAe^Eu??SA$6NFp5@hgW#k4eCkNj* zd|G05ye6Px;VS6-3L(b@D!jxR!)3=&0}sJ#>H|y}P@~z2%##a1IKEP!xd3z>eb5WH z&lkaaAFtvAfJP(~X1a}G=T9RvO;&a|_$1-fR@S5SE-2$}YM7P1g=05En{iz;L1D{h zwYt;@Y(M&99h)K5y7n$3uC4 z`C5vM8KQ#OYt{$V9+mHRaGWN1y3`Uf9?6RC|X1ru3PBlK(1NVdDHp8ew$8r*{q7?KiChszeQkV zgb83m9pfL~OK?WEzSP{d${D=|yxM}KubAT}ii>r*S0&@$NreA~7v;(Kp$-G6a1l@m zR}G5@L!jRjXDGo+9-%(~yj?GckseQhC1YdFMC$HeZ%=7|lPVz1auTQ%Bj+vB1il z&EG1aRYAJrtYZx+$1m?1vql|UT{h)wvhyi5W&liCC#~%KcDsRo;Ip2BVWTa9RJ4=spicEySWT3nwP*e(32mLM3ZMtqtgs+qf@~c!& z(DEh?^Xn5jeo2KYK27sp6W$Qg(1wLm!Y_uBV$ehSBgr?g77(OEj{15Jt+#oeP#ERz zYU>_s*}txvu-E$0Ftf=B=Y3&xT2fpF&VUWtzF#*vn1m;cmsrnIYNw;&%m2_2(J^ynP0QCI78g{h-&#-^%8j5m16C? z5xvud8}Ldo1&DSGPOiMT3noFu^>@)^b-z)Tz#deusgiA9#6f9D*w_q5rRN7B0wTR; zu=cCF5y5RCaTPqMqp}ASaH3FB3{g5jbnx zisb}gb#N>=DNAD_XtZ^kcdDBqS7k$eBm((jC&xT7I?g=F?K7uKu>(>9aB06JS7+{A zaJnuYK|mB+F0BCSLkgJ$d&Zs5H-hdYL^#HsF#;oZMH7 z4c0udKn0g-m})bB42RCOB`7aG02yteDgsJ*vcqISBNKO&RCq)d=D2^!wwL@+k|_D` z2L(1ND9T{dysze@i zfqVbyX8V64W!E4D>pmc*Vs<|Uif*`(!x_l~M}*W>*AfSs>@6rFCXDp$pX-0dj+5J! zx4AQ2`NNH5^wH)`Rf7f&Z^^w~=zkKS_kfvW^ccwVXTSYv!x&)n_^`Edq?Ziwg+yUC z-|H)5WI}iZ3HNHeV6a{h4*= zi-;|qO8&F`*G%o2UyPg!+3+=ftp-V`Sx|+hqYQF*zI`IOErdX{{>^xkST_;j#y*6> z_ZJJ5;X-cwSUoq48EgjW0nkvO+D9+zldxdh4#>)ITdxSICS#Di9e)l%VPWZgp!bQ( zm58xWfzpBIspittaHC3saVEH*h%s#P5QaF$u1mgzrWj93Bab3dgP$3UV&|3J09P@1cTE9;VN?y;g}7(B9*6Dj24i%#g)d)w?2pxn#X z^fTIXL{i-!v8mCwp1fvYe$ z=P0kTYn}|CTfz0-gM)Q4Ashyk%Z(03E1u>AYvfO8pXGD(3) zwwSOe%^B?;du?CMw`JN)8R5aKYFRzW)3M+C4ka3#+0H+PFjN%S*1stFFVj)uziU{f zzocE84%N{!DweoMG*I;t5^SukJ!5x$%g#+EJmvm-qe1bwtHHJcL^pOA-AdQ-?u;H6 z%AsC5f7c5~nL4+-3X{r5XGS0c9zd61O{gN30zBNhwiAt*fu?5tAo6!ppRMod&HnF!fm+QBu>DnIM*%GaNvBVW6A zX8o1!dz)5(2T#o)&OUvSyP%g@)$>f0BxQlZ4$KSU#j-r*CA*#fjE8cVG`syQ_C1|1 zccc|=?UryTb?=xfu7Lb2EC8B`T5C}IUBtWnNbp|Ut<|wlOj1LZ13O}uT*E1|9zT$~ z&_@Jr77c@XT%*V^J?&YCdj2+SiD}zJFHGpHeRkVO2cF9z(9Cu!T8Rvp|1g(0!?b^@ zFfH_`op+v%s9aobv9zAo;Yh`Ny3*u|8?R7wflMEPYFGR_bx3NJDTLdF8!8t#OE`Jn zd=V`v`X1-Y_Gbpc^~ej=%nRIvWXN>EI6uHEZmrt7rPHtEVkLH90RN#0>*~k@SCiKp zoSwnEQPdLrw>t2x7u;`JBF z)=<3c9ufCis)rMu(jW{2M-637R;TRLvoABOVi%i>BB~BYWz1&~3coYX=i)usJ_M|K z03z_{wj9;0Wl7L12iDiwH);e!?ef@raNlFv;4N{PC@gS_F1+BOWeuP=5g}to(O9qv zKOc=cqI&MyZfUK%@3Klw~meurCzjs=8+PhS!UB zQ1xu4i^>f*t;wz(5##XFBi|z_djkP3nw1GPi6?oS7CYZ94Ukci4rl~7riR|wkg3u#1r zu>ggC{O)9Qb_JpK)APkn%gwnHyrRq4X$cAnN&zb#R4=gSnSdREKbTXj53H_4>1pbXxd zYqQTRp5Ki*S(GuvG1AD>ic;#D?2}1<++G(PDeROWE%!#+j)-+ishQ(!;28H1OhB6QzeU zb4TbPNE#o!$|#D4*dw&>>--;}PjU=N+nUbq;>+`E93`&T zP5iLEBK-qx-6}=zQjM1Tin!)w zCK7y}w87TB3|OU*1#%{Al#P5E6b+sMHwfSsE_IjPHF57^j!4GAfBP-Y`p$OzQRVZw z7X__H#6wYkZ&c-Uc77e@#{m6)Ffn+MeE4CMgeU7JB;$<;8XQ3Ho*f4ezlLr8C$-Dc z>E7Wp=Q=xU)e>GS>KEiZwRbj&DLQ+5%^jcQIx!f^x^Yi>B#QnKLF>V0hy=m8Oc(h7 zGN?Erfy@L9bQ+b@5m9IdB9BuS9XfPA{r*Jzs`{h0%Vh#LQcz(6lxl088ujdSi%?lVoL^ z0>0DC(J{O(GoA~YmyL~Y+?AO{yN&57AEdpXFj~0#*+?U14b8uRIM?oXe6?J?XIv;f zIivRA!3)Uws^^SA=u*vJA{~xLKbXeZS?U=rXdSSESG&{jcekN@!D*1>xN%4?!&cs! z=`9qRZQ<1fe$eV@`4k(#!6lvx<}l2!I7U^rH!uNZa^*A3TCq92CDF~r=ZgKKBKcxW!@5QW^KqHicH;&i^?Db+;s_oFpXZcQZ=3Zj0JLfw_)l(v9f&Pog-)Z zzcQ((-zuo5?K7*0ZIZjy0b1GXqBR>Q4mcc#a&<}qWBgZCobdVaeNokw6u%-+G? zL{WI`-dulC7oTrcl+Am(SaG1r?~`upkhRHW6bb3%9Q_kc7iEw^m1yV6mFqv+iTeX< zHQ;vQpO6RY+QpK&Nvr)6Y$k1R;aP)Qd{K+7nY++XaY#v3;pHmkND}*)be_+T)Dfh3 zvse!k4U^0Y14@`U07yW$zdcg#5n(XItLJHh$+letrU=lQ^Gb$ziBZjA zI?sNU&uQ-!A_~5vfgwN&Bdk-T>LiR+0^!s$cDx*lr-K{KXYx~l=RdPJOS_Wk2ZoFv zM~I+-d%A1O4TlIpZY?C-Aj%sngtciKwjg~-f6H+mWQgK?^N6d%_>aVYW;q$`SU{vx z|F}n}!t5)2&dIO*=drbjx6!2cVWe}5LTUi|rAEs>x3WFrJU_Mn(44i03akfFAl5Vl zctGImL>c}@JZiUVtA^43Bk||-rCcs`@n0*Hy-d5@_ zY`U|}I!Mn#XY&^ftLu*FUh|@Z!s4hrs=5;TCn!4)oKoVSL_e!-9(n1>tEWwO0t*KC z2|_t%-Z6gqEqc&8<~(ZX&Y7VN2Tnqv2ZrGl4kKd2 zh&iDiL~)56~$#0akRqqjXHV2P1NtDLv?z7+48q!bw@ z$=_MJ_pd^*`H0@PGJQuY`pA1X{@@Oj@NkBJmq8CKTK@LoEHuDVaj#Ki%of$SqRN*@ z@j$tT5C;6%@>rK<0m3tyW?H8_w7l*)`QaaOJ)x7~?vcwVnpeVABSpF6emP*p1!3Dy z=xjy+fbKkUFEu+W7x&vaA0aLKU&%BrT-teWu4uvcyS?L3ItaC#1rLs>rI04J1O9kk zR>vorWRCJJ;Bv^OC>i0ZSBK}|WGac!tG+Z4Yaxo>iiIw+b4r?8j;gCIpKL~|vN^HX z?G}`H+H`%Uj6gy|!$z?g`m0is^fbudbi*xmM0=!icm^vSPTJTPVipx9Y=TZ)7{KD* z0r@J*%J(adp*JZ4T<6KLh9Wu1=7RDO{%z}@I`wsSZY|807-J;TYH-aSXu_YL`_J9L z&zXW_S?2#anfcu*fGoV5RZ-m7a^^_1<+L!!uhkdKAsA&!zK*M&u8(=7`poxu?NFj<4O3iD!5nV6K$p>W*gdUL6KCf9@QrawLmfG<`yCW01 zxRzks{@IsaB!Vmg-Z1)phS^K#2Obd%uwt?PKwu8|zN zZ*MkEtmQ@>Hc6MoK~h7MX+SWhc;SU8Kaj!C`?H0ZxTNR*uBJTfag6G_TWO|y_h|-C zEKSXml*9&;A3G>H(@q^^g{THbk>RC>3g~-)N>q~qnvdY-?Je7b zN8A6DbUWt>o{{G)Tr^+0KtCw6OL&E*bUXy&`jgAaTOjPMr(UcnF|FI~uq;jlRUIIZ z%R9TxJJYb}^I8Lj0}sTnApBb~4W??p3_ou=#SDAnN5}4biL`&+`#8q&Tc#fyQ9^Uh z+Wms7S;0CFvV+0>pwsz_lsPb6ZpKZ3v%MHTug4#K4lJj~%NyS0M~wWP`FFbzMoc`= zP<1dMR)f2@qGw0RbXm?qre;y{gd+l4XJ|OVZb4m3%{V6+G=lUym(Vk6&QvW@3_%@I_BIp#8j1 zUsU?J+1^_Y&du0=-ShjKnZFemdfdRNx+RsKVbT39G&c&$G^wjo;F&{a<2um)i9!Mk zloYb$krLWGh}S9dteSm%^=p7OdUVM@7zl)e467pZMHem95->W}r%5g8%}nrjy#B51 z1oyWv1i#DzgH?0-tuA9#y%)RebNDWqF?~L2M^S;HRbQN=N@};7&pc|SM&j`s8;$wd z80_ell49RSB%<^>TB_KAoGC;P2{Hszm_CTGfomI~u~z&kotN=QzYMdJ>bS0rH#o

G~%DaE{!9$Wa2V0%A0YTy{1y{FMQt-ZSf+CKdq=m+SQIp_89N&)HeH}N zXm3O@=YG?Q`y2f~A)Ve?+qz|QwJWK!)iKoU3+U>NioCZFRnVo@J zs8#MOsWGidwS&fz;%M9<=)Kq(<@#58jghoAF%%o^-$h)@kR9_6PV>pftvf;li?1<~ z9BXvdKa`j2Thjh(E_#8fmZ6;C-mTfSnb}mL!b_|`T>5_= zll>2Q{YCn%aWnd(&2}3qA%sCW#xZm#*joGXO3sqHVp@s3958+=`$zW4h%zu4AUz712MyN7| z#ha) z&CrcOQW+To_U?}{a|&u}&sEj^UVT-2xIWSb+V_;cWHbZy;l|TM5ts#Y$KuY@mm`@`*Uh$1J&~?-wU(=6>y; zOs@uYLsI-x;y6!POqDDA8Wc(thjv$er3r8MRcl>sWS&jCB@#G0mkgzk1-GYE*Qf&h z{Mr_q4gX9`MC?9r{RZj9`ok6y{gZV=z~+kWj^>VXqLs@3a(LY(FMib}Hhmd{!(m~H zE7PohMc;kasyppMXW>AaBh(rYOt%v%WobX$*ZsAV@Ki!;9a67QR;>MPQYVnP zZ%!nEPwBX4OgAM0RFVbx*Ey+NA-`WDJH~4byaB+`mY(lIu`S$>gVzrcKk^6k7??d7 zw7B;v@Ypd7Smin;=U%mhNfs!{GK7Ba4aE63($pt0pybQLHZXhCv=x9@6^7SxofwC= zR1+jkak!7}VF}hQ=(*o%@u?pySS#-zOS_c>>yVGVH5ivhGJQ2$tQO))xtWX^P9Sq& z2}HPNVlnI?6vk(*vZ+a=8D9GF{555S?I7^`=IweE+ud|pOVZu8o*)%I$@_Mo@aaQM1oR}{)6C`#{ z`-X~WWu}^6@Aeenx(VNJG=Pl$Odq=iyt1HS`#=C6Qb8Rh;uh6Yv06`K2ljWT2_2rL z-JQ@JldvWxyxi$`fz2Kf%C3*mZw9r=YzyAW^y98(BUj#V4~Y@N zC}*Ex#`duyKGVTv;bYfuewyZ7w=^fOc7nILzDdmka9=jqwQS4vW*w$V%;nK}SA1u} zX*iFh8rU8U#(zK~liSk&Kf^&L%=OYn{h0VCo}X&3=yH=?B>SZCL3OC>W zAxI-)N1+eR*DVvfxuV_Mext6`AKYADCIkw##{-yGo?CbJ-)c@V8Y)W6!WGq|F7r+y zHaOd#XFMXC4*pF&k&%3t>AXZumu_|T>Vf6%Ue@aqL^dD}r?;foK$*jNeqlnRA2>kE zKzgLnkqWdboM<-IY5?0>U2}GN1NlBHa9<`ya$>vsh+Sb~Gsh&_6Q^h;(G*VzerZmE zhqjiGl!RL5uhQKKrlav#sko3-xH!2|D5MY))r@;2gx_;)CNvzk1i}x*;H61h5jA^# zZR>d61#`31X1!A!sx92Oy_r!)_E1bbEQo|9lNe7bGS9DZ^2@DO+H8{uGojOnzz?UC zKRyJKJanrlP7jdIy#G?GnMHlLUe&*lfF@CYCg0xs5wz>j-c%?Fj#$5bjDKf$TP_W< z?%+zQj(kX*(@hilvLqZaJuD{zf3`j=^Av^nS`~ZUW8Z5JOg+XE!}>NX#KD&RNh4v+`KW9Ipizk4_tKgpy#b82Zz{u_W|-7) z02I`4!K9+Cn;!-j-G13hxbd&Rcqa^kS+uy1f))ku!Ph;MF?Ggoz3=xKojQa@MXfuE zbbhZh03V;3vF*g2HVgi8@EEsLf>T8jC7&))piwHc_Bh9SgT$788Ou9>SF``xtVt;1 z{KGm*^J#s_@*wYx7RU9Ra6>j?2`gs58VE`hkWmjpVR3qu%Fs`1K!wg<;^u=uu-I zcp*4!mU3@^|IZfCf1Bz26xTKdG@8ZRbgTk8gNAlsbL_~i_Phtijk0rtUQUi~ItS#k z&XjcThd{D29l{yul#NPZ{#-->f}C050ePUu)S1i=k**0U*Sy^Ja!xOgc<*&FH0A%% zlJy54!FOEuI*+SxC0PcDB1!I1%Nh-~2i2AQr;Rq|ja#RMIpK&MPc9wUnHD_y(fmjV zviJp>jQfADGa?`@g-KuEYV<{2?>1Z|qS>Q56^SCtNUYq|8}MUIo-kEPEc_(zKG)wc}9iaX=C8uzTeSaWlmF7 z9z=H^;@ORJ6IY=c950C6AW7gdG##%nQ6~DqKc%(T0X1RG^urjO)xHZM4Rt4fI70RqM5@{3!S4*N?BM1mBZjykEI|tT8a9?J3kIIX+pbFaRmPg%qqp=lI5%4HHDScRNE;d-(+24V zl^X%dPfr2w%fUZTd)J3*%fBeXzAtxcyvNN)=3nv8YMKDhYEKyJDzZBJ~>3r_%Q(4$Jdsmfg={DkgGbKSYVCl41+t&g-h@oZJOg|khRh-UK!cr>s<$aJAh>ySV`gZRcbrT zopWa*2HuK;9ihSTldD%~wrTVi?Kf}#s**(7pXz~ER_>;-BYGQBqJiaooQxPjI3;o! z(ZfS~J$D)}q3Z6E*$Q4^o_`hzad_hX^Jckx(LXqZ{$ZcPxTZv+H%+h9z@8_&r%jFdmJWNO1QhR{0iWR*0ilo@D^tUTqTbR z4EF_>myM$DZ$eWv^}lA4`X9AYkK4>^H~{Fl4fxA7bXNa=&^L!l9aFrf-Dhw-DZMPO5Eve5C9?@uNG}#Ic^(Y-GH)g=%)B?yHk~2(U*ka@O+ujY~|l_j>vW1 zc`od6E!@O^Y-dJ{iD#&T%1HcxCwfZVX^^NyLrJb$s)7Bo+h7kVFAijj# ze8(Qip+6PmdOEIQ`i341;M*IVVprxQcT(1#f8U=vbmWL~Jq$|23gf%k9{JL=95a0H z)SwVLV&0gM)0$t3@F%9z`gkoD*ja}J)hL>QnbuR=tGEnwYmK0iAmZK zz~HO!$A4aj(b*Y_a~@r(HV}UYcz5E5;#>oGAe;0j^%hNW_4`gOH@o6R%P{m)nx^gO z^TL-~_FVub?P~KfGtW_vh?d(I|$J zI?C#~KdUbgUKLBqxsB7WVHU1AuUSHeYDaXsz3;GL&wiV&1pqtV12D@jQN{<(|7$Nu zOxFQyq&3#wPn99HfgE|w0LG(f^#f1-(-+K@CQ4)mPEcXW1p?>Do??4{U=^I39PP@5 zj~F0%Jge5*7Ga{%Rh+%3AO^MBy7|ZyOjeo6Kh|&gVQCh6c)bn?^ANQj8_J zcN_}}d4|X^P+fH^2;s#6?FKOb{HEo4+ z9^}xy?RmJT4I;6vPj1|AT@+SNMG=r2@4m>uTN?I4EQ?Zg=J8g(b7Y@ELRf=ONd0v( zp`5ZHJXOyYpeEGphfr5DuTANPtnSTW?5{P-djHBppcvBaz*c~30 zcoatPuS&yN_HQ)f%?t0_$_mmbpB?r^_S-?T@6|6J7~!ZfUbQS<$8IHONv0Zd)qkW| znF8lW>~-ofuR>q1H(e|}V%l!QT&I%-xVsAmMeRjeb9G;o7H0+t`lEIYqQ@*6n(jA4 zdQw)e^Xa(FOk4^KWG{!5+JC`Y2^}m)Xg*FQKrai0ZJqZZA-!X;_jq8({#hRSzrXFP zK)xf0RE#nzo9mYkL3fkR7YNiWuU0TPc%z@Wg)%JqiYi=na*!kP|L)4=&xX75lkzN7 z+PHj9DpM)x_-J<}Cb%H)YkIN-v%O*}P7=YK2>HgO6oUTYw{?u-;s(78{>#2_kFHbd z&R_+P3cT|q2fUw61PXkyNqG~C>w&n|FU*2;=RbxUG~zi!oJfB6J6ph|JxR1ytWW}Q zTQ~6i0YDxZqYCX=PETvYvTMzdCaFhI`@E)$!Q<{CLyZ%NAN&+pBH;{zYRq~`1$ayU z`F@ut8W|?$NG6hUs?aMe~5qZjj9fe z%%M}1kIM9qza0`K0ivr?_$=|CQ3X@8QQwv_1LcqyW{f>@j>gT24M$rk^obIWQ9bhh z4YZthw~1;n7{vpatA}^BpYJr_uB~i3;p9J)C8!d1%)0&7!c3< za;JL74Co+BZFQiB^hagsUDj-XGmDsb-fVbAXk8GYT9KIvOwxRjZ4G%cTTr%D1L@08 zAH&;l-FNytme-%mnHHGyc%Tvw<)r-md0&nD`t>EidcG@4nu~$!rbv2pcOsk}-5{x3 zHx1zDZU78Hg!in}10KOcP*W#YbtaK$d&z}L*u3fOxR>TqP7%(&n`kNGiXu`f4y1wPkB^I28E2^+c1NoYXKKxyq7Ih|k8Q;q zYO^noJL&Fw%f-$ure=ytbYt+et(k*jkU}lg6DiCl@#cB)7ASLJJl-oJ;hPFdbodLV zaO5l`>y=B$&VW=G-*`K34#*ZuZ65o3315O5H>X(DpGH5fD8PW8?qvD+ld(` zJZCuk9a%d{`~KxHO$;?TYb-VSUEKHYAI5%?%;Nv-fE=CU37kAj^h_?)OnERS-Y~^T zy`+yNp0rH!+lyAj8P~tKA0`b^+UJSV;o0?wC6m3O7q(RUR(FOv4WzO+fC&lX^Ii*#EaiB&*i|k!=p;v z-L|{c68%)!yF6MqQP9HF=c_`@=P>URWqPFNG>9bXhUH)56=g%&5jKt&4Ikj@+4@x) z?x}P~Ko%Vu_^H-OZeu&G4ZwBDSFCM`Um!KFB~Y z6at9<{Yz)`Pd+qDr-@2A&_iL{2`rm*yH|L9nWsSHs8Z+Rj?tz>w3*Wkk`-SF^R6z z>6Vk`E^^Khz7t(H3G?*C9!nV>-iqMG8{<4vf8oZpU)XSNUjPaKELhaB_?ipN?}l4# zltFqt9d9pZc05;mv@#qJ4o9Um_Krtt4sZ*))8fqF0bqo?H#2h52WNI+%yXaAOsj;X z_cC^DxGx8CAnNa1Pn(bILYP89YrIk)_5g}t4r!n(O`*qa4ZJPXu!;T-oVPdYvZVk} zcK6?0+0Dob`_C$>aR=$8BXL=F4Dr4_m(sbrdMJCm-1N*8$@Q>+OiTEUK7I>)jLAqX za6WUtYu5pYx8f|VvSe3)WyX=ceI)zy`L}C_v&%x1zpVgp+2C2&*8RS%qG9zhS^XzL z-3nZzCNJa4ruW)joRVhNJeSEFJcq_}JIeVxqV#KD=$9BR2#}!m07~NbR|wd~d}_57 z1?}}qjrzo3GN)yvq#U@7j@KiTWXDy5d5s6Hj_vgc%KLRi6&cU7 z$*Si~K_O%1I!xTW78$fC2ZK7&ti5>%lpr==WRjn^j@9-M*j#Z+faUTt@@*5VV<8&(xf6yblk$Zi zpowTBpu^*`Dry19`MkxSp8*e(k7OCH)}C6!!$+ET&7LqhmDZ7d|1I|315q5+s~pwR z>DK@#-L_}D6$rqJBUH6E+7K}a_hH;x7Q5Ktst^=d144{(!mlTwAUkZ#cuPBXp!q~P#QJ9K$!Kq8lK{n$J3Etr(8_9@@glX=N2jGLr z%?x&jGnH?zPXz>p!|J4zw9lbf1v@v2YLYQ0ba!IJ#9%KtpNYYuT(6?Z)+>iTfp_LV z5QyHCJG_W@w#r;WE>mhXsoY;>oD{huQzFYzNAc@{nfF{ToJXFm-dQ6SnPvvybOvX~wBsgChJ{-v%fkxR!1()m`O;XD6l-rBtidDVV zTzOeUqb99knw=1g5Rd?4+7_j5qpP5%g|B27TL7m2i)GhKW%dk z=NrPoFm~SMns2Lj?MiP=BNB~f&(vN4g6l9c=j(k6N*ZyZs#ohiNOLg86E2Ixn)yf_ zU^c{#Q8V3#$M!oD$IDHcXqF-j-5vL9;dWcCfa3{LOHu{I9%1B?|c!$S6Mw%TK(}&Qst2_m@wNPSvB4{%6ShAzo}9 zsf8zDz}5!WSB*Qw$mmiue=F}+_{jM_4=;q+`I3oz?BAmFiQ$8t)tse zZg<{4@9`9{@LmK-C!3+&>gc5%Y~v8Fc>p2)obd`=Jd=IS;o@U7eIte0)7oWBa}Mo# zhMiu481f=t3B9Ijtw)7B&-Q>i8v#jN=CdeZIJHPZKo@F;c@{s5rCb&eP3AMKsyf=q%$TjOUbVuH+|`KJ&w)W|Rd%&CEbeQ0Evp zhC=<^Koi~r0Jll+p`C&~gjFOPl19uzwH-1_f3!%&$ShdH@pD4LUP0m<6Met+XKj`3 zcLU5|dU~<6N=r66dt#m?)l|IC@;K(}<~7xnt~Zu(AsM5%TJBb#*600!? z&6Ki&>pQ>!uR5qfAm!m)&_(x};^Lo=_3W|N5^2`uDs}ED?gpYma484F5K^cL6%|Uf zg$tZ@VqAi?G1cQ$+90LoiMca04o{gs(DzuwVdZ;}KcyW{%UOF$IpPfBT3{zC9~f*S zJ2NcXm0%or%oSbpLtb#G?Fv>Bg3BFoO1WnY^&^4JaaF$`Y_y=T70;pk1iIZln|P;2 zIc3}hU%(Uh)=w?WlS0@e%6ya4U#>;AGxbYybFLME@z6y=sdz5ca*8bI4ui#HZ`5HVzHTgqp z=r4B%p3}F79&(eix_EQirfDh8pbAjytq$b8pOC3=kc~;3y7NKaqtgXX^sjT?^9S+= ziY7E^E_!vx4L>pAOZZnD5QlEu!#mmh8W{mEun_7oh#ms#8>shcrKJHKcitzeZ$}-k!!3^l&|}TR!?niK+ZH8Z zwmVwwdHKVgG>WZVXF3MXnvsd6YAWf&m6HEQwe~-yn^zZsj98~J7>#O)$sQBrwk+Q; z@R;|*D4ONR=M<`KNom*#)^H{!(*kgc9Iv7*AvA?-l0!j}e!)AgjV0q0-*?`})A)OL32c;t{C&ZI&-u5uAM@bg~+xJ)+>Ne>omL<>^l#` zW2tcPCyD?Jcx9bEs4Ko72s?nVAZ>WOJs(b-T;Vy4 z<_TCRh7g}%)+sd5`+EB)vd!wu6gO;WJKrG^|p)`(htE5zqZUEt^7CS}3nEbXN~+1+ z&={tX`qTN3NU7lOVV)SCLblavQ9mMsOTD*uqRvvF1X{U1(oZ(Z%#rVB{c~~Z%2nuP zhIa%Pt=ou2^d-PXa3&wu0H0iFq?6?mz`-a@CPgQ#^xxqTt?5wEi_-W3D;^(WU^>y_AG*ZANE zX-9(o;di5l+8c**cpk;WG|O&SieN~BzWzFwE&wk7x&Pg* z{LlISUwzEyPY^l!H=l?MRH+;l%~>Z?!#O;hAP|`$-acY(aM2DB@cBZj_czW> zPvGif@so}9Qy?7dc>UNfY!!yo5$caNgWDN=gpDTWkL>UE`3=c3jguQjm>DzdX>^SY zbZ-60>WkuIT#I7Ss-!0MVjLK#*IoVW%7B|h#?JS%m2N;VIr^oT5*e;AOpd1Jto-8Z zIS=RnMP4J9%g5hsO^p+Icf!a9P-dI~-REog>%=5A3(y*-dCNO8;FTOTe^1x$o|6JR z6>5sNMaw=QanVU6G3524r)T#sTHJHv0`3jeuE>?6=-%!knv%&(MX{bBjj>r!esIaY ztAZl^92?$MRdEz!-vtT2z$*4LWncl_1mDL*@dGghrOwf`4Ai;Z@Fi>! zb+g>`hur9#s_%}`keVi0#A#O0I73y@Gs?!BVx*8}vvK7dgx^Zu(D4*Ifn1zd4YlK6 zop;gB5+8Vvt__;K%*9qu4X2g3iHiKiZb0q+EMhKUh49ShBH9K_jX(6@ot+J)ms52N}u|+TQZZHF(29M1Fsbw z7pqK|j&=Wqi_XWpgVU1sHoC&vXS`d?1l^Tp-S9aJkL$0^VNpRo#!2~_yn|S$!byhh zl<2!@CPk7@#oypMEX~RqzN+T22CXqPOGi&A!`7WWpKc}h6B8}*+e&e;G2|O>7}ZN( z!q-){=Dv(3E|Y(&mOf#6@sq4`E&42J*}*nCU713qN@MbK5^r)%Kyv)>RISzFZWVwI zVv9ifgFIn}V#_!gPe8bhEclhzU7Z~~fPerZC=n8F(|&a>eA1esUZNY0#WXCyMmpF@ zp!nAek5Qk1E;v6yXuzzfcjE$`UI~dxGD;uImV)M~g&o-xikVs*)Ri$|8Vm zUUOMRt31K#J)`&^769Q86zW3D9SAaOX|`Ov|ZlS)mct}O=JM7(oR9f@Oq{nyk~oTlrA5bU{|LJM0AqMAvT zV>B@2&{E^*5Kg-MElMw5{@&M9Q=$V8SJmduq>g#r9{AUJ@=|-dwU-mDHtxWFlvDZXrH@XFxD6#Wh4R8 zm2SM}OWGKUh4K!o!O#qy-J!hX>*Eb6I7=WO*2lk`t~L72X8_V{T_0YIxDa#zc>DT2 z^5^qE7UhUe_|W? zP|-|`lgkYrP`|ZjN2WSP0b{Uabe;kg+Y5H?v3k|g+s&@_wGZ!>2cTRXMw z#H$_lU_0{l!jFOX!qK9yI{?P8hlbc5IXX}J3qRQbb4Pvn8NIp_H?GVrD9Y8UWU~~r z`bo2*D4d=(bh|t`2t=exM+St)#Jf2)ixu4=rBNTRTx`X2Cs0G?U(7{i=5#Dm?vv`w zH^3HgvW(j13o(Y967+rlyM-=$irK#gz;}o`ST=;^UY*tx<^iK8csEE}8NMS@@CK1> z8RYFNK^&v6j=$nBPH_DRaUbZl3!7CcCq4v-{g{w}tIrgKFu&9n=kxTZpQ_7MCWa0a zqae00wiFL_6^>?SG*BZ=P4EYk7scZspG?1^1FDkLvY;a4>3X=ch2i>)(Cp%0tp;0I zf@XOSiu-xx#aJwr)nGwk*cPq)y)20w3iXB@GNANCiUU^LOJCrwQIMb4(n_8DRWN4) zF*a81^3!rf>Y}VhC2t2%QheteI$Vm=a~LBbamMtE%gN8#*IjXmaco-BP$hx!Q$uRW z6+E-o35lDUbi)Djn5_U2*xuqp%#$+g`Avm~h9Kr}ymo-U-JFUrS|;x^;n@9`ye^kg zxa+A{&m(BVXLA(SGSYSE$D{+_knt}W(`x2T3S%`X2gGGjwt|(PyR;Ts#>vjcF&z7 z9T$du;&Ky~&D3EZX!GdfJ2K_WT5!|kwjBg~LXYG@9}eaZm?oDdyRM?g$Bhf4=mbzt zcT+6pT$sizN5$=!v7S2-tuc$R*32&e`#SP8p%5Do%Yya?EV;GI_PaJ|{C&~CrCyNC z(MBR)^)TEtIY`#eJp(MhBpub6Y`vcCE$&dRS1Q~9l8)>z;IpZ$UTxU7uR24#r zcOvc&(9%tl^`NYC-7VW(FW0^Ilnnw@xgnVKUfp%NY6F09DEZ| zlpof467$hRUOR-jDDgViqym9%SyOf1j#B%j!O3yk9gj065(jYhlca<9`}+BKB0*+5DaPS(@)8LhHB0oZ=PKEhgWt+`m|!22+-km(}+O z&^#1#H~7r%SB7*@R!$+PnP$_0?|rNy{eKns|L+O?2?y~VJis#?%fbbrx#4OF)DBUe z>?v@WuLTjXaN0it`dpsybLQuEo+vsvUqa2c%5pQRSKR=g42sZ$(J+#?%z}4y2R`Mx zE}w#3Hma`eL9$*a&7|&HC~1?{+v9w7_A#lGsz5V zq?d#EzdFe;*hFxP!D1vRxZmzB=o6d7=QD|AcnW75n8A+e;z>eDdjek;v$wF;J>cy} z%0FIJ917S!e4vX^%&_dtlC<|5+#R14M=L_XINV6-_yaF`f=qk`}hgnE7o(GQNW~Be=xP%ftVHjMXE&e znoYLyoHyC?shZ@f3W@;La(z=V;xP*b|I@;w-Oa2L63oCu5*nF={4Q>TIE2)=Cx|=^ z90uwh$5c89gU98#y&y7J!EBJVo8viMK68g80fzg+?ngI9TQg*8^Q2L6C3zWKnaHOg zgN-gM1vJaZE&(EPO`ly_gMk##3m?WVvF|^o#JR0 zjJo^7j`7WB+v3MGR7*$XUL|{hw@)fv{&A)&n565?Lc!Mmy)EmsrWciVfP&v?>Agh7@2e#{T3L$JT z>?I^Ksuu-3H}TlHbdU?04)Xno+9s+#7;O!$ns_Kn0cMs32iYtC9D;_K& zOTTyFQZumn%=kMr{Rql##5f|>_XZEtgnM@>K_n)7{_*T?TUBx8C zYBHB)#8P`MGz1pkP`O-{7F@4J6C5EB)#&g5TcSruo^n_y z$NTtfy}nQce82$s<_=DiHHcJNdvnmev{C?!gVudaRcmeE66mq=!I<CQ z!(e~Piq;=Witd0b`Q*5Yc>&OqiE<6JZ{fPsLE4`sD5L|sWYRP8%>U?gWa{aFSZ_Jb zeMcU?@Y^~sPH~7khSSj0nJKy&F`wbpN`PWBViOycH4X0nx0;jO#x82eEyx?@zw-}UiLnV(R>L$hq8>Bl>1z68vV#gsC< z0&3n0jPGoqtpbMI1vSgSkgTRQd9)v_exZAEoXZC(VC~YII&VI@L#uVYW}`Y& zVcgk=cGaw5WonIiAsQP*>N1FCi9NW720Sl@-vvzR$H~9!RqP-+HfKK2ANB7fSy#zRcFpAx%fZ#)+aG5uXudCSiRGGp?Zwzd z9p`;>Wdnv@zO~8_4U`9q#z4thl}-)qBF*~}3vC<)Cg21Dt&(0jwbfUJ5uw_MxD!NO zkH0;SC;JLm-W8E$%oHqVv5G-tJ6WFrn)s~37d>JtUo)h6HH$V+1sou;%iQnKdVJaK zw^7h+(6EY6AzdHilIwpNxadEkKswR4_;~*!qJN&t-S-!c0TL}L)BBYqK|Oo#Ofq^F z?Bm=4T;sv?^sQO|uDj#+!2NvbmoW#XiH06TpzV>=DEADp@e3=GEAYp)UzSzU;{K+* zLTq@ZeFHmWe>w9COl(WdT3_ykt)Q0cZz$IZZ1&O|{6iqgV#8P$1$_!Wy6d)70REmx z8*_~c%Cq$p1K5_0FZG~qBhh1;*!80l1C#Q1FZVI2I?{D1PRXZElWO7s+1-((9K!=H zvaK#?TNGlUOzaK;Nb$Wv!w*m#PTKOkjJ%;4Umn_W$3r21g52J9j&XX3#t;L$Z#>d2 z;+LIhyFjm;NDS%m_5Y#lEu*sRx-L*UrIGHG4(Ud^ySt=2q`Q>v4(Sf*1}OpQ?wjuJ z(sSYSzTY_C7?0mL=cj-0+WTI6#awgE1x($=ECZxCy!+Xqizv8y5t1&mriAiywtc2f zs~z|3JZctN3boLMnc&z>xloX-%}4p{FD(Zffai^` zL(7?eLM2LVKKu3by&qez;O@t#(~eKg>O{%SzaEcfi#LDoVCmRcs=MGwHTER`RPcGX zOM{_OP1Z2glj0XbKxJLW*?MF9aeyVKFtj^zs@ALwcXXg92)bDy2X@TA*Qan9DpNbg zeXk4O-fLBgaj(fbC@g;Yq^Me&-7{-{ER3mpE>7QJ_jpg>uB8U}A9w}^i?iw3FPnZh)gr%G)wx?JcsY}x-Ts#k2SsLct9 zVn`CIq=lz2E3)ut2qHEYP5Wh1#*vo&!xuUVYQJ~zNm_w%*b2w)ew9e%RB-eSBU9`u zGDqk5)lr~3;7hSy^}rHM)Rx(+6w4z$b=`GXhQQnd*}a{}_+)|_tlUo0w^o$-gPaZB zQvh7m;nMRp*GCrEj;#Sm3Z9&^a`0Smd@nO98-9JE)G`V2Z0CNay-1uhM^#iHk}x5U z>YOw?hn~idezCK>`VKJI@fb`$e$!x5=%es~{A*fmY6k%9I#_6DO}_!$FJ$~qmjbkX zHK&}{Rr2HqKP{~wAhsHtHsQ!{u+3ph8$tQ`)Vx~?;bRc`7F8NYvp8(&Y>zY@ZL+X3R=hzTYh`^DBKAK&x)As^*%{j3XrZOoJg-KE=XnIw0dW1`ObwGwH{It%wp)T?C45 zESl$>=v7{%ttt_j_E^~_cKt|mI(z$@ThE&dVIY;mHhqk6i!ALpN6=>Ei}O}Z2NeQ_ z0|Mmw|K{QRw+aYA3l>s<=R)}cdQ4aE22#DPft$hipf4m8$0Uj=AvBY<_auRC?4P-i z#1FBO;ch&dQFyQ>t_&%U-M!|n>Xadng|pfGq9{L9+rWAP_3}E2IZO8k*m`w-#h{AR zC)Z|xDN`TSjT7&{VBWSZES7Zq9BQ~w?dw_#)sMW}0iveNiE4kup9(ATe zU{>1Rmn1w6H2OaEaD7zGK3bNFFC$IE->u%RKOTmY5APMWoC3>(%Z8MoemB~8cbh4h zG_0lp4&M}HK;_}=_b>Z?q9OeX`3gEXV`DXN1a(2xChC5-ulIxkH06XH zB#x0sfsDSea<@70<3C3)(|Q^NQYd9I1YT(~vjGdYY)$Zy#qwEYS06}{L*T9hg&yoQ z^V8tFIYF}h9#>ceP`U$*bP*NQoS7Tnq&WdPF#h~LeQX$oH=^{4{lLgx$GPw>`3AZn zvJ^H2hkhzQT}9U#-L}9}$=dt#-*27QUFY?HDMVyioX>#Rk#{jMtUjZ(jykH!wkPqEH5)@af7ekj1MqD}Cef^}TnHX%yWZv5Rw+A@ z>oR%0E^O@t`h5@Kcm(+J73|&T_Ney|j=yLd&qpJ+fb3}FcdX$pM3?8P>-@poqWl$J z=SD$-yfocJrha9u@~OMlEP&ooM-~tf{TxD62La8Qb@>9I!9_>lG9jEkBhx1hDJ5}V zJKwdYei}3ir3+2r_7`ZyD8`=(gsOVAX zkxiXXzJG3sH6>IbZ-y2*&0P|{DA^;pqdA@w0)+(iwzkYFlHxs8HIJ6%NAR;W2eLpI zFLnBN2OWXg@1$v`Pw@1}s^w0txQnURqc5}0yo+tH8^s9bOoy?Y@lTfF+)24FkDbS@ zoGgGs(}r6C5i9-p=nzGVJFM>bGRa9U-`MNjzM-oTJML`3Gy@^H2*m=bix}CDpz75_ z6jerrZql0Y0u+I9Nd$0%pM{=OV?u+0MC$k?HON21rtF%Wzat=2Sar8pCu}x)tsZ`; zng<%?jd8J1Yg|`@O?k)SF|4Aw_)yPd21)%LUb~TL@u&t9x4%C~2|m`ZBzvN9F=1|4 z7oJ@(O!xf$&E&Tua~N%dD9sHiugd3WECAOC(lNU!vk8hgd3WK5)xYDmX0}%|I`>U^ zQ8fQ7*uPzL{3O-yi-4y4p;n=K>orLjF~hI~-Bg2FD@T>I$f7svHM72w79!gQIC>6~ zsp7!!p^J@2#1ovmI}#N*Y=%JSJhv^$$se1+GgZ2Lz%9HX^hGsq)C2n8hbZOf&GsfC zJnG+i)-_}V241%XyHpWuyT!uVbUv+~sjDdyccLz9t_8SfOP_&#_c)2-Don0DG0 zTq&)S>Cogjk8!tNt`qC`h|ox)??R(AgGllGn1?*>pCD1rK^t*2Dn(pc))X%_UkISh zhhBiJG^X(dN%KLPcY@@od`}mq{K4C6lpyullNwc3$Uv=n#iZ>~ zIV+XGFSN(@J4C6;SS|vav2dbTFL`RHq$)NNxNH}f)xSg4WYw%g+?LgiTGcBc+tkg) zsOEsbV#?=!B5Eim1lHtxU%5w##^%?PHwTr;oAV}e8xT;u<3&|Lfeed1*yV{GOa*9% zDWYzUT&D{tBSCMrT%k%*`8WDFOhJ@2n%SNuRj4H6n+M6qG0jc=@HO7&)X_;p=x;gn&pbsLLFlkD40CWhC zCflgmT0$x!%ru}fRzT?kRd9KaEms;2s3*n<{%Qsk%`{Dr^a9rH-nuUj#Y_E-nqU+v zGzgUmyUlEGpMQ(J4_D)U;xcpahD%E=7rxowmP8KA8!Fs|G85+D{9}Ls%AMBywhNd~ z1R8%ZK|aZ`1(@G>NbgBvW4Eg7dDGFw*K$AoQj~;|JxJNDT%zel;sn z*iLMlm+L{nH8i)_O0=d0;}IJw#z{r&U2UkP8g0`IcoCDr#b4*U%;22ueu9~VX#2TN9@PjBf<8@(btS^8?uPlSQSJ$B=Bxyg zreA}yjMsgr8VLuab1ECtsg{xL%Dx;q_Aq{V0ibzbXgnq42n@PJPOdZQ`T9d(lFUw07@(b1kW@6pzcWU?69KDM*e z;I$!)MM>QI?xx<(z2ir-jY^c73%0(y(fxI?V3w#uH0_vEd4@B(@n2G70NXZ{MAak% zu$Lb|7kt^%qo#@yd{0;?>PD-3d~N5^7&3s&K$zO7(q)54HFBd5=Tjs+*JRoYMC0K% zQIavf+RZsc-l1G+a@>>@X(pH(CwN5DUCjCsPq!B(s&6)HY8|1zi@N=uLGn6I{f0V= zZ-a)QR=!+#?W$FU!`=II{aUJ3Te}+X%9Z-u%HXO~Z{mb7ht4#mjgEi%o@{-4ho3gx z`}*UDATCirSP8q$zzcusoVe_*StU~bVh5odX$!$_#<4g)sz%#nwxz_f6+<1Yi8d&~ zg!daFjpY!^y^j-%fO!e&Md+d-vWYdiL+(>A>njLWXG9*b+rO;8=j73b(Pd?y`$E+r z@3NOawwFHLW_tz@sy5KL%Q2*y+d=dknL|J#`|r6II9bg$+B-^+vXI=sja$P&qR@*x~?jEpFIWtD%e`3r&_Z zC;mxgew*nAhsnU2%YvknNCrXp5w>uYt!z%qjKy``Cxo|`c#&M8 zPh}MOd1S|zu}SgIYNo>7u4<}#{z*2*ntPi2Ms_?J{Ohy32zq)CR08eQ_H5!4);};D zYCy{ho|~iA3)k4&mq&MQ4W|_IeXxZ6CtB5az6tu&tyfAKd$CuomRsIj#}FXsWu8r& zX<#k=jMQKHFR%2CWM&8%PVlgZI70#m7rYjcw-HmuB+UJ^cHsZOgS4YhS(S&&;%84NJAGZQZ=+ z;laj{T`7hdC!S}R`%}Soy;-Fu=&k0PVyUmVym5POE|=~Rm#1|I2K!s-v6bR6@XaMK z(PP*;^25Ds4|55-yKECIh2kqmEekE{5oe zKm6;LqtR4>l+m?CrZB7zcA%RQeXiDZxzlWJ+R|_++vqo2d<8D4s-NQ$)|L{JL~MDV z*Vw1{bf|j)2u&(0u4 z;uGV!occR5L#L^5+Z(4++qs_xT24Qmt%n*u+t50|S`Ej4YMy^;UlFg;xNlgAY3@-s zIKFk7KTPLFk>bYe;6MvC7#QwNdv8wL0YLPw%d@WSnH;fhYQ-4>riujSM@j3;7d!{a z3=L*|EbYP}RG7a0{>2 zS9)fC1SKx3U@ONd*op18RHO&_vBDPW-54m5KD<9D$Ddw0J=)FrxxUl+ZeF7}4rWl) zHJmGxnQVM-n}c*uK>eh&>_Ja+f~LHbt5ZSVB7`YU>%pBCQQwiUg9^kfkz?LTNGZ#^ zdK56>l;w8vI=u3S|F{yR?0eS7B-3<;R9JaS9w+lx4;V|%Yzjb~8_zpK+=7r*0BQ;8 zgRZNCIqow;tr~5jeLl7I8Ox@Zgqcr4h_* zH;uq$7~7TG3q_!a<9;zd+s&Yu@b7rjtKE~p)ys8zOdyALoHS4`PK+CLA|TffB~Txw z@o+^jFxiQS8fpdE=8{U9eifu_I=>V$K!duLB)9p>aK_Rd#<3j>5N#7NcIcab{qkM> z;>4yoJPjgW;^~av%2;%gX7?|gCm{<_oeYdNAcu-n*=<`*<{4^oVEtgOWBDu_@yC?F z(3qjFHzK*6UGV!R^9L;;7$0(|Vt-mDHJ{@D%xchfkoKLI?_^wZ_Je`7;IkA$la31& z1`LMotXyEbLzI91j)xeQt*OwY$l6(?aS4e^Z|rBp+nbc^1r?Fu?=>C)L-O#=xbHvi zvzs7yB2g~=3hXF?B5;o_FXx?f@@>#NdBOpxf=?Y2GeSW~d+duN4;}SKyUP&*X8&FW zzWOSdP$3QYX1=toldp2!8#aw%g}KT75Jw5lSZ^Y~_TkWp`om))u?2*t>TZ)xe6bzC z3KKK({_QUJJqq`IQE=*E@;j|}O6fab1+X9VNE7;Nh<>Q@|44kOQmZr}sFfaj9Ce#Y zO=HXW=kZT`0aNenp*GyXM^Nwbh=&E3U=giewu}aYF;yko@GIsmIm$6qfp#O_%GcIP zbH zjn>**0^qqM3Ur_La%BlM?cdoV*}%+@LHxV->HhLrNV>bwKLZ3hDZ*1k5`(DnCs3H0 zrvOoehV`Xfp^}SUKoKlSCvc*Cw91uwB(hM&{S5JafPi8HP{1%T96 zCXG`5Of}$v!?c;tR*ZQWotD8Y-}5O-S?`4L_&Q@S{Y7+0~SA~2vqs=h3p;9)Y`3s9}tE;#ItHMueDA{#Ff zeQRId28OAlHkZLv&om-h=mpbEH^2{-Kvx%RX8o{ZQgcY~nK%Crx%!Kcub(JB(>+By zaBYgq5!Y)m6tRNAMyO?17NXNW0gr^WdJL2Tsc&&DFh4oVeDBTy!S*lLsMz*mw?;Ny zb&iy$qHH(7rwi;-6wQRrbeAlt>yYXFY>Aam2&ne&4dI#t%Cq^; z$ybx&j%{;vcjfIo4^-M&{KY%2t2o?UDYuGChi1CNK&}UbkN*|-|NO&HOu|qR00-SX zbEku{))dUUT_wAO)QoNX7l^o3Vd-GGJR4r5?=b&Z zR3a)W3dx-t-JCe_o#M*T1*l)s1C0E0vqfp>htIi$3LoE<<50jS-{*d0wX1R&*MK!K zDHTlkXw(~TayY(%(%m#92prF{69)>?Gpa>$=!L+2-wR^w#+8Vy++|jIG!L3k>f2kV zu}j#GOO^f!!pjsO!%}w~m;|OVf05-{%d#U=o=GQxrFVAgo*j2bHqDjt?RNJqmGUQt z4KDH2Ie+)t7N{0d-8)i5_Vcs3+^bFb*R%F(24+cWAG$It-y6j1MVLWnQcgXZvIp9{ zPzp=z=j&5w)hK;~KFcsG>l0;Xspy5W zgk@zS)(8da>kpjF3&l5S=qq|UHr0&?Pe`%WUe$J<&g(!$wIbU+sH8mF(bgB1Bn!h+ z=v6O2cdYS}cB?0BwE!*Wqg3G;D8W!hmFE2{yU)EV=&bHq$k)ppQhmsPBd`PjJz zJTscRJGQ-GZiH5I>aI@zsh~r%F);b9!#A=HPZ$DKW^9AB@W!sp`Kqcd*Svt3K*#oN zAYaJv&5B$;?K=w1Sw5Vp(wCw3xcs|=4}}S!%=X7;f(LR?vxYR$9boPUyCKWQ z*$AYOvh{ktr!hQ>045TNCzq0I1PJ#Yk1N=LLIW~dN?eRp&+>yhWIBlizVy|kGhSY_ z5-f)+-?<45EVJ5#77sEHk9wXo&bHsk zF2*-h2+QYMQdCq`-t-FY6aqL(0~X1m&JQc*&FidBj_vLV3IcHA!9@Z{MLPzUTFkWV z-|YiQpgCqTM}??!7AG!DqfhThkPE;4rnT^l@|9E0=qxKis-U0e?rT*TTfFK5XO8pb z_Oc(#e5o9#CJ-^U9_dy4rNU@ohNms~&DTLMg0t+lrO= zw^#gU4p&h;mjyf}UV!ZEq+NXZsdH0KBNl%3NfSJU8ieX1(vB?5#RT_;;Y$xM65L@% zFgn9ySa^E0Nq{&a!NB=f7y=^<=rf|oYoYw9d|N2AB;uf0kcZ_)e{O-kL1x%;s13o- znTR3G+aAYOj>?1q&QUglL6-QN^vStW2<9_Qx`Y1HZn};}_W;PI5C7z<%wj^PIg1_c z%n9^AF*!E6&{xl99Z?lLDFpV(wqB;PGzha7v@}M-%R!8J%LBr0QhnBH*bh?kK7fO{8Ds-3nXvV*F*qyf}lOYE$)-VhjURZp4 zy)bryIj^!%zQsA2ew}sdDqv8IR8J(W1DOSR^DnON&!yFnkxc-%Mjh5(Da-?fZgM_~ zVJ|<9;qdaZ)yuaUhz`ybCHO@jpk@ZTUeeVp=)RfxnnMX9tA>Na0%t~|Jp>Cudj7yd z4V9CKvQ-riO)b-oDH0hl*dB8f<;<+Y!5O*r(x;IZmE*27Mw=0Cg42KFsYid|J@)+^ z%qIS<;cFvnP{*N4_N&KXCPRyT;ym38dKcnpH1aINhUb%qvhg{l0Q+GnrgO+_^;3yo z1j1>X%UZK7;;LmjGscI8P}xgMyA}Hf+;N}$FQUt-K~t`*MHN?ZMUUCoHA}TP^ zT?!3|umioiA0Iwu+6Z%hIt6KT8zo0OH&kuy)Y~nqwb(tnvgUeRw0L$^or)L9S4-p5 z@~X8RWBes#_`}sp00Z7MljPsl?8=Og`TV}F%RwMJy@Tu2f*8wlg?rPJJV!+aft5R5 z1^b|w569FgMQACl6bb_$0V1Jb5Q48%wb}2JVU0U=R=#4Ub3t;l+E#pIXG4-V_P2nP z!(0%T>KVx^p0CvNyRsG~Hu>7EPjC5#+C`^4>ZhXEIQK8!>Y7E$*CZ(t2a0bI^(+_Z z3d_zb0H#Bip-$=3Su~b(ClXsr)AGdI^t}r>-NDA!14LNaRb@-VkW7C>~hNCm2&h6R@{jotp#8u=KBUH@E|t%VTkezO zkhwcNj!vKSVN@eLiO9SvB<)@F=8G%ZlK3_befgP*?~X}2ND)tRsp_Z!U#WHWQm}2)oO=Ea%ZT;wur@;&2V`7Uo=hy$B(_U~>zzB-u4W55OQ9Q%Znp<2f5DUY z2px+|_!y=KpF7xp^0;AazG(AN(|{yP(N&a!b^B`EZ`yEjg=TlTr-YgmjmW1ucFo+` z=D47_1kV+Dpb4<)mKw_2?H*%=hXz@{bZ}03B@OLlEUiY)7Rd1Y^|HFV(Qq!IbUX2? zXuylVet<$zDPY$3m)QH(O_p6X4^kS7@U;4%%HIt~hi6(ZZksz97!y0KB{by{nfs<; z4^0Y+ia%D9+5~2pW5z1VhgjxNc?!|ZReV@zP`bbxc>RYf`cd9?)od|%TJe9(nEY)3 z-v#Jb-Y@OoW&K<+hR?;OiQ&yTfiB{A9@{)~(RAZ0Ja%K>C8Zb+%6<bk07FILRr2<5mcNcJNYmeZm9G5+kUuSQi9r{WfgESW21@Ndg4mi^8+{* z5Xei><|=yB(?IfCeiCr~HE7ehUjJfEl!+qU)j7@X^=_gFhyTTd{*%UDhYHbvr@)T3 zud43Rt&wcK$is8VqFi1ECAYKbh9T$4sSkcaBKQc;wQt$YERM+k(L(RwbLWN8B4i9z zp$jMRTXu(VBNo^kaXF;U&DaZcxnd+3yi4hXOK#E7bJ^jwSt8AM(oD7)f1E{OVmHi!?PHmV*V}0LQ8QEH?%d&M{dz~6Fv8i8u{%Mb@P8Q4 z1PSvox&zU--W^K^W-5>}pJI@o+eNm}G!F50PlQ-+1RNAC0}N>vVU$)T^VS1N($X%t zjxpaQx}2l{qZLZJF&@^>$RKGm1}_Dt&w3JfHSa21m1acQG|97_r|#8S-t^K&`24wz z8gUXzzu~%TFSe5A5KiokM(lT`=@wtNwkR+h1?0oNU6K)=Ja=Y3p>|2oA!+~5m1H#2 zh+=ELDJaTg`6&W*$-PgI6pb}QhMhE#{}JG|E-Hr4e}qhD+l@5=V^QcHO=S`B0Nvf( z1QfDAR&BYQan4ShglbTyOizeA>ddho?gS3SRbtU_?$O3lFyhEQpwVi~QE&3YD8!#|jfER$Sn5 z>{IsVQZPy8q&5C#yw5x^&D{LZ0zLbxGtE(o)alMsIBGradTOjsuR$UJEl5ZjEXn-% z7qsdfiy8bGd{c)%qE%&{qbxCbsm8uy$)$s!TSq)fK*2ND_>MAz?2ViUp-*Dz$4;c6 z)|l7}Wjv%SjI0&Gf9__OZatD#W!htq;howTSFR3PIkSyO!BP0nw*ug>1kaz2QdN)S zpUb>e{7R157ODS$VgGh~(OjZ{B`94qp*j+L)vVnHd+yHy`fF#Fh{HIU({Ndl8^U>H z-eIQr0N+dHLY(1(Y?N-lI9NNgZc>>*(I$;1<*F4kppQg=vy>gIv`74BFca;6zgjuK|=B)>wa(5uX-v_ z_jgTYt*qsk+h8+}%>wT?6F%7%J)CruL&9W-Rx&ssBUv^&fsf4q302j{PXFloy(go} z;8D_?{F+Be`PGm|M?GL8OeV_7{}#&s_!*&1-uLEXiSC5o9mPODpIq7YJia6Ow70Lj zLdZ+>4!vD^vbc#u}?RpWdaotv`pc%=9hhvc{FEiv$Y!Rj!(Uh;1c8HfaI=>!t zXF^>-+)jG-PpPQ>Z`OM1lGUM+OffEL9~Xc8a98W%NQCFg(z!Mhh@SsXlK|Ey(OWiu zX1a{e@RaGi9m(t94lSw7r)gFcw#!bxYB2q8chW&NfoWYb)e+OWbn9Df62tajmhA7G zi%LQNg|bIkmI)>Yl~1$;wZES|7iT=o8UMb}5>?3x&T2w2Y6F}8rNm~ARc3eu-9c-8 z08L9pnivzs?EzM7@D_YZR&2;O(O7)5Js2WEy+WFnSQ!nrQNYi+wsw^g{gFDrW1!XC-otIWv`$6d;LSlBUC1jXcHy7 z4YeONM|_nH_-d+uP-eRWLy6L*%&=bMlXL>!(p!g`gWK}|HlT!w`v)7dJLV_5FT#@A zZ`WNpTU%r~Pl~u*@?~)U9dGi7d&3S9t_GT&pHI;j;U93QZJNPwATpgY%<*rxP?Ghg zA!AYfYykGC?4>yI!TVRVA+b9bF|rgV4W3PfLbv5PjW|5Nq9zn(2&td|aSVm0AT&jO z=hAlvmf?M$EI>`8FH`YnJNvfYjiJmJwOjoKIxbq(yCT|2Ny08WA~o)ws6V~r?kEd6ZS zdsR1{7*Y7Y-N$vbKlP?~43XZKoEtmKd&|gl78987F4}A))RjeeAI7d2s3!+Uo*t%G z5~vlBU$zFrJe>DRUv!Ci;1B>ZGKK299wCM)MQ%}eliW#a>(8~oh$uRiX{4|`6b?U^ zrII*1_{$2O%Q^XUt)nxz*;{bYocFt-jnQx>7X2-GQI4}!tTTKR6Ee;pmfyuy-Tp*& zj}q&bD^{mkD&65`0Y8TNGb=@p<7$_@O;cN$6K?uLDXFoK z*l#kPNKV?S1HS!8AD1Cy|3XUEKOkwt&d5gkBW5XCe1p@ceT)udW5+?>g}z{&;eSMo zy*rkMv2BmqA)w3oYvF@%6cBzSPF}25>6lW07N9&bA7)O<%`qXH;iSyw=*`hFcXf(q z$?-KS)n9uA6Lb(GCS-Orl%QQ1Fj}e+KF~Y%zz^yE3B}uJeD$1AtDDtSFje$v(BRC* z?i0pgR{3x^+UJTva^J@fl+?ml=y1rXhMC)c95wed^AHT&<`&PF;qJw7APhjQf58VA z@v9&`>(7*(YN=YLQJjlD<5+RB&FZ$@IlO6zmm>XBlfpq=k1g*K6>~l!Yp|wzRjdb< zbF94YzH?X7zQmQUd_=!5x>x)hzHMvKom1i$DL?uwb6DclgBq9D@Cm_yLieHesp~;; z!EHT^sC{*Pn;FrH(ckbQ1hy~9oi&_{{=4!_$m%Yw{dx39v z?nmHK=pIVAjt_UnheJrha2U3d?8ZeQm6-mtDBZ3211|=n*2*8PY(kubMLW(dl79CM zwxaqTz|m_|}`_>^?W-+0=2V#3SRw0EK!0q7HH$stjj z3n+FFw7SI%QlO&%wuMqPq8ZE9I{vkpKvI+D+4?vm-PN#~1KivXGBVzlK_eI{lX{I{ z5KeDC$q%bl-2#<>mKSMP>M!GR;oY(1{@WSUo1rWB%4}REz>$(JZK;LnC_#@;y?}r) z+eK(DJ|L$Rb~IyH1a(9&YN3%G=riSC0Sm_-XklMOy$MJEHb4jwIS+*}0#^OTHd32t zrss!MLlF19?&h|Oe(gz5<#VeI=1&xc3~cRwUBuR-7GOJwG{*YPkqbJ*82e3KsJ_gc z`Je6~b3EF_vU`S?z7vTpqf_pkP8adslJ6qr=++%zY&kq_bf5rCDMLFSNba_$~^Y7mokObU^b9$VS8GP@NKSxrTgP^QvJ;0 z)o98Mj<#n3*(PwVA1Ls0bLflAEzA9nSOd-s2^(4y#h_MvW6B2z`7!?tYC2G0g}07P+!#Wx(0{c6cv0v#zq2WpX;=hsu&GQS zN0Et`e=k#FyO8+-89H$X%E7&a%3KZ82mCKW;-9Pfz7vWn!QXG5qPr+(BL$}8vW&DaOx{EXx=VUH>zUXBZk zRrkX(y^5ObcW!zUgSuwWD_o0#PE`Og!1bYBebJclX zYE80_2kVq^16nkdf3m?Kpds|dh(8@ObO!O&KoNv~ z$W;)#s z{8`|vUYXD*_32xCXu`GckihP&Ed;W70j6^@77vGGWhTImEH%FU=q}X74GxRzw^P1$ z*_grRWz4v#TS=->=pnf0x?DBPesi_0ll8`8HQBp!^>AhgDJhF*xd83o(??N5DRTdX z0ZF;ySd6FqrPV07g`P|!n_B4xx~#_SWq7CFdSGV-^eDTJL8~=6;BF)YaqA} zSU#!wV~<*_N)L*0Byu%6^S?WKS>oB$8Z^1AM1DI3Btn{NsEUG9yZQ^(=wmCfUb*V^ zkr>3MKNhOu)_0tBTF$zO-}=VfXeez7bZ^_sK3> zlpX1O8>%#eR%%;!sxK>-9^Uyhi$(Es{+gxu@vTGbg+{iEGhRhn)|e~rV&=SU8?DCt z;2FZQ{Nq`LJWRb^gn@O_rJR$9S@Dp-!Qawo%_%q%^S1E2UGaF#bbfvYj3QU%9T%v-qHjzmZx>vHWGr=^SQskgTgOXiuALQ8SV38 z{0^fG4J6NP-wmT_6OUP|;F{4fA!zH^V)CWZNSEfD_Ci1!RgD-xAUB)bWaI=KX>R9$ z7rW}9h;tH~lpJq!EdJFQPl+2|?@y)&<4e^>C;E>h@T}Qs1nqf4WwysGK`Q=9h+a;{ z{jUtr13w{W4$`B2pN=(@4+j@UIYW8}4x4Y>eM0^Nju*$EI)7?jO4R7bfh&1*$(xL( zsTmtIIOt_FhpZjLB7LoIYRSPa>awb~4_vrS4F~QGPA=^hRiQHIugIL?gQ$@GhV5yT zlk>6r#v!??v?+cchSqV5LeQ7#tEcLz&F0fElB3Qa*P_zCHa6CKorQ-n?I?r~0VN$f zgt*hsaSkk&&h8Q|(!iSwP<{{TQ8Rx3>c6NL+pF(Ht1&G`|Ec5nQEpI0ZuO5osno_l#1$MO%{1Q)IL2EfVGR!Zggr4Xz!C~_BXM4DO9UU- z5~AbbKz`7l=z~h6u>XE{vBKHX?xZW29-f4I9=#M!WhAg|Un;UCm z=1H+)S&ZmkqOJALe$c-|b24EJ5~o)*T4XOpe(6MCwxHk-LuEd4zF*sSK2A3y8(Bo) z%Jeu|R#;-^*%w=VMXYs#CSA)#jCyVVCd3fl?H~jO&qc8r>ZN52@Zq-A^;~Bs)&&KA zW^fu9heS{qS||x2&Lw?~yU&BBoJ6&RicAcxf|Vj4r#NR6vj_r0E@2<^P7W;Zl@R5U z04|CP&$@L7Rh-DlXYPerjv2I)5JH+tHWSfC_y;dCX-JMT$~_H_{rQ8Lp}0RqfaWBs z!}^rVs_WgjZgHqVs|@0L0`cdy55T$Ku!2*I&j_Z~UcT*7FoaMpkNg<`-@MH?eFm5N za8|x#cldOh;Oaf0=#(LT@XLp}RbW_g!9nM*TwG=XR2-URMPz_8t`J1N7>teKfOXsl z8xP;SalRh!4ER)kI8(Uoq58g`5b0&*ox;J1!j+R$79v4yIBgA z!4b=oCAI9k+D9b6J9h*8B+eX#kQKF0z?XFYfB6zt@Vy)?16)u!Y8`WlrY(cA@DCL9 zFBwOT3mOjmUN;MHH}IcJjT`XB{hfvW@lVOle-2zYN3oFVA0Y(KA<02TSW4GE8BeSO zy@pUk8AlQnruw)IUs!8&y25P)h(Ocwp##EYAUN~xokB(}b%_yIo`#eL-{OZjg};@c zW&zy`wI;p$lldwA6M8X2P?;iywIWm?0_6W-4n*KoAbJn17h>Oa$#N}pxzCSivFh~D za>3%V5XcF46v^{h7Tm<)59f#GTIRz5Ts&{AK>KvXA9_u$rE_2IA7ld$716ZEl$2;u6vh4(5ESFhKD=uDB zu~qrYSkwr=9!T>Sn*X?^Ml*!`B#k1#!U?YgUbn7Aw#&#eh(Whm(ZIs1bl6{C!ui4O z(5!NOlz>L$Z}(6b)eY235c<6>^%eegl?67#YgOgK&OF%=gNV=#SL$XERgwr~vH1C^ zG)k!!1MdPeL%TYu^VmoX7`VHJMY`mR<)hjDq;X$D!7v=Hh_ob8~0SR5Pl&PAO9bi=}F6>*N0UaD#Z*e5bMO!t+kPSfl1ir6mhjO?x=u zc=Ca?yyieW4#ybff#yW zAF1+R!3jlS!%Uk`J~J5uVF_+os8o>+qN?ad5R8;l>F8D+QvoN>4^Ex7W)EI=gBR8L z+|?PLT1TJWOZj>YKF46sTjpjIFi7!Y8y zFT9&I8q-bxKw*IAVpc|5kZmmDI|3#34lvcdHT5LaqXNwgM$lWW#=3RF zOtqF_dlW5y$)=3UH4uOt0~8I`H9EfDa_s*KRI5{&ajmyAb?OMH|5{go?f}TD+5b=JWN=u_}-wCrUg0z003 zUj z3vAn%a9@4hAaFmx*@-p>Y(NlCqa6LC#t8^s@DY9l8K4OfkT9!T;JWH1Qb%5=WXFSxTCK{G~FC{@V#Vr zh%X^DWA8B{^Lm?nY`!C2ahvk%`cL9v_#kXp$1V}JPS_-!I>Ces#LR1K-qZq}Dnye7 zuTJeUR?z%pnWsk%9mt7o;a`f(fVc1g09qgVs@%;7Y-KPyUZ~x;%K7cxJ^ZcxXEr~t z_o;IZVv4TQ=XeF4gMwGZ`aLq4%2B8l<)BtKl0My30L5k!E_*GQa`xPjl5W#abm zr^g3GFGFroP&46R*!c66sB`+}llQXJO~#apU*_ZnvG5jF;;m8lI3%cl<>sQWSfyug7tnw}UhsufpkzE@5PJ4xv1^*= zUEto@c(2P;<<&5&K5b3J&tvzp1ke0$tjt{K0AP0teI?nl;~-%#O>yQF86-qwk!ap2 zpx2AC@Z}PCNR>(W@6g)To&jwacwkuL&8zDE4w2QX3V*XhtT2ifio#P2A8I{!H^@WlH3a^`n8GQB+kC(%#4VzK>b}?RCe~Zds|%L19WLupFZ; z{oI)>-f)n>S+*Oy2v7nQ#%OyLS?cv#yCTAd|9xx!8w=Qk!m}#9Eg|@*l(!c}9>d4F z0(cOkS7}S@5s&6IVDPoF_{jAoU<~&W5sQAJ1%$YEeK5URVCNAi(jCKdSi=1AXR4_A zzs+2>ihy2q#U9sQH+hBuf~VwBUw{=r#Z`$S@yCFoqYtoi5f-8|;j7SH^Hy~EY{&U` z#9qJWLBDrrI_r<>?$a4-iQDHd7<30+9L- z#60&QoPT;%RoT0bFnA{O21fel!bE!pd+UM2r&W=OeydUuo;n4Da%|mu@z+r2^u10R zH-SlC_vVWM{F^5MB1t{<5cp;zPneaVZ;vNBU0a7uW;et^TmNxHQzD>sHymPt7&YL> zP0H3hqMDqe2wGorkm>FK7Ii&BZvndrt)Cq_Hs4lHh-&=`V?(#Y)^!M=iUHPQ%!ia$ zwU((9D?D$+JUDI*B;CgfZUkdU*S7~T@tbElhQXbW>DR+vzLw4!u!G_NyH=a( z^S^k-iEyxZeMzvzAdwRpBIoh_b1fL^;$GbnT-xQ%X2?>0fy$% z9WLLhn&eFANT@#(8Uz`t0c2mp!3x>;Fkd`W13P$ z^B@$~SjnMr1<-R$iw|r85qTYdEnn??7`5Nso*7_dci(@TT2BW{;2_ityhSzve^b)< zPp;7Gy(ogu=gcMpZ+vpGnirO8*r2 zWgYgvh8<#)^J#?z6*sN>J~1184|V`FBcXr7Kizua4nq;xY(=0URAE28YZ29S~#P#UD929WMXq(Qn{ zq=p9RZV-@^5TvA=p@(izkglPmTe^M^@B5zf{lD*=|5~$L;##g@=GphY_rCVEuPe^) z_S;FZ_N(~+c7*{g)nn>tYQhKv1E!&8UJUhLya(hB$5n|VUY3541aw`UI{~#uo$)k& z=YsON&PXmHp>4See&^r8yzN&bh}`%Z*;m6>oi>K2BnFD-fF`|?RxR}=A_)a{55LQs zPt+zMueVf=gdv5QZsR-&hL`rypsQOi+O~={@ps;F-DG!Ow3;^?%Z-l)4#tKv)|SBi ziHNhjx}s95dm5S-0uT+ju2>0w84LM2_c7b&9KEf{{$zciX|6my zcqq|=$Vl zonG96!t_7~qJUFw7Z4s~N2nK8qBpaD!bE<@G`8*AIZPBz@XVSgj;p%^BKd%17WSj; zz(n#3=qMnDSM>42F4~MkQ#8FO1 z*&Km+o)<2jVOx$~ng)T@FURYEl(0J}BE+$cVujNJI3`Vdnqa=Q?Nc@2*sA_-$O6Dt z0$gx7z2QidjO5P#`$X|iJA*!H2ZV-+?v6710djXPyRzO6g6p3oxn3p51@1Fcxzb|b zo4wJ@fj940^-+}Ad4oqA;*jwoIE7{+4`<%knsAf7Eqo0>62>o?VW;$_6qR%f|Lz;- z4HTFuKt43le4t2UfPW1N6RDbrN&(!MB-?{>U zZ_RiAJni~OkcDY;G4`}1<_kG}Od2WupAnoj8P=y}*F+(0s!?69H6Yz#xAn9Ene6vFt=sgfyB^QY%);kOfGYN@ zfn>mbr}(MzxCUmz`%5(ri@|5Y4kK5Wk`zYKmD3`l{w2(X*}hE&**HtUqu%Kqv{sxJ zOyxHMthhefllOL{&_CoR$3=ndd`A)LSBgaJ(uS)4)hPXc`}8w3cr(45Cy>H?)o<=d zam-A2rAw1b%A>nfpEN8u$?pS$9UCmG__b7&46K8V#|rqm4b`WVYq!AVEo=oiNZC1X zFWOP7ie#ayu*3NKRv|!fg*v?3*zi-BC!iHtgkH~DKa+d@9#x1oQfd*@!i|3>AEN@OOBN2nvbzXpu=qmt;HX)*; z`hqM8BL9LX0_^cF;pb~zDHmz|$Qk^$AtMCpTYu(4MGFTURlQ(0(Xj zDWRMl`#tOdxV9C;1ib(}4SQ9H$8TH-Wo;fXV=D66G{cMm)c$n8U(&$!Y~XQ_2Z{LI zoEY%SH}D*m@5uVTtusn_+aFN{Hvuyz58M@a^9l>iOI6h z#R&ADhTwm#iHU*H;DW5N8Ze$uKqX>zZMe(B0~nAkGC2Yjr@I;yxR=jvo}*pye7-tQ z1PD0hVw|Ixqp!Q(a%YH#1){P6GSwIUHRJIugKJO9gPH)HOTpzUrEM?sHm|7pj$&b3 z&j=^Lwx;kf-V=0ixfVBVMycOt;|=cniNkk;t*54mIcnQC>!@C!fKF`SqMBqdUm@Qq zj{7|4Y2iBQ?=Iv8c6r#oSNd(?UCo_rC%9;Se7S+j_F+7%%dJGD7@bqTlp62%0DHzO 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
    5<|UV>bC*?caA>P4 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�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

    ZWxP#UQr(3zr;7$u(7 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 sDS0A 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

    IT}u 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ʵF4F10oWW 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
    Vq*s&onh6W;Wm(EJoxQA!IcBHlwiP#? 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 literal 0 HcmV?d00001 diff --git a/docs/session-keepalive-design.md b/docs/session-keepalive-design.md new file mode 100644 index 0000000..545fb2b --- /dev/null +++ b/docs/session-keepalive-design.md @@ -0,0 +1,239 @@ +--- +summary: "Design notes for unified provider session keepalive scheduling and refresh control." +read_when: + - Planning provider session keepalive work + - Refactoring Augment keepalive behavior + - Designing background session refresh scheduling +--- + +# Session Keepalive Enhancement Design + +**Date:** 2026-01-04 +**Feature:** Proactive session management for all providers +**Inspiration:** Quotio's "Auto-Warmup" feature + +--- + +## Problem Statement + +**Current State:** +- Augment has reactive keepalive (checks every 5min, refreshes when cookies near expiry) +- Other providers (Claude, Codex) have no automatic session management +- Users experience auth failures when sessions expire during idle periods +- Manual re-authentication is disruptive to workflow + +**Pain Points:** +1. **Session expiration during idle time** - User comes back to expired session +2. **No proactive refresh** - We only react to expiration, don't prevent it +3. **Provider-specific logic** - Each provider needs custom keepalive code +4. **No user control** - Can't configure refresh intervals or disable keepalive + +--- + +## Proposed Solution: Unified Session Keepalive System + +### Alternative Names (Better than "Warmup") +1. **Session Keepalive** ✅ (current Augment terminology) +2. **Session Refresh** (more accurate - we're refreshing, not warming) +3. **Auto-Refresh** (simple, user-friendly) +4. **Session Maintenance** (professional, clear intent) +5. **Stay Alive** (casual, friendly) + +**Recommendation:** **"Session Keepalive"** - already used in codebase, technically accurate + +--- + +## Architecture + +### 1. Core Components + +#### `SessionKeepaliveManager` (New) +```swift +@MainActor +public final class SessionKeepaliveManager { + // Unified scheduler for all providers + private var scheduledTasks: [Provider: Task] = [:] + + // Per-provider configuration + private var configs: [Provider: KeepaliveConfig] = [:] + + // Start keepalive for a provider + func start(provider: Provider, config: KeepaliveConfig) + + // Stop keepalive for a provider + func stop(provider: Provider) + + // Force immediate refresh + func forceRefresh(provider: Provider) async +} +``` + +#### `KeepaliveConfig` (New) +```swift +public struct KeepaliveConfig { + enum Mode { + case interval(TimeInterval) // Every X seconds + case daily(hour: Int, minute: Int) // Daily at specific time + case beforeExpiry(buffer: TimeInterval) // X seconds before expiry + } + + let mode: Mode + let enabled: Bool + let minRefreshInterval: TimeInterval // Rate limiting +} +``` + +### 2. Provider Integration + +#### Augment (Existing - Refactor) +- **Current:** `AugmentSessionKeepalive` (standalone actor) +- **New:** Integrate with `SessionKeepaliveManager` +- **Strategy:** `beforeExpiry(buffer: 300)` - refresh 5min before cookie expiry +- **Action:** Ping session endpoint + re-import cookies + +#### Claude (New) +- **Strategy:** `interval(1800)` - refresh every 30 minutes +- **Action:** Run `/status` command via CLI to keep session alive +- **Fallback:** OAuth token refresh if CLI unavailable + +#### Codex (New) +- **Strategy:** `interval(3600)` - refresh every hour +- **Action:** OAuth token refresh using refresh token +- **Benefit:** Prevents "session expired" errors during long coding sessions + +#### Cursor, Gemini, etc. (Future) +- **Strategy:** TBD based on provider auth mechanism +- **Extensible:** Protocol-based design allows easy addition + +--- + +## Implementation Plan + +### Phase 1: Core Infrastructure (Week 1) +1. Create `SessionKeepaliveManager` actor +2. Define `KeepaliveConfig` model +3. Add UserDefaults persistence for per-provider configs +4. Create Settings UI for keepalive configuration + +### Phase 2: Provider Integration (Week 2) +1. **Augment:** Refactor existing `AugmentSessionKeepalive` to use new manager +2. **Claude:** Implement CLI-based keepalive +3. **Codex:** Implement OAuth token refresh keepalive + +### Phase 3: UI & Polish (Week 3) +1. Settings → Providers → [Provider] → "Session Keepalive" section +2. Toggle: Enable/Disable +3. Mode picker: Interval / Daily / Before Expiry +4. Status indicator: Last refresh time, next scheduled refresh +5. Manual "Refresh Now" button + +--- + +## Settings UI Design + +``` +Settings → Providers → Augment + +┌─────────────────────────────────────────┐ +│ Session Keepalive │ +├─────────────────────────────────────────┤ +│ ☑ Keep session alive automatically │ +│ │ +│ Mode: ⦿ Before Expiry │ +│ ○ Every 30 minutes │ +│ ○ Daily at 9:00 AM │ +│ │ +│ Last refresh: 2 minutes ago │ +│ Next refresh: in 3 minutes │ +│ │ +│ [Refresh Now] │ +└─────────────────────────────────────────┘ +``` + +--- + +## Key Differences from Quotio's "Warmup" + +| Aspect | Quotio Warmup | CodexBar Keepalive | +|--------|---------------|-------------------| +| **Purpose** | Trigger 1-token API calls to reset quota counters | Refresh auth sessions to prevent expiration | +| **Target** | Antigravity only (quota reset) | All providers (session management) | +| **Action** | Make minimal API request (costs 1 token) | Refresh auth tokens/cookies (free) | +| **Benefit** | Faster quota resets during peak hours | Uninterrupted access, no auth failures | +| **Cost** | Consumes tokens | No cost (just auth refresh) | + +**Why different?** +- Quotio has a proxy server that routes requests → warmup keeps quota fresh +- CodexBar monitors providers directly → keepalive prevents auth expiration + +--- + +## Benefits + +### For Users +1. **No more "session expired" errors** during active work +2. **Seamless experience** - auth just works +3. **Configurable** - control refresh frequency per provider +4. **Transparent** - see when last refresh happened + +### For Developers +1. **Unified system** - one manager for all providers +2. **Extensible** - easy to add new providers +3. **Testable** - clear separation of concerns +4. **Maintainable** - centralized keepalive logic + +--- + +## Technical Considerations + +### Rate Limiting +- Minimum 2-minute interval between refreshes (prevent API abuse) +- Exponential backoff on failures +- Max 3 retry attempts before disabling + +### Error Handling +- Log failures but don't crash +- Notify user if keepalive fails repeatedly +- Automatic disable after 5 consecutive failures + +### Performance +- Background tasks use `.utility` priority +- No blocking of main thread +- Minimal memory footprint + +### Privacy +- No data sent to external servers +- All refresh actions are local (CLI, OAuth, cookie import) +- User can disable entirely + +--- + +## Next Steps + +1. **Review this design** - Get feedback on architecture +2. **Prototype core manager** - Build `SessionKeepaliveManager` +3. **Integrate Augment** - Refactor existing keepalive +4. **Add Claude support** - Implement CLI-based refresh +5. **Build Settings UI** - Per-provider configuration +6. **Test & iterate** - Ensure reliability + +--- + +## Open Questions + +1. **Should keepalive be enabled by default?** + - Pro: Better UX out of the box + - Con: Users might not want automatic refreshes + - **Recommendation:** Enabled by default, easy to disable + +2. **What's the default refresh interval?** + - Augment: 5min before expiry (existing) + - Claude: 30min interval + - Codex: 60min interval + - **Recommendation:** Conservative defaults, user-configurable + +3. **Should we show keepalive status in menu bar?** + - Pro: Transparency, user knows it's working + - Con: Clutters UI + - **Recommendation:** Show in Settings only, not menu bar + diff --git a/docs/sessions.md b/docs/sessions.md new file mode 100644 index 0000000..0e70787 --- /dev/null +++ b/docs/sessions.md @@ -0,0 +1,17 @@ +# Agent Sessions + +CodexBar can list live Codex and Claude Code sessions on this Mac and other Macs or Linux hosts reachable over SSH. + +Enable **Settings → General → Sessions**. Local sessions refresh every 30 seconds. Remote sessions refresh every 60 seconds and whenever the menu opens. Tailscale discovery includes online macOS and Linux peers; add extra SSH destinations as a comma-separated list, such as `user@host`. + +The menu groups local sessions first, followed by each remote host. A filled dot is active; an empty dot is idle. Select a local row to activate its terminal, editor, or desktop app. The first focus attempt can request macOS Accessibility permission so CodexBar can raise the matching window. Remote rows run the same focus command over SSH. + +The CLI exposes the same scanner: + +```console +codexbar sessions +codexbar sessions --json +codexbar sessions focus +``` + +Remote hosts need key-based, non-interactive SSH and either `codexbar` on `PATH` or CodexBar installed in `/Applications`. diff --git a/docs/site-locales.mjs b/docs/site-locales.mjs new file mode 100644 index 0000000..2619093 --- /dev/null +++ b/docs/site-locales.mjs @@ -0,0 +1,3342 @@ +export const localeCatalog = [ + { + "code": "en", + "name": "English" + }, + { + "code": "zh-CN", + "name": "简体中文" + }, + { + "code": "zh-TW", + "name": "繁體中文" + }, + { + "code": "ja-JP", + "name": "日本語" + }, + { + "code": "es", + "name": "Español" + }, + { + "code": "pt-BR", + "name": "Português (BR)" + }, + { + "code": "ko", + "name": "한국어" + }, + { + "code": "de", + "name": "Deutsch" + }, + { + "code": "fr", + "name": "Français" + }, + { + "code": "ar", + "name": "العربية", + "direction": "rtl" + }, + { + "code": "it", + "name": "Italiano" + }, + { + "code": "vi", + "name": "Tiếng Việt" + }, + { + "code": "nl", + "name": "Nederlands" + }, + { + "code": "tr", + "name": "Türkçe" + }, + { + "code": "uk", + "name": "Українська" + }, + { + "code": "ru", + "name": "Русский" + }, + { + "code": "id", + "name": "Bahasa Indonesia" + }, + { + "code": "pl", + "name": "Polski" + }, + { + "code": "fa", + "name": "فارسی", + "direction": "rtl" + }, + { + "code": "th", + "name": "ไทย" + }, + { + "code": "gl", + "name": "Galego" + }, + { + "code": "ca", + "name": "Català" + }, + { + "code": "sv", + "name": "Svenska" + } +]; + +export const localeMessages = { + "en": { + "meta.title": "CodexBar — every AI coding limit in your menu bar", + "meta.description": "A tiny macOS menu bar app that tracks AI coding-provider usage windows, credits, costs, and resets across 59 providers — Codex, OpenAI, Claude, Cursor, Gemini, Copilot, LiteLLM, and more.", + "meta.ogDescription": "Track usage windows, credits, and resets across 59 AI coding providers from your macOS menu bar.", + "nav.primary": "Primary", + "nav.language": "Language", + "nav.docs": "docs", + "nav.source": "Source", + "nav.download": "download", + "theme.toLight": "Switch to light theme", + "theme.toDark": "Switch to dark theme", + "hero.prefix": "Every AI coding limit,", + "hero.accent": "in your menu bar.", + "hero.description": "CodexBar tracks usage windows, credit balances, and reset countdowns across the providers you actually pay for — one status item each, or merge them into one.", + "hero.download": "Download for macOS", + "hero.fineprint": "Free & open source · macOS 14+ · Universal via GitHub Releases and Homebrew", + "providers.title": "59 providers,{mobileBreak}one menu bar", + "providers.description": "Popular providers become status items with their own usage windows, reset countdowns, charts, and provider menus.", + "providers.yourProvider": "Your provider", + "providers.authoringGuide": "Authoring guide", + "auth.oauth": "OAuth", + "auth.cli": "CLI", + "auth.gcloud": "gcloud", + "auth.cookies": "Cookies", + "auth.cookiesGo": "Cookies + Go", + "auth.deviceFlow": "Device flow", + "auth.bearerLocal": "Bearer / Local", + "auth.apiKey": "API key", + "auth.token": "Token", + "auth.legacyApi": "Legacy API", + "auth.local": "Local", + "auth.apiKeyCookies": "API key + Cookies", + "auth.virtualKey": "Virtual key", + "showcase.alt": "CodexBar menu bar popover showing provider tiles with usage bars, reset countdowns, and credit details.", + "features.resetsTitle": "Resets you can plan around", + "features.resetsBody": "Per-provider session, weekly, and monthly windows with countdowns to the next reset — no more guessing whether to start a long task.", + "features.spendTitle": "Credits, spend, and cost scans", + "features.spendBody": "Credit balances and monthly spend where the provider exposes them, plus configurable local cost scans for Codex and Claude.", + "features.statusTitle": "Status & incidents", + "features.statusBody": "Provider status polling surfaces incident badges in the menu and an indicator overlay on the bar icon.", + "features.cliTitle": "CLI & widgets", + "features.cliBody": "WidgetKit widgets for supported providers and a bundled {codexbar} CLI for scripts and CI — macOS and Linux builds on every release.", + "detail.installTitle": "Install & updates", + "detail.installBody": "Universal app via {releases} with Sparkle auto-updates, or via {cask} (updates via {upgrade}).", + "detail.cliTitle": "CLI", + "detail.cliBody": "A bundled {codexbar} binary plus standalone tarballs for macOS and Linux on each release. On Linux: {linuxCommand}.", + "detail.privacyTitle": "Privacy", + "detail.privacyBody": "Reuses existing provider sessions — OAuth, device flow, API keys, browser cookies, local files — so no passwords are stored. Audit notes in {issue}.", + "detail.permissionsTitle": "macOS permissions", + "detail.permissionsBody": "Full Disk Access for Safari cookies, Keychain access for cookie decryption and OAuth flows, and Files & Folders prompts when provider helpers read project directories.", + "footer.builtBy": "Built by", + "footer.changelog": "Changelog", + "clipboard.copy": "Copy to clipboard", + "clipboard.copied": "Copied", + "nav.home": "CodexBar home", + "nav.projectLinks": "Project links", + "nav.sourceGitHub": "CodexBar source on GitHub", + "nav.sourceStars": "source", + "nav.displayDownload": "Display and download", + "clipboard.copyBrew": "Copy Homebrew install command", + "hero.badgeStart": "AI usage limits", + "hero.badgeEnd": "for macOS", + "hero.descriptionShort": "Track usage windows, credit balances, and reset countdowns across the AI tools you actually pay for.", + "hero.fineprintShort": "Free & open source · macOS 14+", + "features.title": "Limits,\u00a0spend,\u00a0and status", + "mockup.openPanelAria": "CodexBar open in the macOS menu bar", + "mockup.macbookAlt": "MacBook menu bar", + "mockup.menuBarAria": "macOS menu bar status items", + "mockup.menuIconAria": "CodexBar menu bar icon", + "mockup.usagePanelAria": "Open CodexBar usage panel", + "mockup.updatedJustNow": "Updated just now", + "mockup.plus": "Plus", + "mockup.session": "Session", + "mockup.weekly": "Weekly", + "mockup.left60": "60% left", + "mockup.left73": "73% left", + "mockup.left89": "89% left", + "mockup.left98": "98% left", + "mockup.reserve2": "2% in reserve", + "mockup.reserve5": "5% in reserve", + "mockup.onPace": "On pace", + "mockup.resets2h53m": "Resets in 2h 53m", + "mockup.resets4h12m": "Resets in 4h 12m", + "mockup.resets5d4h": "Resets in 5d 4h", + "mockup.resets6d23h": "Resets in 6d 23h", + "mockup.runsOut4d21h": "Runs out in 4d 21h", + "mockup.lastsUntilReset": "Lasts until reset", + "mockup.limitResetCredits": "Limit Reset Credits", + "mockup.nextExpires28d2h": "Next expires in 28d 2h", + "mockup.nextExpires27d21h": "Next expires in 27d 21h", + "mockup.manualResetAvailable": "1 reset available", + "mockup.recentUsageAria": "Recent Codex usage", + "mockup.today": "Today", + "mockup.last31DaysCost": "Last 31 days Cost", + "mockup.last31DaysTokens": "Last 31 days tokens", + "mockup.latestTokens": "Latest tokens", + "mockup.usageChartAria": "31 day usage chart", + "mockup.topModel": "Top model: Example-1", + "mockup.estimatedLogs": "Estimated from local Codex logs for the selected acco...", + "mockup.credits": "Credits", + "mockup.zeroLeft": "0 left", + "mockup.buyCredits": "Buy credits...", + "mockup.partialDegradation": "Partial degradation", + "mockup.twoIncidents": "2 incidents", + "mockup.majorOutage": "Major outage", + "mockup.degraded": "Degraded", + "mockup.operational": "Operational", + "cli.outputPreviewAria": "CodexBar CLI output preview", + "cli.left99": "99% left", + "cli.left100": "100% left", + "cli.left79": "79% left", + "cli.left74": "74% left", + "cli.resets5h": "Resets in 5h", + "cli.resets7d": "Resets in 7d", + "cli.resets23d18h": "Resets in 23d 18h", + "cli.available1": "1 available", + "cli.nextResetCredit": "Next reset credit", + "cli.expires27d22h": "expires in 27d 22h", + "cli.account": "Account", + "cli.plan": "Plan", + "cli.total": "Total", + "cli.auto": "Auto", + "cli.titleLine2": "on CLI", + "cli.lead": "A bundled {codexbar} binary with the same usage output as the menu bar — scripts, CI, and quick terminal checks.", + "cli.note": "Standalone tarballs for macOS and Linux on every release.", + "cli.privacy": "CodexBar reuses existing provider sessions — no passwords stored on disk.", + "widgets.titleLine2": "widgets", + "widgets.lead": "WidgetKit widgets for supported providers — usage windows, reset countdowns, and spend where available. Drop them on your Home Screen and desktop.", + "widgets.note": "Small, medium, and large sizes. Switch providers without leaving the widget.", + "widgets.galleryAria": "macOS widget gallery preview", + "widgets.categoriesAria": "Widget categories", + "widgets.allWidgets": "All Widgets", + "widgets.metricCaption": "Compact widget for credits or cost.", + "widgets.historyCaption": "Usage history chart with recent totals.", + "widgets.usageCaption": "Session and weekly usage with credits and costs.", + "widgets.switcherCaption": "Usage widget with a provider switcher.", + "widgets.burndownCaption": "Remaining budget compared with an ideal steady burn rate.", + "widgets.burndownCombinedCaption": "Session and weekly burn-down charts in one tile.", + "widgets.dragToDesktop": "Drag a widget to the desktop…", + "detail.more": "More" + }, + "zh-CN": { + "meta.title": "CodexBar — 菜单栏中的每个 AI 编码限制", + "meta.description": "一个微小的 macOS 菜单栏应用程序,可跟踪 59 个提供商(Codex、OpenAI、Claude、Cursor、Gemini、Copilot、LiteLLM 等)的 AI 编码提供商使用窗口、积分、成本和重置。", + "meta.ogDescription": "从您的 macOS 菜单栏跟踪 59 个 AI 编码提供商的使用窗口、积分和重置。", + "nav.primary": "基本的", + "nav.language": "语言", + "nav.docs": "文档", + "nav.source": "来源", + "nav.download": "下载", + "theme.toLight": "切换到浅色主题", + "theme.toDark": "切换到深色主题", + "hero.prefix": "每个AI编码限制,", + "hero.accent": "在你的菜单栏中。", + "hero.description": "CodexBar 跟踪您实际付费的提供商的使用窗口、信用余额和重置倒计时 - 每个状态项一项,或将它们合并为一项。", + "hero.download": "下载macOS", + "hero.fineprint": "免费开源 · macOS 14+ · GitHub Releases 和 Homebrew 均提供通用版本", + "providers.title": "59 个提供商,{mobileBreak}一个菜单栏", + "providers.description": "受欢迎的提供商成为状态项目,具有自己的使用窗口、重置倒计时、图表和提供商菜单。", + "providers.yourProvider": "您的提供商", + "providers.authoringGuide": "创作指南", + "auth.oauth": "OAuth", + "auth.cli": "CLI", + "auth.gcloud": "gcloud", + "auth.cookies": "Cookies", + "auth.cookiesGo": "Cookies + Go", + "auth.deviceFlow": "Device flow", + "auth.bearerLocal": "Bearer / Local", + "auth.apiKey": "API key", + "auth.token": "Token", + "auth.legacyApi": "Legacy API", + "auth.local": "Local", + "auth.apiKeyCookies": "API key + Cookies", + "auth.virtualKey": "Virtual key", + "showcase.alt": "CodexBar 菜单栏弹出窗口显示提供商图块,其中包含使用栏、重置倒计时和信用详细信息。", + "features.resetsTitle": "您可以计划重置", + "features.resetsBody": "每个提供商的会话、每周和每月窗口,以及下一次重置的倒计时 - 不再猜测是否开始一项长期任务。", + "features.spendTitle": "积分、支出和成本扫描", + "features.spendBody": "提供商公开的信用余额和每月支出,以及 Codex 和 Claude 的可配置本地成本扫描。", + "features.statusTitle": "状态和事件", + "features.statusBody": "提供商状态轮询会在菜单中显示事件徽章,并在栏图标上覆盖一个指示器。", + "features.cliTitle": "CLI 和小部件", + "features.cliBody": "用于支持的提供程序的 WidgetKit 小部件以及用于脚本的捆绑 {codexbar} CLI 和 CI - macOS 和 Linux 构建在每个版本上。", + "detail.installTitle": "安装和更新", + "detail.installBody": "通过 {releases} 获取支持 Sparkle 自动更新的通用应用,或通过 {cask} 安装(使用 {upgrade} 更新)。", + "detail.cliTitle": "CLI", + "detail.cliBody": "每个版本的 {codexbar} 二进制文件以及 macOS 和 Linux 的独立 tarball。在 Linux 上:{linuxCommand}。", + "detail.privacyTitle": "隐私", + "detail.privacyBody": "重用现有的提供程序会话 - OAuth、设备流、API 密钥、浏览器 cookie、本地文件 - 因此不存储密码。 {issue} 中的审计注释。", + "detail.permissionsTitle": "macOS 权限", + "detail.permissionsBody": "Safari cookie 的完整磁盘访问权限、Cookie 解密和 OAuth 流的 Keychain 访问权限以及提供程序帮助程序读取项目目录时的文件和文件夹提示。", + "footer.builtBy": "建造者", + "footer.changelog": "变更日志", + "clipboard.copy": "复制到剪贴板", + "clipboard.copied": "已复制", + "nav.home": "CodexBar 主页", + "nav.projectLinks": "项目链接", + "nav.sourceGitHub": "CodexBar 在 GitHub 上的源码", + "nav.sourceStars": "源码", + "nav.displayDownload": "显示与下载", + "clipboard.copyBrew": "复制 Homebrew 安装命令", + "hero.badgeStart": "AI 使用限制", + "hero.badgeEnd": "适用于 macOS", + "hero.descriptionShort": "跟踪你实际付费的 AI 工具的使用窗口、积分余额和重置倒计时。", + "hero.fineprintShort": "免费开源 · macOS 14+", + "features.title": "限制、支出和状态", + "mockup.openPanelAria": "CodexBar 已在 macOS 菜单栏中打开", + "mockup.macbookAlt": "MacBook 菜单栏", + "mockup.menuBarAria": "macOS 菜单栏状态项", + "mockup.menuIconAria": "CodexBar 菜单栏图标", + "mockup.usagePanelAria": "打开 CodexBar 使用面板", + "mockup.updatedJustNow": "刚刚更新", + "mockup.plus": "Plus", + "mockup.session": "会话", + "mockup.weekly": "每周", + "mockup.left60": "剩余 60%", + "mockup.left73": "剩余 73%", + "mockup.left89": "剩余 89%", + "mockup.left98": "剩余 98%", + "mockup.reserve2": "2% 备用", + "mockup.reserve5": "5% 备用", + "mockup.onPace": "进度正常", + "mockup.resets2h53m": "2小时53分钟后重置", + "mockup.resets4h12m": "4小时12分钟后重置", + "mockup.resets5d4h": "5天4小时后重置", + "mockup.resets6d23h": "6天23小时后重置", + "mockup.runsOut4d21h": "4天21小时后用尽", + "mockup.lastsUntilReset": "持续到重置", + "mockup.limitResetCredits": "限制重置积分", + "mockup.nextExpires28d2h": "下一个将在 28天2小时后过期", + "mockup.nextExpires27d21h": "下一个将在 27天21小时后过期", + "mockup.manualResetAvailable": "1 次重置可用", + "mockup.recentUsageAria": "Codex 最近使用情况", + "mockup.today": "今天", + "mockup.last31DaysCost": "最近 31 天成本", + "mockup.last31DaysTokens": "最近 31 天 tokens", + "mockup.latestTokens": "最新 tokens", + "mockup.usageChartAria": "31 天使用图表", + "mockup.topModel": "主要模型:Example-1", + "mockup.estimatedLogs": "根据所选账号的本地 Codex 日志估算...", + "mockup.credits": "积分", + "mockup.zeroLeft": "剩余 0", + "mockup.buyCredits": "购买积分...", + "mockup.partialDegradation": "部分降级", + "mockup.twoIncidents": "2 个事件", + "mockup.majorOutage": "严重中断", + "mockup.degraded": "降级", + "mockup.operational": "正常", + "cli.outputPreviewAria": "CodexBar CLI 输出预览", + "cli.left99": "剩余 99%", + "cli.left100": "剩余 100%", + "cli.left79": "剩余 79%", + "cli.left74": "剩余 74%", + "cli.resets5h": "5小时后重置", + "cli.resets7d": "7天后重置", + "cli.resets23d18h": "23天18小时后重置", + "cli.available1": "1 个可用", + "cli.nextResetCredit": "下一个重置积分", + "cli.expires27d22h": "27天22小时后过期", + "cli.account": "账号", + "cli.plan": "套餐", + "cli.total": "总计", + "cli.auto": "自动", + "cli.titleLine2": "在 CLI 中", + "cli.lead": "内置的 {codexbar} 二进制文件提供与菜单栏相同的使用输出,适合脚本、CI 和快速终端检查。", + "cli.note": "每个版本都提供 macOS 和 Linux 的独立 tarball。", + "cli.privacy": "CodexBar 重用现有提供商会话,不在磁盘上保存密码。", + "widgets.titleLine2": "小组件", + "widgets.lead": "支持提供商的 WidgetKit 小组件:使用窗口、重置倒计时,以及可用时的支出。可放到主屏幕和桌面。", + "widgets.note": "小、中、大尺寸。无需离开小组件即可切换提供商。", + "widgets.galleryAria": "macOS 小组件图库预览", + "widgets.categoriesAria": "小组件类别", + "widgets.allWidgets": "所有小组件", + "widgets.metricCaption": "用于积分或成本的紧凑小组件。", + "widgets.historyCaption": "包含近期总计的使用历史图表。", + "widgets.usageCaption": "包含积分和成本的会话与每周使用情况。", + "widgets.switcherCaption": "带提供商切换器的使用小组件。", + "widgets.burndownCaption": "剩余预算与理想稳定消耗速度对比。", + "widgets.burndownCombinedCaption": "会话和每周消耗图表合并在一个图块中。", + "widgets.dragToDesktop": "将小组件拖到桌面…", + "detail.more": "更多" + }, + "zh-TW": { + "meta.title": "CodexBar — 功能表列中的每個 AI 編碼限制", + "meta.description": "一個微小的 macOS 功能表列應用程序,可追蹤 59 個提供者(Codex、OpenAI、Claude、Cursor、Gemini、Copilot、LiteLLM 等)的 AI 編碼提供者使用視窗、積分、成本和重設。", + "meta.ogDescription": "從您的 macOS 功能表列追蹤 59 個 AI 編碼提供者的使用視窗、積分和重設。", + "nav.primary": "基本的", + "nav.language": "語言", + "nav.docs": "文件", + "nav.source": "來源", + "nav.download": "下載", + "theme.toLight": "切換到淺色主題", + "theme.toDark": "切換到深色主題", + "hero.prefix": "每個AI編碼限制,", + "hero.accent": "在你的選單列中。", + "hero.description": "CodexBar 追蹤您實際付費的提供者的使用視窗、信用餘額和重設倒數計時 - 每個狀態項一項,或將它們合併為一項。", + "hero.download": "下載macOS", + "hero.fineprint": "免費開源 · macOS 14+ · GitHub Releases 和 Homebrew 均提供通用版本", + "providers.title": "59 個提供者,{mobileBreak}一個選單列", + "providers.description": "受歡迎的提供者成為狀態項目,具有自己的使用視窗、重置倒數計時、圖表和提供者選單。", + "providers.yourProvider": "您的提供者", + "providers.authoringGuide": "創作指南", + "auth.oauth": "OAuth", + "auth.cli": "CLI", + "auth.gcloud": "gcloud", + "auth.cookies": "Cookies", + "auth.cookiesGo": "Cookies + Go", + "auth.deviceFlow": "Device flow", + "auth.bearerLocal": "Bearer / Local", + "auth.apiKey": "API key", + "auth.token": "Token", + "auth.legacyApi": "Legacy API", + "auth.local": "Local", + "auth.apiKeyCookies": "API key + Cookies", + "auth.virtualKey": "Virtual key", + "showcase.alt": "CodexBar 功能表列彈出視窗顯示提供者圖塊,其中包含使用列、重設倒數計時和信用詳細資料。", + "features.resetsTitle": "您可以計劃重置", + "features.resetsBody": "每個提供者的會話、每周和每月窗口,以及下一次重置的倒數計時 - 不再猜測是否開始一項長期任務。", + "features.spendTitle": "積分、支出和成本掃描", + "features.spendBody": "提供者公開的信用餘額和每月支出,以及 Codex 和 Claude 的可設定本地成本掃描。", + "features.statusTitle": "狀態和事件", + "features.statusBody": "提供者狀態輪詢會在選單中顯示事件徽章,並在列圖示上覆蓋一個指示器。", + "features.cliTitle": "CLI 和小部件", + "features.cliBody": "用於支援的提供者的 WidgetKit 小部件以及用於腳本的捆綁 {codexbar} CLI 和 CI - macOS 和 Linux 建構在每個版本上。", + "detail.installTitle": "安裝和更新", + "detail.installBody": "透過 {releases} 取得支援 Sparkle 自動更新的通用應用程式,或透過 {cask} 安裝(使用 {upgrade} 更新)。", + "detail.cliTitle": "CLI", + "detail.cliBody": "每個版本的 {codexbar} 二進位檔案以及 macOS 和 Linux 的獨立 tarball。在 Linux 上:{linuxCommand}。", + "detail.privacyTitle": "隱私", + "detail.privacyBody": "重複使用現有的提供者會話 - OAuth、裝置流、API 金鑰、瀏覽器 cookie、本機檔案 - 因此不儲存密碼。 {issue} 中的審計註釋。", + "detail.permissionsTitle": "macOS 權限", + "detail.permissionsBody": "Safari cookie 的完整磁碟存取權限、Cookie 解密和 OAuth 流的 Keychain 存取權限以及提供者幫助程式讀取專案目錄時的檔案和資料夾提示。", + "footer.builtBy": "建造者", + "footer.changelog": "變更日誌", + "clipboard.copy": "複製到剪貼簿", + "clipboard.copied": "已複製", + "nav.home": "CodexBar 首頁", + "nav.projectLinks": "專案連結", + "nav.sourceGitHub": "CodexBar 在 GitHub 上的原始碼", + "nav.sourceStars": "原始碼", + "nav.displayDownload": "顯示與下載", + "clipboard.copyBrew": "複製 Homebrew 安裝指令", + "hero.badgeStart": "AI 使用限制", + "hero.badgeEnd": "適用於 macOS", + "hero.descriptionShort": "追蹤你實際付費的 AI 工具的使用視窗、點數餘額與重設倒數。", + "hero.fineprintShort": "免費且開源 · macOS 14+", + "features.title": "限制、支出與狀態", + "mockup.openPanelAria": "CodexBar 已在 macOS 選單列中開啟", + "mockup.macbookAlt": "MacBook 選單列", + "mockup.menuBarAria": "macOS 選單列狀態項目", + "mockup.menuIconAria": "CodexBar 選單列圖示", + "mockup.usagePanelAria": "開啟 CodexBar 使用面板", + "mockup.updatedJustNow": "剛剛更新", + "mockup.plus": "Plus", + "mockup.session": "工作階段", + "mockup.weekly": "每週", + "mockup.left60": "剩餘 60%", + "mockup.left73": "剩餘 73%", + "mockup.left89": "剩餘 89%", + "mockup.left98": "剩餘 98%", + "mockup.reserve2": "2% 備用", + "mockup.reserve5": "5% 備用", + "mockup.onPace": "進度正常", + "mockup.resets2h53m": "2小時53分鐘後重設", + "mockup.resets4h12m": "4小時12分鐘後重設", + "mockup.resets5d4h": "5天4小時後重設", + "mockup.resets6d23h": "6天23小時後重設", + "mockup.runsOut4d21h": "4天21小時後用完", + "mockup.lastsUntilReset": "持續到重設", + "mockup.limitResetCredits": "限制重設點數", + "mockup.nextExpires28d2h": "下一個將於 28天2小時後到期", + "mockup.nextExpires27d21h": "下一個將於 27天21小時後到期", + "mockup.manualResetAvailable": "1 次重設可用", + "mockup.recentUsageAria": "Codex 最近使用情況", + "mockup.today": "今天", + "mockup.last31DaysCost": "最近 31 天成本", + "mockup.last31DaysTokens": "最近 31 天 tokens", + "mockup.latestTokens": "最新 tokens", + "mockup.usageChartAria": "31 天使用圖表", + "mockup.topModel": "主要模型:Example-1", + "mockup.estimatedLogs": "根據所選帳號的本機 Codex 記錄估算...", + "mockup.credits": "點數", + "mockup.zeroLeft": "剩餘 0", + "mockup.buyCredits": "購買點數...", + "mockup.partialDegradation": "部分降級", + "mockup.twoIncidents": "2 個事件", + "mockup.majorOutage": "重大中斷", + "mockup.degraded": "降級", + "mockup.operational": "正常", + "cli.outputPreviewAria": "CodexBar CLI 輸出預覽", + "cli.left99": "剩餘 99%", + "cli.left100": "剩餘 100%", + "cli.left79": "剩餘 79%", + "cli.left74": "剩餘 74%", + "cli.resets5h": "5小時後重設", + "cli.resets7d": "7天後重設", + "cli.resets23d18h": "23天18小時後重設", + "cli.available1": "1 個可用", + "cli.nextResetCredit": "下一個重設點數", + "cli.expires27d22h": "27天22小時後到期", + "cli.account": "帳號", + "cli.plan": "方案", + "cli.total": "總計", + "cli.auto": "自動", + "cli.titleLine2": "在 CLI 中", + "cli.lead": "內建的 {codexbar} 二進位檔提供與選單列相同的使用輸出,適合腳本、CI 與快速終端檢查。", + "cli.note": "每個版本都提供 macOS 與 Linux 的獨立 tarball。", + "cli.privacy": "CodexBar 重用既有提供者工作階段,不在磁碟上儲存密碼。", + "widgets.titleLine2": "小工具", + "widgets.lead": "支援提供者的 WidgetKit 小工具:使用視窗、重設倒數,以及可用時的支出。可放到主畫面和桌面。", + "widgets.note": "小、中、大尺寸。不離開小工具即可切換提供者。", + "widgets.galleryAria": "macOS 小工具圖庫預覽", + "widgets.categoriesAria": "小工具類別", + "widgets.allWidgets": "所有小工具", + "widgets.metricCaption": "用於點數或成本的精簡小工具。", + "widgets.historyCaption": "包含近期總計的使用歷史圖表。", + "widgets.usageCaption": "包含點數與成本的工作階段和每週使用情況。", + "widgets.switcherCaption": "帶提供者切換器的使用小工具。", + "widgets.burndownCaption": "剩餘預算與理想穩定消耗速度對比。", + "widgets.burndownCombinedCaption": "工作階段與每週消耗圖表合併在一個圖塊中。", + "widgets.dragToDesktop": "將小工具拖到桌面…", + "detail.more": "更多" + }, + "ja-JP": { + "meta.title": "CodexBar — メニュー バーのすべての AI コーディング制限", + "meta.description": "小さな macOS メニュー バー アプリ。Codex、OpenAI、Claude、Cursor、Gemini、Copilot、LiteLLM など、59 のプロバイダーにわたる AI コーディング プロバイダーの使用期間、クレジット、コスト、リセットを追跡します。", + "meta.ogDescription": "macOS メニュー バーから、59 の AI コーディング プロバイダーにわたる使用期間、クレジット、リセットを追跡します。", + "nav.primary": "主要な", + "nav.language": "言語", + "nav.docs": "ドキュメント", + "nav.source": "ソース", + "nav.download": "ダウンロード", + "theme.toLight": "ライトテーマに切り替える", + "theme.toDark": "ダークテーマに切り替える", + "hero.prefix": "AI コーディングのあらゆる制限、", + "hero.accent": "メニューバーにあります。", + "hero.description": "CodexBar は、実際に料金を支払っているプロバイダー全体の使用期間、クレジット残高、リセット カウントダウンを追跡します。ステータス項目を 1 つずつ、または 1 つに統合します。", + "hero.download": "macOS のダウンロード", + "hero.fineprint": "無料・オープンソース · macOS 14+ · GitHub Releases と Homebrew でユニバーサル版を提供", + "providers.title": "59 プロバイダー、{mobileBreak}1つのメニューバー", + "providers.description": "人気のあるプロバイダーは、独自の使用期間、リセット カウントダウン、グラフ、プロバイダー メニューを備えたステータス アイテムになります。", + "providers.yourProvider": "あなたのプロバイダー", + "providers.authoringGuide": "オーサリングガイド", + "auth.oauth": "OAuth", + "auth.cli": "CLI", + "auth.gcloud": "gcloud", + "auth.cookies": "Cookies", + "auth.cookiesGo": "Cookies + Go", + "auth.deviceFlow": "Device flow", + "auth.bearerLocal": "Bearer / Local", + "auth.apiKey": "API key", + "auth.token": "Token", + "auth.legacyApi": "Legacy API", + "auth.local": "Local", + "auth.apiKeyCookies": "API key + Cookies", + "auth.virtualKey": "Virtual key", + "showcase.alt": "CodexBar メニュー バーのポップオーバー。使用量バー、リセット カウントダウン、クレジットの詳細を含むプロバイダー タイルが表示されます。", + "features.resetsTitle": "計画的にリセットできる", + "features.resetsBody": "プロバイダーごとのセッション、週次、月次のウィンドウに次のリセットまでのカウントダウンが表示されます。長いタスクを開始するかどうかを推測する必要はもうありません。", + "features.spendTitle": "クレジット、支出、コストのスキャン", + "features.spendBody": "プロバイダーが公開しているクレジット残高と毎月の支出に加え、Codex と Claude の構成可能なローカル コスト スキャン。", + "features.statusTitle": "ステータスとインシデント", + "features.statusBody": "プロバイダー ステータスのポーリングでは、メニューにインシデント バッジが表示され、バー アイコンにインジケーターがオーバーレイされます。", + "features.cliTitle": "CLI とウィジェット", + "features.cliBody": "サポートされているプロバイダー用の WidgetKit ウィジェットと、スクリプト用のバンドルされた {codexbar} CLI、および CI — macOS および Linux は各リリースでビルドされます。", + "detail.installTitle": "インストールとアップデート", + "detail.installBody": "Sparkle 自動更新を備えたユニバーサルアプリを {releases} から入手するか、{cask} でインストールできます({upgrade} で更新)。", + "detail.cliTitle": "CLI", + "detail.cliBody": "各リリースのバンドルされた {codexbar} バイナリと、macOS および Linux 用のスタンドアロン tarball。 Linux: {linuxCommand}。", + "detail.privacyTitle": "プライバシー", + "detail.privacyBody": "既存のプロバイダー セッション (OAuth、デバイス フロー、API キー、ブラウザー Cookie、ローカル ファイル) を再利用するため、パスワードは保存されません。 {issue} の監査メモ。", + "detail.permissionsTitle": "macOS 権限", + "detail.permissionsBody": "Safari Cookie に対するフルディスク アクセス、Cookie 復号化と OAuth フローに対する Keychain アクセス、プロバイダー ヘルパーがプロジェクト ディレクトリを読み取るときにファイルとフォルダーのプロンプトが表示されます。", + "footer.builtBy": "によって建てられました", + "footer.changelog": "変更履歴", + "clipboard.copy": "クリップボードにコピー", + "clipboard.copied": "コピーされました", + "nav.home": "CodexBar ホーム", + "nav.projectLinks": "プロジェクトリンク", + "nav.sourceGitHub": "GitHub 上の CodexBar ソース", + "nav.sourceStars": "ソース", + "nav.displayDownload": "表示とダウンロード", + "clipboard.copyBrew": "Homebrew インストールコマンドをコピー", + "hero.badgeStart": "AI 使用制限", + "hero.badgeEnd": "macOS 向け", + "hero.descriptionShort": "実際に支払っている AI ツールの使用枠、クレジット残高、リセットまでの時間を追跡します。", + "hero.fineprintShort": "無料・オープンソース · macOS 14+", + "features.title": "制限、支出、ステータス", + "mockup.openPanelAria": "macOS メニューバーで開いた CodexBar", + "mockup.macbookAlt": "MacBook メニューバー", + "mockup.menuBarAria": "macOS メニューバーのステータス項目", + "mockup.menuIconAria": "CodexBar メニューバーアイコン", + "mockup.usagePanelAria": "CodexBar 使用状況パネルを開く", + "mockup.updatedJustNow": "たった今更新", + "mockup.plus": "Plus", + "mockup.session": "セッション", + "mockup.weekly": "週間", + "mockup.left60": "残り 60%", + "mockup.left73": "残り 73%", + "mockup.left89": "残り 89%", + "mockup.left98": "残り 98%", + "mockup.reserve2": "予備 2%", + "mockup.reserve5": "予備 5%", + "mockup.onPace": "順調", + "mockup.resets2h53m": "2時間53分後にリセット", + "mockup.resets4h12m": "4時間12分後にリセット", + "mockup.resets5d4h": "5日4時間後にリセット", + "mockup.resets6d23h": "6日23時間後にリセット", + "mockup.runsOut4d21h": "4日21時間後に使い切り", + "mockup.lastsUntilReset": "リセットまで有効", + "mockup.limitResetCredits": "制限リセットクレジット", + "mockup.nextExpires28d2h": "次は 28日2時間後に期限切れ", + "mockup.nextExpires27d21h": "次は 27日21時間後に期限切れ", + "mockup.manualResetAvailable": "リセット 1 回利用可能", + "mockup.recentUsageAria": "最近の Codex 使用状況", + "mockup.today": "今日", + "mockup.last31DaysCost": "直近31日のコスト", + "mockup.last31DaysTokens": "直近31日の tokens", + "mockup.latestTokens": "最新 tokens", + "mockup.usageChartAria": "31日間の使用グラフ", + "mockup.topModel": "トップモデル: Example-1", + "mockup.estimatedLogs": "選択したアカウントのローカル Codex ログから推定...", + "mockup.credits": "クレジット", + "mockup.zeroLeft": "残り 0", + "mockup.buyCredits": "クレジットを購入...", + "mockup.partialDegradation": "一部劣化", + "mockup.twoIncidents": "2 件のインシデント", + "mockup.majorOutage": "重大障害", + "mockup.degraded": "劣化", + "mockup.operational": "正常", + "cli.outputPreviewAria": "CodexBar CLI 出力プレビュー", + "cli.left99": "残り 99%", + "cli.left100": "残り 100%", + "cli.left79": "残り 79%", + "cli.left74": "残り 74%", + "cli.resets5h": "5時間後にリセット", + "cli.resets7d": "7日後にリセット", + "cli.resets23d18h": "23日18時間後にリセット", + "cli.available1": "1 件利用可能", + "cli.nextResetCredit": "次のリセットクレジット", + "cli.expires27d22h": "27日22時間後に期限切れ", + "cli.account": "アカウント", + "cli.plan": "プラン", + "cli.total": "合計", + "cli.auto": "自動", + "cli.titleLine2": "CLI で", + "cli.lead": "同梱の {codexbar} バイナリで、メニューバーと同じ使用状況出力をスクリプト、CI、端末での簡易チェックに使えます。", + "cli.note": "各リリースで macOS と Linux 向けの単体 tarball を提供します。", + "cli.privacy": "CodexBar は既存のプロバイダーセッションを再利用し、パスワードをディスクに保存しません。", + "widgets.titleLine2": "ウィジェット", + "widgets.lead": "対応プロバイダー向けの WidgetKit ウィジェット。使用枠、リセットまでの時間、利用可能な支出をホーム画面やデスクトップに配置できます。", + "widgets.note": "小・中・大サイズ。ウィジェットを離れずにプロバイダーを切り替えられます。", + "widgets.galleryAria": "macOS ウィジェットギャラリープレビュー", + "widgets.categoriesAria": "ウィジェットカテゴリ", + "widgets.allWidgets": "すべてのウィジェット", + "widgets.metricCaption": "クレジットまたはコスト用のコンパクトウィジェット。", + "widgets.historyCaption": "最近の合計付き使用履歴グラフ。", + "widgets.usageCaption": "クレジットとコスト付きのセッションおよび週間使用状況。", + "widgets.switcherCaption": "プロバイダー切り替え付き使用状況ウィジェット。", + "widgets.burndownCaption": "残り予算を理想的な一定消費ペースと比較。", + "widgets.burndownCombinedCaption": "セッションと週間のバーンダウンを1つのタイルに表示。", + "widgets.dragToDesktop": "ウィジェットをデスクトップへドラッグ…", + "detail.more": "その他" + }, + "es": { + "meta.title": "CodexBar: cada límite de codificación de IA en tu barra de menú", + "meta.description": "Una pequeña aplicación de barra de menú macOS que rastrea las ventanas de uso, los créditos, los costos y los restablecimientos de los proveedores de codificación de IA en 59 proveedores: Codex, OpenAI, Claude, Cursor, Gemini, Copilot, LiteLLM y más.", + "meta.ogDescription": "Realice un seguimiento de las ventanas de uso, los créditos y los restablecimientos en 59 proveedores de codificación de IA desde su barra de menú macOS.", + "nav.primary": "Primario", + "nav.language": "Idioma", + "nav.docs": "Documentos", + "nav.source": "Fuente", + "nav.download": "Descargar", + "theme.toLight": "Cambiar al tema claro", + "theme.toDark": "Cambiar al tema oscuro", + "hero.prefix": "Cada límite de codificación de IA,", + "hero.accent": "en su barra de menú.", + "hero.description": "CodexBar realiza un seguimiento de los períodos de uso, los saldos de crédito y restablece las cuentas regresivas de los proveedores por los que realmente paga: un elemento de estado para cada uno o los fusiona en uno solo.", + "hero.download": "Descargar para macOS", + "hero.fineprint": "Gratis y de código abierto · macOS 14+ · Universal mediante GitHub Releases y Homebrew", + "providers.title": "59 proveedores,{mobileBreak}una barra de menús", + "providers.description": "Los proveedores populares se convierten en elementos de estado con sus propias ventanas de uso, restablecen cuentas regresivas, gráficos y menús de proveedores.", + "providers.yourProvider": "Tu proveedor", + "providers.authoringGuide": "guía de autoría", + "auth.oauth": "OAuth", + "auth.cli": "CLI", + "auth.gcloud": "gcloud", + "auth.cookies": "Cookies", + "auth.cookiesGo": "Cookies + Go", + "auth.deviceFlow": "Device flow", + "auth.bearerLocal": "Bearer / Local", + "auth.apiKey": "API key", + "auth.token": "Token", + "auth.legacyApi": "Legacy API", + "auth.local": "Local", + "auth.apiKeyCookies": "API key + Cookies", + "auth.virtualKey": "Virtual key", + "showcase.alt": "Ventana emergente de la barra de menú CodexBar que muestra mosaicos de proveedores con barras de uso, restablecimiento de cuentas regresivas y detalles de crédito.", + "features.resetsTitle": "Restablecimientos que puedes planificar", + "features.resetsBody": "Sesión por proveedor, períodos semanales y mensuales con cuentas regresivas para el siguiente reinicio: ya no tendrá que adivinar si iniciar una tarea larga.", + "features.spendTitle": "Escaneos de créditos, gastos y costos", + "features.spendBody": "Saldos de crédito y gastos mensuales donde el proveedor los expone, además de escaneos de costos locales configurables para Codex y Claude.", + "features.statusTitle": "Estado e incidencias", + "features.statusBody": "El sondeo del estado del proveedor muestra insignias de incidentes en el menú y un indicador superpuesto en el ícono de la barra.", + "features.cliTitle": "CLI y widgets", + "features.cliBody": "Widgets WidgetKit para proveedores compatibles y {codexbar} CLI incluido para scripts y CI: macOS y Linux compilaciones en cada versión.", + "detail.installTitle": "Instalar y actualizar", + "detail.installBody": "Aplicación universal mediante {releases} con actualizaciones automáticas de Sparkle, o mediante {cask} (actualizaciones con {upgrade}).", + "detail.cliTitle": "CLI", + "detail.cliBody": "Un paquete binario {codexbar} más archivos comprimidos independientes para macOS y Linux en cada versión. En Linux: {linuxCommand}.", + "detail.privacyTitle": "Privacidad", + "detail.privacyBody": "Reutiliza sesiones de proveedores existentes (OAuth, flujo de dispositivos, claves API, cookies del navegador, archivos locales) para que no se almacenen contraseñas. Notas de auditoría en {issue}.", + "detail.permissionsTitle": "permisos macOS", + "detail.permissionsBody": "Acceso total al disco para cookies Safari, acceso Keychain para descifrado de cookies y flujos OAuth, y avisos de Archivos y carpetas cuando los ayudantes del proveedor leen los directorios del proyecto.", + "footer.builtBy": "Construido por", + "footer.changelog": "Registro de cambios", + "clipboard.copy": "Copiar al portapapeles", + "clipboard.copied": "Copiado", + "nav.home": "Inicio de CodexBar", + "nav.projectLinks": "Enlaces del proyecto", + "nav.sourceGitHub": "Código de CodexBar en GitHub", + "nav.sourceStars": "código", + "nav.displayDownload": "Pantalla y descarga", + "clipboard.copyBrew": "Copiar comando de instalación de Homebrew", + "hero.badgeStart": "Límites de uso de IA", + "hero.badgeEnd": "para macOS", + "hero.descriptionShort": "Sigue ventanas de uso, saldos de créditos y cuentas regresivas de reinicio en las herramientas de IA por las que realmente pagas.", + "hero.fineprintShort": "Gratis y open source · macOS 14+", + "features.title": "Límites,\u00a0gasto y estado", + "mockup.openPanelAria": "CodexBar abierto en la barra de menús de macOS", + "mockup.macbookAlt": "Barra de menús de MacBook", + "mockup.menuBarAria": "Elementos de estado de la barra de menús de macOS", + "mockup.menuIconAria": "Icono de CodexBar en la barra de menús", + "mockup.usagePanelAria": "Panel de uso abierto de CodexBar", + "mockup.updatedJustNow": "Actualizado ahora", + "mockup.plus": "Plus", + "mockup.session": "Sesión", + "mockup.weekly": "Semanal", + "mockup.left60": "60% restante", + "mockup.left73": "73% restante", + "mockup.left89": "89% restante", + "mockup.left98": "98% restante", + "mockup.reserve2": "2% en reserva", + "mockup.reserve5": "5% en reserva", + "mockup.onPace": "A buen ritmo", + "mockup.resets2h53m": "Se reinicia en 2 h 53 min", + "mockup.resets4h12m": "Se reinicia en 4 h 12 min", + "mockup.resets5d4h": "Se reinicia en 5 d 4 h", + "mockup.resets6d23h": "Se reinicia en 6 d 23 h", + "mockup.runsOut4d21h": "Se agota en 4 d 21 h", + "mockup.lastsUntilReset": "Dura hasta el reinicio", + "mockup.limitResetCredits": "Créditos de reinicio de límite", + "mockup.nextExpires28d2h": "El próximo vence en 28 d 2 h", + "mockup.nextExpires27d21h": "El próximo vence en 27 d 21 h", + "mockup.manualResetAvailable": "1 reinicio disponible", + "mockup.recentUsageAria": "Uso reciente de Codex", + "mockup.today": "Hoy", + "mockup.last31DaysCost": "Costo de los últimos 31 días", + "mockup.last31DaysTokens": "Tokens de los últimos 31 días", + "mockup.latestTokens": "Tokens más recientes", + "mockup.usageChartAria": "Gráfico de uso de 31 días", + "mockup.topModel": "Modelo principal: Example-1", + "mockup.estimatedLogs": "Estimado desde los logs locales de Codex para la cuenta selec...", + "mockup.credits": "Créditos", + "mockup.zeroLeft": "0 restantes", + "mockup.buyCredits": "Comprar créditos...", + "mockup.partialDegradation": "Degradación parcial", + "mockup.twoIncidents": "2 incidentes", + "mockup.majorOutage": "Interrupción grave", + "mockup.degraded": "Degradado", + "mockup.operational": "Operativo", + "cli.outputPreviewAria": "Vista previa de salida del CLI de CodexBar", + "cli.left99": "99% restante", + "cli.left100": "100% restante", + "cli.left79": "79% restante", + "cli.left74": "74% restante", + "cli.resets5h": "Se reinicia en 5 h", + "cli.resets7d": "Se reinicia en 7 d", + "cli.resets23d18h": "Se reinicia en 23 d 18 h", + "cli.available1": "1 disponible", + "cli.nextResetCredit": "Próximo crédito de reinicio", + "cli.expires27d22h": "vence en 27 d 22 h", + "cli.account": "Cuenta", + "cli.plan": "Plan", + "cli.total": "Total", + "cli.auto": "Auto", + "cli.titleLine2": "en CLI", + "cli.lead": "Un binario {codexbar} incluido con la misma salida de uso que la barra de menús: scripts, CI y comprobaciones rápidas de terminal.", + "cli.note": "Tarballs independientes para macOS y Linux en cada versión.", + "cli.privacy": "CodexBar reutiliza sesiones existentes de proveedores; no guarda contraseñas en disco.", + "widgets.titleLine2": "widgets", + "widgets.lead": "Widgets de WidgetKit para proveedores compatibles: ventanas de uso, cuentas regresivas de reinicio y gasto cuando esté disponible. Ponlos en la pantalla de inicio y en el escritorio.", + "widgets.note": "Tamaños pequeño, mediano y grande. Cambia de proveedor sin salir del widget.", + "widgets.galleryAria": "Vista previa de la galería de widgets de macOS", + "widgets.categoriesAria": "Categorías de widgets", + "widgets.allWidgets": "Todos los widgets", + "widgets.metricCaption": "Widget compacto para créditos o costo.", + "widgets.historyCaption": "Gráfico de historial de uso con totales recientes.", + "widgets.usageCaption": "Uso de sesión y semanal con créditos y costos.", + "widgets.switcherCaption": "Widget de uso con selector de proveedor.", + "widgets.burndownCaption": "Presupuesto restante comparado con un ritmo ideal constante.", + "widgets.burndownCombinedCaption": "Gráficos de consumo de sesión y semana en un solo bloque.", + "widgets.dragToDesktop": "Arrastra un widget al escritorio…", + "detail.more": "Más" + }, + "pt-BR": { + "meta.title": "CodexBar — todos os limites de codificação de IA na sua barra de menu", + "meta.description": "Um pequeno aplicativo de barra de menu macOS que rastreia janelas de uso, créditos, custos e redefinições do provedor de codificação de IA em 59 provedores — Codex, OpenAI, Claude, Cursor, Gemini, Copilot, LiteLLM e muito mais.", + "meta.ogDescription": "Rastreie janelas de uso, créditos e redefinições em 59 provedores de codificação de IA na barra de menu macOS.", + "nav.primary": "Primário", + "nav.language": "Linguagem", + "nav.docs": "Documentos", + "nav.source": "Fonte", + "nav.download": "download", + "theme.toLight": "Mudar para tema claro", + "theme.toDark": "Mudar para tema escuro", + "hero.prefix": "Cada limite de codificação de IA,", + "hero.accent": "na sua barra de menu.", + "hero.description": "CodexBar rastreia janelas de uso, saldos de crédito e reinicia contagens regressivas nos provedores pelos quais você realmente paga - um item de status cada, ou mescla-os em um.", + "hero.download": "Baixar para macOS", + "hero.fineprint": "Gratuito e de código aberto · macOS 14+ · Universal via GitHub Releases e Homebrew", + "providers.title": "59 provedores,{mobileBreak}uma barra de menu", + "providers.description": "Provedores populares tornam-se itens de status com suas próprias janelas de uso, reiniciam contagens regressivas, gráficos e menus de provedores.", + "providers.yourProvider": "Seu provedor", + "providers.authoringGuide": "Guia de autoria", + "auth.oauth": "OAuth", + "auth.cli": "CLI", + "auth.gcloud": "gcloud", + "auth.cookies": "Cookies", + "auth.cookiesGo": "Cookies + Go", + "auth.deviceFlow": "Device flow", + "auth.bearerLocal": "Bearer / Local", + "auth.apiKey": "API key", + "auth.token": "Token", + "auth.legacyApi": "Legacy API", + "auth.local": "Local", + "auth.apiKeyCookies": "API key + Cookies", + "auth.virtualKey": "Virtual key", + "showcase.alt": "Popover da barra de menu CodexBar mostrando blocos de provedores com barras de uso, contagens regressivas de redefinição e detalhes de crédito.", + "features.resetsTitle": "Redefinições que você pode planejar", + "features.resetsBody": "Sessão por provedor, janelas semanais e mensais com contagem regressiva para a próxima redefinição — chega de ficar adivinhando se deve iniciar uma tarefa longa.", + "features.spendTitle": "Créditos, gastos e verificações de custos", + "features.spendBody": "Saldos de crédito e gastos mensais onde o provedor os expõe, além de verificações de custos locais configuráveis ​​para Codex e Claude.", + "features.statusTitle": "Status e incidentes", + "features.statusBody": "A pesquisa de status do provedor apresenta emblemas de incidentes no menu e uma sobreposição de indicador no ícone da barra.", + "features.cliTitle": "CLI e widgets", + "features.cliBody": "Widgets WidgetKit para provedores suportados e um pacote {codexbar} CLI para scripts e compilações CI — macOS e Linux em cada versão.", + "detail.installTitle": "Instalar e atualizações", + "detail.installBody": "Aplicativo universal via {releases} com atualizações automáticas do Sparkle ou via {cask} (atualizações com {upgrade}).", + "detail.cliTitle": "CLI", + "detail.cliBody": "Um pacote binário {codexbar} mais tarballs independentes para macOS e Linux em cada versão. Em Linux: {linuxCommand}.", + "detail.privacyTitle": "Privacidade", + "detail.privacyBody": "Reutiliza sessões existentes do provedor — OAuth, fluxo do dispositivo, chaves API, cookies do navegador, arquivos locais — para que nenhuma senha seja armazenada. Notas de auditoria em {issue}.", + "detail.permissionsTitle": "macOS permissões", + "detail.permissionsBody": "Acesso total ao disco para cookies Safari, acesso Keychain para descriptografia de cookies e fluxos OAuth e prompts de arquivos e pastas quando ajudantes do provedor leem diretórios de projetos.", + "footer.builtBy": "Construído por", + "footer.changelog": "Registro de alterações", + "clipboard.copy": "Copiar para a área de transferência", + "clipboard.copied": "Copiado", + "nav.home": "Início do CodexBar", + "nav.projectLinks": "Links do projeto", + "nav.sourceGitHub": "Código do CodexBar no GitHub", + "nav.sourceStars": "código", + "nav.displayDownload": "Exibição e download", + "clipboard.copyBrew": "Copiar comando de instalação do Homebrew", + "hero.badgeStart": "Limites de uso de IA", + "hero.badgeEnd": "para macOS", + "hero.descriptionShort": "Acompanhe janelas de uso, saldos de créditos e contagens regressivas de reset nos apps de IA que você realmente paga.", + "hero.fineprintShort": "Grátis e open source · macOS 14+", + "features.title": "Limites,\u00a0gastos e status", + "mockup.openPanelAria": "CodexBar aberto na barra de menu do macOS", + "mockup.macbookAlt": "Barra de menu do MacBook", + "mockup.menuBarAria": "Itens de status da barra de menu do macOS", + "mockup.menuIconAria": "Ícone do CodexBar na barra de menu", + "mockup.usagePanelAria": "Painel de uso aberto do CodexBar", + "mockup.updatedJustNow": "Atualizado agora", + "mockup.plus": "Plus", + "mockup.session": "Sessão", + "mockup.weekly": "Semanal", + "mockup.left60": "60% restante", + "mockup.left73": "73% restante", + "mockup.left89": "89% restante", + "mockup.left98": "98% restante", + "mockup.reserve2": "2% em reserva", + "mockup.reserve5": "5% em reserva", + "mockup.onPace": "No ritmo", + "mockup.resets2h53m": "Reseta em 2h 53m", + "mockup.resets4h12m": "Reseta em 4h 12m", + "mockup.resets5d4h": "Reseta em 5d 4h", + "mockup.resets6d23h": "Reseta em 6d 23h", + "mockup.runsOut4d21h": "Acaba em 4d 21h", + "mockup.lastsUntilReset": "Dura até o reset", + "mockup.limitResetCredits": "Créditos de reset de limite", + "mockup.nextExpires28d2h": "Próximo expira em 28d 2h", + "mockup.nextExpires27d21h": "Próximo expira em 27d 21h", + "mockup.manualResetAvailable": "1 reset disponível", + "mockup.recentUsageAria": "Uso recente do Codex", + "mockup.today": "Hoje", + "mockup.last31DaysCost": "Custo dos últimos 31 dias", + "mockup.last31DaysTokens": "Tokens dos últimos 31 dias", + "mockup.latestTokens": "Tokens mais recentes", + "mockup.usageChartAria": "Gráfico de uso de 31 dias", + "mockup.topModel": "Modelo principal: Example-1", + "mockup.estimatedLogs": "Estimado a partir dos logs locais do Codex para a conta selec...", + "mockup.credits": "Créditos", + "mockup.zeroLeft": "0 restante", + "mockup.buyCredits": "Comprar créditos...", + "mockup.partialDegradation": "Degradação parcial", + "mockup.twoIncidents": "2 incidentes", + "mockup.majorOutage": "Interrupção grave", + "mockup.degraded": "Degradado", + "mockup.operational": "Operacional", + "cli.outputPreviewAria": "Prévia da saída do CLI do CodexBar", + "cli.left99": "99% restante", + "cli.left100": "100% restante", + "cli.left79": "79% restante", + "cli.left74": "74% restante", + "cli.resets5h": "Reseta em 5h", + "cli.resets7d": "Reseta em 7d", + "cli.resets23d18h": "Reseta em 23d 18h", + "cli.available1": "1 disponível", + "cli.nextResetCredit": "Próximo crédito de reset", + "cli.expires27d22h": "expira em 27d 22h", + "cli.account": "Conta", + "cli.plan": "Plano", + "cli.total": "Total", + "cli.auto": "Auto", + "cli.titleLine2": "no CLI", + "cli.lead": "Um binário {codexbar} incluído com a mesma saída de uso da barra de menu — scripts, CI e checagens rápidas no terminal.", + "cli.note": "Tarballs independentes para macOS e Linux em toda release.", + "cli.privacy": "CodexBar reutiliza sessões existentes dos provedores — nenhuma senha fica salva no disco.", + "widgets.titleLine2": "widgets", + "widgets.lead": "Widgets do WidgetKit para provedores compatíveis — janelas de uso, contagens regressivas de reset e gastos quando disponíveis. Coloque na Tela de Início e na mesa.", + "widgets.note": "Tamanhos pequeno, médio e grande. Troque de provedor sem sair do widget.", + "widgets.galleryAria": "Prévia da galeria de widgets do macOS", + "widgets.categoriesAria": "Categorias de widgets", + "widgets.allWidgets": "Todos os widgets", + "widgets.metricCaption": "Widget compacto para créditos ou custo.", + "widgets.historyCaption": "Gráfico de histórico de uso com totais recentes.", + "widgets.usageCaption": "Uso de sessão e semanal com créditos e custos.", + "widgets.switcherCaption": "Widget de uso com seletor de provedor.", + "widgets.burndownCaption": "Orçamento restante comparado a um ritmo ideal constante.", + "widgets.burndownCombinedCaption": "Gráficos de burndown da sessão e da semana em um só tile.", + "widgets.dragToDesktop": "Arraste um widget para a mesa…", + "detail.more": "Mais" + }, + "ko": { + "meta.title": "CodexBar — 메뉴 표시줄의 모든 AI 코딩 제한", + "meta.description": "Codex, OpenAI, Claude, Cursor, Gemini, Copilot, LiteLLM 등 59개 제공자 전체에서 AI 코딩 제공자 사용 창, 크레딧, 비용 및 재설정을 추적하는 작은 macOS 메뉴 표시줄 앱입니다.", + "meta.ogDescription": "macOS 메뉴 표시줄에서 59개 AI 코딩 제공업체의 사용 기간, 크레딧 및 재설정을 추적하세요.", + "nav.primary": "주요한", + "nav.language": "언어", + "nav.docs": "문서", + "nav.source": "원천", + "nav.download": "다운로드", + "theme.toLight": "밝은 테마로 전환", + "theme.toDark": "어두운 테마로 전환", + "hero.prefix": "모든 AI 코딩의 한계,", + "hero.accent": "메뉴 표시줄에", + "hero.description": "CodexBar는 귀하가 실제로 비용을 지불한 제공업체 전반에 걸쳐 사용 기간, 크레딧 잔액 및 재설정 카운트다운을 추적합니다. 즉, 각각 하나의 상태 항목 또는 하나로 병합됩니다.", + "hero.download": "macOS 동안 다운로드", + "hero.fineprint": "무료 오픈 소스 · macOS 14+ · GitHub Releases와 Homebrew에서 유니버설 제공", + "providers.title": "59개 제공자,{mobileBreak}하나의 메뉴 막대", + "providers.description": "인기 있는 제공업체는 자체 사용 창, 재설정 카운트다운, 차트 및 제공업체 메뉴를 갖춘 상태 항목이 됩니다.", + "providers.yourProvider": "귀하의 제공자", + "providers.authoringGuide": "저작 가이드", + "auth.oauth": "OAuth", + "auth.cli": "CLI", + "auth.gcloud": "gcloud", + "auth.cookies": "Cookies", + "auth.cookiesGo": "Cookies + Go", + "auth.deviceFlow": "Device flow", + "auth.bearerLocal": "Bearer / Local", + "auth.apiKey": "API key", + "auth.token": "Token", + "auth.legacyApi": "Legacy API", + "auth.local": "Local", + "auth.apiKeyCookies": "API key + Cookies", + "auth.virtualKey": "Virtual key", + "showcase.alt": "CodexBar 사용량 표시줄, 재설정 카운트다운 및 신용 세부정보가 포함된 제공업체 타일을 표시하는 메뉴 표시줄 팝오버입니다.", + "features.resetsTitle": "계획할 수 있는 재설정", + "features.resetsBody": "다음 재설정까지 카운트다운이 가능한 공급자별 세션, 주간 및 월간 기간으로 더 이상 긴 작업을 시작할지 여부를 추측할 필요가 없습니다.", + "features.spendTitle": "크레딧, 지출, 비용 스캔", + "features.spendBody": "공급자가 노출하는 신용 ​​잔액 및 월별 지출과 Codex 및 Claude에 대한 구성 가능한 지역 비용 스캔.", + "features.statusTitle": "현황 및 사건", + "features.statusBody": "공급자 상태 폴링은 메뉴에 사건 배지를 표시하고 막대 아이콘에 표시기 오버레이를 표시합니다.", + "features.cliTitle": "CLI 및 위젯", + "features.cliBody": "지원되는 공급자를 위한 WidgetKit 위젯과 스크립트 및 CI용 번들 {codexbar} CLI — macOS 및 Linux는 모든 릴리스에서 빌드됩니다.", + "detail.installTitle": "설치 및 업데이트", + "detail.installBody": "Sparkle 자동 업데이트가 포함된 유니버설 앱은 {releases}에서, 또는 {cask}로 설치할 수 있습니다({upgrade}로 업데이트).", + "detail.cliTitle": "CLI", + "detail.cliBody": "각 릴리스의 macOS 및 Linux에 대한 번들 {codexbar} 바이너리와 독립 실행형 tarball입니다. Linux에: {linuxCommand}.", + "detail.privacyTitle": "은둔", + "detail.privacyBody": "기존 공급자 세션(OAuth, 장치 흐름, API 키, 브라우저 쿠키, 로컬 파일)을 재사용하므로 비밀번호가 저장되지 않습니다. {issue}의 감사 메모입니다.", + "detail.permissionsTitle": "macOS 권한", + "detail.permissionsBody": "Safari 쿠키에 대한 전체 디스크 액세스, 쿠키 암호 해독 및 OAuth 흐름에 대한 Keychain 액세스, 공급자 도우미가 프로젝트 디렉터리를 읽을 때 파일 및 폴더 메시지가 표시됩니다.", + "footer.builtBy": "제작사", + "footer.changelog": "변경 내역", + "clipboard.copy": "클립보드에 복사", + "clipboard.copied": "복사됨", + "nav.home": "CodexBar 홈", + "nav.projectLinks": "프로젝트 링크", + "nav.sourceGitHub": "GitHub의 CodexBar 소스", + "nav.sourceStars": "소스", + "nav.displayDownload": "표시 및 다운로드", + "clipboard.copyBrew": "Homebrew 설치 명령 복사", + "hero.badgeStart": "AI 사용 한도", + "hero.badgeEnd": "macOS용", + "hero.descriptionShort": "실제로 결제하는 AI 도구의 사용 창, 크레딧 잔액, 리셋 카운트다운을 추적합니다.", + "hero.fineprintShort": "무료 오픈 소스 · macOS 14+", + "features.title": "한도,\u00a0지출,\u00a0상태", + "mockup.openPanelAria": "macOS 메뉴 막대에 열린 CodexBar", + "mockup.macbookAlt": "MacBook 메뉴 막대", + "mockup.menuBarAria": "macOS 메뉴 막대 상태 항목", + "mockup.menuIconAria": "CodexBar 메뉴 막대 아이콘", + "mockup.usagePanelAria": "CodexBar 사용 패널 열기", + "mockup.updatedJustNow": "방금 업데이트됨", + "mockup.plus": "Plus", + "mockup.session": "세션", + "mockup.weekly": "주간", + "mockup.left60": "60% 남음", + "mockup.left73": "73% 남음", + "mockup.left89": "89% 남음", + "mockup.left98": "98% 남음", + "mockup.reserve2": "2% 예비", + "mockup.reserve5": "5% 예비", + "mockup.onPace": "정상 속도", + "mockup.resets2h53m": "2시간 53분 후 리셋", + "mockup.resets4h12m": "4시간 12분 후 리셋", + "mockup.resets5d4h": "5일 4시간 후 리셋", + "mockup.resets6d23h": "6일 23시간 후 리셋", + "mockup.runsOut4d21h": "4일 21시간 후 소진", + "mockup.lastsUntilReset": "리셋까지 유지", + "mockup.limitResetCredits": "한도 리셋 크레딧", + "mockup.nextExpires28d2h": "다음 만료까지 28일 2시간", + "mockup.nextExpires27d21h": "다음 만료까지 27일 21시간", + "mockup.manualResetAvailable": "리셋 1개 사용 가능", + "mockup.recentUsageAria": "최근 Codex 사용량", + "mockup.today": "오늘", + "mockup.last31DaysCost": "최근 31일 비용", + "mockup.last31DaysTokens": "최근 31일 tokens", + "mockup.latestTokens": "최신 tokens", + "mockup.usageChartAria": "31일 사용량 차트", + "mockup.topModel": "상위 모델: Example-1", + "mockup.estimatedLogs": "선택한 계정의 로컬 Codex 로그에서 추정...", + "mockup.credits": "크레딧", + "mockup.zeroLeft": "0 남음", + "mockup.buyCredits": "크레딧 구매...", + "mockup.partialDegradation": "부분 성능 저하", + "mockup.twoIncidents": "인시던트 2개", + "mockup.majorOutage": "중대 장애", + "mockup.degraded": "저하됨", + "mockup.operational": "정상", + "cli.outputPreviewAria": "CodexBar CLI 출력 미리보기", + "cli.left99": "99% 남음", + "cli.left100": "100% 남음", + "cli.left79": "79% 남음", + "cli.left74": "74% 남음", + "cli.resets5h": "5시간 후 리셋", + "cli.resets7d": "7일 후 리셋", + "cli.resets23d18h": "23일 18시간 후 리셋", + "cli.available1": "1개 사용 가능", + "cli.nextResetCredit": "다음 리셋 크레딧", + "cli.expires27d22h": "27일 22시간 후 만료", + "cli.account": "계정", + "cli.plan": "플랜", + "cli.total": "합계", + "cli.auto": "자동", + "cli.titleLine2": "CLI에서", + "cli.lead": "번들 {codexbar} 바이너리로 메뉴 막대와 같은 사용량 출력을 스크립트, CI, 빠른 터미널 확인에 사용할 수 있습니다.", + "cli.note": "매 릴리스마다 macOS 및 Linux용 독립 tarball을 제공합니다.", + "cli.privacy": "CodexBar는 기존 제공자 세션을 재사용하며 비밀번호를 디스크에 저장하지 않습니다.", + "widgets.titleLine2": "위젯", + "widgets.lead": "지원 제공자를 위한 WidgetKit 위젯: 사용 창, 리셋 카운트다운, 가능한 경우 지출을 홈 화면과 데스크톱에 배치합니다.", + "widgets.note": "작음, 중간, 큼 크기. 위젯을 떠나지 않고 제공자를 전환합니다.", + "widgets.galleryAria": "macOS 위젯 갤러리 미리보기", + "widgets.categoriesAria": "위젯 카테고리", + "widgets.allWidgets": "모든 위젯", + "widgets.metricCaption": "크레딧 또는 비용용 컴팩트 위젯.", + "widgets.historyCaption": "최근 합계가 있는 사용 기록 차트.", + "widgets.usageCaption": "크레딧과 비용이 포함된 세션 및 주간 사용량.", + "widgets.switcherCaption": "제공자 전환기가 있는 사용량 위젯.", + "widgets.burndownCaption": "남은 예산을 이상적인 일정 소모 속도와 비교.", + "widgets.burndownCombinedCaption": "세션 및 주간 번다운 차트를 하나의 타일에 표시.", + "widgets.dragToDesktop": "위젯을 데스크톱으로 드래그…", + "detail.more": "더 보기" + }, + "de": { + "meta.title": "CodexBar – alle Limits Ihrer KI-Coding-Tools in der Menüleiste", + "meta.description": "Eine kleine macOS-Menüleisten-App, die Nutzungslimits, Guthaben, Kosten und Resets von 59 KI-Coding-Anbietern im Blick behält – Codex, OpenAI, Claude, Cursor, Gemini, Copilot, LiteLLM und mehr.", + "meta.ogDescription": "Nutzungslimits, Guthaben und Resets von 59 KI-Coding-Anbietern direkt in Ihrer macOS-Menüleiste.", + "nav.primary": "Primär", + "nav.language": "Sprache", + "nav.docs": "Dokumente", + "nav.source": "Quelle", + "nav.download": "Herunterladen", + "theme.toLight": "Wechseln Sie zum Lichtthema", + "theme.toDark": "Wechseln Sie zum dunklen Thema", + "hero.prefix": "Alle Limits Ihrer KI-Coding-Tools –", + "hero.accent": "direkt in Ihrer Menüleiste.", + "hero.description": "CodexBar verfolgt Nutzungsfenster, Guthaben und Reset-Countdowns bei den Anbietern, für die Sie tatsächlich bezahlen – jeweils ein Statuselement oder sie werden zu einem zusammengeführt.", + "hero.download": "Herunterladen für macOS", + "hero.fineprint": "Kostenlos und Open Source · macOS 14+ · Universal über GitHub Releases und Homebrew", + "providers.title": "59 Provider,{mobileBreak}eine Menüleiste", + "providers.description": "Beliebte Anbieter werden zu Statuselementen mit eigenen Nutzungsfenstern, Reset-Countdowns, Diagrammen und Anbietermenüs.", + "providers.yourProvider": "Ihr Anbieter", + "providers.authoringGuide": "Autorenleitfaden", + "auth.oauth": "OAuth", + "auth.cli": "CLI", + "auth.gcloud": "gcloud", + "auth.cookies": "Cookies", + "auth.cookiesGo": "Cookies + Go", + "auth.deviceFlow": "Device flow", + "auth.bearerLocal": "Bearer / Local", + "auth.apiKey": "API key", + "auth.token": "Token", + "auth.legacyApi": "Legacy API", + "auth.local": "Local", + "auth.apiKeyCookies": "API key + Cookies", + "auth.virtualKey": "Virtual key", + "showcase.alt": "CodexBar-Menüleisten-Popover mit Anbieterkacheln mit Nutzungsbalken, Reset-Countdowns und Kreditdetails.", + "features.resetsTitle": "Resets, die Sie planen können", + "features.resetsBody": "Sitzung pro Anbieter, wöchentliche und monatliche Fenster mit Countdowns bis zum nächsten Zurücksetzen – kein Raten mehr, ob eine lange Aufgabe gestartet werden soll.", + "features.spendTitle": "Gutschriften-, Ausgaben- und Kostenscans", + "features.spendBody": "Guthaben und monatliche Ausgaben dort, wo der Anbieter sie offenlegt, plus konfigurierbare lokale Kostenscans für Codex und Claude.", + "features.statusTitle": "Status und Vorfälle", + "features.statusBody": "Bei der Abfrage des Anbieterstatus werden Vorfall-Badges im Menü und ein Indikator-Overlay auf dem Balkensymbol angezeigt.", + "features.cliTitle": "CLI und Widgets", + "features.cliBody": "WidgetKit-Widgets für unterstützte Anbieter und eine gebündelte {codexbar} CLI für Skripte und CI – macOS und Linux bauen auf jeder Version auf.", + "detail.installTitle": "Installieren und aktualisieren", + "detail.installBody": "Universelle App über {releases} mit automatischen Sparkle-Updates oder über {cask} (Updates mit {upgrade}).", + "detail.cliTitle": "CLI", + "detail.cliBody": "Eine gebündelte {codexbar}-Binärdatei plus eigenständige Tarballs für macOS und Linux in jeder Version. Auf Linux: {linuxCommand}.", + "detail.privacyTitle": "Privatsphäre", + "detail.privacyBody": "Verwendet vorhandene Anbietersitzungen – OAuth, Gerätefluss, API-Schlüssel, Browser-Cookies, lokale Dateien – wieder, sodass keine Passwörter gespeichert werden. Prüfnotizen in {issue}.", + "detail.permissionsTitle": "macOS-Berechtigungen", + "detail.permissionsBody": "Vollständiger Festplattenzugriff für Safari-Cookies, Keychain-Zugriff für Cookie-Entschlüsselung und OAuth-Abläufe sowie Eingabeaufforderungen für Dateien und Ordner, wenn Anbieterhelfer Projektverzeichnisse lesen.", + "footer.builtBy": "Gebaut von", + "footer.changelog": "Änderungsprotokoll", + "clipboard.copy": "In die Zwischenablage kopieren", + "clipboard.copied": "Kopiert", + "nav.home": "CodexBar-Startseite", + "nav.projectLinks": "Projektlinks", + "nav.sourceGitHub": "CodexBar-Quellcode auf GitHub", + "nav.sourceStars": "Quellcode", + "nav.displayDownload": "Anzeige und Download", + "clipboard.copyBrew": "Homebrew-Installationsbefehl kopieren", + "hero.badgeStart": "AI-Nutzungslimits", + "hero.badgeEnd": "für macOS", + "hero.descriptionShort": "Verfolge Nutzungsfenster, Guthaben und Reset-Countdowns der AI-Tools, für die du wirklich zahlst.", + "hero.fineprintShort": "Kostenlos und Open Source · macOS 14+", + "features.title": "Limits,\u00a0Ausgaben und Status", + "mockup.openPanelAria": "CodexBar in der macOS-Menüleiste geöffnet", + "mockup.macbookAlt": "MacBook-Menüleiste", + "mockup.menuBarAria": "Statusobjekte der macOS-Menüleiste", + "mockup.menuIconAria": "CodexBar-Menüleistenicon", + "mockup.usagePanelAria": "CodexBar-Nutzungspanel öffnen", + "mockup.updatedJustNow": "Gerade aktualisiert", + "mockup.plus": "Plus", + "mockup.session": "Sitzung", + "mockup.weekly": "Wöchentlich", + "mockup.left60": "60% übrig", + "mockup.left73": "73% übrig", + "mockup.left89": "89% übrig", + "mockup.left98": "98% übrig", + "mockup.reserve2": "2% in Reserve", + "mockup.reserve5": "5% in Reserve", + "mockup.onPace": "Im Plan", + "mockup.resets2h53m": "Reset in 2 Std. 53 Min.", + "mockup.resets4h12m": "Reset in 4 Std. 12 Min.", + "mockup.resets5d4h": "Reset in 5 T. 4 Std.", + "mockup.resets6d23h": "Reset in 6 T. 23 Std.", + "mockup.runsOut4d21h": "Aufgebraucht in 4 T. 21 Std.", + "mockup.lastsUntilReset": "Reicht bis zum Reset", + "mockup.limitResetCredits": "Limit-Reset-Credits", + "mockup.nextExpires28d2h": "Nächster Ablauf in 28 T. 2 Std.", + "mockup.nextExpires27d21h": "Nächster Ablauf in 27 T. 21 Std.", + "mockup.manualResetAvailable": "1 Reset verfügbar", + "mockup.recentUsageAria": "Aktuelle Codex-Nutzung", + "mockup.today": "Heute", + "mockup.last31DaysCost": "Kosten der letzten 31 Tage", + "mockup.last31DaysTokens": "Tokens der letzten 31 Tage", + "mockup.latestTokens": "Neueste Tokens", + "mockup.usageChartAria": "31-Tage-Nutzungsdiagramm", + "mockup.topModel": "Topmodell: Example-1", + "mockup.estimatedLogs": "Geschätzt aus lokalen Codex-Logs für das ausgewählte Konto...", + "mockup.credits": "Credits", + "mockup.zeroLeft": "0 übrig", + "mockup.buyCredits": "Credits kaufen...", + "mockup.partialDegradation": "Teilweise Beeinträchtigung", + "mockup.twoIncidents": "2 Vorfälle", + "mockup.majorOutage": "Großer Ausfall", + "mockup.degraded": "Beeinträchtigt", + "mockup.operational": "Betriebsbereit", + "cli.outputPreviewAria": "Vorschau der CodexBar-CLI-Ausgabe", + "cli.left99": "99% übrig", + "cli.left100": "100% übrig", + "cli.left79": "79% übrig", + "cli.left74": "74% übrig", + "cli.resets5h": "Reset in 5 Std.", + "cli.resets7d": "Reset in 7 T.", + "cli.resets23d18h": "Reset in 23 T. 18 Std.", + "cli.available1": "1 verfügbar", + "cli.nextResetCredit": "Nächster Reset-Credit", + "cli.expires27d22h": "läuft in 27 T. 22 Std. ab", + "cli.account": "Konto", + "cli.plan": "Plan", + "cli.total": "Gesamt", + "cli.auto": "Auto", + "cli.titleLine2": "in der CLI", + "cli.lead": "Ein gebündeltes {codexbar}-Binary mit derselben Nutzungsausgabe wie die Menüleiste — für Skripte, CI und schnelle Terminalchecks.", + "cli.note": "Eigenständige Tarballs für macOS und Linux bei jedem Release.", + "cli.privacy": "CodexBar verwendet bestehende Provider-Sitzungen wieder — keine Passwörter werden auf der Festplatte gespeichert.", + "widgets.titleLine2": "Widgets", + "widgets.lead": "WidgetKit-Widgets für unterstützte Provider — Nutzungsfenster, Reset-Countdowns und Ausgaben, wo verfügbar. Lege sie auf Home Screen und Schreibtisch ab.", + "widgets.note": "Kleine, mittlere und große Größen. Wechsle Provider direkt im Widget.", + "widgets.galleryAria": "macOS-Widgetgalerie-Vorschau", + "widgets.categoriesAria": "Widget-Kategorien", + "widgets.allWidgets": "Alle Widgets", + "widgets.metricCaption": "Kompaktes Widget für Credits oder Kosten.", + "widgets.historyCaption": "Nutzungsverlauf mit aktuellen Summen.", + "widgets.usageCaption": "Sitzungs- und Wochennutzung mit Credits und Kosten.", + "widgets.switcherCaption": "Nutzungswidget mit Provider-Wechsler.", + "widgets.burndownCaption": "Verbleibendes Budget im Vergleich zu einer idealen gleichmäßigen Burn-Rate.", + "widgets.burndownCombinedCaption": "Sitzungs- und Wochen-Burndown in einer Kachel.", + "widgets.dragToDesktop": "Widget auf den Schreibtisch ziehen…", + "detail.more": "Mehr" + }, + "fr": { + "meta.title": "CodexBar — chaque limite de codage IA dans votre barre de menus", + "meta.description": "Une petite application de barre de menus macOS qui suit les fenêtres d'utilisation, les crédits, les coûts et les réinitialisations des fournisseurs de codage d'IA sur 59 fournisseurs : Codex, OpenAI, Claude, Cursor, Gemini, Copilot, LiteLLM, et plus encore.", + "meta.ogDescription": "Suivez les fenêtres d'utilisation, les crédits et les réinitialisations auprès de 59 fournisseurs de codage d'IA à partir de votre barre de menus macOS.", + "nav.primary": "Primaire", + "nav.language": "Langue", + "nav.docs": "Documents", + "nav.source": "Source", + "nav.download": "Télécharger", + "theme.toLight": "Passer au thème clair", + "theme.toDark": "Passer au thème sombre", + "hero.prefix": "Chaque limite de codage AI,", + "hero.accent": "dans votre barre de menu.", + "hero.description": "CodexBar suit les fenêtres d'utilisation, les soldes créditeurs et réinitialise les comptes à rebours pour les fournisseurs pour lesquels vous payez réellement - un élément de statut chacun, ou les fusionne en un seul.", + "hero.download": "Télécharger pour macOS", + "hero.fineprint": "Gratuit et open source · macOS 14+ · Universel via GitHub Releases et Homebrew", + "providers.title": "59 fournisseurs,{mobileBreak}une barre des menus", + "providers.description": "Les fournisseurs populaires deviennent des éléments de statut avec leurs propres fenêtres d'utilisation, réinitialisent les comptes à rebours, les graphiques et les menus des fournisseurs.", + "providers.yourProvider": "Votre fournisseur", + "providers.authoringGuide": "Guide de création", + "auth.oauth": "OAuth", + "auth.cli": "CLI", + "auth.gcloud": "gcloud", + "auth.cookies": "Cookies", + "auth.cookiesGo": "Cookies + Go", + "auth.deviceFlow": "Device flow", + "auth.bearerLocal": "Bearer / Local", + "auth.apiKey": "API key", + "auth.token": "Token", + "auth.legacyApi": "Legacy API", + "auth.local": "Local", + "auth.apiKeyCookies": "API key + Cookies", + "auth.virtualKey": "Virtual key", + "showcase.alt": "Fenêtre contextuelle de la barre de menu CodexBar affichant les vignettes du fournisseur avec des barres d'utilisation, des comptes à rebours de réinitialisation et des détails de crédit.", + "features.resetsTitle": "Des réinitialisations que vous pouvez planifier", + "features.resetsBody": "Session par fournisseur, fenêtres hebdomadaires et mensuelles avec comptes à rebours jusqu'à la prochaine réinitialisation : plus besoin de deviner s'il faut démarrer une longue tâche.", + "features.spendTitle": "Analyses des crédits, des dépenses et des coûts", + "features.spendBody": "Soldes créditeurs et dépenses mensuelles là où le fournisseur les expose, ainsi que des analyses de coûts locales configurables pour Codex et Claude.", + "features.statusTitle": "Statut et incidents", + "features.statusBody": "L'interrogation de l'état du fournisseur fait apparaître des badges d'incident dans le menu et un indicateur superposé sur l'icône de la barre.", + "features.cliTitle": "CLI et widgets", + "features.cliBody": "Des widgets WidgetKit pour les fournisseurs pris en charge et un {codexbar} CLI fourni pour les scripts et CI — macOS et Linux s'appuient sur chaque version.", + "detail.installTitle": "Installation et mises à jour", + "detail.installBody": "Application universelle via {releases} avec mises à jour automatiques Sparkle, ou via {cask} (mises à jour avec {upgrade}).", + "detail.cliTitle": "CLI", + "detail.cliBody": "Un binaire {codexbar} fourni ainsi que des archives tar autonomes pour macOS et Linux sur chaque version. Sur Linux : {linuxCommand}.", + "detail.privacyTitle": "Confidentialité", + "detail.privacyBody": "Réutilise les sessions du fournisseur existantes (OAuth, flux de périphérique, clés API, cookies du navigateur, fichiers locaux) afin qu'aucun mot de passe ne soit stocké. Notes d'audit dans {issue}.", + "detail.permissionsTitle": "autorisations macOS", + "detail.permissionsBody": "Accès complet au disque pour les cookies Safari, accès Keychain pour le décryptage des cookies et les flux OAuth, et fichiers et dossiers vous invitent lorsque les assistants du fournisseur lisent les répertoires du projet.", + "footer.builtBy": "Construit par", + "footer.changelog": "Journal des modifications", + "clipboard.copy": "Copier dans le presse-papier", + "clipboard.copied": "Copié", + "nav.home": "Accueil CodexBar", + "nav.projectLinks": "Liens du projet", + "nav.sourceGitHub": "Source CodexBar sur GitHub", + "nav.sourceStars": "source", + "nav.displayDownload": "Affichage et téléchargement", + "clipboard.copyBrew": "Copier la commande Homebrew", + "hero.badgeStart": "Limites d’usage IA", + "hero.badgeEnd": "pour macOS", + "hero.descriptionShort": "Suivez les fenêtres d’utilisation, soldes de crédits et comptes à rebours des outils IA que vous payez vraiment.", + "hero.fineprintShort": "Gratuit et open source · macOS 14+", + "features.title": "Limites,\u00a0dépenses et statut", + "mockup.openPanelAria": "CodexBar ouvert dans la barre des menus macOS", + "mockup.macbookAlt": "Barre des menus du MacBook", + "mockup.menuBarAria": "Éléments d’état de la barre des menus macOS", + "mockup.menuIconAria": "Icône CodexBar de la barre des menus", + "mockup.usagePanelAria": "Ouvrir le panneau d’utilisation CodexBar", + "mockup.updatedJustNow": "Mis à jour à l’instant", + "mockup.plus": "Plus", + "mockup.session": "Session", + "mockup.weekly": "Hebdomadaire", + "mockup.left60": "60% restants", + "mockup.left73": "73% restants", + "mockup.left89": "89% restants", + "mockup.left98": "98% restants", + "mockup.reserve2": "2% en réserve", + "mockup.reserve5": "5% en réserve", + "mockup.onPace": "Dans les temps", + "mockup.resets2h53m": "Réinitialisation dans 2 h 53 min", + "mockup.resets4h12m": "Réinitialisation dans 4 h 12 min", + "mockup.resets5d4h": "Réinitialisation dans 5 j 4 h", + "mockup.resets6d23h": "Réinitialisation dans 6 j 23 h", + "mockup.runsOut4d21h": "Épuisé dans 4 j 21 h", + "mockup.lastsUntilReset": "Tient jusqu’à la réinitialisation", + "mockup.limitResetCredits": "Crédits de réinitialisation de limite", + "mockup.nextExpires28d2h": "Le prochain expire dans 28 j 2 h", + "mockup.nextExpires27d21h": "Le prochain expire dans 27 j 21 h", + "mockup.manualResetAvailable": "1 réinitialisation disponible", + "mockup.recentUsageAria": "Utilisation récente de Codex", + "mockup.today": "Aujourd’hui", + "mockup.last31DaysCost": "Coût des 31 derniers jours", + "mockup.last31DaysTokens": "Tokens des 31 derniers jours", + "mockup.latestTokens": "Derniers tokens", + "mockup.usageChartAria": "Graphique d’utilisation sur 31 jours", + "mockup.topModel": "Modèle principal : Example-1", + "mockup.estimatedLogs": "Estimé à partir des journaux Codex locaux pour le compte sélectionné...", + "mockup.credits": "Crédits", + "mockup.zeroLeft": "0 restant", + "mockup.buyCredits": "Acheter des crédits...", + "mockup.partialDegradation": "Dégradation partielle", + "mockup.twoIncidents": "2 incidents", + "mockup.majorOutage": "Panne majeure", + "mockup.degraded": "Dégradé", + "mockup.operational": "Opérationnel", + "cli.outputPreviewAria": "Aperçu de la sortie CLI CodexBar", + "cli.left99": "99% restants", + "cli.left100": "100% restants", + "cli.left79": "79% restants", + "cli.left74": "74% restants", + "cli.resets5h": "Réinitialisation dans 5 h", + "cli.resets7d": "Réinitialisation dans 7 j", + "cli.resets23d18h": "Réinitialisation dans 23 j 18 h", + "cli.available1": "1 disponible", + "cli.nextResetCredit": "Prochain crédit de réinitialisation", + "cli.expires27d22h": "expire dans 27 j 22 h", + "cli.account": "Compte", + "cli.plan": "Forfait", + "cli.total": "Total", + "cli.auto": "Auto", + "cli.titleLine2": "dans le CLI", + "cli.lead": "Un binaire {codexbar} inclus avec la même sortie d’utilisation que la barre des menus — scripts, CI et vérifications rapides dans le terminal.", + "cli.note": "Tarballs autonomes pour macOS et Linux à chaque version.", + "cli.privacy": "CodexBar réutilise les sessions existantes des fournisseurs — aucun mot de passe n’est stocké sur le disque.", + "widgets.titleLine2": "widgets", + "widgets.lead": "Widgets WidgetKit pour les fournisseurs pris en charge — fenêtres d’utilisation, comptes à rebours de réinitialisation et dépenses si disponibles. Déposez-les sur l’écran d’accueil et le bureau.", + "widgets.note": "Tailles petite, moyenne et grande. Changez de fournisseur sans quitter le widget.", + "widgets.galleryAria": "Aperçu de la galerie de widgets macOS", + "widgets.categoriesAria": "Catégories de widgets", + "widgets.allWidgets": "Tous les widgets", + "widgets.metricCaption": "Widget compact pour crédits ou coût.", + "widgets.historyCaption": "Graphique d’historique d’utilisation avec totaux récents.", + "widgets.usageCaption": "Utilisation de session et hebdomadaire avec crédits et coûts.", + "widgets.switcherCaption": "Widget d’utilisation avec sélecteur de fournisseur.", + "widgets.burndownCaption": "Budget restant comparé à un rythme de consommation idéal et régulier.", + "widgets.burndownCombinedCaption": "Graphiques burn-down de session et semaine dans une seule tuile.", + "widgets.dragToDesktop": "Faites glisser un widget vers le bureau…", + "detail.more": "Plus" + }, + "ar": { + "meta.title": "CodexBar — كل حد لترميز الذكاء الاصطناعي في شريط القائمة", + "meta.description": "تطبيق شريط قوائم macOS صغير الحجم يتتبع نوافذ استخدام موفر ترميز الذكاء الاصطناعي، والائتمانات، والتكاليف، وعمليات إعادة التعيين عبر 59 موفرًا - Codex، وOpenAI، وClaude، وCursor، وGemini، وCopilot، وLiteLLM، والمزيد.", + "meta.ogDescription": "تتبع نوافذ الاستخدام والأرصدة وعمليات إعادة التعيين عبر 59 موفرًا لترميز الذكاء الاصطناعي من شريط القائمة macOS.", + "nav.primary": "أساسي", + "nav.language": "لغة", + "nav.docs": "المستندات", + "nav.source": "مصدر", + "nav.download": "تحميل", + "theme.toLight": "التبديل إلى موضوع الضوء", + "theme.toDark": "التبديل إلى المظهر الداكن", + "hero.prefix": "كل حدود ترميز الذكاء الاصطناعي،", + "hero.accent": "في شريط القائمة الخاص بك.", + "hero.description": "يتتبع CodexBar فترات الاستخدام والأرصدة الائتمانية وإعادة تعيين العد التنازلي عبر مقدمي الخدمة الذين تدفع مقابلهم فعليًا — عنصر حالة واحد لكل منهم، أو دمجهم في عنصر واحد.", + "hero.download": "التنزيل لمدة macOS", + "hero.fineprint": "مجاني ومفتوح المصدر · macOS 14+ · إصدار شامل عبر GitHub Releases وHomebrew", + "providers.title": "59 مزودًا،{mobileBreak}شريط قوائم واحد", + "providers.description": "يصبح الموفرون المشهورون عناصر حالة مع نوافذ الاستخدام الخاصة بهم، وعمليات إعادة تعيين العد التنازلي، والمخططات، وقوائم الموفر.", + "providers.yourProvider": "المزود الخاص بك", + "providers.authoringGuide": "دليل التأليف", + "auth.oauth": "OAuth", + "auth.cli": "CLI", + "auth.gcloud": "gcloud", + "auth.cookies": "Cookies", + "auth.cookiesGo": "Cookies + Go", + "auth.deviceFlow": "Device flow", + "auth.bearerLocal": "Bearer / Local", + "auth.apiKey": "API key", + "auth.token": "Token", + "auth.legacyApi": "Legacy API", + "auth.local": "Local", + "auth.apiKeyCookies": "API key + Cookies", + "auth.virtualKey": "Virtual key", + "showcase.alt": "CodexBar القائمة المنبثقة لشريط القائمة تعرض مربعات الموفر مع أشرطة الاستخدام، وعمليات إعادة التعيين التنازلية، وتفاصيل الائتمان.", + "features.resetsTitle": "إعادة تعيين يمكنك التخطيط حولها", + "features.resetsBody": "جلسة لكل مزود، ونوافذ أسبوعية وشهرية مع العد التنازلي لإعادة التعيين التالية - لم تعد هناك حاجة للتخمين بشأن بدء مهمة طويلة.", + "features.spendTitle": "عمليات فحص الاعتمادات والإنفاق والتكلفة", + "features.spendBody": "الأرصدة الدائنة والإنفاق الشهري حيث يعرضها مقدم الخدمة، بالإضافة إلى عمليات فحص التكلفة المحلية القابلة للتكوين لـ Codex وClaude.", + "features.statusTitle": "الحالة والحوادث", + "features.statusBody": "يعرض استقصاء حالة الموفر شارات الحوادث في القائمة وتراكب المؤشر على أيقونة الشريط.", + "features.cliTitle": "CLI والحاجيات", + "features.cliBody": "أدوات WidgetKit للموفرين المدعومين و{codexbar} CLI المجمعة للنصوص البرمجية وCI - يعتمد macOS وLinux على كل إصدار.", + "detail.installTitle": "التثبيت والتحديثات", + "detail.installBody": "تطبيق شامل عبر {releases} مع تحديثات تلقائية لـ Sparkle، أو عبر {cask} (التحديثات باستخدام {upgrade}).", + "detail.cliTitle": "CLI", + "detail.cliBody": "ملف ثنائي {codexbar} مجمع بالإضافة إلى كرات قطران مستقلة لـ macOS وLinux في كل إصدار. في Linux: {linuxCommand}.", + "detail.privacyTitle": "خصوصية", + "detail.privacyBody": "يعيد استخدام جلسات الموفر الحالية - OAuth، وتدفق الجهاز، ومفاتيح API، وملفات تعريف الارتباط للمتصفح، والملفات المحلية - لذلك لا يتم تخزين كلمات المرور. ملاحظات التدقيق في {issue}.", + "detail.permissionsTitle": "أذونات macOS.", + "detail.permissionsBody": "الوصول الكامل إلى القرص لملفات تعريف الارتباط Safari، والوصول Keychain لفك تشفير ملفات تعريف الارتباط وتدفقات OAuth، ومطالبة الملفات والمجلدات عندما يقرأ مساعدو الموفر أدلة المشروع.", + "footer.builtBy": "بنيت من قبل", + "footer.changelog": "سجل التغيير", + "clipboard.copy": "نسخ إلى الحافظة", + "clipboard.copied": "منقول", + "nav.home": "صفحة CodexBar الرئيسية", + "nav.projectLinks": "روابط المشروع", + "nav.sourceGitHub": "مصدر CodexBar على GitHub", + "nav.sourceStars": "المصدر", + "nav.displayDownload": "العرض والتنزيل", + "clipboard.copyBrew": "نسخ أمر تثبيت Homebrew", + "hero.badgeStart": "حدود استخدام الذكاء الاصطناعي", + "hero.badgeEnd": "لنظام macOS", + "hero.descriptionShort": "تتبّع نوافذ الاستخدام وأرصدة الاعتمادات وعدّادات إعادة الضبط عبر أدوات الذكاء الاصطناعي التي تدفع مقابلها فعلاً.", + "hero.fineprintShort": "مجاني ومفتوح المصدر · macOS 14+", + "features.title": "الحدود والإنفاق والحالة", + "mockup.openPanelAria": "CodexBar مفتوح في شريط قوائم macOS", + "mockup.macbookAlt": "شريط قوائم MacBook", + "mockup.menuBarAria": "عناصر حالة شريط قوائم macOS", + "mockup.menuIconAria": "أيقونة CodexBar في شريط القوائم", + "mockup.usagePanelAria": "فتح لوحة استخدام CodexBar", + "mockup.updatedJustNow": "تم التحديث الآن", + "mockup.plus": "Plus", + "mockup.session": "الجلسة", + "mockup.weekly": "أسبوعي", + "mockup.left60": "متبقٍ 60%", + "mockup.left73": "متبقٍ 73%", + "mockup.left89": "متبقٍ 89%", + "mockup.left98": "متبقٍ 98%", + "mockup.reserve2": "2% في الاحتياطي", + "mockup.reserve5": "5% في الاحتياطي", + "mockup.onPace": "ضمن الوتيرة", + "mockup.resets2h53m": "إعادة الضبط خلال 2س 53د", + "mockup.resets4h12m": "إعادة الضبط خلال 4س 12د", + "mockup.resets5d4h": "إعادة الضبط خلال 5أ 4س", + "mockup.resets6d23h": "إعادة الضبط خلال 6أ 23س", + "mockup.runsOut4d21h": "ينفد خلال 4أ 21س", + "mockup.lastsUntilReset": "يستمر حتى إعادة الضبط", + "mockup.limitResetCredits": "اعتمادات إعادة ضبط الحد", + "mockup.nextExpires28d2h": "التالي ينتهي خلال 28أ 2س", + "mockup.nextExpires27d21h": "التالي ينتهي خلال 27أ 21س", + "mockup.manualResetAvailable": "إعادة ضبط واحدة متاحة", + "mockup.recentUsageAria": "استخدام Codex الأخير", + "mockup.today": "اليوم", + "mockup.last31DaysCost": "تكلفة آخر 31 يوماً", + "mockup.last31DaysTokens": "رموز آخر 31 يوماً", + "mockup.latestTokens": "أحدث الرموز", + "mockup.usageChartAria": "مخطط استخدام 31 يوماً", + "mockup.topModel": "النموذج الأعلى: Example-1", + "mockup.estimatedLogs": "مقدّر من سجلات Codex المحلية للحساب المحدد...", + "mockup.credits": "الاعتمادات", + "mockup.zeroLeft": "0 متبقٍ", + "mockup.buyCredits": "شراء اعتمادات...", + "mockup.partialDegradation": "تدهور جزئي", + "mockup.twoIncidents": "حادثتان", + "mockup.majorOutage": "انقطاع كبير", + "mockup.degraded": "متدهور", + "mockup.operational": "تشغيلي", + "cli.outputPreviewAria": "معاينة خرج CodexBar CLI", + "cli.left99": "متبقٍ 99%", + "cli.left100": "متبقٍ 100%", + "cli.left79": "متبقٍ 79%", + "cli.left74": "متبقٍ 74%", + "cli.resets5h": "إعادة الضبط خلال 5س", + "cli.resets7d": "إعادة الضبط خلال 7أ", + "cli.resets23d18h": "إعادة الضبط خلال 23أ 18س", + "cli.available1": "1 متاح", + "cli.nextResetCredit": "اعتماد إعادة الضبط التالي", + "cli.expires27d22h": "ينتهي خلال 27أ 22س", + "cli.account": "الحساب", + "cli.plan": "الخطة", + "cli.total": "الإجمالي", + "cli.auto": "تلقائي", + "cli.titleLine2": "في CLI", + "cli.lead": "ملف {codexbar} ثنائي مضمّن يعرض نفس خرج الاستخدام مثل شريط القوائم — للسكربتات وCI والفحوصات السريعة في الطرفية.", + "cli.note": "حزم tarball مستقلة لـ macOS وLinux في كل إصدار.", + "cli.privacy": "يعيد CodexBar استخدام جلسات المزوّدين الحالية — لا تُحفظ كلمات مرور على القرص.", + "widgets.titleLine2": "الويدجتات", + "widgets.lead": "ويدجتات WidgetKit للمزوّدين المدعومين — نوافذ استخدام وعدّادات إعادة ضبط وإنفاق حيث يتوفر. ضعها على الشاشة الرئيسية وسطح المكتب.", + "widgets.note": "أحجام صغيرة ومتوسطة وكبيرة. بدّل المزوّد من داخل الويدجت.", + "widgets.galleryAria": "معاينة معرض ويدجتات macOS", + "widgets.categoriesAria": "فئات الويدجت", + "widgets.allWidgets": "كل الويدجتات", + "widgets.metricCaption": "ويدجت مدمج للاعتمادات أو التكلفة.", + "widgets.historyCaption": "مخطط سجل الاستخدام مع المجاميع الأخيرة.", + "widgets.usageCaption": "استخدام الجلسة والأسبوع مع الاعتمادات والتكاليف.", + "widgets.switcherCaption": "ويدجت استخدام مع مبدّل مزوّد.", + "widgets.burndownCaption": "الميزانية المتبقية مقارنة بمعدل استهلاك ثابت مثالي.", + "widgets.burndownCombinedCaption": "مخططات استهلاك الجلسة والأسبوع في مربع واحد.", + "widgets.dragToDesktop": "اسحب ويدجت إلى سطح المكتب…", + "detail.more": "المزيد" + }, + "it": { + "meta.title": "CodexBar: ogni limite di codifica AI nella barra dei menu", + "meta.description": "Una piccola app della barra dei menu macOS che tiene traccia delle finestre di utilizzo, dei crediti, dei costi e dei ripristini del fornitore di codifica AI tra 59 fornitori: Codex, OpenAI, Claude, Cursor, Gemini, Copilot, LiteLLM e altri.", + "meta.ogDescription": "Tieni traccia delle finestre di utilizzo, dei crediti e dei ripristini tra 59 fornitori di codifica AI dalla barra dei menu macOS.", + "nav.primary": "Primario", + "nav.language": "Lingua", + "nav.docs": "Documenti", + "nav.source": "Fonte", + "nav.download": "Scaricamento", + "theme.toLight": "Passa al tema chiaro", + "theme.toDark": "Passa al tema scuro", + "hero.prefix": "Ogni limite di codifica AI,", + "hero.accent": "nella barra dei menu.", + "hero.description": "CodexBar tiene traccia delle finestre di utilizzo, dei saldi del credito e reimposta i conti alla rovescia tra i fornitori per cui paghi effettivamente: un elemento di stato ciascuno o uniscili in uno solo.", + "hero.download": "Scarica per macOS", + "hero.fineprint": "Gratuito e open source · macOS 14+ · Universale tramite GitHub Releases e Homebrew", + "providers.title": "59 provider,{mobileBreak}una barra dei menu", + "providers.description": "I fornitori più popolari diventano elementi di stato con le proprie finestre di utilizzo, reimpostano i conti alla rovescia, i grafici e i menu dei fornitori.", + "providers.yourProvider": "Il tuo fornitore", + "providers.authoringGuide": "Guida all'autore", + "auth.oauth": "OAuth", + "auth.cli": "CLI", + "auth.gcloud": "gcloud", + "auth.cookies": "Cookies", + "auth.cookiesGo": "Cookies + Go", + "auth.deviceFlow": "Device flow", + "auth.bearerLocal": "Bearer / Local", + "auth.apiKey": "API key", + "auth.token": "Token", + "auth.legacyApi": "Legacy API", + "auth.local": "Local", + "auth.apiKeyCookies": "API key + Cookies", + "auth.virtualKey": "Virtual key", + "showcase.alt": "Popover della barra dei menu CodexBar che mostra i riquadri del fornitore con barre di utilizzo, reimpostazione del conto alla rovescia e dettagli del credito.", + "features.resetsTitle": "Ripristini che puoi pianificare", + "features.resetsBody": "Sessione per fornitore, finestre settimanali e mensili con conto alla rovescia fino al ripristino successivo: non dovrai più indovinare se avviare un'attività lunga.", + "features.spendTitle": "Crediti, spesa e scansioni dei costi", + "features.spendBody": "Saldi dei crediti e spesa mensile laddove il fornitore li espone, oltre a scansioni dei costi locali configurabili per Codex e Claude.", + "features.statusTitle": "Stato e incidenti", + "features.statusBody": "Il sondaggio sullo stato del fornitore mostra i badge degli incidenti nel menu e un indicatore in sovrapposizione sull'icona della barra.", + "features.cliTitle": "CLI e widget", + "features.cliBody": "Widget WidgetKit per i provider supportati e un {codexbar} CLI in bundle per gli script e CI: macOS e Linux si basano su ogni versione.", + "detail.installTitle": "Installa e aggiorna", + "detail.installBody": "App universale tramite {releases} con aggiornamenti automatici di Sparkle o tramite {cask} (aggiornamenti con {upgrade}).", + "detail.cliTitle": "CLI", + "detail.cliBody": "Un pacchetto binario {codexbar} più tarball indipendenti per macOS e Linux su ogni versione. Su Linux: {linuxCommand}.", + "detail.privacyTitle": "Privacy", + "detail.privacyBody": "Riutilizza le sessioni del provider esistenti (OAuth, flusso del dispositivo, chiavi API, cookie del browser, file locali), quindi non viene memorizzata alcuna password. Note di controllo in {issue}.", + "detail.permissionsTitle": "macOS autorizzazioni", + "detail.permissionsBody": "Accesso completo al disco per cookie Safari, accesso Keychain per la decrittografia dei cookie e flussi OAuth e richieste di File e cartelle quando gli aiutanti del provider leggono le directory del progetto.", + "footer.builtBy": "Costruito da", + "footer.changelog": "Registro delle modifiche", + "clipboard.copy": "Copia negli appunti", + "clipboard.copied": "Copiato", + "nav.home": "Home CodexBar", + "nav.projectLinks": "Link del progetto", + "nav.sourceGitHub": "Sorgente CodexBar su GitHub", + "nav.sourceStars": "sorgente", + "nav.displayDownload": "Display e download", + "clipboard.copyBrew": "Copia comando di installazione Homebrew", + "hero.badgeStart": "Limiti di utilizzo IA", + "hero.badgeEnd": "per macOS", + "hero.descriptionShort": "Tieni traccia di finestre di utilizzo, saldi credito e countdown di reset negli strumenti IA che paghi davvero.", + "hero.fineprintShort": "Gratis e open source · macOS 14+", + "features.title": "Limiti,\u00a0spesa e stato", + "mockup.openPanelAria": "CodexBar aperto nella barra dei menu macOS", + "mockup.macbookAlt": "Barra dei menu MacBook", + "mockup.menuBarAria": "Elementi di stato della barra dei menu macOS", + "mockup.menuIconAria": "Icona CodexBar nella barra dei menu", + "mockup.usagePanelAria": "Apri pannello utilizzo CodexBar", + "mockup.updatedJustNow": "Aggiornato ora", + "mockup.plus": "Plus", + "mockup.session": "Sessione", + "mockup.weekly": "Settimanale", + "mockup.left60": "60% rimasto", + "mockup.left73": "73% rimasto", + "mockup.left89": "89% rimasto", + "mockup.left98": "98% rimasto", + "mockup.reserve2": "2% in riserva", + "mockup.reserve5": "5% in riserva", + "mockup.onPace": "In linea", + "mockup.resets2h53m": "Reset tra 2 h 53 min", + "mockup.resets4h12m": "Reset tra 4 h 12 min", + "mockup.resets5d4h": "Reset tra 5 g 4 h", + "mockup.resets6d23h": "Reset tra 6 g 23 h", + "mockup.runsOut4d21h": "Si esaurisce tra 4 g 21 h", + "mockup.lastsUntilReset": "Dura fino al reset", + "mockup.limitResetCredits": "Crediti reset limite", + "mockup.nextExpires28d2h": "Il prossimo scade tra 28 g 2 h", + "mockup.nextExpires27d21h": "Il prossimo scade tra 27 g 21 h", + "mockup.manualResetAvailable": "1 reset disponibile", + "mockup.recentUsageAria": "Uso recente di Codex", + "mockup.today": "Oggi", + "mockup.last31DaysCost": "Costo ultimi 31 giorni", + "mockup.last31DaysTokens": "Token ultimi 31 giorni", + "mockup.latestTokens": "Token più recenti", + "mockup.usageChartAria": "Grafico uso 31 giorni", + "mockup.topModel": "Modello principale: Example-1", + "mockup.estimatedLogs": "Stimato dai log Codex locali per l’account selezionato...", + "mockup.credits": "Crediti", + "mockup.zeroLeft": "0 rimasti", + "mockup.buyCredits": "Acquista crediti...", + "mockup.partialDegradation": "Degrado parziale", + "mockup.twoIncidents": "2 incidenti", + "mockup.majorOutage": "Interruzione grave", + "mockup.degraded": "Degradato", + "mockup.operational": "Operativo", + "cli.outputPreviewAria": "Anteprima output CLI CodexBar", + "cli.left99": "99% rimasto", + "cli.left100": "100% rimasto", + "cli.left79": "79% rimasto", + "cli.left74": "74% rimasto", + "cli.resets5h": "Reset tra 5 h", + "cli.resets7d": "Reset tra 7 g", + "cli.resets23d18h": "Reset tra 23 g 18 h", + "cli.available1": "1 disponibile", + "cli.nextResetCredit": "Prossimo credito reset", + "cli.expires27d22h": "scade tra 27 g 22 h", + "cli.account": "Account", + "cli.plan": "Piano", + "cli.total": "Totale", + "cli.auto": "Auto", + "cli.titleLine2": "in CLI", + "cli.lead": "Un binario {codexbar} incluso con lo stesso output di utilizzo della barra dei menu — script, CI e controlli rapidi da terminale.", + "cli.note": "Tarball autonomi per macOS e Linux a ogni release.", + "cli.privacy": "CodexBar riutilizza le sessioni provider esistenti — nessuna password viene salvata su disco.", + "widgets.titleLine2": "widget", + "widgets.lead": "Widget WidgetKit per provider supportati — finestre di utilizzo, countdown reset e spesa dove disponibile. Mettili su Home Screen e desktop.", + "widgets.note": "Dimensioni piccola, media e grande. Cambia provider senza uscire dal widget.", + "widgets.galleryAria": "Anteprima galleria widget macOS", + "widgets.categoriesAria": "Categorie widget", + "widgets.allWidgets": "Tutti i widget", + "widgets.metricCaption": "Widget compatto per crediti o costo.", + "widgets.historyCaption": "Grafico cronologia uso con totali recenti.", + "widgets.usageCaption": "Uso sessione e settimanale con crediti e costi.", + "widgets.switcherCaption": "Widget uso con selettore provider.", + "widgets.burndownCaption": "Budget residuo confrontato con una velocità ideale costante.", + "widgets.burndownCombinedCaption": "Grafici burn-down sessione e settimana in un unico riquadro.", + "widgets.dragToDesktop": "Trascina un widget sul desktop…", + "detail.more": "Altro" + }, + "vi": { + "meta.title": "CodexBar — mọi giới hạn mã hóa AI trong thanh menu của bạn", + "meta.description": "Một ứng dụng thanh menu macOS nhỏ theo dõi khoảng thời gian sử dụng, tín dụng, chi phí và đặt lại của nhà cung cấp mã hóa AI trên 59 nhà cung cấp — Codex, OpenAI, Claude, Cursor, Gemini, Copilot, LiteLLM, v.v.", + "meta.ogDescription": "Theo dõi khoảng thời gian sử dụng, tín dụng và đặt lại trên 59 nhà cung cấp mã hóa AI từ thanh menu macOS của bạn.", + "nav.primary": "Sơ đẳng", + "nav.language": "Ngôn ngữ", + "nav.docs": "Tài liệu", + "nav.source": "Nguồn", + "nav.download": "Tải xuống", + "theme.toLight": "Chuyển sang giao diện nhẹ nhàng", + "theme.toDark": "Chuyển sang chủ đề tối", + "hero.prefix": "Mọi giới hạn mã hóa AI,", + "hero.accent": "trong thanh menu của bạn.", + "hero.description": "CodexBar theo dõi khoảng thời gian sử dụng, số dư tín dụng và đếm ngược đặt lại trên các nhà cung cấp mà bạn thực sự thanh toán — mỗi mục một trạng thái hoặc hợp nhất chúng thành một.", + "hero.download": "Tải xuống cho macOS", + "hero.fineprint": "Miễn phí và nguồn mở · macOS 14+ · Bản universal qua GitHub Releases và Homebrew", + "providers.title": "59 nhà cung cấp,{mobileBreak}một thanh menu", + "providers.description": "Các nhà cung cấp phổ biến trở thành các mục trạng thái với cửa sổ sử dụng của riêng họ, đặt lại bộ đếm ngược, biểu đồ và menu nhà cung cấp.", + "providers.yourProvider": "Nhà cung cấp của bạn", + "providers.authoringGuide": "Hướng dẫn soạn thảo", + "auth.oauth": "OAuth", + "auth.cli": "CLI", + "auth.gcloud": "gcloud", + "auth.cookies": "Cookies", + "auth.cookiesGo": "Cookies + Go", + "auth.deviceFlow": "Device flow", + "auth.bearerLocal": "Bearer / Local", + "auth.apiKey": "API key", + "auth.token": "Token", + "auth.legacyApi": "Legacy API", + "auth.local": "Local", + "auth.apiKeyCookies": "API key + Cookies", + "auth.virtualKey": "Virtual key", + "showcase.alt": "Cửa sổ bật lên thanh menu CodexBar hiển thị các ô nhà cung cấp có thanh sử dụng, đặt lại đếm ngược và chi tiết tín dụng.", + "features.resetsTitle": "Đặt lại bạn có thể lập kế hoạch xung quanh", + "features.resetsBody": "Phiên dành cho mỗi nhà cung cấp, khoảng thời gian hàng tuần và hàng tháng có đếm ngược đến lần đặt lại tiếp theo — không cần phải đoán xem có nên bắt đầu một nhiệm vụ dài hay không.", + "features.spendTitle": "Tín dụng, chi tiêu và quét chi phí", + "features.spendBody": "Số dư tín dụng và chi tiêu hàng tháng mà nhà cung cấp hiển thị, cùng với tính năng quét chi phí địa phương có thể định cấu hình cho Codex và Claude.", + "features.statusTitle": "Tình trạng & sự cố", + "features.statusBody": "Cuộc thăm dò trạng thái nhà cung cấp hiển thị các huy hiệu sự cố trong menu và lớp phủ chỉ báo trên biểu tượng thanh.", + "features.cliTitle": "CLI & tiện ích", + "features.cliBody": "Tiện ích WidgetKit dành cho các nhà cung cấp được hỗ trợ và một gói {codexbar} CLI dành cho tập lệnh và CI — macOS và Linux được xây dựng trên mỗi bản phát hành.", + "detail.installTitle": "Cài đặt và cập nhật", + "detail.installBody": "Ứng dụng universal qua {releases} với cập nhật Sparkle tự động, hoặc qua {cask} (cập nhật bằng {upgrade}).", + "detail.cliTitle": "CLI", + "detail.cliBody": "Một gói nhị phân {codexbar} cộng với các tarball độc lập dành cho macOS và Linux trên mỗi bản phát hành. Trên Linux: {linuxCommand}.", + "detail.privacyTitle": "Sự riêng tư", + "detail.privacyBody": "Sử dụng lại các phiên nhà cung cấp hiện có — OAuth, luồng thiết bị, khóa API, cookie trình duyệt, tệp cục bộ — nên không có mật khẩu nào được lưu trữ. Ghi chú kiểm tra trong {issue}.", + "detail.permissionsTitle": "quyền macOS", + "detail.permissionsBody": "Quyền truy cập toàn bộ ổ đĩa cho cookie Safari, quyền truy cập Keychain để giải mã cookie và luồng OAuth cũng như lời nhắc về Tệp & Thư mục khi người trợ giúp nhà cung cấp đọc thư mục dự án.", + "footer.builtBy": "Được xây dựng bởi", + "footer.changelog": "Nhật ký thay đổi", + "clipboard.copy": "Sao chép vào bảng nhớ tạm", + "clipboard.copied": "Đã sao chép", + "nav.home": "Trang chủ CodexBar", + "nav.projectLinks": "Liên kết dự án", + "nav.sourceGitHub": "Mã nguồn CodexBar trên GitHub", + "nav.sourceStars": "mã nguồn", + "nav.displayDownload": "Hiển thị và tải xuống", + "clipboard.copyBrew": "Sao chép lệnh cài đặt Homebrew", + "hero.badgeStart": "Giới hạn sử dụng AI", + "hero.badgeEnd": "cho macOS", + "hero.descriptionShort": "Theo dõi cửa sổ sử dụng, số dư tín dụng và đếm ngược đặt lại trên các công cụ AI bạn thật sự trả tiền.", + "hero.fineprintShort": "Miễn phí và mã nguồn mở · macOS 14+", + "features.title": "Giới hạn,\u00a0chi tiêu và trạng thái", + "mockup.openPanelAria": "CodexBar đang mở trên thanh menu macOS", + "mockup.macbookAlt": "Thanh menu MacBook", + "mockup.menuBarAria": "Mục trạng thái trên thanh menu macOS", + "mockup.menuIconAria": "Biểu tượng CodexBar trên thanh menu", + "mockup.usagePanelAria": "Mở bảng sử dụng CodexBar", + "mockup.updatedJustNow": "Vừa cập nhật", + "mockup.plus": "Plus", + "mockup.session": "Phiên", + "mockup.weekly": "Hàng tuần", + "mockup.left60": "còn 60%", + "mockup.left73": "còn 73%", + "mockup.left89": "còn 89%", + "mockup.left98": "còn 98%", + "mockup.reserve2": "2% dự trữ", + "mockup.reserve5": "5% dự trữ", + "mockup.onPace": "Đúng tiến độ", + "mockup.resets2h53m": "Đặt lại sau 2g 53p", + "mockup.resets4h12m": "Đặt lại sau 4g 12p", + "mockup.resets5d4h": "Đặt lại sau 5n 4g", + "mockup.resets6d23h": "Đặt lại sau 6n 23g", + "mockup.runsOut4d21h": "Hết sau 4n 21g", + "mockup.lastsUntilReset": "Dùng được đến khi đặt lại", + "mockup.limitResetCredits": "Tín dụng đặt lại giới hạn", + "mockup.nextExpires28d2h": "Lần tiếp theo hết hạn sau 28n 2g", + "mockup.nextExpires27d21h": "Lần tiếp theo hết hạn sau 27n 21g", + "mockup.manualResetAvailable": "Có 1 lần đặt lại", + "mockup.recentUsageAria": "Mức dùng Codex gần đây", + "mockup.today": "Hôm nay", + "mockup.last31DaysCost": "Chi phí 31 ngày qua", + "mockup.last31DaysTokens": "Token 31 ngày qua", + "mockup.latestTokens": "Token mới nhất", + "mockup.usageChartAria": "Biểu đồ sử dụng 31 ngày", + "mockup.topModel": "Model hàng đầu: Example-1", + "mockup.estimatedLogs": "Ước tính từ log Codex cục bộ cho tài khoản đã chọn...", + "mockup.credits": "Tín dụng", + "mockup.zeroLeft": "còn 0", + "mockup.buyCredits": "Mua tín dụng...", + "mockup.partialDegradation": "Suy giảm một phần", + "mockup.twoIncidents": "2 sự cố", + "mockup.majorOutage": "Sự cố nghiêm trọng", + "mockup.degraded": "Suy giảm", + "mockup.operational": "Hoạt động", + "cli.outputPreviewAria": "Xem trước đầu ra CodexBar CLI", + "cli.left99": "còn 99%", + "cli.left100": "còn 100%", + "cli.left79": "còn 79%", + "cli.left74": "còn 74%", + "cli.resets5h": "Đặt lại sau 5g", + "cli.resets7d": "Đặt lại sau 7n", + "cli.resets23d18h": "Đặt lại sau 23n 18g", + "cli.available1": "1 khả dụng", + "cli.nextResetCredit": "Tín dụng đặt lại tiếp theo", + "cli.expires27d22h": "hết hạn sau 27n 22g", + "cli.account": "Tài khoản", + "cli.plan": "Gói", + "cli.total": "Tổng", + "cli.auto": "Tự động", + "cli.titleLine2": "trên CLI", + "cli.lead": "Binary {codexbar} đi kèm có cùng đầu ra sử dụng như thanh menu — cho script, CI và kiểm tra nhanh trong terminal.", + "cli.note": "Tarball độc lập cho macOS và Linux trong mỗi bản phát hành.", + "cli.privacy": "CodexBar dùng lại các phiên nhà cung cấp hiện có — không lưu mật khẩu trên đĩa.", + "widgets.titleLine2": "widget", + "widgets.lead": "WidgetKit cho các nhà cung cấp được hỗ trợ — cửa sổ sử dụng, đếm ngược đặt lại và chi tiêu khi có. Đặt chúng trên Màn hình chính và desktop.", + "widgets.note": "Kích thước nhỏ, vừa và lớn. Đổi nhà cung cấp ngay trong widget.", + "widgets.galleryAria": "Xem trước thư viện widget macOS", + "widgets.categoriesAria": "Danh mục widget", + "widgets.allWidgets": "Tất cả widget", + "widgets.metricCaption": "Widget gọn cho tín dụng hoặc chi phí.", + "widgets.historyCaption": "Biểu đồ lịch sử sử dụng với tổng gần đây.", + "widgets.usageCaption": "Mức dùng phiên và tuần với tín dụng và chi phí.", + "widgets.switcherCaption": "Widget sử dụng có bộ chuyển nhà cung cấp.", + "widgets.burndownCaption": "Ngân sách còn lại so với tốc độ tiêu thụ ổn định lý tưởng.", + "widgets.burndownCombinedCaption": "Biểu đồ burn-down phiên và tuần trong một ô.", + "widgets.dragToDesktop": "Kéo widget ra desktop…", + "detail.more": "Thêm" + }, + "nl": { + "meta.title": "CodexBar — elke AI-coderingslimiet in uw menubalk", + "meta.description": "Een kleine macOS menubalk-app die gebruiksperioden, tegoeden, kosten en resets van AI-coderingsproviders bijhoudt bij 59 providers: Codex, OpenAI, Claude, Cursor, Gemini, Copilot, LiteLLM en meer.", + "meta.ogDescription": "Houd gebruiksvensters, tegoeden en resets bij van 59 leveranciers van AI-codering via uw macOS-menubalk.", + "nav.primary": "Primair", + "nav.language": "Taal", + "nav.docs": "Documenten", + "nav.source": "Bron", + "nav.download": "Downloaden", + "theme.toLight": "Schakel over naar het lichtthema", + "theme.toDark": "Schakel over naar een donker thema", + "hero.prefix": "Elke AI-coderingslimiet,", + "hero.accent": "in uw menubalk.", + "hero.description": "CodexBar houdt gebruiksperioden, tegoeden en reset-countdowns bij voor de providers waarvoor u daadwerkelijk betaalt: elk één statusitem, of u kunt ze samenvoegen tot één statusitem.", + "hero.download": "Downloaden voor macOS", + "hero.fineprint": "Gratis en open source · macOS 14+ · Universeel via GitHub Releases en Homebrew", + "providers.title": "59 providers,{mobileBreak}één menubalk", + "providers.description": "Populaire providers worden statusitems met hun eigen gebruiksvensters, resetcountdowns, grafieken en providermenu's.", + "providers.yourProvider": "Uw aanbieder", + "providers.authoringGuide": "Handleiding voor het schrijven", + "auth.oauth": "OAuth", + "auth.cli": "CLI", + "auth.gcloud": "gcloud", + "auth.cookies": "Cookies", + "auth.cookiesGo": "Cookies + Go", + "auth.deviceFlow": "Device flow", + "auth.bearerLocal": "Bearer / Local", + "auth.apiKey": "API key", + "auth.token": "Token", + "auth.legacyApi": "Legacy API", + "auth.local": "Local", + "auth.apiKeyCookies": "API key + Cookies", + "auth.virtualKey": "Virtual key", + "showcase.alt": "CodexBar menubalkpopover met providertegels met gebruiksbalken, aftellingen voor resetten en kredietgegevens.", + "features.resetsTitle": "Resets die u kunt plannen", + "features.resetsBody": "Per sessie, wekelijkse en maandelijkse vensters per provider met aftelling naar de volgende reset - u hoeft niet meer te raden of u aan een lange taak moet beginnen.", + "features.spendTitle": "Credits, uitgaven en kostenscans", + "features.spendBody": "Tegoeden en maandelijkse uitgaven waar de provider deze openbaar maakt, plus configureerbare lokale kostenscans voor Codex en Claude.", + "features.statusTitle": "Status & incidenten", + "features.statusBody": "Bij het peilen van de providerstatus worden incidentbadges in het menu en een indicator-overlay op het balkpictogram weergegeven.", + "features.cliTitle": "CLI en widgets", + "features.cliBody": "WidgetKit widgets voor ondersteunde providers en een gebundelde {codexbar} CLI voor scripts en CI — macOS en Linux bouwt voort op elke release.", + "detail.installTitle": "Installeren en bijwerken", + "detail.installBody": "Universele app via {releases} met automatische Sparkle-updates, of via {cask} (updates met {upgrade}).", + "detail.cliTitle": "CLI", + "detail.cliBody": "Een gebundeld binair {codexbar}-bestand plus zelfstandige tarballs voor macOS en Linux bij elke release. Op Linux: {linuxCommand}.", + "detail.privacyTitle": "Privacy", + "detail.privacyBody": "Hergebruik bestaande providersessies (OAuth, apparaatstroom, API-sleutels, browsercookies, lokale bestanden) zodat er geen wachtwoorden worden opgeslagen. Controlenotities in {issue}.", + "detail.permissionsTitle": "macOS rechten", + "detail.permissionsBody": "Volledige schijftoegang voor Safari-cookies, Keychain-toegang voor het decoderen van cookies en OAuth-stromen, en aanwijzingen voor Bestanden en mappen wanneer helpers van de provider projectmappen lezen.", + "footer.builtBy": "Gebouwd door", + "footer.changelog": "Wijzigingslog", + "clipboard.copy": "Kopiëren naar klembord", + "clipboard.copied": "Gekopieerd", + "nav.home": "CodexBar-start", + "nav.projectLinks": "Projectlinks", + "nav.sourceGitHub": "CodexBar-bron op GitHub", + "nav.sourceStars": "bron", + "nav.displayDownload": "Weergave en download", + "clipboard.copyBrew": "Homebrew-installatieopdracht kopiëren", + "hero.badgeStart": "AI-gebruikslimieten", + "hero.badgeEnd": "voor macOS", + "hero.descriptionShort": "Volg gebruiksvensters, creditsaldi en reset-countdowns voor de AI-tools waarvoor je echt betaalt.", + "hero.fineprintShort": "Gratis en open source · macOS 14+", + "features.title": "Limieten,\u00a0uitgaven en status", + "mockup.openPanelAria": "CodexBar geopend in de macOS-menubalk", + "mockup.macbookAlt": "MacBook-menubalk", + "mockup.menuBarAria": "macOS-menubalkstatusitems", + "mockup.menuIconAria": "CodexBar-menubalkicoon", + "mockup.usagePanelAria": "CodexBar-gebruikspaneel openen", + "mockup.updatedJustNow": "Zojuist bijgewerkt", + "mockup.plus": "Plus", + "mockup.session": "Sessie", + "mockup.weekly": "Wekelijks", + "mockup.left60": "60% over", + "mockup.left73": "73% over", + "mockup.left89": "89% over", + "mockup.left98": "98% over", + "mockup.reserve2": "2% in reserve", + "mockup.reserve5": "5% in reserve", + "mockup.onPace": "Op schema", + "mockup.resets2h53m": "Reset over 2u 53m", + "mockup.resets4h12m": "Reset over 4u 12m", + "mockup.resets5d4h": "Reset over 5d 4u", + "mockup.resets6d23h": "Reset over 6d 23u", + "mockup.runsOut4d21h": "Op over 4d 21u", + "mockup.lastsUntilReset": "Houdt tot reset", + "mockup.limitResetCredits": "Limiet-resetcredits", + "mockup.nextExpires28d2h": "Volgende verloopt over 28d 2u", + "mockup.nextExpires27d21h": "Volgende verloopt over 27d 21u", + "mockup.manualResetAvailable": "1 reset beschikbaar", + "mockup.recentUsageAria": "Recent Codex-gebruik", + "mockup.today": "Vandaag", + "mockup.last31DaysCost": "Kosten laatste 31 dagen", + "mockup.last31DaysTokens": "Tokens laatste 31 dagen", + "mockup.latestTokens": "Nieuwste tokens", + "mockup.usageChartAria": "31-daagse gebruiksgrafiek", + "mockup.topModel": "Topmodel: Example-1", + "mockup.estimatedLogs": "Geschat uit lokale Codex-logs voor het geselecteerde account...", + "mockup.credits": "Credits", + "mockup.zeroLeft": "0 over", + "mockup.buyCredits": "Credits kopen...", + "mockup.partialDegradation": "Gedeeltelijke degradatie", + "mockup.twoIncidents": "2 incidenten", + "mockup.majorOutage": "Grote storing", + "mockup.degraded": "Gedegradeerd", + "mockup.operational": "Operationeel", + "cli.outputPreviewAria": "Voorbeeld van CodexBar CLI-uitvoer", + "cli.left99": "99% over", + "cli.left100": "100% over", + "cli.left79": "79% over", + "cli.left74": "74% over", + "cli.resets5h": "Reset over 5u", + "cli.resets7d": "Reset over 7d", + "cli.resets23d18h": "Reset over 23d 18u", + "cli.available1": "1 beschikbaar", + "cli.nextResetCredit": "Volgende resetcredit", + "cli.expires27d22h": "verloopt over 27d 22u", + "cli.account": "Account", + "cli.plan": "Plan", + "cli.total": "Totaal", + "cli.auto": "Auto", + "cli.titleLine2": "in CLI", + "cli.lead": "Een meegeleverde {codexbar}-binary met dezelfde gebruiksuitvoer als de menubalk — scripts, CI en snelle terminalchecks.", + "cli.note": "Losse tarballs voor macOS en Linux bij elke release.", + "cli.privacy": "CodexBar hergebruikt bestaande providersessies — er worden geen wachtwoorden op schijf opgeslagen.", + "widgets.titleLine2": "widgets", + "widgets.lead": "WidgetKit-widgets voor ondersteunde providers — gebruiksvensters, reset-countdowns en uitgaven waar beschikbaar. Zet ze op je beginscherm en bureaublad.", + "widgets.note": "Klein, middelgroot en groot. Wissel providers zonder de widget te verlaten.", + "widgets.galleryAria": "macOS-widgetgalerijvoorbeeld", + "widgets.categoriesAria": "Widgetcategorieën", + "widgets.allWidgets": "Alle widgets", + "widgets.metricCaption": "Compacte widget voor credits of kosten.", + "widgets.historyCaption": "Gebruiksgeschiedenisgrafiek met recente totalen.", + "widgets.usageCaption": "Sessie- en weekgebruik met credits en kosten.", + "widgets.switcherCaption": "Gebruikswidget met providerwisselaar.", + "widgets.burndownCaption": "Resterend budget vergeleken met een ideaal constant verbruik.", + "widgets.burndownCombinedCaption": "Sessie- en week-burndowngrafieken in één tegel.", + "widgets.dragToDesktop": "Sleep een widget naar het bureaublad…", + "detail.more": "Meer" + }, + "tr": { + "meta.title": "CodexBar — menü çubuğunuzdaki tüm AI kodlama limitleri", + "meta.description": "AI kodlama sağlayıcısı kullanım pencerelerini, kredilerini, maliyetlerini izleyen ve Codex, OpenAI, Claude, Cursor, Gemini, Copilot, LiteLLM ve daha fazlası olmak üzere 59 sağlayıcı genelinde sıfırlamaları izleyen küçük bir macOS menü çubuğu uygulaması.", + "meta.ogDescription": "macOS menü çubuğunu kullanarak 59 AI kodlama sağlayıcısındaki kullanım pencerelerini, kredileri ve sıfırlamaları izleyin.", + "nav.primary": "Öncelik", + "nav.language": "Dil", + "nav.docs": "Dokümanlar", + "nav.source": "Kaynak", + "nav.download": "İndirmek", + "theme.toLight": "Açık temaya geç", + "theme.toDark": "Koyu temaya geç", + "hero.prefix": "Her AI kodlama sınırı,", + "hero.accent": "Menü çubuğunuzda.", + "hero.description": "CodexBar, gerçekte ödeme yaptığınız sağlayıcılar genelinde kullanım pencerelerini, kredi bakiyelerini ve geri sayımları sıfırlar (her biri bir durum öğesi olacak şekilde) izler veya bunları tek bir öğede birleştirir.", + "hero.download": "macOS için indirin", + "hero.fineprint": "Ücretsiz ve açık kaynak · macOS 14+ · GitHub Releases ve Homebrew ile evrensel sürüm", + "providers.title": "59 sağlayıcı,{mobileBreak}bir menü çubuğu", + "providers.description": "Popüler sağlayıcılar, kendi kullanım pencereleri, sıfırlama geri sayımları, çizelgeleri ve sağlayıcı menüleriyle durum öğeleri haline gelir.", + "providers.yourProvider": "Sağlayıcınız", + "providers.authoringGuide": "Yazma kılavuzu", + "auth.oauth": "OAuth", + "auth.cli": "CLI", + "auth.gcloud": "gcloud", + "auth.cookies": "Cookies", + "auth.cookiesGo": "Cookies + Go", + "auth.deviceFlow": "Device flow", + "auth.bearerLocal": "Bearer / Local", + "auth.apiKey": "API key", + "auth.token": "Token", + "auth.legacyApi": "Legacy API", + "auth.local": "Local", + "auth.apiKeyCookies": "API key + Cookies", + "auth.virtualKey": "Virtual key", + "showcase.alt": "Kullanım çubukları, sıfırlama geri sayımları ve kredi ayrıntılarını içeren sağlayıcı kutucuklarını gösteren CodexBar menü çubuğu açılır penceresi.", + "features.resetsTitle": "Planlayabileceğiniz sıfırlamalar", + "features.resetsBody": "Sağlayıcı başına oturum, haftalık ve aylık pencereler ile bir sonraki sıfırlama için geri sayımlar; artık uzun bir göreve başlayıp başlamayacağınızı tahmin etmenize gerek yok.", + "features.spendTitle": "Krediler, harcama ve maliyet taramaları", + "features.spendBody": "Sağlayıcının sunduğu kredi bakiyeleri ve aylık harcamaların yanı sıra Codex ve Claude için yapılandırılabilir yerel maliyet taramaları.", + "features.statusTitle": "Durum ve olaylar", + "features.statusBody": "Sağlayıcı durum anketi, menüdeki olay rozetlerini ve çubuk simgesinin üzerinde bir gösterge katmanını gösterir.", + "features.cliTitle": "CLI ve widget'lar", + "features.cliBody": "Desteklenen sağlayıcılar için WidgetKit widget'ları ve komut dosyaları için paket halinde bir {codexbar} CLI ve her sürümde CI — macOS ve Linux derlemeleri.", + "detail.installTitle": "Yükleme ve güncellemeler", + "detail.installBody": "Sparkle otomatik güncellemeli evrensel uygulamayı {releases} üzerinden veya {cask} ile kurun ({upgrade} ile güncellenir).", + "detail.cliTitle": "CLI", + "detail.cliBody": "Her sürümde macOS ve Linux için paketlenmiş bir {codexbar} ikili programı ve bağımsız tarball'lar. Linux üzerinde: {linuxCommand}.", + "detail.privacyTitle": "Mahremiyet", + "detail.privacyBody": "Mevcut sağlayıcı oturumlarını (OAuth, cihaz akışı, API anahtarları, tarayıcı çerezleri, yerel dosyalar) yeniden kullanır, böylece hiçbir şifre saklanmaz. {issue} içindeki denetim notları.", + "detail.permissionsTitle": "macOS izinleri", + "detail.permissionsBody": "Safari çerezleri için Tam Disk Erişimi, çerez şifre çözme ve OAuth akışları için Keychain erişimi ve Dosyalar ve Klasörler, sağlayıcı yardımcıları proje dizinlerini okuduğunda istemde bulunur.", + "footer.builtBy": "Tarafından inşa edildi", + "footer.changelog": "Değişiklik günlüğü", + "clipboard.copy": "Panoya kopyala", + "clipboard.copied": "Kopyalandı", + "nav.home": "CodexBar ana sayfası", + "nav.projectLinks": "Proje bağlantıları", + "nav.sourceGitHub": "GitHub’da CodexBar kaynağı", + "nav.sourceStars": "kaynak", + "nav.displayDownload": "Görünüm ve indirme", + "clipboard.copyBrew": "Homebrew kurulum komutunu kopyala", + "hero.badgeStart": "AI kullanım limitleri", + "hero.badgeEnd": "macOS için", + "hero.descriptionShort": "Gerçekten ödeme yaptığın AI araçlarında kullanım pencerelerini, kredi bakiyelerini ve sıfırlama geri sayımlarını takip et.", + "hero.fineprintShort": "Ücretsiz ve açık kaynak · macOS 14+", + "features.title": "Limitler,\u00a0harcama ve durum", + "mockup.openPanelAria": "CodexBar macOS menü çubuğunda açık", + "mockup.macbookAlt": "MacBook menü çubuğu", + "mockup.menuBarAria": "macOS menü çubuğu durum öğeleri", + "mockup.menuIconAria": "CodexBar menü çubuğu simgesi", + "mockup.usagePanelAria": "CodexBar kullanım panelini aç", + "mockup.updatedJustNow": "Az önce güncellendi", + "mockup.plus": "Plus", + "mockup.session": "Oturum", + "mockup.weekly": "Haftalık", + "mockup.left60": "%60 kaldı", + "mockup.left73": "%73 kaldı", + "mockup.left89": "%89 kaldı", + "mockup.left98": "%98 kaldı", + "mockup.reserve2": "%2 yedekte", + "mockup.reserve5": "%5 yedekte", + "mockup.onPace": "Planında", + "mockup.resets2h53m": "2sa 53dk sonra sıfırlanır", + "mockup.resets4h12m": "4sa 12dk sonra sıfırlanır", + "mockup.resets5d4h": "5g 4sa sonra sıfırlanır", + "mockup.resets6d23h": "6g 23sa sonra sıfırlanır", + "mockup.runsOut4d21h": "4g 21sa sonra biter", + "mockup.lastsUntilReset": "Sıfırlamaya kadar yeter", + "mockup.limitResetCredits": "Limit sıfırlama kredileri", + "mockup.nextExpires28d2h": "Sonraki 28g 2sa içinde sona erer", + "mockup.nextExpires27d21h": "Sonraki 27g 21sa içinde sona erer", + "mockup.manualResetAvailable": "1 sıfırlama kullanılabilir", + "mockup.recentUsageAria": "Son Codex kullanımı", + "mockup.today": "Bugün", + "mockup.last31DaysCost": "Son 31 gün maliyeti", + "mockup.last31DaysTokens": "Son 31 gün tokenları", + "mockup.latestTokens": "En son tokenlar", + "mockup.usageChartAria": "31 günlük kullanım grafiği", + "mockup.topModel": "En iyi model: Example-1", + "mockup.estimatedLogs": "Seçili hesap için yerel Codex günlüklerinden tahmini...", + "mockup.credits": "Krediler", + "mockup.zeroLeft": "0 kaldı", + "mockup.buyCredits": "Kredi satın al...", + "mockup.partialDegradation": "Kısmi bozulma", + "mockup.twoIncidents": "2 olay", + "mockup.majorOutage": "Büyük kesinti", + "mockup.degraded": "Bozulmuş", + "mockup.operational": "Çalışıyor", + "cli.outputPreviewAria": "CodexBar CLI çıktı önizlemesi", + "cli.left99": "%99 kaldı", + "cli.left100": "%100 kaldı", + "cli.left79": "%79 kaldı", + "cli.left74": "%74 kaldı", + "cli.resets5h": "5sa sonra sıfırlanır", + "cli.resets7d": "7g sonra sıfırlanır", + "cli.resets23d18h": "23g 18sa sonra sıfırlanır", + "cli.available1": "1 kullanılabilir", + "cli.nextResetCredit": "Sonraki sıfırlama kredisi", + "cli.expires27d22h": "27g 22sa içinde sona erer", + "cli.account": "Hesap", + "cli.plan": "Plan", + "cli.total": "Toplam", + "cli.auto": "Otomatik", + "cli.titleLine2": "CLI’da", + "cli.lead": "Menü çubuğuyla aynı kullanım çıktısını veren gömülü bir {codexbar} ikilisi — scriptler, CI ve hızlı terminal kontrolleri için.", + "cli.note": "Her sürümde macOS ve Linux için bağımsız tarball’lar.", + "cli.privacy": "CodexBar mevcut sağlayıcı oturumlarını yeniden kullanır — diskte parola saklanmaz.", + "widgets.titleLine2": "widgetlar", + "widgets.lead": "Desteklenen sağlayıcılar için WidgetKit widgetları — kullanım pencereleri, sıfırlama geri sayımları ve varsa harcama. Ana ekrana ve masaüstüne bırak.", + "widgets.note": "Küçük, orta ve büyük boyutlar. Widget’tan çıkmadan sağlayıcı değiştir.", + "widgets.galleryAria": "macOS widget galerisi önizlemesi", + "widgets.categoriesAria": "Widget kategorileri", + "widgets.allWidgets": "Tüm widgetlar", + "widgets.metricCaption": "Kredi veya maliyet için kompakt widget.", + "widgets.historyCaption": "Yakın toplamlarla kullanım geçmişi grafiği.", + "widgets.usageCaption": "Kredi ve maliyetlerle oturum ve haftalık kullanım.", + "widgets.switcherCaption": "Sağlayıcı değiştiricili kullanım widgetı.", + "widgets.burndownCaption": "Kalan bütçenin ideal sabit tüketim hızıyla karşılaştırması.", + "widgets.burndownCombinedCaption": "Oturum ve haftalık burn-down grafikleri tek kutuda.", + "widgets.dragToDesktop": "Bir widgetı masaüstüne sürükle…", + "detail.more": "Daha fazla" + }, + "uk": { + "meta.title": "CodexBar — кожне обмеження кодування AI у вашій панелі меню", + "meta.description": "Маленький додаток macOS на панелі меню, який відстежує вікна використання постачальників кодування штучного інтелекту, кредити, витрати та скидання 59 постачальників — Codex, OpenAI, Claude, Cursor, Gemini, Copilot, LiteLLM тощо.", + "meta.ogDescription": "Відстежуйте вікна використання, кредити та скидання 59 постачальників кодування ШІ за допомогою панелі меню macOS.", + "nav.primary": "Первинний", + "nav.language": "Мова", + "nav.docs": "документи", + "nav.source": "Джерело", + "nav.download": "Завантажити", + "theme.toLight": "Переключитися на світлу тему", + "theme.toDark": "Переключитися на темну тему", + "hero.prefix": "Кожен ліміт кодування ШІ,", + "hero.accent": "у панелі меню.", + "hero.description": "CodexBar відстежує вікна використання, кредитні баланси та скидає зворотний відлік для постачальників, за яких ви фактично платите, — по одному статусу для кожного або об’єднує їх в один.", + "hero.download": "Завантажити для macOS", + "hero.fineprint": "Безкоштовний і відкритий код · macOS 14+ · Універсальна версія через GitHub Releases і Homebrew", + "providers.title": "59 провайдерів,{mobileBreak}одна панель меню", + "providers.description": "Популярні постачальники стають елементами статусу з власними вікнами використання, скиданням зворотного відліку, діаграмами та меню постачальників.", + "providers.yourProvider": "Ваш провайдер", + "providers.authoringGuide": "Авторський посібник", + "auth.oauth": "OAuth", + "auth.cli": "CLI", + "auth.gcloud": "gcloud", + "auth.cookies": "Cookies", + "auth.cookiesGo": "Cookies + Go", + "auth.deviceFlow": "Device flow", + "auth.bearerLocal": "Bearer / Local", + "auth.apiKey": "API key", + "auth.token": "Token", + "auth.legacyApi": "Legacy API", + "auth.local": "Local", + "auth.apiKeyCookies": "API key + Cookies", + "auth.virtualKey": "Virtual key", + "showcase.alt": "CodexBar спливаюче вікно панелі меню, що показує плитки постачальника зі смужками використання, зворотним відліком скидання та деталями кредиту.", + "features.resetsTitle": "Скидання, які ви можете планувати", + "features.resetsBody": "Сеанси для кожного постачальника, тижневі та місячні вікна зі зворотним відліком до наступного скидання — більше не потрібно гадати, чи починати довге завдання.", + "features.spendTitle": "Сканування кредитів, витрат і витрат", + "features.spendBody": "Кредитні баланси та щомісячні витрати там, де їх показує постачальник, а також настроювані локальні сканування витрат для Codex і Claude.", + "features.statusTitle": "Статус та інциденти", + "features.statusBody": "Поверхні для опитування статусу постачальника показують значки в меню та накладення індикатора на піктограму панелі.", + "features.cliTitle": "CLI і віджети", + "features.cliBody": "Віджети WidgetKit для підтримуваних постачальників і пакет {codexbar} CLI для сценаріїв і CI — macOS і Linux будуються на кожному випуску.", + "detail.installTitle": "Встановлення та оновлення", + "detail.installBody": "Універсальний додаток через {releases} з автоматичними оновленнями Sparkle або через {cask} (оновлення за допомогою {upgrade}).", + "detail.cliTitle": "CLI", + "detail.cliBody": "Двійковий файл {codexbar} у комплекті, а також окремі архіви для macOS і Linux у кожному випуску. На Linux: {linuxCommand}.", + "detail.privacyTitle": "Конфіденційність", + "detail.privacyBody": "Повторно використовує існуючі сеанси постачальника — OAuth, потік пристрою, ключі API, файли cookie браузера, локальні файли — тому паролі не зберігаються. Аудиторські примітки в {issue}.", + "detail.permissionsTitle": "macOS дозволи", + "detail.permissionsBody": "Повний доступ до диска для файлів cookie Safari, доступ Keychain для розшифровки файлів cookie та потоків OAuth, а також підказки щодо файлів і папок, коли помічники постачальника читають каталоги проекту.", + "footer.builtBy": "Побудовано", + "footer.changelog": "Журнал змін", + "clipboard.copy": "Копіювати в буфер обміну", + "clipboard.copied": "Скопійовано", + "nav.home": "Домівка CodexBar", + "nav.projectLinks": "Посилання проєкту", + "nav.sourceGitHub": "Код CodexBar на GitHub", + "nav.sourceStars": "код", + "nav.displayDownload": "Вигляд і завантаження", + "clipboard.copyBrew": "Скопіювати команду встановлення Homebrew", + "hero.badgeStart": "Ліміти використання AI", + "hero.badgeEnd": "для macOS", + "hero.descriptionShort": "Відстежуйте вікна використання, баланси кредитів і відлік до скидання в AI-інструментах, за які ви справді платите.", + "hero.fineprintShort": "Безкоштовно й open source · macOS 14+", + "features.title": "Ліміти,\u00a0витрати й статус", + "mockup.openPanelAria": "CodexBar відкрито в рядку меню macOS", + "mockup.macbookAlt": "Рядок меню MacBook", + "mockup.menuBarAria": "Елементи статусу рядка меню macOS", + "mockup.menuIconAria": "Іконка CodexBar у рядку меню", + "mockup.usagePanelAria": "Відкрити панель використання CodexBar", + "mockup.updatedJustNow": "Щойно оновлено", + "mockup.plus": "Plus", + "mockup.session": "Сесія", + "mockup.weekly": "Щотижня", + "mockup.left60": "залишилось 60%", + "mockup.left73": "залишилось 73%", + "mockup.left89": "залишилось 89%", + "mockup.left98": "залишилось 98%", + "mockup.reserve2": "2% у резерві", + "mockup.reserve5": "5% у резерві", + "mockup.onPace": "За планом", + "mockup.resets2h53m": "Скидання через 2 год 53 хв", + "mockup.resets4h12m": "Скидання через 4 год 12 хв", + "mockup.resets5d4h": "Скидання через 5 д 4 год", + "mockup.resets6d23h": "Скидання через 6 д 23 год", + "mockup.runsOut4d21h": "Закінчиться через 4 д 21 год", + "mockup.lastsUntilReset": "Вистачить до скидання", + "mockup.limitResetCredits": "Кредити скидання ліміту", + "mockup.nextExpires28d2h": "Наступний спливає через 28 д 2 год", + "mockup.nextExpires27d21h": "Наступний спливає через 27 д 21 год", + "mockup.manualResetAvailable": "Доступне 1 скидання", + "mockup.recentUsageAria": "Нещодавнє використання Codex", + "mockup.today": "Сьогодні", + "mockup.last31DaysCost": "Вартість за останні 31 день", + "mockup.last31DaysTokens": "Токени за останні 31 день", + "mockup.latestTokens": "Останні токени", + "mockup.usageChartAria": "Графік використання за 31 день", + "mockup.topModel": "Топмодель: Example-1", + "mockup.estimatedLogs": "Оцінено з локальних журналів Codex для вибраного акаунта...", + "mockup.credits": "Кредити", + "mockup.zeroLeft": "залишилось 0", + "mockup.buyCredits": "Купити кредити...", + "mockup.partialDegradation": "Часткова деградація", + "mockup.twoIncidents": "2 інциденти", + "mockup.majorOutage": "Серйозний збій", + "mockup.degraded": "Погіршено", + "mockup.operational": "Працює", + "cli.outputPreviewAria": "Попередній перегляд виводу CodexBar CLI", + "cli.left99": "залишилось 99%", + "cli.left100": "залишилось 100%", + "cli.left79": "залишилось 79%", + "cli.left74": "залишилось 74%", + "cli.resets5h": "Скидання через 5 год", + "cli.resets7d": "Скидання через 7 д", + "cli.resets23d18h": "Скидання через 23 д 18 год", + "cli.available1": "1 доступний", + "cli.nextResetCredit": "Наступний кредит скидання", + "cli.expires27d22h": "спливає через 27 д 22 год", + "cli.account": "Акаунт", + "cli.plan": "План", + "cli.total": "Усього", + "cli.auto": "Авто", + "cli.titleLine2": "у CLI", + "cli.lead": "Вбудований бінарник {codexbar} з таким самим виводом використання, як у рядку меню — для скриптів, CI та швидких перевірок у терміналі.", + "cli.note": "Окремі tarball для macOS і Linux у кожному релізі.", + "cli.privacy": "CodexBar повторно використовує наявні сесії провайдерів — паролі не зберігаються на диску.", + "widgets.titleLine2": "віджети", + "widgets.lead": "WidgetKit-віджети для підтримуваних провайдерів — вікна використання, відлік до скидання та витрати, якщо доступні. Розмістіть їх на початковому екрані та робочому столі.", + "widgets.note": "Малі, середні й великі розміри. Перемикайте провайдерів, не виходячи з віджета.", + "widgets.galleryAria": "Попередній перегляд галереї віджетів macOS", + "widgets.categoriesAria": "Категорії віджетів", + "widgets.allWidgets": "Усі віджети", + "widgets.metricCaption": "Компактний віджет для кредитів або вартості.", + "widgets.historyCaption": "Графік історії використання з останніми підсумками.", + "widgets.usageCaption": "Сесійне й тижневе використання з кредитами та витратами.", + "widgets.switcherCaption": "Віджет використання з перемикачем провайдера.", + "widgets.burndownCaption": "Залишок бюджету порівняно з ідеальним рівномірним темпом витрат.", + "widgets.burndownCombinedCaption": "Сесійний і тижневий burn-down в одній плитці.", + "widgets.dragToDesktop": "Перетягніть віджет на робочий стіл…", + "detail.more": "Більше" + }, + "ru": { + "meta.title": "CodexBar — все лимиты AI-кодинга в вашей строке меню", + "meta.description": "Небольшое приложение для строки меню macOS, которое отслеживает окна использования, кредиты, расходы и сбросы лимитов у 59 AI-провайдеров для кодинга — Codex, OpenAI, Claude, Cursor, Gemini, Copilot, LiteLLM и других.", + "meta.ogDescription": "Отслеживайте окна использования, кредиты и сбросы лимитов у 59 AI-провайдеров для кодинга прямо из строки меню macOS.", + "nav.primary": "Основная навигация", + "nav.language": "Язык", + "nav.docs": "Документация", + "nav.source": "Исходный код", + "nav.download": "Скачать", + "theme.toLight": "Переключиться на светлую тему", + "theme.toDark": "Переключиться на темную тему", + "hero.prefix": "Все лимиты AI-кодинга,", + "hero.accent": "в строке меню.", + "hero.description": "CodexBar отслеживает окна использования, балансы кредитов и обратный отсчет до сброса у провайдеров, за которых вы действительно платите, — по одному элементу статуса на каждого или все вместе в одном.", + "hero.download": "Скачать для macOS", + "hero.fineprint": "Бесплатно и с открытым исходным кодом · macOS 14+ · универсальная сборка через GitHub Releases и Homebrew", + "providers.title": "59 провайдеров,{mobileBreak}одна строка меню", + "providers.description": "Популярные провайдеры становятся элементами статуса со своими окнами использования, обратным отсчетом до сброса, графиками и меню провайдера.", + "providers.yourProvider": "Ваш провайдер", + "providers.authoringGuide": "Руководство по добавлению", + "auth.cookies": "Cookie", + "auth.cookiesGo": "Cookie + Go", + "auth.deviceFlow": "Device flow", + "auth.bearerLocal": "Bearer / Local", + "auth.apiKey": "API-ключ", + "auth.token": "Токен", + "auth.legacyApi": "Старый API", + "auth.local": "Локально", + "auth.apiKeyCookies": "API-ключ + Cookie", + "auth.virtualKey": "Виртуальный ключ", + "showcase.alt": "Поповер CodexBar в строке меню с плитками провайдеров, индикаторами использования, обратным отсчетом до сброса и данными о кредитах.", + "features.resetsTitle": "Сбросы, которые можно планировать", + "features.resetsBody": "Сессионные, недельные и месячные окна по каждому провайдеру с обратным отсчетом до следующего сброса — больше не нужно гадать, стоит ли начинать долгую задачу.", + "features.spendTitle": "Кредиты, расходы и сканирование стоимости", + "features.spendBody": "Балансы кредитов и месячные расходы там, где провайдер их показывает, плюс настраиваемое локальное сканирование стоимости для Codex и Claude.", + "features.statusTitle": "Статус и инциденты", + "features.statusBody": "Опрос статуса провайдеров показывает бейджи инцидентов в меню и индикатор поверх значка в строке меню.", + "features.cliTitle": "CLI и виджеты", + "features.cliBody": "Виджеты WidgetKit для поддерживаемых провайдеров и встроенный CLI {codexbar} для скриптов и CI — сборки для macOS и Linux в каждом релизе.", + "detail.installTitle": "Установка и обновления", + "detail.installBody": "Универсальное приложение через {releases} с автообновлениями Sparkle или через {cask} (обновления через {upgrade}).", + "detail.cliTitle": "CLI", + "detail.cliBody": "Встроенный бинарный файл {codexbar} плюс отдельные tarball-архивы для macOS и Linux в каждом релизе. В Linux: {linuxCommand}.", + "detail.privacyTitle": "Конфиденциальность", + "detail.privacyBody": "Повторно использует существующие сессии провайдеров — OAuth, device flow, API-ключи, cookie браузера, локальные файлы — поэтому пароли не сохраняются. Примечания аудита в {issue}.", + "detail.permissionsTitle": "Разрешения macOS", + "detail.permissionsBody": "Полный доступ к диску для cookie Safari, доступ к Keychain для расшифровки cookie и OAuth-потоков, а также запросы «Файлы и папки», когда вспомогательные процессы провайдеров читают каталоги проектов.", + "footer.builtBy": "Создал", + "footer.changelog": "История изменений", + "clipboard.copy": "Скопировать в буфер обмена", + "clipboard.copied": "Скопировано", + "auth.oauth": "OAuth", + "auth.cli": "CLI", + "auth.gcloud": "gcloud", + "nav.home": "Главная CodexBar", + "nav.projectLinks": "Ссылки проекта", + "nav.sourceGitHub": "Исходный код CodexBar на GitHub", + "nav.sourceStars": "исходный код", + "nav.displayDownload": "Отображение и загрузка", + "clipboard.copyBrew": "Скопировать команду установки Homebrew", + "hero.badgeStart": "Лимиты использования AI", + "hero.badgeEnd": "для macOS", + "hero.descriptionShort": "Отслеживайте окна использования, балансы кредитов и время до сброса лимитов в AI-инструментах, за которые вы платите.", + "hero.fineprintShort": "Бесплатно и с открытым исходным кодом · macOS 14+", + "features.title": "Лимиты,\u00a0расходы\u00a0и статус", + "mockup.openPanelAria": "CodexBar открыт в строке меню macOS", + "mockup.macbookAlt": "Строка меню MacBook", + "mockup.menuBarAria": "Элементы статуса в строке меню macOS", + "mockup.menuIconAria": "Значок CodexBar в строке меню", + "mockup.usagePanelAria": "Открытая панель использования CodexBar", + "mockup.updatedJustNow": "Обновлено только что", + "mockup.plus": "Plus", + "mockup.session": "Сессия", + "mockup.weekly": "Неделя", + "mockup.left60": "Осталось 60%", + "mockup.left73": "Осталось 73%", + "mockup.left89": "Осталось 89%", + "mockup.left98": "Осталось 98%", + "mockup.reserve2": "2% в резерве", + "mockup.reserve5": "5% в резерве", + "mockup.onPace": "По плану", + "mockup.resets2h53m": "Сброс через 2 ч 53 мин", + "mockup.resets4h12m": "Сброс через 4 ч 12 мин", + "mockup.resets5d4h": "Сброс через 5 д 4 ч", + "mockup.resets6d23h": "Сброс через 6 д 23 ч", + "mockup.runsOut4d21h": "Закончится через 4 д 21 ч", + "mockup.lastsUntilReset": "Хватит до сброса", + "mockup.limitResetCredits": "Кредиты сброса лимита", + "mockup.nextExpires28d2h": "Следующий истекает через 28 д 2 ч", + "mockup.nextExpires27d21h": "Следующий истекает через 27 д 21 ч", + "mockup.manualResetAvailable": "Доступен 1 сброс", + "mockup.recentUsageAria": "Недавнее использование Codex", + "mockup.today": "Сегодня", + "mockup.last31DaysCost": "Расходы за 31 день", + "mockup.last31DaysTokens": "Токены за 31 день", + "mockup.latestTokens": "Токены в последнем запросе", + "mockup.usageChartAria": "График использования за 31 день", + "mockup.topModel": "Основная модель: Example-1", + "mockup.estimatedLogs": "Оценка по локальным логам Codex для выбранного акка...", + "mockup.credits": "Кредиты", + "mockup.zeroLeft": "Осталось 0", + "mockup.buyCredits": "Купить кредиты...", + "mockup.partialDegradation": "Частичное ухудшение", + "mockup.twoIncidents": "2 инцидента", + "mockup.majorOutage": "Серьёзный сбой", + "mockup.degraded": "Работает с перебоями", + "mockup.operational": "Работает нормально", + "cli.outputPreviewAria": "Предпросмотр вывода CLI CodexBar", + "cli.left99": "Осталось 99%", + "cli.left100": "Осталось 100%", + "cli.left79": "Осталось 79%", + "cli.left74": "Осталось 74%", + "cli.resets5h": "Сброс через 5 ч", + "cli.resets7d": "Сброс через 7 д", + "cli.resets23d18h": "Сброс через 23 д 18 ч", + "cli.available1": "Доступен 1", + "cli.nextResetCredit": "Следующий кредит сброса", + "cli.expires27d22h": "истекает через 27 д 22 ч", + "cli.account": "Аккаунт", + "cli.plan": "Тариф", + "cli.total": "Всего", + "cli.auto": "Авто", + "cli.titleLine2": "в CLI", + "cli.lead": "Встроенный бинарный файл {codexbar} с теми же данными об использовании, что и в строке меню, — для скриптов, CI и быстрых проверок в терминале.", + "cli.note": "Отдельные tarball-архивы для macOS и Linux в каждом релизе.", + "cli.privacy": "CodexBar повторно использует существующие сессии провайдеров — пароли не сохраняются на диске.", + "widgets.titleLine2": "виджеты", + "widgets.lead": "Виджеты WidgetKit для поддерживаемых провайдеров: окна использования, время до сброса и расходы, если они доступны. Разместите их на экране «Домой» или рабочем столе.", + "widgets.note": "Малый, средний и большой размеры. Переключайте провайдеров, не покидая виджет.", + "widgets.galleryAria": "Предпросмотр галереи виджетов macOS", + "widgets.categoriesAria": "Категории виджетов", + "widgets.allWidgets": "Все виджеты", + "widgets.metricCaption": "Компактный виджет для кредитов или расходов.", + "widgets.historyCaption": "График истории использования с последними итогами.", + "widgets.usageCaption": "Сессионное и недельное использование с кредитами и расходами.", + "widgets.switcherCaption": "Виджет использования с переключателем провайдеров.", + "widgets.burndownCaption": "Оставшийся бюджет в сравнении с идеальным равномерным темпом расходования.", + "widgets.burndownCombinedCaption": "Графики расходования сессионного и недельного лимитов в одной плитке.", + "widgets.dragToDesktop": "Перетащите виджет на рабочий стол…", + "detail.more": "Подробнее" + }, + "id": { + "meta.title": "CodexBar — setiap batas pengkodean AI di bilah menu Anda", + "meta.description": "Aplikasi bilah menu macOS kecil yang melacak periode penggunaan, kredit, biaya, dan penyetelan ulang penyedia pengkodean AI di 59 penyedia — Codex, OpenAI, Claude, Cursor, Gemini, Copilot, LiteLLM, dan banyak lagi.", + "meta.ogDescription": "Lacak jangka waktu penggunaan, kredit, dan penyetelan ulang di 59 penyedia pengkodean AI dari bilah menu macOS Anda.", + "nav.primary": "Utama", + "nav.language": "Bahasa", + "nav.docs": "dokumen", + "nav.source": "Sumber", + "nav.download": "Unduh", + "theme.toLight": "Beralih ke tema terang", + "theme.toDark": "Beralih ke tema gelap", + "hero.prefix": "Setiap batas pengkodean AI,", + "hero.accent": "di bilah menu Anda.", + "hero.description": "CodexBar melacak jangka waktu penggunaan, saldo kredit, dan hitungan mundur penyetelan ulang di seluruh penyedia yang sebenarnya Anda bayar — masing-masing satu item status, atau gabungkan menjadi satu.", + "hero.download": "Unduh untuk macOS", + "hero.fineprint": "Gratis dan sumber terbuka · macOS 14+ · Universal melalui GitHub Releases dan Homebrew", + "providers.title": "59 penyedia,{mobileBreak}satu bilah menu", + "providers.description": "Penyedia populer menjadi item status dengan jendela penggunaannya sendiri, hitung mundur pengaturan ulang, bagan, dan menu penyedia.", + "providers.yourProvider": "Penyedia Anda", + "providers.authoringGuide": "Panduan penulisan", + "auth.oauth": "OAuth", + "auth.cli": "CLI", + "auth.gcloud": "gcloud", + "auth.cookies": "Cookies", + "auth.cookiesGo": "Cookies + Go", + "auth.deviceFlow": "Device flow", + "auth.bearerLocal": "Bearer / Local", + "auth.apiKey": "API key", + "auth.token": "Token", + "auth.legacyApi": "Legacy API", + "auth.local": "Local", + "auth.apiKeyCookies": "API key + Cookies", + "auth.virtualKey": "Virtual key", + "showcase.alt": "CodexBar popover bilah menu menampilkan ubin penyedia dengan bilah penggunaan, hitungan mundur penyetelan ulang, dan detail kredit.", + "features.resetsTitle": "Penyetelan ulang dapat Anda rencanakan", + "features.resetsBody": "Sesi per penyedia, jendela mingguan, dan bulanan dengan hitungan mundur ke pengaturan ulang berikutnya — tidak perlu lagi menebak-nebak apakah akan memulai tugas yang panjang.", + "features.spendTitle": "Pemindaian kredit, pembelanjaan, dan biaya", + "features.spendBody": "Saldo kredit dan pembelanjaan bulanan di mana penyedia memaparkannya, ditambah pemindaian biaya lokal yang dapat dikonfigurasi untuk Codex dan Claude.", + "features.statusTitle": "Status & insiden", + "features.statusBody": "Jajak pendapat status penyedia menampilkan lencana insiden di menu dan hamparan indikator pada ikon bilah.", + "features.cliTitle": "CLI & widget", + "features.cliBody": "Widget WidgetKit untuk penyedia yang didukung dan paket {codexbar} CLI untuk skrip dan CI — macOS dan Linux dibuat pada setiap rilis.", + "detail.installTitle": "Instal & perbarui", + "detail.installBody": "Aplikasi universal melalui {releases} dengan pembaruan otomatis Sparkle, atau melalui {cask} (pembaruan dengan {upgrade}).", + "detail.cliTitle": "CLI", + "detail.cliBody": "Biner {codexbar} yang dibundel ditambah tarbal mandiri untuk macOS dan Linux pada setiap rilis. Pada Linux: {linuxCommand}.", + "detail.privacyTitle": "Pribadi", + "detail.privacyBody": "Menggunakan kembali sesi penyedia yang ada — OAuth, alur perangkat, kunci API, cookie browser, file lokal — sehingga tidak ada kata sandi yang disimpan. Catatan audit di {issue}.", + "detail.permissionsTitle": "izin macOS", + "detail.permissionsBody": "Akses Disk Penuh untuk cookie Safari, akses Keychain untuk dekripsi cookie dan alur OAuth, serta permintaan File & Folder saat pembantu penyedia membaca direktori proyek.", + "footer.builtBy": "Dibangun oleh", + "footer.changelog": "log perubahan", + "clipboard.copy": "Salin ke papan klip", + "clipboard.copied": "Disalin", + "nav.home": "Beranda CodexBar", + "nav.projectLinks": "Tautan proyek", + "nav.sourceGitHub": "Sumber CodexBar di GitHub", + "nav.sourceStars": "sumber", + "nav.displayDownload": "Tampilan dan unduhan", + "clipboard.copyBrew": "Salin perintah instal Homebrew", + "hero.badgeStart": "Batas penggunaan AI", + "hero.badgeEnd": "untuk macOS", + "hero.descriptionShort": "Lacak jendela penggunaan, saldo kredit, dan hitung mundur reset di alat AI yang benar-benar kamu bayar.", + "hero.fineprintShort": "Gratis dan open source · macOS 14+", + "features.title": "Batas,\u00a0biaya,\u00a0dan status", + "mockup.openPanelAria": "CodexBar terbuka di bilah menu macOS", + "mockup.macbookAlt": "Bilah menu MacBook", + "mockup.menuBarAria": "Item status bilah menu macOS", + "mockup.menuIconAria": "Ikon CodexBar di bilah menu", + "mockup.usagePanelAria": "Buka panel penggunaan CodexBar", + "mockup.updatedJustNow": "Baru saja diperbarui", + "mockup.plus": "Plus", + "mockup.session": "Sesi", + "mockup.weekly": "Mingguan", + "mockup.left60": "tersisa 60%", + "mockup.left73": "tersisa 73%", + "mockup.left89": "tersisa 89%", + "mockup.left98": "tersisa 98%", + "mockup.reserve2": "2% cadangan", + "mockup.reserve5": "5% cadangan", + "mockup.onPace": "Sesuai laju", + "mockup.resets2h53m": "Reset dalam 2j 53m", + "mockup.resets4h12m": "Reset dalam 4j 12m", + "mockup.resets5d4h": "Reset dalam 5h 4j", + "mockup.resets6d23h": "Reset dalam 6h 23j", + "mockup.runsOut4d21h": "Habis dalam 4h 21j", + "mockup.lastsUntilReset": "Bertahan sampai reset", + "mockup.limitResetCredits": "Kredit reset batas", + "mockup.nextExpires28d2h": "Berikutnya kedaluwarsa dalam 28h 2j", + "mockup.nextExpires27d21h": "Berikutnya kedaluwarsa dalam 27h 21j", + "mockup.manualResetAvailable": "1 reset tersedia", + "mockup.recentUsageAria": "Penggunaan Codex terbaru", + "mockup.today": "Hari ini", + "mockup.last31DaysCost": "Biaya 31 hari terakhir", + "mockup.last31DaysTokens": "Token 31 hari terakhir", + "mockup.latestTokens": "Token terbaru", + "mockup.usageChartAria": "Grafik penggunaan 31 hari", + "mockup.topModel": "Model teratas: Example-1", + "mockup.estimatedLogs": "Diperkirakan dari log Codex lokal untuk akun terpilih...", + "mockup.credits": "Kredit", + "mockup.zeroLeft": "tersisa 0", + "mockup.buyCredits": "Beli kredit...", + "mockup.partialDegradation": "Degradasi sebagian", + "mockup.twoIncidents": "2 insiden", + "mockup.majorOutage": "Gangguan besar", + "mockup.degraded": "Terdegradasi", + "mockup.operational": "Operasional", + "cli.outputPreviewAria": "Pratinjau keluaran CodexBar CLI", + "cli.left99": "tersisa 99%", + "cli.left100": "tersisa 100%", + "cli.left79": "tersisa 79%", + "cli.left74": "tersisa 74%", + "cli.resets5h": "Reset dalam 5j", + "cli.resets7d": "Reset dalam 7h", + "cli.resets23d18h": "Reset dalam 23h 18j", + "cli.available1": "1 tersedia", + "cli.nextResetCredit": "Kredit reset berikutnya", + "cli.expires27d22h": "kedaluwarsa dalam 27h 22j", + "cli.account": "Akun", + "cli.plan": "Paket", + "cli.total": "Total", + "cli.auto": "Otomatis", + "cli.titleLine2": "di CLI", + "cli.lead": "Binary {codexbar} bawaan dengan keluaran penggunaan yang sama seperti bilah menu — untuk skrip, CI, dan pemeriksaan terminal cepat.", + "cli.note": "Tarball mandiri untuk macOS dan Linux di setiap rilis.", + "cli.privacy": "CodexBar menggunakan ulang sesi penyedia yang sudah ada — tidak ada kata sandi yang disimpan di disk.", + "widgets.titleLine2": "widget", + "widgets.lead": "WidgetKit untuk penyedia yang didukung — jendela penggunaan, hitung mundur reset, dan biaya bila tersedia. Letakkan di Layar Utama dan desktop.", + "widgets.note": "Ukuran kecil, sedang, dan besar. Ganti penyedia tanpa keluar dari widget.", + "widgets.galleryAria": "Pratinjau galeri widget macOS", + "widgets.categoriesAria": "Kategori widget", + "widgets.allWidgets": "Semua Widget", + "widgets.metricCaption": "Widget ringkas untuk kredit atau biaya.", + "widgets.historyCaption": "Grafik riwayat penggunaan dengan total terbaru.", + "widgets.usageCaption": "Penggunaan sesi dan mingguan dengan kredit dan biaya.", + "widgets.switcherCaption": "Widget penggunaan dengan pengalih penyedia.", + "widgets.burndownCaption": "Sisa anggaran dibandingkan laju pemakaian stabil ideal.", + "widgets.burndownCombinedCaption": "Grafik burn-down sesi dan mingguan dalam satu tile.", + "widgets.dragToDesktop": "Seret widget ke desktop…", + "detail.more": "Lainnya" + }, + "pl": { + "meta.title": "CodexBar — każdy limit kodowania AI na pasku menu", + "meta.description": "Mała aplikacja z paskiem menu macOS, która śledzi okna użycia dostawcy kodowania AI, kredyty, koszty i resety u 59 dostawców — Codex, OpenAI, Claude, Cursor, Gemini, Copilot, LiteLLM i nie tylko.", + "meta.ogDescription": "Śledź okresy użytkowania, kredyty i resety u 59 dostawców kodowania AI za pomocą paska menu macOS.", + "nav.primary": "Podstawowy", + "nav.language": "Język", + "nav.docs": "Dokumenty", + "nav.source": "Źródło", + "nav.download": "Pobierać", + "theme.toLight": "Przełącz na jasny motyw", + "theme.toDark": "Przełącz na ciemny motyw", + "hero.prefix": "Każdy limit kodowania AI,", + "hero.accent": "na pasku menu.", + "hero.description": "CodexBar śledzi okna użytkowania, salda kredytów i resetuje odliczanie u dostawców, za których faktycznie płacisz — po jednym statusie dla każdego lub połącz je w jeden.", + "hero.download": "Pobierz dla macOS", + "hero.fineprint": "Darmowe i otwarte oprogramowanie · macOS 14+ · Wersja uniwersalna przez GitHub Releases i Homebrew", + "providers.title": "59 dostawców,{mobileBreak}jeden pasek menu", + "providers.description": "Popularni dostawcy stają się elementami statusu z własnymi oknami użytkowania, resetowaniem odliczania, wykresami i menu dostawców.", + "providers.yourProvider": "Twój dostawca", + "providers.authoringGuide": "Przewodnik autorski", + "auth.oauth": "OAuth", + "auth.cli": "CLI", + "auth.gcloud": "gcloud", + "auth.cookies": "Cookies", + "auth.cookiesGo": "Cookies + Go", + "auth.deviceFlow": "Device flow", + "auth.bearerLocal": "Bearer / Local", + "auth.apiKey": "API key", + "auth.token": "Token", + "auth.legacyApi": "Legacy API", + "auth.local": "Local", + "auth.apiKeyCookies": "API key + Cookies", + "auth.virtualKey": "Virtual key", + "showcase.alt": "Wyskakujący pasek menu CodexBar pokazujący kafelki dostawców z paskami użytkowania, resetowaniem odliczania i szczegółami kredytu.", + "features.resetsTitle": "Resety, które możesz zaplanować", + "features.resetsBody": "Sesja dla każdego dostawcy, okna tygodniowe i miesięczne z odliczaniem do następnego resetu — koniec z zastanawianiem się, czy rozpocząć długie zadanie.", + "features.spendTitle": "Skanowanie kredytów, wydatków i kosztów", + "features.spendBody": "Salda kredytowe i miesięczne wydatki tam, gdzie dostawca je udostępnia, a także konfigurowalne lokalne skanowanie kosztów dla Codexu i Claude.", + "features.statusTitle": "Stan i zdarzenia", + "features.statusBody": "Odpytywanie stanu dostawcy wyświetla w menu plakietki zdarzeń oraz nakładkę wskaźnika na ikonie paska.", + "features.cliTitle": "CLI i widżety", + "features.cliBody": "Widżety WidgetKit dla obsługiwanych dostawców oraz pakiet {codexbar} CLI dla skryptów i kompilacji CI — macOS i Linux w każdej wersji.", + "detail.installTitle": "Zainstaluj i aktualizuj", + "detail.installBody": "Aplikacja uniwersalna przez {releases} z automatycznymi aktualizacjami Sparkle lub przez {cask} (aktualizacje za pomocą {upgrade}).", + "detail.cliTitle": "CLI", + "detail.cliBody": "Dołączony plik binarny {codexbar} oraz samodzielne archiwum tar dla macOS i Linux w każdym wydaniu. W Linux: {linuxCommand}.", + "detail.privacyTitle": "Prywatność", + "detail.privacyBody": "Wykorzystuje ponownie istniejące sesje dostawcy — OAuth, przepływ urządzenia, klucze API, pliki cookie przeglądarki, pliki lokalne — dzięki czemu nie są przechowywane żadne hasła. Notatki z audytu w {issue}.", + "detail.permissionsTitle": "uprawnienia macOS", + "detail.permissionsBody": "Pełny dostęp do dysku dla plików cookie Safari, dostęp Keychain do odszyfrowywania plików cookie i przepływów OAuth oraz monit o pliki i foldery, gdy pomocnicy dostawcy czytają katalogi projektu.", + "footer.builtBy": "Zbudowany przez", + "footer.changelog": "Dziennik zmian", + "clipboard.copy": "Skopiuj do schowka", + "clipboard.copied": "Skopiowano", + "nav.home": "Strona główna CodexBar", + "nav.projectLinks": "Linki projektu", + "nav.sourceGitHub": "Kod CodexBar na GitHub", + "nav.sourceStars": "kod", + "nav.displayDownload": "Wygląd i pobieranie", + "clipboard.copyBrew": "Kopiuj polecenie instalacji Homebrew", + "hero.badgeStart": "Limity użycia AI", + "hero.badgeEnd": "dla macOS", + "hero.descriptionShort": "Śledź okna użycia, salda kredytów i odliczanie do resetu w narzędziach AI, za które naprawdę płacisz.", + "hero.fineprintShort": "Darmowe i open source · macOS 14+", + "features.title": "Limity,\u00a0wydatki i status", + "mockup.openPanelAria": "CodexBar otwarty na pasku menu macOS", + "mockup.macbookAlt": "Pasek menu MacBooka", + "mockup.menuBarAria": "Elementy statusu paska menu macOS", + "mockup.menuIconAria": "Ikona CodexBar na pasku menu", + "mockup.usagePanelAria": "Otwórz panel użycia CodexBar", + "mockup.updatedJustNow": "Zaktualizowano przed chwilą", + "mockup.plus": "Plus", + "mockup.session": "Sesja", + "mockup.weekly": "Tygodniowo", + "mockup.left60": "pozostało 60%", + "mockup.left73": "pozostało 73%", + "mockup.left89": "pozostało 89%", + "mockup.left98": "pozostało 98%", + "mockup.reserve2": "2% w rezerwie", + "mockup.reserve5": "5% w rezerwie", + "mockup.onPace": "Zgodnie z tempem", + "mockup.resets2h53m": "Reset za 2 godz. 53 min", + "mockup.resets4h12m": "Reset za 4 godz. 12 min", + "mockup.resets5d4h": "Reset za 5 d 4 godz.", + "mockup.resets6d23h": "Reset za 6 d 23 godz.", + "mockup.runsOut4d21h": "Skończy się za 4 d 21 godz.", + "mockup.lastsUntilReset": "Wystarczy do resetu", + "mockup.limitResetCredits": "Kredyty resetu limitu", + "mockup.nextExpires28d2h": "Następny wygasa za 28 d 2 godz.", + "mockup.nextExpires27d21h": "Następny wygasa za 27 d 21 godz.", + "mockup.manualResetAvailable": "Dostępny 1 reset", + "mockup.recentUsageAria": "Ostatnie użycie Codex", + "mockup.today": "Dzisiaj", + "mockup.last31DaysCost": "Koszt z ostatnich 31 dni", + "mockup.last31DaysTokens": "Tokeny z ostatnich 31 dni", + "mockup.latestTokens": "Najnowsze tokeny", + "mockup.usageChartAria": "Wykres użycia z 31 dni", + "mockup.topModel": "Główny model: Example-1", + "mockup.estimatedLogs": "Oszacowano z lokalnych logów Codex dla wybranego konta...", + "mockup.credits": "Kredyty", + "mockup.zeroLeft": "pozostało 0", + "mockup.buyCredits": "Kup kredyty...", + "mockup.partialDegradation": "Częściowa degradacja", + "mockup.twoIncidents": "2 incydenty", + "mockup.majorOutage": "Poważna awaria", + "mockup.degraded": "Pogorszone", + "mockup.operational": "Działa", + "cli.outputPreviewAria": "Podgląd wyjścia CodexBar CLI", + "cli.left99": "pozostało 99%", + "cli.left100": "pozostało 100%", + "cli.left79": "pozostało 79%", + "cli.left74": "pozostało 74%", + "cli.resets5h": "Reset za 5 godz.", + "cli.resets7d": "Reset za 7 d", + "cli.resets23d18h": "Reset za 23 d 18 godz.", + "cli.available1": "1 dostępny", + "cli.nextResetCredit": "Następny kredyt resetu", + "cli.expires27d22h": "wygasa za 27 d 22 godz.", + "cli.account": "Konto", + "cli.plan": "Plan", + "cli.total": "Razem", + "cli.auto": "Auto", + "cli.titleLine2": "w CLI", + "cli.lead": "Dołączony plik binarny {codexbar} z takim samym wyjściem użycia jak pasek menu — do skryptów, CI i szybkich kontroli w terminalu.", + "cli.note": "Samodzielne tarballe dla macOS i Linuxa w każdym wydaniu.", + "cli.privacy": "CodexBar ponownie używa istniejących sesji dostawców — hasła nie są zapisywane na dysku.", + "widgets.titleLine2": "widżety", + "widgets.lead": "Widgety WidgetKit dla obsługiwanych dostawców — okna użycia, odliczanie do resetu i wydatki, jeśli dostępne. Umieść je na ekranie początkowym i pulpicie.", + "widgets.note": "Małe, średnie i duże rozmiary. Przełączaj dostawców bez opuszczania widżetu.", + "widgets.galleryAria": "Podgląd galerii widżetów macOS", + "widgets.categoriesAria": "Kategorie widżetów", + "widgets.allWidgets": "Wszystkie widżety", + "widgets.metricCaption": "Kompaktowy widżet dla kredytów lub kosztu.", + "widgets.historyCaption": "Wykres historii użycia z ostatnimi sumami.", + "widgets.usageCaption": "Użycie sesji i tygodnia z kredytami oraz kosztami.", + "widgets.switcherCaption": "Widżet użycia z przełącznikiem dostawcy.", + "widgets.burndownCaption": "Pozostały budżet porównany z idealnym stałym tempem spalania.", + "widgets.burndownCombinedCaption": "Wykresy burn-down sesji i tygodnia w jednym kafelku.", + "widgets.dragToDesktop": "Przeciągnij widżet na pulpit…", + "detail.more": "Więcej" + }, + "fa": { + "meta.title": "CodexBar - هر محدودیت کدنویسی هوش مصنوعی در نوار منو شما", + "meta.description": "یک برنامه نوار منو کوچک macOS که پنجره‌های استفاده از ارائه‌دهنده کدنویسی هوش مصنوعی، اعتبارات، هزینه‌ها، و بازنشانی را در بین 59 ارائه‌دهنده - Codex، OpenAI، Claude، Cursor، Gemini، Copilot، LiteLLM و موارد دیگر بازنشانی می‌کند.", + "meta.ogDescription": "پنجره‌های استفاده، اعتبارات و بازنشانی‌ها را در بین 59 ارائه‌دهنده کدنویسی هوش مصنوعی از نوار منوی macOS خود ردیابی کنید.", + "nav.primary": "اولیه", + "nav.language": "زبان", + "nav.docs": "اسناد", + "nav.source": "منبع", + "nav.download": "دانلود کنید", + "theme.toLight": "به طرح زمینه روشن تغییر دهید", + "theme.toDark": "به طرح زمینه تیره بروید", + "hero.prefix": "هر محدودیت کدنویسی هوش مصنوعی،", + "hero.accent": "در نوار منوی شما", + "hero.description": "CodexBar پنجره‌های استفاده، مانده اعتبار و بازنشانی شمارش معکوس را در سراسر ارائه‌دهندگانی که واقعاً برایشان پول پرداخت می‌کنید ردیابی می‌کند - هر کدام یک مورد وضعیت، یا آنها را در یکی ادغام کنید.", + "hero.download": "دانلود برای macOS", + "hero.fineprint": "رایگان و متن‌باز · macOS 14+ · نسخهٔ یونیورسال از GitHub Releases و Homebrew", + "providers.title": "59 ارائه دهنده،{mobileBreak}یک نوار منو", + "providers.description": "ارائه‌دهندگان محبوب با پنجره‌های استفاده خاص خود، شمارش معکوس، نمودارها و منوهای ارائه‌دهنده را بازنشانی می‌کنند.", + "providers.yourProvider": "ارائه دهنده شما", + "providers.authoringGuide": "راهنمای نگارش", + "auth.oauth": "OAuth", + "auth.cli": "CLI", + "auth.gcloud": "gcloud", + "auth.cookies": "Cookies", + "auth.cookiesGo": "Cookies + Go", + "auth.deviceFlow": "Device flow", + "auth.bearerLocal": "Bearer / Local", + "auth.apiKey": "API key", + "auth.token": "Token", + "auth.legacyApi": "Legacy API", + "auth.local": "Local", + "auth.apiKeyCookies": "API key + Cookies", + "auth.virtualKey": "Virtual key", + "showcase.alt": "پاپاور نوار منو CodexBar که کاشی‌های ارائه‌دهنده را با نوارهای استفاده، شمارش معکوس بازنشانی، و جزئیات اعتبار نشان می‌دهد.", + "features.resetsTitle": "بازنشانی می کند که می توانید برای آن برنامه ریزی کنید", + "features.resetsBody": "هر جلسه ارائه دهنده، پنجره های هفتگی و ماهانه با شمارش معکوس برای تنظیم مجدد بعدی - دیگر حدس نمی زنید که آیا یک کار طولانی را شروع کنید یا خیر.", + "features.spendTitle": "اسکن اعتبار، هزینه و هزینه", + "features.spendBody": "موجودی اعتبار و هزینه‌های ماهانه در جایی که ارائه‌دهنده آن‌ها را نشان می‌دهد، به‌علاوه اسکن‌های هزینه محلی قابل تنظیم برای Codex و Claude.", + "features.statusTitle": "وضعیت و حوادث", + "features.statusBody": "نشان‌های برخورد سطوح نظرسنجی وضعیت ارائه‌دهنده در منو و یک پوشش نشانگر روی نماد نوار.", + "features.cliTitle": "CLI و ویجت‌ها", + "features.cliBody": "ویجت‌های WidgetKit برای ارائه‌دهندگان پشتیبانی‌شده و یک {codexbar} CLI برای اسکریپت‌ها و CI — macOS و Linux در هر نسخه ساخته می‌شود.", + "detail.installTitle": "نصب و به روز رسانی", + "detail.installBody": "برنامهٔ یونیورسال از طریق {releases} با به‌روزرسانی خودکار Sparkle، یا از طریق {cask} (به‌روزرسانی با {upgrade}).", + "detail.cliTitle": "CLI", + "detail.cliBody": "یک {codexbar} باینری به همراه تاربال‌های مستقل برای macOS و Linux در هر نسخه. در Linux: {linuxCommand}.", + "detail.privacyTitle": "حریم خصوصی", + "detail.privacyBody": "از جلسات ارائه‌دهنده موجود - OAuth، جریان دستگاه، کلیدهای API، کوکی‌های مرورگر، فایل‌های محلی - مجدداً استفاده می‌کند - بنابراین هیچ گذرواژه‌ای ذخیره نمی‌شود. یادداشت های حسابرسی در {issue}.", + "detail.permissionsTitle": "مجوزهای macOS", + "detail.permissionsBody": "دسترسی کامل به دیسک برای کوکی‌های Safari، دسترسی Keychain برای رمزگشایی کوکی‌ها و جریان‌های OAuth، و هنگامی که کمک‌کنندگان ارائه‌دهنده دایرکتوری‌های پروژه را می‌خوانند، از Files & Folders درخواست می‌کند.", + "footer.builtBy": "ساخته شده توسط", + "footer.changelog": "تغییرات", + "clipboard.copy": "در کلیپ بورد کپی کنید", + "clipboard.copied": "کپی شده", + "nav.home": "خانه CodexBar", + "nav.projectLinks": "پیوندهای پروژه", + "nav.sourceGitHub": "کد منبع CodexBar در GitHub", + "nav.sourceStars": "منبع", + "nav.displayDownload": "نمایش و دانلود", + "clipboard.copyBrew": "کپی فرمان نصب Homebrew", + "hero.badgeStart": "محدودیت‌های استفاده از هوش مصنوعی", + "hero.badgeEnd": "برای macOS", + "hero.descriptionShort": "پنجره‌های استفاده، مانده اعتبار و شمارش معکوس بازنشانی را در ابزارهای هوش مصنوعی‌ای که واقعاً برایشان پرداخت می‌کنید دنبال کنید.", + "hero.fineprintShort": "رایگان و متن‌باز · macOS 14+", + "features.title": "محدودیت‌ها، هزینه و وضعیت", + "mockup.openPanelAria": "CodexBar در نوار منوی macOS باز است", + "mockup.macbookAlt": "نوار منوی MacBook", + "mockup.menuBarAria": "موارد وضعیت نوار منوی macOS", + "mockup.menuIconAria": "نماد CodexBar در نوار منو", + "mockup.usagePanelAria": "باز کردن پنل استفاده CodexBar", + "mockup.updatedJustNow": "همین حالا به‌روزرسانی شد", + "mockup.plus": "Plus", + "mockup.session": "نشست", + "mockup.weekly": "هفتگی", + "mockup.left60": "۶۰٪ باقی‌مانده", + "mockup.left73": "۷۳٪ باقی‌مانده", + "mockup.left89": "۸۹٪ باقی‌مانده", + "mockup.left98": "۹۸٪ باقی‌مانده", + "mockup.reserve2": "۲٪ در ذخیره", + "mockup.reserve5": "۵٪ در ذخیره", + "mockup.onPace": "طبق برنامه", + "mockup.resets2h53m": "بازنشانی در ۲س ۵۳د", + "mockup.resets4h12m": "بازنشانی در ۴س ۱۲د", + "mockup.resets5d4h": "بازنشانی در ۵ر ۴س", + "mockup.resets6d23h": "بازنشانی در ۶ر ۲۳س", + "mockup.runsOut4d21h": "اتمام در ۴ر ۲۱س", + "mockup.lastsUntilReset": "تا بازنشانی دوام دارد", + "mockup.limitResetCredits": "اعتبارهای بازنشانی محدودیت", + "mockup.nextExpires28d2h": "بعدی در ۲۸ر ۲س منقضی می‌شود", + "mockup.nextExpires27d21h": "بعدی در ۲۷ر ۲۱س منقضی می‌شود", + "mockup.manualResetAvailable": "۱ بازنشانی موجود است", + "mockup.recentUsageAria": "استفاده اخیر Codex", + "mockup.today": "امروز", + "mockup.last31DaysCost": "هزینه ۳۱ روز گذشته", + "mockup.last31DaysTokens": "توکن‌های ۳۱ روز گذشته", + "mockup.latestTokens": "آخرین توکن‌ها", + "mockup.usageChartAria": "نمودار استفاده ۳۱ روزه", + "mockup.topModel": "مدل برتر: Example-1", + "mockup.estimatedLogs": "برآوردشده از لاگ‌های محلی Codex برای حساب انتخاب‌شده...", + "mockup.credits": "اعتبارها", + "mockup.zeroLeft": "۰ باقی‌مانده", + "mockup.buyCredits": "خرید اعتبار...", + "mockup.partialDegradation": "افت جزئی", + "mockup.twoIncidents": "۲ رخداد", + "mockup.majorOutage": "قطعی عمده", + "mockup.degraded": "افت کرده", + "mockup.operational": "عملیاتی", + "cli.outputPreviewAria": "پیش‌نمایش خروجی CodexBar CLI", + "cli.left99": "۹۹٪ باقی‌مانده", + "cli.left100": "۱۰۰٪ باقی‌مانده", + "cli.left79": "۷۹٪ باقی‌مانده", + "cli.left74": "۷۴٪ باقی‌مانده", + "cli.resets5h": "بازنشانی در ۵س", + "cli.resets7d": "بازنشانی در ۷ر", + "cli.resets23d18h": "بازنشانی در ۲۳ر ۱۸س", + "cli.available1": "۱ موجود", + "cli.nextResetCredit": "اعتبار بازنشانی بعدی", + "cli.expires27d22h": "در ۲۷ر ۲۲س منقضی می‌شود", + "cli.account": "حساب", + "cli.plan": "طرح", + "cli.total": "کل", + "cli.auto": "خودکار", + "cli.titleLine2": "در CLI", + "cli.lead": "یک باینری {codexbar} همراه با همان خروجی استفاده نوار منو — برای اسکریپت‌ها، CI و بررسی سریع ترمینال.", + "cli.note": "tarballهای مستقل برای macOS و Linux در هر انتشار.", + "cli.privacy": "CodexBar از نشست‌های موجود ارائه‌دهندگان دوباره استفاده می‌کند — هیچ گذرواژه‌ای روی دیسک ذخیره نمی‌شود.", + "widgets.titleLine2": "ویجت‌ها", + "widgets.lead": "ویجت‌های WidgetKit برای ارائه‌دهندگان پشتیبانی‌شده — پنجره‌های استفاده، شمارش معکوس بازنشانی و هزینه در صورت دسترسی. آن‌ها را روی صفحه اصلی و دسکتاپ بگذارید.", + "widgets.note": "اندازه‌های کوچک، متوسط و بزرگ. بدون خروج از ویجت ارائه‌دهنده را عوض کنید.", + "widgets.galleryAria": "پیش‌نمایش گالری ویجت macOS", + "widgets.categoriesAria": "دسته‌های ویجت", + "widgets.allWidgets": "همه ویجت‌ها", + "widgets.metricCaption": "ویجت فشرده برای اعتبار یا هزینه.", + "widgets.historyCaption": "نمودار تاریخچه استفاده با مجموع‌های اخیر.", + "widgets.usageCaption": "استفاده نشست و هفتگی همراه با اعتبار و هزینه.", + "widgets.switcherCaption": "ویجت استفاده با تعویض‌کننده ارائه‌دهنده.", + "widgets.burndownCaption": "بودجه باقی‌مانده در مقایسه با نرخ مصرف ثابت ایده‌آل.", + "widgets.burndownCombinedCaption": "نمودارهای burn-down نشست و هفته در یک کاشی.", + "widgets.dragToDesktop": "یک ویجت را به دسکتاپ بکشید…", + "detail.more": "بیشتر" + }, + "th": { + "meta.title": "CodexBar — ทุกขีดจำกัดการเข้ารหัส AI ในแถบเมนูของคุณ", + "meta.description": "แอปแถบเมนู macOS ขนาดเล็กที่ติดตามกรอบเวลาการใช้งานของผู้ให้บริการเข้ารหัส AI เครดิต ต้นทุน และการรีเซ็ตในผู้ให้บริการ 59 ราย — Codex, OpenAI, Claude, Cursor, Gemini, Copilot, LiteLLM และอีกมากมาย", + "meta.ogDescription": "ติดตามกรอบเวลาการใช้งาน เครดิต และการรีเซ็ตในผู้ให้บริการการเข้ารหัส AI 59 รายจากแถบเมนู macOS", + "nav.primary": "หลัก", + "nav.language": "ภาษา", + "nav.docs": "เอกสาร", + "nav.source": "แหล่งที่มา", + "nav.download": "ดาวน์โหลด", + "theme.toLight": "เปลี่ยนเป็นธีมสว่าง", + "theme.toDark": "เปลี่ยนเป็นธีมสีเข้ม", + "hero.prefix": "ทุกขีดจำกัดการเข้ารหัส AI", + "hero.accent": "ในแถบเมนูของคุณ", + "hero.description": "CodexBar ติดตามกรอบเวลาการใช้งาน ยอดเครดิต และรีเซ็ตการนับถอยหลังของผู้ให้บริการที่คุณชำระเงินจริง — รายการสถานะแต่ละรายการ หรือรวมรายการเหล่านั้นเป็นรายการเดียว", + "hero.download": "ดาวน์โหลดสำหรับ macOS", + "hero.fineprint": "ฟรีและโอเพ่นซอร์ส · macOS 14+ · รุ่น Universal ผ่าน GitHub Releases และ Homebrew", + "providers.title": "ผู้ให้บริการ 59 ราย{mobileBreak}หนึ่งแถบเมนู", + "providers.description": "ผู้ให้บริการยอดนิยมจะกลายเป็นรายการสถานะที่มีหน้าต่างการใช้งานของตนเอง รีเซ็ตการนับถอยหลัง แผนภูมิ และเมนูของผู้ให้บริการ", + "providers.yourProvider": "ผู้ให้บริการของคุณ", + "providers.authoringGuide": "คู่มือการเขียน", + "auth.oauth": "OAuth", + "auth.cli": "CLI", + "auth.gcloud": "gcloud", + "auth.cookies": "Cookies", + "auth.cookiesGo": "Cookies + Go", + "auth.deviceFlow": "Device flow", + "auth.bearerLocal": "Bearer / Local", + "auth.apiKey": "API key", + "auth.token": "Token", + "auth.legacyApi": "Legacy API", + "auth.local": "Local", + "auth.apiKeyCookies": "API key + Cookies", + "auth.virtualKey": "Virtual key", + "showcase.alt": "ป๊อปโอเวอร์แถบเมนู CodexBar แสดงไทล์ผู้ให้บริการพร้อมแถบการใช้งาน การรีเซ็ตการนับถอยหลัง และรายละเอียดเครดิต", + "features.resetsTitle": "รีเซ็ตคุณสามารถวางแผนได้", + "features.resetsBody": "เซสชันต่อผู้ให้บริการ รายสัปดาห์และรายเดือนพร้อมการนับถอยหลังสู่การรีเซ็ตครั้งถัดไป — ไม่ต้องเดาอีกต่อไปว่าจะเริ่มงานที่ยาวนานหรือไม่", + "features.spendTitle": "เครดิต การใช้จ่าย และการสแกนต้นทุน", + "features.spendBody": "ยอดเครดิตและการใช้จ่ายรายเดือนที่ผู้ให้บริการเปิดเผย รวมถึงการสแกนต้นทุนในท้องถิ่นที่กำหนดค่าได้สำหรับ Codex และ Claude", + "features.statusTitle": "สถานะและเหตุการณ์ที่เกิดขึ้น", + "features.statusBody": "การสำรวจสถานะผู้ให้บริการจะแสดงป้ายเหตุการณ์ในเมนูและมีตัวบ่งชี้ซ้อนทับบนไอคอนแถบ", + "features.cliTitle": "CLI & วิดเจ็ต", + "features.cliBody": "วิดเจ็ต WidgetKit สำหรับผู้ให้บริการที่รองรับและ {codexbar} CLI แบบรวมสำหรับสคริปต์และ CI — macOS และ Linux บิวด์ในทุกรีลีส", + "detail.installTitle": "ติดตั้งและอัพเดต", + "detail.installBody": "แอป Universal ผ่าน {releases} พร้อมการอัปเดตอัตโนมัติ Sparkle หรือผ่าน {cask} (อัปเดตด้วย {upgrade})", + "detail.cliTitle": "CLI", + "detail.cliBody": "ไบนารี {codexbar} ที่รวมเข้าด้วยกันพร้อม tarball แบบสแตนด์อโลนสำหรับ macOS และ Linux ในแต่ละรุ่น ใน Linux: {linuxCommand}", + "detail.privacyTitle": "ความเป็นส่วนตัว", + "detail.privacyBody": "ใช้เซสชันของผู้ให้บริการที่มีอยู่ซ้ำ — OAuth, การไหลเวียนของอุปกรณ์, คีย์ API, คุกกี้ของเบราว์เซอร์, ไฟล์ในเครื่อง — ดังนั้นจึงไม่มีการจัดเก็บรหัสผ่าน บันทึกการตรวจสอบใน {issue}", + "detail.permissionsTitle": "สิทธิ์ macOS", + "detail.permissionsBody": "การเข้าถึงดิสก์โดยสมบูรณ์สำหรับคุกกี้ Safari, การเข้าถึง Keychain สำหรับการถอดรหัสคุกกี้และโฟลว์ OAuth และไฟล์และโฟลเดอร์แจ้งเตือนเมื่อผู้ช่วยผู้ให้บริการอ่านไดเรกทอรีโปรเจ็กต์", + "footer.builtBy": "สร้างโดย", + "footer.changelog": "บันทึกการเปลี่ยนแปลง", + "clipboard.copy": "คัดลอกไปยังคลิปบอร์ด", + "clipboard.copied": "คัดลอกแล้ว", + "nav.home": "หน้าแรก CodexBar", + "nav.projectLinks": "ลิงก์โปรเจกต์", + "nav.sourceGitHub": "ซอร์ส CodexBar บน GitHub", + "nav.sourceStars": "ซอร์ส", + "nav.displayDownload": "การแสดงผลและดาวน์โหลด", + "clipboard.copyBrew": "คัดลอกคำสั่งติดตั้ง Homebrew", + "hero.badgeStart": "ขีดจำกัดการใช้งาน AI", + "hero.badgeEnd": "สำหรับ macOS", + "hero.descriptionShort": "ติดตามช่วงเวลาการใช้งาน ยอดเครดิต และเวลานับถอยหลังรีเซ็ตของเครื่องมือ AI ที่คุณจ่ายเงินจริง", + "hero.fineprintShort": "ฟรีและโอเพนซอร์ส · macOS 14+", + "features.title": "ขีดจำกัด ค่าใช้จ่าย และสถานะ", + "mockup.openPanelAria": "CodexBar เปิดอยู่ในแถบเมนู macOS", + "mockup.macbookAlt": "แถบเมนู MacBook", + "mockup.menuBarAria": "รายการสถานะบนแถบเมนู macOS", + "mockup.menuIconAria": "ไอคอน CodexBar บนแถบเมนู", + "mockup.usagePanelAria": "เปิดแผงการใช้งาน CodexBar", + "mockup.updatedJustNow": "อัปเดตเมื่อครู่", + "mockup.plus": "Plus", + "mockup.session": "เซสชัน", + "mockup.weekly": "รายสัปดาห์", + "mockup.left60": "เหลือ 60%", + "mockup.left73": "เหลือ 73%", + "mockup.left89": "เหลือ 89%", + "mockup.left98": "เหลือ 98%", + "mockup.reserve2": "สำรอง 2%", + "mockup.reserve5": "สำรอง 5%", + "mockup.onPace": "เป็นไปตามแผน", + "mockup.resets2h53m": "รีเซ็ตใน 2ชม. 53น.", + "mockup.resets4h12m": "รีเซ็ตใน 4ชม. 12น.", + "mockup.resets5d4h": "รีเซ็ตใน 5วัน 4ชม.", + "mockup.resets6d23h": "รีเซ็ตใน 6วัน 23ชม.", + "mockup.runsOut4d21h": "หมดใน 4วัน 21ชม.", + "mockup.lastsUntilReset": "ใช้ได้จนถึงรีเซ็ต", + "mockup.limitResetCredits": "เครดิตรีเซ็ตขีดจำกัด", + "mockup.nextExpires28d2h": "รายการถัดไปหมดอายุใน 28วัน 2ชม.", + "mockup.nextExpires27d21h": "รายการถัดไปหมดอายุใน 27วัน 21ชม.", + "mockup.manualResetAvailable": "มีรีเซ็ต 1 ครั้ง", + "mockup.recentUsageAria": "การใช้งาน Codex ล่าสุด", + "mockup.today": "วันนี้", + "mockup.last31DaysCost": "ค่าใช้จ่าย 31 วันที่ผ่านมา", + "mockup.last31DaysTokens": "โทเค็น 31 วันที่ผ่านมา", + "mockup.latestTokens": "โทเค็นล่าสุด", + "mockup.usageChartAria": "กราฟการใช้งาน 31 วัน", + "mockup.topModel": "โมเดลหลัก: Example-1", + "mockup.estimatedLogs": "ประมาณจากบันทึก Codex ในเครื่องสำหรับบัญชีที่เลือก...", + "mockup.credits": "เครดิต", + "mockup.zeroLeft": "เหลือ 0", + "mockup.buyCredits": "ซื้อเครดิต...", + "mockup.partialDegradation": "ลดประสิทธิภาพบางส่วน", + "mockup.twoIncidents": "2 เหตุการณ์", + "mockup.majorOutage": "ระบบล่มรุนแรง", + "mockup.degraded": "ประสิทธิภาพลดลง", + "mockup.operational": "ทำงานปกติ", + "cli.outputPreviewAria": "ตัวอย่างผลลัพธ์ CodexBar CLI", + "cli.left99": "เหลือ 99%", + "cli.left100": "เหลือ 100%", + "cli.left79": "เหลือ 79%", + "cli.left74": "เหลือ 74%", + "cli.resets5h": "รีเซ็ตใน 5ชม.", + "cli.resets7d": "รีเซ็ตใน 7วัน", + "cli.resets23d18h": "รีเซ็ตใน 23วัน 18ชม.", + "cli.available1": "ใช้ได้ 1", + "cli.nextResetCredit": "เครดิตรีเซ็ตถัดไป", + "cli.expires27d22h": "หมดอายุใน 27วัน 22ชม.", + "cli.account": "บัญชี", + "cli.plan": "แผน", + "cli.total": "ทั้งหมด", + "cli.auto": "อัตโนมัติ", + "cli.titleLine2": "บน CLI", + "cli.lead": "ไบนารี {codexbar} ที่มาพร้อมกันให้ผลลัพธ์การใช้งานเหมือนแถบเมนู — สำหรับสคริปต์ CI และการตรวจในเทอร์มินัลอย่างรวดเร็ว", + "cli.note": "มี tarball แยกสำหรับ macOS และ Linux ในทุกรุ่น", + "cli.privacy": "CodexBar ใช้เซสชันผู้ให้บริการเดิมซ้ำ — ไม่บันทึกรหัสผ่านไว้บนดิสก์", + "widgets.titleLine2": "วิดเจ็ต", + "widgets.lead": "WidgetKit สำหรับผู้ให้บริการที่รองรับ — ช่วงใช้งาน เวลานับถอยหลังรีเซ็ต และค่าใช้จ่ายเมื่อมี วางไว้บนหน้าจอโฮมและเดสก์ท็อปได้", + "widgets.note": "ขนาดเล็ก กลาง และใหญ่ เปลี่ยนผู้ให้บริการได้โดยไม่ต้องออกจากวิดเจ็ต", + "widgets.galleryAria": "ตัวอย่างแกลเลอรีวิดเจ็ต macOS", + "widgets.categoriesAria": "หมวดหมู่วิดเจ็ต", + "widgets.allWidgets": "วิดเจ็ตทั้งหมด", + "widgets.metricCaption": "วิดเจ็ตกะทัดรัดสำหรับเครดิตหรือค่าใช้จ่าย", + "widgets.historyCaption": "กราฟประวัติการใช้งานพร้อมยอดรวมล่าสุด", + "widgets.usageCaption": "การใช้งานเซสชันและรายสัปดาห์พร้อมเครดิตและค่าใช้จ่าย", + "widgets.switcherCaption": "วิดเจ็ตการใช้งานพร้อมตัวสลับผู้ให้บริการ", + "widgets.burndownCaption": "งบประมาณที่เหลือเทียบกับอัตราใช้งานคงที่ในอุดมคติ", + "widgets.burndownCombinedCaption": "กราฟ burn-down ของเซสชันและสัปดาห์ในไทล์เดียว", + "widgets.dragToDesktop": "ลากวิดเจ็ตไปยังเดสก์ท็อป…", + "detail.more": "เพิ่มเติม" + }, + "gl": { + "meta.title": "CodexBar — todos os límites de programación con IA na túa barra de menús", + "meta.description": "Unha pequena aplicación de barra de menús para macOS que controla as xanelas de uso, os créditos, os custos e os restablecementos de 59 provedores de programación con IA — Codex, OpenAI, Claude, Cursor, Gemini, Copilot, LiteLLM e máis.", + "meta.ogDescription": "Controla as xanelas de uso, os créditos e os restablecementos de 59 provedores de programación con IA desde a barra de menús de macOS.", + "nav.primary": "Principal", + "nav.language": "Idioma", + "nav.docs": "Documentación", + "nav.source": "Código fonte", + "nav.download": "Descargar", + "theme.toLight": "Cambiar ao tema claro", + "theme.toDark": "Cambiar ao tema escuro", + "hero.prefix": "Todos os límites de programación con IA,", + "hero.accent": "na túa barra de menús.", + "hero.description": "CodexBar controla as xanelas de uso, os saldos de crédito e as contas atrás ata o restablecemento dos provedores polos que realmente pagas — un elemento de estado para cada un ou todos combinados nun só.", + "hero.download": "Descargar para macOS", + "hero.fineprint": "Gratuíto e de código aberto · macOS 14+ · Universal mediante GitHub Releases e Homebrew", + "providers.title": "59 provedores,{mobileBreak}unha barra de menús", + "providers.description": "Os provedores populares convértense en elementos de estado coas súas propias xanelas de uso, contas atrás de restablecemento, gráficas e menús.", + "providers.yourProvider": "O teu provedor", + "providers.authoringGuide": "Guía de creación", + "auth.oauth": "OAuth", + "auth.cli": "CLI", + "auth.gcloud": "gcloud", + "auth.cookies": "Cookies", + "auth.cookiesGo": "Cookies + Go", + "auth.deviceFlow": "Fluxo de dispositivo", + "auth.bearerLocal": "Bearer / Local", + "auth.apiKey": "Chave de API", + "auth.token": "Token", + "auth.legacyApi": "API antiga", + "auth.local": "Local", + "auth.apiKeyCookies": "Chave de API + cookies", + "auth.virtualKey": "Chave virtual", + "showcase.alt": "Panel emerxente de CodexBar na barra de menús con tarxetas de provedores, barras de uso, contas atrás de restablecemento e detalles de crédito.", + "features.resetsTitle": "Restablecementos que podes planificar", + "features.resetsBody": "Xanelas de sesión, semanais e mensuais por provedor con contas atrás ata o seguinte restablecemento — sen ter que adiviñar se podes comezar unha tarefa longa.", + "features.spendTitle": "Créditos, gasto e análises de custos", + "features.spendBody": "Saldos de crédito e gasto mensual cando o provedor os ofrece, ademais de análises locais de custos configurables para Codex e Claude.", + "features.statusTitle": "Estado e incidencias", + "features.statusBody": "A consulta do estado dos provedores mostra distintivos de incidencias no menú e un indicador sobre a icona da barra.", + "features.cliTitle": "CLI e widgets", + "features.cliBody": "Widgets de WidgetKit para os provedores compatibles e unha CLI {codexbar} incluída para scripts e CI — compilacións para macOS e Linux en cada versión.", + "detail.installTitle": "Instalación e actualizacións", + "detail.installBody": "Aplicación universal mediante {releases} con actualizacións automáticas de Sparkle ou mediante {cask} (actualizacións con {upgrade}).", + "detail.cliTitle": "CLI", + "detail.cliBody": "Un binario {codexbar} incluído, ademais de tarballs independentes para macOS e Linux en cada versión. En Linux: {linuxCommand}.", + "detail.privacyTitle": "Privacidade", + "detail.privacyBody": "Reutiliza as sesións existentes dos provedores — OAuth, fluxo de dispositivo, chaves de API, cookies do navegador e ficheiros locais — polo que non se gardan contrasinais. Notas da auditoría en {issue}.", + "detail.permissionsTitle": "Permisos de macOS", + "detail.permissionsBody": "Acceso completo ao disco para as cookies de Safari, acceso ao Chaveiro para descifrar cookies e fluxos OAuth, e solicitudes de Ficheiros e cartafoles cando os auxiliares dos provedores len os directorios dos proxectos.", + "footer.builtBy": "Creado por", + "footer.changelog": "Rexistro de cambios", + "clipboard.copy": "Copiar ao portapapeis", + "clipboard.copied": "Copiado", + "nav.home": "Inicio de CodexBar", + "nav.projectLinks": "Ligazóns do proxecto", + "nav.sourceGitHub": "Código fonte de CodexBar en GitHub", + "nav.sourceStars": "código fonte", + "nav.displayDownload": "Visualización e descarga", + "clipboard.copyBrew": "Copiar a orde de instalación de Homebrew", + "hero.badgeStart": "Límites de uso da IA", + "hero.badgeEnd": "para macOS", + "hero.descriptionShort": "Controla as xanelas de uso, os saldos de crédito e as contas atrás de restablecemento das ferramentas de IA polas que realmente pagas.", + "hero.fineprintShort": "Gratuíto e de código aberto · macOS 14+", + "features.title": "Límites,\u00a0gasto e estado", + "mockup.openPanelAria": "CodexBar aberto na barra de menús de macOS", + "mockup.macbookAlt": "Barra de menús do MacBook", + "mockup.menuBarAria": "Elementos de estado da barra de menús de macOS", + "mockup.menuIconAria": "Icona de CodexBar na barra de menús", + "mockup.usagePanelAria": "Abrir o panel de uso de CodexBar", + "mockup.updatedJustNow": "Actualizado agora mesmo", + "mockup.plus": "Plus", + "mockup.session": "Sesión", + "mockup.weekly": "Semanal", + "mockup.left60": "60% restante", + "mockup.left73": "73% restante", + "mockup.left89": "89% restante", + "mockup.left98": "98% restante", + "mockup.reserve2": "2% en reserva", + "mockup.reserve5": "5% en reserva", + "mockup.onPace": "Ao ritmo previsto", + "mockup.resets2h53m": "Restablécese en 2 h 53 min", + "mockup.resets4h12m": "Restablécese en 4 h 12 min", + "mockup.resets5d4h": "Restablécese en 5 d 4 h", + "mockup.resets6d23h": "Restablécese en 6 d 23 h", + "mockup.runsOut4d21h": "Esgótase en 4 d 21 h", + "mockup.lastsUntilReset": "Dura ata o restablecemento", + "mockup.limitResetCredits": "Créditos para restablecer límites", + "mockup.nextExpires28d2h": "O seguinte caduca en 28 d 2 h", + "mockup.nextExpires27d21h": "O seguinte caduca en 27 d 21 h", + "mockup.manualResetAvailable": "1 restablecemento dispoñible", + "mockup.recentUsageAria": "Uso recente de Codex", + "mockup.today": "Hoxe", + "mockup.last31DaysCost": "Custo dos últimos 31 días", + "mockup.last31DaysTokens": "Tokens dos últimos 31 días", + "mockup.latestTokens": "Tokens máis recentes", + "mockup.usageChartAria": "Gráfica de uso de 31 días", + "mockup.topModel": "Modelo principal: Example-1", + "mockup.estimatedLogs": "Estimado a partir dos rexistros locais de Codex para a conta seleccionada...", + "mockup.credits": "Créditos", + "mockup.zeroLeft": "0 restante", + "mockup.buyCredits": "Comprar créditos...", + "mockup.partialDegradation": "Degradación parcial", + "mockup.twoIncidents": "2 incidencias", + "mockup.majorOutage": "Interrupción grave", + "mockup.degraded": "Degradado", + "mockup.operational": "Operativo", + "cli.outputPreviewAria": "Vista previa da saída da CLI de CodexBar", + "cli.left99": "99% restante", + "cli.left100": "100% restante", + "cli.left79": "79% restante", + "cli.left74": "74% restante", + "cli.resets5h": "Restablécese en 5 h", + "cli.resets7d": "Restablécese en 7 d", + "cli.resets23d18h": "Restablécese en 23 d 18 h", + "cli.available1": "1 dispoñible", + "cli.nextResetCredit": "Seguinte crédito de restablecemento", + "cli.expires27d22h": "caduca en 27 d 22 h", + "cli.account": "Conta", + "cli.plan": "Plan", + "cli.total": "Total", + "cli.auto": "Auto", + "cli.titleLine2": "na CLI", + "cli.lead": "Un binario {codexbar} incluído coa mesma saída de uso que a barra de menús — scripts, CI e comprobacións rápidas no terminal.", + "cli.note": "Tarballs independentes para macOS e Linux en cada versión.", + "cli.privacy": "CodexBar reutiliza as sesións existentes dos provedores — non se gardan contrasinais no disco.", + "widgets.titleLine2": "widgets", + "widgets.lead": "Widgets de WidgetKit para os provedores compatibles — xanelas de uso, contas atrás de restablecemento e gasto cando estea dispoñible. Colócaos na pantalla de inicio e no escritorio.", + "widgets.note": "Tamaños pequeno, mediano e grande. Cambia de provedor sen saír do widget.", + "widgets.galleryAria": "Vista previa da galería de widgets de macOS", + "widgets.categoriesAria": "Categorías de widgets", + "widgets.allWidgets": "Todos os widgets", + "widgets.metricCaption": "Widget compacto para créditos ou custos.", + "widgets.historyCaption": "Gráfica do historial de uso cos totais recentes.", + "widgets.usageCaption": "Uso da sesión e semanal con créditos e custos.", + "widgets.switcherCaption": "Widget de uso cun selector de provedor.", + "widgets.burndownCaption": "Orzamento restante comparado cun ritmo ideal de consumo constante.", + "widgets.burndownCombinedCaption": "Gráficas de consumo da sesión e da semana nunha soa tarxeta.", + "widgets.dragToDesktop": "Arrastra un widget ao escritorio…", + "detail.more": "Máis" + }, + "ca": { + "meta.title": "CodexBar: tots els límits de la programació amb IA a la barra de menús", + "meta.description": "Una petita aplicació de barra de menús per a macOS que fa un seguiment de les finestres d'ús, els crèdits, els costos i els restabliments dels proveïdors de programació amb IA: 59 proveïdors, entre els quals Codex, OpenAI, Claude, Cursor, Gemini, Copilot, LiteLLM i més.", + "meta.ogDescription": "Feu el seguiment de les finestres d'ús, els crèdits i els restabliments de 59 proveïdors de programació amb IA des de la barra de menús del macOS.", + "nav.primary": "Navegació principal", + "nav.language": "Llengua", + "nav.docs": "Documentació", + "nav.source": "Codi font", + "nav.download": "Baixeu", + "theme.toLight": "Canvia al tema clar", + "theme.toDark": "Canvia al tema fosc", + "hero.prefix": "Cada límit de la programació amb IA,", + "hero.accent": "a la barra de menús.", + "hero.description": "El CodexBar fa el seguiment de les finestres d'ús, els saldos de crèdit i els comptes enrere fins al restabliment dels proveïdors pels quals realment pagueu: un element d'estat per a cadascun, o combineu-los tots en un de sol.", + "hero.download": "Baixeu per al macOS", + "hero.fineprint": "Gratuït i de codi obert · macOS 14+ · Universal mitjançant GitHub Releases i Homebrew", + "providers.title": "59 proveïdors,{mobileBreak}una barra de menús", + "providers.description": "Els proveïdors populars es converteixen en elements d'estat amb les seves pròpies finestres d'ús, comptes enrere de restabliment, gràfics i menús de proveïdor.", + "providers.yourProvider": "El vostre proveïdor", + "providers.authoringGuide": "Guia de creació", + "auth.oauth": "OAuth", + "auth.cli": "CLI", + "auth.gcloud": "gcloud", + "auth.cookies": "Galetes", + "auth.cookiesGo": "Galetes + Go", + "auth.deviceFlow": "Flux de dispositiu", + "auth.bearerLocal": "Bearer / Local", + "auth.apiKey": "Clau d'API", + "auth.token": "Token", + "auth.legacyApi": "API antiga", + "auth.local": "Local", + "auth.apiKeyCookies": "Clau d'API + galetes", + "auth.virtualKey": "Clau virtual", + "showcase.alt": "Finestra emergent del CodexBar a la barra de menús que mostra les targetes dels proveïdors amb barres d'ús, comptes enrere de restabliment i detalls de crèdit.", + "features.resetsTitle": "Restabliments que podeu planificar", + "features.resetsBody": "Sessió per proveïdor, finestres setmanals i mensuals amb comptes enrere fins al restabliment següent; sense haver d'endevinar si podeu iniciar una tasca llarga.", + "features.spendTitle": "Crèdits, despesa i anàlisis de costos", + "features.spendBody": "Saldos de crèdit i despesa mensual allà on el proveïdor els exposa, més anàlisis de costos locals configurables per a Codex i Claude.", + "features.statusTitle": "Estat i incidències", + "features.statusBody": "El sondeig d'estat dels proveïdors mostra insígnies d'incidències al menú i una superposició d'indicadors a la icona de la barra.", + "features.cliTitle": "CLI i ginys", + "features.cliBody": "Ginys de WidgetKit per als proveïdors compatibles i una CLI {codexbar} inclosa per a scripts i CI: el macOS i el Linux es publiquen a cada versió.", + "detail.installTitle": "Instal·lació i actualitzacions", + "detail.installBody": "Aplicació universal mitjançant {releases} amb actualitzacions automàtiques de Sparkle o mitjançant {cask} (actualitzacions amb {upgrade}).", + "detail.cliTitle": "CLI", + "detail.cliBody": "Un binari {codexbar} inclòs, més tarballs autònoms per al macOS i el Linux a cada versió. Al Linux: {linuxCommand}.", + "detail.privacyTitle": "Privadesa", + "detail.privacyBody": "Reutilitza les sessions existents dels proveïdors (OAuth, flux de dispositiu, claus d'API, galetes del navegador, fitxers locals), de manera que no s'emmagatzema cap contrasenya. Notes d'auditoria a {issue}.", + "detail.permissionsTitle": "Permisos del macOS", + "detail.permissionsBody": "Accés complet al disc per a les galetes de Safari, accés al Clauer per desxifrar les galetes i gestionar els fluxos OAuth, i sol·licituds d'accés a Fitxers i carpetes quan els processos auxiliars dels proveïdors llegeixen els directoris dels projectes.", + "footer.builtBy": "Creat per", + "footer.changelog": "Registre de canvis", + "clipboard.copy": "Copia al porta-retalls", + "clipboard.copied": "Copiat", + "nav.home": "Inici de CodexBar", + "nav.projectLinks": "Enllaços del projecte", + "nav.sourceGitHub": "Codi font de CodexBar a GitHub", + "nav.sourceStars": "codi", + "nav.displayDownload": "Visualització i descàrrega", + "clipboard.copyBrew": "Copia l’ordre d’instal·lació de Homebrew", + "hero.badgeStart": "Límits d’ús d’IA", + "hero.badgeEnd": "per a macOS", + "hero.descriptionShort": "Segueix finestres d’ús, saldos de crèdits i comptes enrere de reinici als tools d’IA que realment pagues.", + "hero.fineprintShort": "Gratis i open source · macOS 14+", + "features.title": "Límits,\u00a0despesa i estat", + "mockup.openPanelAria": "CodexBar obert a la barra de menús de macOS", + "mockup.macbookAlt": "Barra de menús del MacBook", + "mockup.menuBarAria": "Elements d’estat de la barra de menús de macOS", + "mockup.menuIconAria": "Icona de CodexBar a la barra de menús", + "mockup.usagePanelAria": "Obre el panell d’ús de CodexBar", + "mockup.updatedJustNow": "Actualitzat ara mateix", + "mockup.plus": "Plus", + "mockup.session": "Sessió", + "mockup.weekly": "Setmanal", + "mockup.left60": "60% restant", + "mockup.left73": "73% restant", + "mockup.left89": "89% restant", + "mockup.left98": "98% restant", + "mockup.reserve2": "2% en reserva", + "mockup.reserve5": "5% en reserva", + "mockup.onPace": "Al ritme correcte", + "mockup.resets2h53m": "Es reinicia en 2 h 53 min", + "mockup.resets4h12m": "Es reinicia en 4 h 12 min", + "mockup.resets5d4h": "Es reinicia en 5 d 4 h", + "mockup.resets6d23h": "Es reinicia en 6 d 23 h", + "mockup.runsOut4d21h": "S’esgota en 4 d 21 h", + "mockup.lastsUntilReset": "Dura fins al reinici", + "mockup.limitResetCredits": "Crèdits de reinici de límit", + "mockup.nextExpires28d2h": "El següent caduca en 28 d 2 h", + "mockup.nextExpires27d21h": "El següent caduca en 27 d 21 h", + "mockup.manualResetAvailable": "1 reinici disponible", + "mockup.recentUsageAria": "Ús recent de Codex", + "mockup.today": "Avui", + "mockup.last31DaysCost": "Cost dels darrers 31 dies", + "mockup.last31DaysTokens": "Tokens dels darrers 31 dies", + "mockup.latestTokens": "Tokens més recents", + "mockup.usageChartAria": "Gràfic d’ús de 31 dies", + "mockup.topModel": "Model principal: Example-1", + "mockup.estimatedLogs": "Estimat a partir dels logs locals de Codex per al compte seleccionat...", + "mockup.credits": "Crèdits", + "mockup.zeroLeft": "0 restant", + "mockup.buyCredits": "Compra crèdits...", + "mockup.partialDegradation": "Degradació parcial", + "mockup.twoIncidents": "2 incidents", + "mockup.majorOutage": "Tall greu", + "mockup.degraded": "Degradat", + "mockup.operational": "Operatiu", + "cli.outputPreviewAria": "Vista prèvia de la sortida del CLI de CodexBar", + "cli.left99": "99% restant", + "cli.left100": "100% restant", + "cli.left79": "79% restant", + "cli.left74": "74% restant", + "cli.resets5h": "Es reinicia en 5 h", + "cli.resets7d": "Es reinicia en 7 d", + "cli.resets23d18h": "Es reinicia en 23 d 18 h", + "cli.available1": "1 disponible", + "cli.nextResetCredit": "Crèdit de reinici següent", + "cli.expires27d22h": "caduca en 27 d 22 h", + "cli.account": "Compte", + "cli.plan": "Pla", + "cli.total": "Total", + "cli.auto": "Auto", + "cli.titleLine2": "al CLI", + "cli.lead": "Un binari {codexbar} inclòs amb la mateixa sortida d’ús que la barra de menús — scripts, CI i comprovacions ràpides al terminal.", + "cli.note": "Tarballs independents per a macOS i Linux a cada release.", + "cli.privacy": "CodexBar reutilitza sessions existents dels proveïdors — no desa contrasenyes al disc.", + "widgets.titleLine2": "ginys", + "widgets.lead": "Ginys WidgetKit per a proveïdors compatibles — finestres d’ús, comptes enrere de reinici i despesa quan està disponible. Deixa’ls a la pantalla d’inici i a l’escriptori.", + "widgets.note": "Mides petita, mitjana i gran. Canvia de proveïdor sense sortir del giny.", + "widgets.galleryAria": "Vista prèvia de la galeria de ginys de macOS", + "widgets.categoriesAria": "Categories de ginys", + "widgets.allWidgets": "Tots els ginys", + "widgets.metricCaption": "Giny compacte per a crèdits o cost.", + "widgets.historyCaption": "Gràfic d’historial d’ús amb totals recents.", + "widgets.usageCaption": "Ús de sessió i setmanal amb crèdits i costos.", + "widgets.switcherCaption": "Giny d’ús amb selector de proveïdor.", + "widgets.burndownCaption": "Pressupost restant comparat amb un ritme ideal de consum constant.", + "widgets.burndownCombinedCaption": "Gràfics burn-down de sessió i setmana en una sola fitxa.", + "widgets.dragToDesktop": "Arrossega un giny a l’escriptori…", + "detail.more": "Més" + }, + "sv": { + "meta.title": "CodexBar — varje AI-kodningsgräns i din menyrad", + "meta.description": "En liten macOS menyradsapp som spårar AI-kodningsleverantörers användningsfönster, krediter, kostnader och återställningar hos 59 leverantörer – Codex, OpenAI, Claude, Cursor, Gemini, Copilot, LiteLLM och mer.", + "meta.ogDescription": "Spåra användningsfönster, krediter och återställningar hos 59 AI-kodningsleverantörer från din macOS-menyrad.", + "nav.primary": "Primär", + "nav.language": "Språk", + "nav.docs": "Dokument", + "nav.source": "Källa", + "nav.download": "Ladda ner", + "theme.toLight": "Byt till ljustema", + "theme.toDark": "Byt till mörkt tema", + "hero.prefix": "Varje AI-kodningsgräns,", + "hero.accent": "i din menyrad.", + "hero.description": "CodexBar spårar användningsfönster, kreditsaldon och återställningsnedräkningar för de leverantörer du faktiskt betalar för – en statuspost var, eller slå samman dem till en.", + "hero.download": "Ladda ner för macOS", + "hero.fineprint": "Gratis och öppen källkod · macOS 14+ · Universal via GitHub Releases och Homebrew", + "providers.title": "59 leverantörer,{mobileBreak}en menyrad", + "providers.description": "Populära leverantörer blir statusobjekt med sina egna användningsfönster, återställer nedräkningar, diagram och leverantörsmenyer.", + "providers.yourProvider": "Din leverantör", + "providers.authoringGuide": "Författarguide", + "auth.oauth": "OAuth", + "auth.cli": "CLI", + "auth.gcloud": "gcloud", + "auth.cookies": "Cookies", + "auth.cookiesGo": "Cookies + Go", + "auth.deviceFlow": "Device flow", + "auth.bearerLocal": "Bearer / Local", + "auth.apiKey": "API key", + "auth.token": "Token", + "auth.legacyApi": "Legacy API", + "auth.local": "Local", + "auth.apiKeyCookies": "API key + Cookies", + "auth.virtualKey": "Virtual key", + "showcase.alt": "CodexBar menyrad popover som visar leverantörsrutor med användningsfält, återställda nedräkningar och kreditinformation.", + "features.resetsTitle": "Återställningar du kan planera runt", + "features.resetsBody": "Session per leverantör, vecko- och månadsfönster med nedräkningar till nästa återställning – du slipper gissa om du ska påbörja en lång uppgift.", + "features.spendTitle": "Krediter, utgifter och kostnadsskanningar", + "features.spendBody": "Kreditsaldon och månatliga utgifter där leverantören exponerar dem, plus konfigurerbara lokala kostnadsskanningar för Codex och Claude.", + "features.statusTitle": "Status & incidenter", + "features.statusBody": "Leverantörsstatusundersökning visar incidentmärken i menyn och en indikatoröverlagring på fältikonen.", + "features.cliTitle": "CLI och widgets", + "features.cliBody": "WidgetKit-widgets för leverantörer som stöds och en medföljande {codexbar} CLI för skript och CI — macOS och Linux bygger på varje version.", + "detail.installTitle": "Installera och uppdatera", + "detail.installBody": "Universell app via {releases} med automatiska Sparkle-uppdateringar, eller via {cask} (uppdateringar med {upgrade}).", + "detail.cliTitle": "CLI", + "detail.cliBody": "En medföljande binär {codexbar} plus fristående tarballs för macOS och Linux på varje version. På Linux: {linuxCommand}.", + "detail.privacyTitle": "Privatliv", + "detail.privacyBody": "Återanvänder befintliga leverantörssessioner – OAuth, enhetsflöde, API-nycklar, webbläsarcookies, lokala filer – så inga lösenord lagras. Granskningsanteckningar i {issue}.", + "detail.permissionsTitle": "macOS behörigheter", + "detail.permissionsBody": "Full diskåtkomst för Safari-cookies, Keychain-åtkomst för cookie-dekryptering och OAuth-flöden och filer och mappar när leverantörshjälpare läser projektkataloger.", + "footer.builtBy": "Byggd av", + "footer.changelog": "Ändringslogg", + "clipboard.copy": "Kopiera till urklipp", + "clipboard.copied": "Kopierade", + "nav.home": "CodexBar-start", + "nav.projectLinks": "Projektlänkar", + "nav.sourceGitHub": "CodexBar-källa på GitHub", + "nav.sourceStars": "källa", + "nav.displayDownload": "Visning och nedladdning", + "clipboard.copyBrew": "Kopiera Homebrew-installationskommandot", + "hero.badgeStart": "AI-användningsgränser", + "hero.badgeEnd": "för macOS", + "hero.descriptionShort": "Följ användningsfönster, kreditsaldon och nedräkningar till återställning för AI-verktygen du faktiskt betalar för.", + "hero.fineprintShort": "Gratis och open source · macOS 14+", + "features.title": "Gränser,\u00a0utgifter och status", + "mockup.openPanelAria": "CodexBar öppet i macOS-menyraden", + "mockup.macbookAlt": "MacBook-menyrad", + "mockup.menuBarAria": "Statusobjekt i macOS-menyraden", + "mockup.menuIconAria": "CodexBar-ikon i menyraden", + "mockup.usagePanelAria": "Öppna CodexBar-användningspanelen", + "mockup.updatedJustNow": "Uppdaterat nyss", + "mockup.plus": "Plus", + "mockup.session": "Session", + "mockup.weekly": "Veckovis", + "mockup.left60": "60% kvar", + "mockup.left73": "73% kvar", + "mockup.left89": "89% kvar", + "mockup.left98": "98% kvar", + "mockup.reserve2": "2% i reserv", + "mockup.reserve5": "5% i reserv", + "mockup.onPace": "I fas", + "mockup.resets2h53m": "Återställs om 2 h 53 min", + "mockup.resets4h12m": "Återställs om 4 h 12 min", + "mockup.resets5d4h": "Återställs om 5 d 4 h", + "mockup.resets6d23h": "Återställs om 6 d 23 h", + "mockup.runsOut4d21h": "Tar slut om 4 d 21 h", + "mockup.lastsUntilReset": "Räcker till återställning", + "mockup.limitResetCredits": "Gränsåterställningskrediter", + "mockup.nextExpires28d2h": "Nästa löper ut om 28 d 2 h", + "mockup.nextExpires27d21h": "Nästa löper ut om 27 d 21 h", + "mockup.manualResetAvailable": "1 återställning tillgänglig", + "mockup.recentUsageAria": "Senaste Codex-användning", + "mockup.today": "Idag", + "mockup.last31DaysCost": "Kostnad senaste 31 dagarna", + "mockup.last31DaysTokens": "Tokens senaste 31 dagarna", + "mockup.latestTokens": "Senaste tokens", + "mockup.usageChartAria": "31-dagars användningsdiagram", + "mockup.topModel": "Toppmodell: Example-1", + "mockup.estimatedLogs": "Uppskattat från lokala Codex-loggar för valt konto...", + "mockup.credits": "Krediter", + "mockup.zeroLeft": "0 kvar", + "mockup.buyCredits": "Köp krediter...", + "mockup.partialDegradation": "Delvis degradering", + "mockup.twoIncidents": "2 incidenter", + "mockup.majorOutage": "Stort avbrott", + "mockup.degraded": "Degraderad", + "mockup.operational": "Operativ", + "cli.outputPreviewAria": "Förhandsvisning av CodexBar CLI-utdata", + "cli.left99": "99% kvar", + "cli.left100": "100% kvar", + "cli.left79": "79% kvar", + "cli.left74": "74% kvar", + "cli.resets5h": "Återställs om 5 h", + "cli.resets7d": "Återställs om 7 d", + "cli.resets23d18h": "Återställs om 23 d 18 h", + "cli.available1": "1 tillgänglig", + "cli.nextResetCredit": "Nästa återställningskredit", + "cli.expires27d22h": "löper ut om 27 d 22 h", + "cli.account": "Konto", + "cli.plan": "Plan", + "cli.total": "Totalt", + "cli.auto": "Auto", + "cli.titleLine2": "i CLI", + "cli.lead": "En medföljande {codexbar}-binär med samma användningsutdata som menyraden — för skript, CI och snabba terminalkontroller.", + "cli.note": "Fristående tarballs för macOS och Linux vid varje release.", + "cli.privacy": "CodexBar återanvänder befintliga providersessioner — inga lösenord sparas på disk.", + "widgets.titleLine2": "widgetar", + "widgets.lead": "WidgetKit-widgetar för stödda providers — användningsfönster, återställningsnedräkningar och utgifter där det finns. Lägg dem på hemskärmen och skrivbordet.", + "widgets.note": "Små, medelstora och stora storlekar. Byt provider utan att lämna widgeten.", + "widgets.galleryAria": "Förhandsvisning av macOS-widgetgalleri", + "widgets.categoriesAria": "Widgetkategorier", + "widgets.allWidgets": "Alla widgetar", + "widgets.metricCaption": "Kompakt widget för krediter eller kostnad.", + "widgets.historyCaption": "Användningshistorikdiagram med senaste totaler.", + "widgets.usageCaption": "Session- och veckovis användning med krediter och kostnader.", + "widgets.switcherCaption": "Användningswidget med providerbytare.", + "widgets.burndownCaption": "Återstående budget jämförd med en ideal jämn förbrukningstakt.", + "widgets.burndownCombinedCaption": "Session- och veckovisa burn-down-diagram i en ruta.", + "widgets.dragToDesktop": "Dra en widget till skrivbordet…", + "detail.more": "Mer" + } +}; diff --git a/docs/site-utilities.css b/docs/site-utilities.css new file mode 100644 index 0000000..bed5a5a --- /dev/null +++ b/docs/site-utilities.css @@ -0,0 +1 @@ +*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }/*! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:SFMono-Regular,SF Mono,Menlo,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.absolute{position:absolute}.relative{position:relative}.inset-x-0{left:0;right:0}.top-0{top:0}.z-10{z-index:10}.z-20{z-index:20}.mt-12{margin-top:3rem}.mt-5{margin-top:1.25rem}.mt-6{margin-top:1.5rem}.mt-8{margin-top:2rem}.block{display:block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.grid{display:grid}.hidden{display:none}.h-11{height:2.75rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-7{height:1.75rem}.h-9{height:2.25rem}.h-\[var\(--header-height\)\]{height:var(--header-height)}.h-full{height:100%}.min-h-screen{min-height:100vh}.w-3\.5{width:.875rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-7{width:1.75rem}.w-fit{width:-moz-fit-content;width:fit-content}.w-full{width:100%}.max-w-2xl{max-width:42rem}.max-w-3xl{max-width:48rem}.max-w-\[38rem\]{max-width:38rem}.max-w-full{max-width:100%}.shrink-0{flex-shrink:0}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.resize{resize:both}.list-none{list-style-type:none}.place-items-center{place-items:center}.items-center{align-items:center}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-2{gap:.5rem}.gap-2\.5{gap:.625rem}.gap-3{gap:.75rem}.gap-5{gap:1.25rem}.overflow-hidden{overflow:hidden}.overflow-x-hidden{overflow-x:hidden}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-balance{text-wrap:balance}.rounded-\[7px\]{border-radius:7px}.rounded-full{border-radius:9999px}.rounded-md{border-radius:.375rem}.bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity,1))}.bg-transparent{background-color:transparent}.object-contain{-o-object-fit:contain;object-fit:contain}.p-0{padding:0}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.py-16{padding-top:4rem;padding-bottom:4rem}.py-20{padding-top:5rem;padding-bottom:5rem}.font-mono{font-family:SFMono-Regular,SF Mono,Menlo,monospace}.text-\[13px\]{font-size:13px}.text-\[14px\]{font-size:14px}.text-\[15px\]{font-size:15px}.text-\[clamp\(1rem\2c 1\.25vw\2c 1\.28rem\)\]{font-size:clamp(1rem,1.25vw,1.28rem)}.text-\[clamp\(1rem\2c 1\.35vw\2c 1\.28rem\)\]{font-size:clamp(1rem,1.35vw,1.28rem)}.text-\[clamp\(2\.4rem\2c 4\.4vw\2c 5rem\)\]{font-size:clamp(2.4rem,4.4vw,5rem)}.text-\[clamp\(3rem\2c 5\.7vw\2c 60px\)\]{font-size:clamp(3rem,5.7vw,60px)}.text-sm{font-size:.875rem;line-height:1.25rem}.font-medium{font-weight:500}.font-semibold{font-weight:600}.leading-\[0\.98\]{line-height:.98}.leading-\[1\.42\]{line-height:1.42}.leading-\[1\.45\]{line-height:1.45}.tracking-\[-0\.025em\]{letter-spacing:-.025em}.tracking-\[-0\.02em\]{letter-spacing:-.02em}.tracking-\[-0\.035em\]{letter-spacing:-.035em}.tracking-\[-0\.03em\]{letter-spacing:-.03em}.tracking-\[-0\.06em\]{letter-spacing:-.06em}.tracking-\[-0\.07em\]{letter-spacing:-.07em}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.text-zinc-100{--tw-text-opacity:1;color:rgb(244 244 245/var(--tw-text-opacity,1))}.text-zinc-400{--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.text-zinc-600{--tw-text-opacity:1;color:rgb(82 82 91/var(--tw-text-opacity,1))}.text-zinc-700{--tw-text-opacity:1;color:rgb(63 63 70/var(--tw-text-opacity,1))}.shadow-\[0_0_1\.5rem_rgba\(14\2c 165\2c 233\2c 0\.24\)\]{--tw-shadow:0 0 1.5rem rgba(14,165,233,.24);--tw-shadow-colored:0 0 1.5rem var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.drop-shadow{--tw-drop-shadow:drop-shadow(0 1px 2px rgba(0,0,0,.1)) drop-shadow(0 1px 1px rgba(0,0,0,.06))}.drop-shadow,.invert{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.invert{--tw-invert:invert(100%)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.hover\:bg-white\/10:hover{background-color:hsla(0,0%,100%,.1)}.hover\:text-white:hover{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}@media (min-width:640px){.sm\:mt-10{margin-top:2.5rem}.sm\:block{display:block}.sm\:inline{display:inline}.sm\:hidden{display:none}.sm\:h-10{height:2.5rem}.sm\:h-8{height:2rem}.sm\:w-8{width:2rem}.sm\:justify-start{justify-content:flex-start}.sm\:gap-3{gap:.75rem}.sm\:rounded-lg{border-radius:.5rem}.sm\:px-5{padding-left:1.25rem;padding-right:1.25rem}.sm\:px-8{padding-left:2rem;padding-right:2rem}.sm\:text-base{font-size:1rem;line-height:1.5rem}.sm\:text-lg{font-size:1.125rem;line-height:1.75rem}}@media (min-width:768px){.md\:flex{display:flex}.md\:grid{display:grid}.md\:grid-cols-\[1fr_auto_1fr\]{grid-template-columns:1fr auto 1fr}}@media (min-width:769px){.tablet\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.tablet\:grid-cols-\[1fr_0\.86fr\]{grid-template-columns:1fr .86fr}.tablet\:items-center{align-items:center}}@media (min-width:1024px){.lg\:px-12{padding-left:3rem;padding-right:3rem}.lg\:py-20{padding-top:5rem;padding-bottom:5rem}.lg\:py-28{padding-top:7rem;padding-bottom:7rem}}@media (min-width:1280px){.xl\:grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}} \ No newline at end of file diff --git a/docs/site.css b/docs/site.css new file mode 100644 index 0000000..d958c7a --- /dev/null +++ b/docs/site.css @@ -0,0 +1,2607 @@ +:root { + color-scheme: dark; + --page-bg: #000; + --page-glow: rgba(255, 255, 255, 0.075); + --page-text: #f4f4f5; + --page-muted: #a1a1aa; + --page-subtle: #71717a; + --page-faint: #52525b; + --page-line: rgba(255, 255, 255, 0.08); + --control-bg: rgba(255, 255, 255, 0.04); + --control-border: rgba(255, 255, 255, 0.1); + --control-hover: rgba(255, 255, 255, 0.075); + --control-active: rgba(255, 255, 255, 0.12); + --control-text: #a1a1aa; + --control-active-text: #fff; + --primary-bg: #f4f4f5; + --primary-text: #09090b; + --primary-hover: #e4e4e7; + --apple-filter: none; + --header-height: 4rem; + --hero-bg: #000; + --hero-fade-end: var(--hero-bg); + --mockup-y: 10px; + --mockup-scale: 1.15; + --mockup-tune-width: 1920; + --mockup-fluid-max: 1.22; + --mockup-screen-margin-right: 50px; + /* Keep the MacBook right-aligned before site.js refines the viewport calculation. */ + --mockup-x: max(calc(-32.777vw - 50px), calc(50vw - 1352.72px)); + --mockup-artboard-ratio: 1.18; + /* Menubar: Figma 130/150px + scale 0.94, × visual correction (top ×1.308, right ×1.548, scale ×1.55) */ + --menubar-scale: 1.457; + --menubar-icon-scale: 1.28; + --menubar-gap: 0.9cqw; + --popover-scale: 0.85; + --hud-anchor-top: 5.25%; + --hud-margin-right: 3.8%; + /* Panel: Figma formula × visual correction (top ×1.104, right ×1.322, scale ×0.934) */ + --hud-panel-top: 8.5%; + --hud-panel-margin-right: 3.7%; + --hud-panel-width: 18.22%; + --hud-menu-nudge-x: 0px; + --hud-menu-nudge-y: 0px; + --hud-panel-nudge-x: 0px; + --hud-panel-nudge-y: 0px; + --glow-x: 331px; + --glow-y: -260px; + --glow-scale: 2.4; + --glow-opacity: 0.55; + --glow-blur: 72px; + --glow-color-a: #003c61; + --glow-color-b: #8000ff; + /* Hero entrance choreography (copy + mockup HUD) */ + --hero-ease: cubic-bezier(0.23, 1, 0.32, 1); + --hero-reveal-duration: 420ms; + --hero-reveal-step: 40ms; + --hero-reveal-1: 0ms; + --hero-reveal-2: 40ms; + --hero-reveal-3: 80ms; + --hero-reveal-4: 125ms; + --hero-reveal-5: 170ms; + --hero-menubar-start: 100ms; + --hero-menubar-wave: 30ms; + --hero-mark-after-menubar: 30ms; + --hero-popover-after-mark: 60ms; + --mobile-mockup-stage-height: 33.5rem; + --mobile-mockup-stage-max-width: 26rem; + --mobile-stage-inline-gutter: 1.25rem; + --mobile-mockup-width: 251%; + --mobile-mockup-offset-x: -32px; + --mobile-mockup-offset-y: 18px; + --mobile-mockup-scale: 0.99; + --mobile-hud-anchor-top: 5.25%; + --mobile-hud-margin-right: 3.8%; + --mobile-hud-panel-top: 9.15%; + --mobile-hud-panel-margin-right: 6%; + --mobile-hud-panel-width: 20%; + --mobile-hud-menu-nudge-x: 0px; + --mobile-hud-menu-nudge-y: 0px; + --mobile-menubar-scale: 1.271; + --mobile-menubar-gap: 0.9cqw; + --mobile-popover-scale: 1.39; + --tablet-mockup-x: -247px; + --tablet-mockup-y: 13px; + --tablet-mockup-scale: 1.2; + --tablet-mockup-tune-width: 1022; + --tablet-mockup-fluid-max: 1.18; + --tablet-mockup-stage-height: 42rem; + /* Panel tablet tune @ 1020 → top 9.5%, scale 1.35 */ + --tablet-hud-panel-top: 9.5%; + --tablet-hud-panel-margin-right: 3.7%; + --tablet-hud-panel-width: 18.22%; + --tablet-popover-scale: 1.35; +} + +:root[data-theme="light"] { + color-scheme: light; + --page-bg: #f7f7f5; + --page-glow: rgba(0, 0, 0, 0.05); + --page-text: #18181b; + --page-muted: #52525b; + --page-subtle: #71717a; + --page-faint: #a1a1aa; + --page-line: rgba(0, 0, 0, 0.1); + --control-bg: rgba(0, 0, 0, 0.035); + --control-border: rgba(0, 0, 0, 0.11); + --control-hover: rgba(0, 0, 0, 0.065); + --control-active: rgba(0, 0, 0, 0.1); + --control-text: #71717a; + --control-active-text: #18181b; + --primary-bg: #18181b; + --primary-text: #fff; + --primary-hover: #3f3f46; + --apple-filter: brightness(0) invert(1); +} + +html { scroll-behavior: smooth; } + +body { + margin: 0; + background: + radial-gradient(circle at 50% 76%, var(--page-glow), transparent 29rem), + var(--page-bg); + color: var(--page-text); + -webkit-font-smoothing: antialiased; +} + +:where(a, button, [role="option"]):focus-visible { + outline: 3px solid #38bdf8; + outline-offset: 3px; +} + +html.bg-black { background-color: var(--page-bg) !important; } + +::selection { background: #0099ff; color: #fff; } + +.mockup-stage { + position: absolute; + inset: 0; + overflow: hidden; +} + +.mockup-wrap { + position: absolute; + top: var(--header-height); + left: 50%; + width: 118%; + aspect-ratio: 6111 / 3239; + transform: translate(calc(-50% + var(--mockup-x)), var(--mockup-y)) + scale(var(--mockup-layout-scale, calc(var(--mockup-scale) * clamp(1, calc(var(--mockup-tune-width) * 1px / 100vw), var(--mockup-fluid-max))))); + transform-origin: top center; + will-change: transform; +} + +.mockup-wrap::after { + content: ""; + position: absolute; + z-index: 6; + right: 0; + bottom: -1px; + left: 0; + height: 32%; + pointer-events: none; + background: linear-gradient(180deg, transparent 0%, rgba(0, 0, 0, 0.58) 50%, #000 68%, #000 100%); +} + +.mockup-glow { + position: absolute; + z-index: 0; + top: 34%; + left: 50%; + width: 68%; + height: 38%; + transform: translate(calc(-50% + var(--glow-x)), var(--glow-y)) scale(var(--glow-scale)); + border-radius: 999px; + background: + radial-gradient(circle at 52% 50%, color-mix(in srgb, var(--glow-color-a) 28%, transparent), transparent 45%), + radial-gradient(circle at 42% 56%, color-mix(in srgb, var(--glow-color-b) 16%, transparent), transparent 58%); + filter: blur(var(--glow-blur)); + opacity: var(--glow-opacity); + pointer-events: none; + will-change: transform, opacity, filter; +} + +.mockup-wrap > img { + position: relative; + z-index: 1; +} + +/* Desktop: tracks the mockup image transform; mobile: fills the clipped stage */ +.mockup-hud-layer { + position: absolute; + z-index: 2; + top: var(--header-height); + left: 50%; + width: 118%; + aspect-ratio: 6111 / 3239; + transform: translate(calc(-50% + var(--mockup-x)), var(--mockup-y)) + scale(var(--mockup-layout-scale, calc(var(--mockup-scale) * clamp(1, calc(var(--mockup-tune-width) * 1px / 100vw), var(--mockup-fluid-max))))); + transform-origin: top center; + pointer-events: none; + will-change: transform; +} + +/* HUD coordinates: percentages are relative to the full SVG artboard box */ +.mockup-artboard { + position: absolute; + inset: 0; + container-type: size; + container-name: mockup-artboard; + pointer-events: none; +} + +.mockup-hud-anchor { + display: contents; +} + +.system-menubar { + position: absolute; + top: var(--hud-anchor-top); + right: var(--hud-margin-right); + left: auto; + z-index: 3; + display: flex; + align-items: center; + gap: calc(var(--menubar-gap) / var(--menubar-scale)); + overflow: visible; + transform: translate(var(--hud-menu-nudge-x), var(--hud-menu-nudge-y)) scale(var(--menubar-scale)); + transform-origin: top right; + color: rgba(245, 245, 245, 0.94); + font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", "Inter", sans-serif; + font-size: clamp(0.48rem, 0.52cqw, 0.75rem); + font-weight: 650; + letter-spacing: -0.045em; + text-shadow: 0 0.08em 0.28em rgba(0, 0, 0, 0.74); + will-change: transform; + pointer-events: auto; +} + +.menu-bar-mark { + position: relative; + flex: none; + width: calc(1em * var(--menubar-icon-scale)); + height: calc(1em * var(--menubar-icon-scale)); + transform: translateY(0.01em); + filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.4)); +} + +.menu-bar-mark::before { + content: ""; + position: absolute; + inset: -0.22em -0.3em; + border-radius: 999px; + background: rgba(255, 255, 255, 0.24); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.12); +} + +.menu-bar-mark span { + position: absolute; + z-index: 1; + left: 10%; + display: block; + width: 80%; + height: 22%; + overflow: hidden; + border-radius: 999px; + background: #a8aaa8; +} + +.menu-bar-mark span::before { + content: ""; + position: absolute; + inset: 0; + border-radius: inherit; + background: linear-gradient(90deg, #f5f5f3 0%, #e7e7e5 100%); + transform: scaleX(0); + transform-origin: left center; + transition: transform 400ms cubic-bezier(0.23, 1, 0.32, 1) var(--mark-bar-delay, 0ms); + will-change: transform; +} + +.menu-bar-mark span:first-child { + top: 23%; + --mark-fill: 0.68; + --mark-bar-delay: 0ms; +} + +.menu-bar-mark span:last-child { + bottom: 23%; + --mark-fill: 0.33; + --mark-bar-delay: 80ms; +} + +.mockup-stage.is-mark-animated .menu-bar-mark span::before { + transform: scaleX(var(--mark-fill)); +} + +.system-menubar svg, +.system-menubar .sf-symbol { + flex: none; + display: block; + width: calc(1em * var(--menubar-icon-scale)); + height: calc(1em * var(--menubar-icon-scale)); +} + +.system-menubar svg { + overflow: visible; + color: #dbdbdb; + fill: none; + stroke: currentColor; + stroke-width: 2.35; + stroke-linecap: round; + stroke-linejoin: round; + filter: drop-shadow(0 0.08em 0.18em rgba(0, 0, 0, 0.58)); +} + +.system-menubar .sf-symbol { + object-fit: contain; + filter: brightness(0) invert(86%) drop-shadow(0 0.08em 0.18em rgba(0, 0, 0, 0.58)); +} + +.system-menubar .sf-symbol--openclaw { + filter: drop-shadow(0 0.08em 0.18em rgba(0, 0, 0, 0.58)); +} + +.system-menubar .time { + margin-left: calc(var(--menubar-gap) * -0.08 / var(--menubar-scale)); + white-space: nowrap; + font-size: 0.8em; +} + +.system-menubar > * { + opacity: 0; + transform: translateY(-0.42em); + transition: + opacity 280ms cubic-bezier(0.23, 1, 0.32, 1), + transform 280ms cubic-bezier(0.23, 1, 0.32, 1); + transition-delay: var(--menubar-enter-delay, 0ms); + will-change: opacity, transform; +} + +.system-menubar > .menu-bar-mark { + transform: translateY(calc(0.01em - 0.42em)); +} + +.mockup-stage.is-menubar-entered .system-menubar > * { + opacity: 1; + transform: translateY(0); +} + +.mockup-stage.is-menubar-entered .system-menubar > .menu-bar-mark { + transform: translateY(0.01em); +} + +.codex-popover { + position: absolute; + top: var(--hud-panel-top); + right: var(--hud-panel-margin-right); + left: auto; + z-index: 4; + width: var(--hud-panel-width); + box-sizing: border-box; + padding: 0.78rem 0.82rem 0.9rem; + transform: translate(var(--hud-panel-nudge-x), calc(var(--hud-panel-nudge-y) + 8px)) + scale(calc(var(--popover-scale) * 0.985)); + transform-origin: top right; + overflow: hidden; + border: 1px solid rgba(255, 255, 255, 0.08); + border-radius: 1rem; + background: linear-gradient(180deg, rgba(35, 35, 38, 0.94), rgba(20, 20, 22, 0.97)); + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.1), + inset 0 -1px 0 rgba(255, 255, 255, 0.08), + 0 1.5rem 2.5rem rgba(0, 0, 0, 0.56); + color: rgba(244, 244, 245, 0.92); + font-size: clamp(0.45rem, 0.48cqw, 0.68rem); + letter-spacing: -0.035em; + line-height: 1.15; + backdrop-filter: blur(18px); + user-select: text; + -webkit-user-select: text; + opacity: 0; + pointer-events: auto; + transition: + opacity 300ms var(--hero-ease), + transform 360ms var(--hero-ease); + will-change: transform, opacity; +} + +.mockup-stage.is-animated .codex-popover { + opacity: 1; + transform: translate(var(--hud-panel-nudge-x), var(--hud-panel-nudge-y)) scale(var(--popover-scale)); +} + +.popover-top, +.popover-section, +.popover-foot { + position: relative; + z-index: 1; +} + +.popover-top { + display: grid; + grid-template-columns: 1fr auto; + gap: 0.35rem; + padding-bottom: 0.55rem; + border-bottom: 1px solid rgba(255, 255, 255, 0.16); +} + +.popover-top strong, +.popover-section h3, +.popover-number strong, +.popover-foot strong { + display: block; + color: rgba(244, 244, 245, 0.96); + font-weight: 780; +} + +.popover-top span, +.popover-number span, +.popover-note, +.popover-foot span { + color: rgba(244, 244, 245, 0.58); + font-weight: 650; +} + +.popover-top .right { text-align: right; } + +.popover-section { margin-top: 0.9rem; } +.popover-section h3 { margin-bottom: 0.42rem; font-size: 1.28em; } + +.usage-meter { + position: relative; + height: 0.42rem; + overflow: hidden; + border-radius: 999px; + background: rgba(255, 255, 255, 0.09); +} + +.usage-meter::before { + content: ""; + display: block; + width: var(--fill); + height: 100%; + border-radius: inherit; + background: #4fb6c3; + transform: scaleX(0); + transform-origin: left center; + transition: transform 500ms cubic-bezier(0.23, 1, 0.32, 1) var(--meter-delay, 70ms); +} + +.usage-meter::after { + content: ""; + position: absolute; + top: 0; + left: var(--danger); + width: 0.14rem; + height: 100%; + border-radius: 999px; + background: #ff4055; + opacity: 0; + transition: opacity 140ms ease calc(var(--meter-delay, 70ms) + 380ms); +} + +.usage-meter i { + position: absolute; + top: 18%; + left: var(--tick); + width: 1px; + height: 64%; + background: rgba(255, 255, 255, 0.34); + opacity: 0; + transition: opacity 180ms ease calc(var(--meter-delay, 70ms) + 280ms); +} + +.mockup-stage.is-animated .usage-meter::before { transform: scaleX(1); } +.mockup-stage.is-animated .usage-meter::after, +.mockup-stage.is-animated .usage-meter i { opacity: 1; } + +.usage-row { + display: grid; + grid-template-columns: 1fr auto; + gap: 0.75rem; + margin-top: 0.45rem; +} + +.usage-row strong, +.usage-row span { + display: block; + font-weight: 760; +} + +.usage-row .right { text-align: right; color: rgba(244, 244, 245, 0.62); } + +.reset-credit { + display: grid; + grid-template-columns: 1fr auto; + gap: 0.75rem; + margin-top: 0.9rem; + padding-top: 0.86rem; + border-top: 1px solid rgba(255, 255, 255, 0.14); +} + +.reset-credit strong, +.reset-credit span { + display: block; + font-weight: 760; +} + +.reset-credit span, +.reset-credit p:last-child { + color: rgba(244, 244, 245, 0.58); +} + +.number-grid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 0.65rem 1.15rem; + margin-top: 0.9rem; +} + +.popover-number strong { margin-top: 0.12rem; font-size: 1.22em; } + +.usage-chart { + display: flex; + align-items: end; + gap: 0.18rem; + height: 4.15rem; + margin-top: 0.75rem; + border-bottom: 1px solid rgba(79, 182, 195, 0.26); +} + +.usage-chart i { + flex: 1; + min-width: 0.12rem; + height: var(--h); + border-radius: 0.12rem 0.12rem 0 0; + background: rgba(79, 182, 195, 0.78); + opacity: 0.18; + transform: scaleY(0); + transform-origin: bottom center; + transition: + transform 380ms cubic-bezier(0.23, 1, 0.32, 1) var(--bar-delay, 120ms), + opacity 180ms ease var(--bar-delay, 120ms); +} + +.mockup-stage.is-animated .usage-chart i { + opacity: 1; + transform: scaleY(1); +} + +.popover-note { + margin-top: 0.62rem; + font-size: 0.96em; +} + +.popover-note strong { color: rgba(244, 244, 245, 0.72); } + +.popover-foot { + margin-top: 1rem; + padding-top: 0.86rem; + border-top: 1px solid rgba(255, 255, 255, 0.14); +} + +.credit-meter { + height: 0.46rem; + margin: 0.55rem 0 0.55rem; + border-radius: 999px; + background: rgba(255, 255, 255, 0.08); +} + +.credit-row, +.buy-row { + display: flex; + align-items: center; + justify-content: space-between; +} + +.buy-row { + justify-content: flex-start; + gap: 0.55rem; + margin-top: 0.8rem; + font-size: 1.18em; + font-weight: 780; +} + +.buy-row svg { width: 1em; height: 1em; color: rgba(244, 244, 245, 0.78); } + +.hero-content { + position: relative; + z-index: 10; + pointer-events: none; +} + +.hero-section { + position: relative; + min-height: 100vh; + padding-top: var(--header-height); +} + +.hero-section::after { + content: ""; + position: absolute; + inset-inline: 0; + bottom: 0; + z-index: 9; + height: clamp(7rem, 18vh, 13rem); + pointer-events: none; + background: linear-gradient( + 180deg, + transparent 0%, + rgba(0, 0, 0, 0.55) 40%, + #000 65%, + #000 100% + ); +} + +.hero-copy { + position: relative; + pointer-events: auto; + width: 100%; + max-width: 42rem; + padding-top: clamp(9rem, 21vh, 13rem); + text-align: left; +} + +.hero-cta-row { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 1rem; +} + +@media (min-width: 1185px) { + .hero-cta-row { + flex-direction: row; + flex-wrap: nowrap; + align-items: center; + } +} + +.hero-title-line { + display: block; + text-wrap: balance; +} + +@media (min-width: 1800px) { + .hero-copy h1 { + font-size: 60px !important; + } +} + +.brew-pill { + background: + linear-gradient(180deg, rgba(255, 255, 255, 0.075), rgba(255, 255, 255, 0.025)), + rgba(13, 13, 15, 0.78); + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.1), + inset 0 0 0 1px rgba(255, 255, 255, 0.12), + 0 0.75rem 2rem rgba(0, 0, 0, 0.28); + backdrop-filter: blur(14px); +} + +.apple-icon { + display: block; + width: 1rem; + height: 1rem; + object-fit: contain; + transform: translateY(-0.5px); + filter: var(--apple-filter); +} + +.theme-option { + display: grid; + width: 1.75rem; + height: 1.75rem; + place-items: center; + border-radius: 999px; + color: var(--control-text); + transition: transform 140ms cubic-bezier(0.23, 1, 0.32, 1), background-color 140ms ease, color 140ms ease; +} + +.theme-option svg { width: 0.9rem; height: 0.9rem; } +.theme-option [data-theme-icon] { display: none; } +:root[data-theme-preference="system"] .theme-option [data-theme-icon="system"], +:root[data-theme-preference="light"] .theme-option [data-theme-icon="light"], +:root[data-theme-preference="dark"] .theme-option [data-theme-icon="dark"] { display: block; } +.theme-option:active { transform: scale(0.94); } + +.language-picker { + position: relative; +} + +.language-picker-trigger { + display: inline-flex; + height: 2.125rem; + align-items: center; + gap: 0.35rem; + padding: 0 0.55rem; + border: 1px solid var(--control-border); + border-radius: 999px; + background: var(--control-bg); + color: var(--control-text); + font-size: 0.75rem; + font-weight: 600; + line-height: 1; + cursor: pointer; + transition: background-color 140ms ease, border-color 140ms ease, color 140ms ease; +} + +.language-picker-trigger svg { + width: 0.85rem; + height: 0.85rem; + flex: none; +} + +.language-picker-menu { + position: absolute; + top: calc(100% + 0.45rem); + right: 0; + z-index: 40; + width: min(13.5rem, calc(100vw - 2rem)); + overflow: hidden; + padding: 0.35rem 0.3rem 0.35rem 0.35rem; + border: 1px solid var(--control-border); + border-radius: 0.85rem; + background: color-mix(in srgb, var(--page-bg) 82%, #18181b); + box-shadow: + inset 0 1px 0 color-mix(in srgb, var(--page-text) 8%, transparent), + 0 1rem 2.5rem rgba(0, 0, 0, 0.42); + backdrop-filter: blur(18px); +} + +.language-picker-menu-scroll { + display: grid; + gap: 0.1rem; + max-height: min(21rem, calc(100vh - 6.5rem)); + overflow-y: auto; + overscroll-behavior: contain; + padding-right: 0.2rem; + scrollbar-width: thin; + scrollbar-color: color-mix(in srgb, var(--page-text) 24%, transparent) transparent; +} + +.language-picker-menu-scroll::-webkit-scrollbar { + width: 5px; +} + +.language-picker-menu-scroll::-webkit-scrollbar-track { + margin: 0.15rem 0; + background: transparent; +} + +.language-picker-menu-scroll::-webkit-scrollbar-thumb { + border: 1px solid transparent; + border-radius: 999px; + background: color-mix(in srgb, var(--page-text) 24%, transparent); + background-clip: padding-box; +} + +.language-picker-menu-scroll::-webkit-scrollbar-corner { + background: transparent; +} + +.language-picker-menu[hidden] { display: none; } + +.language-option { + display: grid; + grid-template-columns: 1rem 1fr; + align-items: center; + gap: 0.55rem; + width: 100%; + padding: 0.5rem 0.55rem; + border: 0; + border-radius: 0.55rem; + background: transparent; + color: var(--page-text); + font-size: 0.82rem; + font-weight: 500; + letter-spacing: -0.02em; + line-height: 1.2; + text-align: left; + cursor: pointer; + transition: background-color 120ms ease, color 120ms ease; +} + +.language-option svg { + width: 0.85rem; + height: 0.85rem; + opacity: 0; +} + +.language-option[aria-selected="true"] { + background: #0099ff; + color: #fff; +} + +.language-option[aria-selected="true"] svg { opacity: 1; } + +@media (hover: hover) and (pointer: fine) { + .language-picker-trigger:hover { + background: var(--control-hover); + color: var(--page-text); + } + + .language-option:not([aria-selected="true"]):hover { + background: var(--control-hover); + } +} + +.header-divider { + width: 1px; + height: 1.25rem; + background: var(--page-line); +} + +.download-button { + background: var(--primary-bg) !important; + color: var(--primary-text) !important; + box-shadow: + 0 1px 2px rgba(0, 0, 0, 0.14), + inset 0 1px 0 rgba(255, 255, 255, 0.34); +} + +@media (hover: hover) and (pointer: fine) { + .download-button:hover { + background: var(--primary-hover) !important; + box-shadow: + 0 10px 24px rgba(0, 0, 0, 0.24), + inset 0 1px 0 rgba(255, 255, 255, 0.42); + } +} + +:root[data-theme="light"] .text-white, +:root[data-theme="light"] .text-zinc-100 { color: var(--page-text) !important; } +:root[data-theme="light"] .text-zinc-400 { color: var(--page-muted) !important; } +:root[data-theme="light"] .text-zinc-500 { color: var(--page-subtle) !important; } +:root[data-theme="light"] .text-zinc-600, +:root[data-theme="light"] .text-zinc-700 { color: var(--page-faint) !important; } + +:root[data-theme="light"] .hero-copy .text-zinc-100 { color: #f4f4f5 !important; } +:root[data-theme="light"] .hero-copy .text-zinc-400 { color: #a1a1aa !important; } +:root[data-theme="light"] .hero-copy .text-zinc-600 { color: #52525b !important; } + +:root[data-theme="light"] .hero-copy .brew-pill { + background: + linear-gradient(180deg, rgba(255, 255, 255, 0.075), rgba(255, 255, 255, 0.025)), + rgba(13, 13, 15, 0.78); + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.1), + inset 0 0 0 1px rgba(255, 255, 255, 0.12), + 0 0.75rem 2rem rgba(0, 0, 0, 0.28); +} + +:root[data-theme="light"] .hero-download { + background: #fff !important; + color: #09090b !important; + box-shadow: + 0 1px 2px rgba(0, 0, 0, 0.08), + inset 0 1px 0 rgba(255, 255, 255, 0.9); +} + +@media (hover: hover) and (pointer: fine) { + :root[data-theme="light"] .hero-download:hover { + background: #e4e4e7 !important; + box-shadow: + 0 10px 24px rgba(0, 0, 0, 0.12), + inset 0 1px 0 rgba(255, 255, 255, 0.72); + } +} +:root[data-theme="light"] .hero-download .apple-icon { filter: none; } + +:root[data-theme="light"] .provider-card p > strong { color: var(--page-text); } +:root[data-theme="light"] .provider-card p > span { color: var(--page-subtle); } + +@media (hover: hover) and (pointer: fine) { + .theme-option:hover { color: var(--page-text); } +} + +.provider-section { + position: relative; + border-top: 1px solid var(--page-line); + background: var(--page-bg); +} + +.section-inner { + width: 100%; + max-width: 1380px; + margin-inline: auto; +} + +.provider-reveal { + opacity: 0; + transform: translateY(12px); + transition: + opacity 420ms cubic-bezier(0.23, 1, 0.32, 1), + transform 420ms cubic-bezier(0.23, 1, 0.32, 1); + transition-delay: var(--reveal-delay, 0ms); +} + +.provider-section.is-revealed .provider-reveal, +.features-section.is-revealed .provider-reveal, +.cli-section.is-revealed .provider-reveal, +.widgets-section.is-revealed .provider-reveal, +.technical-section.is-revealed .provider-reveal { + opacity: 1; + transform: translateY(0); +} + +.provider-card { + position: relative; + min-height: 4.6rem; +} + +.provider-card-link { + display: grid; + min-height: inherit; + grid-template-columns: 3.1rem 1fr; + align-items: center; + gap: 1rem; + padding: 0.65rem 0; + color: inherit; + text-decoration: none; +} + +.provider-card[hidden] { display: none; } + +.provider-card-link:focus-visible { + border-radius: 0.5rem; + outline: 2px solid #2497ff; + outline-offset: 3px; +} + +.provider-logo { + position: relative; + display: grid; + width: 3.1rem; + height: 3.1rem; + place-items: center; + color: var(--page-text); + font-size: 0.86rem; + font-weight: 700; + letter-spacing: -0.08em; +} + +.provider-logo::after { + content: attr(data-icon); + position: absolute; + display: grid; + inset: 0; + place-items: center; +} + +.provider-logo::before { + content: ""; + position: absolute; + z-index: 2; + inset: 0.7rem; + background: var(--page-text); + opacity: 1; + pointer-events: none; + -webkit-mask: var(--icon) center / contain no-repeat; + mask: var(--icon) center / contain no-repeat; + transition: background-color 120ms ease; +} + +.provider-logo:has(img)::after { display: none; } +.provider-logo:not(:has(img))::before { display: none; } + +.provider-logo img { + position: relative; + z-index: 1; + display: block; + width: 1.7rem; + height: 1.7rem; + object-fit: contain; + opacity: 0; +} + +.provider-logo > svg { + position: absolute; + z-index: 1; + inset: 0; + width: 1.7rem; + height: 1.7rem; + margin: auto; + color: var(--page-text); +} + +@media (hover: hover) and (pointer: fine) { + .provider-card:hover .provider-logo::before { + background: color-mix(in srgb, var(--brand) 78%, var(--page-text)); + } +} + +.provider-card p > strong, +.provider-card p > span { + display: block; +} + +.provider-card p > strong { + color: var(--page-text); + font-size: 1.12rem; + line-height: 1.15; + letter-spacing: -0.035em; +} + +.provider-card p > span { + margin-top: 0.35rem; + color: var(--page-subtle); + font-size: 1rem; + letter-spacing: -0.025em; +} + +.provider-card p > .provider-authoring { + display: inline-flex; + align-items: center; + gap: 0.22rem; + color: #0099ff; +} + +.provider-authoring svg { + width: 0.9em; + height: 0.9em; + flex: none; +} + +.button-press { transition: transform 160ms cubic-bezier(0.23, 1, 0.32, 1), background-color 160ms ease, color 160ms ease, box-shadow 160ms ease; } +.button-press:active { transform: scale(0.97); } + +.reveal { + opacity: 0; + transform: translateY(10px); + animation: reveal var(--hero-reveal-duration) var(--hero-ease) forwards; + animation-delay: var(--hero-reveal-delay, var(--hero-reveal-1)); +} + +.reveal-2 { --hero-reveal-delay: var(--hero-reveal-2); } +.reveal-3 { --hero-reveal-delay: var(--hero-reveal-3); } +.reveal-4 { --hero-reveal-delay: var(--hero-reveal-4); } +.reveal-5 { --hero-reveal-delay: var(--hero-reveal-5); } + +@keyframes reveal { + to { opacity: 1; transform: translateY(0); } +} + +@media (prefers-reduced-motion: reduce) { + html { scroll-behavior: auto; } + .reveal { animation: none; opacity: 1; transform: none; } + .provider-reveal, + .features-section .provider-reveal, + .cli-section .provider-reveal, + .widgets-section .provider-reveal, + .technical-section .provider-reveal { + transform: none; + transition: opacity 160ms ease; + transition-delay: 0ms; + } + .usage-meter::before, + .usage-chart i { + transform: none; + transition: opacity 160ms ease; + } + .usage-meter::after, + .usage-meter i { transition: opacity 160ms ease; } + .system-menubar > * { + opacity: 1; + transform: none; + transition: none; + } + .menu-bar-mark span::before { + transform: scaleX(var(--mark-fill)); + transition: none; + } + .codex-popover { opacity: 1; transition: none; transform: translate(var(--hud-panel-nudge-x), var(--hud-panel-nudge-y)) scale(var(--popover-scale)); } +} + +.features-section { + position: relative; + border-top: 1px solid var(--page-line); + background: var(--page-bg); + color: var(--page-text); +} + +.technical-section { + position: relative; + border-top: 1px solid var(--page-line); + background: var(--page-bg); +} + +.features-heading { + margin: 0 0 clamp(2.5rem, 5vw, 3.75rem); + max-width: none; + color: var(--page-text); + font-size: clamp(2.2rem, 4vw, 4.5rem); + font-weight: 600; + letter-spacing: -0.07em; + line-height: 0.98; + white-space: nowrap; +} + +.section-title-line { + display: block; +} + +@media (min-width: 1280px) { + .section-title-line { white-space: nowrap; } +} + +.features-grid { + display: grid; + gap: clamp(2rem, 3vw, 2.75rem); +} + +@media (min-width: 900px) { + .features-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } +} + +.feature-card { + display: flex; + flex-direction: column; + height: 100%; +} + +.feature-card h3 { + margin: 0; + color: var(--page-text); + font-size: clamp(1.12rem, 1.35vw, 1.32rem); + font-weight: 650; + letter-spacing: -0.035em; + line-height: 1.15; +} + +.feature-card-copy { + margin-top: auto; + margin-bottom: 1.35rem; +} + +.feature-card p { + margin: 0.7rem 0 0; + color: var(--page-muted); + font-size: clamp(0.94rem, 1vw, 1rem); + line-height: 1.52; + letter-spacing: -0.02em; +} + +.feature-card-visual { + position: relative; + flex: none; + width: 100%; + aspect-ratio: 27 / 17; + overflow: hidden; + border: 1px solid var(--page-line); + border-radius: 0.8rem; + background: var(--page-bg); + line-height: 0; + container-type: size; + container-name: feature-visual; +} + +.feature-card-visual img { + display: block; + width: 100%; + height: 100%; + object-fit: cover; + object-position: top center; +} + +.feature-card-overlay { + position: absolute; + inset: 0 14% 18% 14%; + border-bottom-left-radius: 0.8rem; + border-bottom-right-radius: 0.8rem; + background: rgba(14, 14, 16, 0.56); + backdrop-filter: blur(24px) saturate(1.4); + -webkit-backdrop-filter: blur(24px) saturate(1.4); + line-height: normal; + overflow: hidden; + isolation: isolate; +} + +.feature-card-overlay.is-usage-menu { + box-shadow: none; +} + +.feature-usage-panel, +.feature-cost-panel, +.feature-status-panel { + height: 100%; + padding: 5% 6%; + border-bottom-left-radius: inherit; + border-bottom-right-radius: inherit; + background: transparent; + color: rgba(244, 244, 245, 0.96); + font-size: clamp(0.55rem, 3.8cqw, 0.76rem); + letter-spacing: -0.02em; +} + +.feature-cost-stats { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 0.45em 0.75em; + margin: 0; +} + +.feature-credit-head { + display: grid; + grid-template-columns: minmax(0, 1fr) auto; + align-items: center; + gap: 0.85em; + margin-bottom: 0.5em; + padding-bottom: 0.5em; + border-bottom: 1px solid rgba(255, 255, 255, 0.1); +} + +.feature-credit-head p { + margin: 0; +} + +.feature-credit-head strong, +.feature-credit-head span { + display: block; + white-space: nowrap; +} + +.feature-credit-head strong { + color: rgba(244, 244, 245, 0.9); + font-size: 1em; + font-weight: 650; + letter-spacing: -0.03em; + line-height: 1.15; +} + +.feature-credit-head span { + margin-top: 0.18rem; + color: rgba(244, 244, 245, 0.52); + font-size: 0.95em; + font-weight: 500; + line-height: 1.2; +} + +.feature-credit-head p:last-child { + align-self: center; + color: rgba(244, 244, 245, 0.64); + font-size: 0.94em; + text-align: right; +} + +.feature-cost-stats > div { + min-width: 0; +} + +.feature-cost-stats dt { + margin: 0; + color: rgba(244, 244, 245, 0.5); + font-size: 0.9em; + font-weight: 500; + line-height: 1.2; +} + +.feature-cost-stats dd { + margin: 0.1rem 0 0; + font-size: 1.08em; + font-weight: 650; + letter-spacing: -0.03em; + line-height: 1.15; + white-space: nowrap; +} + +.feature-cost-chart { + display: flex; + align-items: flex-end; + gap: 1.5px; + height: clamp(1.25rem, 16cqh, 2.55rem); + margin-top: 0.5em; +} + +.feature-cost-chart > i { + flex: 1; + min-width: 0; + height: var(--h); + border-radius: 2px 2px 1px 1px; + background: #3584a3; +} + +.feature-card-overlay.is-status-menu { + background: rgba(14, 14, 16, 0.62); +} + +.feature-status-panel { + display: flex; + flex-direction: column; + justify-content: center; +} + +.feature-status-summary { + display: flex; + align-items: center; + justify-content: space-between; + gap: 0.65em; + margin: 0 0 0.85em; + color: #fff; + font-size: 1.02em; + font-weight: 650; + letter-spacing: -0.03em; + line-height: 1.2; +} + +.feature-status-summary span { + flex: none; + color: rgba(255, 255, 255, 0.86); + font-size: 0.8em; + font-weight: 600; +} + +.feature-status-list { + list-style: none; + margin: 0; + padding: 0; + display: grid; + gap: 0.22em; +} + +.feature-status-list li { + display: grid; + grid-template-columns: auto minmax(0, 1fr) auto; + align-items: center; + gap: 0.35em; + min-height: 1.35em; + padding: 0.15em 0.28em; + border-radius: 0.34rem; + background: rgba(255, 255, 255, 0.055); +} + +.feature-status-dot { + width: 0.42em; + height: 0.42em; + border-radius: 999px; + background: #33c759; +} + +.feature-status-list li.is-minor .feature-status-dot { + background: #f5c518; +} + +.feature-status-list li.is-critical .feature-status-dot { + background: #e84d3f; +} + +.feature-status-name { + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + color: rgba(244, 244, 245, 0.82); + font-weight: 600; +} + +.feature-status-label { + color: rgba(244, 244, 245, 0.62); + font-size: 0.92em; + font-weight: 500; + white-space: nowrap; +} + +.feature-usage-block + .feature-usage-block { + margin-top: 0.75em; +} + +.feature-usage-panel { + display: flex; + flex-direction: column; + justify-content: center; +} + +.feature-cost-panel { + display: flex; + flex-direction: column; + justify-content: center; +} + +.feature-usage-header { + display: grid; + grid-template-columns: minmax(0, 0.72fr) minmax(0, 1fr); + gap: 0.5em; + margin-bottom: 0.5em; + padding-bottom: 0.35em; + border-bottom: 1px solid rgba(255, 255, 255, 0.13); +} + +.feature-usage-header p, +.feature-usage-meta p { + margin: 0; +} + +.feature-usage-header strong, +.feature-usage-header span, +.feature-usage-meta strong, +.feature-usage-meta span { + display: block; +} + +.feature-usage-header strong { + color: rgba(244, 244, 245, 0.95); + font-size: 1.08em; + font-weight: 650; + letter-spacing: -0.035em; + line-height: 1.05; +} + +.feature-usage-header span { + margin-top: 0.14rem; + color: rgba(244, 244, 245, 0.5); + font-size: 0.9em; + font-weight: 500; + line-height: 1.2; +} + +.feature-usage-account { + text-align: right; +} + +.feature-usage-account strong { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.feature-usage-title { + margin: 0; + color: rgba(244, 244, 245, 0.96); + font-size: 1.08em; + font-weight: 650; + letter-spacing: -0.03em; + line-height: 1.1; +} + +.feature-usage-track { + position: relative; + height: 0.42em; + margin-top: 0.38em; + border-radius: 999px; + background: rgba(255, 255, 255, 0.12); + overflow: hidden; +} + +.feature-usage-fill { + position: relative; + display: flex; + height: 100%; + width: var(--amount, 100%); + border-radius: inherit; +} + +.feature-usage-fill > i { + flex: var(--flex); + min-width: 0; + background: #3584a3; +} + +.feature-usage-fill > i.is-reserve { + background: #3584a3; +} + +.feature-usage-fill > i.is-spent { + background: rgba(255, 255, 255, 0.12); +} + +.feature-usage-fill::after { + content: ''; + position: absolute; + inset: 0; + background: repeating-linear-gradient( + 90deg, + rgba(0, 0, 0, 0.16) 0, + rgba(0, 0, 0, 0.16) 1px, + transparent 1px, + transparent 25% + ); + pointer-events: none; +} + +.feature-usage-track::after { + content: ""; + position: absolute; + inset: 0; + background: + linear-gradient(90deg, transparent 19.8%, rgba(255, 255, 255, 0.5) 19.8% 20.2%, transparent 20.2%), + linear-gradient(90deg, transparent 49.8%, rgba(255, 255, 255, 0.4) 49.8% 50.2%, transparent 50.2%); + pointer-events: none; +} + +.feature-usage-meta { + display: grid; + grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); + align-items: start; + gap: 0.45em; + margin-top: 0.28em; + color: rgba(244, 244, 245, 0.5); + font-size: 0.9em; + font-weight: 500; + letter-spacing: -0.035em; + line-height: 1.18; +} + +.feature-usage-panel p, +.feature-usage-panel strong, +.feature-usage-panel span { + color: inherit; + font-size: inherit; + line-height: inherit; +} + +.feature-usage-meta strong, +.feature-usage-meta span { + white-space: nowrap; +} + +.feature-usage-meta span { + margin-top: 0.12rem; +} + +.feature-usage-meta .is-subtle { + color: rgba(244, 244, 245, 0.5); +} + +.feature-usage-meta > :last-child { + text-align: right; +} + +.cli-section, +.widgets-section { + position: relative; + border-top: 1px solid var(--page-line); + background: var(--page-bg); + color: var(--page-text); +} + +.split-layout { + display: grid; + gap: clamp(2.5rem, 5vw, 4rem); + align-items: center; +} + +@media (min-width: 769px) { + .split-layout { + grid-template-columns: minmax(0, 1.08fr) minmax(0, 0.68fr); + gap: clamp(1.75rem, 4vw, 2.75rem); + } + + .split-layout--copy-left { + grid-template-columns: minmax(0, 0.68fr) minmax(0, 1.08fr); + } + + .split-layout--copy-left .split-copy { + text-align: right; + } + + .split-layout--copy-left .split-copy-heading, + .split-layout--copy-left .split-copy-lead, + .split-layout--copy-left .split-copy-note { + margin-left: auto; + } +} + +@media (min-width: 1920px) { + .mockup-wrap, + .mockup-hud-layer { + width: calc(var(--mockup-tune-width) * 1.18px); + transform: translate(calc(-50% + var(--mockup-x)), var(--mockup-y)) scale(var(--mockup-layout-scale, var(--mockup-scale))); + } +} + +@media (min-width: 1024px) { + .hero-section { + min-height: calc(100vh - 2.5rem); + } + + .split-layout { + grid-template-columns: minmax(0, 1.12fr) minmax(0, 0.82fr); + gap: clamp(2.5rem, 5vw, 4rem); + } + + .split-layout--copy-left { + grid-template-columns: minmax(0, 0.82fr) minmax(0, 1.18fr); + } +} + +@media (min-width: 1024px) and (max-width: 1279px) { + .hero-copy h1 { + font-size: clamp(2.65rem, 4.8vw, 3.35rem) !important; + } +} + +@media (min-width: 1024px) and (max-height: 820px) { + .hero-copy { + padding-top: clamp(8rem, 20vh, 10.4rem); + } +} + +@media (min-width: 769px) and (max-width: 1023px) { + .hero-section { + position: relative; + min-height: auto; + height: auto; + padding: 0; + overflow: hidden; + isolation: isolate; + } + + .mockup-stage { + position: relative; + z-index: 1; + width: 100%; + height: var(--tablet-mockup-stage-height); + aspect-ratio: auto; + overflow: hidden; + } + + .mockup-wrap::after { + height: 42%; + } + + .mockup-glow { + top: 18%; + } + + .mockup-wrap, + .mockup-hud-layer { + top: var(--header-height); + transform: translate(calc(-50% + var(--tablet-mockup-x)), var(--tablet-mockup-y)) + scale(calc(var(--tablet-mockup-scale) * clamp(1, calc(var(--tablet-mockup-tune-width) * 1px / 100vw), var(--tablet-mockup-fluid-max)))); + } + + .hero-section::after { + z-index: 8; + height: clamp(8rem, 22vh, 14rem); + } + + .hero-content { + position: absolute; + inset: var(--header-height) 0 0; + z-index: 10; + } + + .hero-copy { + max-width: min(42rem, 58vw); + padding-top: clamp(5rem, 12vh, 6.75rem); + padding-bottom: 1rem; + } + + .hero-copy h1 { + margin-top: 1rem; + font-size: clamp(3rem, 6.25vw, 3.55rem) !important; + letter-spacing: 0 !important; + line-height: 1.01 !important; + text-wrap: balance; + } + + .hero-copy p { + max-width: min(32rem, 58vw); + margin-top: 1rem; + letter-spacing: 0 !important; + } + + .hero-cta-row { + margin-top: 1.25rem; + } + + .hero-copy > p:last-child { + margin-top: 0.85rem; + } + + .codex-popover { + top: var(--tablet-hud-panel-top); + right: var(--tablet-hud-panel-margin-right); + width: var(--tablet-hud-panel-width); + transform: translate(var(--hud-panel-nudge-x), var(--hud-panel-nudge-y)) scale(var(--tablet-popover-scale)); + } +} + +.split-copy-heading { + margin: 0 0 clamp(1.1rem, 2vw, 1.5rem); + max-width: 12ch; + color: var(--page-text); + font-size: clamp(2.2rem, 4vw, 4.5rem); + font-weight: 600; + letter-spacing: -0.07em; + line-height: 0.98; +} + +.split-copy-lead { + margin: 0 0 1rem; + max-width: 34ch; + color: var(--page-muted); + font-size: clamp(1rem, 1.35vw, 1.22rem); + letter-spacing: -0.035em; + line-height: 1.45; + text-wrap: balance; +} + +.split-copy-note { + margin: 0; + max-width: 32ch; + color: var(--page-subtle); + font-size: 0.88rem; + letter-spacing: -0.02em; + line-height: 1.45; +} + +.split-visual-wrap { + min-width: 0; +} + +.mac-widget-sheet { + overflow: hidden; + border: 1px solid rgba(255, 255, 255, 0.12); + border-radius: 1.15rem; + background: + linear-gradient(180deg, rgba(58, 58, 60, 0.94) 0%, rgba(28, 28, 30, 0.98) 100%); + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.1), + 0 1.75rem 3.5rem rgba(0, 0, 0, 0.48); + color: rgba(255, 255, 255, 0.9); + font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', system-ui, sans-serif; + font-size: clamp(0.62rem, 0.72vw, 0.72rem); + letter-spacing: -0.01em; +} + +.mac-widget-sheet__body { + display: flex; + align-items: stretch; + height: clamp(16rem, 28vw, 22rem); + overflow: hidden; +} + +.mac-widget-sidebar { + flex: 0 0 clamp(7.5rem, 20%, 10.5rem); + padding: 0.8rem 0.55rem; + border-right: 1px solid rgba(255, 255, 255, 0.08); + background: rgba(0, 0, 0, 0.14); +} + +.mac-widget-search { + display: flex; + align-items: center; + gap: 0.35rem; + margin-bottom: 0.8rem; + padding: 0.38rem 0.5rem; + border-radius: 0.42rem; + background: rgba(255, 255, 255, 0.08); + color: rgba(255, 255, 255, 0.72); +} + +.mac-widget-search svg { + flex: 0 0 auto; + width: 0.72rem; + height: 0.72rem; + color: rgba(255, 255, 255, 0.42); +} + +.mac-widget-nav { + display: grid; + gap: 0.2rem; + margin: 0; + padding: 0; + list-style: none; +} + +.mac-widget-nav li { + display: flex; + align-items: center; + gap: 0.45rem; + padding: 0.34rem 0.42rem; + border-radius: 0.42rem; + color: rgba(255, 255, 255, 0.72); + line-height: 1.2; +} + +.mac-widget-nav li.is-active { + background: rgba(255, 255, 255, 0.12); + color: rgba(255, 255, 255, 0.95); +} + +.mac-widget-nav-icon { + display: grid; + flex: 0 0 1.15rem; + place-items: center; + width: 1.15rem; + height: 1.15rem; + border-radius: 0.28rem; + background: rgba(255, 255, 255, 0.1); + color: rgba(255, 255, 255, 0.72); +} + +.mac-widget-nav-icon.is-app { + overflow: hidden; + background: #0a84ff; +} + +.mac-widget-nav-icon.is-app img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.mac-widget-main { + display: flex; + flex: 1; + flex-direction: column; + min-width: 0; + min-height: 0; + overflow: hidden; + padding: 0.8rem 0.85rem 0; +} + +.mac-widget-main__title { + margin: 0 0 0.7rem; + flex: none; + color: rgba(255, 255, 255, 0.42); + font-size: 0.95em; + font-weight: 500; +} + +.mac-widget-gallery-wrap { + position: relative; + flex: 1; + min-height: 0; + margin-inline: -0.85rem; + overflow: hidden; +} + +.mac-widget-gallery-wrap::after { + content: ''; + position: absolute; + right: 7px; + bottom: 0; + left: 0; + z-index: 1; + height: 2.75rem; + pointer-events: none; + background: linear-gradient(180deg, rgba(30, 30, 32, 0), rgba(26, 26, 28, 0.94) 68%, rgba(24, 24, 26, 1)); + opacity: 0; + transition: opacity 180ms ease; +} + +.mac-widget-gallery-wrap.has-scroll-fade::after { + opacity: 1; +} + +.mac-widget-gallery { + height: 100%; + overflow-y: auto; + overscroll-behavior: contain; + padding-inline: 0.85rem; + padding-bottom: 1.25rem; +} + +.mac-widget-gallery::-webkit-scrollbar { + width: 5px; +} + +.mac-widget-gallery::-webkit-scrollbar-thumb { + border-radius: 999px; + background: rgba(255, 255, 255, 0.22); +} + +.mac-widget-row { + display: flex; + align-items: flex-start; + gap: clamp(0.45rem, 1.2vw, 0.8rem); +} + +.mac-widget-row + .mac-widget-row { + margin-top: 0.55rem; +} + +.widget-tile { + display: flex; + flex: 1 1 0; + flex-direction: column; + align-items: center; + gap: 0.15rem; + min-width: 0; + text-align: center; +} + +.widget-preview { + width: 100%; + margin-bottom: 0.45rem; + overflow: hidden; + border-radius: 1rem; + background: #18181a; + box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.35); + line-height: 0; +} + +.widget-preview img { + display: block; + width: 100%; + height: auto; + transform: scale(1.03); + transform-origin: center; +} + +.widget-tile.is-small .widget-preview { + width: min(100%, 5.4rem); +} + +.widget-tile h4 { + margin: 0; + color: rgba(255, 255, 255, 0.95); + font-size: 0.95em; + font-weight: 600; + line-height: 1.2; +} + +.widget-tile p { + margin: 0; + color: rgba(255, 255, 255, 0.42); + font-size: 0.88em; + line-height: 1.25; +} + +.mac-widget-sheet__foot { + display: flex; + align-items: center; + justify-content: space-between; + gap: 1rem; + padding: 0.62rem 0.9rem; + border-top: 1px solid rgba(255, 255, 255, 0.08); + color: rgba(255, 255, 255, 0.48); +} + +.mac-widget-sheet__foot p { + margin: 0; +} + +.mac-widget-ok { + flex: 0 0 auto; + padding: 0.28rem 1rem; + border-radius: 999px; + background: #0a84ff; + color: #fff; + font-size: 0.95em; + font-weight: 600; + line-height: 1.2; +} + +.cli-terminal { + overflow: hidden; + border: 1px solid rgba(255, 255, 255, 0.1); + border-radius: 1rem; + background: linear-gradient(180deg, rgba(24, 24, 26, 0.96), rgba(12, 12, 13, 0.98)); + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.08), + 0 1.5rem 3.5rem rgba(0, 0, 0, 0.45); + font-family: 'SFMono-Regular', 'SF Mono', Menlo, monospace; + font-size: clamp(0.68rem, 0.82vw, 0.8rem); + letter-spacing: -0.02em; + line-height: 1.45; +} + +.cli-terminal-chrome { + display: flex; + align-items: center; + justify-content: space-between; + gap: 1rem; + padding: 0.7rem 0.95rem; + border-bottom: 1px solid rgba(255, 255, 255, 0.08); + color: rgba(244, 244, 245, 0.72); +} + +.cli-terminal-dots { + display: flex; + align-items: center; + gap: 0.38rem; +} + +.cli-terminal-dots span { + width: 0.58rem; + height: 0.58rem; + border-radius: 999px; + background: rgba(255, 255, 255, 0.18); +} + +.cli-terminal-dots span:nth-child(1) { background: #ff5f57; } +.cli-terminal-dots span:nth-child(2) { background: #febc2e; } +.cli-terminal-dots span:nth-child(3) { background: #28c840; } + +.cli-terminal-title { + flex: 1; + text-align: center; + color: rgba(244, 244, 245, 0.58); +} + +.cli-terminal-chrome-spacer { + flex: none; + width: calc(0.58rem * 3 + 0.38rem * 2); +} + +.cli-terminal-body { + padding: 1rem 1rem 0.35rem; +} + +.cli-provider-block + .cli-provider-block { + margin-top: 1.15rem; + padding-top: 1.05rem; + border-top: 1px solid rgba(255, 255, 255, 0.08); +} + +.cli-provider-label { + margin-bottom: 0.75rem; + color: rgba(244, 244, 245, 0.88); + font-weight: 600; +} + +.cli-row { + display: grid; + grid-template-columns: minmax(4.5rem, 5.5rem) minmax(4.5rem, 6rem) 1fr auto; + gap: 0.55rem 0.75rem; + align-items: center; + margin-bottom: 0.42rem; +} + +.cli-row.is-meta { + grid-template-columns: minmax(4.5rem, 5.5rem) 1fr; +} + +.cli-row-label { + color: rgba(244, 244, 245, 0.58); +} + +.cli-row-value { + color: rgba(244, 244, 245, 0.92); +} + +.cli-meter { + display: flex; + gap: 0.12rem; + min-width: 0; +} + +.cli-meter i { + flex: 1; + min-width: 0.28rem; + max-width: 0.55rem; + height: 0.62rem; + border-radius: 0.1rem; + background: rgba(255, 255, 255, 0.1); +} + +.cli-meter i.is-filled { + background: #0099ff; +} + +.cli-row-note { + color: rgba(244, 244, 245, 0.48); + white-space: nowrap; +} + +.cli-terminal-foot { + display: flex; + align-items: center; + justify-content: flex-start; + gap: 1rem; + margin-top: 0.85rem; + padding: 0.8rem 1rem; + border-top: 1px solid rgba(255, 255, 255, 0.08); + color: rgba(244, 244, 245, 0.72); +} + +.cli-terminal-foot strong { + color: rgba(244, 244, 245, 0.92); + font-weight: 600; +} + +.cli-terminal-cursor { + color: rgba(244, 244, 245, 0.55); + animation: cli-cursor-blink 1.1s step-end infinite; +} + +@keyframes cli-cursor-blink { + 50% { opacity: 0; } +} + +.cli-footnote { + display: flex; + align-items: flex-start; + justify-content: flex-start; + gap: 0.35rem; + margin-top: clamp(1.5rem, 3vw, 2rem); + color: var(--page-subtle); + font-size: 0.82rem; + letter-spacing: -0.02em; + line-height: 1.45; +} + +.cli-footnote span { + max-width: 38ch; + text-wrap: balance; +} + +.cli-footnote svg { + width: 1.15rem; + height: 1.15rem; + flex: none; + color: #0099ff; +} + +@media (max-width: 720px) { + .cli-row { + grid-template-columns: 1fr; + gap: 0.25rem; + } + + .cli-row-note { white-space: normal; } +} + +.section-eyebrow { + margin: 0 0 1.35rem; + color: var(--page-faint); + font-size: 0.72rem; + font-weight: 600; + letter-spacing: 0.16em; + line-height: 1; + text-transform: uppercase; +} + +.technical-grid { + display: grid; + gap: 2rem; +} + +@media (min-width: 768px) { + .technical-grid { + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 2.5rem 3.5rem; + } +} + +.technical-block h3 { + margin: 0; + color: var(--page-text); + font-size: 0.98rem; + font-weight: 650; + letter-spacing: -0.03em; + line-height: 1.2; +} + +.technical-block p { + margin: 0.5rem 0 0; + color: var(--page-subtle); + font-size: 0.92rem; + line-height: 1.55; + letter-spacing: -0.02em; +} + +.text-link { + color: #0099ff; + text-decoration: none; + transition: color 140ms ease; +} + +.text-link:hover { color: #33adff; } + +.inline-code { + display: inline; + padding: 0.12em 0.42em; + border-radius: 0.35rem; + background: color-mix(in srgb, var(--page-text) 7%, transparent); + color: var(--page-text); + font-family: 'SFMono-Regular', 'SF Mono', Menlo, monospace; + font-size: 0.88em; + letter-spacing: -0.02em; + white-space: nowrap; +} + +[data-brew-icon] [data-icon="check"] { display: none; } + +[data-brew-icon][data-copied="true"] { + color: #4ade80; +} + +[data-brew-icon][data-copied="true"] [data-icon="copy"] { display: none; } +[data-brew-icon][data-copied="true"] [data-icon="check"] { display: block; } + +.site-footer { + border-top: 1px solid var(--page-line); + padding: 1.75rem 1.25rem 2.5rem; + color: var(--page-faint); + font-size: 0.82rem; + letter-spacing: -0.02em; + line-height: 1.5; + text-align: center; +} + +.site-footer a { + color: var(--page-subtle); + text-decoration: none; + transition: color 140ms ease; +} + +@media (hover: hover) and (pointer: fine) { + .site-footer a:hover { color: var(--page-text); } +} + +@media (max-width: 768px) { + .cli-section .split-layout .split-copy { + order: 1; + text-align: left; + } + + .cli-section .split-layout .split-visual-wrap { + order: 2; + } +} + +@media (max-width: 720px) { + .cli-section, + .widgets-section, + .technical-section { + padding-top: 4.25rem; + padding-bottom: 4.25rem; + } + + .split-layout, + .split-layout--copy-left { + gap: 2rem; + } + + .split-copy, + .split-layout--copy-left .split-copy { + text-align: left; + } + + .split-copy-heading { + max-width: 11ch; + font-size: 2.25rem; + letter-spacing: 0; + line-height: 1.02; + } + + .split-copy-lead, + .split-copy-note { + max-width: 100%; + letter-spacing: 0; + } + + .cli-terminal { + border-radius: 0.85rem; + font-size: 0.62rem; + letter-spacing: 0; + } + + .cli-terminal-chrome { + padding: 0.62rem 0.78rem; + } + + .cli-terminal-body { + padding: 0.95rem 0.88rem 0.35rem; + } + + .cli-provider-block + .cli-provider-block { + margin-top: 0.9rem; + padding-top: 0.85rem; + } + + .cli-provider-label { + margin-bottom: 0.58rem; + } + + .cli-row:not(.is-meta) { + grid-template-columns: 4.35rem 5.55rem minmax(0, 1fr); + gap: 0.22rem 0.48rem; + margin-bottom: 0.48rem; + } + + .cli-row.is-meta { + grid-template-columns: 7.65rem minmax(0, 1fr); + gap: 0.22rem 0.48rem; + margin-bottom: 0.42rem; + } + + .cli-row.is-meta .cli-row-value { + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + .cli-row-note { + grid-column: 3; + justify-self: end; + white-space: nowrap; + } + + .cli-meter { + width: 100%; + min-width: 0; + } + + .cli-terminal-foot { + padding: 0.68rem 0.82rem; + } + + .cli-footnote { + align-items: center; + } +} + +@media (max-width: 768px) { + main#top > section:first-child { + display: flex; + min-height: auto; + flex-direction: column; + overflow: hidden; + padding-top: var(--header-height); + background: var(--page-bg); + } + + .hero-content { + order: 1; + width: 100%; + } + + .hero-copy { + width: 100%; + max-width: none; + margin-inline: 0; + padding: 2.25rem 0 0; + text-align: left; + } + + .hero-copy .justify-center { + justify-content: flex-start !important; + } + + .hero-copy h1 { + margin-top: 1.05rem; + font-size: clamp(2.45rem, 11vw, 3.35rem) !important; + letter-spacing: 0 !important; + line-height: 1.02 !important; + text-wrap: balance; + } + + .hero-title-line { + display: inline; + } + + .hero-title-line + .hero-title-line::before { + content: " "; + } + + .hero-copy p { + margin-top: 1.1rem; + max-width: none; + letter-spacing: 0 !important; + } + + .hero-copy > p:last-child { + text-align: center; + } + + .hero-copy br { + display: none !important; + } + + .hero-cta-row { + justify-content: flex-start; + gap: 0.75rem; + margin-top: 1.55rem; + } + + .hero-download, + .brew-pill { + width: 100%; + justify-content: center; + } + + .brew-pill { + height: auto; + min-height: 2.75rem; + padding: 0.7rem 1rem; + overflow: hidden; + border: 1px solid var(--control-border); + border-radius: 0.85rem; + background: var(--control-bg); + box-shadow: none; + backdrop-filter: none; + color: var(--page-text); + } + + .brew-pill [data-brew-label], + .brew-pill .text-zinc-100 { + color: var(--page-text) !important; + } + + .brew-pill .text-zinc-400, + .brew-pill [data-brew-icon] { + color: var(--page-muted) !important; + } + + .brew-pill [data-brew-label] { + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + font-size: 0.76rem; + letter-spacing: -0.02em; + } + + :root[data-theme="light"] .hero-copy .brew-pill { + background: var(--control-bg); + border-color: var(--control-border); + box-shadow: none; + } + + @media (hover: hover) and (pointer: fine) { + .brew-pill:hover { + background: var(--control-hover) !important; + } + } + + .brew-pill:active { + background: var(--control-active) !important; + } + + .mockup-stage { + position: relative; + order: 2; + width: 100%; + height: var(--mobile-mockup-stage-height); + margin-top: 1.35rem; + overflow: hidden; + background: var(--hero-bg); + } + + :root[data-theme="light"] .hero-copy .text-zinc-100 { + color: var(--page-text) !important; + } + + :root[data-theme="light"] .hero-copy .text-zinc-400 { + color: var(--page-muted) !important; + } + + :root[data-theme="light"] .hero-copy .text-zinc-600 { + color: var(--page-faint) !important; + } + + .mockup-glow { + display: none; + } + + /* MacBook + HUD: right-anchored in full-bleed stage — crops notch, shows menu-bar side */ + .mockup-wrap, + .mockup-hud-layer { + top: 0; + left: auto; + right: 0; + width: var(--mobile-mockup-width); + aspect-ratio: 6111 / 3239; + transform: translate(var(--mobile-mockup-offset-x), var(--mobile-mockup-offset-y)) + scale(var(--mobile-mockup-scale)); + transform-origin: top right; + } + + .mockup-hud-layer { + bottom: auto; + height: auto; + z-index: 5; + } + + .mockup-wrap::after { + height: 42%; + } + + .system-menubar { + top: var(--mobile-hud-anchor-top); + right: var(--mobile-hud-margin-right); + gap: calc(var(--mobile-menubar-gap) / var(--mobile-menubar-scale)); + transform: translate(var(--mobile-hud-menu-nudge-x), var(--mobile-hud-menu-nudge-y)) scale(var(--mobile-menubar-scale)); + transform-origin: top right; + font-size: clamp(0.48rem, 0.52cqw, 0.75rem); + } + + .codex-popover { + top: var(--mobile-hud-panel-top); + right: var(--mobile-hud-panel-margin-right); + width: var(--mobile-hud-panel-width); + transform: translate(var(--hud-panel-nudge-x), var(--hud-panel-nudge-y)) scale(var(--mobile-popover-scale)); + transform-origin: top right; + border-radius: 0.65rem; + } + + .provider-section, + .features-section { + padding-top: 4rem; + padding-bottom: 4rem; + } + + .provider-section .section-inner > ul { + display: grid !important; + grid-template-columns: repeat(3, minmax(0, 1fr)) !important; + gap: 1.35rem 0.85rem !important; + } + + .provider-card { + min-height: auto !important; + text-align: center; + } + + .provider-card-link { + min-height: 0; + grid-template-columns: minmax(0, 1fr); + justify-items: center; + gap: 0.45rem; + padding: 0.2rem 0 !important; + } + + .provider-card-link p { + width: 100%; + min-width: 0; + } + + .provider-logo { + width: 2.15rem; + height: 2.15rem; + font-size: 0.68rem; + } + + .provider-logo::before { + inset: 0.48rem; + } + + .provider-logo img, + .provider-logo > svg { + width: 1.25rem; + height: 1.25rem; + } + + .provider-section h2, + .features-heading { + white-space: normal; + font-size: clamp(2rem, 8.8vw, 2.35rem); + letter-spacing: 0; + line-height: 1.03; + } + + .features-heading { + max-width: 12ch; + } + + .section-title-line { + white-space: normal; + } + + .provider-card p > strong, + .provider-card p > span, + .feature-card h3, + .feature-card-copy p, + .technical-block h3, + .technical-block p, + .site-footer { + letter-spacing: 0; + } + + .provider-card p > strong { + font-size: 0.82rem; + line-height: 1.08; + overflow-wrap: anywhere; + } + + .provider-card p > span { + margin-top: 0.18rem; + font-size: 0.7rem; + line-height: 1.12; + overflow-wrap: anywhere; + } + + .features-heading { + margin-bottom: 2rem; + } + + .features-grid { + gap: 2.2rem; + } + + .feature-card-copy { + margin-bottom: 0.9rem; + } + + .feature-card-copy p { + font-size: 0.98rem; + line-height: 1.48; + } + + .feature-card-visual { + aspect-ratio: 4 / 3; + border-radius: 0.72rem; + } + + .inline-code { + white-space: normal; + overflow-wrap: anywhere; + } +} diff --git a/docs/site.js b/docs/site.js new file mode 100644 index 0000000..f218ffb --- /dev/null +++ b/docs/site.js @@ -0,0 +1,737 @@ +import { localeCatalog, localeMessages } from './site-locales.mjs'; + +const root = document.documentElement; +let activeMessages = localeMessages.en; + +const HERO_MOBILE_MAX = 768; +const HERO_TABLET_MAX = 1023; +const HERO_DESKTOP_MIN = 1024; +const MOCKUP_SCREEN_MARGIN_RIGHT = 50; +const MOCKUP_SCREEN_MARGIN_RIGHT_TABLET = 15; +const MOCKUP_ARTBOARD_RATIO = 1.18; +/* Tablet MacBook X tune @ 1001px, scale 1.2 */ +const HERO_TABLET_MOCKUP_X_CORRECTION = -9; + +const HERO_MOBILE_MOCKUP_TUNE_SCALE = 0.99; +/* Mobile MacBook X tune @ 490px, right-anchored full-bleed stage */ +const HERO_MOBILE_MOCKUP_X_CORRECTION = -32; + +const HERO_ARTBOARD = { width: 6111, height: 3239 }; + +/* Figma @ 6111×3239 — menubar anchor 130 top / 150 right; scale 0.94 (desktop) / 0.82 (mobile) */ +const HERO_MENUBAR_BASE = { + figmaTop: 130, + figmaRight: 150, + scale: 0.94, + mobileScale: 0.82, + iconScale: 1.28, +}; + +/* Visual correction vs computed base (tune @ 1920 → 5.25%, 3.8%, scale ×1.55) */ +const HERO_MENUBAR_CORRECTION = { + top: 5.25 / ((HERO_MENUBAR_BASE.figmaTop / HERO_ARTBOARD.height) * 100), + right: 3.8 / ((HERO_MENUBAR_BASE.figmaRight / HERO_ARTBOARD.width) * 100), + scale: 1.55, +}; + +function getMenubarComputed() { + const topPx = HERO_MENUBAR_BASE.figmaTop * HERO_MENUBAR_CORRECTION.top; + const rightPx = HERO_MENUBAR_BASE.figmaRight * HERO_MENUBAR_CORRECTION.right; + const scale = HERO_MENUBAR_BASE.scale * HERO_MENUBAR_CORRECTION.scale; + const mobileScale = HERO_MENUBAR_BASE.mobileScale * HERO_MENUBAR_CORRECTION.scale; + return { + topPx, + rightPx, + anchorTop: `${artboardPxToTopPercent(topPx).toFixed(2)}%`, + marginRight: `${artboardPxToRightPercent(rightPx).toFixed(2)}%`, + scale: Math.round(scale * 1000) / 1000, + mobileScale: Math.round(mobileScale * 1000) / 1000, + }; +} + +const HERO_FIGMA_SCREEN = { paddingTop: 125, paddingRight: 141 }; + +const HERO_FIGMA_PANEL = { gapBelowMenubar: 20, insetBeyondPaddingRight: 30 }; + +const HERO_PANEL_WIDTH_ON_SCREEN = 0.191; + +function getMenubarRenderedHeightPx() { + const emPx = 0.52 * (HERO_ARTBOARD.width / 100); + return emPx * HERO_MENUBAR_BASE.iconScale * getMenubarComputed().scale; +} + +function getPanelBasePx() { + const menubar = getMenubarComputed(); + const menubarHeight = (menubar.topPx - HERO_FIGMA_SCREEN.paddingTop) + getMenubarRenderedHeightPx(); + return { + topPx: HERO_FIGMA_SCREEN.paddingTop + menubarHeight + HERO_FIGMA_PANEL.gapBelowMenubar, + rightPx: HERO_FIGMA_SCREEN.paddingRight + HERO_FIGMA_PANEL.insetBeyondPaddingRight, + }; +} + +/* SVG inner-screen geometry (panel width still % of inner screen) */ +const HERO_SCREEN_GEOMETRY = { + top: 124.92 / 3239, + width: (5970.48 - 140.89) / 6111, + height: (3239 - 124.92) / 3239, + rightInset: (6111 - 5970.48) / 6111, +}; + +function artboardPxToTopPercent(px) { + return (px / HERO_ARTBOARD.height) * 100; +} + +function artboardPxToRightPercent(px) { + return (px / HERO_ARTBOARD.width) * 100; +} + +const HERO_PANEL_BASE = { popoverScale: 0.91, mobilePopoverScale: 1.01 }; + +/* Visual correction vs computed base (tune @ 1920 → 8.5%, 3.7%, scale 0.85) */ +const HERO_PANEL_CORRECTION = (() => { + const base = getPanelBasePx(); + return { + top: 8.5 / artboardPxToTopPercent(base.topPx), + right: 3.7 / artboardPxToRightPercent(base.rightPx), + scale: 0.85 / HERO_PANEL_BASE.popoverScale, + }; +})(); + +/* Tablet-only correction (tune @ 1020 → top 9.5%, scale 1.35) */ +const HERO_PANEL_TABLET_CORRECTION = (() => { + const base = getPanelBasePx(); + return { + top: 9.5 / artboardPxToTopPercent(base.topPx), + scale: 1.35, + }; +})(); + +function getPanelComputed() { + const base = getPanelBasePx(); + const topPx = base.topPx * HERO_PANEL_CORRECTION.top; + const rightPx = base.rightPx * HERO_PANEL_CORRECTION.right; + const scale = Math.round(HERO_PANEL_BASE.popoverScale * HERO_PANEL_CORRECTION.scale * 1000) / 1000; + const mobileScale = Math.round(HERO_PANEL_BASE.mobilePopoverScale * HERO_PANEL_CORRECTION.scale * 1000) / 1000; + return { + topPx, + rightPx, + panelTop: `${artboardPxToTopPercent(topPx).toFixed(2)}%`, + panelMarginRight: `${artboardPxToRightPercent(rightPx).toFixed(2)}%`, + panelWidth: `${(HERO_PANEL_WIDTH_ON_SCREEN * HERO_SCREEN_GEOMETRY.width * 100).toFixed(2)}%`, + scale, + mobileScale, + }; +} + +/* Mobile-only correction (tune @ 490 → top/right/scale; @ 444 → width 20%) */ +const HERO_PANEL_MOBILE_CORRECTION = (() => { + const panel = getPanelComputed(); + return { + top: 9.15 / parseFloat(panel.panelTop), + right: 6 / parseFloat(panel.panelMarginRight), + width: 20 / parseFloat(panel.panelWidth), + scale: 1.39 / panel.mobileScale, + }; +})(); + +function getMobilePanelComputed() { + const base = getPanelBasePx(); + const panel = getPanelComputed(); + const topPx = base.topPx * HERO_PANEL_MOBILE_CORRECTION.top; + return { + panelTop: `${artboardPxToTopPercent(topPx).toFixed(2)}%`, + panelMarginRight: `${(parseFloat(panel.panelMarginRight) * HERO_PANEL_MOBILE_CORRECTION.right).toFixed(2)}%`, + panelWidth: `${(parseFloat(panel.panelWidth) * HERO_PANEL_MOBILE_CORRECTION.width).toFixed(2)}%`, + scale: Math.round(panel.mobileScale * HERO_PANEL_MOBILE_CORRECTION.scale * 1000) / 1000, + }; +} + +function getTabletPanelComputed() { + const base = getPanelBasePx(); + const panel = getPanelComputed(); + const topPx = base.topPx * HERO_PANEL_TABLET_CORRECTION.top; + return { + panelTop: `${artboardPxToTopPercent(topPx).toFixed(2)}%`, + panelMarginRight: panel.panelMarginRight, + panelWidth: panel.panelWidth, + scale: HERO_PANEL_TABLET_CORRECTION.scale, + }; +} + +function getHudDefaultsFromGeometry() { + const menubar = getMenubarComputed(); + const panel = getPanelComputed(); + const tabletPanel = getTabletPanelComputed(); + const mobilePanel = getMobilePanelComputed(); + return { + '--hud-anchor-top': menubar.anchorTop, + '--hud-margin-right': menubar.marginRight, + '--menubar-scale': String(menubar.scale), + '--mobile-hud-anchor-top': menubar.anchorTop, + '--mobile-hud-margin-right': menubar.marginRight, + '--mobile-menubar-scale': String(menubar.mobileScale), + '--hud-panel-top': panel.panelTop, + '--hud-panel-margin-right': panel.panelMarginRight, + '--hud-panel-width': panel.panelWidth, + '--popover-scale': String(panel.scale), + '--tablet-hud-panel-top': tabletPanel.panelTop, + '--tablet-hud-panel-margin-right': tabletPanel.panelMarginRight, + '--tablet-hud-panel-width': tabletPanel.panelWidth, + '--tablet-popover-scale': String(tabletPanel.scale), + '--mobile-hud-panel-top': mobilePanel.panelTop, + '--mobile-hud-panel-margin-right': mobilePanel.panelMarginRight, + '--mobile-hud-panel-width': mobilePanel.panelWidth, + '--mobile-popover-scale': String(mobilePanel.scale), + }; +} + +const HERO_DESKTOP_ANCHOR = { + width: 1920, + fluidMax: 1.22, + tabletTuneWidth: 1022, + tabletFluidMax: 1.18, + mockupY: 10, + mockupScale: 1.15, + tabletMockupScale: 1.2, +}; + +const HERO_LAYOUT_VARS = ['--mockup-x', '--mockup-y', '--tablet-mockup-x', '--tablet-mockup-stage-height']; + +function readRootPx(name, fallback) { + const raw = getComputedStyle(document.documentElement).getPropertyValue(name).trim(); + if (!raw) return fallback; + if (raw.endsWith('rem')) { + const rootFont = Number.parseFloat(getComputedStyle(document.documentElement).fontSize); + const rem = Number.parseFloat(raw); + return Number.isFinite(rem) && Number.isFinite(rootFont) ? rem * rootFont : fallback; + } + const value = Number.parseFloat(raw); + return Number.isFinite(value) ? value : fallback; +} + +function computeTabletStageHeight(width) { + const headerPx = readRootPx('--header-height', 64); + const tuneWidth = HERO_DESKTOP_ANCHOR.tabletTuneWidth; + const baseWidth = getMockupBaseWidth(width, tuneWidth); + const artboardHeight = baseWidth * (3239 / 6111); + const scale = getMockupEffectiveScale(width, { tablet: true }); + const scaledHeight = artboardHeight * scale; + const mockupY = readRootNumber('--tablet-mockup-y', 13); + const mockupBottom = headerPx + mockupY + scaledHeight; + const panelTop = readRootPercent('--tablet-hud-panel-top', 9.5); + const panelScale = readRootNumber('--tablet-popover-scale', 1.35); + const panelApproxHeight = scaledHeight * 0.36 * panelScale; + const panelBottom = headerPx + mockupY + scaledHeight * panelTop + panelApproxHeight; + + return Math.ceil(Math.max(mockupBottom, panelBottom) + 12); +} + +function getHeroFluidFactor(width, tuneWidth = HERO_DESKTOP_ANCHOR.width, fluidMax = HERO_DESKTOP_ANCHOR.fluidMax) { + return Math.min(Math.max(1, tuneWidth / width), fluidMax); +} + +function getMockupBaseWidth(width, tuneWidth = HERO_DESKTOP_ANCHOR.width) { + const layoutWidth = width >= tuneWidth ? tuneWidth : width; + return layoutWidth * MOCKUP_ARTBOARD_RATIO; +} + +function readRootNumber(name, fallback) { + const raw = getComputedStyle(document.documentElement).getPropertyValue(name).trim(); + const value = Number.parseFloat(raw); + return Number.isFinite(value) ? value : fallback; +} + +function readRootPercent(name, fallbackPercent) { + const raw = getComputedStyle(document.documentElement).getPropertyValue(name).trim(); + if (!raw) return fallbackPercent / 100; + if (raw.endsWith('%')) { + const value = Number.parseFloat(raw); + return Number.isFinite(value) ? value / 100 : fallbackPercent / 100; + } + const value = Number.parseFloat(raw); + return Number.isFinite(value) ? value / 100 : fallbackPercent / 100; +} + +function getMockupEffectiveScale(width, { tablet = false } = {}) { + const tuneWidth = tablet ? HERO_DESKTOP_ANCHOR.tabletTuneWidth : HERO_DESKTOP_ANCHOR.width; + const fluidMax = tablet ? HERO_DESKTOP_ANCHOR.tabletFluidMax : HERO_DESKTOP_ANCHOR.fluidMax; + const scale = tablet + ? readRootNumber('--tablet-mockup-scale', HERO_DESKTOP_ANCHOR.tabletMockupScale) + : readRootNumber('--mockup-scale', HERO_DESKTOP_ANCHOR.mockupScale); + if (width >= tuneWidth) return scale; + return scale * getHeroFluidFactor(width, tuneWidth, fluidMax); +} + +function computeMockupX(width, { tablet = false } = {}) { + const tuneWidth = tablet ? HERO_DESKTOP_ANCHOR.tabletTuneWidth : HERO_DESKTOP_ANCHOR.width; + const scaledWidth = getMockupBaseWidth(width, tuneWidth) * getMockupEffectiveScale(width, { tablet }); + const marginRight = tablet ? MOCKUP_SCREEN_MARGIN_RIGHT_TABLET : MOCKUP_SCREEN_MARGIN_RIGHT; + const baseX = (width / 2) - marginRight - (scaledWidth / 2); + return tablet ? baseX + HERO_TABLET_MOCKUP_X_CORRECTION : baseX; +} + +function getMobileStageWidth(viewportWidth) { + return viewportWidth; +} + +function computeMobileMockupOffsetX(viewportWidth) { + const stageWidth = getMobileStageWidth(viewportWidth); + const scale = readRootNumber('--mobile-mockup-scale', HERO_MOBILE_MOCKUP_TUNE_SCALE); + const widthPct = readRootNumber('--mobile-mockup-width', 251) / 100; + const scaledWidth = stageWidth * widthPct * scale; + const scaleNudge = (HERO_MOBILE_MOCKUP_TUNE_SCALE - scale) * scaledWidth * 0.5; + return Math.round((HERO_MOBILE_MOCKUP_X_CORRECTION + scaleNudge) * 100) / 100; +} + +function applyHudGeometryDefaults() { + const defaults = getHudDefaultsFromGeometry(); + const root = document.documentElement; + Object.entries(defaults).forEach(([name, value]) => { + if (!root.style.getPropertyValue(name)) { + root.style.setProperty(name, value); + } + }); +} + +function clearHeroDesktopLayout() { + HERO_LAYOUT_VARS.forEach((name) => document.documentElement.style.removeProperty(name)); +} + +function applyHeroDesktopLayout() { + const width = window.innerWidth; + const root = document.documentElement; + const isTablet = width > HERO_MOBILE_MAX && width <= HERO_TABLET_MAX; + const marginRight = isTablet ? MOCKUP_SCREEN_MARGIN_RIGHT_TABLET : MOCKUP_SCREEN_MARGIN_RIGHT; + root.style.setProperty('--mockup-screen-margin-right', `${marginRight}px`); + + if (width <= HERO_MOBILE_MAX) { + clearHeroDesktopLayout(); + root.style.setProperty('--mobile-mockup-offset-x', `${computeMobileMockupOffsetX(width)}px`); + return; + } + + root.style.removeProperty('--mobile-mockup-offset-x'); + + const mockupX = Math.round(computeMockupX(width, { tablet: isTablet }) * 100) / 100; + + if (width <= HERO_TABLET_MAX) { + root.style.setProperty('--tablet-mockup-x', `${mockupX}px`); + root.style.setProperty('--tablet-mockup-y', `${readRootNumber('--tablet-mockup-y', 13)}px`); + root.style.setProperty('--tablet-mockup-stage-height', `${computeTabletStageHeight(width)}px`); + root.style.removeProperty('--mockup-x'); + root.style.removeProperty('--mockup-y'); + return; + } + + root.style.setProperty('--mockup-x', `${mockupX}px`); + root.style.setProperty('--mockup-y', `${HERO_DESKTOP_ANCHOR.mockupY}px`); + root.style.removeProperty('--tablet-mockup-x'); + root.style.removeProperty('--tablet-mockup-y'); + root.style.removeProperty('--tablet-mockup-stage-height'); +} + +applyHudGeometryDefaults(); +applyHeroDesktopLayout(); + +window.addEventListener('resize', applyHeroDesktopLayout); +window.visualViewport?.addEventListener('resize', applyHeroDesktopLayout); + +const themeMedia = window.matchMedia('(prefers-color-scheme: dark)'); +const themeToggle = document.querySelector('#theme-toggle'); +const themeNames = { system: 'System', light: 'Light', dark: 'Dark' }; + +function applyThemePreference(preference, persist = true) { + const resolvedTheme = preference === 'system' + ? (themeMedia.matches ? 'dark' : 'light') + : preference; + + root.dataset.theme = resolvedTheme; + root.dataset.themePreference = preference; + themeToggle.dataset.themeValue = preference; + themeToggle.title = `${themeNames[preference]} theme`; + updateThemeToggleLabel(); + + if (persist) { + try { + localStorage.setItem('codexbar-theme', preference); + } catch (_) {} + } +} + +function updateThemeToggleLabel() { + const nextTheme = root.dataset.theme === 'dark' ? 'light' : 'dark'; + const label = message(nextTheme === 'dark' ? 'theme.toDark' : 'theme.toLight'); + themeToggle.setAttribute('aria-label', label); + themeToggle.title = label; +} + +themeToggle.addEventListener('click', () => { + const nextPreference = root.dataset.theme === 'dark' ? 'light' : 'dark'; + applyThemePreference(nextPreference); +}); + +themeMedia.addEventListener('change', () => { + if (root.dataset.themePreference === 'system') applyThemePreference('system', false); +}); + +applyThemePreference(root.dataset.themePreference || 'system', false); + +const languageShortNames = { + en: 'EN', + 'zh-CN': '简', + 'zh-TW': '繁', + 'ja-JP': 'JA', + es: 'ES', + 'pt-BR': 'PT', + ko: 'KO', + de: 'DE', + fr: 'FR', + ar: 'AR', + it: 'IT', + vi: 'VI', + nl: 'NL', + tr: 'TR', + uk: 'UK', + id: 'ID', + pl: 'PL', + fa: 'FA', + th: 'TH', + ca: 'CA', + sv: 'SV', +}; +const languages = localeCatalog.map((language) => ({ + ...language, + id: language.code, + short: languageShortNames[language.code] || language.code.slice(0, 2).toUpperCase(), + label: language.name, +})); +const supportedLanguages = new Set(languages.map((language) => language.id)); +const rtlLanguages = new Set(localeCatalog.filter((language) => language.direction === 'rtl').map((language) => language.code)); +const localeAliases = { + 'zh-cn': 'zh-CN', + 'zh-hans': 'zh-CN', + 'zh-hant': 'zh-TW', + 'zh-hk': 'zh-TW', + 'zh-tw': 'zh-TW', + ja: 'ja-JP', + pt: 'pt-BR', + 'pt-br': 'pt-BR', +}; +const languageStorageKey = 'codexbar-language'; +const languagePicker = document.querySelector('#language-picker'); +const languageTrigger = document.querySelector('#language-picker-trigger'); +const languageMenu = document.querySelector('#language-picker-menu'); +const languageList = document.querySelector('#language-picker-list'); +const languageShort = document.querySelector('[data-lang-short]'); + +function normalizeLocale(value) { + if (!value) return null; + const lower = value.toLowerCase(); + if (localeAliases[lower]) return localeAliases[lower]; + return languages.find((language) => language.id.toLowerCase() === lower || lower.startsWith(`${language.id.toLowerCase()}-`))?.id || null; +} + +function selectedLocale() { + try { + const queryLocale = normalizeLocale(new URLSearchParams(location.search).get('lang')); + if (queryLocale) return queryLocale; + const storedLocale = normalizeLocale(localStorage.getItem(languageStorageKey)); + if (storedLocale) return storedLocale; + } catch (_) {} + + for (const language of navigator.languages || [navigator.language]) { + const locale = normalizeLocale(language); + if (locale) return locale; + } + return 'en'; +} + +let activeLanguage = selectedLocale(); +if (!supportedLanguages.has(activeLanguage)) activeLanguage = 'en'; + +function message(key) { + return activeMessages[key] || localeMessages.en[key] || key; +} + +function applyAttributeMessages(dataAttribute, targetAttribute) { + document.querySelectorAll(`[${dataAttribute}]`).forEach((element) => { + element.setAttribute(targetAttribute, message(element.getAttribute(dataAttribute))); + }); +} + +function richToken(name) { + const codeTokens = { + cask: 'brew install --cask steipete/tap/codexbar', + codexbar: 'codexbar', + linuxCommand: 'brew install steipete/tap/codexbar', + upgrade: 'brew upgrade', + }; + if (codeTokens[name]) { + const code = document.createElement('code'); + code.className = 'inline-code'; + code.textContent = codeTokens[name]; + return code; + } + if (name === 'releases') { + const link = document.createElement('a'); + link.className = 'text-link'; + link.href = 'https://github.com/steipete/CodexBar/releases'; + link.textContent = 'GitHub Releases'; + return link; + } + if (name === 'issue') { + const link = document.createElement('a'); + link.className = 'text-link'; + link.href = 'https://github.com/steipete/CodexBar/issues/12'; + link.textContent = 'issue #12'; + return link; + } + if (name === 'mobileBreak') { + return document.createElement('br'); + } + if (name === 'break') { + const wrapper = document.createDocumentFragment(); + const space = document.createElement('span'); + space.className = 'inline sm:hidden'; + space.textContent = ' '; + const br = document.createElement('br'); + br.className = 'hidden sm:block'; + wrapper.append(space, br); + return wrapper; + } + return document.createTextNode(`{${name}}`); +} + +function renderRichMessage(element, value) { + const fragment = document.createDocumentFragment(); + const tokenPattern = /\{([a-zA-Z][a-zA-Z0-9]*)\}/g; + let cursor = 0; + let match; + + while ((match = tokenPattern.exec(value)) !== null) { + fragment.append(document.createTextNode(value.slice(cursor, match.index))); + fragment.append(richToken(match[1])); + cursor = match.index + match[0].length; + } + fragment.append(document.createTextNode(value.slice(cursor))); + element.replaceChildren(fragment); +} + +function applyLanguageMessages() { + activeMessages = { ...localeMessages.en, ...(localeMessages[activeLanguage] || {}) }; + root.lang = activeLanguage; + root.dir = rtlLanguages.has(activeLanguage) ? 'rtl' : 'ltr'; + root.dataset.locale = activeLanguage; + document.title = message('meta.title'); + document.querySelector('meta[name="description"]')?.setAttribute('content', message('meta.description')); + document.querySelector('meta[property="og:description"]')?.setAttribute('content', message('meta.ogDescription')); + document.querySelectorAll('[data-i18n]').forEach((element) => { + element.textContent = message(element.dataset.i18n); + }); + document.querySelectorAll('[data-i18n-rich]').forEach((element) => { + renderRichMessage(element, message(element.dataset.i18nRich)); + }); + applyAttributeMessages('data-i18n-aria-label', 'aria-label'); + applyAttributeMessages('data-i18n-title', 'title'); + applyAttributeMessages('data-i18n-alt', 'alt'); + updateThemeToggleLabel(); +} + +function renderLanguageMenu() { + languageList.replaceChildren(); + languages.forEach((language) => { + const option = document.createElement('button'); + option.type = 'button'; + option.className = 'language-option button-press'; + option.role = 'option'; + option.dataset.lang = language.id; + option.setAttribute('aria-selected', String(language.id === activeLanguage)); + option.tabIndex = language.id === activeLanguage ? 0 : -1; + option.innerHTML = ` + + ${language.label} + `; + option.addEventListener('click', () => selectLanguage(language.id)); + languageList.append(option); + }); +} + +function updateLanguageUi() { + const current = languages.find((language) => language.id === activeLanguage) || languages[0]; + languageShort.textContent = current.short; + root.dataset.language = current.id; + applyLanguageMessages(); + languageList.querySelectorAll('[role="option"]').forEach((option) => { + const selected = option.dataset.lang === activeLanguage; + option.setAttribute('aria-selected', String(selected)); + option.tabIndex = selected ? 0 : -1; + }); +} + +function setLanguageMenuOpen(open, { focusOption = false, restoreFocus = false } = {}) { + languageMenu.hidden = !open; + languageTrigger.setAttribute('aria-expanded', String(open)); + if (open && focusOption) { + languageList.querySelector('[aria-selected="true"]')?.focus(); + } else if (!open && restoreFocus) { + languageTrigger.focus(); + } +} + +function selectLanguage(languageId) { + activeLanguage = languageId; + try { + localStorage.setItem(languageStorageKey, languageId); + const url = new URL(location.href); + url.searchParams.set('lang', languageId); + history.replaceState(null, '', url); + } catch (_) {} + updateLanguageUi(); + setLanguageMenuOpen(false, { restoreFocus: true }); +} + +renderLanguageMenu(); +updateLanguageUi(); + +languageTrigger.addEventListener('click', () => { + setLanguageMenuOpen(languageMenu.hidden, { focusOption: languageMenu.hidden }); +}); + +languageTrigger.addEventListener('keydown', (event) => { + if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') return; + event.preventDefault(); + setLanguageMenuOpen(true, { focusOption: true }); +}); + +languageList.addEventListener('keydown', (event) => { + const options = [...languageList.querySelectorAll('[role="option"]')]; + const currentIndex = Math.max(0, options.indexOf(document.activeElement)); + let nextIndex; + if (event.key === 'ArrowDown') nextIndex = (currentIndex + 1) % options.length; + if (event.key === 'ArrowUp') nextIndex = (currentIndex - 1 + options.length) % options.length; + if (event.key === 'Home') nextIndex = 0; + if (event.key === 'End') nextIndex = options.length - 1; + if (nextIndex === undefined) return; + event.preventDefault(); + options[nextIndex]?.focus(); +}); + +document.addEventListener('click', (event) => { + if (!languagePicker.contains(event.target)) setLanguageMenuOpen(false); +}); + +document.addEventListener('keydown', (event) => { + if (event.key === 'Escape' && !languageMenu.hidden) { + event.preventDefault(); + setLanguageMenuOpen(false, { restoreFocus: true }); + } +}); + +const providerSection = document.querySelector('[data-provider-section]'); +const providerCards = providerSection.querySelectorAll('.provider-card:not([hidden])'); +providerCards.forEach((card, index) => { + card.classList.add('provider-reveal'); + card.style.setProperty('--reveal-delay', `${80 + Math.min(index, 12) * 24}ms`); +}); + +const revealSection = (section) => section.classList.add('is-revealed'); + +if ('IntersectionObserver' in window) { + const revealObserver = new IntersectionObserver((entries, observer) => { + entries.forEach((entry) => { + if (!entry.isIntersecting) return; + revealSection(entry.target); + observer.unobserve(entry.target); + }); + }, { threshold: 0.01, rootMargin: '0px 0px -8% 0px' }); + + [providerSection, ...document.querySelectorAll('[data-scroll-section]')].forEach((section) => { + revealObserver.observe(section); + }); +} else { + revealSection(providerSection); + document.querySelectorAll('[data-scroll-section]').forEach(revealSection); +} + +document.querySelectorAll('.mac-widget-gallery-wrap').forEach((wrap) => { + const gallery = wrap.querySelector('.mac-widget-gallery'); + if (!gallery) return; + + const syncScrollFade = () => { + const overflows = gallery.scrollHeight > gallery.clientHeight + 1; + const atBottom = gallery.scrollTop + gallery.clientHeight >= gallery.scrollHeight - 2; + wrap.classList.toggle('has-scroll-fade', overflows && !atBottom); + }; + + gallery.addEventListener('scroll', syncScrollFade, { passive: true }); + window.addEventListener('resize', syncScrollFade); + if ('ResizeObserver' in window) { + new ResizeObserver(syncScrollFade).observe(gallery); + } + syncScrollFade(); +}); + +const mockupStage = document.querySelector('#mockup-stage'); +const menubarItems = mockupStage.querySelectorAll('.system-menubar > *'); +const heroRootStyles = getComputedStyle(document.documentElement); +const readHeroMs = (name) => Number.parseFloat(heroRootStyles.getPropertyValue(name)) || 0; +const menubarStartDelay = readHeroMs('--hero-menubar-start'); +const menubarWaveGap = readHeroMs('--hero-menubar-wave'); +const reducedHeroMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches; +const lastMenubarItemDelay = Math.max(0, menubarItems.length - 1) * menubarWaveGap; +const markStartDelay = menubarStartDelay + lastMenubarItemDelay + readHeroMs('--hero-mark-after-menubar'); +const popoverStartDelay = markStartDelay + readHeroMs('--hero-popover-after-mark'); + +menubarItems.forEach((item, index) => { + item.style.setProperty('--menubar-enter-delay', `${reducedHeroMotion ? 0 : index * menubarWaveGap}ms`); +}); + +const animatePopoverDetails = () => { + mockupStage.querySelectorAll('.usage-meter').forEach((meter, index) => { + meter.style.setProperty('--meter-delay', `${reducedHeroMotion ? 0 : 70 + index * 70}ms`); + }); + mockupStage.querySelectorAll('.usage-chart i').forEach((bar, index) => { + bar.style.setProperty('--bar-delay', `${reducedHeroMotion ? 0 : 120 + index * 6}ms`); + }); + mockupStage.classList.add('is-animated'); +}; + +if (reducedHeroMotion) { + mockupStage.classList.add('is-menubar-entered', 'is-mark-animated'); + animatePopoverDetails(); +} else { + window.setTimeout(() => mockupStage.classList.add('is-menubar-entered'), menubarStartDelay); + window.setTimeout(() => mockupStage.classList.add('is-mark-animated'), markStartDelay); + window.setTimeout(animatePopoverDetails, popoverStartDelay); +} + +const brewCopyButton = document.querySelector('#brew-copy'); +const brewCopyLabel = brewCopyButton?.querySelector('[data-brew-label]'); +const brewCopyIcon = brewCopyButton?.querySelector('[data-brew-icon]'); +const brewCopyStatus = brewCopyButton?.querySelector('[data-brew-status]'); +let brewCopyResetTimer; + +async function copyBrewCommand() { + const command = brewCopyLabel?.textContent?.trim(); + if (!command || !navigator.clipboard?.writeText) return; + + try { + await navigator.clipboard.writeText(command); + } catch (_) { + return; + } + + window.clearTimeout(brewCopyResetTimer); + brewCopyIcon.dataset.copied = 'true'; + brewCopyStatus.textContent = message('clipboard.copied'); + brewCopyButton.setAttribute('aria-label', message('clipboard.copied')); + brewCopyResetTimer = window.setTimeout(() => { + delete brewCopyIcon.dataset.copied; + brewCopyStatus.textContent = ''; + brewCopyButton.setAttribute('aria-label', message('clipboard.copyBrew')); + }, 1500); +} + +brewCopyButton?.addEventListener('click', copyBrewCommand); diff --git a/docs/social.html b/docs/social.html new file mode 100644 index 0000000..e659465 --- /dev/null +++ b/docs/social.html @@ -0,0 +1,242 @@ + + + + + CodexBar social card + + + +
    + + + + +
    +
    +
    + +
    +
    +
    + + CodexBar +
    +
    codexbar.app
    +
    + +
    +

    Every AI coding limit, in your menu bar.

    +

    59 providers·usage windows, credits, resets·one status item each, or merged.

    +
    + +
      +
    • C
      Codex
    • +
    • C
      Claude
    • +
    • C
      Cursor
    • +
    • O
      OpenCode
    • +
    • A
      Alibaba
    • +
    • G
      Gemini
    • +
    • A
      Antigravity
    • + +
    • D
      Droid
    • +
    • C
      Copilot
    • +
    • z
      z.ai
    • +
    • M
      MiniMax
    • +
    • K
      Kimi
    • +
    • K
      Kimi K2 Legacy
    • +
    • K
      Kilo
    • +
    • K
      Kiro
    • + +
    • V
      Vertex AI
    • +
    • A
      Augment
    • +
    • A
      Amp
    • +
    • O
      Ollama
    • +
    • S
      Synthetic
    • +
    • J
      JetBrains AI
    • +
    • W
      Warp
    • +
    • E
      ElevenLabs
    • +
    • O
      OpenRouter
    • + +
    • P
      Perplexity
    • +
    • A
      Abacus AI
    • +
    • M
      Mistral
    • +
    • D
      DeepSeek
    • +
    • C
      Codebuff
    • +
    • LL
      LiteLLM
    • +
    +
    + + diff --git a/docs/social.png b/docs/social.png new file mode 100644 index 0000000000000000000000000000000000000000..e6cbeb46f7baf0318f9b3344d11b7fb4aae5e429 GIT binary patch literal 580936 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

    8qMry65$xV1>D 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

    =$; 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%0Dcsq3vyJyPieOs)%-m<5Aj0QC= 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 z zX925ZbdZq|-epXPEM+o>CQx!X_I}gv@*~)7$OdQK7WtmY+m7ZQh%({Q^pDh3JSFoC zbp&08^G`&iOwWf>3Y8NJedY%j{Y@T3!Os`V>fWvZH2*dSPh4TuKc|CWOA|$h8fh|<#O}ps}stWR^&|gCLd{C3hhuJ zQ4l9ZGzKBzkZK=Qx#UF05Ew9RDJ@Fb5~g~Fn(pg=Z>Hk*%df4%b~3b}o7Mfv zk}-}{X9X^T7f@jVhnRGc_>hy#Qt#xjEX7VIc6DG^n9Rj_IK`n4+CY0&^O9V(lQCZ} zP9ajnKWLJ!F4+TwV|JkRQx`gZ;~OWmD-dHqhl$4 z1V-h8pz9aN3?aY-(49#Qibf*=RRtS_ELZB3R>A0F!Xtp}C9eN^d% z97YZL=iCfINUuBgY`;8SC!r>2{er?9lc9=Q(k9j9Ye|4FAA-Whdn@88eH)5*`l8j; z=bzps{x;*i0DtC5e(TwQ(EX>4i1J^d{oV58Z;YE?m&8{o zui1XufIs8=OKDy`|FPriZ@)Bn=GR)D-_&Owwi1F2d$D7B=TL85f>zZX)cMw^YSp&) z-fktmL!)RF5~EqP*z1*^<&6DuSK3e5qR%^G+RJ6^b@3U>vRZ(J5zUX?n$p&(;{v5jMQX^dWNMNHoT>y-r& zHR|}@BbXmxLj}V;c;FmzQo4*7<2Jb}=)x`^qW~SfaT#B*QGh*ue1K3HyrC@_zfNFI zY|YFmPAsMuZBy0($1?~74@wd(m^j{p&?~vh$uNu)xeVmi7tT{Z4x@7`?F+miG*SCRRjTS@VZn2 zYd&dmHYAx;)bjGPPijNTgw;Fgu7l7q1l(3cJHrr+z4&COXWQg&bPgNzN14nql_oIp zIle)Em~85bpg5yEtOneuF3~Q!C(4!EKahmqg16f3~J5LEUmv6sb2{QoD6ekbZ`6`!N-UF|=>GKqK4~xwiDV zfrN}d-7ES6Mk>dbEuDpjaf85shx8h{{gjq>BaHRbCdV$zoeZHM=JU9ns0kxwpO!t5 zrT|JVWX01=vmIAmPJ|gc^+*n4a&BA%mszobtTd#mjix4DO#^G^1QTTmQ_4 z-wF!a#*hSo(JHmeXB7Vg8e37`c7xhQ8ee-onVz1x)vPMzGZz<6rw`ln<9aU7Gam>* z*!gntC~w%qM0W))b8 zU4@TZy~rAOeB!b9B3zO`+dOx!vSW-$%D2k z5$S9hbMg(kdCd3c`MF3+_b00{A8_!S!#3JkFmc@=$suDZh@B4k;WS3haHDuC*Avhw z(Mt%f$Vp})X?WHN>Pt_?djPzN290w4hqUsD>k~dDu}%R?RZR+YGBA} z1Xl8HN<2O56w)&#&s^iHsqT_z?#Byi9W$r>6@1&F5SCf9b|tDl;rgX{XM zuGM`5GvA1-ppMy&7XjB>9 ztpYze$dWychF@V}(QRx;oxS#IdDup7)qqeh1Syyxf`@XS9aT908yAX!4?ZbWQB(78 znGCr>?&>_^_42`EWr#vBIY~5^A04W9Ay&KYfg$P?FlfGK0^zFFYloZD9Qj7HWTXbX z$eiuq*Z8{HfKp~^_ZJuOfh}R@c6-VlShB1amX3Vy^B3`J1 zV$uVjJ|IvEyR=v* zYtBw&zyMlTh8&la%B_#Vl>miOhJDxgBEW!yjW-70^KwfguQ5pqMW{=S;Y1QE+=4-G z7BUc{9;vN~Oo&o@iKTojrB%}?!wl^ff#{W?aPycIrEBWK8Gs_v5?o>{*;`VIp)L@X zEw z7yb7JwtiomQ>0g$6=l(yMkU2hhBk1Yf<7n2=M_HnTspCXb3N=cXv291 z+_cs~hS@u|x@pF;KPauG6coCh!#6#(19C?{0RNI0j5gt1cICdsd4)ol4f2|hnHhrw z5`b9>BrV$MEA$HbNcspeV037I7((*g-nQ^+fO?F2Z=n@FY-qCKBoTnz7fiXu$?1#h z^o+&|1RcZfE$X1yu=WXVIXOSq>$A>x>7dquJF30VAUimq}o!{jK@N12?AE$qQz8HWi(|%lzeMf=6|NI%> zUwZyG##g#-xh=vVr%=Q$>C1AwP?`DjIFkLj6Dy<^XnnIUhE$=5{U*q2=-MyJmbKfp zCT*j>{Wsdz{vk@J=q1eL(di96S{wBnj@sSb#d;lK^>ZspE$ya;)y~+qf?y~tdQ-y~ zhI{Yzx02z_1bjL8*M)5qsqYvhMM#HsA5z8d=T|7#9YYJbdTkp6Z|tqkf?{YPMS_Fj z=E2<`2dNZM-DK5(tUJ!35o#L6n@$F0uxh%w@LeyQVR~&G4y0tLl)T7fqzac>DaLJ6 zHF4Ky=lYew;Jk%!OmE_xUc*Y(*%&)9W7&hfQTs7ZQ~ox2d7o-!sCvMai!3%J%v2x4 zjB)3W#h1$uc*fH>33J78iRA$TLADG#;#K2?SEgmo8|MRdn%-(9xyN zCmj(Hjy_rfk`yH7YQpSQR6sNfK_G}~FutiI2}v5F^SRbcYJiRMhUY$w7G8U@s;5i4lNoogx>J)`;6$$=rm>o7GrM{e?qX>Jx8qhTS| z_U!tEkOwwbE-2!#8sD@?wf%&_qp5x7pl2hOc=jW=;sJ$Q!JyG@54{-{YDXLj@z-`H zDz9?mg!ni1tk}ZF;P#?f$}SmJS9pat^sXHd@;`KC(_CAmQ)q5JwF~tI<_fKMHFwK6 zGc-9%z0>S+8A*&(!`d*UX~#F;EL>f(?p#$`gKAs7C0-c~>ZnyqF2CPtaZxn&T@laD zOXh1q_b1oRt2F!0zS{LxZz{fviGHb( zzx4dg?ECSrM*Wv+{4>5^wBc8u|CaH+U!wV|5(_JY%6K=v-nL)8iQ@Hr|5SBddF=hZ zr>u79bZG!gJHK0lQr^%`OL>zD_V>49tpU!OQTH_5Y3)J@?{!fNvD4u))Af}|_-f~7 z8*1heqTmOL?rqd@MU8owPK^>U-Y5$|a9o3xIZRVpooxY}R39a)4NSEqmf5Km$1j`O9LeBJ z5BbHZFk3@bB63Np#WZBF_0s?+hA|gZmKYXTbSB=j zCJbcRE|`~~5eALN=Ab5oJC;N-$3F{hBQ+{#M1f2`cC5+ynnlxmIxek4cVx+zh2t$7? zJz>aihhLq#kL6uv4ZtyuLmS6uqM8S>#@N19%!m-0*O^s)Ms6f;4Dg0GX)}g7n!q<; zbjs}msBdnyTWUFCS3&k8easjXAWb(NHL(?4qvF3WsdI`PL(4h2d4_$*%mRgJ@Ciz0 zi_R46&l=x$3Q6Ewi0)c7BNKMB>Szu}df#wKfwxi^lN!Ljy$<>1T=ISP@rK zk=6<}=hhuY@qL~0Rb9I!_2>q=+FXbHtO^0L3?25N#oys#KfeVReKRhF$D+f_jdM3M z@(jSl+1LhkcEOE)mE(D%$-6RlWAVGit<0S@dTJ%uG;94f@f%OiGynW^FQf0ub^GZP z?-PGPmuC=i`}$R0`|fdno8A5Up1#liBJHjG@0$0M_J398ue8nnjPL*K_`d4)tM4~Z zw@Y*LFUF`qU26l5$Nl-*NH@Q4=B8Sz7i`R%L5%&=4f6RFZkBzZ+1<6w?txwWtXQX| z-)rvhZc;NTk!pjcJIcb1x{Z4aML4rw2h zqhVbza79cV;4E|TFS1V)^O{(Tk<)#2#JiPgqiH-+GDZh5O_SEFfm`PRon4Fa&N9mv zWzL5o5gfJ_gj3%`gSZ_JamKO7BKc@f;NcX$V*U)NL_HiT5`c27hgiDGBIkZ zVuFib#iq>7N0U1(LgXC4h;3A96gCD0zY;AnAcV&j!VIBM%z97R2*733jstMOB4^F= zv_CYgQBI`tHtB1MEks9)J237Ew1UC$=u8DY`i##Hhlv_}!!A%q8$y|%rS})8s)n4P znA020llF=7z`Cp-ub9qKB-=UUfhbCq{G(c(E2X8JG8eg<$ z$VV>V&;jtAk1(p`WDg*^Q@*L-A!dxC`I>Bp9mpkIN>ZoKnB6K0(6G`WvrWW>!fIn8 zpw4A@(!Wkfa>Y@VSXT3)Auf}0FXr`X14cx?Od;evc?qXB8_+VOm&A>Lmy^*xQhzuf zvJotI45sF4i3)Kv;u{6ZqF!o6qY&$8&^BPal;1A;trZJu>uA#6xsl%W@r|G2 z`DON$vgNp-%`FPHCmh&oiL2L{Hy`-riu%0&>RyK=wC zV!v3zKa%B^H-5K}uXDxUYn%OGoW5=U?Wg`Vq@7|v%WHqe_xk*AkMHx&X?D45`>M45 ztJ?*#J@0pQvUHj>4B25-+v4|Gbt$%$7IuYOw=J@1HtvQu{mh=_1>Y~oRJHK4UGQgz zg;iadNnHT85#|Y}JtPab^uOBgfpXjPCs`OXzxX)qPDeN7Q;ll>dFRv zJ<#Tm@gbz!mxWU>08yv!K}?AyrcYkR6BZJz6850QQwqk}-k2OyPqaKfGL9k@r7(h= zB8*=zvp3Oz9p|jb7J5n5mNOX8$25#Xnq73k0~<@kZ={ZHa%}Fh9)!8$<5yA3(Q_{` zVCs9-;=(){>BGipwiU2}OhZ9SesH)hAkrkSv#e@{Iu$jcyp26wutdRfXR%4u2^B$& zeu~{vJO(j~%T_R&I}tWZe>1_Fd`J4v+EK4pig?hi7~#bYKGvsfZhps7k0=9s7)_Rc(zP z+0>MbcW#Bpmr!cQfBK7G$oo{+_%ih`J-?B~+NKuvo6px7f6}V>_9uTH zzHc)AcBTI1*B_?b$LG)T{^a>HzQ6SR7msgGSu%mQ?fJ5$egPQQeEEAjZoK8Pc4xPx zXSO#uSKU|Oqyn573#in9Z!utOPGVf@hS!FuN`eHnX&dt_LRWS_sGIijypoz*ZQTNAqRg{6fcp*WVV(xj46i)sU&9#-EPW7 zE{giCRv>5n45Sw{5C!lt>4MG$>P%s&$x?Et8Qnfi11Oia*_%^g)&bfdug^2l--&U_ zg_7bm@}LcOB^xx)LUc`92T?8BoE&duNxU(Z&DD~c8axu!q>w+GbZSCJqcr)0;#!xL z<-n$dXHqJ{S;86P-j$rm*=8jR{y9XA=zal-)6)8GYFc>FG<)QGe8Hw4(!Yz4e@?7C z&5)9f@D4(gQc_`(b81@{Den#{tP1eeoV%K#Q*0fV9< z!WDkz_!eXxwB^I9STPa^T8uty=7YN0A+3}3=U~BoFDe63m;g0kW147X4 zs=*WK6p1V~E0%wnE!Cu1U=*mU;ixcxJ?I=(FkI8r+8%IwY9`#pQ$f>Zqq|x+_{xdF zqUAsct$|kYR!QJ`MJ-%l?1CxYBRy^5vy2#p%sEl34lYY;lPXvvDex%{ZQAZkE@c@o z*N#-n;36@TSJF18Op|ryx`UNMKhd0ajB}WGG??TI?IyI(ER44cXx@)Pg~#5AIlRW~ zrVk;AZg!FKHKOs;mY~)f>+9mev3TP>-ac+We=hu04dx|Dy!afi>-efw&+Qt&SVZ_& zJ^SX@S1)U#_%CMMCD`A6zGuqcFtvZD>c8LY-+um#@BODgvT}#Bva{O%}M3vXp#|BILRm3Ih9ZK1yVU@Uw_l96M0=XV4?l0z3JQr@(^KGSl+i^?zw<|-Q*YD?!2l>^P92D>rKPz6P7tu79qj5_e^V|nkn%6u26UANwzVi5>gkFES8%s@H~>Ye z)h#r#Cyw~W8C#!L9Gyh6hFIAk?n7>tw+4eS33fkI`fKN;pFarV7FP?o#SxzcmEl@O zqmRA=)kxZ<)-BQBD!~PkL+_omHR_{I#^f-v{Gc;o=Zxr#5g6b(%lxt&cN#fWIZBmB zo0=DhDj`mstg!UQ!mPB?QbF@1@FOXzCB@Zy}v0e2~I^a2nC{uHW)rA+9{CT&jb6(Kc03rbYzWHP*MUY6>`liCPAy0j!9 z^h?^$&=5d_cXvE$;`HSQktVqL<=B(du@qqPC#WUMbkK|@&(2jZQQ<5&+RCq733zhG zr6Jx-DCk0%oDCYcM96g`6biAxNn7KPBN)P*!4+P^pDt}_G6;ON#%O5*AIsCv7Pscc zR@)0fdx*TK6EkfE&w#vfo5FI{1ThDiI!o4V(k2b=jEQ5dtwP?6Y;-ejw~)3&1E+zd zHg31Ax~sO_E;plA1*EC!WbMvDxh2WY?cJiCOa;=S7c0sXMAwV_57VG-R=piIPclHW z?Z;)qIcyKFpxx#1_G_U{ziP(b9$dod^YxeQRwv%(e(|QvHQ%=LeSvt~e&rdzScJ!y zwSW1mf7$f-GUIPP?!TY+J3{}YcKg-mY0=%DZ<`c9Ncm@c@%$Ozoq;>$uZ?f}y4i(S zPuLGS`=Z(J$wiJ?!0GlY+2QB%!~t(Eao1G9K`$w&*?>Y=t2l_K9_@`gZf@j^SgQln zTbgzllC!KX^bvC3^aR)F^sYgDG84fCfGmnDDz&`lQ@ELsk^917Uogmk|i@C$l*hVLu^{l{^pX)-#=* zQU=v;3TS5t(>pN(Y3R|ikSzmA4TUN5j2-Y5Ka$EsA+A0AQeoWDOv9bx_@vk6#A!JeaQwSIGh`! z*7S+ka6rP$B-hvzD#R62guA%YdCCbPnn5_X{w{wrlGu^g%GMDP(JiZk6v+efG@vSG zdeANQngaxuE~Q8CXH=t(KdF((b#tEQkV}yoUnWg)Y?}EcyiSEgH8v%OIf4tEBx;r} zWgyJ@sT;4Hkqh&rjB7P%&KVuxvbtzXt?g7KH|05yKwIQv000mGNkl?6J2oUxBx8l7CLzKo-)+pJS&Uw|khY-K!jy=Q(3)5h2* zCGaGBl+glfG)=BnsM`uPXPn6q$)qr;kbQIoJ=avLO1+Fm+RHp)jxq%=S$vMrClZ=^w?b8p;Ob}9yDXm&F zd5=iJDLz3y>9o?z9<49r$-(dqMU#Wu5|DQbCxc!ssqL16O-MFp;^8bJu_XYoR$nyl zwb?(&w!mg)n2f`L?x0AS5hIKq6sJ@Imu@O_J`El$AO&q}1aLyJ2fzX6GzhxrK(d*F zCg8i&JLRb~lUC53gVi0vrcXM0b!`VV${CG4P3#oN5t67i*5|T3LzuXlTb&6OFgEBn zrX$Lwo_d_~vkWPHyRjk4L~jPhYtaEx;2d9#YBUsj5{WFOzC#EE0uIb$WkUUnUSy zDaR(c*t@|f@VM#;1=*{uF`#Rj!R|7$MUdtvjWdn#Kpue7NvW0OjZ1**JJNY<`X$m} z0UJx|7!)8^c3p%3wCg^D5KPjIBWWV#g;GgMK z#xH!;|B+|U`FD@+dz6>SdZ+#!{qpxss;3=I#o1V$roT%0pHHcGt@<;*KY#v*#@D}l zb={KQ5y7u7tq!=C=x7Uw{9fk12+wrls*CGtq`tUY>j~71F8X5vS;`TH6%O>xi@V?V z<@+UG)=Q{gt2)=2>N@PKk<=>U zV!jzVEAbVW%HW7q2E5+0JKK?KrL>YM1^CX!)7sw zfIACSjp4OuGFW+pTrd{R2O|J-d?)ZK@YO?fGXb=WeE+0K4e)Ps(M~ZGglSndBR)iE z6=6Kdn&WFajA66`%5Ty3biq>NE3dAYetTP3f1xx;))><%M7m55cQ}M_nI4Nn;p69U ztzO5lXAF9dwL;7j2&I#f^iV2ym!Yn$s{f+rm;k{`dH}zqYrO23C67vsmy*MR-`FQg zpyZ&&(L7-3ek;@$ZfA%0G+Vm+;fFz4GzD=}S_hwkRRGe|+BRvDx8)lt2H_YPCO{kt zQQNc&Bx_X!#Rrw>Fa}$PAZw)8A28-zYhHp!9X^Q%=q)C1r%($FK|`BHL~TB~?`}7q zCbvffct(7>`uDlr|GG6ce;kP3}Bvv7Q&2*iV=0bJPAfkuD&`;^vR-lTt1MdhuOFAWHPgMWVZGWsI3|D<`Z^8Nt1#{16ucj@CP<&8Vv z%+fW>*JP@^{#(tyrRhYs>zj8~{G{;LDLeo9!z}h^eBY<}^7(HcU%$2gi@x}qm#+G? zt9FbO+V)*38x|6WcWwO@Efk8oRvv6T%d|S>Yzvgy%ih1ROUYKvZ-}&w0S`vMwj{1( z99K7?rXwj+@|>n+)IQ|B3cOHE`HPYu(qI@g+|FKFi^SD1y1w9%mkt}$^Wq|SBDXOj z7%=j9r~>_3%x90uffHJXZ&m6vQM0Y|=$nA-){uQ5=fDDf1+KKH7ZaZ?q4s7CFg$Gz zYEpXdMIYcvE3XRb0LL?)UTsnuHe8}e#rM_}g`awc=@T_buq*gC2-2oghQ~M%ds2=X z`RU|zlG|B@Cyk|-MIu*^&@c*K-1g#egdSnP(mKlz4L86i7uFU(%Hs*xCgaEj1r5ev z@jE)pmH?=b7;Z7l zJ;Yz$`KhGz2}t0=A&F!Vi+tiUXL|y(Y@q{@$}TP=OhAG`*PmXjCs=1<$P9d+vMI>C zV0o462yrhUf}}@83C?)&BD`(z^e7~N-3NgJoC0QyJRDsP_<+d*f{`k$$s7H$>FG+r zIu{!Xptpu7fwlTu!2pS4E&bdaa5%X}2Epi;|5OCcbIzHhv-{`V#9tcOOX$rVsu~5+ z861Ho%r|TSOU$@}YWPVrIh&Ua+M&*dUk#!*QfIXVlt0#rO@-2IRUuET6#g{hkT01* z8b=wqS=+nMyo2zCr~?i~%O}l23>+c1qNKL&2zyb@la2H8Y@fK|z;o@@0?K>;8%e2?2xnJ@s>S|BOql?_f zc16?6xt%N5-`SY^TeH~b;vRi_`{+EqmD9GnR}J{P{PQy){Gy59KF@jMivssjc=PLX zQD1PV*S_^`$MwCx%>Gnty!rK+1HSap{Z`H|J-zT}(mlWNA3(C(^JjejjPK9$#v6KK zuz1q9msTD0XPkDM4}RG88t^_kL}CQBu*653byEB4zM zueunQP!PS|OG|DD!6?2{SJ#KZxL8|3)cuYpdubwV^A{Qd2_(*?{XCkz^-)yF)3rNj zvEjE~EG~;Wjq12!)ov zXOdfj9)Lq=1}2e&f%JWTAi7{96nYqwER~=gFXTnFZ0T83SeNejX~6Re)IQl%03HP2 zJB}K239r~6wqTZKW+qE9mqGsImH`r7EE)pVld(%|Hev_+qP<@rlEEpP)m*9$pNAn{DXKH=*5DcQ(iX^Bv61Y z!?-_)x&(b*(0JjEp->arn}Vy6Yo%8HiUnW8UEv%rnt1f&@fec~SVzmnL@%_^M(lEg zvxfuEv-aFXvy^v5PM3^f$msU+c#}{t!^a&>WtzcM!m;&w19I1Fl5y1B|AC9IX&rD2OFpbZyl10Sj0b zP;s=7{wJV>b1mjnS%T0Zi4$GXcl55J5pVv<|pCQ7DZtgS9{Gv(CMwju&{AcVvwX;M?ta)iFIZDEq)`GB-_0 zRAq1vi`689L$8{xVLYzKRv>E#ZJZkTi?Gd={!-L_!U1LpnfC6^Z|pfiFRCBz%IL3h z{UZNdH0y1@r0;LMwe7;={X8)Jy9Z7G2g6sqtitVyAAR~7Pu2OA3hzpOS!OTr9b5eF z&FkmY;67LS^7Fel_Noi<50Smf{4>5kdj8YL_eG)iEJ2ULzay232=vhoo+_E6XCLivn@MVS29)gm~)B`APwJ zO00vt>Ar;#{5T?ti{&>{NhqUE`b0%J3K>Vom57KoQWr7#a6tKmjRsYy~VE5y=n zrC#o^D1oG~BB#@IdRHlM2w*wD?n%MYi$u*WUrp*{Og}ReJ7kjQ6iE)2RcmxDlumsl=(QkU~@x>%t%);bW6jr3>Z}+@#Z85n*8En2rv@K(lT(8 zwSo%kJje2JdSZbL#8EWC$6AomNCJ_oW9K%+TRM*qUaHly*3ThDndEe9@drOVF^^@>-<rW%A!JwF8}}rVM#Iln9!?66*qLZY1d?d&HfQ{LSEQi%oRj91NDN)67+;K*{C8;>wwM4NXz1 za9YXV`h_m$Fjs`%*u2mwR$CvBSHC#3*;O}O+RHJ2&Gvx67`5^Ax|;nmuYXnC)7$7g zQY-)Z^_g#c!9V{|F}|r z`uz29{25<+dh=&|-)HowYrvwwoPwQ*D67*XG6D#*%ORj&er@zjnef_8l)~MRHR-z2I1vH+Du# zpS#OMP$N0ngLXEk_Mon&hg_;sV5L5zqS%9CvVH_BcN}D*4#7n;hOM)LPXv~% zWTt=7QS)JsdeS^f0tx(rQ4l;MHcStARO zAiXqVB(B7{`8K2ztgw6XH?-rxYW0QMrbn9=3*<&rmhJrm|- zNz-dDaw}xwi9cNqJUk8mppOdqDlqw|Y@B54JwmHfE}kQb*nZ$#2cdp09tdo+>z}!P zT?TK|^s}NmF@9L|O$CN$O{Qc}?}h9PkORhh&KM7t(d~(p7_iMFViqqMUM zL2i_}fZsu6lFfo6nIO^|>@qJlcos1#J%=}eW%iQs2}9p`Z*XL369P$SiV|T)8X{(I zXWK+0edM4$&5fjKD-3x<**10cekfc!y2;z3Y%T_H4OuoR%9yZ}Gqd3bRVB6UI$4xY zMsA>DB$vPHFE(Rxdltmv5|9*6$iI#)%~-R_l^W6L(n%9aP0|wQxmTRaloivs+FO~f z-J|B9QEa%1o>G)`?g>#uz8t?+#8DCJzir4l++$-W%*tKDkltyR(V@7y(Xd@|rNnW? zIkw+>=M~gm>)(qxDV&MC(_blhJ01T4{&@pJ67c)BzIbXD)!%D_ zf6{+{pVFT`*!wrPGAqqHhV}0}UqF$sTlHg$A0xeGD)v9fAsfH=`VdMIM2NNc$?dNtS?|folQJ)FwniHO1MbdQVk>zJ%5IJA%~ie`*>ZYD z4Z4wVp(`|TvyVX&${fH52^%vmf?25?lGR>x7)tHpvc!90p1>F>&D$7E&gqbbF5ro5 z=L#L6tBOTVvHPGXMwY?h)^ljx4ebM?@VoCtC+$;h_jE3kQo$5r587FgPlY<7{Nk`I z)%_55VNx;NcBl&2G)7`bGa$+Nk+zh)JfdD7h8K2y&QKva0|J_*3`n^BSOP&n6_fUs z1QKBPxwEDh%|v373f8>EK;)h=5EouBlJd{T^BE8tm*_qPVtHjSWS5B56m*!2orXaa zJ_${!lsfiBhGe7`1hHB~Q)q|t$%MnL#+Qnn5DyynyNJH?qMh=w8C-xtlJ1D@#a^To z*V3O5t{AjPB*CM_Fp+J^r}x@ljY%cmIkra@Orcu8rfuVP>=9kh?OLh)!~k9z!z~&~ zZR|2NNJCbv$c!aO8J(u32yPgA)KlJQt+p5~4h%vx7OnPiZ<8?lQ?qpo22JU&D2tNI zIyvk@$+%Wk2P>P<4^9aHBQ9yI;kwI_iv77arZ>;;?N=tTre3$Jb}QKI#`e5^#MQh` z>79wV|MYd4I}N}7KL7v#|NnwM)93&I00v1!K~w_(o?

    !#hF%wCSnD*qe&H|omi8jeGym8 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 r(Sfw@Gniv literal 0 HcmV?d00001 diff --git a/docs/widgets/02-codexbar-history-large.png b/docs/widgets/02-codexbar-history-large.png new file mode 100644 index 0000000000000000000000000000000000000000..6d3af5f5e113a0a23987e7cb3279eaa83f754864 GIT binary patch literal 48932 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 literal 0 HcmV?d00001 diff --git a/docs/widgets/03-codexbar-metric-compact.png b/docs/widgets/03-codexbar-metric-compact.png new file mode 100644 index 0000000000000000000000000000000000000000..a428ef714f348b5c44d7c9f111e58ad8424d079c GIT binary patch literal 20887 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 E0Fqz2X8-^I literal 0 HcmV?d00001 diff --git a/docs/widgets/04-codexbar-burndown.png b/docs/widgets/04-codexbar-burndown.png new file mode 100644 index 0000000000000000000000000000000000000000..ae308e3c35fd6eaeb7bab455e1a13864d2279b97 GIT binary patch literal 94309 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�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�h!+xff)vc&^-(TR;!bi>AzW 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 literal 0 HcmV?d00001 diff --git a/docs/widgets/08-codexbar-usage-large.png b/docs/widgets/08-codexbar-usage-large.png new file mode 100644 index 0000000000000000000000000000000000000000..865bcb102e797d2ab6c533f3f94cd13c702203c0 GIT binary patch literal 56104 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%0AZ?5iB7Xz>n#fenoLXf`Qw#Rv-gIO_Camc55E9}6 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

    yGJ)j6P);lPWX>c&}Dj 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 P!0*`;4W&{Av!MR~f#X-e literal 0 HcmV?d00001 diff --git a/docs/widgets/09-codexbar-switcher-compact.png b/docs/widgets/09-codexbar-switcher-compact.png new file mode 100644 index 0000000000000000000000000000000000000000..c33b2ee76d72d243173d90dd7eb4c718e4ad3b45 GIT binary patch literal 25647 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

    ={cZU5uYXO437vK3 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℘e{V^9vlv=tqP1NzvYxeGDB$F0 z^t$jv@}1M9WMhVeKv_gB092t7ke0a8S0|v0*H1kv$t_;;5{t?%C^(0A(_yd(ckF^R z>2lVSAx&id5IOFwER%5L=J<=Sa?k4_m1Em>HRb2Ps0UPC(us5551ZHELu2$aBrq>J zOzOXwserQuG7_Y&=2u7iIfNH23GIPJjFvh&IRwPsHx>KL4q+oegt_SN&_fq=UHqY$ zA(;aC&%RYD?-aawjbE2on?6r#DW}ib?TdgMXnP3V^LeP)VhI7Ci|4QC7wg&+{tqJD B{$Bt9 literal 0 HcmV?d00001 diff --git a/docs/widgets/11-codexbar-switcher-large.png b/docs/widgets/11-codexbar-switcher-large.png new file mode 100644 index 0000000000000000000000000000000000000000..741f47d2f245a075d6e1a2c317c9224cf918c36f GIT binary patch literal 58478 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 JR*M@3{Re{8o)Q26 literal 0 HcmV?d00001 diff --git a/docs/windsurf.md b/docs/windsurf.md new file mode 100644 index 0000000..dcbb19e --- /dev/null +++ b/docs/windsurf.md @@ -0,0 +1,172 @@ +--- +summary: "Windsurf provider data sources: browser localStorage session import, local SQLite cache, and GetPlanStatus protobuf API." +read_when: + - Debugging Windsurf usage fetch + - Updating Windsurf web session import or API handling + - Adjusting Windsurf provider UI/menu behavior +--- + +# Windsurf provider + +Windsurf supports two data sources: a web API backed by the current website session, and a local SQLite cache. + +## Data sources + fallback order + +Usage source picker: +- Preferences → Providers → Windsurf → Usage source (Auto / Web API / Local). + +### Auto mode (default) +1) **Web API** (preferred) — real-time data from windsurf.com. +2) **Local SQLite cache** (fallback) — reads from Windsurf's `state.vscdb`. + +### Web API fetch order +1) **Manual session bundle** (when Cookie source = Manual). +2) **Browser localStorage import** — extracts complete `devin_*` session bundles from Chromium browsers, checking + `app.devin.ai` before the legacy `windsurf.com` origin. + +### Local SQLite cache +- File: `~/Library/Application Support/Windsurf/User/globalStorage/state.vscdb`. +- Key: `windsurf.settings.cachedPlanInfo` in `ItemTable`. +- Newer cache shapes may omit `quotaUsage` but include `usage` counters. In that case CodexBar derives + usage windows from `usedMessages/messages` and `usedFlowActions/flowActions`. +- Limitation: only updates when Windsurf is launched; can be significantly stale. + +## Cookie source settings + +Preferences → Providers → Windsurf → Cookie source: + +- **Automatic** (default): imports the active Windsurf session bundle from Chromium browser localStorage. +- **Manual**: paste a JSON bundle with `devin_session_token`, `devin_auth1_token`, `devin_account_id`, and `devin_primary_org_id`. +- **Off**: disables web API access entirely; only local SQLite cache is used. + +### How to get a manual session bundle + +1. Open [windsurf.com/profile](https://windsurf.com/profile) in Chrome or Edge and sign in. +2. Open Developer Tools (`F12` or `Cmd+Option+I`). +3. Go to the **Console** tab. +4. Paste the following JavaScript and press Enter: + +```javascript +(() => { + const keys = [ + "devin_session_token", + "devin_auth1_token", + "devin_account_id", + "devin_primary_org_id", + ]; + + const read = (key) => { + const value = localStorage.getItem(key); + if (!value) return null; + try { + return JSON.parse(value); + } catch { + return value; + } + }; + + const payload = Object.fromEntries(keys.map((key) => [key, read(key)])); + const missing = keys.filter((key) => !payload[key]); + + if (missing.length > 0) { + console.log("Missing Windsurf session keys:", missing.join(", ")); + return; + } + + const json = JSON.stringify(payload, null, 2); + console.log(json); + if (typeof copy === "function") { + copy(json); + console.log("Copied Windsurf session bundle to clipboard."); + } +})(); +``` + +5. Copy the JSON output. +6. In CodexBar: Providers → Windsurf → Cookie source → Manual → paste the JSON bundle. + +## Authentication flow (Automatic mode) + +```text +Browser localStorage (leveldb on disk) + ↓ extract devin_session_token / devin_auth1_token / devin_account_id / devin_primary_org_id +POST https://windsurf.com/_backend/.../GetPlanStatus + ↓ headers: x-auth-token + x-devin-* + ↓ protobuf body: { auth_token, include_top_up_status: true } +UsageSnapshot (daily/weekly quota %) +``` + +## Browser session extraction + +- **Browsers scanned**: Chrome, Edge, Brave, Arc, Vivaldi, Chromium, and compatible Chromium forks. +- **Local storage path**: `~/Library/Application Support///Local Storage/leveldb/` +- **Origins**: `https://app.devin.ai`, then legacy `https://windsurf.com` +- Values from different structured origins are never combined. A partial app-origin bundle cannot contaminate a + complete legacy-origin fallback. +- **Required keys**: + - `devin_session_token` + - `devin_auth1_token` + - `devin_account_id` + - `devin_primary_org_id` + +## API endpoint + +### GetPlanStatus (ConnectRPC over protobuf) +- `POST https://windsurf.com/_backend/exa.seat_management_pb.SeatManagementService/GetPlanStatus` +- Headers: + - `Content-Type: application/proto` + - `Connect-Protocol-Version: 1` + - `Origin: https://windsurf.com` + - `Referer: https://windsurf.com/profile` + - `x-auth-token: ` + - `x-devin-session-token: ` + - `x-devin-auth1-token: ` + - `x-devin-account-id: ` + - `x-devin-primary-org-id: ` +- Protobuf request fields: + - `1 auth_token: string` + - `2 include_top_up_status: bool` +- Parsed response fields used by CodexBar: + - `plan_status.plan_info.plan_name` + - `plan_status.plan_end` + - `plan_status.daily_quota_remaining_percent` + - `plan_status.weekly_quota_remaining_percent` + - `plan_status.daily_quota_reset_at_unix` + - `plan_status.weekly_quota_reset_at_unix` + +## Snapshot mapping +- Web primary: daily usage percent (`100 - daily_quota_remaining_percent`). +- Web secondary: weekly usage percent (`100 - weekly_quota_remaining_percent`). +- Local primary: daily quota percent when present; otherwise message usage (`usedMessages/messages`). +- Local secondary: weekly quota percent when present; otherwise flow-action usage (`usedFlowActions/flowActions`). +- Reset: daily/weekly reset timestamps (Unix seconds), when available. +- Plan: `plan_status.plan_info.plan_name`. +- Expiry: `plan_status.plan_end`. + +## Troubleshooting + +### "No Windsurf web session found in Chromium localStorage" +- Sign in to [app.devin.ai](https://app.devin.ai) or [windsurf.com](https://windsurf.com) in Chrome, Edge, or another + Chromium browser. +- Grant Full Disk Access to CodexBar (System Settings → Privacy & Security → Full Disk Access). +- Try Manual mode and paste the JSON session bundle directly. + +### "Invalid Windsurf session payload" +- The manual value must include all four keys: `devin_session_token`, `devin_auth1_token`, `devin_account_id`, and `devin_primary_org_id`. +- Re-run the console snippet on a logged-in `windsurf.com` page. + +### "Windsurf API call failed: HTTP 401" +- The imported browser session is stale or invalid. +- Refresh the Windsurf page in your browser and try again. +- If using Manual mode, paste a fresh JSON bundle. + +### Stale data with Local mode +- The local SQLite cache only updates when Windsurf is launched. Switch to Auto or Web API mode for real-time data. + +## Key files +- `Sources/CodexBarCore/Providers/Windsurf/WindsurfStatusProbe.swift` (local SQLite) +- `Sources/CodexBarCore/Providers/Windsurf/WindsurfDevinSessionImporter.swift` (Chromium localStorage extraction) +- `Sources/CodexBarCore/Providers/Windsurf/WindsurfWebFetcher.swift` (protobuf request + response parsing) +- `Sources/CodexBarCore/Providers/Windsurf/WindsurfProviderDescriptor.swift` (fetch strategies) +- `Sources/CodexBar/Providers/Windsurf/WindsurfProviderImplementation.swift` (settings UI) +- `Sources/CodexBar/Providers/Windsurf/WindsurfSettingsStore.swift` (settings persistence) diff --git a/docs/zai.md b/docs/zai.md new file mode 100644 index 0000000..f02bc66 --- /dev/null +++ b/docs/zai.md @@ -0,0 +1,143 @@ +--- +summary: "z.ai provider data sources: API token in config/env and quota API response parsing." +read_when: + - Debugging z.ai token storage or quota parsing + - Updating z.ai API endpoints +--- + +# z.ai provider + +z.ai is API-token based. No browser cookies. + +## Token sources (fallback order) +1) Config token (`~/.config/codexbar/config.json` or legacy `~/.codexbar/config.json` → `providers[].apiKey`). +2) Environment variable `Z_AI_API_KEY`. + +### Config location +- New installs: `~/.config/codexbar/config.json` +- Legacy installs: `~/.codexbar/config.json` +- Override for scripts/tests: `CODEXBAR_CONFIG=/path/to/config.json` + +## Setup + +Set **API region** to **Global (api.z.ai)** or **BigModel CN (open.bigmodel.cn)**. + +- UI: Settings → Providers → z.ai. For team usage, add a token account, turn on **Team mode**, then enter the API key, + Organization ID, and Project ID. +- CLI personal: + + ```bash + printf '%s' "$Z_AI_API_KEY" | codexbar config set-api-key --provider zai --stdin + ``` + +- CLI team: + + ```bash + printf '%s' "$Z_AI_API_KEY" | codexbar config set-api-key --provider zai --stdin \ + --label Team \ + --usage-scope team \ + --organization-id org_... \ + --workspace-id proj_... + ``` + +- Check: + + ```bash + codexbar config validate + codexbar usage --provider zai --account Team + ``` + +Personal config can use `providers[].apiKey`. Team config uses `tokenAccounts`: + +```json +{ + "id": "zai", + "enabled": true, + "region": "bigmodel-cn", + "tokenAccounts": { + "version": 1, + "activeIndex": 0, + "accounts": [ + { + "id": "00000000-0000-0000-0000-000000000001", + "label": "Team", + "token": "", + "addedAt": 0, + "lastUsed": null, + "usageScope": "team", + "organizationId": "org_...", + "workspaceID": "proj_..." + } + ] + } +} +``` + +Keep `organizationId` and `workspaceID` single-line. Do not paste display names, URLs, or multiple IDs. + +## Finding the BigModel team IDs +For BigModel China team usage, CodexBar needs the `Bigmodel-Organization` and `Bigmodel-Project` request headers: + +1. Open the BigModel API-key page and create/copy the API key: + - `https://bigmodel.cn/usercenter/proj-mgmt/apikeys` + - Some accounts still redirect through `https://open.bigmodel.cn/usercenter/apikeys`. +2. Open the team usage dashboard: + - `https://bigmodel.cn/coding-plan/team/usage-stats` +3. Select the organization/team and project to track. +4. Open browser DevTools → Network, refresh the team usage page, and inspect the + request to `api/monitor/usage/quota/limit` or `api/monitor/usage/model-usage`. Copy these request headers: + - `Bigmodel-Organization` → `organizationId` + - `Bigmodel-Project` → `workspaceID` + +Copy each value once, on one line. Multi-line or duplicated IDs can make the API return `data: {}`, leaving MCP, +5-hour, and hourly usage empty. + +## API endpoint +- `GET https://api.z.ai/api/monitor/usage/quota/limit` +- BigModel (China mainland) host: `https://open.bigmodel.cn` +- Override host via Providers → z.ai → *API region* or `Z_AI_API_HOST=open.bigmodel.cn`. +- Override the full quota URL (e.g. coding plan endpoint) via `Z_AI_QUOTA_URL=https://open.bigmodel.cn/api/coding/paas/v4`. +- Endpoint overrides must be explicit HTTPS URLs or bare hosts/paths that CodexBar normalizes to HTTPS. Explicit + `http://` overrides fail closed before the bearer token is attached to a request. If both z.ai overrides are set, + `Z_AI_QUOTA_URL` has priority for quota requests; a stale lower-priority `Z_AI_API_HOST` is ignored for that quota + path, but direct model-usage requests still validate `Z_AI_API_HOST` before sending bearer auth. +- Headers: + - `authorization: Bearer ` + - `accept: application/json` + +### BigModel team usage +- The default usage scope is **personal**. Only a token account with `usageScope: team` is queried as team usage. +- Each z.ai token account can enable **Team mode** via UI, CLI, or config. Team accounts store: + - `usageScope`: `team` + - `organizationId`: BigModel organization id + - `workspaceID`: BigModel project id +- Team quota scope appends `type=2`; team hourly model usage appends `type=3`. Both send the BigModel selectors: + - `Bigmodel-Organization: ` + - `Bigmodel-Project: ` +- Live API checks return success with empty limits when one of the selectors is missing, so CodexBar treats both + Organization ID and Project ID as required for team usage. + +## Usage dashboard +- Global: `https://z.ai/manage-apikey/coding-plan/personal/my-plan` +- BigModel China: `https://bigmodel.cn/coding-plan/personal/usage` +- BigModel China team: `https://bigmodel.cn/coding-plan/team/usage-stats` +- CodexBar's Usage Dashboard action follows the configured API region. + +## Parsing + mapping +- Response fields: + - `data.limits[]` → each limit entry. + - `data.planName` (or `plan`, `plan_type`, `packageName`) → plan label. +- Limit types: + - `TOKENS_LIMIT` → primary (tokens window). + - `TIME_LIMIT` → secondary (MCP/time window) if tokens also present. +- Window duration: + - Unit + number → minutes/hours/days. +- Reset: + - `nextResetTime` (epoch ms) → date. +- Usage details: + - `usageDetails[]` per model (MCP usage list). + +## Key files +- `Sources/CodexBarCore/Providers/Zai/ZaiUsageStats.swift` +- `Sources/CodexBarCore/Providers/Zai/ZaiSettingsReader.swift` +- `Sources/CodexBar/ZaiTokenStore.swift` (legacy migration helper) diff --git a/docs/zed.md b/docs/zed.md new file mode 100644 index 0000000..b609941 --- /dev/null +++ b/docs/zed.md @@ -0,0 +1,76 @@ +--- +summary: "Zed provider data source: editor Keychain session and Zed cloud API." +read_when: + - Debugging Zed usage fetch + - Updating Zed Keychain or cloud API handling + - Adjusting Zed provider UI/menu behavior +--- + +# Zed provider + +CodexBar monitors Zed plan status, billing cycle dates, edit-prediction quota, and overdue invoices via Zed's cloud API. + +## Data source + +**Local probe (Keychain + cloud API)** — reads the same credentials Zed stores after GitHub sign-in, then calls: + +```text +GET https://cloud.zed.dev/client/users/me +Authorization: {user_id} {access_token} +``` + +### Keychain credentials + +| Item | Value | +| --- | --- | +| Service URL | `https://zed.dev` by default, or the configured HTTPS `server_url` for a custom server | +| Keychain class | **Internet password** (`kSecClassInternetPassword`, server = service URL). Generic-password fallback is supported for older layouts. | +| Account | Zed user ID (string) | +| Secret | Access token (UTF-8 bytes) | + +CodexBar requests a non-interactive Keychain read. Existing Zed items can still carry an access-control list that makes +macOS show a SecurityAgent prompt the first time CodexBar reads them. Choose **Always Allow** to avoid repeat prompts. If +Zed has never been signed in, or access is denied, the provider reports **Not signed in to Zed**. + +### Settings override + +CodexBar reads Zed’s user settings from `~/.config/zed/settings.json`. The `credentials_url` setting (falls back to +`server_url`) selects which Keychain entry to read. For the trusted +`https://zed.dev` and `https://staging.zed.dev` servers, Zed may use a separate credential identifier. Custom servers +must use HTTPS and store credentials under the exact same `server_url`; CodexBar rejects cross-origin overrides so a +settings-file change cannot forward a Keychain token to another host. + +## Snapshot mapping + +| Zed field | CodexBar display | +| --- | --- | +| `plan.plan_v3` | Plan label (Free / Pro / Trial / Student / Business) | +| `plan.usage.edit_predictions` | Primary bar: used/limit or “Unlimited” on Pro+ | +| `plan.subscription_period.ended_at` | Billing cycle reset / secondary window | +| `plan.has_overdue_invoices` | Warning note + billing window marker | + +## Limitations + +### Not tracked as “Zed” + +Per [LLM Providers](https://zed.dev/docs/ai/llm-providers.html) and [External Agents](https://zed.dev/docs/ai/external-agents.html): + +- BYOK models → track via OpenAI, Claude, Gemini, etc. +- External agents (Claude Agent, Codex ACP) → bill through those providers + +## Troubleshooting + +### “Not signed in to Zed” +- Sign in from the **Zed editor app** (Command Palette → `client: sign in`). +- Confirm a Keychain internet-password entry exists for server `https://zed.dev` (or your custom `credentials_url`). + +### “Could not read Zed credentials from the Keychain” +- macOS may block Keychain access until you allow CodexBar (same class of issue as other IDE probes). +- Re-sign in to Zed after changing `credentials_url`. + +## Key files + +- `Sources/CodexBarCore/Providers/Zed/ZedStatusProbe.swift` - Keychain read, cloud API, snapshot mapping +- `Sources/CodexBarCore/Providers/Zed/ZedProviderDescriptor.swift` - provider metadata and local fetch strategy +- `Sources/CodexBar/Providers/Zed/ZedProviderImplementation.swift` - app registration +- `Tests/CodexBarTests/ZedStatusProbeTests.swift` - cloud API and routing tests