cctally 1.113.0 → 1.115.0
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 +47 -0
- package/README.md +4 -6
- package/bin/_cctally_account.py +32 -8
- package/bin/_cctally_cache.py +6035 -722
- package/bin/_cctally_completion.py +1287 -0
- package/bin/_cctally_config.py +37 -0
- package/bin/_cctally_core.py +400 -2
- package/bin/_cctally_dashboard.py +98 -20
- package/bin/_cctally_dashboard_conversation.py +292 -23
- package/bin/_cctally_dashboard_envelope.py +16 -3
- package/bin/_cctally_dashboard_perf.py +128 -9
- package/bin/_cctally_dashboard_sources.py +285 -213
- package/bin/_cctally_db.py +1177 -23
- package/bin/_cctally_diagnosis_sources.py +22 -4
- package/bin/_cctally_doctor.py +572 -45
- package/bin/_cctally_five_hour.py +84 -33
- package/bin/_cctally_forecast.py +108 -15
- package/bin/_cctally_journal.py +3950 -116
- package/bin/_cctally_journal_repair.py +101 -12
- package/bin/_cctally_milestone_history.py +82 -9
- package/bin/_cctally_parser.py +42 -0
- package/bin/_cctally_percent_breakdown.py +3 -2
- package/bin/_cctally_project.py +8 -2
- package/bin/_cctally_quarantine.py +652 -0
- package/bin/_cctally_quota.py +227 -37
- package/bin/_cctally_quota_model.py +360 -83
- package/bin/_cctally_record.py +691 -149
- package/bin/_cctally_rederive.py +320 -41
- package/bin/_cctally_refresh.py +84 -13
- package/bin/_cctally_source_analytics.py +83 -17
- package/bin/_cctally_statusline.py +6154 -517
- package/bin/_cctally_store.py +367 -53
- package/bin/_cctally_transcript.py +8 -7
- package/bin/_cctally_tui.py +61 -56
- package/bin/_cctally_weekrefs.py +128 -21
- package/bin/_lib_account_binding.py +152 -0
- package/bin/_lib_account_protocol.py +386 -0
- package/bin/_lib_aggregators.py +4 -0
- package/bin/_lib_cache_coverage.py +13 -1
- package/bin/_lib_cache_report.py +35 -6
- package/bin/_lib_cache_writer_lock.py +19 -3
- package/bin/_lib_clone_copy.py +142 -0
- package/bin/_lib_codex_conversation.py +32 -0
- package/bin/_lib_codex_conversation_query.py +297 -49
- package/bin/_lib_codex_conversation_watch.py +59 -14
- package/bin/_lib_codex_drain_admission.py +214 -0
- package/bin/_lib_codex_metadata.py +18 -1
- package/bin/_lib_codex_publication_barrier.py +277 -0
- package/bin/_lib_codex_rollout_container.py +502 -0
- package/bin/_lib_conversation_dispatch.py +3 -0
- package/bin/_lib_conversation_query.py +106 -59
- package/bin/_lib_conversation_retention.py +1605 -640
- package/bin/_lib_cost_provenance.py +53 -2
- package/bin/_lib_detector_access_registry.py +3817 -0
- package/bin/_lib_doctor.py +714 -69
- package/bin/_lib_five_hour.py +126 -0
- package/bin/_lib_fmt.py +11 -0
- package/bin/_lib_ingest_frontier.py +414 -20
- package/bin/_lib_journal.py +141 -10
- package/bin/_lib_jsonl.py +5 -4
- package/bin/_lib_legacy_spool.py +126 -0
- package/bin/_lib_legacy_writer_evidence.py +136 -0
- package/bin/_lib_merge_gate.py +231 -86
- package/bin/_lib_meter_rate_change.py +10 -0
- package/bin/_lib_outcome_quarantine.py +690 -0
- package/bin/_lib_perf.py +27 -1
- package/bin/_lib_pricing.py +199 -9
- package/bin/_lib_pricing_check.py +20 -4
- package/bin/_lib_quarantine.py +154 -0
- package/bin/_lib_quota_calibration.py +53 -8
- package/bin/_lib_quota_copy.py +2 -1
- package/bin/_lib_quota_model.py +288 -46
- package/bin/_lib_reclaim_planner.py +792 -0
- package/bin/_lib_rederive.py +319 -82
- package/bin/_lib_segment_summary.py +35 -2
- package/bin/_lib_snapshot_cache.py +21 -0
- package/bin/_lib_sqlite_close.py +81 -0
- package/bin/_lib_statusline_candidates.py +292 -23
- package/bin/_lib_subscription_weeks.py +100 -17
- package/bin/_lib_tick_stats.py +217 -17
- package/bin/_lib_wal_checkpoint.py +1077 -0
- package/bin/_lib_write_budget.py +483 -0
- package/bin/_lib_write_io.py +703 -0
- package/bin/cctally +31 -1
- package/dashboard/static/assets/{ConversationsView-CEZ-BUyi.js → ConversationsView-Bc8LCOAZ.js} +1 -1
- package/dashboard/static/assets/{DoctorModal-CE1oH_Zy.js → DoctorModal-D--qVBwe.js} +1 -1
- package/dashboard/static/assets/ModalRoot-DLPgyAM_.js +1 -0
- package/dashboard/static/assets/{ProjectsDrillPanel-B3DZoCeD.js → ProjectsDrillPanel-z53a4v4M.js} +1 -1
- package/dashboard/static/assets/{SourceDetailModal-CHp9EgLP.js → SourceDetailModal-Bw0T8W-W.js} +1 -1
- package/dashboard/static/assets/{UpdateModal-5iKST6jo.js → UpdateModal-D5AKx4Yw.js} +1 -1
- package/dashboard/static/assets/index-BKITk1CT.css +1 -0
- package/dashboard/static/assets/{index-Cm0VTxJC.js → index-BXDOzSng.js} +3 -3
- package/dashboard/static/assets/{outlineNavigation-DkXGL8J6.js → outlineNavigation-JObY7cUY.js} +1 -1
- package/dashboard/static/dashboard.html +2 -2
- package/package.json +19 -1
- package/dashboard/static/assets/ModalRoot-D5Y8IFUG.js +0 -1
- package/dashboard/static/assets/index-Dt4tqf43.css +0 -1
|
@@ -122,7 +122,8 @@ def claude_card_rate_violations(snapshot) -> list:
|
|
|
122
122
|
A closed amount of exactly $0 proves a missing card only while no Claude
|
|
123
123
|
card prices a used token class at zero. Base rates, any present long-
|
|
124
124
|
context tier, the derived 1-hour cache-write rate and any Fast multiplier
|
|
125
|
-
must all be positive; an empty list is that invariant.
|
|
125
|
+
must all be positive; an empty list is that invariant. A whole-request
|
|
126
|
+
(prompt-length) declaration must also be complete and well formed (#929).
|
|
126
127
|
"""
|
|
127
128
|
_lib_pricing = _pricing()
|
|
128
129
|
out = []
|
|
@@ -143,23 +144,73 @@ def claude_card_rate_violations(snapshot) -> list:
|
|
|
143
144
|
_positive_rate(multiplier) and _positive_rate(tier_input)
|
|
144
145
|
):
|
|
145
146
|
out.append((model, "cache_write_1h_above_200k_tokens"))
|
|
147
|
+
# Not the request hot path, so the unrecognised-field scan runs here
|
|
148
|
+
# too: a card carrying only such a field half-declares the tier (#929).
|
|
149
|
+
if (_lib_pricing._is_whole_request_card(card)
|
|
150
|
+
or _lib_pricing._unrecognised_whole_request_fields(card)):
|
|
151
|
+
out.extend(_whole_request_violations(
|
|
152
|
+
_lib_pricing, model, card, multiplier))
|
|
146
153
|
stripped = _lib_pricing._strip_anthropic_model_prefix(model)
|
|
147
154
|
if stripped in fast and not _positive_rate(fast[stripped]):
|
|
148
155
|
out.append((model, "fast_multiplier"))
|
|
149
156
|
return out
|
|
150
157
|
|
|
151
158
|
|
|
159
|
+
def _whole_request_violations(_lib_pricing, model, card, multiplier) -> list:
|
|
160
|
+
"""The whole-request (prompt-length) tier's share of the invariant (#929).
|
|
161
|
+
|
|
162
|
+
Every higher rate must be present and positive, the threshold marker must
|
|
163
|
+
be the integer the `_above_100k_tokens` fields name, the card must not mix
|
|
164
|
+
in a marginal `_above_200k_tokens` tier, the derived higher 1-hour write
|
|
165
|
+
rate (higher input x multiplier) must be positive, and the card must carry
|
|
166
|
+
no `_above_100k_tokens` field other than the four recognised ones (the
|
|
167
|
+
selector and `check_table_shapes` refuse such a card too).
|
|
168
|
+
"""
|
|
169
|
+
out = []
|
|
170
|
+
for _base, tier in _lib_pricing.CLAUDE_WHOLE_REQUEST_TIER_FIELDS:
|
|
171
|
+
if not _positive_rate(card.get(tier)):
|
|
172
|
+
out.append((model, tier))
|
|
173
|
+
key = _lib_pricing.CLAUDE_WHOLE_REQUEST_THRESHOLD_KEY
|
|
174
|
+
threshold = card.get(key)
|
|
175
|
+
if (key not in card or isinstance(threshold, bool)
|
|
176
|
+
or not isinstance(threshold, int)
|
|
177
|
+
or threshold != _lib_pricing.CLAUDE_WHOLE_REQUEST_THRESHOLD):
|
|
178
|
+
out.append((model, key))
|
|
179
|
+
if any(k.endswith("_above_200k_tokens") for k in card):
|
|
180
|
+
out.append((model, "whole_request_mixed_tiers"))
|
|
181
|
+
if not (_positive_rate(multiplier) and _positive_rate(
|
|
182
|
+
card.get("input_cost_per_token_above_100k_tokens"))):
|
|
183
|
+
out.append((model, "cache_write_1h_above_100k_tokens"))
|
|
184
|
+
for field in _lib_pricing._unrecognised_whole_request_fields(card):
|
|
185
|
+
out.append((model, field))
|
|
186
|
+
return out
|
|
187
|
+
|
|
188
|
+
|
|
152
189
|
def claude_entry_rates_positive(card, entry, snapshot) -> bool:
|
|
153
190
|
"""True iff every rate that prices one of ``entry``'s tokens is positive.
|
|
154
191
|
|
|
155
192
|
Mirrors `_lib_pricing._calculate_entry_cost` term by term: each token class
|
|
156
193
|
is priced below the long-context threshold at its base rate and above it at
|
|
157
194
|
a present tier rate, and a known 1-hour cache-write split prices its share
|
|
158
|
-
at the derived input-times-multiplier rate.
|
|
195
|
+
at the derived input-times-multiplier rate. A whole-request card (#929) is
|
|
196
|
+
first resolved to the card the entry's prompt selects.
|
|
159
197
|
"""
|
|
160
198
|
if card is None:
|
|
161
199
|
return False
|
|
162
200
|
_lib_pricing = _pricing()
|
|
201
|
+
# #929: a whole-request card prices this entry at the card its prompt
|
|
202
|
+
# selects, so judge THAT card; every check below then runs unchanged on
|
|
203
|
+
# it. A malformed declaration prices nothing reliably: refuse it.
|
|
204
|
+
if _lib_pricing._is_whole_request_card(card):
|
|
205
|
+
try:
|
|
206
|
+
card = _lib_pricing._select_claude_request_card(
|
|
207
|
+
card,
|
|
208
|
+
input_tokens=int(entry.input_tokens or 0),
|
|
209
|
+
cache_creation_tokens=int(entry.cache_creation_tokens or 0),
|
|
210
|
+
cache_read_tokens=int(entry.cache_read_tokens or 0),
|
|
211
|
+
)
|
|
212
|
+
except ValueError:
|
|
213
|
+
return False
|
|
163
214
|
threshold = snapshot.tier_thresholds["claude"]
|
|
164
215
|
|
|
165
216
|
def tiered(tokens, base_key, tier_key):
|