pi-tarmis-provider 1.1.0 → 1.1.2

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
@@ -27,13 +27,13 @@ _One OpenAI-compatible API to open models on Tarmis's own GPUs — DeepSeek, GLM
27
27
 
28
28
  ## Available Models
29
29
 
30
- | Model | Context | Vision | Reasoning | Input $/M | Output $/M |
31
- |-------|---------|--------|-----------|-----------|------------|
32
- | DeepSeek V4 Flash | 1.0M | ❌ | ✅ | $0.09 | $0.18 |
33
- | DeepSeek V4 Pro | 1.0M | ❌ | ✅ | $0.43 | $0.87 |
34
- | GLM-5.2 | 1.0M | ❌ | ✅ | $0.60 | $2.20 |
35
- | Kimi K3 | 1.0M | ✅ | ✅ | $2.50 | $10.00 |
36
- | MiniMax M3 | 524K | ❌ | ✅ | $0.30 | $1.20 |
30
+ | Model | Context | Vision | Reasoning | Input $/M | Cache Read $/M | Output $/M |
31
+ |-------|---------|--------|-----------|-----------|-----------------|------------|
32
+ | DeepSeek V4 Flash | 1.0M | ❌ | ✅ | $0.09 | $0.02 | $0.18 |
33
+ | DeepSeek V4 Pro | 1.0M | ❌ | ✅ | $0.43 | $0.09 | $0.87 |
34
+ | GLM-5.2 | 1.0M | ❌ | ✅ | $0.60 | $0.14 | $2.20 |
35
+ | Kimi K3 | 1.0M | ✅ | ✅ | $2.50 | $0.25 | $10.00 |
36
+ | MiniMax M3 | 524K | ❌ | ✅ | $0.30 | $0.06 | $1.20 |
37
37
 
38
38
  > The table above is regenerated by `node scripts/update-models.js` from the live Tarmis API. Costs are per million tokens (the API reports per-token prices). Prices subject to change — check [docs.tarmis.ai/docs/pricing](https://docs.tarmis.ai/docs/pricing) for current pricing.
39
39
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-tarmis-provider",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "description": "Tarmis provider extension for pi - Open models on Tarmis's own GPUs via an OpenAI-compatible API",
5
5
  "type": "module",
6
6
  "main": "index.ts",
@@ -47,7 +47,7 @@
47
47
  ]
48
48
  },
49
49
  "devDependencies": {
50
- "@earendil-works/pi-coding-agent": "^0.84.2",
50
+ "@earendil-works/pi-coding-agent": "^0.84.3",
51
51
  "@types/node": "^25.9.1",
52
52
  "typescript": "^6.0.3"
53
53
  },
@@ -286,8 +286,9 @@ function loadJson(filePath, fallback) {
286
286
 
287
287
  function formatCost(cost, isFree) {
288
288
  if (isFree) return '**Free**';
289
- if (cost === 0) return '-';
290
- return `$${cost.toFixed(2)}`;
289
+ if (cost === 0) return '—';
290
+ if (cost === null || cost === undefined) return '—';
291
+ return '$' + cost.toFixed(2);
291
292
  }
292
293
 
293
294
  function formatContextWindow(n) {
@@ -298,8 +299,8 @@ function formatContextWindow(n) {
298
299
 
299
300
  function generateReadmeTable(models) {
300
301
  const lines = [
301
- '| Model | Context | Vision | Reasoning | Input $/M | Output $/M |',
302
- '|-------|---------|--------|-----------|-----------|------------|',
302
+ '| Model | Context | Vision | Reasoning | Input $/M | Cache Read $/M | Output $/M |',
303
+ '|-------|---------|--------|-----------|-----------|-----------------|------------|',
303
304
  ];
304
305
 
305
306
  for (const model of models) {
@@ -309,9 +310,10 @@ function generateReadmeTable(models) {
309
310
  const reasoning = model.reasoning ? '✅' : '❌';
310
311
  const isFree = model._meta?.isFree ?? (model.cost.input === 0 && model.cost.output === 0);
311
312
  const inputCost = formatCost(model.cost.input, isFree);
313
+ const cacheReadCost = formatCost(model.cost.cacheRead, isFree);
312
314
  const outputCost = formatCost(model.cost.output, isFree);
313
315
 
314
- lines.push(`| ${name} | ${context} | ${vision} | ${reasoning} | ${inputCost} | ${outputCost} |`);
316
+ lines.push(`| ${name} | ${context} | ${vision} | ${reasoning} | ${inputCost} | ${cacheReadCost} | ${outputCost} |`);
315
317
  }
316
318
 
317
319
  return lines.join('\n');
@@ -400,6 +402,31 @@ function updateDeprecatedModels(modelsJsonPath, newModels) {
400
402
  }
401
403
  }
402
404
 
405
+ /**
406
+ * Grace-period deprecated models (deprecatedAt within TTL) with metadata stripped.
407
+ * Keeps the README table serving models that are delisted but still within their
408
+ * 14-day grace window.
409
+ */
410
+ function withDeprecatedForReadme(models) {
411
+ const deprecatedPath = path.join(path.dirname(MODELS_JSON_PATH), 'deprecated-models.json');
412
+ let deprecated = {};
413
+ try {
414
+ const parsed = JSON.parse(fs.readFileSync(deprecatedPath, 'utf8'));
415
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) deprecated = parsed;
416
+ } catch { /* no graveyard yet */ }
417
+ const now = Date.now();
418
+ const seen = new Set(models.map(m => m.id));
419
+ const extras = [];
420
+ for (const entry of Object.values(deprecated)) {
421
+ if (!entry || !entry.id || seen.has(entry.id)) continue;
422
+ const removedAt = Date.parse(entry.deprecatedAt || '');
423
+ if (Number.isNaN(removedAt) || now - removedAt > DEPRECATED_MODEL_TTL_MS) continue;
424
+ const m = { ...entry };
425
+ delete m.deprecatedAt;
426
+ extras.push(m);
427
+ }
428
+ return extras.length > 0 ? [...models, ...extras] : models;
429
+ }
403
430
  async function main() {
404
431
  console.log(`Fetching models from ${MODELS_API_URL}...`);
405
432
 
@@ -464,7 +491,7 @@ async function main() {
464
491
  // Build full model list for README: base -> patch -> custom
465
492
  const customModels = loadJson(CUSTOM_MODELS_JSON_PATH, []);
466
493
  const readmeModels = buildModels(
467
- apiTransformed,
494
+ withDeprecatedForReadme(apiTransformed),
468
495
  Array.isArray(customModels) ? customModels : [],
469
496
  patch
470
497
  );