@oh-my-pi/pi-catalog 17.1.6 → 17.1.8

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/CHANGELOG.md CHANGED
@@ -2,6 +2,27 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [17.1.8] - 2026-07-28
6
+
7
+ ### Added
8
+
9
+ - Added `resolveVertexEndpointHost(location)` utility to resolve the correct Vertex AI API endpoint hostnames for global, multi-region, and regional locations.
10
+
11
+ ### Fixed
12
+
13
+ - Fixed an issue where `calculateCost` under-reported Anthropic cache-write costs by honoring the `usage.cttl` breakdown to correctly price 1-hour retention writes at 2x the base input rate.
14
+
15
+ ## [17.1.7] - 2026-07-27
16
+
17
+ ### Added
18
+
19
+ - Added support for moonshotai/Kimi-K3 and kimi-k3-fast models
20
+ - Added umans-kimi-k3 prerelease model configuration
21
+
22
+ ### Changed
23
+
24
+ - Updated pricing and token limits for selected models
25
+
5
26
  ## [17.1.6] - 2026-07-27
6
27
 
7
28
  ### Added
@@ -136,6 +136,19 @@ export declare function modelMatchesHost(model: {
136
136
  provider: string;
137
137
  baseUrl: string;
138
138
  }, host: KnownHost): boolean;
139
+ /**
140
+ * Hostname for a Vertex AI GenerateContent / rawPredict / OpenAI-compat
141
+ * request for the given location.
142
+ *
143
+ * - `global` → global endpoint (`aiplatform.googleapis.com`)
144
+ * - `eu` / `us` multi-regions → REP endpoints (`aiplatform.{eu|us}.rep.googleapis.com`)
145
+ * - every other location → regional (`{location}-aiplatform.googleapis.com`)
146
+ *
147
+ * Multi-region codes do NOT follow the regional `{location}-aiplatform` pattern;
148
+ * interpolating them that way yields hosts like `eu-aiplatform.googleapis.com`
149
+ * that 404.
150
+ */
151
+ export declare function resolveVertexEndpointHost(location: string): string;
139
152
  /** Vertex AI express-mode OpenAI-compatible endpoint (`…/endpoints/openapi`). */
140
153
  export declare function isVertexExpressOpenAIUrl(baseUrl: string): boolean;
141
154
  /** Vertex AI Anthropic raw-predict endpoints (`:streamRawPredict` / `:rawPredict`). */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@oh-my-pi/pi-catalog",
4
- "version": "17.1.6",
4
+ "version": "17.1.8",
5
5
  "description": "Model catalog for omp: bundled model database, provider discovery descriptors, model identity, classification, and equivalence",
6
6
  "homepage": "https://omp.sh",
7
7
  "author": "Can Boluk",
@@ -34,12 +34,12 @@
34
34
  },
35
35
  "dependencies": {
36
36
  "@bufbuild/protobuf": "^2.12.1",
37
- "@oh-my-pi/pi-utils": "17.1.6",
37
+ "@oh-my-pi/pi-utils": "17.1.8",
38
38
  "arktype": "2.2.3",
39
39
  "zod": "^4"
40
40
  },
41
41
  "devDependencies": {
42
- "@oh-my-pi/pi-ai": "17.1.6",
42
+ "@oh-my-pi/pi-ai": "17.1.8",
43
43
  "@types/bun": "^1.3.14"
44
44
  },
45
45
  "engines": {
package/src/hosts.ts CHANGED
@@ -111,6 +111,24 @@ function includesAsciiCaseInsensitive(value: string, lowerNeedle: string): boole
111
111
 
112
112
  // --- Endpoint-shape predicates (URL path/verb shapes, not vendor hosts) ---
113
113
 
114
+ /**
115
+ * Hostname for a Vertex AI GenerateContent / rawPredict / OpenAI-compat
116
+ * request for the given location.
117
+ *
118
+ * - `global` → global endpoint (`aiplatform.googleapis.com`)
119
+ * - `eu` / `us` multi-regions → REP endpoints (`aiplatform.{eu|us}.rep.googleapis.com`)
120
+ * - every other location → regional (`{location}-aiplatform.googleapis.com`)
121
+ *
122
+ * Multi-region codes do NOT follow the regional `{location}-aiplatform` pattern;
123
+ * interpolating them that way yields hosts like `eu-aiplatform.googleapis.com`
124
+ * that 404.
125
+ */
126
+ export function resolveVertexEndpointHost(location: string): string {
127
+ if (location === "global") return "aiplatform.googleapis.com";
128
+ if (location === "eu" || location === "us") return `aiplatform.${location}.rep.googleapis.com`;
129
+ return `${location}-aiplatform.googleapis.com`;
130
+ }
131
+
114
132
  /** Vertex AI express-mode OpenAI-compatible endpoint (`…/endpoints/openapi`). */
115
133
  export function isVertexExpressOpenAIUrl(baseUrl: string): boolean {
116
134
  return baseUrl.includes("/endpoints/openapi");
package/src/models.json CHANGED
@@ -13155,6 +13155,27 @@
13155
13155
  "supportsComputerUse": false,
13156
13156
  "supportsComputerUseConfig": false
13157
13157
  },
13158
+ "moonshotai/Kimi-K3": {
13159
+ "id": "moonshotai/Kimi-K3",
13160
+ "name": "Kimi K3",
13161
+ "api": "openai-completions",
13162
+ "provider": "baseten",
13163
+ "baseUrl": "https://inference.baseten.co/v1",
13164
+ "reasoning": false,
13165
+ "input": [
13166
+ "text",
13167
+ "image"
13168
+ ],
13169
+ "cost": {
13170
+ "input": 3,
13171
+ "output": 15,
13172
+ "cacheRead": 0.3,
13173
+ "cacheWrite": 0
13174
+ },
13175
+ "contextWindow": 1048576,
13176
+ "maxTokens": 1048576,
13177
+ "supportsComputerUse": false
13178
+ },
13158
13179
  "nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B": {
13159
13180
  "id": "nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B",
13160
13181
  "name": "Nemotron Ultra",
@@ -17111,6 +17132,40 @@
17111
17132
  "supportsComputerUse": false,
17112
17133
  "supportsComputerUseConfig": false
17113
17134
  },
17135
+ "kimi-k3": {
17136
+ "id": "kimi-k3",
17137
+ "name": "Kimi K3",
17138
+ "api": "openai-completions",
17139
+ "provider": "fireworks",
17140
+ "baseUrl": "https://api.fireworks.ai/inference/v1",
17141
+ "reasoning": true,
17142
+ "input": [
17143
+ "text",
17144
+ "image"
17145
+ ],
17146
+ "cost": {
17147
+ "input": 3,
17148
+ "output": 15,
17149
+ "cacheRead": 0.3,
17150
+ "cacheWrite": 0
17151
+ },
17152
+ "contextWindow": 1048576,
17153
+ "maxTokens": 131072,
17154
+ "thinking": {
17155
+ "mode": "effort",
17156
+ "efforts": [
17157
+ "low",
17158
+ "high",
17159
+ "max"
17160
+ ],
17161
+ "defaultLevel": "max",
17162
+ "effortMap": {
17163
+ "max": "max"
17164
+ },
17165
+ "requiresEffort": true
17166
+ },
17167
+ "supportsComputerUse": false
17168
+ },
17114
17169
  "minimax-m2.5": {
17115
17170
  "id": "minimax-m2.5",
17116
17171
  "name": "MiniMax-M2.5",
@@ -27541,7 +27596,8 @@
27541
27596
  },
27542
27597
  "contextWindow": null,
27543
27598
  "maxTokens": null,
27544
- "supportsComputerUse": false
27599
+ "supportsComputerUse": false,
27600
+ "supportsComputerUseConfig": false
27545
27601
  },
27546
27602
  "liquid/lfm-2-24b-a2b": {
27547
27603
  "id": "liquid/lfm-2-24b-a2b",
@@ -30167,7 +30223,8 @@
30167
30223
  },
30168
30224
  "contextWindow": null,
30169
30225
  "maxTokens": null,
30170
- "supportsComputerUse": false
30226
+ "supportsComputerUse": false,
30227
+ "supportsComputerUseConfig": false
30171
30228
  },
30172
30229
  "openai/gpt-4o:extended": {
30173
30230
  "id": "openai/gpt-4o:extended",
@@ -64047,6 +64104,38 @@
64047
64104
  ]
64048
64105
  }
64049
64106
  },
64107
+ "kimi-k3": {
64108
+ "id": "kimi-k3",
64109
+ "name": "Kimi K3",
64110
+ "api": "ollama-chat",
64111
+ "provider": "ollama-cloud",
64112
+ "baseUrl": "https://ollama.com",
64113
+ "reasoning": true,
64114
+ "thinking": {
64115
+ "mode": "effort",
64116
+ "efforts": [
64117
+ "low",
64118
+ "high",
64119
+ "max"
64120
+ ],
64121
+ "defaultLevel": "max",
64122
+ "requiresEffort": true
64123
+ },
64124
+ "input": [
64125
+ "text",
64126
+ "image"
64127
+ ],
64128
+ "cost": {
64129
+ "input": 3,
64130
+ "output": 15,
64131
+ "cacheRead": 0.3,
64132
+ "cacheWrite": 0
64133
+ },
64134
+ "contextWindow": 1048576,
64135
+ "maxTokens": 8192,
64136
+ "omitMaxOutputTokens": true,
64137
+ "supportsComputerUse": false
64138
+ },
64050
64139
  "minimax-m2": {
64051
64140
  "id": "minimax-m2",
64052
64141
  "name": "minimax-m2",
@@ -68713,6 +68802,39 @@
68713
68802
  ]
68714
68803
  }
68715
68804
  },
68805
+ "kimi-k3": {
68806
+ "id": "kimi-k3",
68807
+ "name": "Kimi K3",
68808
+ "api": "openai-completions",
68809
+ "provider": "opencode-zen",
68810
+ "baseUrl": "https://opencode.ai/zen/v1",
68811
+ "reasoning": true,
68812
+ "input": [
68813
+ "text",
68814
+ "image"
68815
+ ],
68816
+ "cost": {
68817
+ "input": 3,
68818
+ "output": 15,
68819
+ "cacheRead": 0.3,
68820
+ "cacheWrite": 0
68821
+ },
68822
+ "contextWindow": 1048576,
68823
+ "maxTokens": 131072,
68824
+ "thinking": {
68825
+ "mode": "effort",
68826
+ "efforts": [
68827
+ "low",
68828
+ "high",
68829
+ "max"
68830
+ ],
68831
+ "defaultLevel": "max",
68832
+ "effortMap": {
68833
+ "max": "max"
68834
+ },
68835
+ "requiresEffort": true
68836
+ }
68837
+ },
68716
68838
  "laguna-s-2.1-free": {
68717
68839
  "id": "laguna-s-2.1-free",
68718
68840
  "name": "Laguna S 2.1 Free",
@@ -72047,8 +72169,8 @@
72047
72169
  "image"
72048
72170
  ],
72049
72171
  "cost": {
72050
- "input": 0.12,
72051
- "output": 0.35,
72172
+ "input": 0.14,
72173
+ "output": 0.42,
72052
72174
  "cacheRead": 0.049999999999999996,
72053
72175
  "cacheWrite": 0
72054
72176
  },
@@ -74224,9 +74346,9 @@
74224
74346
  "text"
74225
74347
  ],
74226
74348
  "cost": {
74227
- "input": 0.6,
74228
- "output": 3.5999999999999996,
74229
- "cacheRead": 0.19999999999999998,
74349
+ "input": 0.5,
74350
+ "output": 2.2,
74351
+ "cacheRead": 0.09999999999999999,
74230
74352
  "cacheWrite": 0
74231
74353
  },
74232
74354
  "contextWindow": 512288,
@@ -75036,11 +75158,11 @@
75036
75158
  "cost": {
75037
75159
  "input": 1.25,
75038
75160
  "output": 10,
75039
- "cacheRead": 0.125,
75161
+ "cacheRead": 0.13,
75040
75162
  "cacheWrite": 0
75041
75163
  },
75042
75164
  "contextWindow": 128000,
75043
- "maxTokens": 16384,
75165
+ "maxTokens": 32000,
75044
75166
  "supportsComputerUse": false,
75045
75167
  "supportsComputerUseConfig": false
75046
75168
  },
@@ -75503,10 +75625,10 @@
75503
75625
  "image"
75504
75626
  ],
75505
75627
  "cost": {
75506
- "input": 1,
75507
- "output": 6,
75508
- "cacheRead": 0.09999999999999999,
75509
- "cacheWrite": 1.25
75628
+ "input": 0.5,
75629
+ "output": 3,
75630
+ "cacheRead": 0.049999999999999996,
75631
+ "cacheWrite": 0.625
75510
75632
  },
75511
75633
  "contextWindow": 1050000,
75512
75634
  "maxTokens": 128000,
@@ -75535,10 +75657,10 @@
75535
75657
  "image"
75536
75658
  ],
75537
75659
  "cost": {
75538
- "input": 1,
75539
- "output": 6,
75540
- "cacheRead": 0.09999999999999999,
75541
- "cacheWrite": 1.25
75660
+ "input": 0.5,
75661
+ "output": 3,
75662
+ "cacheRead": 0.049999999999999996,
75663
+ "cacheWrite": 0.625
75542
75664
  },
75543
75665
  "contextWindow": 1050000,
75544
75666
  "maxTokens": 128000,
@@ -75631,10 +75753,10 @@
75631
75753
  "image"
75632
75754
  ],
75633
75755
  "cost": {
75634
- "input": 2.5,
75635
- "output": 15,
75636
- "cacheRead": 0.25,
75637
- "cacheWrite": 3.125
75756
+ "input": 1.25,
75757
+ "output": 7.5,
75758
+ "cacheRead": 0.125,
75759
+ "cacheWrite": 1.5625
75638
75760
  },
75639
75761
  "contextWindow": 1050000,
75640
75762
  "maxTokens": 128000,
@@ -75663,10 +75785,10 @@
75663
75785
  "image"
75664
75786
  ],
75665
75787
  "cost": {
75666
- "input": 2.5,
75667
- "output": 15,
75668
- "cacheRead": 0.25,
75669
- "cacheWrite": 3.125
75788
+ "input": 1.25,
75789
+ "output": 7.5,
75790
+ "cacheRead": 0.125,
75791
+ "cacheWrite": 1.5625
75670
75792
  },
75671
75793
  "contextWindow": 1050000,
75672
75794
  "maxTokens": 128000,
@@ -79676,9 +79798,9 @@
79676
79798
  "text"
79677
79799
  ],
79678
79800
  "cost": {
79679
- "input": 0.6692,
79680
- "output": 2.1032,
79681
- "cacheRead": 0.12428,
79801
+ "input": 0.7714000000000001,
79802
+ "output": 2.4244,
79803
+ "cacheRead": 0.14326,
79682
79804
  "cacheWrite": 0
79683
79805
  },
79684
79806
  "contextWindow": 1048576,
@@ -81152,6 +81274,40 @@
81152
81274
  "escapeBuiltinToolNames": true
81153
81275
  }
81154
81276
  },
81277
+ "umans-kimi-k3": {
81278
+ "id": "umans-kimi-k3",
81279
+ "name": "Umans Kimi K3 (prerelease)",
81280
+ "api": "anthropic-messages",
81281
+ "provider": "umans",
81282
+ "baseUrl": "https://api.code.umans.ai",
81283
+ "reasoning": true,
81284
+ "thinking": {
81285
+ "mode": "budget",
81286
+ "efforts": [
81287
+ "minimal",
81288
+ "low",
81289
+ "medium",
81290
+ "high",
81291
+ "xhigh"
81292
+ ]
81293
+ },
81294
+ "input": [
81295
+ "text",
81296
+ "image"
81297
+ ],
81298
+ "cost": {
81299
+ "input": 0,
81300
+ "output": 0,
81301
+ "cacheRead": 0,
81302
+ "cacheWrite": 0
81303
+ },
81304
+ "contextWindow": 1048576,
81305
+ "maxTokens": 131071,
81306
+ "supportsComputerUse": false,
81307
+ "compat": {
81308
+ "escapeBuiltinToolNames": true
81309
+ }
81310
+ },
81155
81311
  "umans-qwen3.6-35b-a3b": {
81156
81312
  "id": "umans-qwen3.6-35b-a3b",
81157
81313
  "name": "Umans Qwen3.6 35B A3B",
@@ -88444,6 +88600,37 @@
88444
88600
  },
88445
88601
  "supportsComputerUse": false
88446
88602
  },
88603
+ "moonshotai/kimi-k3-fast": {
88604
+ "id": "moonshotai/kimi-k3-fast",
88605
+ "name": "Kimi K3 Fast",
88606
+ "api": "anthropic-messages",
88607
+ "provider": "vercel-ai-gateway",
88608
+ "baseUrl": "https://ai-gateway.vercel.sh",
88609
+ "reasoning": true,
88610
+ "input": [
88611
+ "text",
88612
+ "image"
88613
+ ],
88614
+ "cost": {
88615
+ "input": 4.5,
88616
+ "output": 22.5,
88617
+ "cacheRead": 0.44999999999999996,
88618
+ "cacheWrite": 0
88619
+ },
88620
+ "contextWindow": 1000000,
88621
+ "maxTokens": 131072,
88622
+ "thinking": {
88623
+ "mode": "budget",
88624
+ "efforts": [
88625
+ "low",
88626
+ "high",
88627
+ "max"
88628
+ ],
88629
+ "defaultLevel": "max",
88630
+ "requiresEffort": true
88631
+ },
88632
+ "supportsComputerUse": false
88633
+ },
88447
88634
  "nvidia/nemotron-3-nano-30b-a3b": {
88448
88635
  "id": "nvidia/nemotron-3-nano-30b-a3b",
88449
88636
  "name": "Nemotron 3 Nano 30B A3B",
@@ -91404,9 +91591,9 @@
91404
91591
  "text"
91405
91592
  ],
91406
91593
  "cost": {
91407
- "input": 1.75,
91408
- "output": 5.5,
91409
- "cacheRead": 0.325,
91594
+ "input": 1.575,
91595
+ "output": 4.95,
91596
+ "cacheRead": 0.2875,
91410
91597
  "cacheWrite": 0
91411
91598
  },
91412
91599
  "contextWindow": 1048576,
package/src/models.ts CHANGED
@@ -48,10 +48,38 @@ export function calculateCost<TApi extends Api>(model: Model<TApi>, usage: Usage
48
48
  usage.cost.input = (model.cost.input / 1000000) * (usage.input + (orchestration?.input ?? 0));
49
49
  usage.cost.output = (model.cost.output / 1000000) * (usage.output + (orchestration?.output ?? 0));
50
50
  usage.cost.cacheRead = (model.cost.cacheRead / 1000000) * (usage.cacheRead + (orchestration?.cacheRead ?? 0));
51
- usage.cost.cacheWrite = (model.cost.cacheWrite / 1000000) * usage.cacheWrite;
51
+ usage.cost.cacheWrite = cacheWriteCost(model, usage);
52
52
  usage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;
53
53
  return usage.cost;
54
54
  }
55
+
56
+ /**
57
+ * Price cache-write tokens, honoring the TTL breakdown when the provider reports one.
58
+ *
59
+ * `model.cost.cacheWrite` is the 5-minute write rate (Anthropic bills 5m writes at
60
+ * 1.25x base input). When `usage.cttl` is present the write mixes 5m and 1h
61
+ * breakpoints — omp defaults to 1h retention on first-party Anthropic, and 1h writes
62
+ * bill at 2x base input — so each component is priced at its own rate instead of the
63
+ * flat 5m rate. Deriving 1h from `input * 2` (Anthropic's published multiplier) is
64
+ * model-independent and stays correct even for legacy entries whose stored
65
+ * `cacheWrite` scalar drifts from 1.25x input. Providers that omit `cttl`
66
+ * (everyone but Anthropic) keep the flat-rate calculation.
67
+ *
68
+ * The breakdown is documented to sum to `usage.cacheWrite`, but the two are written
69
+ * from independent wire fields (`cache_creation` vs `cache_creation_input_tokens`),
70
+ * so any unattributed remainder is priced at the flat rate instead of being dropped:
71
+ * a partial or stale breakdown must never make write tokens free.
72
+ */
73
+ function cacheWriteCost<TApi extends Api>(model: Model<TApi>, usage: Usage): number {
74
+ const rate5m = model.cost.cacheWrite / 1000000;
75
+ const cttl = usage.cttl;
76
+ if (!cttl) return rate5m * usage.cacheWrite;
77
+ const fiveMinute = cttl.ephemeral5m ?? 0;
78
+ const oneHour = cttl.ephemeral1h ?? 0;
79
+ const residual = Math.max(0, usage.cacheWrite - fiveMinute - oneHour);
80
+ return rate5m * (fiveMinute + residual) + ((model.cost.input * 2) / 1000000) * oneHour;
81
+ }
82
+
55
83
  /**
56
84
  * Check if two models are equal by comparing both their id and provider.
57
85
  * Returns false if either model is null or undefined.