Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions apps/agentacct/Sources/agentacct/V1Model.swift
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ struct V1StepUsage: Decodable {
let linkedUsageRecords: Int?
let pricedUsageRecords: Int?
let unpricedUsageRecords: Int?
let costConfidence: String?

enum CodingKeys: String, CodingKey {
case totalTokens = "total_tokens"
Expand All @@ -175,14 +176,18 @@ struct V1StepUsage: Decodable {
case linkedUsageRecords = "linked_usage_records"
case pricedUsageRecords = "priced_usage_records"
case unpricedUsageRecords = "unpriced_usage_records"
case costConfidence = "cost_confidence"
}

/// The shared cost honesty rule: None-never-$0; a value with unpriced
/// rows alongside is a partial subtotal (~$).
/// The shared cost honesty rule: None-never-$0; a value with unpriced rows
/// alongside is a partial subtotal (~$); a complete figure is exact ("$")
/// only when its priced records are all reported/billed — an estimated
/// (token-priced) step reads "≈$" rather than over-claiming exactness.
var costText: String {
guard let cost = estimatedCostUsd else { return "—" }
let partial = (unpricedUsageRecords ?? 0) > 0
return Fmt.dollars(cost, prefix: partial ? "~$" : "$")
if (unpricedUsageRecords ?? 0) > 0 { return Fmt.dollars(cost, prefix: "~$") }
let reported = costConfidence == "client_reported" || costConfidence == "provider_billed"
return Fmt.dollars(cost, prefix: reported ? "$" : "≈$")
}
}

Expand Down
28 changes: 28 additions & 0 deletions src/agentacct/v1_sessions.py
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,29 @@ def _project_check(event: dict[str, Any]) -> dict[str, Any]:
return {name: event.get(name) for name in _STEP_CHECK_FIELDS}


_REPORTED_COST_CONFIDENCES = frozenset({"client_reported", "provider_billed"})


def _step_cost_confidence(breakdown: Any) -> str | None:
"""One cost-confidence for a step, from its per-record breakdown. A step's
cost is only as exact as its weakest priced record: if every priced record
is reported/billed the step is exact; if any is a token-based estimate (or an
unknown confidence) the whole step reads as an estimate. Returns None when
nothing was priced (the step renders "—", never a fabricated exact $0)."""
if not isinstance(breakdown, dict):
return None
present = {
str(key)
for key, count in breakdown.items()
if isinstance(count, int) and not isinstance(count, bool) and count > 0
}
if not present:
return None
if present <= _REPORTED_COST_CONFIDENCES:
return "provider_billed" if "provider_billed" in present else "client_reported"
return "estimated_from_tokens"


def _project_step(item: dict[str, Any], models: list[dict[str, Any]]) -> dict[str, Any]:
evidence_events = item.get("evidence_events")
checks = [
Expand Down Expand Up @@ -531,6 +554,11 @@ def _project_step(item: dict[str, Any], models: list[dict[str, Any]]) -> dict[st
"linked_usage_records": item.get("linked_usage_records"),
"priced_usage_records": item.get("priced_usage_records"),
"unpriced_usage_records": item.get("unpriced_usage_records"),
# One confidence for the whole step: exact only when every priced
# record is reported/billed, else an estimate. The macOS app uses
# this to pick "$" vs "≈$" so a step cost never reads exact when it
# was estimated from tokens.
"cost_confidence": _step_cost_confidence(item.get("cost_confidence_breakdown")),
},
"join_confidence": item.get("join_confidence"),
"join_explanation": item.get("join_explanation"),
Expand Down
26 changes: 26 additions & 0 deletions tests/test_v1_sessions.py
Original file line number Diff line number Diff line change
Expand Up @@ -1052,3 +1052,29 @@ def test_plan_endpoint_calibrated_aggregates_agree(tmp_path):
# Cache: an unchanged store serves the same build (same generated_at).
again = client.get("/v1/plan", headers=AUTH, params={"days": 14}).json()
assert again["generated_at"] == payload["generated_at"]


def test_step_cost_confidence_is_exact_only_when_every_priced_record_is_reported() -> None:
from agentacct.v1_sessions import _step_cost_confidence

# Nothing priced -> no confidence (the step renders "—", never an exact $0).
assert _step_cost_confidence(None) is None
assert _step_cost_confidence({}) is None
assert _step_cost_confidence({"client_reported": 0}) is None
# All reported/billed -> exact.
assert _step_cost_confidence({"client_reported": 3}) == "client_reported"
assert _step_cost_confidence({"provider_billed": 2}) == "provider_billed"
assert (
_step_cost_confidence({"client_reported": 2, "provider_billed": 1})
== "provider_billed"
)
# Any token-based estimate (or an unknown confidence) pulls the whole step
# down to an estimate — the header must not over-claim exactness.
assert (
_step_cost_confidence({"client_reported": 5, "estimated_from_tokens": 1})
== "estimated_from_tokens"
)
assert _step_cost_confidence({"estimated_from_tokens": 4}) == "estimated_from_tokens"
assert _step_cost_confidence({"unknown": 1}) == "estimated_from_tokens"
# Boolean counts are not integer counts we trust.
assert _step_cost_confidence({"client_reported": True}) is None
Loading