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.
Files changed (225) hide show
  1. {usage_cli-0.31.5 → usage_cli-0.31.6}/PKG-INFO +1 -1
  2. {usage_cli-0.31.5 → usage_cli-0.31.6}/pyproject.toml +1 -1
  3. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_usage_statusline_grok.py +13 -4
  4. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_wintray.py +31 -1
  5. {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_cli.egg-info/PKG-INFO +1 -1
  6. {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_statusline_grok.py +8 -2
  7. {usage_cli-0.31.5 → usage_cli-0.31.6}/wintray/app.py +13 -3
  8. {usage_cli-0.31.5 → usage_cli-0.31.6}/LICENSE +0 -0
  9. {usage_cli-0.31.5 → usage_cli-0.31.6}/README.md +0 -0
  10. {usage_cli-0.31.5 → usage_cli-0.31.6}/adapters/__init__.py +0 -0
  11. {usage_cli-0.31.5 → usage_cli-0.31.6}/adapters/agy.py +0 -0
  12. {usage_cli-0.31.5 → usage_cli-0.31.6}/adapters/claude.py +0 -0
  13. {usage_cli-0.31.5 → usage_cli-0.31.6}/adapters/codex.py +0 -0
  14. {usage_cli-0.31.5 → usage_cli-0.31.6}/adapters/grok.py +0 -0
  15. {usage_cli-0.31.5 → usage_cli-0.31.6}/adapters/muse.py +0 -0
  16. {usage_cli-0.31.5 → usage_cli-0.31.6}/adapters/rate_limits.py +0 -0
  17. {usage_cli-0.31.5 → usage_cli-0.31.6}/adapters/registry.py +0 -0
  18. {usage_cli-0.31.5 → usage_cli-0.31.6}/adapters/types.py +0 -0
  19. {usage_cli-0.31.5 → usage_cli-0.31.6}/analyzer/__init__.py +0 -0
  20. {usage_cli-0.31.5 → usage_cli-0.31.6}/analyzer/aggregator.py +0 -0
  21. {usage_cli-0.31.5 → usage_cli-0.31.6}/analyzer/blocks.py +0 -0
  22. {usage_cli-0.31.5 → usage_cli-0.31.6}/analyzer/diagnoser.py +0 -0
  23. {usage_cli-0.31.5 → usage_cli-0.31.6}/analyzer/dispatch_ledger.py +0 -0
  24. {usage_cli-0.31.5 → usage_cli-0.31.6}/analyzer/insights.py +0 -0
  25. {usage_cli-0.31.5 → usage_cli-0.31.6}/analyzer/persona_loader.py +0 -0
  26. {usage_cli-0.31.5 → usage_cli-0.31.6}/analyzer/reporter.py +0 -0
  27. {usage_cli-0.31.5 → usage_cli-0.31.6}/analyzer/subscription.py +0 -0
  28. {usage_cli-0.31.5 → usage_cli-0.31.6}/analyzer/usage_snapshot.py +0 -0
  29. {usage_cli-0.31.5 → usage_cli-0.31.6}/doctor.py +0 -0
  30. {usage_cli-0.31.5 → usage_cli-0.31.6}/fsevents_watch.py +0 -0
  31. {usage_cli-0.31.5 → usage_cli-0.31.6}/i18n.json +0 -0
  32. {usage_cli-0.31.5 → usage_cli-0.31.6}/i18n.py +0 -0
  33. {usage_cli-0.31.5 → usage_cli-0.31.6}/installer/__init__.py +0 -0
  34. {usage_cli-0.31.5 → usage_cli-0.31.6}/installer/login_item.py +0 -0
  35. {usage_cli-0.31.5 → usage_cli-0.31.6}/installer/session_hooks.py +0 -0
  36. {usage_cli-0.31.5 → usage_cli-0.31.6}/installer/setup_hook.py +0 -0
  37. {usage_cli-0.31.5 → usage_cli-0.31.6}/installer/statusline_settings.py +0 -0
  38. {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/__init__.py +0 -0
  39. {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/agy_disk_cache.py +0 -0
  40. {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/agy_loader.py +0 -0
  41. {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/agy_quota_probe.py +0 -0
  42. {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/cache_quarantine.py +0 -0
  43. {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/claude_paths.py +0 -0
  44. {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/codex_disk_cache.py +0 -0
  45. {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/codex_events.py +0 -0
  46. {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/codex_fork_replay.py +0 -0
  47. {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/codex_loader.py +0 -0
  48. {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/codex_paths.py +0 -0
  49. {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/disk_cache_common.py +0 -0
  50. {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/disk_cache_lifecycle.py +0 -0
  51. {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/grok_loader.py +0 -0
  52. {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/grok_quota_probe.py +0 -0
  53. {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/history_disk_cache.py +0 -0
  54. {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/history_loader.py +0 -0
  55. {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/jsonl_limits.py +0 -0
  56. {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/jsonl_utils.py +0 -0
  57. {usage_cli-0.31.5 → usage_cli-0.31.6}/loaders/muse_loader.py +0 -0
  58. {usage_cli-0.31.5 → usage_cli-0.31.6}/main.py +0 -0
  59. {usage_cli-0.31.5 → usage_cli-0.31.6}/menubar/__init__.py +0 -0
  60. {usage_cli-0.31.5 → usage_cli-0.31.6}/menubar/actions.py +0 -0
  61. {usage_cli-0.31.5 → usage_cli-0.31.6}/menubar/agy.py +0 -0
  62. {usage_cli-0.31.5 → usage_cli-0.31.6}/menubar/app.py +0 -0
  63. {usage_cli-0.31.5 → usage_cli-0.31.6}/menubar/chrome.py +0 -0
  64. {usage_cli-0.31.5 → usage_cli-0.31.6}/menubar/grok.py +0 -0
  65. {usage_cli-0.31.5 → usage_cli-0.31.6}/menubar/menu.py +0 -0
  66. {usage_cli-0.31.5 → usage_cli-0.31.6}/menubar/notify.py +0 -0
  67. {usage_cli-0.31.5 → usage_cli-0.31.6}/menubar/popover.py +0 -0
  68. {usage_cli-0.31.5 → usage_cli-0.31.6}/menubar/prefs.py +0 -0
  69. {usage_cli-0.31.5 → usage_cli-0.31.6}/menubar/refresh.py +0 -0
  70. {usage_cli-0.31.5 → usage_cli-0.31.6}/menubar/state.py +0 -0
  71. {usage_cli-0.31.5 → usage_cli-0.31.6}/menubar/title.py +0 -0
  72. {usage_cli-0.31.5 → usage_cli-0.31.6}/menubar/update.py +0 -0
  73. {usage_cli-0.31.5 → usage_cli-0.31.6}/panels/__init__.py +0 -0
  74. {usage_cli-0.31.5 → usage_cli-0.31.6}/panels/base.py +0 -0
  75. {usage_cli-0.31.5 → usage_cli-0.31.6}/panels/dynamic_height.py +0 -0
  76. {usage_cli-0.31.5 → usage_cli-0.31.6}/panels/panel_scale.py +0 -0
  77. {usage_cli-0.31.5 → usage_cli-0.31.6}/panels/panel_window.py +0 -0
  78. {usage_cli-0.31.5 → usage_cli-0.31.6}/panels/panel_window_state.py +0 -0
  79. {usage_cli-0.31.5 → usage_cli-0.31.6}/panels/payload.py +0 -0
  80. {usage_cli-0.31.5 → usage_cli-0.31.6}/panels/web_panel.py +0 -0
  81. {usage_cli-0.31.5 → usage_cli-0.31.6}/panels/window_drag.py +0 -0
  82. {usage_cli-0.31.5 → usage_cli-0.31.6}/prefs.py +0 -0
  83. {usage_cli-0.31.5 → usage_cli-0.31.6}/pricing.py +0 -0
  84. {usage_cli-0.31.5 → usage_cli-0.31.6}/project_resolver.py +0 -0
  85. {usage_cli-0.31.5 → usage_cli-0.31.6}/quota/__init__.py +0 -0
  86. {usage_cli-0.31.5 → usage_cli-0.31.6}/quota/agy_window_keeper.py +0 -0
  87. {usage_cli-0.31.5 → usage_cli-0.31.6}/quota/burn_rate.py +0 -0
  88. {usage_cli-0.31.5 → usage_cli-0.31.6}/quota/codex_window_keeper.py +0 -0
  89. {usage_cli-0.31.5 → usage_cli-0.31.6}/quota/usage_rate.py +0 -0
  90. {usage_cli-0.31.5 → usage_cli-0.31.6}/quota/window_keeper.py +0 -0
  91. {usage_cli-0.31.5 → usage_cli-0.31.6}/service_status.py +0 -0
  92. {usage_cli-0.31.5 → usage_cli-0.31.6}/setup.cfg +0 -0
  93. {usage_cli-0.31.5 → usage_cli-0.31.6}/setup_app.py +0 -0
  94. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_adapters_claude.py +0 -0
  95. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_adapters_codex.py +0 -0
  96. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_adapters_rate_limits.py +0 -0
  97. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_aggregator.py +0 -0
  98. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_agy_adapter.py +0 -0
  99. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_agy_disk_cache.py +0 -0
  100. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_agy_loader.py +0 -0
  101. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_agy_quota_probe.py +0 -0
  102. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_agy_window_keeper.py +0 -0
  103. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_analyzer_blocks.py +0 -0
  104. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_analyzer_pipeline.py +0 -0
  105. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_burn_rate.py +0 -0
  106. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_cache_quarantine.py +0 -0
  107. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_claude_paths.py +0 -0
  108. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_codex_consistency.py +0 -0
  109. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_codex_loader.py +0 -0
  110. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_codex_window_keeper.py +0 -0
  111. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_diagnoser.py +0 -0
  112. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_disk_cache_shards.py +0 -0
  113. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_dispatch_ledger.py +0 -0
  114. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_doctor.py +0 -0
  115. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_dynamic_height.py +0 -0
  116. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_fsevents_watch.py +0 -0
  117. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_grok_loader.py +0 -0
  118. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_grok_quota_probe.py +0 -0
  119. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_history_loader.py +0 -0
  120. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_hook_scripts_are_standalone.py +0 -0
  121. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_html_report_snapshot.py +0 -0
  122. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_i18n_format_fallback.py +0 -0
  123. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_i18n_key_parity.py +0 -0
  124. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_i18n_packaged_path.py +0 -0
  125. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_insights.py +0 -0
  126. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_jsonl_utils.py +0 -0
  127. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_login_item.py +0 -0
  128. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_main.py +0 -0
  129. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_menubar.py +0 -0
  130. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_menubar_agy.py +0 -0
  131. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_menubar_grok.py +0 -0
  132. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_menubar_notify.py +0 -0
  133. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_menubar_prefs.py +0 -0
  134. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_menubar_state.py +0 -0
  135. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_muse_loader.py +0 -0
  136. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_packaged_resources.py +0 -0
  137. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_packaging.py +0 -0
  138. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_panel_footer_layout.py +0 -0
  139. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_panel_scale.py +0 -0
  140. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_panel_window_state.py +0 -0
  141. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_panels.py +0 -0
  142. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_panels_lazy_import.py +0 -0
  143. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_persona_loader.py +0 -0
  144. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_pricing.py +0 -0
  145. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_project_resolver.py +0 -0
  146. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_report_daily_chart.py +0 -0
  147. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_report_filter_js.py +0 -0
  148. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_reporter_build_data.py +0 -0
  149. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_service_status.py +0 -0
  150. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_session_resume.py +0 -0
  151. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_setup_app.py +0 -0
  152. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_setup_hook.py +0 -0
  153. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_setup_hook_coexistence.py +0 -0
  154. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_setup_hook_resume.py +0 -0
  155. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_setup_hook_terse.py +0 -0
  156. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_subprocess_utils.py +0 -0
  157. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_subscription.py +0 -0
  158. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_time_utils.py +0 -0
  159. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_tui.py +0 -0
  160. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_tui_sprite.py +0 -0
  161. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_ui_tables.py +0 -0
  162. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_update_checker.py +0 -0
  163. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_update_gate.py +0 -0
  164. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_update_release_notes.py +0 -0
  165. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_usage_cli.py +0 -0
  166. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_usage_client.py +0 -0
  167. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_usage_diagnosis_snapshot.py +0 -0
  168. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_usage_dir_sweeper.py +0 -0
  169. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_usage_lang.py +0 -0
  170. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_usage_logging.py +0 -0
  171. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_usage_notifications.py +0 -0
  172. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_usage_rate.py +0 -0
  173. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_usage_snapshot.py +0 -0
  174. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_usage_snapshot_replay.py +0 -0
  175. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_usage_statusline.py +0 -0
  176. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_usage_statusline_agy.py +0 -0
  177. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_usage_statusline_forwarder.py +0 -0
  178. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_usage_terse_mode.py +0 -0
  179. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_usage_terse_reminder.py +0 -0
  180. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_web_panel_payload.py +0 -0
  181. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_wheel_packaging.py +0 -0
  182. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_win_login_item.py +0 -0
  183. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_window_keeper.py +0 -0
  184. {usage_cli-0.31.5 → usage_cli-0.31.6}/tests/test_windows_manifest.py +0 -0
  185. {usage_cli-0.31.5 → usage_cli-0.31.6}/tui/__init__.py +0 -0
  186. {usage_cli-0.31.5 → usage_cli-0.31.6}/tui/app.py +0 -0
  187. {usage_cli-0.31.5 → usage_cli-0.31.6}/tui/sprite.py +0 -0
  188. {usage_cli-0.31.5 → usage_cli-0.31.6}/ui/__init__.py +0 -0
  189. {usage_cli-0.31.5 → usage_cli-0.31.6}/ui/html_report.py +0 -0
  190. {usage_cli-0.31.5 → usage_cli-0.31.6}/ui/report_charts.py +0 -0
  191. {usage_cli-0.31.5 → usage_cli-0.31.6}/ui/report_daily_chart.py +0 -0
  192. {usage_cli-0.31.5 → usage_cli-0.31.6}/ui/report_filter.py +0 -0
  193. {usage_cli-0.31.5 → usage_cli-0.31.6}/ui/report_ledger.py +0 -0
  194. {usage_cli-0.31.5 → usage_cli-0.31.6}/ui/report_scripts.py +0 -0
  195. {usage_cli-0.31.5 → usage_cli-0.31.6}/ui/report_styles.py +0 -0
  196. {usage_cli-0.31.5 → usage_cli-0.31.6}/ui/tables.py +0 -0
  197. {usage_cli-0.31.5 → usage_cli-0.31.6}/updates/__init__.py +0 -0
  198. {usage_cli-0.31.5 → usage_cli-0.31.6}/updates/checker.py +0 -0
  199. {usage_cli-0.31.5 → usage_cli-0.31.6}/updates/gate.py +0 -0
  200. {usage_cli-0.31.5 → usage_cli-0.31.6}/updates/release_notes.py +0 -0
  201. {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_cli.egg-info/SOURCES.txt +0 -0
  202. {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_cli.egg-info/dependency_links.txt +0 -0
  203. {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_cli.egg-info/entry_points.txt +0 -0
  204. {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_cli.egg-info/requires.txt +0 -0
  205. {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_cli.egg-info/top_level.txt +0 -0
  206. {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_cli.py +0 -0
  207. {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_client.py +0 -0
  208. {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_common/__init__.py +0 -0
  209. {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_common/subprocess_utils.py +0 -0
  210. {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_common/time_utils.py +0 -0
  211. {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_common/usage_dir_sweeper.py +0 -0
  212. {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_common/usage_lang.py +0 -0
  213. {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_common/usage_logging.py +0 -0
  214. {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_diagnosis_snapshot.py +0 -0
  215. {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_notifications.py +0 -0
  216. {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_session_resume.py +0 -0
  217. {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_statusline.py +0 -0
  218. {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_statusline_agy.py +0 -0
  219. {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_statusline_forwarder.py +0 -0
  220. {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_terse_mode.py +0 -0
  221. {usage_cli-0.31.5 → usage_cli-0.31.6}/usage_terse_reminder.py +0 -0
  222. {usage_cli-0.31.5 → usage_cli-0.31.6}/wintray/__init__.py +0 -0
  223. {usage_cli-0.31.5 → usage_cli-0.31.6}/wintray/login_item.py +0 -0
  224. {usage_cli-0.31.5 → usage_cli-0.31.6}/wintray/menu.py +0 -0
  225. {usage_cli-0.31.5 → usage_cli-0.31.6}/wintray/watch.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: usage-cli
3
- Version: 0.31.5
3
+ Version: 0.31.6
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.31.5"
3
+ version = "0.31.6"
4
4
  description = "usage — 在 macOS menu bar 與 Windows 系統匣顯示 Claude Code、Codex、Antigravity 用量的小工具(也提供終端機 TUI)"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.13"
@@ -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 "週配額:■■■□□□□□ 42%" in output
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 "對話窗:■□□□□□□□ 8% / 2.0M" in output
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
- assert "■" not in first_line
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 "週配額:□□□□□□□□ 0%" in output
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" if isinstance(entry, wintray_menu.MenuSeparator) else _t("en", entry.i18n_key)
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
  [
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: usage-cli
3
- Version: 0.31.5
3
+ Version: 0.31.6
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
@@ -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)}{'■' * filled}{C['reset']}"
183
- f"{'□' * (bar_width - filled)} "
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(_t(controller.language, entry.i18n_key), pystray.Menu(*children))
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(_t(controller.language, entry.i18n_key), action, **kwargs)
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