claude-code-tracker 1.1.6 → 1.1.7

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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/backfill.py +23 -13
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-code-tracker",
3
- "version": "1.1.6",
3
+ "version": "1.1.7",
4
4
  "description": "Automatic token, cost, and prompt tracking for Claude Code sessions",
5
5
  "keywords": [
6
6
  "claude",
package/src/backfill.py CHANGED
@@ -50,7 +50,7 @@ for jf in jsonl_files:
50
50
  inp = out = cache_create = cache_read = 0
51
51
  model = "unknown"
52
52
  first_ts = None
53
- last_ts = None
53
+ msgs = []
54
54
 
55
55
  try:
56
56
  with open(jf) as f:
@@ -58,10 +58,13 @@ for jf in jsonl_files:
58
58
  try:
59
59
  obj = json.loads(line)
60
60
  ts = obj.get("timestamp")
61
- if ts:
62
- if first_ts is None:
63
- first_ts = ts
64
- last_ts = ts
61
+ if ts and first_ts is None:
62
+ first_ts = ts
63
+ t = obj.get("type")
64
+ if t == "user" and not obj.get("isSidechain") and ts:
65
+ msgs.append(("user", ts))
66
+ elif t == "assistant" and ts:
67
+ msgs.append(("assistant", ts))
65
68
  msg = obj.get("message", {})
66
69
  if isinstance(msg, dict) and msg.get("role") == "assistant":
67
70
  usage = msg.get("usage", {})
@@ -94,15 +97,22 @@ for jf in jsonl_files:
94
97
  if not session_date:
95
98
  session_date = datetime.fromtimestamp(os.path.getmtime(jf)).strftime("%Y-%m-%d")
96
99
 
97
- # Duration
100
+ # Duration: sum of per-turn active thinking time (user -> first assistant reply)
98
101
  duration = 0
99
- if first_ts and last_ts:
100
- try:
101
- t0 = datetime.fromisoformat(first_ts.replace("Z", "+00:00"))
102
- t1 = datetime.fromisoformat(last_ts.replace("Z", "+00:00"))
103
- duration = max(0, int((t1 - t0).total_seconds()))
104
- except Exception:
105
- pass
102
+ i = 0
103
+ while i < len(msgs):
104
+ if msgs[i][0] == "user":
105
+ j = i + 1
106
+ while j < len(msgs) and msgs[j][0] != "assistant":
107
+ j += 1
108
+ if j < len(msgs):
109
+ try:
110
+ t0 = datetime.fromisoformat(msgs[i][1].replace("Z", "+00:00"))
111
+ t1 = datetime.fromisoformat(msgs[j][1].replace("Z", "+00:00"))
112
+ duration += max(0, int((t1 - t0).total_seconds()))
113
+ except Exception:
114
+ pass
115
+ i += 1
106
116
 
107
117
  # Cost
108
118
  if "opus" in model: