metergraph-core 0.2.29__tar.gz → 0.2.30__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: metergraph-core
3
- Version: 0.2.29
3
+ Version: 0.2.30
4
4
  Summary: Reusable MeterGraph catalog and deterministic billing engine
5
5
  License-Expression: Apache-2.0
6
6
  Requires-Python: >=3.10
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "metergraph-core"
3
- version = "0.2.29"
3
+ version = "0.2.30"
4
4
  description = "Reusable MeterGraph catalog and deterministic billing engine"
5
5
  readme = "README.md"
6
6
  license = "Apache-2.0"
@@ -6,11 +6,49 @@ from typing import Any, Mapping
6
6
 
7
7
  from .catalog import CostResult
8
8
 
9
- _OPENROUTER = "openrouter"
10
- _CHAT_COMPLETIONS = "chat.completions"
11
- _OPENROUTER_COST_SOURCE = "openrouter.usage.cost"
12
- _OPENROUTER_UPSTREAM_COST_SOURCE = (
13
- "openrouter.usage.cost_details.upstream_inference_cost"
9
+ @dataclass(frozen=True, slots=True)
10
+ class _QualifiedSource:
11
+ """A gateway whose reported amount this module will bill from.
12
+
13
+ Three things have to line up before an amount is believed, because the field
14
+ carrying one is open: a customer's own client can write to it.
15
+
16
+ * The **gateway**, so an amount is attributed to a system we have checked.
17
+ * The **endpoint**, because a gateway prices its endpoints differently and a
18
+ figure is only interpretable alongside the one that produced it.
19
+ * The **source**, naming the field the amount was read from, so a row cannot
20
+ qualify by claiming a gateway name alone.
21
+
22
+ A gateway absent from this table is not distrusted so much as unverified:
23
+ its amount is still recorded, and the catalog still prices the call, so the
24
+ two can be compared before it is added here.
25
+ """
26
+
27
+ gateway: str
28
+ endpoints: frozenset[str]
29
+ cost_source: str
30
+ upstream_cost_source: str | None = None
31
+
32
+
33
+ # Each entry reconciles against the providers' own published rates, including
34
+ # the per-request and per-query charges a token rate cannot express. Portkey was
35
+ # checked across a 46,241-call export: its figure matches published rates for
36
+ # Anthropic, xAI and Perplexity to the cent, and for OpenAI once the per-search
37
+ # charge is counted -- 20,590 of 20,590 rows, exactly.
38
+ _QUALIFIED_SOURCES = (
39
+ _QualifiedSource(
40
+ gateway="openrouter",
41
+ endpoints=frozenset({"chat.completions"}),
42
+ cost_source="openrouter.usage.cost",
43
+ upstream_cost_source=(
44
+ "openrouter.usage.cost_details.upstream_inference_cost"
45
+ ),
46
+ ),
47
+ _QualifiedSource(
48
+ gateway="portkey",
49
+ endpoints=frozenset({"chat.completions", "responses"}),
50
+ cost_source="portkey.cost",
51
+ ),
14
52
  )
15
53
 
16
54
 
@@ -82,11 +120,12 @@ def normalize_gateway_evidence(row: Mapping[str, Any]) -> GatewayBillingEvidence
82
120
  )
83
121
 
84
122
 
85
- def _is_openrouter_chat_completions(evidence: GatewayBillingEvidence) -> bool:
86
- return (
87
- evidence.gateway == _OPENROUTER
88
- and evidence.endpoint == _CHAT_COMPLETIONS
89
- )
123
+ def _qualified_source(evidence: GatewayBillingEvidence) -> _QualifiedSource | None:
124
+ """The entry this row's gateway and endpoint match, if any."""
125
+ for source in _QUALIFIED_SOURCES:
126
+ if evidence.gateway == source.gateway and evidence.endpoint in source.endpoints:
127
+ return source
128
+ return None
90
129
 
91
130
 
92
131
  def resolve_billing(
@@ -95,18 +134,18 @@ def resolve_billing(
95
134
  ) -> BillingDecision:
96
135
  """Select effective cost without combining independent reported amounts."""
97
136
 
98
- qualified_openrouter = _is_openrouter_chat_completions(evidence)
137
+ qualified = _qualified_source(evidence)
99
138
  reported_cost = (
100
139
  evidence.reported_cost_usd
101
- if qualified_openrouter
102
- and evidence.reported_cost_source == _OPENROUTER_COST_SOURCE
140
+ if qualified is not None
141
+ and evidence.reported_cost_source == qualified.cost_source
103
142
  else None
104
143
  )
105
144
  upstream_cost = (
106
145
  evidence.reported_upstream_cost_usd
107
- if qualified_openrouter
108
- and evidence.reported_upstream_cost_source
109
- == _OPENROUTER_UPSTREAM_COST_SOURCE
146
+ if qualified is not None
147
+ and qualified.upstream_cost_source is not None
148
+ and evidence.reported_upstream_cost_source == qualified.upstream_cost_source
110
149
  else None
111
150
  )
112
151
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: metergraph-core
3
- Version: 0.2.29
3
+ Version: 0.2.30
4
4
  Summary: Reusable MeterGraph catalog and deterministic billing engine
5
5
  License-Expression: Apache-2.0
6
6
  Requires-Python: >=3.10