metergraph-core 0.2.54__tar.gz → 0.2.56__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.
Files changed (18) hide show
  1. {metergraph_core-0.2.54/src/metergraph_core.egg-info → metergraph_core-0.2.56}/PKG-INFO +1 -1
  2. {metergraph_core-0.2.54 → metergraph_core-0.2.56}/pyproject.toml +1 -1
  3. {metergraph_core-0.2.54 → metergraph_core-0.2.56}/src/metergraph_core/__init__.py +8 -0
  4. {metergraph_core-0.2.54 → metergraph_core-0.2.56}/src/metergraph_core/data/models.yaml +53 -1
  5. {metergraph_core-0.2.54 → metergraph_core-0.2.56}/src/metergraph_core/data/prices.yaml +54 -2
  6. {metergraph_core-0.2.54 → metergraph_core-0.2.56}/src/metergraph_core/retrieval.py +93 -0
  7. {metergraph_core-0.2.54 → metergraph_core-0.2.56/src/metergraph_core.egg-info}/PKG-INFO +1 -1
  8. {metergraph_core-0.2.54 → metergraph_core-0.2.56}/MANIFEST.in +0 -0
  9. {metergraph_core-0.2.54 → metergraph_core-0.2.56}/README.md +0 -0
  10. {metergraph_core-0.2.54 → metergraph_core-0.2.56}/setup.cfg +0 -0
  11. {metergraph_core-0.2.54 → metergraph_core-0.2.56}/src/metergraph_core/billing.py +0 -0
  12. {metergraph_core-0.2.54 → metergraph_core-0.2.56}/src/metergraph_core/catalog.py +0 -0
  13. {metergraph_core-0.2.54 → metergraph_core-0.2.56}/src/metergraph_core/loader.py +0 -0
  14. {metergraph_core-0.2.54 → metergraph_core-0.2.56}/src/metergraph_core/models.py +0 -0
  15. {metergraph_core-0.2.54 → metergraph_core-0.2.56}/src/metergraph_core.egg-info/SOURCES.txt +0 -0
  16. {metergraph_core-0.2.54 → metergraph_core-0.2.56}/src/metergraph_core.egg-info/dependency_links.txt +0 -0
  17. {metergraph_core-0.2.54 → metergraph_core-0.2.56}/src/metergraph_core.egg-info/requires.txt +0 -0
  18. {metergraph_core-0.2.54 → metergraph_core-0.2.56}/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.54
3
+ Version: 0.2.56
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.54"
3
+ version = "0.2.56"
4
4
  description = "Reusable MeterGraph catalog and deterministic billing engine"
5
5
  readme = "README.md"
6
6
  license = "Apache-2.0"
@@ -37,6 +37,10 @@ from .models import (
37
37
  validate_model_registry,
38
38
  )
39
39
  from .retrieval import (
40
+ count_fetch_units,
41
+ count_search_units,
42
+ fetch_operation_for_channel,
43
+ search_operation_for_channel,
40
44
  RetrievalCatalog,
41
45
  RetrievalCostResult,
42
46
  RetrievalPrice,
@@ -62,6 +66,8 @@ __all__ = [
62
66
  "RetrievalCatalog",
63
67
  "RetrievalCostResult",
64
68
  "RetrievalPrice",
69
+ "count_fetch_units",
70
+ "count_search_units",
65
71
  "counts_cache_read_in_input",
66
72
  "direct_channel_for_provider",
67
73
  "normalize_provider",
@@ -73,5 +79,7 @@ __all__ = [
73
79
  "parse_disputes",
74
80
  "parse_retrieval",
75
81
  "resolve_billing",
82
+ "fetch_operation_for_channel",
83
+ "search_operation_for_channel",
76
84
  "validate_model_registry",
77
85
  ]
@@ -1,4 +1,4 @@
1
- version: '2026-10-06'
1
+ version: '2026-10-07'
2
2
  models:
3
3
  - canonical_id: openai/gpt-5.6-sol
4
4
  display_name: GPT-5.6 Sol
@@ -603,6 +603,50 @@ models:
603
603
  pricing_channel: vercel-ai-gateway
604
604
  execution_profiles:
605
605
  - default
606
+ - canonical_id: openai/gpt-6.1-sol
607
+ display_name: GPT-6.1 Sol
608
+ publisher: openai
609
+ routes:
610
+ - key: default:openai/gpt-6.1-sol
611
+ id: openai/gpt-6.1-sol
612
+ provider: vercel
613
+ model_id: openai/gpt-6.1-sol
614
+ pricing_channel: vercel-ai-gateway
615
+ execution_profiles:
616
+ - default
617
+ - canonical_id: xai/grok-4.7
618
+ display_name: Grok 4.7
619
+ publisher: xai
620
+ routes:
621
+ - key: default:xai/grok-4.7
622
+ id: xai/grok-4.7
623
+ provider: vercel
624
+ model_id: xai/grok-4.7
625
+ pricing_channel: vercel-ai-gateway
626
+ execution_profiles:
627
+ - default
628
+ - canonical_id: moonshotai/kimi-k2.7-code
629
+ display_name: Kimi K2.7 Code
630
+ publisher: moonshotai
631
+ routes:
632
+ - key: default:moonshotai/kimi-k2.7-code
633
+ id: moonshotai/kimi-k2.7-code
634
+ provider: vercel
635
+ model_id: moonshotai/kimi-k2.7-code
636
+ pricing_channel: vercel-ai-gateway
637
+ execution_profiles:
638
+ - default
639
+ - canonical_id: zai/glm-5.3
640
+ display_name: GLM 5.3
641
+ publisher: zai
642
+ routes:
643
+ - key: default:zai/glm-5.3
644
+ id: zai/glm-5.3
645
+ provider: vercel
646
+ model_id: zai/glm-5.3
647
+ pricing_channel: vercel-ai-gateway
648
+ execution_profiles:
649
+ - default
606
650
  execution_profiles:
607
651
  - id: default
608
652
  routes:
@@ -641,6 +685,10 @@ execution_profiles:
641
685
  - default:inception/mercury-2.5
642
686
  - default:anthropic/claude-opus-5.5
643
687
  - default:anthropic/claude-sonnet-5.5
688
+ - default:openai/gpt-6.1-sol
689
+ - default:xai/grok-4.7
690
+ - default:moonshotai/kimi-k2.7-code
691
+ - default:zai/glm-5.3
644
692
  - default:openai/gpt-5.4-mini
645
693
  - default:openai/gpt-5.4-nano
646
694
  - default:anthropic/claude-opus-4.8
@@ -710,6 +758,10 @@ offer_groups:
710
758
  - default:inception/mercury-2.5
711
759
  - default:anthropic/claude-opus-5.5
712
760
  - default:anthropic/claude-sonnet-5.5
761
+ - default:openai/gpt-6.1-sol
762
+ - default:xai/grok-4.7
763
+ - default:moonshotai/kimi-k2.7-code
764
+ - default:zai/glm-5.3
713
765
  - id: fireworks
714
766
  credential: FIREWORKS_API_KEY
715
767
  routes:
@@ -6,9 +6,9 @@
6
6
  #
7
7
  # Community updates welcome: add an alias or price entry with its provider
8
8
  # source_url and open a PR. CI validates structure and date overlaps.
9
- version: "2026-10-06"
9
+ version: "2026-10-07"
10
10
  currency: USD
11
- pricing_verified_at: "2026-10-06"
11
+ pricing_verified_at: "2026-10-07"
12
12
  models:
13
13
  - canonical_id: openai/gpt-6-sol
14
14
  publisher: openai
@@ -2639,6 +2639,32 @@ models:
2639
2639
  output_per_mtok: 15.00
2640
2640
  cache_read_per_mtok: 0.30
2641
2641
  source_url: https://fireworks.ai/models/fireworks/kimi-k3
2642
+ - canonical_id: moonshotai/kimi-k2.7-code
2643
+ publisher: moonshotai
2644
+ aliases:
2645
+ - {provider: moonshotai, alias: kimi-k2.7-code, channel: moonshot-api}
2646
+ - {provider: unknown, alias: kimi-k2.7-code, channel: moonshot-api}
2647
+ - {provider: litellm, alias: kimi-k2.7-code, channel: moonshot-api}
2648
+ - provider: moonshotai
2649
+ alias: moonshotai/kimi-k2.7-code
2650
+ channel: vercel-ai-gateway
2651
+ rules: {input_includes_cache_read: true}
2652
+ # Not on Fireworks or Bedrock as of 2026-10-07.
2653
+ prices:
2654
+ - channel: vercel-ai-gateway
2655
+ region: global
2656
+ effective_from: "2026-10-07"
2657
+ input_per_mtok: 0.95
2658
+ output_per_mtok: 4.00
2659
+ cache_read_per_mtok: 0.19
2660
+ source_url: https://ai-gateway.vercel.sh/v1/models
2661
+ - channel: moonshot-api
2662
+ region: global
2663
+ effective_from: "2026-10-07"
2664
+ input_per_mtok: 0.95
2665
+ output_per_mtok: 4.00
2666
+ cache_read_per_mtok: 0.19
2667
+ source_url: https://platform.kimi.ai/docs/pricing/chat
2642
2668
  - canonical_id: moonshotai/kimi-k3-fast
2643
2669
  publisher: moonshotai
2644
2670
  aliases:
@@ -2976,6 +3002,12 @@ models:
2976
3002
  rules: {input_includes_cache_read: true}
2977
3003
  effective_from: "2026-10-02"
2978
3004
  source_url: https://ai-gateway.vercel.sh/v1/models
3005
+ - provider: xai
3006
+ alias: xai/grok-4.7
3007
+ channel: vercel-ai-gateway
3008
+ rules: {input_includes_cache_read: true}
3009
+ effective_from: "2026-10-02"
3010
+ source_url: https://ai-gateway.vercel.sh/v1/models
2979
3011
  prices:
2980
3012
  - channel: vercel-ai-gateway
2981
3013
  region: global
@@ -3111,6 +3143,9 @@ models:
3111
3143
  alias: fireworks:accounts/fireworks/models/glm-5p3
3112
3144
  channel: fireworks-api
3113
3145
  rules: {input_includes_cache_read: true}
3146
+ - {provider: bedrock, alias: global.zai.glm-5.3, channel: aws-bedrock, price_region: global}
3147
+ - {provider: bedrock, alias: us.zai.glm-5.3, channel: aws-bedrock-geo, price_region: global}
3148
+ - {provider: bedrock, alias: zai.glm-5.3, channel: aws-bedrock, price_region: global}
3114
3149
  prices:
3115
3150
  - channel: vercel-ai-gateway
3116
3151
  region: global
@@ -3133,6 +3168,23 @@ models:
3133
3168
  output_per_mtok: 4.40
3134
3169
  cache_read_per_mtok: 0.26
3135
3170
  source_url: https://fireworks.ai/models/fireworks/glm-5p3
3171
+ # The 5m field stores AWS's 30-minute cache-write rate.
3172
+ - channel: aws-bedrock
3173
+ region: global
3174
+ effective_from: "2026-10-07"
3175
+ input_per_mtok: 1.68
3176
+ output_per_mtok: 5.28
3177
+ cache_read_per_mtok: 0.312
3178
+ cache_write_5m_per_mtok: 2.10
3179
+ source_url: https://aws.amazon.com/bedrock/pricing/
3180
+ - channel: aws-bedrock-geo
3181
+ region: global
3182
+ effective_from: "2026-10-07"
3183
+ input_per_mtok: 1.848
3184
+ output_per_mtok: 5.808
3185
+ cache_read_per_mtok: 0.3432
3186
+ cache_write_5m_per_mtok: 2.31
3187
+ source_url: https://aws.amazon.com/bedrock/pricing/
3136
3188
 
3137
3189
  - canonical_id: zai/glm-5.3-flash
3138
3190
  publisher: zai
@@ -15,6 +15,8 @@ count and an unknown operation or channel come back ``unpriced`` with a reason
15
15
  from dataclasses import dataclass
16
16
  from datetime import datetime, timezone
17
17
  from decimal import Decimal, ROUND_HALF_UP
18
+ from collections.abc import Mapping
19
+ from types import MappingProxyType
18
20
  from typing import Any
19
21
 
20
22
  from .catalog import _COST_QUANTUM, _coerce_datetime
@@ -52,6 +54,97 @@ class RetrievalCostResult:
52
54
  reasons: tuple[str, ...] = ()
53
55
 
54
56
 
57
+ # The retrieval operation a counted search or fetch is billed as on each
58
+ # channel. A channel absent here charges no per-use fee for that operation.
59
+ SEARCH_OPERATION_BY_CHANNEL: Mapping[str, str] = MappingProxyType({
60
+ "openai-api": "web_search",
61
+ "anthropic-api": "web_search",
62
+ "google-api": "google_search_grounding",
63
+ "google-vertex-ai": "google_search_grounding",
64
+ # Perplexity bills a request fee by search context size, which no
65
+ # capture path records; the low tier is the floor every request pays.
66
+ "perplexity-api": "search_request_low",
67
+ })
68
+ FETCH_OPERATION_BY_CHANNEL: Mapping[str, str] = MappingProxyType({
69
+ "anthropic-api": "web_fetch",
70
+ })
71
+
72
+ # The tool-call item types a provider emits for a search or a fetch it ran
73
+ # itself, as the Responses API and the relay record them.
74
+ _SEARCH_TOOL_TYPES = frozenset({"web_search_call"})
75
+ _FETCH_TOOL_TYPES = frozenset({"web_fetch_call"})
76
+ _PERPLEXITY = frozenset({"perplexity", "perplexity-ai"})
77
+
78
+
79
+ def search_operation_for_channel(channel: Any) -> str | None:
80
+ """The retrieval operation a counted search is billed as on ``channel``,
81
+ or ``None`` where the channel charges no per-search fee."""
82
+ return SEARCH_OPERATION_BY_CHANNEL.get(str(channel or "").strip().lower())
83
+
84
+
85
+ def fetch_operation_for_channel(channel: Any) -> str | None:
86
+ """The retrieval operation a counted fetch is billed as on ``channel``,
87
+ or ``None`` where the channel charges no per-fetch fee."""
88
+ return FETCH_OPERATION_BY_CHANNEL.get(str(channel or "").strip().lower())
89
+
90
+
91
+ def _count(value: Any) -> int | None:
92
+ if value is None or isinstance(value, bool):
93
+ return None
94
+ try:
95
+ count = int(value)
96
+ except (TypeError, ValueError, OverflowError):
97
+ return None
98
+ return count if count >= 0 else None
99
+
100
+
101
+ def _tool_items(row: Mapping[str, Any], types: frozenset[str]) -> int | None:
102
+ """Items of the given types among ``tool_calls``: a measured zero when the
103
+ list is there and holds none, ``None`` when there is no list to read."""
104
+ calls = row.get("tool_calls")
105
+ if not isinstance(calls, list):
106
+ return None
107
+ return sum(
108
+ 1
109
+ for call in calls
110
+ if isinstance(call, Mapping) and str(call.get("type") or "").strip().lower() in types
111
+ )
112
+
113
+
114
+ def count_search_units(row: Mapping[str, Any]) -> int | None:
115
+ """The searches one call row made, read from whichever field its capture
116
+ path carries, in the order they are believed: ``web_search_calls`` and
117
+ ``grounding_queries`` (the relay's per-provider counts), Anthropic's
118
+ ``server_tool_use.web_search_requests``, then the ``web_search_call``
119
+ items among ``tool_calls``. A Perplexity call is one search, since
120
+ Perplexity bills every request as one. A field that is present and says
121
+ nothing was searched is a measured zero; ``None`` means no field says."""
122
+ for key in ("web_search_calls", "grounding_queries"):
123
+ count = _count(row.get(key))
124
+ if count is not None:
125
+ return count
126
+ server = row.get("server_tool_use")
127
+ if isinstance(server, Mapping):
128
+ count = _count(server.get("web_search_requests"))
129
+ if count is not None:
130
+ return count
131
+ if str(row.get("provider") or "").strip().lower() in _PERPLEXITY:
132
+ return 1
133
+ return _tool_items(row, _SEARCH_TOOL_TYPES)
134
+
135
+
136
+ def count_fetch_units(row: Mapping[str, Any]) -> int | None:
137
+ """The page fetches one call row made: Anthropic's
138
+ ``server_tool_use.web_fetch_requests``, then the ``web_fetch_call``
139
+ items among ``tool_calls``, with the same measured-zero rule."""
140
+ server = row.get("server_tool_use")
141
+ if isinstance(server, Mapping):
142
+ count = _count(server.get("web_fetch_requests"))
143
+ if count is not None:
144
+ return count
145
+ return _tool_items(row, _FETCH_TOOL_TYPES)
146
+
147
+
55
148
  def _units(value: Any) -> tuple[int | None, str | None]:
56
149
  """Coerce a retrieval unit count under a strict-integer contract.
57
150
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: metergraph-core
3
- Version: 0.2.54
3
+ Version: 0.2.56
4
4
  Summary: Reusable MeterGraph catalog and deterministic billing engine
5
5
  License-Expression: Apache-2.0
6
6
  Requires-Python: >=3.10