Implement LLM-WP-0007: Kimi K3 default and EUR spend reporting
Add moonshotai/kimi-k3 as OpenRouter basemodel default after live smoke, USD→EUR cost conversion, append-only usage ledger, and CLI run/cost/spend week commands with token and euro reporting.
This commit is contained in:
parent
f3121c3f1f
commit
09aa1f3604
21 changed files with 1396 additions and 103 deletions
127
tests/test_usage.py
Normal file
127
tests/test_usage.py
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
from datetime import datetime
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
import pytest
|
||||
|
||||
from llm_connect.models import LLMResponse
|
||||
from llm_connect.usage import (
|
||||
UsageEvent,
|
||||
UsageLedger,
|
||||
default_usage_ledger_path,
|
||||
event_from_response,
|
||||
maybe_record_usage,
|
||||
suppress_auto_usage_record,
|
||||
week_window,
|
||||
)
|
||||
|
||||
|
||||
def test_default_ledger_path_env_and_xdg():
|
||||
assert default_usage_ledger_path(env={"LLM_CONNECT_USAGE_LEDGER": "/tmp/u.jsonl"}) == (
|
||||
__import__("pathlib").Path("/tmp/u.jsonl")
|
||||
)
|
||||
path = default_usage_ledger_path(env={"XDG_DATA_HOME": "/tmp/xdg"})
|
||||
assert path.as_posix().endswith("llm-connect/usage.jsonl")
|
||||
assert "xdg" in path.as_posix()
|
||||
|
||||
|
||||
def test_usage_ledger_append_and_sum_range(tmp_path):
|
||||
ledger = UsageLedger(tmp_path / "usage.jsonl")
|
||||
berlin = ZoneInfo("Europe/Berlin")
|
||||
monday = datetime(2026, 8, 3, 10, 0, tzinfo=berlin) # Monday
|
||||
sunday = datetime(2026, 8, 2, 12, 0, tzinfo=berlin) # previous Sunday
|
||||
|
||||
ledger.append(
|
||||
UsageEvent(
|
||||
provider="openrouter",
|
||||
model_id="moonshotai/kimi-k3",
|
||||
prompt_tokens=100,
|
||||
completion_tokens=50,
|
||||
total_tokens=150,
|
||||
cost_usd=0.001,
|
||||
cost_eur=0.00092,
|
||||
cost_source="rate_table:moonshotai/kimi-k3",
|
||||
fx_source="snapshot:2026-08-03",
|
||||
source="cli",
|
||||
recorded_at=monday,
|
||||
)
|
||||
)
|
||||
ledger.append(
|
||||
UsageEvent(
|
||||
provider="openrouter",
|
||||
model_id="moonshotai/kimi-k3",
|
||||
prompt_tokens=10,
|
||||
completion_tokens=5,
|
||||
total_tokens=15,
|
||||
cost_usd=0.0001,
|
||||
cost_eur=0.000092,
|
||||
cost_source="rate_table:moonshotai/kimi-k3",
|
||||
source="cli",
|
||||
recorded_at=sunday,
|
||||
)
|
||||
)
|
||||
|
||||
start, end = week_window(
|
||||
"current",
|
||||
now=datetime(2026, 8, 5, 18, 0, tzinfo=berlin),
|
||||
tz="Europe/Berlin",
|
||||
)
|
||||
summary = ledger.sum_range(start, end)
|
||||
|
||||
assert summary.event_count == 1
|
||||
assert summary.prompt_tokens == 100
|
||||
assert summary.total_tokens == 150
|
||||
assert summary.cost_eur == pytest.approx(0.00092)
|
||||
|
||||
last_start, last_end = week_window(
|
||||
"last",
|
||||
now=datetime(2026, 8, 5, 18, 0, tzinfo=berlin),
|
||||
tz="Europe/Berlin",
|
||||
)
|
||||
last_summary = ledger.sum_range(last_start, last_end)
|
||||
assert last_summary.event_count == 1
|
||||
assert last_summary.total_tokens == 15
|
||||
|
||||
|
||||
def test_week_window_current_and_last():
|
||||
berlin = ZoneInfo("Europe/Berlin")
|
||||
now = datetime(2026, 8, 5, 15, 30, tzinfo=berlin) # Wednesday
|
||||
start, end = week_window("current", now=now, tz="Europe/Berlin")
|
||||
assert start.weekday() == 0
|
||||
assert start.hour == 0
|
||||
assert end == now
|
||||
|
||||
last_start, last_end = week_window("last", now=now, tz="Europe/Berlin")
|
||||
assert (last_end - last_start).days == 7
|
||||
assert last_end == start
|
||||
|
||||
|
||||
def test_event_from_response_estimates_kimi_cost():
|
||||
response = LLMResponse(
|
||||
content="hi",
|
||||
model="moonshotai/kimi-k3",
|
||||
usage={"prompt_tokens": 1000, "completion_tokens": 1000, "total_tokens": 2000},
|
||||
)
|
||||
event = event_from_response(response, provider="openrouter", source="cli", fx=1.0)
|
||||
|
||||
assert event.cost_usd == pytest.approx(0.018)
|
||||
assert event.cost_eur == pytest.approx(0.018)
|
||||
assert event.cost_source == "rate_table:moonshotai/kimi-k3"
|
||||
|
||||
|
||||
def test_maybe_record_usage_opt_in(tmp_path, monkeypatch):
|
||||
ledger = tmp_path / "usage.jsonl"
|
||||
monkeypatch.setenv("LLM_CONNECT_USAGE_LEDGER", str(ledger))
|
||||
response = LLMResponse(
|
||||
content="x",
|
||||
model="moonshotai/kimi-k3",
|
||||
usage={"prompt_tokens": 10, "completion_tokens": 5, "total_tokens": 15},
|
||||
metadata={"provider": "openrouter"},
|
||||
)
|
||||
|
||||
event = maybe_record_usage(response, provider="openrouter", source="library")
|
||||
assert event is not None
|
||||
assert ledger.is_file()
|
||||
assert UsageLedger(ledger).read_all()[0].source == "library"
|
||||
|
||||
with suppress_auto_usage_record():
|
||||
assert maybe_record_usage(response, provider="openrouter", source="library") is None
|
||||
Loading…
Add table
Add a link
Reference in a new issue