cctally 1.20.4 → 1.21.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.
- package/CHANGELOG.md +10 -0
- package/bin/_lib_pricing.py +6 -0
- package/bin/cctally +50 -10
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,16 @@ based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
## [1.21.1] - 2026-05-28
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- **`cctally statusline` now shows the correct 7d percentage after an Anthropic mid-week reset (or in-place credit) instead of staying pinned to the pre-reset peak.** The statusline's 7d number is monotonic-clamped against a high-water mark read from `weekly_usage_snapshots`, but the clamp keyed only on `week_start_date` — `SELECT MAX(weekly_percent) WHERE week_start_date = ?`. When Anthropic resets a 7d window mid-cycle, the post-reset snapshots keep the *same* `week_start_date` (and `week_end_at`) as the pre-reset ramp, so the bucket-wide `MAX` returned the stale pre-reset peak (e.g. 41%) and clamped the true post-reset value (e.g. 2%) back up to it; the statusline read e.g. `7d 41%` while `cctally report`/`forecast` and the dashboard — which segment the week at the reset via `week_reset_events` — correctly showed 2%. The 5h segment was never affected because a 5h reset mints a new `five_hour_window_key` that naturally scopes its `MAX`. The clamp now mirrors the CLI/dashboard segmentation (`_apply_reset_events_to_subweeks`: the post-reset window's `start_ts` becomes `effective_reset_at_utc`) by flooring the `MAX` to snapshots captured at/after the latest reset effective within the current window — `... AND unixepoch(captured_at_utc) >= unixepoch(<floor>)`, with `unixepoch()` on both sides because reset rows carry mixed offset spellings (`+00:00` and legacy `+03:00`) while `captured_at_utc` uses `Z`, so a lexical comparison would misorder them (the same rule the 5h-block cross-reset flag follows). Weeks with no reset event take the unchanged legacy query, so the normal monotonic-within-window behavior is byte-identical. Regression: new `extensions-hwm-7d-post-reset` fixture in `bin/cctally-statusline-test` (33 scenarios) seeds a pre-reset peak + post-reset row sharing one `week_start_date` plus a `week_reset_events` row and asserts the rendered line reads `7d 2%`, not `7d 41%`.
|
|
12
|
+
|
|
13
|
+
## [1.21.0] - 2026-05-28
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
- **Claude Opus 4.8 pricing.** `claude-opus-4-8` is now in the embedded `CLAUDE_MODEL_PRICING` table at the standard Opus 4.x rates ($5/MTok input · $6.25/MTok 5-minute cache write · $0.50/MTok cache read · $25/MTok output — identical to Opus 4.5/4.6/4.7), so every cost-computing command (`daily`, `weekly`, `session`, `blocks`, `report`, …) prices Opus 4.8 sessions correctly instead of warning "unknown model, treating cost as $0". The 1M-context variant `claude-opus-4-8[1m]` is added to `CLAUDE_MODEL_CONTEXT_WINDOWS` so `cctally statusline`'s 🧠 context-% segment measures against the real 1,000,000-token window rather than silently falling through to the 200K "opus" family default. Only the bare model id is added (matching how Opus 4.6/4.7 appear in real session JSONL); no dated `claude-opus-4-8-YYYYMMDD` twin is included since Anthropic's published id for this model is the bare alias.
|
|
17
|
+
|
|
8
18
|
## [1.20.4] - 2026-05-28
|
|
9
19
|
|
|
10
20
|
### Changed
|
package/bin/_lib_pricing.py
CHANGED
|
@@ -194,6 +194,12 @@ CLAUDE_MODEL_PRICING: dict[str, dict[str, Any]] = {
|
|
|
194
194
|
"cache_creation_input_token_cost": 6.25e-06,
|
|
195
195
|
"cache_read_input_token_cost": 5e-07,
|
|
196
196
|
},
|
|
197
|
+
"claude-opus-4-8": {
|
|
198
|
+
"input_cost_per_token": 5e-06,
|
|
199
|
+
"output_cost_per_token": 2.5e-05,
|
|
200
|
+
"cache_creation_input_token_cost": 6.25e-06,
|
|
201
|
+
"cache_read_input_token_cost": 5e-07,
|
|
202
|
+
},
|
|
197
203
|
"claude-sonnet-4-20250514": {
|
|
198
204
|
"input_cost_per_token": 3e-06,
|
|
199
205
|
"output_cost_per_token": 1.5e-05,
|
package/bin/cctally
CHANGED
|
@@ -281,6 +281,7 @@ _short_model_name = _lib_pricing._short_model_name
|
|
|
281
281
|
# Unknown model id → segment renders `🧠 N/A` + one-shot stderr warn.
|
|
282
282
|
CLAUDE_MODEL_CONTEXT_WINDOWS = {
|
|
283
283
|
# 1M-token variants (explicit IDs override the family default).
|
|
284
|
+
"claude-opus-4-8[1m]": 1_000_000,
|
|
284
285
|
"claude-opus-4-7[1m]": 1_000_000,
|
|
285
286
|
"claude-sonnet-4-5[1m]": 1_000_000,
|
|
286
287
|
# Default 200K for every other Sonnet/Opus/Haiku family member.
|
|
@@ -4952,17 +4953,56 @@ def _build_statusline_injections(warn_once):
|
|
|
4952
4953
|
pass
|
|
4953
4954
|
if seven_resets is not None:
|
|
4954
4955
|
try:
|
|
4955
|
-
# Seven-day window
|
|
4956
|
-
#
|
|
4957
|
-
|
|
4958
|
-
|
|
4959
|
-
).
|
|
4960
|
-
|
|
4961
|
-
|
|
4962
|
-
|
|
4963
|
-
|
|
4964
|
-
|
|
4956
|
+
# Seven-day window bounds from the resets_at epoch:
|
|
4957
|
+
# week_end = reset; week_start = reset - 7 days. The
|
|
4958
|
+
# date form is the snapshot lookup key (week_start_date
|
|
4959
|
+
# is deliberately NOT re-anchored across a mid-week
|
|
4960
|
+
# reset — see _apply_reset_events_to_subweeks).
|
|
4961
|
+
week_end_dt = dt.datetime.fromtimestamp(
|
|
4962
|
+
int(seven_resets), tz=dt.timezone.utc,
|
|
4963
|
+
)
|
|
4964
|
+
week_start_dt = week_end_dt - dt.timedelta(days=7)
|
|
4965
|
+
week_start_date = week_start_dt.date().isoformat()
|
|
4966
|
+
# Reset-aware floor. An Anthropic mid-week reset / in-
|
|
4967
|
+
# place credit leaves the pre-reset peak snapshots in
|
|
4968
|
+
# this SAME week_start_date bucket (the boundary the
|
|
4969
|
+
# snapshots carry does not change). A naive bucket-wide
|
|
4970
|
+
# MAX(weekly_percent) would clamp the post-reset value
|
|
4971
|
+
# UP to that stale peak — the statusline would show the
|
|
4972
|
+
# pre-reset 7d %. Mirror the CLI/dashboard segmentation
|
|
4973
|
+
# (_apply_reset_events_to_subweeks: post-reset window
|
|
4974
|
+
# start_ts := effective_reset_at_utc) by flooring the
|
|
4975
|
+
# MAX to snapshots captured at/after the latest reset
|
|
4976
|
+
# effective WITHIN this window. unixepoch() on both
|
|
4977
|
+
# sides — reset rows carry mixed offset spellings
|
|
4978
|
+
# (+00:00 / +03:00) while captured_at_utc uses 'Z', so a
|
|
4979
|
+
# lexical compare would misorder them (same rule as the
|
|
4980
|
+
# 5h-block cross-reset flag).
|
|
4981
|
+
floor_row = conn.execute(
|
|
4982
|
+
"SELECT MAX(effective_reset_at_utc) "
|
|
4983
|
+
"FROM week_reset_events "
|
|
4984
|
+
"WHERE unixepoch(effective_reset_at_utc) >= unixepoch(?) "
|
|
4985
|
+
" AND unixepoch(effective_reset_at_utc) < unixepoch(?)",
|
|
4986
|
+
(week_start_dt.isoformat(), week_end_dt.isoformat()),
|
|
4965
4987
|
).fetchone()
|
|
4988
|
+
floor_iso = (
|
|
4989
|
+
floor_row[0] if floor_row and floor_row[0] else None
|
|
4990
|
+
)
|
|
4991
|
+
if floor_iso is not None:
|
|
4992
|
+
row = conn.execute(
|
|
4993
|
+
"SELECT MAX(weekly_percent) "
|
|
4994
|
+
"FROM weekly_usage_snapshots "
|
|
4995
|
+
"WHERE week_start_date = ? "
|
|
4996
|
+
" AND unixepoch(captured_at_utc) >= unixepoch(?)",
|
|
4997
|
+
(week_start_date, floor_iso),
|
|
4998
|
+
).fetchone()
|
|
4999
|
+
else:
|
|
5000
|
+
row = conn.execute(
|
|
5001
|
+
"SELECT MAX(weekly_percent) "
|
|
5002
|
+
"FROM weekly_usage_snapshots "
|
|
5003
|
+
"WHERE week_start_date = ?",
|
|
5004
|
+
(week_start_date,),
|
|
5005
|
+
).fetchone()
|
|
4966
5006
|
if row and row[0] is not None:
|
|
4967
5007
|
seven_hwm = float(row[0])
|
|
4968
5008
|
except Exception:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cctally",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.21.1",
|
|
4
4
|
"description": "Claude Code usage tracker and local dashboard for Pro/Max subscription limits - weekly cost-per-percent trend, quota forecasts, threshold alerts. ccusage-compatible.",
|
|
5
5
|
"homepage": "https://github.com/omrikais/cctally",
|
|
6
6
|
"repository": {
|