metergraph-core 0.2.56__tar.gz → 0.2.58__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.
- {metergraph_core-0.2.56/src/metergraph_core.egg-info → metergraph_core-0.2.58}/PKG-INFO +8 -1
- {metergraph_core-0.2.56 → metergraph_core-0.2.58}/README.md +7 -0
- {metergraph_core-0.2.56 → metergraph_core-0.2.58}/pyproject.toml +1 -1
- {metergraph_core-0.2.56 → metergraph_core-0.2.58}/src/metergraph_core/__init__.py +2 -0
- {metergraph_core-0.2.56 → metergraph_core-0.2.58}/src/metergraph_core/catalog.py +16 -6
- {metergraph_core-0.2.56 → metergraph_core-0.2.58}/src/metergraph_core/data/models.yaml +78 -1
- {metergraph_core-0.2.56 → metergraph_core-0.2.58}/src/metergraph_core/data/prices.yaml +11 -0
- {metergraph_core-0.2.56 → metergraph_core-0.2.58}/src/metergraph_core/loader.py +1 -0
- {metergraph_core-0.2.56 → metergraph_core-0.2.58}/src/metergraph_core/models.py +68 -0
- {metergraph_core-0.2.56 → metergraph_core-0.2.58/src/metergraph_core.egg-info}/PKG-INFO +8 -1
- {metergraph_core-0.2.56 → metergraph_core-0.2.58}/MANIFEST.in +0 -0
- {metergraph_core-0.2.56 → metergraph_core-0.2.58}/setup.cfg +0 -0
- {metergraph_core-0.2.56 → metergraph_core-0.2.58}/src/metergraph_core/billing.py +0 -0
- {metergraph_core-0.2.56 → metergraph_core-0.2.58}/src/metergraph_core/retrieval.py +0 -0
- {metergraph_core-0.2.56 → metergraph_core-0.2.58}/src/metergraph_core.egg-info/SOURCES.txt +0 -0
- {metergraph_core-0.2.56 → metergraph_core-0.2.58}/src/metergraph_core.egg-info/dependency_links.txt +0 -0
- {metergraph_core-0.2.56 → metergraph_core-0.2.58}/src/metergraph_core.egg-info/requires.txt +0 -0
- {metergraph_core-0.2.56 → metergraph_core-0.2.58}/src/metergraph_core.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: metergraph-core
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.58
|
|
4
4
|
Summary: Reusable MeterGraph catalog and deterministic billing engine
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
Requires-Python: >=3.10
|
|
@@ -109,6 +109,13 @@ IDs may intentionally repeat across execution profiles when gateway and
|
|
|
109
109
|
Bedrock use different physical routes; each route therefore also has a unique
|
|
110
110
|
internal `key`.
|
|
111
111
|
|
|
112
|
+
A model entry may record `released`, the publisher's general-availability
|
|
113
|
+
date as an ISO date. `models.release_date(canonical_id, load_catalog())`
|
|
114
|
+
returns that date with basis `released`, or, when none is recorded, the
|
|
115
|
+
earliest `effective_from` of the model's catalog prices with basis
|
|
116
|
+
`first_price`, so a consumer can tell a launch date from a pricing date
|
|
117
|
+
without computing the fallback itself.
|
|
118
|
+
|
|
112
119
|
Use `validate_model_registry(models, load_catalog())` to verify that every
|
|
113
120
|
route's provider-facing model ID is declared on its exact pricing channel,
|
|
114
121
|
resolves to its canonical model, and has an active price on the registry
|
|
@@ -97,6 +97,13 @@ IDs may intentionally repeat across execution profiles when gateway and
|
|
|
97
97
|
Bedrock use different physical routes; each route therefore also has a unique
|
|
98
98
|
internal `key`.
|
|
99
99
|
|
|
100
|
+
A model entry may record `released`, the publisher's general-availability
|
|
101
|
+
date as an ISO date. `models.release_date(canonical_id, load_catalog())`
|
|
102
|
+
returns that date with basis `released`, or, when none is recorded, the
|
|
103
|
+
earliest `effective_from` of the model's catalog prices with basis
|
|
104
|
+
`first_price`, so a consumer can tell a launch date from a pricing date
|
|
105
|
+
without computing the fallback itself.
|
|
106
|
+
|
|
100
107
|
Use `validate_model_registry(models, load_catalog())` to verify that every
|
|
101
108
|
route's provider-facing model ID is declared on its exact pricing channel,
|
|
102
109
|
resolves to its canonical model, and has an active price on the registry
|
|
@@ -32,6 +32,7 @@ from .models import (
|
|
|
32
32
|
ModelRegistryError,
|
|
33
33
|
ModelRoute,
|
|
34
34
|
OfferGroup,
|
|
35
|
+
ReleaseDate,
|
|
35
36
|
load_model_registry,
|
|
36
37
|
parse_model_registry,
|
|
37
38
|
validate_model_registry,
|
|
@@ -60,6 +61,7 @@ __all__ = [
|
|
|
60
61
|
"ModelRegistryError",
|
|
61
62
|
"ModelRoute",
|
|
62
63
|
"OfferGroup",
|
|
64
|
+
"ReleaseDate",
|
|
63
65
|
"GatewayBillingEvidence",
|
|
64
66
|
"Price",
|
|
65
67
|
"ResolvedPrice",
|
|
@@ -209,19 +209,24 @@ class Price:
|
|
|
209
209
|
# imply one: google-vertex-ai serves Anthropic's models beside Google's,
|
|
210
210
|
# and the two report cache reads differently.
|
|
211
211
|
publisher: str | None = None
|
|
212
|
+
# A fixed fee charged once per call on top of tokens, in USD per 1,000
|
|
213
|
+
# calls: a gateway billing a model's built-in search per request.
|
|
214
|
+
request_fee_per_1k_usd: Decimal | None = None
|
|
212
215
|
|
|
213
216
|
|
|
214
217
|
@dataclass(frozen=True, slots=True)
|
|
215
218
|
class CostComponents:
|
|
216
|
-
"""A priced call's cost by what it paid for. The
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
219
|
+
"""A priced call's cost by what it paid for. The parts sum to the call's
|
|
220
|
+
``cost_usd`` exactly: each is quantized and the rounding residue lands in
|
|
221
|
+
the input part, so a consumer that stores them can rebuild the total
|
|
222
|
+
without a second rounding. ``request_usd`` is a per-call fee, zero on
|
|
223
|
+
every row that has none."""
|
|
220
224
|
|
|
221
225
|
input_usd: Decimal
|
|
222
226
|
output_usd: Decimal
|
|
223
227
|
cache_read_usd: Decimal
|
|
224
228
|
cache_write_usd: Decimal
|
|
229
|
+
request_usd: Decimal = Decimal("0")
|
|
225
230
|
|
|
226
231
|
|
|
227
232
|
@dataclass(frozen=True, slots=True)
|
|
@@ -456,15 +461,20 @@ def _price_tokens(
|
|
|
456
461
|
)
|
|
457
462
|
if rules.get("uncaptured_fees"):
|
|
458
463
|
reasons.append("uncaptured_fees")
|
|
464
|
+
request_usd = (
|
|
465
|
+
Decimal("0")
|
|
466
|
+
if price.request_fee_per_1k_usd is None
|
|
467
|
+
else price.request_fee_per_1k_usd / Decimal(1000)
|
|
468
|
+
)
|
|
459
469
|
|
|
460
470
|
# The total is rounded once, as it always was; the parts are rounded
|
|
461
471
|
# each and the residue goes to input, so they sum to the total exactly.
|
|
462
|
-
cost = (input_usd + output_usd + cache_read_usd + cache_write_usd).quantize(
|
|
472
|
+
cost = (input_usd + output_usd + cache_read_usd + cache_write_usd + request_usd).quantize(
|
|
463
473
|
_COST_QUANTUM, rounding=ROUND_HALF_UP
|
|
464
474
|
)
|
|
465
475
|
parts = [
|
|
466
476
|
part.quantize(_COST_QUANTUM, rounding=ROUND_HALF_UP)
|
|
467
|
-
for part in (input_usd, output_usd, cache_read_usd, cache_write_usd)
|
|
477
|
+
for part in (input_usd, output_usd, cache_read_usd, cache_write_usd, request_usd)
|
|
468
478
|
]
|
|
469
479
|
parts[0] += cost - sum(parts)
|
|
470
480
|
return cost, reasons, CostComponents(*parts)
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
version: '2026-10-
|
|
1
|
+
version: '2026-10-09'
|
|
2
2
|
models:
|
|
3
3
|
- canonical_id: openai/gpt-5.6-sol
|
|
4
4
|
display_name: GPT-5.6 Sol
|
|
5
5
|
publisher: openai
|
|
6
|
+
released: '2026-07-09' # https://x.com/OpenAI/status/2074704958419792299
|
|
6
7
|
routes:
|
|
7
8
|
- key: default:openai/gpt-5.6-sol
|
|
8
9
|
id: openai/gpt-5.6-sol
|
|
@@ -29,6 +30,7 @@ models:
|
|
|
29
30
|
- canonical_id: openai/gpt-5.6-luna
|
|
30
31
|
display_name: GPT-5.6 Luna
|
|
31
32
|
publisher: openai
|
|
33
|
+
released: '2026-07-09' # https://x.com/OpenAI/status/2074704958419792299
|
|
32
34
|
routes:
|
|
33
35
|
- key: default:openai/gpt-5.6-luna
|
|
34
36
|
id: openai/gpt-5.6-luna
|
|
@@ -55,6 +57,7 @@ models:
|
|
|
55
57
|
- canonical_id: openai/gpt-6-luna
|
|
56
58
|
display_name: GPT-6 Luna
|
|
57
59
|
publisher: openai
|
|
60
|
+
released: '2026-09-22' # https://community.openai.com/t/announcing-gpt-6-sol-and-gpt-6-luna-in-the-api-codex-and-chatgpt/1399925
|
|
58
61
|
routes:
|
|
59
62
|
- key: default:openai/gpt-6-luna
|
|
60
63
|
id: openai/gpt-6-luna
|
|
@@ -66,6 +69,7 @@ models:
|
|
|
66
69
|
- canonical_id: openai/gpt-6-sol
|
|
67
70
|
display_name: GPT-6 Sol
|
|
68
71
|
publisher: openai
|
|
72
|
+
released: '2026-09-22' # https://community.openai.com/t/announcing-gpt-6-sol-and-gpt-6-luna-in-the-api-codex-and-chatgpt/1399925
|
|
69
73
|
routes:
|
|
70
74
|
- key: default:openai/gpt-6-sol
|
|
71
75
|
id: openai/gpt-6-sol
|
|
@@ -77,6 +81,7 @@ models:
|
|
|
77
81
|
- canonical_id: openai/gpt-6-astra
|
|
78
82
|
display_name: GPT-6 Astra
|
|
79
83
|
publisher: openai
|
|
84
|
+
released: '2026-09-04' # https://en.wikipedia.org/wiki/GPT-6_Astra
|
|
80
85
|
routes:
|
|
81
86
|
- key: default:openai/gpt-6-astra
|
|
82
87
|
id: openai/gpt-6-astra
|
|
@@ -88,6 +93,7 @@ models:
|
|
|
88
93
|
- canonical_id: openai/gpt-5-mini
|
|
89
94
|
display_name: GPT-5 Mini
|
|
90
95
|
publisher: openai
|
|
96
|
+
released: '2025-08-07' # https://openai.com/index/introducing-gpt-5/
|
|
91
97
|
routes:
|
|
92
98
|
- key: default:openai/gpt-5-mini
|
|
93
99
|
id: openai/gpt-5-mini
|
|
@@ -99,6 +105,7 @@ models:
|
|
|
99
105
|
- canonical_id: openai/gpt-5.6-terra
|
|
100
106
|
display_name: GPT-5.6 Terra
|
|
101
107
|
publisher: openai
|
|
108
|
+
released: '2026-07-09' # https://x.com/OpenAI/status/2074704958419792299
|
|
102
109
|
routes:
|
|
103
110
|
- key: default:openai/gpt-5.6-terra
|
|
104
111
|
id: openai/gpt-5.6-terra
|
|
@@ -125,6 +132,7 @@ models:
|
|
|
125
132
|
- canonical_id: anthropic/claude-opus-5
|
|
126
133
|
display_name: Claude Opus 5
|
|
127
134
|
publisher: anthropic
|
|
135
|
+
released: '2026-07-24' # https://github.com/jqueryscript/anthropic-claude-timeline
|
|
128
136
|
routes:
|
|
129
137
|
- key: default:anthropic/claude-opus-5
|
|
130
138
|
id: anthropic/claude-opus-5
|
|
@@ -144,6 +152,7 @@ models:
|
|
|
144
152
|
- canonical_id: anthropic/claude-sonnet-5
|
|
145
153
|
display_name: Claude Sonnet 5
|
|
146
154
|
publisher: anthropic
|
|
155
|
+
released: '2026-06-30' # https://github.com/jqueryscript/anthropic-claude-timeline
|
|
147
156
|
routes:
|
|
148
157
|
- key: default:anthropic/claude-sonnet-5
|
|
149
158
|
id: anthropic/claude-sonnet-5
|
|
@@ -170,6 +179,7 @@ models:
|
|
|
170
179
|
- canonical_id: anthropic/claude-fable-5
|
|
171
180
|
display_name: Claude Fable 5
|
|
172
181
|
publisher: anthropic
|
|
182
|
+
released: '2026-06-09' # https://github.com/jqueryscript/anthropic-claude-timeline
|
|
173
183
|
routes:
|
|
174
184
|
- key: default:anthropic/claude-fable-5
|
|
175
185
|
id: anthropic/claude-fable-5
|
|
@@ -181,6 +191,7 @@ models:
|
|
|
181
191
|
- canonical_id: anthropic/claude-fable-5.1
|
|
182
192
|
display_name: Claude Fable 5.1
|
|
183
193
|
publisher: anthropic
|
|
194
|
+
released: '2026-09-01' # https://www.anthropic.com/claude/fable
|
|
184
195
|
routes:
|
|
185
196
|
- key: default:anthropic/claude-fable-5.1
|
|
186
197
|
id: anthropic/claude-fable-5.1
|
|
@@ -192,6 +203,7 @@ models:
|
|
|
192
203
|
- canonical_id: google/gemini-3.1-pro-preview
|
|
193
204
|
display_name: Gemini 3.1 Pro Preview
|
|
194
205
|
publisher: google
|
|
206
|
+
released: '2026-02-19' # https://en.wikipedia.org/wiki/Gemini_(language_model)
|
|
195
207
|
routes:
|
|
196
208
|
- key: default:google/gemini-3.1-pro-preview
|
|
197
209
|
id: google/gemini-3.1-pro-preview
|
|
@@ -203,6 +215,7 @@ models:
|
|
|
203
215
|
- canonical_id: google/gemini-3.6-flash
|
|
204
216
|
display_name: Gemini 3.6 Flash
|
|
205
217
|
publisher: google
|
|
218
|
+
released: '2026-07-21' # https://docs.cloud.google.com/gemini-enterprise-agent-platform/models/gemini/3-6-flash
|
|
206
219
|
routes:
|
|
207
220
|
- key: default:google/gemini-3.6-flash
|
|
208
221
|
id: google/gemini-3.6-flash
|
|
@@ -214,6 +227,7 @@ models:
|
|
|
214
227
|
- canonical_id: google/gemini-3.8-flash
|
|
215
228
|
display_name: Gemini 3.8 Flash
|
|
216
229
|
publisher: google
|
|
230
|
+
released: '2026-09-02' # https://emergent.sh/news/google-launches-gemini-3-8-flash-third-flash
|
|
217
231
|
routes:
|
|
218
232
|
- key: default:google/gemini-3.8-flash
|
|
219
233
|
id: google/gemini-3.8-flash
|
|
@@ -225,6 +239,7 @@ models:
|
|
|
225
239
|
- canonical_id: google/gemini-3.7-flash
|
|
226
240
|
display_name: Gemini 3.7 Flash
|
|
227
241
|
publisher: google
|
|
242
|
+
released: '2026-08-13' # https://ai.google.dev/gemini-api/docs/models/gemini-3.7-flash
|
|
228
243
|
routes:
|
|
229
244
|
- key: default:google/gemini-3.7-flash
|
|
230
245
|
id: google/gemini-3.7-flash
|
|
@@ -236,6 +251,7 @@ models:
|
|
|
236
251
|
- canonical_id: google/gemini-3.5-flash
|
|
237
252
|
display_name: Gemini 3.5 Flash
|
|
238
253
|
publisher: google
|
|
254
|
+
released: '2026-05-19' # https://docs.cloud.google.com/gemini-enterprise-agent-platform/models/gemini/3-5-flash
|
|
239
255
|
routes:
|
|
240
256
|
- key: default:google/gemini-3.5-flash
|
|
241
257
|
id: google/gemini-3.5-flash
|
|
@@ -247,6 +263,7 @@ models:
|
|
|
247
263
|
- canonical_id: google/gemini-3.5-flash-lite
|
|
248
264
|
display_name: Gemini 3.5 Flash-Lite
|
|
249
265
|
publisher: google
|
|
266
|
+
released: '2026-07-21' # https://datanorth.ai/news/google-releases-gemini-3-5-flash
|
|
250
267
|
routes:
|
|
251
268
|
- key: default:google/gemini-3.5-flash-lite
|
|
252
269
|
id: google/gemini-3.5-flash-lite
|
|
@@ -258,6 +275,7 @@ models:
|
|
|
258
275
|
- canonical_id: google/gemini-3.1-flash-lite
|
|
259
276
|
display_name: Gemini 3.1 Flash-Lite
|
|
260
277
|
publisher: google
|
|
278
|
+
released: '2026-05-07' # https://cloud.google.com/blog/products/ai-machine-learning/gemini-3-1-flash-lite-is-now-generally-available
|
|
261
279
|
routes:
|
|
262
280
|
- key: default:google/gemini-3.1-flash-lite
|
|
263
281
|
id: google/gemini-3.1-flash-lite
|
|
@@ -269,6 +287,7 @@ models:
|
|
|
269
287
|
- canonical_id: google/gemma-4-31b-it
|
|
270
288
|
display_name: Gemma 4 31B
|
|
271
289
|
publisher: google
|
|
290
|
+
released: '2026-04-02' # https://ai.google.dev/gemma/docs/releases
|
|
272
291
|
routes:
|
|
273
292
|
- key: default:google/gemma-4-31b-it
|
|
274
293
|
id: google/gemma-4-31b-it
|
|
@@ -280,6 +299,7 @@ models:
|
|
|
280
299
|
- canonical_id: google/gemma-4-26b-a4b-it
|
|
281
300
|
display_name: Gemma 4 26B
|
|
282
301
|
publisher: google
|
|
302
|
+
released: '2026-04-02' # https://ai.google.dev/gemma/docs/releases
|
|
283
303
|
routes:
|
|
284
304
|
- key: default:google/gemma-4-26b-a4b-it
|
|
285
305
|
id: google/gemma-4-26b-a4b-it
|
|
@@ -291,6 +311,7 @@ models:
|
|
|
291
311
|
- canonical_id: moonshotai/kimi-k3
|
|
292
312
|
display_name: Kimi K3
|
|
293
313
|
publisher: moonshotai
|
|
314
|
+
released: '2026-07-16' # https://en.wikipedia.org/wiki/Kimi_(AI)
|
|
294
315
|
routes:
|
|
295
316
|
- key: default:moonshotai/kimi-k3
|
|
296
317
|
id: moonshotai/kimi-k3
|
|
@@ -302,6 +323,7 @@ models:
|
|
|
302
323
|
- canonical_id: moonshotai/kimi-k2.5
|
|
303
324
|
display_name: Kimi K2.5
|
|
304
325
|
publisher: moonshotai
|
|
326
|
+
released: '2026-01-27' # https://en.wikipedia.org/wiki/Kimi_(chatbot)
|
|
305
327
|
routes:
|
|
306
328
|
- key: default:moonshotai/kimi-k2.5
|
|
307
329
|
id: moonshotai/kimi-k2.5
|
|
@@ -320,6 +342,7 @@ models:
|
|
|
320
342
|
- canonical_id: minimax/minimax-m3
|
|
321
343
|
display_name: MiniMax M3
|
|
322
344
|
publisher: minimax
|
|
345
|
+
released: '2026-06-01' # https://www.minimax.io/blog/minimax-m3
|
|
323
346
|
routes:
|
|
324
347
|
- key: default:minimax/minimax-m3
|
|
325
348
|
id: minimax/minimax-m3
|
|
@@ -331,6 +354,7 @@ models:
|
|
|
331
354
|
- canonical_id: deepseek/v4-pro
|
|
332
355
|
display_name: DeepSeek V4 Pro
|
|
333
356
|
publisher: deepseek
|
|
357
|
+
released: '2026-08-13' # https://www.yottalabs.ai/post/deepseek-v4-release-date-specs-how-to-access-2026
|
|
334
358
|
routes:
|
|
335
359
|
- key: default:deepseek/deepseek-v4-pro
|
|
336
360
|
id: deepseek/deepseek-v4-pro
|
|
@@ -342,6 +366,7 @@ models:
|
|
|
342
366
|
- canonical_id: deepseek/v4-flash
|
|
343
367
|
display_name: DeepSeek V4 Flash
|
|
344
368
|
publisher: deepseek
|
|
369
|
+
released: '2026-07-31' # https://www.lindy.ai/blog/deepseek-v4-flash
|
|
345
370
|
routes:
|
|
346
371
|
- key: default:deepseek/deepseek-v4-flash
|
|
347
372
|
id: deepseek/deepseek-v4-flash
|
|
@@ -353,6 +378,7 @@ models:
|
|
|
353
378
|
- canonical_id: xai/grok-4.1-fast-reasoning
|
|
354
379
|
display_name: Grok 4.1 Fast Reasoning
|
|
355
380
|
publisher: xai
|
|
381
|
+
released: '2025-11-19' # https://x.ai/news/grok-4-1-fast
|
|
356
382
|
routes:
|
|
357
383
|
- key: default:xai/grok-4.1-fast-reasoning
|
|
358
384
|
id: xai/grok-4.1-fast-reasoning
|
|
@@ -364,6 +390,7 @@ models:
|
|
|
364
390
|
- canonical_id: xai/grok-4.1-fast-non-reasoning
|
|
365
391
|
display_name: Grok 4.1 Fast
|
|
366
392
|
publisher: xai
|
|
393
|
+
released: '2025-11-19' # https://x.ai/news/grok-4-1-fast
|
|
367
394
|
routes:
|
|
368
395
|
- key: default:xai/grok-4.1-fast-non-reasoning
|
|
369
396
|
id: xai/grok-4.1-fast-non-reasoning
|
|
@@ -375,6 +402,7 @@ models:
|
|
|
375
402
|
- canonical_id: mistral/ministral-14b
|
|
376
403
|
display_name: Ministral 3 14B
|
|
377
404
|
publisher: mistral
|
|
405
|
+
released: '2025-12-02' # https://mistral.ai/news/mistral-3
|
|
378
406
|
routes:
|
|
379
407
|
- key: default:mistral/ministral-14b
|
|
380
408
|
id: mistral/ministral-14b
|
|
@@ -386,6 +414,7 @@ models:
|
|
|
386
414
|
- canonical_id: nvidia/nemotron-3-super-120b-a12b
|
|
387
415
|
display_name: Nemotron 3 Super
|
|
388
416
|
publisher: nvidia
|
|
417
|
+
released: '2026-03-11' # https://huggingface.co/nvidia/NVIDIA-Nemotron-3-Super-120B-A12B-BF16
|
|
389
418
|
routes:
|
|
390
419
|
- key: default:nvidia/nemotron-3-super-120b-a12b
|
|
391
420
|
id: nvidia/nemotron-3-super-120b-a12b
|
|
@@ -397,6 +426,7 @@ models:
|
|
|
397
426
|
- canonical_id: zai/glm-5.3-flash
|
|
398
427
|
display_name: GLM 5.3 Flash
|
|
399
428
|
publisher: zai
|
|
429
|
+
released: '2026-08-26' # https://emergent.sh/news/glm-5-3-flash-officially-launched
|
|
400
430
|
routes:
|
|
401
431
|
- key: default:zai/glm-5.3-flash
|
|
402
432
|
id: zai/glm-5.3-flash
|
|
@@ -408,6 +438,7 @@ models:
|
|
|
408
438
|
- canonical_id: deepseek/deepseek-v4.1-flash
|
|
409
439
|
display_name: DeepSeek V4.1 Flash
|
|
410
440
|
publisher: deepseek
|
|
441
|
+
released: '2026-09-10' # https://llm-stats.com/models/deepseek-v4.1-flash
|
|
411
442
|
routes:
|
|
412
443
|
- key: default:deepseek/deepseek-v4.1-flash
|
|
413
444
|
id: deepseek/deepseek-v4.1-flash
|
|
@@ -419,6 +450,7 @@ models:
|
|
|
419
450
|
- canonical_id: alibaba/qwen3.8-flash
|
|
420
451
|
display_name: Qwen 3.8 Flash
|
|
421
452
|
publisher: alibaba
|
|
453
|
+
released: '2026-08-26' # https://thenewstack.io/qwen38-flash-previews-qwen4/
|
|
422
454
|
routes:
|
|
423
455
|
- key: default:alibaba/qwen3.8-flash
|
|
424
456
|
id: alibaba/qwen3.8-flash
|
|
@@ -430,6 +462,7 @@ models:
|
|
|
430
462
|
- canonical_id: inception/mercury-2.5
|
|
431
463
|
display_name: Mercury 2.5
|
|
432
464
|
publisher: inception
|
|
465
|
+
released: '2026-09-08' # https://runtimewire.com/article/inception-mercury-2-5-diffusion-language-model-launch
|
|
433
466
|
routes:
|
|
434
467
|
- key: default:inception/mercury-2.5
|
|
435
468
|
id: inception/mercury-2.5
|
|
@@ -441,6 +474,7 @@ models:
|
|
|
441
474
|
- canonical_id: openai/gpt-5.4-mini
|
|
442
475
|
display_name: GPT-5.4 Mini
|
|
443
476
|
publisher: openai
|
|
477
|
+
released: '2026-03-17' # https://community.openai.com/t/introducing-gpt-5-4-mini-and-nano-our-most-capable-small-models-yet/1377015
|
|
444
478
|
routes:
|
|
445
479
|
- key: default:openai/gpt-5.4-mini
|
|
446
480
|
id: openai/gpt-5.4-mini
|
|
@@ -460,6 +494,7 @@ models:
|
|
|
460
494
|
- canonical_id: openai/gpt-5.4-nano
|
|
461
495
|
display_name: GPT-5.4 Nano
|
|
462
496
|
publisher: openai
|
|
497
|
+
released: '2026-03-17' # https://community.openai.com/t/introducing-gpt-5-4-mini-and-nano-our-most-capable-small-models-yet/1377015
|
|
463
498
|
routes:
|
|
464
499
|
- key: default:openai/gpt-5.4-nano
|
|
465
500
|
id: openai/gpt-5.4-nano
|
|
@@ -479,6 +514,7 @@ models:
|
|
|
479
514
|
- canonical_id: anthropic/claude-opus-4.8
|
|
480
515
|
display_name: Claude Opus 4.8
|
|
481
516
|
publisher: anthropic
|
|
517
|
+
released: '2026-05-28' # https://hidekazu-konishi.com/entry/anthropic_claude_model_release_timeline.html
|
|
482
518
|
routes:
|
|
483
519
|
- key: default:anthropic/claude-opus-4.8
|
|
484
520
|
id: anthropic/claude-opus-4.8
|
|
@@ -498,6 +534,7 @@ models:
|
|
|
498
534
|
- canonical_id: anthropic/claude-haiku-4.5
|
|
499
535
|
display_name: Claude Haiku 4.5
|
|
500
536
|
publisher: anthropic
|
|
537
|
+
released: '2025-10-15' # https://www.anthropic.com/news/claude-haiku-4-5
|
|
501
538
|
routes:
|
|
502
539
|
- key: default:anthropic/claude-haiku-4.5
|
|
503
540
|
id: anthropic/claude-haiku-4.5
|
|
@@ -517,6 +554,7 @@ models:
|
|
|
517
554
|
- canonical_id: fireworks/glm-5p2
|
|
518
555
|
display_name: GLM 5.2
|
|
519
556
|
publisher: fireworks
|
|
557
|
+
released: '2026-06-13' # https://pandaily.com/zhipu-ai-glm-5-dot-2-open-source-mit-jun2026
|
|
520
558
|
routes:
|
|
521
559
|
- key: default:fireworks:accounts/fireworks/models/glm-5p2
|
|
522
560
|
id: fireworks:accounts/fireworks/models/glm-5p2
|
|
@@ -528,6 +566,7 @@ models:
|
|
|
528
566
|
- canonical_id: fireworks/qwen3p7-plus
|
|
529
567
|
display_name: Qwen 3.7 Plus
|
|
530
568
|
publisher: fireworks
|
|
569
|
+
released: '2026-06-01' # https://www.vals.ai/models/alibaba_qwen3.7-plus
|
|
531
570
|
routes:
|
|
532
571
|
- key: default:fireworks:accounts/fireworks/models/qwen3p7-plus
|
|
533
572
|
id: fireworks:accounts/fireworks/models/qwen3p7-plus
|
|
@@ -539,6 +578,7 @@ models:
|
|
|
539
578
|
- canonical_id: openai/gpt-5.4
|
|
540
579
|
display_name: GPT-5.4
|
|
541
580
|
publisher: openai
|
|
581
|
+
released: '2026-03-05' # https://en.wikipedia.org/wiki/GPT-5.4
|
|
542
582
|
routes:
|
|
543
583
|
- key: default:openai:gpt-5.4
|
|
544
584
|
id: openai:gpt-5.4
|
|
@@ -551,6 +591,7 @@ models:
|
|
|
551
591
|
- canonical_id: google/gemma-3-27b-it
|
|
552
592
|
display_name: Gemma 3 27B
|
|
553
593
|
publisher: google
|
|
594
|
+
released: '2025-03-12' # https://blog.google/technology/developers/gemma-3/
|
|
554
595
|
routes:
|
|
555
596
|
- key: bedrock:google/gemma-3-27b-it
|
|
556
597
|
id: google/gemma-3-27b-it
|
|
@@ -562,6 +603,7 @@ models:
|
|
|
562
603
|
- canonical_id: deepseek/v3.2
|
|
563
604
|
display_name: DeepSeek V3.2
|
|
564
605
|
publisher: deepseek
|
|
606
|
+
released: '2025-12-01' # https://en.wikipedia.org/wiki/DeepSeek_(chatbot)
|
|
565
607
|
routes:
|
|
566
608
|
- key: bedrock:deepseek/deepseek-v3.2
|
|
567
609
|
id: deepseek/deepseek-v3.2
|
|
@@ -573,6 +615,7 @@ models:
|
|
|
573
615
|
- canonical_id: deepseek/v3.1
|
|
574
616
|
display_name: DeepSeek V3.1
|
|
575
617
|
publisher: deepseek
|
|
618
|
+
released: '2025-08-21' # https://en.wikipedia.org/wiki/DeepSeek_(chatbot)
|
|
576
619
|
routes:
|
|
577
620
|
- key: bedrock:deepseek/deepseek-v3.1
|
|
578
621
|
id: deepseek/deepseek-v3.1
|
|
@@ -584,6 +627,7 @@ models:
|
|
|
584
627
|
- canonical_id: anthropic/claude-opus-5.5
|
|
585
628
|
display_name: Claude Opus 5.5
|
|
586
629
|
publisher: anthropic
|
|
630
|
+
released: '2026-09-22' # https://www.anthropic.com/claude-opus-5-5
|
|
587
631
|
routes:
|
|
588
632
|
- key: default:anthropic/claude-opus-5.5
|
|
589
633
|
id: anthropic/claude-opus-5.5
|
|
@@ -595,6 +639,7 @@ models:
|
|
|
595
639
|
- canonical_id: anthropic/claude-sonnet-5.5
|
|
596
640
|
display_name: Claude Sonnet 5.5
|
|
597
641
|
publisher: anthropic
|
|
642
|
+
released: '2026-09-28' # https://www.anthropic.com/claude/sonnet
|
|
598
643
|
routes:
|
|
599
644
|
- key: default:anthropic/claude-sonnet-5.5
|
|
600
645
|
id: anthropic/claude-sonnet-5.5
|
|
@@ -606,6 +651,7 @@ models:
|
|
|
606
651
|
- canonical_id: openai/gpt-6.1-sol
|
|
607
652
|
display_name: GPT-6.1 Sol
|
|
608
653
|
publisher: openai
|
|
654
|
+
released: '2026-09-29' # https://www.sitepoint.com/gpt-6-1-sol-developers-pricing-quickstart/
|
|
609
655
|
routes:
|
|
610
656
|
- key: default:openai/gpt-6.1-sol
|
|
611
657
|
id: openai/gpt-6.1-sol
|
|
@@ -617,6 +663,7 @@ models:
|
|
|
617
663
|
- canonical_id: xai/grok-4.7
|
|
618
664
|
display_name: Grok 4.7
|
|
619
665
|
publisher: xai
|
|
666
|
+
released: '2026-09-21' # https://x.ai/news
|
|
620
667
|
routes:
|
|
621
668
|
- key: default:xai/grok-4.7
|
|
622
669
|
id: xai/grok-4.7
|
|
@@ -628,6 +675,7 @@ models:
|
|
|
628
675
|
- canonical_id: moonshotai/kimi-k2.7-code
|
|
629
676
|
display_name: Kimi K2.7 Code
|
|
630
677
|
publisher: moonshotai
|
|
678
|
+
released: '2026-06-12' # https://www.marktechpost.com/2026/06/12/moonshot-ai-releases-kimi-k2-7-code-a-coding-model-reporting-21-8-on-kimi-code-bench-v2-over-k2-6/
|
|
631
679
|
routes:
|
|
632
680
|
- key: default:moonshotai/kimi-k2.7-code
|
|
633
681
|
id: moonshotai/kimi-k2.7-code
|
|
@@ -639,6 +687,7 @@ models:
|
|
|
639
687
|
- canonical_id: zai/glm-5.3
|
|
640
688
|
display_name: GLM 5.3
|
|
641
689
|
publisher: zai
|
|
690
|
+
released: '2026-08-14' # https://emergent.sh/news/glm-53-officially-launched-1e1dc
|
|
642
691
|
routes:
|
|
643
692
|
- key: default:zai/glm-5.3
|
|
644
693
|
id: zai/glm-5.3
|
|
@@ -647,6 +696,30 @@ models:
|
|
|
647
696
|
pricing_channel: vercel-ai-gateway
|
|
648
697
|
execution_profiles:
|
|
649
698
|
- default
|
|
699
|
+
- canonical_id: anthropic/claude-sonnet-4.6
|
|
700
|
+
display_name: Claude Sonnet 4.6
|
|
701
|
+
publisher: anthropic
|
|
702
|
+
released: '2026-02-17' # https://alternativeto.net/news/2026/2/anthropic-s-claude-sonnet-4-6-launches-with-faster-speeds-and-1m-token-context
|
|
703
|
+
routes:
|
|
704
|
+
- key: default:anthropic/claude-sonnet-4.6
|
|
705
|
+
id: anthropic/claude-sonnet-4.6
|
|
706
|
+
provider: vercel
|
|
707
|
+
model_id: anthropic/claude-sonnet-4.6
|
|
708
|
+
pricing_channel: vercel-ai-gateway
|
|
709
|
+
execution_profiles:
|
|
710
|
+
- default
|
|
711
|
+
- canonical_id: xai/grok-4.3
|
|
712
|
+
display_name: Grok 4.3
|
|
713
|
+
publisher: xai
|
|
714
|
+
released: '2026-04-30' # https://artificialanalysis.ai/articles/xai-launches-grok-4-3-with-improved-agentic-performance-and-lower-pricing
|
|
715
|
+
routes:
|
|
716
|
+
- key: default:xai/grok-4.3
|
|
717
|
+
id: xai/grok-4.3
|
|
718
|
+
provider: vercel
|
|
719
|
+
model_id: xai/grok-4.3
|
|
720
|
+
pricing_channel: vercel-ai-gateway
|
|
721
|
+
execution_profiles:
|
|
722
|
+
- default
|
|
650
723
|
execution_profiles:
|
|
651
724
|
- id: default
|
|
652
725
|
routes:
|
|
@@ -705,6 +778,8 @@ execution_profiles:
|
|
|
705
778
|
- default:anthropic:claude-opus-4-8
|
|
706
779
|
- default:anthropic:claude-sonnet-5
|
|
707
780
|
- default:anthropic:claude-haiku-4-5
|
|
781
|
+
- default:anthropic/claude-sonnet-4.6
|
|
782
|
+
- default:xai/grok-4.3
|
|
708
783
|
- id: bedrock
|
|
709
784
|
routes:
|
|
710
785
|
- bedrock:anthropic/claude-sonnet-5
|
|
@@ -762,6 +837,8 @@ offer_groups:
|
|
|
762
837
|
- default:xai/grok-4.7
|
|
763
838
|
- default:moonshotai/kimi-k2.7-code
|
|
764
839
|
- default:zai/glm-5.3
|
|
840
|
+
- default:anthropic/claude-sonnet-4.6
|
|
841
|
+
- default:xai/grok-4.3
|
|
765
842
|
- id: fireworks
|
|
766
843
|
credential: FIREWORKS_API_KEY
|
|
767
844
|
routes:
|
|
@@ -2029,6 +2029,7 @@ models:
|
|
|
2029
2029
|
- {provider: x-ai, alias: grok-latest, channel: xai-api}
|
|
2030
2030
|
- {provider: bedrock, alias: xai.grok-4.3, channel: aws-bedrock}
|
|
2031
2031
|
- {provider: vercel, alias: spacexai/grok-4.3, channel: vercel-ai-gateway}
|
|
2032
|
+
- {provider: xai, alias: xai/grok-4.3, channel: vercel-ai-gateway}
|
|
2032
2033
|
- {provider: litellm, alias: grok-4.3, channel: xai-api}
|
|
2033
2034
|
- {provider: litellm, alias: grok-4.3-latest, channel: xai-api}
|
|
2034
2035
|
- {provider: unknown, alias: grok-4.3, channel: xai-api}
|
|
@@ -2077,6 +2078,7 @@ models:
|
|
|
2077
2078
|
- {provider: litellm, alias: sonar, channel: perplexity-api}
|
|
2078
2079
|
- {provider: perplexity-ai, alias: perplexity/sonar, channel: perplexity-api}
|
|
2079
2080
|
- {provider: unknown, alias: sonar, channel: perplexity-api}
|
|
2081
|
+
- {provider: vercel, alias: perplexity/sonar, channel: vercel-ai-gateway}
|
|
2080
2082
|
prices:
|
|
2081
2083
|
- channel: perplexity-api
|
|
2082
2084
|
region: global
|
|
@@ -2086,6 +2088,15 @@ models:
|
|
|
2086
2088
|
rules:
|
|
2087
2089
|
uncaptured_fees: true
|
|
2088
2090
|
source_url: https://docs.perplexity.ai/docs/getting-started/pricing
|
|
2091
|
+
# The gateway bills Sonar's built-in search per call, so the row carries
|
|
2092
|
+
# it as a request fee and the call is priced in full.
|
|
2093
|
+
- channel: vercel-ai-gateway
|
|
2094
|
+
region: global
|
|
2095
|
+
effective_from: "2026-10-11"
|
|
2096
|
+
input_per_mtok: 0.25
|
|
2097
|
+
output_per_mtok: 2.50
|
|
2098
|
+
request_fee_per_1k_usd: 2.50
|
|
2099
|
+
source_url: https://vercel.com/ai-gateway/models/sonar
|
|
2089
2100
|
|
|
2090
2101
|
- canonical_id: openai/gpt-5-mini
|
|
2091
2102
|
publisher: openai
|
|
@@ -305,6 +305,7 @@ def parse_catalog(
|
|
|
305
305
|
),
|
|
306
306
|
batch_input_per_mtok=_decimal(price.get("batch_input_per_mtok")),
|
|
307
307
|
batch_output_per_mtok=_decimal(price.get("batch_output_per_mtok")),
|
|
308
|
+
request_fee_per_1k_usd=_decimal(price.get("request_fee_per_1k_usd")),
|
|
308
309
|
rules=_freeze(price.get("rules") or {}),
|
|
309
310
|
effective_from=effective_from,
|
|
310
311
|
effective_to=effective_to,
|
|
@@ -76,6 +76,19 @@ class ModelDefinition:
|
|
|
76
76
|
display_name: str
|
|
77
77
|
publisher: str
|
|
78
78
|
routes: tuple[ModelRoute, ...]
|
|
79
|
+
# The publisher's general-availability date, when recorded.
|
|
80
|
+
released: date | None = None
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@dataclass(frozen=True, slots=True)
|
|
84
|
+
class ReleaseDate:
|
|
85
|
+
"""When a model became available, and what that date is based on:
|
|
86
|
+
``released`` is the registry's recorded date; ``first_price`` is the
|
|
87
|
+
earliest price window the catalog has for the model, used when no date
|
|
88
|
+
is recorded."""
|
|
89
|
+
|
|
90
|
+
date: date
|
|
91
|
+
basis: str
|
|
79
92
|
|
|
80
93
|
|
|
81
94
|
@dataclass(frozen=True, slots=True)
|
|
@@ -96,6 +109,36 @@ class ModelRegistry:
|
|
|
96
109
|
def model(self, canonical_id: str) -> ModelDefinition:
|
|
97
110
|
return self.models[canonical_id]
|
|
98
111
|
|
|
112
|
+
def release_date(
|
|
113
|
+
self, canonical_id: str, catalog: LoadedCatalog
|
|
114
|
+
) -> ReleaseDate | None:
|
|
115
|
+
"""The model's release date: recorded when the registry has one,
|
|
116
|
+
otherwise the earliest ``effective_from`` of its catalog prices, or
|
|
117
|
+
None when neither exists. Callers never compute the fallback
|
|
118
|
+
themselves, so every product reads the same answer."""
|
|
119
|
+
model = self.models.get(canonical_id)
|
|
120
|
+
if model is not None and model.released is not None:
|
|
121
|
+
return ReleaseDate(model.released, "released")
|
|
122
|
+
entry = next(
|
|
123
|
+
(
|
|
124
|
+
entry
|
|
125
|
+
for entry in catalog.document.get("models", [])
|
|
126
|
+
if entry.get("canonical_id") == canonical_id
|
|
127
|
+
),
|
|
128
|
+
None,
|
|
129
|
+
)
|
|
130
|
+
# A price window starts on a date or a timestamp; the catalog accepts
|
|
131
|
+
# both, so both are read here.
|
|
132
|
+
first_price = min(
|
|
133
|
+
(
|
|
134
|
+
_window_day(price["effective_from"])
|
|
135
|
+
for price in (entry or {}).get("prices", [])
|
|
136
|
+
if price.get("effective_from") is not None
|
|
137
|
+
),
|
|
138
|
+
default=None,
|
|
139
|
+
)
|
|
140
|
+
return None if first_price is None else ReleaseDate(first_price, "first_price")
|
|
141
|
+
|
|
99
142
|
def route(self, route_key: str) -> ModelRoute:
|
|
100
143
|
return self.routes[route_key]
|
|
101
144
|
|
|
@@ -152,6 +195,29 @@ def _unique_text_list(value: Any, field: str) -> tuple[str, ...]:
|
|
|
152
195
|
return items
|
|
153
196
|
|
|
154
197
|
|
|
198
|
+
def _window_day(value: Any) -> date:
|
|
199
|
+
"""The calendar day a catalog price window starts, from a date or a
|
|
200
|
+
timestamp as the catalog loader accepts them."""
|
|
201
|
+
if isinstance(value, datetime):
|
|
202
|
+
return value.date()
|
|
203
|
+
if isinstance(value, date):
|
|
204
|
+
return value
|
|
205
|
+
return datetime.fromisoformat(str(value)).date()
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def _optional_date(value: Any, field: str) -> date | None:
|
|
209
|
+
"""An ISO calendar date, or None when absent. A datetime is not accepted:
|
|
210
|
+
a release is a day, and the registry version is already a date."""
|
|
211
|
+
if value is None:
|
|
212
|
+
return None
|
|
213
|
+
if isinstance(value, date) and not isinstance(value, datetime):
|
|
214
|
+
return value
|
|
215
|
+
try:
|
|
216
|
+
return date.fromisoformat(str(value))
|
|
217
|
+
except ValueError as exc:
|
|
218
|
+
raise ModelRegistryError(f"{field} must be an ISO date") from exc
|
|
219
|
+
|
|
220
|
+
|
|
155
221
|
def _registry_version_date(version: str) -> date:
|
|
156
222
|
date_value, separator, revision = version.partition(".")
|
|
157
223
|
try:
|
|
@@ -194,6 +260,7 @@ def parse_model_registry(document: Any) -> ModelRegistry:
|
|
|
194
260
|
raise ModelRegistryError(
|
|
195
261
|
f"{canonical_id}: publisher {publisher!r} does not match canonical id"
|
|
196
262
|
)
|
|
263
|
+
released = _optional_date(model.get("released"), f"{canonical_id}: released")
|
|
197
264
|
model_routes: list[ModelRoute] = []
|
|
198
265
|
route_values = _list(model.get("routes"), f"{canonical_id}: routes")
|
|
199
266
|
if not route_values:
|
|
@@ -263,6 +330,7 @@ def parse_model_registry(document: Any) -> ModelRegistry:
|
|
|
263
330
|
display_name=display_name,
|
|
264
331
|
publisher=publisher,
|
|
265
332
|
routes=tuple(model_routes),
|
|
333
|
+
released=released,
|
|
266
334
|
)
|
|
267
335
|
|
|
268
336
|
execution_profiles: dict[str, tuple[str, ...]] = {}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: metergraph-core
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.58
|
|
4
4
|
Summary: Reusable MeterGraph catalog and deterministic billing engine
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
Requires-Python: >=3.10
|
|
@@ -109,6 +109,13 @@ IDs may intentionally repeat across execution profiles when gateway and
|
|
|
109
109
|
Bedrock use different physical routes; each route therefore also has a unique
|
|
110
110
|
internal `key`.
|
|
111
111
|
|
|
112
|
+
A model entry may record `released`, the publisher's general-availability
|
|
113
|
+
date as an ISO date. `models.release_date(canonical_id, load_catalog())`
|
|
114
|
+
returns that date with basis `released`, or, when none is recorded, the
|
|
115
|
+
earliest `effective_from` of the model's catalog prices with basis
|
|
116
|
+
`first_price`, so a consumer can tell a launch date from a pricing date
|
|
117
|
+
without computing the fallback itself.
|
|
118
|
+
|
|
112
119
|
Use `validate_model_registry(models, load_catalog())` to verify that every
|
|
113
120
|
route's provider-facing model ID is declared on its exact pricing channel,
|
|
114
121
|
resolves to its canonical model, and has an active price on the registry
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{metergraph_core-0.2.56 → metergraph_core-0.2.58}/src/metergraph_core.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
{metergraph_core-0.2.56 → metergraph_core-0.2.58}/src/metergraph_core.egg-info/top_level.txt
RENAMED
|
File without changes
|