@pydantic/genai-prices 0.0.22 → 0.0.24

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.
package/dist/index.d.cts CHANGED
@@ -1,3 +1,9 @@
1
+ export declare interface ArrayMatch {
2
+ field: string;
3
+ match: MatchLogic;
4
+ type: 'array-match';
5
+ }
6
+
1
7
  export declare function calcPrice(usage: Usage, modelId: string, options?: PriceOptions): PriceCalculationResult;
2
8
 
3
9
  export declare interface ConditionalPrice {
@@ -5,6 +11,8 @@ export declare interface ConditionalPrice {
5
11
  prices: ModelPrice;
6
12
  }
7
13
 
14
+ export declare type ExtractPath = (ArrayMatch | string)[] | string;
15
+
8
16
  export declare function extractUsage(provider: Provider, responseData: unknown, apiFlavor?: string): [string, Usage];
9
17
 
10
18
  export declare function findProvider(options: ProviderFindOptions): Provider | undefined;
@@ -140,13 +148,13 @@ export declare interface Usage {
140
148
  export declare interface UsageExtractor {
141
149
  api_flavor: string;
142
150
  mappings: UsageExtractorMapping[];
143
- model_path: string | string[];
144
- root: string | string[];
151
+ model_path: ExtractPath;
152
+ root: ExtractPath;
145
153
  }
146
154
 
147
155
  export declare interface UsageExtractorMapping {
148
156
  dest: 'cache_audio_read_tokens' | 'cache_read_tokens' | 'cache_write_tokens' | 'input_audio_tokens' | 'input_tokens' | 'output_audio_tokens' | 'output_tokens';
149
- path: string | string[];
157
+ path: ExtractPath;
150
158
  required: boolean;
151
159
  }
152
160
 
package/dist/index.d.ts CHANGED
@@ -1,3 +1,9 @@
1
+ export declare interface ArrayMatch {
2
+ field: string;
3
+ match: MatchLogic;
4
+ type: 'array-match';
5
+ }
6
+
1
7
  export declare function calcPrice(usage: Usage, modelId: string, options?: PriceOptions): PriceCalculationResult;
2
8
 
3
9
  export declare interface ConditionalPrice {
@@ -5,6 +11,8 @@ export declare interface ConditionalPrice {
5
11
  prices: ModelPrice;
6
12
  }
7
13
 
14
+ export declare type ExtractPath = (ArrayMatch | string)[] | string;
15
+
8
16
  export declare function extractUsage(provider: Provider, responseData: unknown, apiFlavor?: string): [string, Usage];
9
17
 
10
18
  export declare function findProvider(options: ProviderFindOptions): Provider | undefined;
@@ -140,13 +148,13 @@ export declare interface Usage {
140
148
  export declare interface UsageExtractor {
141
149
  api_flavor: string;
142
150
  mappings: UsageExtractorMapping[];
143
- model_path: string | string[];
144
- root: string | string[];
151
+ model_path: ExtractPath;
152
+ root: ExtractPath;
145
153
  }
146
154
 
147
155
  export declare interface UsageExtractorMapping {
148
156
  dest: 'cache_audio_read_tokens' | 'cache_read_tokens' | 'cache_write_tokens' | 'input_audio_tokens' | 'input_tokens' | 'output_audio_tokens' | 'output_tokens';
149
- path: string | string[];
157
+ path: ExtractPath;
150
158
  required: boolean;
151
159
  }
152
160
 
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- const f = [
1
+ const w = [
2
2
  {
3
3
  id: "anthropic",
4
4
  name: "Anthropic",
@@ -21,6 +21,16 @@ const f = [
21
21
  dest: "input_tokens",
22
22
  required: !0
23
23
  },
24
+ {
25
+ path: "cache_creation_input_tokens",
26
+ dest: "input_tokens",
27
+ required: !1
28
+ },
29
+ {
30
+ path: "cache_read_input_tokens",
31
+ dest: "input_tokens",
32
+ required: !1
33
+ },
24
34
  {
25
35
  path: "cache_creation_input_tokens",
26
36
  dest: "cache_write_tokens",
@@ -1509,8 +1519,8 @@ Compared to other leading proprietary and open-weights models Command A delivers
1509
1519
  extractors: [
1510
1520
  {
1511
1521
  api_flavor: "default",
1512
- root: "UsageMetadata",
1513
- model_path: "model",
1522
+ root: "usageMetadata",
1523
+ model_path: "modelVersion",
1514
1524
  mappings: [
1515
1525
  {
1516
1526
  path: "promptTokenCount",
@@ -1518,10 +1528,35 @@ Compared to other leading proprietary and open-weights models Command A delivers
1518
1528
  required: !0
1519
1529
  },
1520
1530
  {
1521
- path: "cachedContentTokenCount",
1531
+ path: [
1532
+ "cacheTokensDetails",
1533
+ {
1534
+ type: "array-match",
1535
+ field: "modality",
1536
+ match: {
1537
+ equals: "TEXT"
1538
+ }
1539
+ },
1540
+ "tokenCount"
1541
+ ],
1522
1542
  dest: "cache_read_tokens",
1523
1543
  required: !1
1524
1544
  },
1545
+ {
1546
+ path: [
1547
+ "cacheTokensDetails",
1548
+ {
1549
+ type: "array-match",
1550
+ field: "modality",
1551
+ match: {
1552
+ equals: "AUDIO"
1553
+ }
1554
+ },
1555
+ "tokenCount"
1556
+ ],
1557
+ dest: "cache_audio_read_tokens",
1558
+ required: !1
1559
+ },
1525
1560
  {
1526
1561
  path: "candidatesTokenCount",
1527
1562
  dest: "output_tokens",
@@ -3613,7 +3648,7 @@ Compared to other leading proprietary and open-weights models Command A delivers
3613
3648
  equals: "gpt-5-nano"
3614
3649
  },
3615
3650
  {
3616
- equals: "gpt-5-nano-2025-04-14"
3651
+ starts_with: "gpt-5-nano-"
3617
3652
  }
3618
3653
  ]
3619
3654
  },
@@ -10846,23 +10881,23 @@ Compared to other leading proprietary and open-weights models Command A delivers
10846
10881
  ]
10847
10882
  }
10848
10883
  ];
10849
- function x(t, e) {
10884
+ function y(t, e) {
10850
10885
  if (e <= 0) return 0;
10851
10886
  let a = 0;
10852
- const i = [...t.tiers].sort((r, m) => r.start - m.start), o = i[0]?.start ?? e, s = Math.min(e, o);
10853
- a += s * t.base / 1e6;
10887
+ const i = [...t.tiers].sort((r, s) => r.start - s.start), o = i[0]?.start ?? e, n = Math.min(e, o);
10888
+ a += n * t.base / 1e6;
10854
10889
  for (let r = 0; r < i.length; r++) {
10855
- const m = i[r], n = i[r + 1]?.start ?? 1 / 0, u = Math.max(0, Math.min(e, n) - m.start);
10856
- u > 0 && (a += u * m.price / 1e6);
10890
+ const s = i[r], m = i[r + 1]?.start ?? 1 / 0, u = Math.max(0, Math.min(e, m) - s.start);
10891
+ u > 0 && (a += u * s.price / 1e6);
10857
10892
  }
10858
10893
  return a;
10859
10894
  }
10860
- function l(t, e, a) {
10861
- return t === void 0 || e === void 0 ? 0 : typeof t == "number" ? t * e / 1e6 : x(t, e);
10895
+ function p(t, e, a) {
10896
+ return t === void 0 || e === void 0 ? 0 : typeof t == "number" ? t * e / 1e6 : y(t, e);
10862
10897
  }
10863
- function B(t, e) {
10898
+ function M(t, e) {
10864
10899
  let a = 0, i = 0;
10865
- a += l(e.input_mtok, t.input_tokens), a += l(e.cache_write_mtok, t.cache_write_tokens), a += l(e.cache_read_mtok, t.cache_read_tokens), a += l(e.input_audio_mtok, t.input_audio_tokens), a += l(e.cache_audio_read_mtok, t.cache_audio_read_tokens), i += l(e.output_mtok, t.output_tokens), i += l(e.output_audio_mtok, t.output_audio_tokens), e.requests_kcount !== void 0 && (a += e.requests_kcount / 1e3);
10900
+ a += p(e.input_mtok, t.input_tokens), a += p(e.cache_write_mtok, t.cache_write_tokens), a += p(e.cache_read_mtok, t.cache_read_tokens), a += p(e.input_audio_mtok, t.input_audio_tokens), a += p(e.cache_audio_read_mtok, t.cache_audio_read_tokens), i += p(e.output_mtok, t.output_tokens), i += p(e.output_audio_mtok, t.output_audio_tokens), e.requests_kcount !== void 0 && (a += e.requests_kcount / 1e3);
10866
10901
  const o = a + i;
10867
10902
  return {
10868
10903
  input_price: a,
@@ -10870,7 +10905,7 @@ function B(t, e) {
10870
10905
  total_price: o
10871
10906
  };
10872
10907
  }
10873
- function y(t, e) {
10908
+ function I(t, e) {
10874
10909
  if (!Array.isArray(t.prices))
10875
10910
  return t.prices;
10876
10911
  for (let a = t.prices.length - 1; a >= 0; a--) {
@@ -10881,150 +10916,167 @@ function y(t, e) {
10881
10916
  if (e >= new Date(o.start_date))
10882
10917
  return i.prices;
10883
10918
  } else {
10884
- const s = e.toISOString().slice(11, 19), r = o.start_time, m = o.end_time;
10885
- if (m < r) {
10886
- if (s >= r || s < m)
10919
+ const n = e.toISOString().slice(11, 19), r = o.start_time, s = o.end_time;
10920
+ if (s < r) {
10921
+ if (n >= r || n < s)
10887
10922
  return i.prices;
10888
- } else if (s >= r && s < m)
10923
+ } else if (n >= r && n < s)
10889
10924
  return i.prices;
10890
10925
  }
10891
10926
  }
10892
10927
  return t.prices[0].prices;
10893
10928
  }
10894
- function d(t, e) {
10895
- return "or" in t ? t.or.some((a) => d(a, e)) : "and" in t ? t.and.every((a) => d(a, e)) : "equals" in t ? e === t.equals : "starts_with" in t ? e.startsWith(t.starts_with) : "ends_with" in t ? e.endsWith(t.ends_with) : "contains" in t ? e.includes(t.contains) : "regex" in t ? new RegExp(t.regex).test(e) : !1;
10929
+ function h(t, e) {
10930
+ return "or" in t ? t.or.some((a) => h(a, e)) : "and" in t ? t.and.every((a) => h(a, e)) : "equals" in t ? e === t.equals : "starts_with" in t ? e.startsWith(t.starts_with) : "ends_with" in t ? e.endsWith(t.ends_with) : "contains" in t ? e.includes(t.contains) : "regex" in t ? new RegExp(t.regex).test(e) : !1;
10896
10931
  }
10897
- function M(t, e) {
10932
+ function P(t, e) {
10898
10933
  const a = e.toLowerCase().trim(), i = t.find((o) => o.id === a);
10899
- return i || t.find((o) => o.provider_match && d(o.provider_match, a));
10934
+ return i || t.find((o) => o.provider_match && h(o.provider_match, a));
10900
10935
  }
10901
- function w(t, { modelId: e, providerApiUrl: a, providerId: i }) {
10936
+ function v(t, { modelId: e, providerApiUrl: a, providerId: i }) {
10902
10937
  if (i)
10903
- return M(t, i);
10938
+ return P(t, i);
10904
10939
  if (a)
10905
10940
  return t.find((o) => new RegExp(o.api_pattern).test(a));
10906
10941
  if (e)
10907
- return t.find((o) => o.model_match && d(o.model_match, e));
10942
+ return t.find((o) => o.model_match && h(o.model_match, e));
10908
10943
  }
10909
- function I(t, e) {
10910
- return t.find((a) => d(a.match, e));
10944
+ function L(t, e) {
10945
+ return t.find((a) => h(a.match, e));
10911
10946
  }
10912
- const P = "https://raw.githubusercontent.com/pydantic/genai-prices/main/prices/data.json";
10913
- let h = f, g = Promise.resolve(f), q = null;
10914
- function L(t) {
10915
- "then" in t ? (g = t, t.then((e) => {
10916
- h = e;
10917
- })) : (g = Promise.resolve(t), h = t);
10947
+ const T = "https://raw.githubusercontent.com/pydantic/genai-prices/main/prices/data.json";
10948
+ let _ = w, q = Promise.resolve(w), b = null;
10949
+ function G(t) {
10950
+ "then" in t ? (q = t, t.then((e) => {
10951
+ _ = e;
10952
+ })) : (q = Promise.resolve(t), _ = t);
10918
10953
  }
10919
- function T(t) {
10920
- q = t;
10954
+ function S(t) {
10955
+ b = t;
10921
10956
  }
10922
- function R(t) {
10957
+ function z(t) {
10923
10958
  t({
10924
- onCalc: T,
10925
- remoteDataUrl: P,
10926
- setProviderData: L
10959
+ onCalc: S,
10960
+ remoteDataUrl: T,
10961
+ setProviderData: G
10927
10962
  });
10928
10963
  }
10929
- function A() {
10930
- return g;
10964
+ function N() {
10965
+ return q;
10931
10966
  }
10932
- function C(t, e, a) {
10933
- q?.();
10934
- const i = e.toLowerCase().trim(), o = a?.provider ?? w(h, { modelId: i, providerApiUrl: a?.providerApiUrl, providerId: a?.providerId });
10967
+ function Q(t, e, a) {
10968
+ b?.();
10969
+ const i = e.toLowerCase().trim(), o = a?.provider ?? v(_, { modelId: i, providerApiUrl: a?.providerApiUrl, providerId: a?.providerId });
10935
10970
  if (!o) return null;
10936
- const s = I(o.models, i);
10937
- if (!s) return null;
10938
- const r = a?.timestamp ?? /* @__PURE__ */ new Date(), m = y(s, r), n = B(t, m);
10971
+ const n = L(o.models, i);
10972
+ if (!n) return null;
10973
+ const r = a?.timestamp ?? /* @__PURE__ */ new Date(), s = I(n, r), m = M(t, s);
10939
10974
  return {
10940
10975
  auto_update_timestamp: void 0,
10941
- model: s,
10942
- model_price: m,
10976
+ model: n,
10977
+ model_price: s,
10943
10978
  provider: o,
10944
- ...n
10979
+ ...m
10945
10980
  };
10946
10981
  }
10947
- function z(t) {
10948
- return q?.(), w(h, t);
10982
+ function E(t) {
10983
+ return b?.(), v(_, t);
10949
10984
  }
10950
- function N(t, e, a) {
10985
+ function O(t, e, a) {
10951
10986
  if (!t.extractors)
10952
10987
  throw new Error("No extraction logic defined for this provider");
10953
10988
  let i;
10954
10989
  if (a) {
10955
- const n = t.extractors.find((u) => u.api_flavor === a);
10956
- if (n)
10957
- i = n;
10990
+ const m = t.extractors.find((u) => u.api_flavor === a);
10991
+ if (m)
10992
+ i = m;
10958
10993
  else {
10959
- const u = t.extractors.map((p) => p.api_flavor).join(", ");
10994
+ const u = t.extractors.map((l) => l.api_flavor).join(", ");
10960
10995
  throw new Error(`Unknown apiFlavor '${a}', allowed values: ${u}`);
10961
10996
  }
10962
10997
  } else if (t.extractors.length === 1)
10963
10998
  i = t.extractors[0];
10964
10999
  else
10965
11000
  throw new Error("No apiFlavor specified and multiple extractors available");
10966
- if (!b.guard(e))
11001
+ if (!k.guard(e))
10967
11002
  throw new Error(`Expected response data to be a mapping object, got ${c(e)}`);
10968
- const o = _(i.model_path, e, G, !0, []), s = v(i.root), r = _(s, e, b, !0, []), m = {};
10969
- for (const n of i.mappings) {
10970
- const u = _(n.path, r, S, n.required, s);
11003
+ const o = g(i.model_path, e, A, !0, []), n = x(i.root), r = g(n, e, k, !0, []), s = {};
11004
+ for (const m of i.mappings) {
11005
+ const u = g(m.path, r, C, m.required, n);
10971
11006
  if (u !== null) {
10972
- const p = m[n.dest] ?? 0;
10973
- m[n.dest] = p + u;
11007
+ const l = s[m.dest] ?? 0;
11008
+ s[m.dest] = l + u;
10974
11009
  }
10975
11010
  }
10976
- if (!Object.keys(m).length)
11011
+ if (!Object.keys(s).length)
10977
11012
  throw new Error(`No usage information found at ${JSON.stringify(i.root)}`);
10978
- return [o, m];
11013
+ return [o, s];
10979
11014
  }
10980
- function _(t, e, a, i, o) {
10981
- const [s, ...r] = v(t).reverse();
10982
- if (typeof s != "string")
10983
- throw new Error(`Expected last step of path to be a string, got ${c(s)}`);
10984
- let m = e;
11015
+ function g(t, e, a, i, o) {
11016
+ const [n, ...r] = x(t).reverse();
11017
+ if (typeof n != "string")
11018
+ throw new Error(`Expected last step of path to be a string, got ${c(n)}`);
10985
11019
  r.reverse();
10986
- const n = [];
10987
- for (const p of r) {
10988
- n.push(p), m = m[p];
10989
- const k = c(m);
10990
- if (k === "undefined") {
10991
- if (i)
10992
- throw new Error(`Missing value at \`${[...o, ...n].join(".")}\``);
10993
- return null;
10994
- } else if (k !== "mapping")
10995
- throw new Error(`Expected \`${[...o, ...n].join(".")}\` value to be a mapping, got ${k}`);
11020
+ let s = e;
11021
+ const m = [];
11022
+ for (const l of r) {
11023
+ if (m.push(l), typeof l == "object")
11024
+ if (Array.isArray(s))
11025
+ s = R(l, s);
11026
+ else
11027
+ throw new Error(`Expected \`${d(o, m)}\` value to be a mapping, got ${c(s)}`);
11028
+ else if (k.guard(s))
11029
+ s = s[l];
11030
+ else
11031
+ throw new Error(`Expected \`${d(o, m)}\` value to be a mapping, got ${c(s)}`);
11032
+ if (typeof s > "u")
11033
+ if (i) {
11034
+ const B = typeof l == "object" ? "Unable to find item" : "Missing value";
11035
+ throw new Error(`${B} at \`${d(o, m)}\``);
11036
+ } else
11037
+ return null;
10996
11038
  }
10997
- const u = m[s];
11039
+ if (!k.guard(s))
11040
+ throw new Error(`Expected \`${d(o, m)}\` value to be a mapping, got ${c(s)}`);
11041
+ const u = s[n];
10998
11042
  if (typeof u > "u") {
10999
11043
  if (i)
11000
- throw n.push(s), new Error(`Missing value at \`${[...o, ...n].join(".")}\``);
11044
+ throw m.push(n), new Error(`Missing value at \`${d(o, m)}\``);
11001
11045
  return null;
11002
11046
  }
11003
11047
  if (a.guard(u))
11004
11048
  return u;
11005
- throw n.push(s), new Error(`Expected \`${[...o, ...n].join(".")}\` value to be a ${a.name}, got ${c(u)}`);
11049
+ throw m.push(n), new Error(`Expected \`${d(o, m)}\` value to be a ${a.name}, got ${c(u)}`);
11006
11050
  }
11007
- function v(t) {
11051
+ function R(t, e) {
11052
+ for (const a of e)
11053
+ if (k.guard(a)) {
11054
+ const i = a[t.field];
11055
+ if (typeof i == "string" && h(t.match, i))
11056
+ return a;
11057
+ }
11058
+ }
11059
+ function x(t) {
11008
11060
  return Array.isArray(t) ? [...t] : [t];
11009
11061
  }
11010
11062
  function c(t) {
11011
11063
  return t === null ? "null" : Array.isArray(t) ? "array" : typeof t == "object" ? "mapping" : typeof t;
11012
11064
  }
11013
- const b = {
11065
+ const k = {
11014
11066
  guard: (t) => c(t) === "mapping",
11015
11067
  name: "mapping"
11016
- }, G = {
11068
+ }, A = {
11017
11069
  guard: (t) => typeof t == "string",
11018
11070
  name: "string"
11019
- }, S = {
11071
+ }, C = {
11020
11072
  guard: (t) => typeof t == "number",
11021
11073
  name: "number"
11022
- };
11074
+ }, d = (t, e) => [...t.map(f), ...e.map(f)].join("."), f = (t) => typeof t == "string" ? t : JSON.stringify(t);
11023
11075
  export {
11024
- P as REMOTE_DATA_JSON_URL,
11025
- C as calcPrice,
11026
- N as extractUsage,
11027
- z as findProvider,
11028
- R as updatePrices,
11029
- A as waitForUpdate
11076
+ T as REMOTE_DATA_JSON_URL,
11077
+ Q as calcPrice,
11078
+ O as extractUsage,
11079
+ E as findProvider,
11080
+ z as updatePrices,
11081
+ N as waitForUpdate
11030
11082
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pydantic/genai-prices",
3
- "version": "0.0.22",
3
+ "version": "0.0.24",
4
4
  "description": "Calculate prices for calling LLM inference APIs",
5
5
  "author": "Pydantic Team",
6
6
  "type": "module",
@@ -47,7 +47,7 @@
47
47
  "dev": "vite build --watch",
48
48
  "typecheck": "tsc --noEmit",
49
49
  "lint": "eslint",
50
- "format": "eslint --fix --quiet",
50
+ "lint-fix": "eslint --fix --quiet",
51
51
  "test": "vitest run",
52
52
  "test:watch": "vitest",
53
53
  "test:ui": "vitest --ui",