usage-cli 0.34.2__tar.gz → 0.34.3__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.
Files changed (281) hide show
  1. {usage_cli-0.34.2/usage_cli.egg-info → usage_cli-0.34.3}/PKG-INFO +1 -1
  2. {usage_cli-0.34.2 → usage_cli-0.34.3}/pyproject.toml +1 -1
  3. {usage_cli-0.34.2 → usage_cli-0.34.3}/quota/codex_window_keeper.py +2 -0
  4. {usage_cli-0.34.2 → usage_cli-0.34.3}/quota/window_keeper.py +6 -0
  5. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_codex_window_keeper.py +1 -0
  6. usage_cli-0.34.3/tests/test_taskbar_obstacles.py +118 -0
  7. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_window_keeper.py +4 -0
  8. {usage_cli-0.34.2 → usage_cli-0.34.3/usage_cli.egg-info}/PKG-INFO +1 -1
  9. {usage_cli-0.34.2 → usage_cli-0.34.3}/usage_cli.egg-info/SOURCES.txt +1 -0
  10. {usage_cli-0.34.2 → usage_cli-0.34.3}/wintray/taskbar_obstacles.py +73 -1
  11. {usage_cli-0.34.2 → usage_cli-0.34.3}/LICENSE +0 -0
  12. {usage_cli-0.34.2 → usage_cli-0.34.3}/README.md +0 -0
  13. {usage_cli-0.34.2 → usage_cli-0.34.3}/THIRD_PARTY_NOTICES.md +0 -0
  14. {usage_cli-0.34.2 → usage_cli-0.34.3}/adapters/__init__.py +0 -0
  15. {usage_cli-0.34.2 → usage_cli-0.34.3}/adapters/agy.py +0 -0
  16. {usage_cli-0.34.2 → usage_cli-0.34.3}/adapters/claude.py +0 -0
  17. {usage_cli-0.34.2 → usage_cli-0.34.3}/adapters/codex.py +0 -0
  18. {usage_cli-0.34.2 → usage_cli-0.34.3}/adapters/grok.py +0 -0
  19. {usage_cli-0.34.2 → usage_cli-0.34.3}/adapters/muse.py +0 -0
  20. {usage_cli-0.34.2 → usage_cli-0.34.3}/adapters/rate_limits.py +0 -0
  21. {usage_cli-0.34.2 → usage_cli-0.34.3}/adapters/registry.py +0 -0
  22. {usage_cli-0.34.2 → usage_cli-0.34.3}/adapters/types.py +0 -0
  23. {usage_cli-0.34.2 → usage_cli-0.34.3}/analyzer/__init__.py +0 -0
  24. {usage_cli-0.34.2 → usage_cli-0.34.3}/analyzer/aggregator.py +0 -0
  25. {usage_cli-0.34.2 → usage_cli-0.34.3}/analyzer/blocks.py +0 -0
  26. {usage_cli-0.34.2 → usage_cli-0.34.3}/analyzer/diagnoser.py +0 -0
  27. {usage_cli-0.34.2 → usage_cli-0.34.3}/analyzer/diagnosis_snapshot.py +0 -0
  28. {usage_cli-0.34.2 → usage_cli-0.34.3}/analyzer/dispatch_ledger.py +0 -0
  29. {usage_cli-0.34.2 → usage_cli-0.34.3}/analyzer/history_persist.py +0 -0
  30. {usage_cli-0.34.2 → usage_cli-0.34.3}/analyzer/insights.py +0 -0
  31. {usage_cli-0.34.2 → usage_cli-0.34.3}/analyzer/ledger_backfill.py +0 -0
  32. {usage_cli-0.34.2 → usage_cli-0.34.3}/analyzer/persona_loader.py +0 -0
  33. {usage_cli-0.34.2 → usage_cli-0.34.3}/analyzer/reporter.py +0 -0
  34. {usage_cli-0.34.2 → usage_cli-0.34.3}/analyzer/subscription.py +0 -0
  35. {usage_cli-0.34.2 → usage_cli-0.34.3}/analyzer/usage_snapshot.py +0 -0
  36. {usage_cli-0.34.2 → usage_cli-0.34.3}/i18n.json +0 -0
  37. {usage_cli-0.34.2 → usage_cli-0.34.3}/installer/__init__.py +0 -0
  38. {usage_cli-0.34.2 → usage_cli-0.34.3}/installer/claude_pane.py +0 -0
  39. {usage_cli-0.34.2 → usage_cli-0.34.3}/installer/codex_hook_trust.py +0 -0
  40. {usage_cli-0.34.2 → usage_cli-0.34.3}/installer/login_item.py +0 -0
  41. {usage_cli-0.34.2 → usage_cli-0.34.3}/installer/session_hooks.py +0 -0
  42. {usage_cli-0.34.2 → usage_cli-0.34.3}/installer/setup_hook.py +0 -0
  43. {usage_cli-0.34.2 → usage_cli-0.34.3}/installer/statusline_settings.py +0 -0
  44. {usage_cli-0.34.2 → usage_cli-0.34.3}/loaders/__init__.py +0 -0
  45. {usage_cli-0.34.2 → usage_cli-0.34.3}/loaders/_shared_cache_file.py +0 -0
  46. {usage_cli-0.34.2 → usage_cli-0.34.3}/loaders/agy_disk_cache.py +0 -0
  47. {usage_cli-0.34.2 → usage_cli-0.34.3}/loaders/agy_loader.py +0 -0
  48. {usage_cli-0.34.2 → usage_cli-0.34.3}/loaders/agy_quota_probe.py +0 -0
  49. {usage_cli-0.34.2 → usage_cli-0.34.3}/loaders/cache_quarantine.py +0 -0
  50. {usage_cli-0.34.2 → usage_cli-0.34.3}/loaders/chromium_cache.py +0 -0
  51. {usage_cli-0.34.2 → usage_cli-0.34.3}/loaders/claude_desktop.py +0 -0
  52. {usage_cli-0.34.2 → usage_cli-0.34.3}/loaders/claude_paths.py +0 -0
  53. {usage_cli-0.34.2 → usage_cli-0.34.3}/loaders/claude_usage.py +0 -0
  54. {usage_cli-0.34.2 → usage_cli-0.34.3}/loaders/codex_disk_cache.py +0 -0
  55. {usage_cli-0.34.2 → usage_cli-0.34.3}/loaders/codex_events.py +0 -0
  56. {usage_cli-0.34.2 → usage_cli-0.34.3}/loaders/codex_fork_replay.py +0 -0
  57. {usage_cli-0.34.2 → usage_cli-0.34.3}/loaders/codex_loader.py +0 -0
  58. {usage_cli-0.34.2 → usage_cli-0.34.3}/loaders/codex_paths.py +0 -0
  59. {usage_cli-0.34.2 → usage_cli-0.34.3}/loaders/disk_cache_common.py +0 -0
  60. {usage_cli-0.34.2 → usage_cli-0.34.3}/loaders/disk_cache_lifecycle.py +0 -0
  61. {usage_cli-0.34.2 → usage_cli-0.34.3}/loaders/grok_loader.py +0 -0
  62. {usage_cli-0.34.2 → usage_cli-0.34.3}/loaders/grok_quota_probe.py +0 -0
  63. {usage_cli-0.34.2 → usage_cli-0.34.3}/loaders/history_disk_cache.py +0 -0
  64. {usage_cli-0.34.2 → usage_cli-0.34.3}/loaders/history_loader.py +0 -0
  65. {usage_cli-0.34.2 → usage_cli-0.34.3}/loaders/jsonl_limits.py +0 -0
  66. {usage_cli-0.34.2 → usage_cli-0.34.3}/loaders/jsonl_utils.py +0 -0
  67. {usage_cli-0.34.2 → usage_cli-0.34.3}/loaders/muse_loader.py +0 -0
  68. {usage_cli-0.34.2 → usage_cli-0.34.3}/loaders/muse_quota_probe.py +0 -0
  69. {usage_cli-0.34.2 → usage_cli-0.34.3}/main.py +0 -0
  70. {usage_cli-0.34.2 → usage_cli-0.34.3}/menubar/__init__.py +0 -0
  71. {usage_cli-0.34.2 → usage_cli-0.34.3}/menubar/actions.py +0 -0
  72. {usage_cli-0.34.2 → usage_cli-0.34.3}/menubar/agy.py +0 -0
  73. {usage_cli-0.34.2 → usage_cli-0.34.3}/menubar/app.py +0 -0
  74. {usage_cli-0.34.2 → usage_cli-0.34.3}/menubar/chrome.py +0 -0
  75. {usage_cli-0.34.2 → usage_cli-0.34.3}/menubar/fsevents_watch.py +0 -0
  76. {usage_cli-0.34.2 → usage_cli-0.34.3}/menubar/grok.py +0 -0
  77. {usage_cli-0.34.2 → usage_cli-0.34.3}/menubar/manual_refresh.py +0 -0
  78. {usage_cli-0.34.2 → usage_cli-0.34.3}/menubar/menu.py +0 -0
  79. {usage_cli-0.34.2 → usage_cli-0.34.3}/menubar/muse.py +0 -0
  80. {usage_cli-0.34.2 → usage_cli-0.34.3}/menubar/new_badge.py +0 -0
  81. {usage_cli-0.34.2 → usage_cli-0.34.3}/menubar/notify.py +0 -0
  82. {usage_cli-0.34.2 → usage_cli-0.34.3}/menubar/popover.py +0 -0
  83. {usage_cli-0.34.2 → usage_cli-0.34.3}/menubar/prefs.py +0 -0
  84. {usage_cli-0.34.2 → usage_cli-0.34.3}/menubar/refresh.py +0 -0
  85. {usage_cli-0.34.2 → usage_cli-0.34.3}/menubar/state.py +0 -0
  86. {usage_cli-0.34.2 → usage_cli-0.34.3}/menubar/title.py +0 -0
  87. {usage_cli-0.34.2 → usage_cli-0.34.3}/menubar/update.py +0 -0
  88. {usage_cli-0.34.2 → usage_cli-0.34.3}/menubar/whats_new.py +0 -0
  89. {usage_cli-0.34.2 → usage_cli-0.34.3}/panels/__init__.py +0 -0
  90. {usage_cli-0.34.2 → usage_cli-0.34.3}/panels/base.py +0 -0
  91. {usage_cli-0.34.2 → usage_cli-0.34.3}/panels/catalog.py +0 -0
  92. {usage_cli-0.34.2 → usage_cli-0.34.3}/panels/dynamic_height.py +0 -0
  93. {usage_cli-0.34.2 → usage_cli-0.34.3}/panels/panel_scale.py +0 -0
  94. {usage_cli-0.34.2 → usage_cli-0.34.3}/panels/panel_window.py +0 -0
  95. {usage_cli-0.34.2 → usage_cli-0.34.3}/panels/panel_window_state.py +0 -0
  96. {usage_cli-0.34.2 → usage_cli-0.34.3}/panels/payload.py +0 -0
  97. {usage_cli-0.34.2 → usage_cli-0.34.3}/panels/web_panel.py +0 -0
  98. {usage_cli-0.34.2 → usage_cli-0.34.3}/panels/window_drag.py +0 -0
  99. {usage_cli-0.34.2 → usage_cli-0.34.3}/quota/__init__.py +0 -0
  100. {usage_cli-0.34.2 → usage_cli-0.34.3}/quota/agy_window_keeper.py +0 -0
  101. {usage_cli-0.34.2 → usage_cli-0.34.3}/quota/burn_rate.py +0 -0
  102. {usage_cli-0.34.2 → usage_cli-0.34.3}/quota/keeper_outcome.py +0 -0
  103. {usage_cli-0.34.2 → usage_cli-0.34.3}/quota/notifications.py +0 -0
  104. {usage_cli-0.34.2 → usage_cli-0.34.3}/quota/quota_snapshot.py +0 -0
  105. {usage_cli-0.34.2 → usage_cli-0.34.3}/quota/status_payload.py +0 -0
  106. {usage_cli-0.34.2 → usage_cli-0.34.3}/quota/usage_rate.py +0 -0
  107. {usage_cli-0.34.2 → usage_cli-0.34.3}/setup.cfg +0 -0
  108. {usage_cli-0.34.2 → usage_cli-0.34.3}/setup_app.py +0 -0
  109. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_adapters_claude.py +0 -0
  110. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_adapters_codex.py +0 -0
  111. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_adapters_rate_limits.py +0 -0
  112. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_aggregator.py +0 -0
  113. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_agy_adapter.py +0 -0
  114. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_agy_disk_cache.py +0 -0
  115. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_agy_loader.py +0 -0
  116. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_agy_quota_probe.py +0 -0
  117. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_agy_window_keeper.py +0 -0
  118. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_analyzer_blocks.py +0 -0
  119. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_analyzer_pipeline.py +0 -0
  120. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_app_version.py +0 -0
  121. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_burn_rate.py +0 -0
  122. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_cache_quarantine.py +0 -0
  123. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_check_upstream.py +0 -0
  124. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_chromium_cache.py +0 -0
  125. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_claude_desktop.py +0 -0
  126. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_claude_pane.py +0 -0
  127. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_claude_paths.py +0 -0
  128. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_codex_consistency.py +0 -0
  129. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_codex_hook_trust.py +0 -0
  130. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_codex_loader.py +0 -0
  131. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_compact_cards.py +0 -0
  132. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_desktop_fresh_cache.py +0 -0
  133. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_desktop_quota_display.py +0 -0
  134. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_desktop_quota_review.py +0 -0
  135. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_diagnoser.py +0 -0
  136. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_disk_cache_shards.py +0 -0
  137. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_dispatch_ledger.py +0 -0
  138. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_doctor.py +0 -0
  139. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_dynamic_height.py +0 -0
  140. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_fsevents_watch.py +0 -0
  141. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_grok_loader.py +0 -0
  142. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_grok_quota_probe.py +0 -0
  143. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_history_loader.py +0 -0
  144. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_history_persist.py +0 -0
  145. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_hook_scripts_are_standalone.py +0 -0
  146. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_html_report_snapshot.py +0 -0
  147. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_i18n_format_fallback.py +0 -0
  148. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_i18n_key_parity.py +0 -0
  149. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_i18n_packaged_path.py +0 -0
  150. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_insights.py +0 -0
  151. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_jsonl_utils.py +0 -0
  152. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_keeper_menu.py +0 -0
  153. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_keeper_outcome.py +0 -0
  154. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_ledger_backfill.py +0 -0
  155. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_login_item.py +0 -0
  156. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_main.py +0 -0
  157. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_manual_refresh.py +0 -0
  158. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_menubar.py +0 -0
  159. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_menubar_agy.py +0 -0
  160. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_menubar_grok.py +0 -0
  161. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_menubar_muse.py +0 -0
  162. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_menubar_notify.py +0 -0
  163. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_menubar_prefs.py +0 -0
  164. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_menubar_state.py +0 -0
  165. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_menubar_update.py +0 -0
  166. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_muse_coverage.py +0 -0
  167. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_muse_loader.py +0 -0
  168. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_muse_quota_probe.py +0 -0
  169. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_muse_review_regressions.py +0 -0
  170. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_new_badge.py +0 -0
  171. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_packaged_resources.py +0 -0
  172. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_packaging.py +0 -0
  173. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_panel_footer_layout.py +0 -0
  174. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_panel_scale.py +0 -0
  175. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_panel_window_state.py +0 -0
  176. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_panels.py +0 -0
  177. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_panels_lazy_import.py +0 -0
  178. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_persona_loader.py +0 -0
  179. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_pricing.py +0 -0
  180. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_project_resolver.py +0 -0
  181. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_quota_aware.py +0 -0
  182. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_quota_label.py +0 -0
  183. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_report_cold_read.py +0 -0
  184. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_report_daily_chart.py +0 -0
  185. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_report_filter_js.py +0 -0
  186. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_report_share_mask.py +0 -0
  187. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_reporter_build_data.py +0 -0
  188. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_service_status.py +0 -0
  189. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_session_resume.py +0 -0
  190. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_setup_app.py +0 -0
  191. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_setup_hook.py +0 -0
  192. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_setup_hook_coexistence.py +0 -0
  193. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_setup_hook_resume.py +0 -0
  194. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_setup_hook_terse.py +0 -0
  195. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_subprocess_utils.py +0 -0
  196. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_subscription.py +0 -0
  197. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_taskbar_menu.py +0 -0
  198. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_time_utils.py +0 -0
  199. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_tui.py +0 -0
  200. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_tui_sprite.py +0 -0
  201. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_ui_tables.py +0 -0
  202. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_update_checker.py +0 -0
  203. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_update_gate.py +0 -0
  204. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_update_release_notes.py +0 -0
  205. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_usage_cli.py +0 -0
  206. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_usage_client.py +0 -0
  207. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_usage_diagnosis_snapshot.py +0 -0
  208. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_usage_dir_sweeper.py +0 -0
  209. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_usage_lang.py +0 -0
  210. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_usage_logging.py +0 -0
  211. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_usage_notifications.py +0 -0
  212. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_usage_rate.py +0 -0
  213. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_usage_snapshot.py +0 -0
  214. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_usage_snapshot_replay.py +0 -0
  215. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_usage_statusline.py +0 -0
  216. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_usage_statusline_agy.py +0 -0
  217. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_usage_statusline_forwarder.py +0 -0
  218. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_usage_statusline_grok.py +0 -0
  219. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_usage_terse_mode.py +0 -0
  220. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_usage_terse_reminder.py +0 -0
  221. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_web_panel_payload.py +0 -0
  222. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_whats_new.py +0 -0
  223. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_wheel_packaging.py +0 -0
  224. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_win_login_item.py +0 -0
  225. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_windows_manifest.py +0 -0
  226. {usage_cli-0.34.2 → usage_cli-0.34.3}/tests/test_wintray.py +0 -0
  227. {usage_cli-0.34.2 → usage_cli-0.34.3}/tui/__init__.py +0 -0
  228. {usage_cli-0.34.2 → usage_cli-0.34.3}/tui/app.py +0 -0
  229. {usage_cli-0.34.2 → usage_cli-0.34.3}/tui/sprite.py +0 -0
  230. {usage_cli-0.34.2 → usage_cli-0.34.3}/ui/__init__.py +0 -0
  231. {usage_cli-0.34.2 → usage_cli-0.34.3}/ui/html_report.py +0 -0
  232. {usage_cli-0.34.2 → usage_cli-0.34.3}/ui/report_charts.py +0 -0
  233. {usage_cli-0.34.2 → usage_cli-0.34.3}/ui/report_daily_chart.py +0 -0
  234. {usage_cli-0.34.2 → usage_cli-0.34.3}/ui/report_filter.py +0 -0
  235. {usage_cli-0.34.2 → usage_cli-0.34.3}/ui/report_ledger.py +0 -0
  236. {usage_cli-0.34.2 → usage_cli-0.34.3}/ui/report_scripts.py +0 -0
  237. {usage_cli-0.34.2 → usage_cli-0.34.3}/ui/report_styles.py +0 -0
  238. {usage_cli-0.34.2 → usage_cli-0.34.3}/ui/tables.py +0 -0
  239. {usage_cli-0.34.2 → usage_cli-0.34.3}/updates/__init__.py +0 -0
  240. {usage_cli-0.34.2 → usage_cli-0.34.3}/updates/checker.py +0 -0
  241. {usage_cli-0.34.2 → usage_cli-0.34.3}/updates/gate.py +0 -0
  242. {usage_cli-0.34.2 → usage_cli-0.34.3}/updates/release_notes.py +0 -0
  243. {usage_cli-0.34.2 → usage_cli-0.34.3}/updates/whats_new.py +0 -0
  244. {usage_cli-0.34.2 → usage_cli-0.34.3}/usage_app/__init__.py +0 -0
  245. {usage_cli-0.34.2 → usage_cli-0.34.3}/usage_app/cli.py +0 -0
  246. {usage_cli-0.34.2 → usage_cli-0.34.3}/usage_app/doctor.py +0 -0
  247. {usage_cli-0.34.2 → usage_cli-0.34.3}/usage_cli.egg-info/dependency_links.txt +0 -0
  248. {usage_cli-0.34.2 → usage_cli-0.34.3}/usage_cli.egg-info/entry_points.txt +0 -0
  249. {usage_cli-0.34.2 → usage_cli-0.34.3}/usage_cli.egg-info/requires.txt +0 -0
  250. {usage_cli-0.34.2 → usage_cli-0.34.3}/usage_cli.egg-info/top_level.txt +0 -0
  251. {usage_cli-0.34.2 → usage_cli-0.34.3}/usage_common/__init__.py +0 -0
  252. {usage_cli-0.34.2 → usage_cli-0.34.3}/usage_common/app_version.py +0 -0
  253. {usage_cli-0.34.2 → usage_cli-0.34.3}/usage_common/i18n.py +0 -0
  254. {usage_cli-0.34.2 → usage_cli-0.34.3}/usage_common/prefs.py +0 -0
  255. {usage_cli-0.34.2 → usage_cli-0.34.3}/usage_common/pricing.py +0 -0
  256. {usage_cli-0.34.2 → usage_cli-0.34.3}/usage_common/project_resolver.py +0 -0
  257. {usage_cli-0.34.2 → usage_cli-0.34.3}/usage_common/service_status.py +0 -0
  258. {usage_cli-0.34.2 → usage_cli-0.34.3}/usage_common/subprocess_utils.py +0 -0
  259. {usage_cli-0.34.2 → usage_cli-0.34.3}/usage_common/time_utils.py +0 -0
  260. {usage_cli-0.34.2 → usage_cli-0.34.3}/usage_common/usage_dir_sweeper.py +0 -0
  261. {usage_cli-0.34.2 → usage_cli-0.34.3}/usage_common/usage_lang.py +0 -0
  262. {usage_cli-0.34.2 → usage_cli-0.34.3}/usage_common/usage_logging.py +0 -0
  263. {usage_cli-0.34.2 → usage_cli-0.34.3}/usage_hooks/__init__.py +0 -0
  264. {usage_cli-0.34.2 → usage_cli-0.34.3}/usage_hooks/usage_quota_aware.py +0 -0
  265. {usage_cli-0.34.2 → usage_cli-0.34.3}/usage_hooks/usage_session_resume.py +0 -0
  266. {usage_cli-0.34.2 → usage_cli-0.34.3}/usage_hooks/usage_statusline.py +0 -0
  267. {usage_cli-0.34.2 → usage_cli-0.34.3}/usage_hooks/usage_statusline_agy.py +0 -0
  268. {usage_cli-0.34.2 → usage_cli-0.34.3}/usage_hooks/usage_statusline_forwarder.py +0 -0
  269. {usage_cli-0.34.2 → usage_cli-0.34.3}/usage_hooks/usage_statusline_grok.py +0 -0
  270. {usage_cli-0.34.2 → usage_cli-0.34.3}/usage_hooks/usage_terse_mode.py +0 -0
  271. {usage_cli-0.34.2 → usage_cli-0.34.3}/usage_hooks/usage_terse_reminder.py +0 -0
  272. {usage_cli-0.34.2 → usage_cli-0.34.3}/wintray/__init__.py +0 -0
  273. {usage_cli-0.34.2 → usage_cli-0.34.3}/wintray/app.py +0 -0
  274. {usage_cli-0.34.2 → usage_cli-0.34.3}/wintray/login_item.py +0 -0
  275. {usage_cli-0.34.2 → usage_cli-0.34.3}/wintray/menu.py +0 -0
  276. {usage_cli-0.34.2 → usage_cli-0.34.3}/wintray/prefs.py +0 -0
  277. {usage_cli-0.34.2 → usage_cli-0.34.3}/wintray/quota_label.py +0 -0
  278. {usage_cli-0.34.2 → usage_cli-0.34.3}/wintray/taskbar_menu.py +0 -0
  279. {usage_cli-0.34.2 → usage_cli-0.34.3}/wintray/taskbar_overlay.py +0 -0
  280. {usage_cli-0.34.2 → usage_cli-0.34.3}/wintray/watch.py +0 -0
  281. {usage_cli-0.34.2 → usage_cli-0.34.3}/wintray/whats_new.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: usage-cli
3
- Version: 0.34.2
3
+ Version: 0.34.3
4
4
  Summary: usage — 在 macOS menu bar 與 Windows 系統匣顯示 Claude Code、Codex、Antigravity 用量的小工具(也提供終端機 TUI)
5
5
  License-Expression: AGPL-3.0-only
6
6
  Requires-Python: >=3.13
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "usage-cli"
3
- version = "0.34.2"
3
+ version = "0.34.3"
4
4
  description = "usage — 在 macOS menu bar 與 Windows 系統匣顯示 Claude Code、Codex、Antigravity 用量的小工具(也提供終端機 TUI)"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.13"
@@ -171,6 +171,8 @@ def _run_codex_ping(codex_bin: str) -> subprocess.CompletedProcess[str]:
171
171
  "-m",
172
172
  "gpt-5.6-luna",
173
173
  "--skip-git-repo-check",
174
+ # Keep the ping out of the user's `codex resume` list.
175
+ "--ephemeral",
174
176
  "-c",
175
177
  "features.hooks=false",
176
178
  "-c",
@@ -172,6 +172,12 @@ def _run_claude_ping(claude_bin: str) -> subprocess.CompletedProcess[str]:
172
172
  "haiku",
173
173
  "--settings",
174
174
  str(KEEPER_CLAUDE_SETTINGS_PATH),
175
+ # No tools or MCP servers keeps the ping small; no persistence keeps
176
+ # it out of the user's /resume list.
177
+ "--tools",
178
+ "",
179
+ "--strict-mcp-config",
180
+ "--no-session-persistence",
175
181
  ],
176
182
  stdin=subprocess.DEVNULL,
177
183
  capture_output=True,
@@ -635,6 +635,7 @@ def test_run_codex_ping_uses_verified_noninteractive_command(
635
635
  "-m",
636
636
  "gpt-5.6-luna",
637
637
  "--skip-git-repo-check",
638
+ "--ephemeral",
638
639
  "-c",
639
640
  "features.hooks=false",
640
641
  "-c",
@@ -0,0 +1,118 @@
1
+ # SPDX-License-Identifier: AGPL-3.0-only
2
+ # Copyright (C) 2026 lollapalooza <https://github.com/aqua5230>
3
+
4
+ from __future__ import annotations
5
+
6
+ import ctypes as C
7
+ import importlib
8
+ from collections.abc import Iterator
9
+ from types import SimpleNamespace
10
+ from typing import Any
11
+ from unittest.mock import Mock
12
+
13
+ import pytest
14
+
15
+ from wintray import taskbar_obstacles as obstacles
16
+
17
+
18
+ @pytest.fixture(autouse=True)
19
+ def clear_wts_api_cache() -> Iterator[None]:
20
+ obstacles._wts_api.cache_clear()
21
+ yield
22
+ obstacles._wts_api.cache_clear()
23
+
24
+
25
+ def test_session_flags_offset() -> None:
26
+ assert (
27
+ obstacles._WTSINFOEXW.Data.offset + obstacles._WTSINFOEX_LEVEL1_W.SessionFlags.offset == 16
28
+ )
29
+ assert C.sizeof(obstacles._WTSINFOEXW) == 232
30
+
31
+
32
+ @pytest.mark.parametrize("flags, locked", [(0, True), (1, False), (-1, False)])
33
+ def test_session_locked_reads_buffer(
34
+ monkeypatch: pytest.MonkeyPatch, flags: int, locked: bool
35
+ ) -> None:
36
+ info = obstacles._WTSINFOEXW(Level=1)
37
+ info.Data.WTSInfoExLevel1.SessionFlags = flags
38
+
39
+ def query(server: object, session: int, kind: int, buffer: Any, size: Any) -> int:
40
+ assert (server, session, kind) == (None, 0xFFFFFFFF, 25)
41
+ C.cast(buffer, C.POINTER(C.c_void_p))[0] = C.addressof(info)
42
+ C.cast(size, C.POINTER(C.c_uint32))[0] = C.sizeof(info)
43
+ return 1
44
+
45
+ wts = SimpleNamespace(WTSQuerySessionInformationW=Mock(side_effect=query), WTSFreeMemory=Mock())
46
+ load = Mock(return_value=wts)
47
+ monkeypatch.setattr(C, "WinDLL", load, raising=False)
48
+
49
+ assert obstacles._session_locked() is locked
50
+ load.assert_called_once_with("wtsapi32", use_last_error=True)
51
+ assert wts.WTSQuerySessionInformationW.restype is C.c_int
52
+ assert len(wts.WTSQuerySessionInformationW.argtypes) == 5
53
+ wts.WTSFreeMemory.assert_called_once()
54
+ assert wts.WTSFreeMemory.call_args.args[0].value == C.addressof(info)
55
+
56
+
57
+ def test_session_locked_api_failure(monkeypatch: pytest.MonkeyPatch) -> None:
58
+ wts = SimpleNamespace(WTSQuerySessionInformationW=Mock(return_value=0), WTSFreeMemory=Mock())
59
+ monkeypatch.setattr(C, "WinDLL", Mock(return_value=wts), raising=False)
60
+ assert obstacles._session_locked() is False
61
+ wts.WTSFreeMemory.assert_not_called()
62
+
63
+
64
+ @pytest.mark.parametrize("error", [OSError("unavailable"), AttributeError("WinDLL")])
65
+ def test_session_locked_unavailable(monkeypatch: pytest.MonkeyPatch, error: Exception) -> None:
66
+ monkeypatch.setattr(C, "WinDLL", Mock(side_effect=error), raising=False)
67
+ assert obstacles._session_locked() is False
68
+
69
+
70
+ def test_watch_preserves_snapshot_while_locked_then_refreshes(
71
+ monkeypatch: pytest.MonkeyPatch,
72
+ ) -> None:
73
+ bounds = SimpleNamespace(Left=1.2, Top=2.3, Right=30.4, Bottom=40.5, IsEmpty=False)
74
+ button = SimpleNamespace(Current=SimpleNamespace(BoundingRectangle=bounds, IsOffscreen=False))
75
+ find_all = Mock(return_value=[button])
76
+ element = SimpleNamespace(
77
+ ControlTypeProperty="control",
78
+ FromHandle=Mock(return_value=SimpleNamespace(FindAll=find_all)),
79
+ )
80
+ modules = {
81
+ "clr": SimpleNamespace(AddReference=Mock()),
82
+ "System.Runtime.InteropServices": SimpleNamespace(
83
+ RuntimeEnvironment=SimpleNamespace(GetRuntimeDirectory=lambda: "/framework")
84
+ ),
85
+ "System.Windows.Automation": SimpleNamespace(
86
+ AutomationElement=element,
87
+ OrCondition=Mock(),
88
+ PropertyCondition=Mock(),
89
+ ControlType=SimpleNamespace(Button="button", ListItem="item"),
90
+ TreeScope=SimpleNamespace(Descendants="descendants"),
91
+ ),
92
+ "System": SimpleNamespace(IntPtr=lambda hwnd: hwnd),
93
+ }
94
+ monkeypatch.setattr(importlib, "import_module", lambda name: modules[name])
95
+ monkeypatch.setattr(obstacles, "_session_locked", Mock(side_effect=[True, False]))
96
+ worker = obstacles.TaskbarObstacles.__new__(obstacles.TaskbarObstacles)
97
+ worker.hwnd = 123
98
+ worker.snapshot = (123, ((5, 6, 7, 8),))
99
+ stop = Mock()
100
+ stop.is_set.side_effect = [False, False, True]
101
+ worker._stop = stop
102
+
103
+ def wait(seconds: int) -> None:
104
+ assert seconds == 2
105
+ if stop.wait.call_count == 1:
106
+ find_all.assert_not_called()
107
+ element.FromHandle.assert_not_called()
108
+ assert worker.snapshot == (123, ((5, 6, 7, 8),))
109
+ else:
110
+ find_all.assert_called_once_with(
111
+ "descendants", modules["System.Windows.Automation"].OrCondition.return_value
112
+ )
113
+ assert worker.snapshot == (123, ((1, 2, 30, 40),))
114
+
115
+ stop.wait.side_effect = wait
116
+ worker._watch()
117
+ assert stop.wait.call_count == 2
118
+ assert worker.snapshot == (123, ((1, 2, 30, 40),))
@@ -38,6 +38,10 @@ def test_run_claude_ping_skips_user_hooks(monkeypatch: pytest.MonkeyPatch, tmp_p
38
38
  "haiku",
39
39
  "--settings",
40
40
  str(settings_path),
41
+ "--tools",
42
+ "",
43
+ "--strict-mcp-config",
44
+ "--no-session-persistence",
41
45
  ]
42
46
  assert settings_path.is_file()
43
47
  assert json.loads(settings_path.read_text(encoding="utf-8")) == {"disableAllHooks": True}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: usage-cli
3
- Version: 0.34.2
3
+ Version: 0.34.3
4
4
  Summary: usage — 在 macOS menu bar 與 Windows 系統匣顯示 Claude Code、Codex、Antigravity 用量的小工具(也提供終端機 TUI)
5
5
  License-Expression: AGPL-3.0-only
6
6
  Requires-Python: >=3.13
@@ -188,6 +188,7 @@ tests/test_setup_hook_terse.py
188
188
  tests/test_subprocess_utils.py
189
189
  tests/test_subscription.py
190
190
  tests/test_taskbar_menu.py
191
+ tests/test_taskbar_obstacles.py
191
192
  tests/test_time_utils.py
192
193
  tests/test_tui.py
193
194
  tests/test_tui_sprite.py
@@ -5,9 +5,11 @@
5
5
 
6
6
  from __future__ import annotations
7
7
 
8
+ import ctypes as C
8
9
  import importlib
9
10
  import logging
10
11
  import threading
12
+ from functools import cache
11
13
  from pathlib import Path
12
14
 
13
15
  from wintray.taskbar_overlay import Rect
@@ -15,6 +17,76 @@ from wintray.taskbar_overlay import Rect
15
17
  logger = logging.getLogger(__name__)
16
18
 
17
19
 
20
+ class _WTSINFOEX_LEVEL1_W(C.Structure):
21
+ # Windows WCHAR and LONG stay 16/32 bits even on hosts with wider C types.
22
+ _fields_ = [
23
+ ("SessionId", C.c_uint32),
24
+ ("SessionState", C.c_int32),
25
+ ("SessionFlags", C.c_int32),
26
+ ("WinStationName", C.c_uint16 * 33),
27
+ ("UserName", C.c_uint16 * 21),
28
+ ("DomainName", C.c_uint16 * 18),
29
+ ("LogonTime", C.c_int64),
30
+ ("ConnectTime", C.c_int64),
31
+ ("DisconnectTime", C.c_int64),
32
+ ("LastInputTime", C.c_int64),
33
+ ("CurrentTime", C.c_int64),
34
+ ("IncomingBytes", C.c_uint32),
35
+ ("OutgoingBytes", C.c_uint32),
36
+ ("IncomingFrames", C.c_uint32),
37
+ ("OutgoingFrames", C.c_uint32),
38
+ ("IncomingCompressedBytes", C.c_uint32),
39
+ ("OutgoingCompressedBytes", C.c_uint32),
40
+ ]
41
+
42
+
43
+ class _WTSINFOEX_LEVEL_W(C.Union):
44
+ _fields_ = [("WTSInfoExLevel1", _WTSINFOEX_LEVEL1_W)]
45
+
46
+
47
+ class _WTSINFOEXW(C.Structure):
48
+ _fields_ = [("Level", C.c_uint32), ("Data", _WTSINFOEX_LEVEL_W)]
49
+
50
+
51
+ @cache
52
+ def _wts_api() -> C.CDLL:
53
+ # WinDLL is absent from ctypes and its stubs on non-Windows hosts.
54
+ loader = getattr(C, "WinDLL") # noqa: B009
55
+ wts: C.CDLL = loader("wtsapi32", use_last_error=True)
56
+ wts.WTSQuerySessionInformationW.argtypes = [
57
+ C.c_void_p,
58
+ C.c_uint32,
59
+ C.c_int,
60
+ C.POINTER(C.c_void_p),
61
+ C.POINTER(C.c_uint32),
62
+ ]
63
+ wts.WTSQuerySessionInformationW.restype = C.c_int
64
+ wts.WTSFreeMemory.argtypes = [C.c_void_p]
65
+ wts.WTSFreeMemory.restype = None
66
+ return wts
67
+
68
+
69
+ def _session_locked() -> bool:
70
+ try:
71
+ wts = _wts_api()
72
+ buffer = C.c_void_p()
73
+ size = C.c_uint32()
74
+ try:
75
+ if not wts.WTSQuerySessionInformationW(
76
+ None, 0xFFFFFFFF, 25, C.byref(buffer), C.byref(size)
77
+ ):
78
+ return False
79
+ if not buffer or size.value < C.sizeof(_WTSINFOEXW):
80
+ return False
81
+ info = C.cast(buffer, C.POINTER(_WTSINFOEXW)).contents
82
+ return bool(info.Level == 1 and info.Data.WTSInfoExLevel1.SessionFlags == 0)
83
+ finally:
84
+ if buffer:
85
+ wts.WTSFreeMemory(buffer)
86
+ except (OSError, AttributeError):
87
+ return False
88
+
89
+
18
90
  class TaskbarObstacles:
19
91
  def __init__(self) -> None:
20
92
  self.hwnd = 0
@@ -42,7 +114,7 @@ class TaskbarObstacles:
42
114
  )
43
115
  while not self._stop.is_set():
44
116
  hwnd = self.hwnd
45
- if hwnd:
117
+ if hwnd and not _session_locked():
46
118
  try:
47
119
  root = element.FromHandle(system.IntPtr(hwnd))
48
120
  buttons = root.FindAll(automation.TreeScope.Descendants, condition)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes