usage-cli 0.34.3__tar.gz → 0.34.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {usage_cli-0.34.3/usage_cli.egg-info → usage_cli-0.34.5}/PKG-INFO +1 -1
- {usage_cli-0.34.3 → usage_cli-0.34.5}/loaders/muse_quota_probe.py +30 -2
- {usage_cli-0.34.3 → usage_cli-0.34.5}/pyproject.toml +1 -1
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_muse_quota_probe.py +39 -1
- {usage_cli-0.34.3 → usage_cli-0.34.5/usage_cli.egg-info}/PKG-INFO +1 -1
- {usage_cli-0.34.3 → usage_cli-0.34.5}/LICENSE +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/README.md +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/THIRD_PARTY_NOTICES.md +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/adapters/__init__.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/adapters/agy.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/adapters/claude.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/adapters/codex.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/adapters/grok.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/adapters/muse.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/adapters/rate_limits.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/adapters/registry.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/adapters/types.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/analyzer/__init__.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/analyzer/aggregator.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/analyzer/blocks.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/analyzer/diagnoser.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/analyzer/diagnosis_snapshot.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/analyzer/dispatch_ledger.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/analyzer/history_persist.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/analyzer/insights.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/analyzer/ledger_backfill.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/analyzer/persona_loader.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/analyzer/reporter.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/analyzer/subscription.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/analyzer/usage_snapshot.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/i18n.json +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/installer/__init__.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/installer/claude_pane.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/installer/codex_hook_trust.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/installer/login_item.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/installer/session_hooks.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/installer/setup_hook.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/installer/statusline_settings.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/loaders/__init__.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/loaders/_shared_cache_file.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/loaders/agy_disk_cache.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/loaders/agy_loader.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/loaders/agy_quota_probe.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/loaders/cache_quarantine.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/loaders/chromium_cache.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/loaders/claude_desktop.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/loaders/claude_paths.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/loaders/claude_usage.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/loaders/codex_disk_cache.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/loaders/codex_events.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/loaders/codex_fork_replay.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/loaders/codex_loader.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/loaders/codex_paths.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/loaders/disk_cache_common.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/loaders/disk_cache_lifecycle.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/loaders/grok_loader.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/loaders/grok_quota_probe.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/loaders/history_disk_cache.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/loaders/history_loader.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/loaders/jsonl_limits.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/loaders/jsonl_utils.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/loaders/muse_loader.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/main.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/menubar/__init__.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/menubar/actions.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/menubar/agy.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/menubar/app.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/menubar/chrome.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/menubar/fsevents_watch.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/menubar/grok.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/menubar/manual_refresh.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/menubar/menu.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/menubar/muse.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/menubar/new_badge.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/menubar/notify.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/menubar/popover.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/menubar/prefs.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/menubar/refresh.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/menubar/state.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/menubar/title.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/menubar/update.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/menubar/whats_new.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/panels/__init__.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/panels/base.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/panels/catalog.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/panels/dynamic_height.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/panels/panel_scale.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/panels/panel_window.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/panels/panel_window_state.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/panels/payload.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/panels/web_panel.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/panels/window_drag.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/quota/__init__.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/quota/agy_window_keeper.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/quota/burn_rate.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/quota/codex_window_keeper.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/quota/keeper_outcome.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/quota/notifications.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/quota/quota_snapshot.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/quota/status_payload.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/quota/usage_rate.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/quota/window_keeper.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/setup.cfg +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/setup_app.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_adapters_claude.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_adapters_codex.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_adapters_rate_limits.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_aggregator.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_agy_adapter.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_agy_disk_cache.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_agy_loader.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_agy_quota_probe.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_agy_window_keeper.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_analyzer_blocks.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_analyzer_pipeline.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_app_version.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_burn_rate.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_cache_quarantine.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_check_upstream.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_chromium_cache.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_claude_desktop.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_claude_pane.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_claude_paths.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_codex_consistency.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_codex_hook_trust.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_codex_loader.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_codex_window_keeper.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_compact_cards.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_desktop_fresh_cache.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_desktop_quota_display.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_desktop_quota_review.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_diagnoser.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_disk_cache_shards.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_dispatch_ledger.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_doctor.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_dynamic_height.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_fsevents_watch.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_grok_loader.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_grok_quota_probe.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_history_loader.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_history_persist.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_hook_scripts_are_standalone.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_html_report_snapshot.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_i18n_format_fallback.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_i18n_key_parity.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_i18n_packaged_path.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_insights.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_jsonl_utils.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_keeper_menu.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_keeper_outcome.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_ledger_backfill.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_login_item.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_main.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_manual_refresh.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_menubar.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_menubar_agy.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_menubar_grok.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_menubar_muse.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_menubar_notify.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_menubar_prefs.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_menubar_state.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_menubar_update.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_muse_coverage.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_muse_loader.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_muse_review_regressions.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_new_badge.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_packaged_resources.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_packaging.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_panel_footer_layout.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_panel_scale.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_panel_window_state.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_panels.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_panels_lazy_import.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_persona_loader.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_pricing.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_project_resolver.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_quota_aware.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_quota_label.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_report_cold_read.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_report_daily_chart.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_report_filter_js.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_report_share_mask.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_reporter_build_data.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_service_status.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_session_resume.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_setup_app.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_setup_hook.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_setup_hook_coexistence.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_setup_hook_resume.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_setup_hook_terse.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_subprocess_utils.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_subscription.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_taskbar_menu.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_taskbar_obstacles.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_time_utils.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_tui.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_tui_sprite.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_ui_tables.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_update_checker.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_update_gate.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_update_release_notes.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_usage_cli.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_usage_client.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_usage_diagnosis_snapshot.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_usage_dir_sweeper.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_usage_lang.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_usage_logging.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_usage_notifications.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_usage_rate.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_usage_snapshot.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_usage_snapshot_replay.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_usage_statusline.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_usage_statusline_agy.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_usage_statusline_forwarder.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_usage_statusline_grok.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_usage_terse_mode.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_usage_terse_reminder.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_web_panel_payload.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_whats_new.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_wheel_packaging.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_win_login_item.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_window_keeper.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_windows_manifest.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tests/test_wintray.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tui/__init__.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tui/app.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/tui/sprite.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/ui/__init__.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/ui/html_report.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/ui/report_charts.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/ui/report_daily_chart.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/ui/report_filter.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/ui/report_ledger.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/ui/report_scripts.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/ui/report_styles.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/ui/tables.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/updates/__init__.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/updates/checker.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/updates/gate.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/updates/release_notes.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/updates/whats_new.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/usage_app/__init__.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/usage_app/cli.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/usage_app/doctor.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/usage_cli.egg-info/SOURCES.txt +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/usage_cli.egg-info/dependency_links.txt +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/usage_cli.egg-info/entry_points.txt +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/usage_cli.egg-info/requires.txt +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/usage_cli.egg-info/top_level.txt +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/usage_common/__init__.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/usage_common/app_version.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/usage_common/i18n.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/usage_common/prefs.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/usage_common/pricing.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/usage_common/project_resolver.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/usage_common/service_status.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/usage_common/subprocess_utils.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/usage_common/time_utils.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/usage_common/usage_dir_sweeper.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/usage_common/usage_lang.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/usage_common/usage_logging.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/usage_hooks/__init__.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/usage_hooks/usage_quota_aware.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/usage_hooks/usage_session_resume.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/usage_hooks/usage_statusline.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/usage_hooks/usage_statusline_agy.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/usage_hooks/usage_statusline_forwarder.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/usage_hooks/usage_statusline_grok.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/usage_hooks/usage_terse_mode.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/usage_hooks/usage_terse_reminder.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/wintray/__init__.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/wintray/app.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/wintray/login_item.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/wintray/menu.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/wintray/prefs.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/wintray/quota_label.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/wintray/taskbar_menu.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/wintray/taskbar_obstacles.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/wintray/taskbar_overlay.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/wintray/watch.py +0 -0
- {usage_cli-0.34.3 → usage_cli-0.34.5}/wintray/whats_new.py +0 -0
|
@@ -10,12 +10,14 @@ import json
|
|
|
10
10
|
import logging
|
|
11
11
|
import math
|
|
12
12
|
import os
|
|
13
|
+
import re
|
|
13
14
|
import shutil
|
|
14
15
|
import subprocess
|
|
15
16
|
import tempfile
|
|
16
17
|
import threading
|
|
17
18
|
import time
|
|
18
19
|
from contextlib import suppress
|
|
20
|
+
from datetime import datetime
|
|
19
21
|
from pathlib import Path
|
|
20
22
|
from typing import TypedDict, TypeGuard
|
|
21
23
|
|
|
@@ -27,6 +29,9 @@ CACHE_PATH = Path.home() / ".usage/muse_quota.json"
|
|
|
27
29
|
PROBE_DIR = Path.home() / ".usage/muse-probe"
|
|
28
30
|
MUSE_MODEL = "muse-spark-1.3"
|
|
29
31
|
STALE_SECONDS = 30 * 60
|
|
32
|
+
_EXHAUSTED = re.compile(
|
|
33
|
+
r"Subscription quota exhausted\. Your usage window resets at (\d{4}-\d\d-\d\dT[\d:.]+Z)"
|
|
34
|
+
)
|
|
30
35
|
_probe_lock = threading.Lock()
|
|
31
36
|
_probe_running = False
|
|
32
37
|
_retry_after = 0.0
|
|
@@ -76,7 +81,8 @@ def validate_muse_cache(payload: object) -> MuseQuotaResult | None:
|
|
|
76
81
|
if not isinstance(window, dict):
|
|
77
82
|
return None
|
|
78
83
|
used, reset = window.get("used_percent"), window.get("resets_at")
|
|
79
|
-
|
|
84
|
+
# An exhausted window reports past 100 (e.g. 104); the row clamps it for display.
|
|
85
|
+
if not _number(used) or not _number(reset) or used < 0:
|
|
80
86
|
return None
|
|
81
87
|
windows.append(MuseQuotaWindow(used_percent=float(used), resets_at=float(reset)))
|
|
82
88
|
return MuseQuotaResult(
|
|
@@ -108,6 +114,25 @@ def parse_muse_allowance(stdout: str, checked_at: float) -> MuseQuotaResult | No
|
|
|
108
114
|
return None
|
|
109
115
|
|
|
110
116
|
|
|
117
|
+
def parse_exhausted_window(stdout: str, cached: MuseQuotaResult | None) -> MuseQuotaResult | None:
|
|
118
|
+
"""Read the 429 Muse returns once the 5-hour window is used up; it carries no allowance.
|
|
119
|
+
|
|
120
|
+
Only the window's reset time is known, so the weekly reading and its age stay from ``cached``.
|
|
121
|
+
"""
|
|
122
|
+
match = _EXHAUSTED.search(stdout)
|
|
123
|
+
if cached is None or match is None:
|
|
124
|
+
return None
|
|
125
|
+
try:
|
|
126
|
+
reset = datetime.fromisoformat(match[1]).timestamp()
|
|
127
|
+
except ValueError:
|
|
128
|
+
return None
|
|
129
|
+
return MuseQuotaResult(
|
|
130
|
+
checked_at=cached["checked_at"],
|
|
131
|
+
window=MuseQuotaWindow(used_percent=100.0, resets_at=reset),
|
|
132
|
+
weekly=cached["weekly"],
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
|
|
111
136
|
def read_cache() -> MuseQuotaResult | None:
|
|
112
137
|
"""Ignore invalid shared snapshots without deleting or quarantining them."""
|
|
113
138
|
try:
|
|
@@ -213,7 +238,10 @@ def _probe_worker(executable: str) -> None:
|
|
|
213
238
|
process.kill()
|
|
214
239
|
process.communicate()
|
|
215
240
|
raise
|
|
216
|
-
|
|
241
|
+
if process.returncode == 0:
|
|
242
|
+
result = parse_muse_allowance(stdout, time.time())
|
|
243
|
+
else:
|
|
244
|
+
result = parse_exhausted_window(stdout, read_cache())
|
|
217
245
|
if result is not None:
|
|
218
246
|
_write_cache(result)
|
|
219
247
|
succeeded = True
|
|
@@ -60,13 +60,51 @@ def test_read_missing_corrupt_and_good_cache() -> None:
|
|
|
60
60
|
assert probe.read_cache() == quota()
|
|
61
61
|
|
|
62
62
|
|
|
63
|
-
@pytest.mark.parametrize("value", [True, None, "25", -1,
|
|
63
|
+
@pytest.mark.parametrize("value", [True, None, "25", -1, float("nan"), float("inf"), 10**400])
|
|
64
64
|
def test_invalid_percent_rejected(value: object) -> None:
|
|
65
65
|
raw = event()
|
|
66
66
|
raw["payload"]["allowance"]["window"]["used_percent"] = value
|
|
67
67
|
assert probe.parse_muse_allowance(json.dumps(raw), 1000) is None
|
|
68
68
|
|
|
69
69
|
|
|
70
|
+
@pytest.mark.parametrize("value", [100, 104, 105, 250])
|
|
71
|
+
def test_exhausted_window_past_100_is_kept(value: int) -> None:
|
|
72
|
+
raw = event()
|
|
73
|
+
raw["payload"]["allowance"]["window"]["used_percent"] = value
|
|
74
|
+
result = probe.parse_muse_allowance(json.dumps(raw), 1000)
|
|
75
|
+
assert result is not None and result["window"]["used_percent"] == value
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
# Captured from Muse Code 1.4.11 on 2026-10-21 while the 5-hour window was used up.
|
|
79
|
+
EXHAUSTED = json.dumps(
|
|
80
|
+
{
|
|
81
|
+
"payload_type": "run.terminal.failed",
|
|
82
|
+
"payload": {
|
|
83
|
+
"reason": "API error 429 [request_id=x]: Subscription quota exhausted. "
|
|
84
|
+
"Your usage window resets at 2026-10-21T08:28:56Z. (rate_limit_error)"
|
|
85
|
+
},
|
|
86
|
+
}
|
|
87
|
+
)
|
|
88
|
+
EXHAUSTED_QUOTA = {**quota(), "window": {"used_percent": 100.0, "resets_at": 1792571336.0}}
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def test_exhausted_429_keeps_weekly_and_snapshot_age() -> None:
|
|
92
|
+
assert probe.parse_exhausted_window(EXHAUSTED, quota()) == EXHAUSTED_QUOTA
|
|
93
|
+
assert probe.parse_exhausted_window(EXHAUSTED, None) is None
|
|
94
|
+
assert probe.parse_exhausted_window(json.dumps(event()), quota()) is None
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def test_exhausted_probe_updates_session_window(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
98
|
+
probe.CACHE_PATH.write_text(json.dumps(quota()))
|
|
99
|
+
process = Mock(returncode=1)
|
|
100
|
+
process.poll.return_value = 1
|
|
101
|
+
process.communicate.return_value = (EXHAUSTED, "")
|
|
102
|
+
monkeypatch.setattr(subprocess, "Popen", Mock(return_value=process))
|
|
103
|
+
probe._probe_worker("/fake/muse")
|
|
104
|
+
assert probe.read_cache() == EXHAUSTED_QUOTA
|
|
105
|
+
assert probe._retry_after == 0.0
|
|
106
|
+
|
|
107
|
+
|
|
70
108
|
def test_missing_weekly_is_rejected() -> None:
|
|
71
109
|
raw = event()
|
|
72
110
|
del raw["payload"]["allowance"]["weekly"]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|