pi-coralbricks-provider 1.0.27 → 1.0.28

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/README.md CHANGED
@@ -85,7 +85,7 @@ pi
85
85
 
86
86
  | Model | Context | Vision | Reasoning | Input $/M | Cache Read $/M | Cache Write $/M | Output $/M |
87
87
  |-------|---------|--------|-----------|-----------|-----------------|------------------|------------|
88
- | DeepSeek V4.1 Flash | 1.0M | ✅ | ✅ | $0.30 | — | $0.09 | $1.20 |
88
+ | DeepSeek V4.1 Flash | 1.0M | ✅ | ✅ | $0.01 | — | $0.09 | $1.20 |
89
89
  | GLM 5.3 | 1.0M | ❌ | ✅ | $1.12 | — | $1.68 | $4.40 |
90
90
 
91
91
  *Costs are per million tokens. Cache Read shows — because Coral bills cached input at **$0** on every model. Prompt tokens Coral has not cached yet are billed once at the Cache Write rate, in place of the Input rate. Prices subject to change — check [Coral's live catalog](https://www.coralbricks.ai/api/public/models).*
package/index.ts CHANGED
@@ -197,6 +197,17 @@ function toNumber(value: unknown): number {
197
197
  return typeof value === "number" && Number.isFinite(value) ? value : 0;
198
198
  }
199
199
 
200
+ /**
201
+ * Full price of a written prompt token. Since 2026-10-08 Coral states the cache write ON TOP
202
+ * of input (/v1/models cache_write_per_m, catalog cacheWritePerM), and a written token is
203
+ * billed input + that. pi prices a written token at cacheWrite alone, so add the two. 0 when
204
+ * the row carries no cache-write rate. Rounded so 1.12 + 0.56 is 1.68, not 1.6800000000000002.
205
+ */
206
+ function writtenTokenCost(input: number, cacheWriteOnTop: unknown): number {
207
+ if (typeof cacheWriteOnTop !== "number" || !Number.isFinite(cacheWriteOnTop)) return 0;
208
+ return Math.round((input + cacheWriteOnTop) * 1e6) / 1e6;
209
+ }
210
+
200
211
  function displayName(id: string): string {
201
212
  return id
202
213
  .split(/[-_/]/)
@@ -233,8 +244,9 @@ function baseCompat() {
233
244
  /**
234
245
  * Transform a Coral /v1/models row. Coral reports per-million USD pricing
235
246
  * (input_per_m / output_per_m / cached_input_per_m — cached reads are $0 on
236
- * every model — and cache_write_per_m, the rate for prompt tokens written to
237
- * the cache), context_length, and supports_image_input.
247
+ * every model — and cache_write_per_m, the cache write ON TOP of input for a
248
+ * prompt token written to the cache), context_length, and supports_image_input.
249
+ * pi's cacheWrite is the full price of a written token: input + cache_write_per_m.
238
250
  */
239
251
  function transformApiModel(apiModel: any): JsonModel | null {
240
252
  if (!apiModel?.id) return null;
@@ -248,7 +260,7 @@ function transformApiModel(apiModel: any): JsonModel | null {
248
260
  input: toNumber(pricing.input_per_m),
249
261
  output: toNumber(pricing.output_per_m),
250
262
  cacheRead: toNumber(pricing.cached_input_per_m),
251
- cacheWrite: toNumber(pricing.cache_write_per_m),
263
+ cacheWrite: writtenTokenCost(toNumber(pricing.input_per_m), pricing.cache_write_per_m),
252
264
  },
253
265
  contextWindow: parseContextWindow(apiModel.context_length),
254
266
  maxTokens: DEFAULT_MAX_TOKENS[apiModel.id] ?? FALLBACK_MAX_TOKENS,
@@ -261,10 +273,10 @@ function transformApiModel(apiModel: any): JsonModel | null {
261
273
  * Transform a row from the public model catalog
262
274
  * (https://www.coralbricks.ai/api/public/models) — the no-auth mirror of the
263
275
  * gateway control plane. Fields: slug, name, contextWindow ("1M"),
264
- * inputPerM / outputPerM. Coral's own prices are authoritative here; the
265
- * parity/field vendor comparison fields are ignored. The catalog carries no
266
- * cache-write rate, so cacheWrite stays 0 and mergeWithEmbedded keeps the
267
- * embedded rate.
276
+ * inputPerM / outputPerM, and since 2026-10-08 cacheWritePerM (the cache write on
277
+ * top of input). Coral's own prices are authoritative here; the parity/field vendor
278
+ * comparison fields are ignored. A row without cacheWritePerM leaves cacheWrite 0 so
279
+ * mergeWithEmbedded keeps the embedded rate.
268
280
  */
269
281
  function transformCatalogModel(entry: any): JsonModel | null {
270
282
  if (!entry?.slug) return null;
@@ -277,7 +289,7 @@ function transformCatalogModel(entry: any): JsonModel | null {
277
289
  input: toNumber(entry.inputPerM),
278
290
  output: toNumber(entry.outputPerM),
279
291
  cacheRead: 0,
280
- cacheWrite: 0,
292
+ cacheWrite: writtenTokenCost(toNumber(entry.inputPerM), entry.cacheWritePerM),
281
293
  },
282
294
  contextWindow: parseContextWindow(entry.contextWindow),
283
295
  maxTokens: DEFAULT_MAX_TOKENS[entry.slug] ?? FALLBACK_MAX_TOKENS,
package/models.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "image"
9
9
  ],
10
10
  "cost": {
11
- "input": 0.3,
11
+ "input": 0.01,
12
12
  "output": 1.2,
13
13
  "cacheRead": 0,
14
14
  "cacheWrite": 0.09
@@ -30,7 +30,7 @@
30
30
  "image"
31
31
  ],
32
32
  "cost": {
33
- "input": 0.3,
33
+ "input": 0.01,
34
34
  "output": 1.2,
35
35
  "cacheRead": 0,
36
36
  "cacheWrite": 0.09
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-coralbricks-provider",
3
- "version": "1.0.27",
3
+ "version": "1.0.28",
4
4
  "description": "CoralBricks provider extension for pi - Access GLM 5.3 and DeepSeek V4.1 Flash (FP4 variants included) through the Coral Inference API",
5
5
  "author": "monotykamary",
6
6
  "homepage": "https://github.com/monotykamary/pi-coralbricks-provider#readme",
@@ -166,6 +166,13 @@ function saveJson(filePath, data) {
166
166
  console.log(`✓ Saved ${path.basename(filePath)}`);
167
167
  }
168
168
 
169
+ // Coral states the cache write ON TOP of input (2026-10-08); pi's cacheWrite is the full
170
+ // price of a written token, input + it. 0 when the row has no cache-write rate.
171
+ function writtenTokenCost(input, cacheWriteOnTop) {
172
+ if (typeof cacheWriteOnTop !== 'number' || !Number.isFinite(cacheWriteOnTop)) return 0;
173
+ return Math.round((input + cacheWriteOnTop) * 1e6) / 1e6;
174
+ }
175
+
169
176
  function toNumber(value) {
170
177
  return typeof value === 'number' && Number.isFinite(value) ? value : 0;
171
178
  }
@@ -274,7 +281,9 @@ function transformApiModel(apiModel, existingModelsMap) {
274
281
  if (typeof pricing.input_per_m === 'number') existing.cost.input = pricing.input_per_m;
275
282
  if (typeof pricing.output_per_m === 'number') existing.cost.output = pricing.output_per_m;
276
283
  existing.cost.cacheRead = toNumber(pricing.cached_input_per_m);
277
- if (typeof pricing.cache_write_per_m === 'number') existing.cost.cacheWrite = pricing.cache_write_per_m;
284
+ if (typeof pricing.cache_write_per_m === 'number') {
285
+ existing.cost.cacheWrite = writtenTokenCost(existing.cost.input, pricing.cache_write_per_m);
286
+ }
278
287
  existing.input = input;
279
288
  return existing;
280
289
  }
@@ -289,7 +298,7 @@ function transformApiModel(apiModel, existingModelsMap) {
289
298
  input: toNumber(pricing.input_per_m),
290
299
  output: toNumber(pricing.output_per_m),
291
300
  cacheRead: toNumber(pricing.cached_input_per_m),
292
- cacheWrite: toNumber(pricing.cache_write_per_m),
301
+ cacheWrite: writtenTokenCost(toNumber(pricing.input_per_m), pricing.cache_write_per_m),
293
302
  },
294
303
  contextWindow,
295
304
  maxTokens,
@@ -311,6 +320,9 @@ function transformCatalogModel(entry, existingModelsMap) {
311
320
  if (contextWindow) existing.contextWindow = contextWindow;
312
321
  if (typeof entry.inputPerM === 'number') existing.cost.input = entry.inputPerM;
313
322
  if (typeof entry.outputPerM === 'number') existing.cost.output = entry.outputPerM;
323
+ if (typeof entry.cacheWritePerM === 'number') {
324
+ existing.cost.cacheWrite = writtenTokenCost(existing.cost.input, entry.cacheWritePerM);
325
+ }
314
326
  return existing;
315
327
  }
316
328
 
@@ -323,7 +335,7 @@ function transformCatalogModel(entry, existingModelsMap) {
323
335
  input: toNumber(entry.inputPerM),
324
336
  output: toNumber(entry.outputPerM),
325
337
  cacheRead: 0,
326
- cacheWrite: 0,
338
+ cacheWrite: writtenTokenCost(toNumber(entry.inputPerM), entry.cacheWritePerM),
327
339
  },
328
340
  contextWindow,
329
341
  maxTokens,