token-tracker 0.3.2__tar.gz → 0.3.4__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 (25) hide show
  1. {token_tracker-0.3.2 → token_tracker-0.3.4}/PKG-INFO +1 -1
  2. {token_tracker-0.3.2 → token_tracker-0.3.4}/pyproject.toml +1 -1
  3. {token_tracker-0.3.2 → token_tracker-0.3.4}/src/cli.py +42 -4
  4. {token_tracker-0.3.2 → token_tracker-0.3.4}/src/hooks.py +24 -11
  5. {token_tracker-0.3.2 → token_tracker-0.3.4}/token_tracker.egg-info/PKG-INFO +1 -1
  6. {token_tracker-0.3.2 → token_tracker-0.3.4}/README.md +0 -0
  7. {token_tracker-0.3.2 → token_tracker-0.3.4}/setup.cfg +0 -0
  8. {token_tracker-0.3.2 → token_tracker-0.3.4}/src/__init__.py +0 -0
  9. {token_tracker-0.3.2 → token_tracker-0.3.4}/src/adapters/__init__.py +0 -0
  10. {token_tracker-0.3.2 → token_tracker-0.3.4}/src/adapters/claude.py +0 -0
  11. {token_tracker-0.3.2 → token_tracker-0.3.4}/src/adapters/codex.py +0 -0
  12. {token_tracker-0.3.2 → token_tracker-0.3.4}/src/adapters/rate_limits.py +0 -0
  13. {token_tracker-0.3.2 → token_tracker-0.3.4}/src/adapters/registry.py +0 -0
  14. {token_tracker-0.3.2 → token_tracker-0.3.4}/src/adapters/types.py +0 -0
  15. {token_tracker-0.3.2 → token_tracker-0.3.4}/src/analyzer/__init__.py +0 -0
  16. {token_tracker-0.3.2 → token_tracker-0.3.4}/src/analyzer/aggregator.py +0 -0
  17. {token_tracker-0.3.2 → token_tracker-0.3.4}/src/analyzer/blocks.py +0 -0
  18. {token_tracker-0.3.2 → token_tracker-0.3.4}/src/analyzer/cost.py +0 -0
  19. {token_tracker-0.3.2 → token_tracker-0.3.4}/src/ui/__init__.py +0 -0
  20. {token_tracker-0.3.2 → token_tracker-0.3.4}/src/ui/tables.py +0 -0
  21. {token_tracker-0.3.2 → token_tracker-0.3.4}/token_tracker.egg-info/SOURCES.txt +0 -0
  22. {token_tracker-0.3.2 → token_tracker-0.3.4}/token_tracker.egg-info/dependency_links.txt +0 -0
  23. {token_tracker-0.3.2 → token_tracker-0.3.4}/token_tracker.egg-info/entry_points.txt +0 -0
  24. {token_tracker-0.3.2 → token_tracker-0.3.4}/token_tracker.egg-info/requires.txt +0 -0
  25. {token_tracker-0.3.2 → token_tracker-0.3.4}/token_tracker.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: token-tracker
3
- Version: 0.3.2
3
+ Version: 0.3.4
4
4
  Summary: Track token usage across local AI agents (Claude Code, Codex)
5
5
  Requires-Python: >=3.11
6
6
  Requires-Dist: rich>=13.7
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "token-tracker"
7
- version = "0.3.2"
7
+ version = "0.3.4"
8
8
  description = "Track token usage across local AI agents (Claude Code, Codex)"
9
9
  requires-python = ">=3.11"
10
10
  dependencies = [
@@ -92,8 +92,6 @@ def _fit_screen(text: str, height: int, scroll_offset: int) -> tuple[str, int]:
92
92
 
93
93
 
94
94
  def _show_interactive_dashboard(agents):
95
- import tty
96
- import termios
97
95
  import shutil
98
96
  from io import StringIO
99
97
  from rich.console import Console as RichConsole
@@ -135,7 +133,7 @@ def _show_interactive_dashboard(agents):
135
133
  sys.stdout.write("\033[2J\033[3J\033[H" + screen)
136
134
  sys.stdout.flush()
137
135
 
138
- key = _read_key(tty, termios)
136
+ key = _read_key()
139
137
  if key == "left":
140
138
  current = (current - 1) % len(agents)
141
139
  scroll_offset = 0
@@ -158,9 +156,11 @@ def _show_interactive_dashboard(agents):
158
156
  _tables.console = orig
159
157
 
160
158
 
161
- def _read_key(tty, termios):
159
+ def _read_key_unix():
162
160
  import os as _os
163
161
  import select
162
+ import tty
163
+ import termios
164
164
  fd = sys.stdin.fileno()
165
165
  old = termios.tcgetattr(fd)
166
166
  try:
@@ -204,6 +204,44 @@ def _read_key(tty, termios):
204
204
  termios.tcsetattr(fd, termios.TCSADRAIN, old)
205
205
 
206
206
 
207
+ def _read_key_win():
208
+ import msvcrt
209
+ ch = msvcrt.getch()
210
+ if ch in (b"\xe0", b"\x00"):
211
+ ch2 = msvcrt.getch()
212
+ if ch2 == b"K":
213
+ return "left"
214
+ if ch2 == b"M":
215
+ return "right"
216
+ if ch2 == b"H":
217
+ return "up"
218
+ if ch2 == b"P":
219
+ return "down"
220
+ if ch2 == b"I":
221
+ return "page_up"
222
+ if ch2 == b"Q":
223
+ return "page_down"
224
+ return "other"
225
+ if ch == b"h":
226
+ return "left"
227
+ if ch == b"l":
228
+ return "right"
229
+ if ch == b"k":
230
+ return "up"
231
+ if ch == b"j":
232
+ return "down"
233
+ if ch == b"b":
234
+ return "page_up"
235
+ if ch == b"f":
236
+ return "page_down"
237
+ if ch in (b"q", b"Q", b"\x03", b"\x1b"):
238
+ return "quit"
239
+ return "other"
240
+
241
+
242
+ _read_key = _read_key_win if sys.platform == "win32" else _read_key_unix
243
+
244
+
207
245
  def _get_version() -> str:
208
246
  from importlib.metadata import version
209
247
  return version("token-tracker")
@@ -2,6 +2,7 @@ import json
2
2
  import os
3
3
  import re
4
4
  import stat
5
+ import sys
5
6
  import tomllib
6
7
 
7
8
  from .ui.tables import console
@@ -10,7 +11,7 @@ CLAUDE_SETTINGS = os.path.expanduser("~/.claude/settings.json")
10
11
  HOOK_SCRIPT_PATH = os.path.expanduser("~/.claude/tt-statusline.py")
11
12
  CODEX_CONFIG = os.path.expanduser("~/.codex/config.toml")
12
13
  CODEX_BACKUP = os.path.expanduser("~/.codex/tt-backup.json")
13
- HOOK_VERSION = "1.4"
14
+ HOOK_VERSION = "1.5"
14
15
  _BACKUP_KEY = "tokenTracker"
15
16
  _PREV_SL_KEY = "previousStatusLine"
16
17
  _SL_REGEX = re.compile(r'status_line\s*=\s*\[.*?\]', re.DOTALL)
@@ -25,7 +26,7 @@ CODEX_STATUS_LINE = [
25
26
 
26
27
  HOOK_SCRIPT = r'''#!/usr/bin/env python3
27
28
  """Claude Code statusLine — 状态栏显示 + 数据持久化到 tt-status.json"""
28
- __version__ = "1.4"
29
+ __version__ = "1.5"
29
30
  import json, os, re, subprocess, sys, tempfile
30
31
  from datetime import datetime, timezone
31
32
 
@@ -37,6 +38,9 @@ C = {
37
38
  "peach": "\033[38;5;216m", "dim": "\033[2m", "reset": "\033[0m",
38
39
  }
39
40
 
41
+ if sys.platform == "win32":
42
+ sys.stdout.reconfigure(encoding="utf-8", errors="replace")
43
+
40
44
 
41
45
  def vlen(s):
42
46
  return len(ANSI_RE.sub("", s))
@@ -47,13 +51,15 @@ def get_width():
47
51
  return max(1, os.get_terminal_size(2).columns - 4)
48
52
  except Exception:
49
53
  pass
50
- import fcntl, struct, termios
51
- try:
52
- with open('/dev/tty', 'r') as tty:
53
- res = fcntl.ioctl(tty, termios.TIOCGWINSZ, b'\x00' * 8)
54
- return max(1, struct.unpack('hh', res[:4])[1] - 4)
55
- except Exception:
56
- return 116
54
+ if os.name != "nt":
55
+ try:
56
+ import fcntl, struct, termios
57
+ with open('/dev/tty', 'r') as tty:
58
+ res = fcntl.ioctl(tty, termios.TIOCGWINSZ, b'\x00' * 8)
59
+ return max(1, struct.unpack('hh', res[:4])[1] - 4)
60
+ except Exception:
61
+ pass
62
+ return 116
57
63
 
58
64
 
59
65
  def color_by_pct(pct):
@@ -237,6 +243,7 @@ def render(data, now):
237
243
  output = [" | ".join(line) for line in (line1, line2, line3) if line]
238
244
  if output:
239
245
  print("\n".join(output))
246
+ sys.stdout.flush()
240
247
 
241
248
 
242
249
  def main():
@@ -310,13 +317,18 @@ def _installed_hook_version() -> str | None:
310
317
 
311
318
 
312
319
  def needs_update() -> bool:
320
+ if not os.path.isdir(os.path.dirname(HOOK_SCRIPT_PATH)):
321
+ return False
313
322
  return _installed_hook_version() != HOOK_VERSION
314
323
 
315
324
 
316
325
  def update_hook() -> None:
326
+ if not os.path.isdir(os.path.dirname(HOOK_SCRIPT_PATH)):
327
+ return
317
328
  with open(HOOK_SCRIPT_PATH, "w", encoding="utf-8") as f:
318
329
  f.write(HOOK_SCRIPT)
319
- os.chmod(HOOK_SCRIPT_PATH, os.stat(HOOK_SCRIPT_PATH).st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
330
+ if os.name != "nt":
331
+ os.chmod(HOOK_SCRIPT_PATH, os.stat(HOOK_SCRIPT_PATH).st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
320
332
 
321
333
 
322
334
  # --- setup ---
@@ -358,7 +370,8 @@ def _setup_claude() -> None:
358
370
  console.print(f"[yellow]检测到已有 statusLine,备份后替换[/yellow]")
359
371
  settings.setdefault(_BACKUP_KEY, {})[_PREV_SL_KEY] = existing
360
372
 
361
- settings["statusLine"] = {"type": "command", "command": f"python3 {HOOK_SCRIPT_PATH}"}
373
+ python = sys.executable or "python3"
374
+ settings["statusLine"] = {"type": "command", "command": f"{python} {HOOK_SCRIPT_PATH}"}
362
375
 
363
376
  with open(CLAUDE_SETTINGS, "w", encoding="utf-8") as f:
364
377
  json.dump(settings, f, indent=2, ensure_ascii=False)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: token-tracker
3
- Version: 0.3.2
3
+ Version: 0.3.4
4
4
  Summary: Track token usage across local AI agents (Claude Code, Codex)
5
5
  Requires-Python: >=3.11
6
6
  Requires-Dist: rich>=13.7
File without changes
File without changes