cctally 1.88.0 → 1.88.2
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 +13 -0
- package/bin/_lib_conversation_retention.py +25 -1
- package/bin/_lib_pricing.py +35 -20
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,19 @@ based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
## [1.88.2] - 2026-07-31
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- Codex costs for the GPT-5.6 Terra and Luna models now use OpenAI's current published rates. OpenAI cut both models on 2026-07-30 — Terra from $2.50 to $2.00 per million input tokens, and Luna by 80%, from $1.00 to $0.20 — while cctally's embedded rate card still held the pre-cut prices, so Terra usage priced about 25% high and Luna usage about five times high across `codex-daily`, `codex-monthly`, `codex-weekly` and `codex-session`, the Codex half of `budget` and its spend alerts, and the dashboard. Both models now carry the published post-cut rates across the standard and long-context tiers. Codex costs are recalculated every time they are read, so corrected figures appear immediately with no rebuild; cctally stores one rate per model rather than a dated price history, so Terra and Luna usage from before the cut is now valued at the new rates as well, and budget alerts already recorded keep the amount they were recorded with. Sol and the base GPT-5.6 model were not repriced and are unchanged. (#441)
|
|
12
|
+
|
|
13
|
+
## [1.88.1] - 2026-07-31
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
- Session names no longer disappear from the Recent Sessions card while cctally is pruning old transcripts. The prune held the transcript store's maintenance lock exclusively for its entire pass, and the Sessions card's name lookup is deliberately built to give up instantly rather than wait on that lock, so every Claude session rendered a blank name until the prune finished — minutes on a large store, and for most installs on the v1.88.0 upgrade in particular, whose one-off transcript re-read is followed by an unthrottled sweep. The prune still claims the lock exclusively, which is what keeps it serialized against a second prune or a `cctally db vacuum`, but now holds it shared for the pass itself so read-only lookups are no longer locked out. What gets pruned, and when, is unchanged.
|
|
17
|
+
|
|
18
|
+
### Security
|
|
19
|
+
- Update the build-time `postcss` dependency to 8.5.25, clearing a path-traversal advisory (GHSA-r28c-9q8g-f849) in its source-map auto-loading. It is a development dependency used only when building the dashboard bundle from source, so it is absent from npm, Homebrew, and every other install, and the shipped dashboard is byte-for-byte unchanged.
|
|
20
|
+
|
|
8
21
|
## [1.88.0] - 2026-07-31
|
|
9
22
|
|
|
10
23
|
### Fixed
|
|
@@ -255,7 +255,11 @@ def _maybe_prune_conversation_retention(
|
|
|
255
255
|
skipped (retention disabled, throttled within 24h, or a lock contended).
|
|
256
256
|
|
|
257
257
|
Concurrency (F7): a dedicated non-blocking MAINTENANCE flock serializes prune
|
|
258
|
-
attempts across processes (a second dashboard skips cleanly).
|
|
258
|
+
attempts across processes (a second dashboard skips cleanly). It is claimed
|
|
259
|
+
EXCLUSIVE and then downgraded to SHARED for the pass proper, so a long prune
|
|
260
|
+
cannot starve the fail-closed panel readers that sample it
|
|
261
|
+
``LOCK_SH | LOCK_NB``; a rival ``LOCK_EX | LOCK_NB`` claim still fails
|
|
262
|
+
against the held SHARED, so the serialization is unchanged. Under it, the
|
|
259
263
|
two provider flocks are taken in a FIXED order (Claude then Codex),
|
|
260
264
|
non-blocking, so a rebuild/reingest mid-flight makes the prune skip this
|
|
261
265
|
cycle rather than race between candidate selection and deletion. The prune of
|
|
@@ -297,6 +301,26 @@ def _maybe_prune_conversation_retention(
|
|
|
297
301
|
fcntl.flock(codex_fh, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
|
298
302
|
except (BlockingIOError, OSError):
|
|
299
303
|
return None # a Codex sync is mid-flight; retry next cycle
|
|
304
|
+
# Downgrade the maintenance flock to SHARED for the pass proper.
|
|
305
|
+
# The EXCLUSIVE acquire above is what wins the race; holding it
|
|
306
|
+
# exclusive for the whole pass additionally locked out the
|
|
307
|
+
# fail-CLOSED panel readers, which take this flock
|
|
308
|
+
# `LOCK_SH | LOCK_NB` and blank their column on any contention
|
|
309
|
+
# (`read_session_titles_bounded` -> every Claude session title in
|
|
310
|
+
# the Recent Sessions card, for the minutes a large prune runs).
|
|
311
|
+
# A prune is a writer, not a family replacement: concurrent
|
|
312
|
+
# writes are already excluded by the two provider flocks, and
|
|
313
|
+
# the replacement paths readers guard against take this flock
|
|
314
|
+
# EXCLUSIVE, which a held SHARED still blocks. Rival prunes and
|
|
315
|
+
# `db vacuum` claim `LOCK_EX | LOCK_NB`, which also still fails.
|
|
316
|
+
# MUST stay after both provider flocks: a flock conversion is
|
|
317
|
+
# not atomic, so a rival can slip into the downgrade window —
|
|
318
|
+
# the provider flocks it then fails to claim are what make that
|
|
319
|
+
# harmless.
|
|
320
|
+
try:
|
|
321
|
+
fcntl.flock(maint_fh, fcntl.LOCK_SH)
|
|
322
|
+
except OSError:
|
|
323
|
+
pass # keep the exclusive hold; correctness is unchanged
|
|
300
324
|
cutoff = now_utc - dt.timedelta(days=int(retention_days))
|
|
301
325
|
conn.execute("BEGIN IMMEDIATE")
|
|
302
326
|
try:
|
package/bin/_lib_pricing.py
CHANGED
|
@@ -53,7 +53,7 @@ def _chip_for_model(name: str) -> str:
|
|
|
53
53
|
# Date the embedded pricing snapshots below were last verified against
|
|
54
54
|
# vendor sources. Bump whenever CLAUDE_MODEL_PRICING / CODEX_MODEL_PRICING
|
|
55
55
|
# is synced. Read by `pricing-check` + the release pre-flight staleness nudge.
|
|
56
|
-
PRICING_SNAPSHOT_DATE = "2026-07-
|
|
56
|
+
PRICING_SNAPSHOT_DATE = "2026-07-31"
|
|
57
57
|
PRICING_STALENESS_DAYS = 60 # release pre-flight WARNs past this age
|
|
58
58
|
|
|
59
59
|
# Canonical machine-readable pricing source (Claude values + Codex values).
|
|
@@ -99,7 +99,9 @@ PRICING_DRIFT_ALLOWLIST: list[dict] = [
|
|
|
99
99
|
|
|
100
100
|
# Anthropic API pricing snapshot:
|
|
101
101
|
# - Source: https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json
|
|
102
|
-
# - Captured/verified: 2026-07-28
|
|
102
|
+
# - Captured/verified: 2026-07-28. PRICING_SNAPSHOT_DATE has since moved to
|
|
103
|
+
# 2026-07-31 for the Codex-side gpt-5.6-terra/-luna correction (#441); these
|
|
104
|
+
# Claude values were NOT re-verified that day.
|
|
103
105
|
# - Verified by maintainer against docs.claude.com/en/docs/about-claude/pricing;
|
|
104
106
|
# update in PRs touching this table.
|
|
105
107
|
# 2026-06-10: added claude-fable-5 ($10/$50 per MTok; 1M context, no
|
|
@@ -386,9 +388,10 @@ _unknown_model_warnings: set[str] = set()
|
|
|
386
388
|
#
|
|
387
389
|
# Codex (OpenAI) API pricing snapshot:
|
|
388
390
|
# - Source: https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json
|
|
389
|
-
# - Captured: 2026-07-19 — the last
|
|
390
|
-
#
|
|
391
|
-
#
|
|
391
|
+
# - Captured: 2026-07-19 — the last FULL Codex sync. PRICING_SNAPSHOT_DATE has
|
|
392
|
+
# since moved for two targeted syncs (2026-07-24, the Claude-side opus-5 sync;
|
|
393
|
+
# 2026-07-31, the gpt-5.6-terra/-luna correction logged below). Codex values
|
|
394
|
+
# outside those two corrections were NOT re-verified on those days.
|
|
392
395
|
# - As of the 2026-07-19 sync this carries every openai-provider
|
|
393
396
|
# gpt-5* model the LiteLLM snapshot lists, so `pricing-check`'s scope finds
|
|
394
397
|
# nothing missing. Models absent from this table still fall back to `gpt-5`
|
|
@@ -402,6 +405,16 @@ _unknown_model_warnings: set[str] = set()
|
|
|
402
405
|
# 2026-07-19: verified all tracked values and the complete openai-provider
|
|
403
406
|
# gpt-5* model set against the live LiteLLM snapshot; no named table entries
|
|
404
407
|
# were missing. Official OpenAI model pages were used as the vendor cross-check.
|
|
408
|
+
# 2026-07-31 (#441): OpenAI repriced two gpt-5.6 variants on 2026-07-30 —
|
|
409
|
+
# gpt-5.6-terra $2.50/$15 -> $2.00/$12 per MTok, and gpt-5.6-luna $1.00/$6 ->
|
|
410
|
+
# $0.20/$1.20 (an 80% cut) — which left our 2026-07-10 values stale on all six
|
|
411
|
+
# cost fields each. Adopted the vendor's post-cut rates from
|
|
412
|
+
# developers.openai.com/api/docs/pricing (standard + long-context tiers, all
|
|
413
|
+
# twelve fields), which match the live LiteLLM snapshot exactly. This is NOT
|
|
414
|
+
# the introductory-rate pattern PRICING_DRIFT_ALLOWLIST exists to suppress:
|
|
415
|
+
# the vendor lists these as standard ongoing prices with no promotional or
|
|
416
|
+
# expiring annotation, so the durable rate is the cut rate. gpt-5.6 and
|
|
417
|
+
# gpt-5.6-sol were not repriced and are unchanged.
|
|
405
418
|
#
|
|
406
419
|
# Billing rules:
|
|
407
420
|
# - reasoning_output_tokens is billed at the *output* rate (matches
|
|
@@ -494,10 +507,12 @@ CODEX_MODEL_PRICING: dict[str, dict[str, Any]] = {
|
|
|
494
507
|
"cache_read_input_token_cost_above_272k_tokens": 1e-06,
|
|
495
508
|
"output_cost_per_token_above_272k_tokens": 4.5e-05,
|
|
496
509
|
},
|
|
497
|
-
# ──
|
|
510
|
+
# ── gpt-5.6 family (LiteLLM openai-provider entries) ──
|
|
498
511
|
# Exact model_prices_and_context_window.json values; each carries the
|
|
499
|
-
# above-272k tier (max_input_tokens 1050000). gpt-5.6 and gpt-5.6-sol
|
|
500
|
-
# gpt-5.5's rate card
|
|
512
|
+
# above-272k tier (max_input_tokens 1050000). gpt-5.6 and gpt-5.6-sol keep
|
|
513
|
+
# gpt-5.5's rate card from the 2026-07-10 sync; -terra and -luna carry
|
|
514
|
+
# OpenAI's 2026-07-30 post-cut rates (#441) and no longer track gpt-5.4's
|
|
515
|
+
# card or any other model's.
|
|
501
516
|
"gpt-5.6": {
|
|
502
517
|
"input_cost_per_token": 5e-06,
|
|
503
518
|
"cache_read_input_token_cost": 5e-07,
|
|
@@ -515,20 +530,20 @@ CODEX_MODEL_PRICING: dict[str, dict[str, Any]] = {
|
|
|
515
530
|
"output_cost_per_token_above_272k_tokens": 4.5e-05,
|
|
516
531
|
},
|
|
517
532
|
"gpt-5.6-terra": {
|
|
518
|
-
"input_cost_per_token":
|
|
519
|
-
"cache_read_input_token_cost":
|
|
520
|
-
"output_cost_per_token": 1.
|
|
521
|
-
"input_cost_per_token_above_272k_tokens":
|
|
522
|
-
"cache_read_input_token_cost_above_272k_tokens":
|
|
523
|
-
"output_cost_per_token_above_272k_tokens":
|
|
533
|
+
"input_cost_per_token": 2e-06,
|
|
534
|
+
"cache_read_input_token_cost": 2e-07,
|
|
535
|
+
"output_cost_per_token": 1.2e-05,
|
|
536
|
+
"input_cost_per_token_above_272k_tokens": 4e-06,
|
|
537
|
+
"cache_read_input_token_cost_above_272k_tokens": 4e-07,
|
|
538
|
+
"output_cost_per_token_above_272k_tokens": 1.8e-05,
|
|
524
539
|
},
|
|
525
540
|
"gpt-5.6-luna": {
|
|
526
|
-
"input_cost_per_token":
|
|
527
|
-
"cache_read_input_token_cost":
|
|
528
|
-
"output_cost_per_token":
|
|
529
|
-
"input_cost_per_token_above_272k_tokens":
|
|
530
|
-
"cache_read_input_token_cost_above_272k_tokens":
|
|
531
|
-
"output_cost_per_token_above_272k_tokens":
|
|
541
|
+
"input_cost_per_token": 2e-07,
|
|
542
|
+
"cache_read_input_token_cost": 2e-08,
|
|
543
|
+
"output_cost_per_token": 1.2e-06,
|
|
544
|
+
"input_cost_per_token_above_272k_tokens": 4e-07,
|
|
545
|
+
"cache_read_input_token_cost_above_272k_tokens": 4e-08,
|
|
546
|
+
"output_cost_per_token_above_272k_tokens": 1.8e-06,
|
|
532
547
|
},
|
|
533
548
|
# ── Issue #123: full gpt-5.x LiteLLM sync (2026-05-30 snapshot) ──
|
|
534
549
|
# Exact model_prices_and_context_window.json values for every
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cctally",
|
|
3
|
-
"version": "1.88.
|
|
3
|
+
"version": "1.88.2",
|
|
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": {
|