claude-finops 0.15.0 → 0.15.1

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/finops/procs.py +9 -4
  2. package/package.json +1 -1
package/finops/procs.py CHANGED
@@ -71,6 +71,12 @@ def _is_claude(p):
71
71
  return base in ("claude", "claude.exe", "claude.cmd") or cmd.endswith("/claude")
72
72
 
73
73
 
74
+ def _same_start(reg, p):
75
+ """True unless the registry's procStart names a different start time than ps reports.
76
+ Whitespace is normalised: the registry pads single-digit days ("Oct 9"), ps output is re-joined ("Oct 9")."""
77
+ return not reg.get("procStart") or reg["procStart"].split() == p["lstart"].split()
78
+
79
+
74
80
  def _ancestors(pid, procs):
75
81
  seen = set()
76
82
  while pid in procs and pid not in seen and pid > 1:
@@ -128,8 +134,7 @@ def list_sessions(pricing):
128
134
  continue
129
135
  pid = reg.get("pid")
130
136
  p = procs.get(pid)
131
- alive = bool(p) and _is_claude(p) and (
132
- not reg.get("procStart") or reg["procStart"] == p["lstart"])
137
+ alive = bool(p) and _is_claude(p) and _same_start(reg, p)
133
138
  if not alive:
134
139
  continue
135
140
  st = _transcript_stats(reg.get("sessionId"), pricing)
@@ -160,7 +165,7 @@ def act(pid, action):
160
165
  p = procs.get(pid)
161
166
  if not p or not _is_claude(p):
162
167
  return {"ok": False, "error": "Process is no longer running."}
163
- if reg.get("procStart") and reg["procStart"] != p["lstart"]:
168
+ if not _same_start(reg, p):
164
169
  return {"ok": False, "error": "PID was reused by another process; refusing."}
165
170
  sig, msg = ACTIONS[action]
166
171
  try:
@@ -642,7 +647,7 @@ def compact(pid, opts=None):
642
647
  p = _ps().get(pid)
643
648
  if not p or not _is_claude(p):
644
649
  return {"ok": False, "error": "Process is no longer running.", "copy": text}
645
- if reg.get("procStart") and reg["procStart"] != p["lstart"]:
650
+ if not _same_start(reg, p):
646
651
  return {"ok": False, "error": "PID was reused by another process; refusing.", "copy": text}
647
652
 
648
653
  tty = _tty_of(pid)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-finops",
3
- "version": "0.15.0",
3
+ "version": "0.15.1",
4
4
  "description": "Local FinOps dashboard for Claude Code: what you used, what it cost, why it cost that much, and what to change. Reads your own transcripts, no API key, no data leaves the machine.",
5
5
  "bin": {
6
6
  "claude-finops": "bin/claude-finops.js"