mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-10 23:07:03 +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
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JThjboXTeZ3yJPBzxMx5wS
182 lines
5.7 KiB
Python
182 lines
5.7 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
import sqlite3
|
|
from typing import TYPE_CHECKING
|
|
|
|
import pytest
|
|
|
|
from python_pkg.token_dashboard import ingest
|
|
from python_pkg.token_dashboard.tests.conftest import (
|
|
assistant,
|
|
prompt,
|
|
result,
|
|
usd_opus_output,
|
|
use,
|
|
write,
|
|
)
|
|
|
|
if TYPE_CHECKING:
|
|
from collections.abc import Callable, Iterator
|
|
from pathlib import Path
|
|
|
|
|
|
def _tree(root: Path) -> None:
|
|
agent = use("ta", "Agent", description="Find x", subagent_type="Explore")
|
|
write(
|
|
root / "proj" / "s1.jsonl",
|
|
[
|
|
prompt("first", 0),
|
|
assistant("m1", 10, blocks=[agent]),
|
|
result("ta", 11, "launched", toolUseResult={"agentId": "abc"}),
|
|
assistant("m2", 20),
|
|
prompt("second", 1000),
|
|
assistant("m3", 1010, blocks=[{"type": "text", "text": "DONE: x"}]),
|
|
],
|
|
)
|
|
subdir = root / "proj" / "s1" / "subagents"
|
|
write(subdir / "agent-abc.jsonl", [prompt("task", 12), assistant("a1", 200)])
|
|
(subdir / "agent-abc.meta.json").write_text(
|
|
json.dumps({"agentType": "Explore", "description": "Find x"}),
|
|
encoding="utf-8",
|
|
)
|
|
# An agent that outlived /clear: nothing in s1 spawned it.
|
|
write(subdir / "agent-zzz.jsonl", [prompt("orphan", 30), assistant("z1", 40)])
|
|
|
|
|
|
def _run(tmp_path: Path, budget: float = 30.0) -> ingest.Outcome:
|
|
return ingest.run(
|
|
root=tmp_path / "projects",
|
|
db_path=tmp_path / "t.sqlite",
|
|
report_dir=tmp_path / "report",
|
|
budget_s=budget,
|
|
)
|
|
|
|
|
|
@pytest.fixture
|
|
def db(tmp_path: Path) -> Iterator[Callable[[], sqlite3.Connection]]:
|
|
opened: list[sqlite3.Connection] = []
|
|
|
|
def _open() -> sqlite3.Connection:
|
|
opened.append(sqlite3.connect(tmp_path / "t.sqlite"))
|
|
return opened[-1]
|
|
|
|
yield _open
|
|
for conn in opened:
|
|
conn.close()
|
|
|
|
|
|
def test_session_cost_reconciles_to_prompts_plus_unattributed(
|
|
tmp_path: Path, db: Callable[[], sqlite3.Connection]
|
|
) -> None:
|
|
_tree(tmp_path / "projects")
|
|
outcome = _run(tmp_path)
|
|
assert outcome.complete
|
|
conn = db()
|
|
usd, active_s, wall_s, tag = conn.execute(
|
|
"SELECT usd, active_s, wall_s, final_tag FROM session_summary WHERE key='s1'"
|
|
).fetchone()
|
|
assert usd == pytest.approx(usd_opus_output(1000) * 5)
|
|
prompts = conn.execute(
|
|
"SELECT idx, usd_own + usd_sub FROM prompt_summary WHERE key='s1' ORDER BY idx"
|
|
).fetchall()
|
|
unattributed = conn.execute(
|
|
"SELECT SUM(usd) FROM subagent_link WHERE main_key='s1' AND prompt_idx IS NULL"
|
|
).fetchone()[0]
|
|
assert sum(v for _, v in prompts) + unattributed == pytest.approx(usd)
|
|
# Prompt 0 carries its own two turns plus the Explore agent it spawned.
|
|
assert prompts[0][1] == pytest.approx(usd_opus_output(1000) * 3)
|
|
assert wall_s == 1010
|
|
# Union of main + subagent activity: 0..200 bridged, then 1000..1010.
|
|
assert active_s == pytest.approx(210)
|
|
assert tag == "DONE"
|
|
|
|
|
|
def test_subagent_links_to_its_prompt_via_agent_id(
|
|
tmp_path: Path, db: Callable[[], sqlite3.Connection]
|
|
) -> None:
|
|
_tree(tmp_path / "projects")
|
|
_run(tmp_path)
|
|
rows = dict(
|
|
db().execute("SELECT sub_key, prompt_idx FROM subagent_link").fetchall()
|
|
)
|
|
assert rows == {"s1/agent-abc": 0, "s1/agent-zzz": None}
|
|
|
|
|
|
def test_rerun_skips_unchanged_and_rows_outlive_deleted_files(
|
|
tmp_path: Path, db: Callable[[], sqlite3.Connection]
|
|
) -> None:
|
|
_tree(tmp_path / "projects")
|
|
_run(tmp_path)
|
|
assert _run(tmp_path).parsed == 0
|
|
(tmp_path / "projects" / "proj" / "s1.jsonl").unlink()
|
|
_run(tmp_path)
|
|
count = db().execute("SELECT COUNT(*) FROM turns").fetchone()[0]
|
|
assert count == 5
|
|
|
|
|
|
def test_changed_file_is_reparsed_without_duplicating_rows(
|
|
tmp_path: Path, db: Callable[[], sqlite3.Connection]
|
|
) -> None:
|
|
_tree(tmp_path / "projects")
|
|
_run(tmp_path)
|
|
path = tmp_path / "projects" / "proj" / "s1.jsonl"
|
|
with path.open("a", encoding="utf-8") as handle:
|
|
handle.write(json.dumps(assistant("m4", 1020)) + "\n")
|
|
assert _run(tmp_path).parsed == 1
|
|
count = db().execute("SELECT COUNT(*) FROM turns").fetchone()[0]
|
|
assert count == 6
|
|
|
|
|
|
def test_zero_budget_leaves_work_pending_and_resumes(tmp_path: Path) -> None:
|
|
_tree(tmp_path / "projects")
|
|
first = _run(tmp_path, budget=0.0)
|
|
assert not first.complete
|
|
assert first.parsed == 1 # always makes progress
|
|
rest = _run(tmp_path)
|
|
assert rest.complete
|
|
assert first.parsed + rest.parsed == 3
|
|
|
|
|
|
def test_daily_rollup_matches_turns(
|
|
tmp_path: Path, db: Callable[[], sqlite3.Connection]
|
|
) -> None:
|
|
_tree(tmp_path / "projects")
|
|
_run(tmp_path)
|
|
conn = db()
|
|
total, calls, sub = conn.execute(
|
|
"SELECT SUM(usd), SUM(calls), SUM(usd_sub) FROM daily"
|
|
).fetchone()
|
|
assert total == pytest.approx(usd_opus_output(1000) * 5)
|
|
assert calls == 5
|
|
assert sub == pytest.approx(usd_opus_output(1000) * 2)
|
|
|
|
|
|
def test_cli_exit_codes(tmp_path: Path) -> None:
|
|
_tree(tmp_path / "projects")
|
|
args = [
|
|
"--root",
|
|
str(tmp_path / "projects"),
|
|
"--db",
|
|
str(tmp_path / "t.sqlite"),
|
|
"--report-dir",
|
|
str(tmp_path / "report"),
|
|
]
|
|
assert ingest.main([*args, "--budget", "0"]) == ingest.EXIT_PENDING
|
|
assert ingest.main(args) == 0
|
|
|
|
|
|
def test_session_with_no_prompts_and_no_main_file(
|
|
tmp_path: Path, db: Callable[[], sqlite3.Connection]
|
|
) -> None:
|
|
sub = tmp_path / "projects" / "proj" / "gone" / "subagents" / "agent-q.jsonl"
|
|
write(sub, [assistant("q1", 5), assistant("q2", 6)])
|
|
assert _run(tmp_path).complete
|
|
usd, prompts = (
|
|
db()
|
|
.execute("SELECT usd, prompts FROM session_summary WHERE key='gone'")
|
|
.fetchone()
|
|
)
|
|
assert usd == pytest.approx(usd_opus_output(1000) * 2)
|
|
assert prompts == 0
|