usage-cli 0.31.5__tar.gz → 0.31.6__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.31.5 → usage_cli-0.31.6}/PKG-INFO +1 -1
- {usage_cli-0.31.5 → usage_cli-0.31.6}/pyproject.toml +1 -1
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_usage_statusline_grok.py +13 -4
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_wintray.py +31 -1
- {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_cli.egg-info/PKG-INFO +1 -1
- {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_statusline_grok.py +8 -2
- {usage_cli-0.31.5 → usage_cli-0.31.6}/wintray/app.py +13 -3
- {usage_cli-0.31.5 → usage_cli-0.31.6}/LICENSE +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/README.md +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/adapters/__init__.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/adapters/agy.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/adapters/claude.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/adapters/codex.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/adapters/grok.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/adapters/muse.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/adapters/rate_limits.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/adapters/registry.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/adapters/types.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/analyzer/__init__.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/analyzer/aggregator.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/analyzer/blocks.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/analyzer/diagnoser.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/analyzer/dispatch_ledger.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/analyzer/insights.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/analyzer/persona_loader.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/analyzer/reporter.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/analyzer/subscription.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/analyzer/usage_snapshot.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/doctor.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/fsevents_watch.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/i18n.json +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/i18n.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/installer/__init__.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/installer/login_item.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/installer/session_hooks.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/installer/setup_hook.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/installer/statusline_settings.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/__init__.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/agy_disk_cache.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/agy_loader.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/agy_quota_probe.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/cache_quarantine.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/claude_paths.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/codex_disk_cache.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/codex_events.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/codex_fork_replay.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/codex_loader.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/codex_paths.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/disk_cache_common.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/disk_cache_lifecycle.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/grok_loader.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/grok_quota_probe.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/history_disk_cache.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/history_loader.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/jsonl_limits.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/jsonl_utils.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/muse_loader.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/main.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/menubar/__init__.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/menubar/actions.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/menubar/agy.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/menubar/app.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/menubar/chrome.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/menubar/grok.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/menubar/menu.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/menubar/notify.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/menubar/popover.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/menubar/prefs.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/menubar/refresh.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/menubar/state.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/menubar/title.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/menubar/update.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/panels/__init__.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/panels/base.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/panels/dynamic_height.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/panels/panel_scale.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/panels/panel_window.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/panels/panel_window_state.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/panels/payload.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/panels/web_panel.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/panels/window_drag.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/prefs.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/pricing.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/project_resolver.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/quota/__init__.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/quota/agy_window_keeper.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/quota/burn_rate.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/quota/codex_window_keeper.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/quota/usage_rate.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/quota/window_keeper.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/service_status.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/setup.cfg +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/setup_app.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_adapters_claude.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_adapters_codex.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_adapters_rate_limits.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_aggregator.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_agy_adapter.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_agy_disk_cache.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_agy_loader.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_agy_quota_probe.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_agy_window_keeper.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_analyzer_blocks.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_analyzer_pipeline.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_burn_rate.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_cache_quarantine.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_claude_paths.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_codex_consistency.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_codex_loader.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_codex_window_keeper.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_diagnoser.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_disk_cache_shards.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_dispatch_ledger.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_doctor.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_dynamic_height.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_fsevents_watch.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_grok_loader.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_grok_quota_probe.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_history_loader.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_hook_scripts_are_standalone.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_html_report_snapshot.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_i18n_format_fallback.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_i18n_key_parity.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_i18n_packaged_path.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_insights.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_jsonl_utils.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_login_item.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_main.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_menubar.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_menubar_agy.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_menubar_grok.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_menubar_notify.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_menubar_prefs.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_menubar_state.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_muse_loader.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_packaged_resources.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_packaging.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_panel_footer_layout.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_panel_scale.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_panel_window_state.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_panels.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_panels_lazy_import.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_persona_loader.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_pricing.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_project_resolver.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_report_daily_chart.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_report_filter_js.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_reporter_build_data.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_service_status.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_session_resume.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_setup_app.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_setup_hook.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_setup_hook_coexistence.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_setup_hook_resume.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_setup_hook_terse.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_subprocess_utils.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_subscription.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_time_utils.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_tui.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_tui_sprite.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_ui_tables.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_update_checker.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_update_gate.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_update_release_notes.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_usage_cli.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_usage_client.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_usage_diagnosis_snapshot.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_usage_dir_sweeper.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_usage_lang.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_usage_logging.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_usage_notifications.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_usage_rate.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_usage_snapshot.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_usage_snapshot_replay.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_usage_statusline.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_usage_statusline_agy.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_usage_statusline_forwarder.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_usage_terse_mode.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_usage_terse_reminder.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_web_panel_payload.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_wheel_packaging.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_win_login_item.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_window_keeper.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_windows_manifest.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tui/__init__.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tui/app.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/tui/sprite.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/ui/__init__.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/ui/html_report.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/ui/report_charts.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/ui/report_daily_chart.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/ui/report_filter.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/ui/report_ledger.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/ui/report_scripts.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/ui/report_styles.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/ui/tables.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/updates/__init__.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/updates/checker.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/updates/gate.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/updates/release_notes.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_cli.egg-info/SOURCES.txt +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_cli.egg-info/dependency_links.txt +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_cli.egg-info/entry_points.txt +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_cli.egg-info/requires.txt +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_cli.egg-info/top_level.txt +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_cli.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_client.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_common/__init__.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_common/subprocess_utils.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_common/time_utils.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_common/usage_dir_sweeper.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_common/usage_lang.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_common/usage_logging.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_diagnosis_snapshot.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_notifications.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_session_resume.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_statusline.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_statusline_agy.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_statusline_forwarder.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_terse_mode.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_terse_reminder.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/wintray/__init__.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/wintray/login_item.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/wintray/menu.py +0 -0
- {usage_cli-0.31.5 → usage_cli-0.31.6}/wintray/watch.py +0 -0
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
from __future__ import annotations
|
|
8
8
|
|
|
9
9
|
import json
|
|
10
|
+
import os
|
|
10
11
|
import re
|
|
11
12
|
import tomllib
|
|
12
13
|
from pathlib import Path
|
|
@@ -71,6 +72,11 @@ def _visible(value: str) -> str:
|
|
|
71
72
|
return _ANSI.sub("", value)
|
|
72
73
|
|
|
73
74
|
|
|
75
|
+
def test_progress_bar_chars_are_platform_specific() -> None:
|
|
76
|
+
assert usage_statusline_grok._progress_bar_chars("nt") == ("█", "░")
|
|
77
|
+
assert usage_statusline_grok._progress_bar_chars("posix") == ("■", "□")
|
|
78
|
+
|
|
79
|
+
|
|
74
80
|
def test_render_fixture_contains_expected_status(
|
|
75
81
|
monkeypatch: pytest.MonkeyPatch,
|
|
76
82
|
tmp_path: Path,
|
|
@@ -82,11 +88,12 @@ def test_render_fixture_contains_expected_status(
|
|
|
82
88
|
monkeypatch.setenv("COLUMNS", "300")
|
|
83
89
|
|
|
84
90
|
output = _visible(usage_statusline_grok.render(_fixture_data()))
|
|
91
|
+
filled, empty = usage_statusline_grok._progress_bar_chars(os.name)
|
|
85
92
|
|
|
86
93
|
assert "project(main)" in output
|
|
87
|
-
assert "
|
|
94
|
+
assert f"週配額:{filled * 3}{empty * 5} 42%" in output
|
|
88
95
|
assert re.search(r"\(剩[0-9]+d[0-9]+h\)", output)
|
|
89
|
-
assert "
|
|
96
|
+
assert f"對話窗:{filled}{empty * 7} 8% / 2.0M" in output
|
|
90
97
|
assert "會話時長:20min" in output
|
|
91
98
|
assert "Grok 4.6/深思" in output
|
|
92
99
|
assert output.count("\n") == 1
|
|
@@ -160,7 +167,8 @@ def test_render_degrades_for_narrow_terminal(
|
|
|
160
167
|
assert "Weekly:42%" in first_line
|
|
161
168
|
assert "Context:8%" in first_line
|
|
162
169
|
assert "left" not in first_line
|
|
163
|
-
|
|
170
|
+
filled, _empty = usage_statusline_grok._progress_bar_chars(os.name)
|
|
171
|
+
assert filled not in first_line
|
|
164
172
|
|
|
165
173
|
|
|
166
174
|
def _patch_grok_paths(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> tuple[Path, Path, Path]:
|
|
@@ -377,5 +385,6 @@ def test_render_shows_zero_quota_when_percent_is_omitted(
|
|
|
377
385
|
monkeypatch.setenv("COLUMNS", "300")
|
|
378
386
|
|
|
379
387
|
output = _visible(usage_statusline_grok.render(_fixture_data()))
|
|
388
|
+
_filled, empty = usage_statusline_grok._progress_bar_chars(os.name)
|
|
380
389
|
|
|
381
|
-
assert "
|
|
390
|
+
assert f"週配額:{empty * 8} 0%" in output
|
|
@@ -1612,7 +1612,9 @@ def test_panel_and_tray_menus_render_the_shared_model(
|
|
|
1612
1612
|
assert [
|
|
1613
1613
|
"separator" if item is FakeMenu.SEPARATOR else item.label for item in tray_menu.items[1:]
|
|
1614
1614
|
] == [
|
|
1615
|
-
"separator"
|
|
1615
|
+
"separator"
|
|
1616
|
+
if isinstance(entry, wintray_menu.MenuSeparator)
|
|
1617
|
+
else wintray._without_power_glyph(_t("en", entry.i18n_key))
|
|
1616
1618
|
for entry in tray_model
|
|
1617
1619
|
]
|
|
1618
1620
|
assert model_keys(tray_model) == ["reset_panel_position", "separator", "quit"]
|
|
@@ -1631,6 +1633,34 @@ def test_panel_body_keeps_refresh_and_quit_escape_controls(
|
|
|
1631
1633
|
assert 'data-action="quit"' in html
|
|
1632
1634
|
|
|
1633
1635
|
|
|
1636
|
+
@pytest.mark.parametrize("_panel_id,_key,filename", wintray.WINDOWS_PANELS)
|
|
1637
|
+
def test_panel_html_removes_the_power_glyph(_panel_id: str, _key: str, filename: str) -> None:
|
|
1638
|
+
html = wintray.panel_html(filename)
|
|
1639
|
+
|
|
1640
|
+
assert "⏻" not in html
|
|
1641
|
+
assert '"quit": "結束"' in html
|
|
1642
|
+
assert '"quit": "⏻ 結束"' not in html
|
|
1643
|
+
|
|
1644
|
+
|
|
1645
|
+
def test_tray_quit_label_removes_the_power_glyph() -> None:
|
|
1646
|
+
class FakeMenuItem:
|
|
1647
|
+
def __init__(self, label: str, action: object, **kwargs: object) -> None:
|
|
1648
|
+
self.label = label
|
|
1649
|
+
|
|
1650
|
+
class FakeMenu:
|
|
1651
|
+
SEPARATOR = object()
|
|
1652
|
+
|
|
1653
|
+
controller = wintray._WindowsTrayController(mock=True, interval=60)
|
|
1654
|
+
controller.language = "zh-TW"
|
|
1655
|
+
entry = wintray_menu.MenuCommand("quit", "quit", surfaces=frozenset({wintray_menu.TRAY}))
|
|
1656
|
+
item = wintray._tray_menu_entry(
|
|
1657
|
+
SimpleNamespace(Menu=FakeMenu, MenuItem=FakeMenuItem), controller, entry
|
|
1658
|
+
)
|
|
1659
|
+
|
|
1660
|
+
assert "⏻" not in item.label
|
|
1661
|
+
assert item.label == item.label.lstrip()
|
|
1662
|
+
|
|
1663
|
+
|
|
1634
1664
|
@pytest.mark.parametrize(
|
|
1635
1665
|
("payload", "method", "expected"),
|
|
1636
1666
|
[
|
|
@@ -175,12 +175,18 @@ def color_by_pct(pct: float) -> str:
|
|
|
175
175
|
return "\033[38;5;160m"
|
|
176
176
|
|
|
177
177
|
|
|
178
|
+
def _progress_bar_chars(os_name: str) -> Tuple[str, str]:
|
|
179
|
+
# Legacy Windows consoles draw ■□ double-width.
|
|
180
|
+
return ("█", "░") if os_name == "nt" else ("■", "□")
|
|
181
|
+
|
|
182
|
+
|
|
178
183
|
def progress_bar(value: Any, bar_width: int = 8) -> str:
|
|
179
184
|
pct = max(0.0, min(100.0, float(value)))
|
|
180
185
|
filled = round(pct / 100 * bar_width)
|
|
186
|
+
filled_char, empty_char = _progress_bar_chars(os.name)
|
|
181
187
|
return (
|
|
182
|
-
f"{color_by_pct(pct)}{
|
|
183
|
-
f"{
|
|
188
|
+
f"{color_by_pct(pct)}{filled_char * filled}{C['reset']}"
|
|
189
|
+
f"{empty_char * (bar_width - filled)} "
|
|
184
190
|
f"{color_by_pct(pct)}{pct:.0f}%{C['reset']}"
|
|
185
191
|
)
|
|
186
192
|
|
|
@@ -604,12 +604,17 @@ def draw_tray_icon(used_percent: float | None) -> Image:
|
|
|
604
604
|
return image
|
|
605
605
|
|
|
606
606
|
|
|
607
|
+
def _without_power_glyph(text: str) -> str:
|
|
608
|
+
"""Windows fonts lack U+23FB."""
|
|
609
|
+
return text.replace("⏻ ", "")
|
|
610
|
+
|
|
611
|
+
|
|
607
612
|
def panel_html(filename: str) -> str:
|
|
608
613
|
html = _load_panel_html(filename)
|
|
609
614
|
html = html.replace("{{PANEL_FLAVOR}}", _panel_flavor())
|
|
610
615
|
html = inject_content_height_script(html)
|
|
611
616
|
marker = "<head>"
|
|
612
|
-
return html.replace(marker, f"{marker}\n{JS_SHIM}", 1)
|
|
617
|
+
return _without_power_glyph(html.replace(marker, f"{marker}\n{JS_SHIM}", 1))
|
|
613
618
|
|
|
614
619
|
|
|
615
620
|
def _active_panel_id() -> str:
|
|
@@ -2250,7 +2255,10 @@ def _tray_menu_entry(
|
|
|
2250
2255
|
return pystray.Menu.SEPARATOR
|
|
2251
2256
|
if isinstance(entry, wintray_menu.MenuGroup):
|
|
2252
2257
|
children = tuple(_tray_menu_entry(pystray, controller, child) for child in entry.children)
|
|
2253
|
-
return pystray.MenuItem(
|
|
2258
|
+
return pystray.MenuItem(
|
|
2259
|
+
_without_power_glyph(_t(controller.language, entry.i18n_key)),
|
|
2260
|
+
pystray.Menu(*children),
|
|
2261
|
+
)
|
|
2254
2262
|
action = getattr(controller, entry.action)
|
|
2255
2263
|
kwargs: dict[str, object] = {"radio": entry.radio}
|
|
2256
2264
|
if entry.checked_by is not None:
|
|
@@ -2261,7 +2269,9 @@ def _tray_menu_entry(
|
|
|
2261
2269
|
def action(_icon: Any, _item: Any, *, value: str = value) -> Any:
|
|
2262
2270
|
return getattr(controller, entry.action)(value)
|
|
2263
2271
|
|
|
2264
|
-
return pystray.MenuItem(
|
|
2272
|
+
return pystray.MenuItem(
|
|
2273
|
+
_without_power_glyph(_t(controller.language, entry.i18n_key)), action, **kwargs
|
|
2274
|
+
)
|
|
2265
2275
|
|
|
2266
2276
|
|
|
2267
2277
|
def _session_resume_enabled() -> bool:
|
|
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
|
|
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
|