mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-10 21:47:02 +01:00
Some checks are pending
dependency freshness / dependencies on newest stable (push) Waiting to run
md-naming / markdown naming convention (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (mypy, mypy) (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (pylint, pylint) (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (rest, ) (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (shellcheck, shellcheck) (push) Waiting to run
Python tests / test (push) Waiting to run
repo-contract / repo contract (push) Waiting to run
Shell tests / shell-tests (push) Waiting to run
Shell tests / lib-tests (push) Waiting to run
Shell tests / arch-tests (push) Waiting to run
Links sessions to todo notes (note_claim.sh, todo-images prompts, fuzzy first prompt >= 0.5, handoff chains), dates completions from the status HLC in the first Firebase dump, and adds usd_per_note, note_linked_usd_share, notes_done(_linked) to the snapshot, a WEEKLY section and notes.json. token_dashboard stores the build-class A/B (agent-ab-build.jsonl) as meta ab_build. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WzxdWWMeapxnDcgk7HSw67
64 lines
1.9 KiB
Python
64 lines
1.9 KiB
Python
"""Lifetime USD and tokens of the sessions linked to notes (main + subagents).
|
|
|
|
Window-free on purpose: a note finished this week was often worked last week.
|
|
Files already loaded whole by the audit are reused instead of re-parsed.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
from typing import TYPE_CHECKING
|
|
|
|
from python_pkg.token_audit import parse, pricing
|
|
from python_pkg.token_audit.model import TOKEN_KINDS
|
|
|
|
if TYPE_CHECKING:
|
|
from pathlib import Path
|
|
|
|
from python_pkg.token_audit.model import Session
|
|
from python_pkg.token_audit.pricing import PriceBook
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class Spend:
|
|
"""Dollars at list price and raw tokens (all four classes)."""
|
|
|
|
usd: float = 0.0
|
|
tokens: int = 0
|
|
|
|
def __add__(self, other: Spend) -> Spend:
|
|
"""Sum two spends."""
|
|
return Spend(self.usd + other.usd, self.tokens + other.tokens)
|
|
|
|
|
|
def of_session(session: Session, book: PriceBook) -> Spend:
|
|
"""Spend of every turn a loaded session holds."""
|
|
return Spend(
|
|
sum(pricing.usd(turn, book) for turn in session.turns),
|
|
sum(turn.usage.get(kind, 0) for turn in session.turns for kind in TOKEN_KINDS),
|
|
)
|
|
|
|
|
|
def files_of(main: Path) -> list[Path]:
|
|
"""A main transcript plus every subagent transcript filed under it."""
|
|
return [main, *sorted(main.with_suffix("").glob("subagents/agent-*.jsonl"))]
|
|
|
|
|
|
def lifetime(
|
|
mains: dict[str, Path],
|
|
wanted: set[str],
|
|
book: PriceBook,
|
|
reuse: dict[str, Spend],
|
|
) -> dict[str, Spend]:
|
|
"""Whole-file spend per wanted session id, reusing ``reuse[path]`` hits."""
|
|
out: dict[str, Spend] = {}
|
|
for sid in sorted(wanted & mains.keys()):
|
|
total = Spend()
|
|
for path in files_of(mains[sid]):
|
|
hit = reuse.get(str(path))
|
|
total += (
|
|
hit if hit is not None else of_session(parse.load_session(path), book)
|
|
)
|
|
out[sid] = total
|
|
return out
|