pi-coralbricks-provider 1.0.25 → 1.0.26
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 +8 -6
- package/deprecated-models.json +1 -103
- package/models.json +47 -3
- package/package.json +2 -2
- package/patch.json +2 -16
- package/scripts/update-models.js +39 -9
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# 🪸 pi-coralbricks-provider
|
|
4
4
|
|
|
5
|
-
**GLM 5.3
|
|
5
|
+
**GLM 5.3 & DeepSeek V4.1 Flash (FP4 variants included) through [Coral Bricks](https://www.coralbricks.ai)**
|
|
6
6
|
|
|
7
7
|
_A [pi](https://github.com/earendil-works/pi-coding-agent) provider extension for Coral's OpenAI-compatible inference gateway — up to **1M context** on open models._
|
|
8
8
|
|
|
@@ -22,8 +22,8 @@ Run `bun run test:pi` for offline manifest, catalog, lifecycle and streaming che
|
|
|
22
22
|
|
|
23
23
|
## Features
|
|
24
24
|
|
|
25
|
-
- **
|
|
26
|
-
- **1M token context** on GLM and DeepSeek, with vision (image input) on
|
|
25
|
+
- **4 reasoning models** from Coral's live catalog — GLM 5.3 and its FP4 variant, DeepSeek V4.1 Flash and its FP4 variant
|
|
26
|
+
- **1M token context** on GLM and DeepSeek, with vision (image input) on DeepSeek V4.1 Flash and its FP4 variant
|
|
27
27
|
- **OpenAI-compatible API** — standard `/v1/chat/completions`, streaming, and tool calling
|
|
28
28
|
- **Per-family thinking levels** — zai-style `thinking` control for GLM (including a *real* off switch), `reasoning_effort` for DeepSeek V4.1 Flash
|
|
29
29
|
- **Accurate cost tracking** — input, cache-write and output rates mirror Coral's [published pricing](https://www.coralbricks.ai/pricing), and cached reads are **$0 on every model**
|
|
@@ -86,7 +86,9 @@ pi
|
|
|
86
86
|
| Model | Context | Vision | Reasoning | Input $/M | Cache Read $/M | Cache Write $/M | Output $/M |
|
|
87
87
|
|-------|---------|--------|-----------|-----------|-----------------|------------------|------------|
|
|
88
88
|
| DeepSeek V4.1 Flash | 1.0M | ✅ | ✅ | $0.30 | — | $0.09 | $1.20 |
|
|
89
|
+
| DeepSeek V4.1 Flash FP4 | 1.0M | ✅ | ✅ | $0.30 | — | $0.09 | $1.20 |
|
|
89
90
|
| GLM 5.3 | 1.0M | ❌ | ✅ | $1.12 | — | $1.68 | $4.40 |
|
|
91
|
+
| GLM 5.3 FP4 | 1.0M | ❌ | ✅ | $1.12 | — | $1.68 | $4.40 |
|
|
90
92
|
|
|
91
93
|
*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).*
|
|
92
94
|
|
|
@@ -168,7 +170,7 @@ Verified against the live gateway:
|
|
|
168
170
|
| Model | Format | off | low | medium | high | max |
|
|
169
171
|
|-------|--------|-----|-----|--------|------|-----|
|
|
170
172
|
| GLM 5.3 FP4 | `thinking: {type}` + `reasoning_effort` | ✅ | ✅ | — | ✅ | ✅ |
|
|
171
|
-
| GLM 5.3 Flash | `thinking: {type}` + `reasoning_effort` | ✅ | ✅ | — | ✅ | ✅ |
|
|
173
|
+
| GLM 5.3 Flash (retired) | `thinking: {type}` + `reasoning_effort` | ✅ | ✅ | — | ✅ | ✅ |
|
|
172
174
|
| DeepSeek V4.1 Flash | `reasoning_effort` | ✅ | ✅ | — | ✅ | ✅ |
|
|
173
175
|
|
|
174
176
|
- **GLM** accepts zai-style `thinking: {type: "disabled"}` on Coral — pi's *off* level turns thinking off, though a short preamble of a few dozen tokens can still appear (the upstream Z.ai API has no off at all, so this differs from the canonical Z.ai map).
|
|
@@ -186,7 +188,7 @@ Coral's gateway follows the OpenAI Chat Completions API:
|
|
|
186
188
|
|
|
187
189
|
### Patch Overrides & Custom Models
|
|
188
190
|
|
|
189
|
-
- **`patch.json`** — per-model overrides applied on top of `models.json` (reasoning flags, pricing corrections, compat settings, thinking level maps). Currently
|
|
191
|
+
- **`patch.json`** — per-model overrides applied on top of `models.json` (reasoning flags, pricing corrections, compat settings, thinking level maps). Currently one entry per live model: GLM 5.3 and its FP4 twin (reasoning, thinking level map, zai-style compat settings) and DeepSeek V4.1 Flash and its FP4 twin (reasoning, image input, thinking level map, `openai`-style compat settings).
|
|
190
192
|
- **`custom-models.json`** — full model definitions for models Coral doesn't list. Merged after patch.
|
|
191
193
|
|
|
192
194
|
Merge order: `[live|cache|embedded] → patch.json → custom-models.json`
|
|
@@ -198,7 +200,7 @@ Validated with [synbad](https://github.com/synthetic-lab/synbad) — Synthetic's
|
|
|
198
200
|
| Model | Unary | Stream | Notes |
|
|
199
201
|
|-------|-------|--------|-------|
|
|
200
202
|
| GLM 5.3 FP4 | 13/13 ✅ | 13/13 ✅ | 5/5 runs |
|
|
201
|
-
| GLM 5.3 Flash | 12/13 ⚠️ | 12/13 ⚠️ | `reasoning/reasoning-parsing` passes 4 of 5 runs; see below |
|
|
203
|
+
| GLM 5.3 Flash (retired) | 12/13 ⚠️ | 12/13 ⚠️ | `reasoning/reasoning-parsing` passes 4 of 5 runs; see below |
|
|
202
204
|
| GPT-OSS 120B (retired) | 12/13 ⚠️ | 12/13 ⚠️ | `tools/parallel-tool` 0 of 5 runs, before Coral retired the model |
|
|
203
205
|
| DeepSeek V4.1 Flash | 12/13 ⚠️ | 12/13 ⚠️ | `tools/octo-list-no-optional-args` passes 1 of 5 runs; see below |
|
|
204
206
|
| Kimi K3 (retired) | 13/13 ✅ | 13/13 ✅ | 5/5 runs, before Coral retired the model |
|
package/deprecated-models.json
CHANGED
|
@@ -1,103 +1 @@
|
|
|
1
|
-
{
|
|
2
|
-
"deepseek-v4.1-flash-fast-fp4": {
|
|
3
|
-
"id": "deepseek-v4.1-flash-fast-fp4",
|
|
4
|
-
"name": "DeepSeek V4.1 Flash",
|
|
5
|
-
"reasoning": false,
|
|
6
|
-
"input": [
|
|
7
|
-
"text",
|
|
8
|
-
"image"
|
|
9
|
-
],
|
|
10
|
-
"cost": {
|
|
11
|
-
"input": 0.3,
|
|
12
|
-
"output": 1.2,
|
|
13
|
-
"cacheRead": 0,
|
|
14
|
-
"cacheWrite": 0.09
|
|
15
|
-
},
|
|
16
|
-
"contextWindow": 1048576,
|
|
17
|
-
"maxTokens": 32768,
|
|
18
|
-
"compat": {
|
|
19
|
-
"supportsDeveloperRole": false,
|
|
20
|
-
"supportsStore": false,
|
|
21
|
-
"maxTokensField": "max_tokens"
|
|
22
|
-
},
|
|
23
|
-
"deprecatedAt": "2026-10-05T00:00:07.034Z"
|
|
24
|
-
},
|
|
25
|
-
"glm-5.3-flash-fp4": {
|
|
26
|
-
"id": "glm-5.3-flash-fp4",
|
|
27
|
-
"name": "GLM 5.3 Flash",
|
|
28
|
-
"reasoning": false,
|
|
29
|
-
"input": [
|
|
30
|
-
"text",
|
|
31
|
-
"image"
|
|
32
|
-
],
|
|
33
|
-
"cost": {
|
|
34
|
-
"input": 0.15,
|
|
35
|
-
"output": 0.5,
|
|
36
|
-
"cacheRead": 0,
|
|
37
|
-
"cacheWrite": 0.23
|
|
38
|
-
},
|
|
39
|
-
"contextWindow": 1048576,
|
|
40
|
-
"maxTokens": 32768,
|
|
41
|
-
"compat": {
|
|
42
|
-
"supportsDeveloperRole": false,
|
|
43
|
-
"supportsStore": false,
|
|
44
|
-
"maxTokensField": "max_tokens"
|
|
45
|
-
},
|
|
46
|
-
"deprecatedAt": "2026-10-05T00:00:07.034Z"
|
|
47
|
-
},
|
|
48
|
-
"glm-5.3-fp4": {
|
|
49
|
-
"id": "glm-5.3-fp4",
|
|
50
|
-
"name": "GLM 5.3 FP4",
|
|
51
|
-
"reasoning": true,
|
|
52
|
-
"input": [
|
|
53
|
-
"text"
|
|
54
|
-
],
|
|
55
|
-
"cost": {
|
|
56
|
-
"input": 1.12,
|
|
57
|
-
"output": 4.4,
|
|
58
|
-
"cacheRead": 0,
|
|
59
|
-
"cacheWrite": 1.68
|
|
60
|
-
},
|
|
61
|
-
"contextWindow": 1048576,
|
|
62
|
-
"maxTokens": 131072,
|
|
63
|
-
"thinkingLevelMap": {
|
|
64
|
-
"off": "none",
|
|
65
|
-
"minimal": null,
|
|
66
|
-
"low": "low",
|
|
67
|
-
"medium": null,
|
|
68
|
-
"high": "high",
|
|
69
|
-
"xhigh": null,
|
|
70
|
-
"max": "max"
|
|
71
|
-
},
|
|
72
|
-
"compat": {
|
|
73
|
-
"supportsStore": false,
|
|
74
|
-
"supportsDeveloperRole": false,
|
|
75
|
-
"supportsReasoningEffort": true,
|
|
76
|
-
"maxTokensField": "max_tokens",
|
|
77
|
-
"thinkingFormat": "zai"
|
|
78
|
-
},
|
|
79
|
-
"deprecatedAt": "2026-10-05T00:00:07.034Z"
|
|
80
|
-
},
|
|
81
|
-
"glm-5.3-flash-fast": {
|
|
82
|
-
"id": "glm-5.3-flash-fast",
|
|
83
|
-
"name": "GLM 5.3 Flash",
|
|
84
|
-
"reasoning": false,
|
|
85
|
-
"input": [
|
|
86
|
-
"text"
|
|
87
|
-
],
|
|
88
|
-
"cost": {
|
|
89
|
-
"input": 0.15,
|
|
90
|
-
"output": 0.5,
|
|
91
|
-
"cacheRead": 0,
|
|
92
|
-
"cacheWrite": 0
|
|
93
|
-
},
|
|
94
|
-
"contextWindow": 1048576,
|
|
95
|
-
"maxTokens": 32768,
|
|
96
|
-
"compat": {
|
|
97
|
-
"supportsDeveloperRole": false,
|
|
98
|
-
"supportsStore": false,
|
|
99
|
-
"maxTokensField": "max_tokens"
|
|
100
|
-
},
|
|
101
|
-
"deprecatedAt": "2026-10-07T00:00:09.219Z"
|
|
102
|
-
}
|
|
103
|
-
}
|
|
1
|
+
{}
|
package/models.json
CHANGED
|
@@ -4,13 +4,36 @@
|
|
|
4
4
|
"name": "DeepSeek V4.1 Flash",
|
|
5
5
|
"reasoning": false,
|
|
6
6
|
"input": [
|
|
7
|
-
"text"
|
|
7
|
+
"text",
|
|
8
|
+
"image"
|
|
9
|
+
],
|
|
10
|
+
"cost": {
|
|
11
|
+
"input": 0.3,
|
|
12
|
+
"output": 1.2,
|
|
13
|
+
"cacheRead": 0,
|
|
14
|
+
"cacheWrite": 0.09
|
|
15
|
+
},
|
|
16
|
+
"contextWindow": 1048576,
|
|
17
|
+
"maxTokens": 32768,
|
|
18
|
+
"compat": {
|
|
19
|
+
"supportsDeveloperRole": false,
|
|
20
|
+
"supportsStore": false,
|
|
21
|
+
"maxTokensField": "max_tokens"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"id": "deepseek-v4.1-flash-fast-fp4",
|
|
26
|
+
"name": "Deepseek V4.1 Flash Fast Fp4",
|
|
27
|
+
"reasoning": false,
|
|
28
|
+
"input": [
|
|
29
|
+
"text",
|
|
30
|
+
"image"
|
|
8
31
|
],
|
|
9
32
|
"cost": {
|
|
10
33
|
"input": 0.3,
|
|
11
34
|
"output": 1.2,
|
|
12
35
|
"cacheRead": 0,
|
|
13
|
-
"cacheWrite": 0
|
|
36
|
+
"cacheWrite": 0.09
|
|
14
37
|
},
|
|
15
38
|
"contextWindow": 1048576,
|
|
16
39
|
"maxTokens": 32768,
|
|
@@ -31,7 +54,28 @@
|
|
|
31
54
|
"input": 1.12,
|
|
32
55
|
"output": 4.4,
|
|
33
56
|
"cacheRead": 0,
|
|
34
|
-
"cacheWrite":
|
|
57
|
+
"cacheWrite": 1.68
|
|
58
|
+
},
|
|
59
|
+
"contextWindow": 1048576,
|
|
60
|
+
"maxTokens": 32768,
|
|
61
|
+
"compat": {
|
|
62
|
+
"supportsDeveloperRole": false,
|
|
63
|
+
"supportsStore": false,
|
|
64
|
+
"maxTokensField": "max_tokens"
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"id": "glm-5.3-fp4",
|
|
69
|
+
"name": "Glm 5.3 Fp4",
|
|
70
|
+
"reasoning": false,
|
|
71
|
+
"input": [
|
|
72
|
+
"text"
|
|
73
|
+
],
|
|
74
|
+
"cost": {
|
|
75
|
+
"input": 1.12,
|
|
76
|
+
"output": 4.4,
|
|
77
|
+
"cacheRead": 0,
|
|
78
|
+
"cacheWrite": 1.68
|
|
35
79
|
},
|
|
36
80
|
"contextWindow": 1048576,
|
|
37
81
|
"maxTokens": 32768,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-coralbricks-provider",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "CoralBricks provider extension for pi - Access GLM 5.3
|
|
3
|
+
"version": "1.0.26",
|
|
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",
|
|
7
7
|
"repository": {
|
package/patch.json
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
"compat": { "supportsReasoningEffort": true, "thinkingFormat": "openai" }
|
|
8
8
|
},
|
|
9
9
|
"deepseek-v4.1-flash-fast-fp4": {
|
|
10
|
+
"name": "DeepSeek V4.1 Flash FP4",
|
|
10
11
|
"reasoning": true,
|
|
11
12
|
"input": ["text", "image"],
|
|
12
13
|
"thinkingLevelMap": { "off": "none", "minimal": null, "low": "low", "medium": null, "high": "high", "xhigh": null, "max": "max" },
|
|
@@ -21,26 +22,11 @@
|
|
|
21
22
|
"compat": { "supportsReasoningEffort": true, "thinkingFormat": "zai" }
|
|
22
23
|
},
|
|
23
24
|
"glm-5.3-fp4": {
|
|
25
|
+
"name": "GLM 5.3 FP4",
|
|
24
26
|
"reasoning": true,
|
|
25
27
|
"thinkingLevelMap": { "off": "none", "minimal": null, "low": "low", "medium": null, "high": "high", "xhigh": null, "max": "max" },
|
|
26
28
|
"maxTokens": 131072,
|
|
27
29
|
"cost": { "cacheWrite": 1.68 },
|
|
28
30
|
"compat": { "supportsReasoningEffort": true, "thinkingFormat": "zai" }
|
|
29
|
-
},
|
|
30
|
-
"glm-5.3-flash-fast": {
|
|
31
|
-
"reasoning": true,
|
|
32
|
-
"input": ["text", "image"],
|
|
33
|
-
"thinkingLevelMap": { "off": "none", "minimal": null, "low": "low", "medium": null, "high": "high", "xhigh": null, "max": "max" },
|
|
34
|
-
"maxTokens": 131072,
|
|
35
|
-
"cost": { "cacheWrite": 0.23 },
|
|
36
|
-
"compat": { "supportsReasoningEffort": true, "thinkingFormat": "zai" }
|
|
37
|
-
},
|
|
38
|
-
"glm-5.3-flash-fp4": {
|
|
39
|
-
"reasoning": true,
|
|
40
|
-
"input": ["text", "image"],
|
|
41
|
-
"thinkingLevelMap": { "off": "none", "minimal": null, "low": "low", "medium": null, "high": "high", "xhigh": null, "max": "max" },
|
|
42
|
-
"maxTokens": 131072,
|
|
43
|
-
"cost": { "cacheWrite": 0.23 },
|
|
44
|
-
"compat": { "supportsReasoningEffort": true, "thinkingFormat": "zai" }
|
|
45
31
|
}
|
|
46
32
|
}
|
package/scripts/update-models.js
CHANGED
|
@@ -14,6 +14,10 @@
|
|
|
14
14
|
* same control-plane data without a key (contextWindow like "1M", inputPerM,
|
|
15
15
|
* outputPerM). Used when no key is configured or /v1/models fails.
|
|
16
16
|
*
|
|
17
|
+
* The catalog is a subset: it lists each model's canonical slug, not every
|
|
18
|
+
* variant enabled for a key, so a catalog run only ever adds or keeps models —
|
|
19
|
+
* it never delists one (see keepUnlistedModels).
|
|
20
|
+
*
|
|
17
21
|
* models.json is the source of truth for curated specs — the script preserves
|
|
18
22
|
* existing data and only adds new models with API-derived defaults.
|
|
19
23
|
* Curate models.json manually after new model discovery.
|
|
@@ -219,18 +223,38 @@ async function fetchPublicCatalog() {
|
|
|
219
223
|
return models;
|
|
220
224
|
}
|
|
221
225
|
|
|
222
|
-
async function fetchModels() {
|
|
223
|
-
const apiKey = resolveApiKey();
|
|
226
|
+
async function fetchModels(apiKey) {
|
|
224
227
|
if (apiKey) {
|
|
225
228
|
try {
|
|
226
|
-
return await fetchV1Models(apiKey);
|
|
229
|
+
return { models: await fetchV1Models(apiKey), authoritative: true };
|
|
227
230
|
} catch (error) {
|
|
228
231
|
console.warn(`⚠ /v1/models failed (${error.message}); falling back to public catalog`);
|
|
229
232
|
}
|
|
230
233
|
} else {
|
|
231
234
|
console.warn('⚠ No API key found (no `coralbricks` credential in ' + AUTH_JSON_PATH + ', CORALBRICKS_API_KEY unset); using the public catalog');
|
|
232
235
|
}
|
|
233
|
-
return fetchPublicCatalog();
|
|
236
|
+
return { models: await fetchPublicCatalog(), authoritative: false };
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* The public catalog is a subset of the per-key /v1/models set: it advertises a
|
|
241
|
+
* model's canonical slug, not every variant enabled for the key (the -fp4 twins
|
|
242
|
+
* are listed by /v1/models only). It can vouch for what exists, never for what
|
|
243
|
+
* is gone, so a non-authoritative fetch keeps every already-known model it does
|
|
244
|
+
* not list: a keyless run may discover models, it may not delist them. Returns
|
|
245
|
+
* the ids it kept, in the order they were appended.
|
|
246
|
+
*/
|
|
247
|
+
function keepUnlistedModels(models, existingModelsMap, authoritative) {
|
|
248
|
+
if (authoritative) return [];
|
|
249
|
+
const seen = new Set(models.map((m) => m.id));
|
|
250
|
+
const kept = [];
|
|
251
|
+
for (const [id, existing] of Object.entries(existingModelsMap)) {
|
|
252
|
+
if (!seen.has(id)) {
|
|
253
|
+
models.push(existing);
|
|
254
|
+
kept.push(id);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return kept;
|
|
234
258
|
}
|
|
235
259
|
|
|
236
260
|
// Transform API model → models.json entry
|
|
@@ -547,7 +571,8 @@ async function main() {
|
|
|
547
571
|
return;
|
|
548
572
|
}
|
|
549
573
|
|
|
550
|
-
const
|
|
574
|
+
const apiKey = resolveApiKey();
|
|
575
|
+
const { models: apiModels, authoritative } = await fetchModels(apiKey);
|
|
551
576
|
|
|
552
577
|
// Load existing models.json — source of truth for curated specs
|
|
553
578
|
const existingModels = loadJson(MODELS_JSON_PATH);
|
|
@@ -562,15 +587,20 @@ async function main() {
|
|
|
562
587
|
isCatalogShape ? transformCatalogModel(m, existingModelsMap) : transformApiModel(m, existingModelsMap)
|
|
563
588
|
);
|
|
564
589
|
|
|
565
|
-
// Live API is authoritative — models absent from
|
|
566
|
-
//
|
|
590
|
+
// Live API is authoritative — models absent from it are removed (embedded
|
|
591
|
+
// data is already used for enrichment in transformApiModel). A catalog run
|
|
592
|
+
// is not: keep every known model it does not list.
|
|
593
|
+
const kept = keepUnlistedModels(models, existingModelsMap, authoritative);
|
|
594
|
+
if (kept.length > 0) {
|
|
595
|
+
console.warn(`⚠ Public catalog listed ${kept.length} fewer model(s) than models.json; kept: ${kept.join(', ')}`);
|
|
596
|
+
}
|
|
567
597
|
|
|
568
598
|
// Sort by model name
|
|
569
599
|
models.sort((a, b) => a.name.localeCompare(b.name));
|
|
570
600
|
|
|
571
601
|
// Save models.json (pure API output, no patch/custom baked in)
|
|
572
602
|
// Move delisted models to deprecated-models.json BEFORE models.json is overwritten
|
|
573
|
-
await updateDeprecatedModels(MODELS_JSON_PATH, models,
|
|
603
|
+
await updateDeprecatedModels(MODELS_JSON_PATH, models, apiKey);
|
|
574
604
|
saveJson(MODELS_JSON_PATH, models);
|
|
575
605
|
|
|
576
606
|
// Build the README model list: base → patch → custom. Grace-period models stay
|
|
@@ -608,4 +638,4 @@ if (process.argv[1] && path.resolve(process.argv[1]) === path.resolve(fileURLToP
|
|
|
608
638
|
main();
|
|
609
639
|
}
|
|
610
640
|
|
|
611
|
-
export { isRetiredUpstream, updateDeprecatedModels };
|
|
641
|
+
export { isRetiredUpstream, keepUnlistedModels, updateDeprecatedModels };
|