pi-opencode-go-provider 1.0.5 → 1.0.7
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/AGENTS.md +1 -0
- package/README.md +8 -4
- package/deprecated-models.json +1 -0
- package/index.ts +34 -1
- package/models.json +143 -68
- package/package.json +1 -1
- package/patch.json +152 -8
- package/scripts/update-models.js +107 -2
package/AGENTS.md
CHANGED
|
@@ -7,6 +7,7 @@ The following files are **idempotent** and regenerated by `scripts/update-models
|
|
|
7
7
|
| File | Why it's auto-generated |
|
|
8
8
|
|------|------------------------|
|
|
9
9
|
| `models.json` | Built from the provider API. `update-models.js` fetches models, preserves curated data for known IDs, and writes this file. |
|
|
10
|
+
| `deprecated-models.json` | Graveyard for models the API delisted. update-models.js stamps them with deprecatedAt and pi keeps serving them for a 2-week grace period, then evicts them. Never edit by hand. |
|
|
10
11
|
| `README.md` (model table) | The table under `## Available Models` is replaced in-place by `update-models.js` after merging base models → patch → custom models. |
|
|
11
12
|
|
|
12
13
|
## Correct Files to Edit
|
package/README.md
CHANGED
|
@@ -69,16 +69,20 @@ pi
|
|
|
69
69
|
| Model | API | Type | Context | Max Tokens | Input Cost | Output Cost |
|
|
70
70
|
|-------|-----|------|---------|------------|------------|-------------|
|
|
71
71
|
| DeepSeek V4 Flash | Completions | Text | 1.0M | 384K | $0.14 | $0.28 |
|
|
72
|
-
| DeepSeek V4 Pro | Completions | Text | 1.0M | 384K | $
|
|
72
|
+
| DeepSeek V4 Pro | Completions | Text | 1.0M | 384K | $0.43 | $0.87 |
|
|
73
73
|
| GLM-5.1 | Completions | Text | 203K | 33K | $1.40 | $4.40 |
|
|
74
74
|
| GLM-5.2 | Completions | Text | 1.0M | 131K | $1.40 | $4.40 |
|
|
75
|
+
| GPT-5.6 Luna (2x usage) | Completions | Text + Image | 1.1M | 128K | $0.10 | $0.60 |
|
|
76
|
+
| Grok 4.5 | Responses | Text + Image | 500K | 500K | $2.00 | $6.00 |
|
|
77
|
+
| Hy3 | Completions | Text | 256K | 64K | $0.14 | $0.58 |
|
|
75
78
|
| Kimi K2.6 | Completions | Text + Image | 262K | 66K | $0.95 | $4.00 |
|
|
76
79
|
| Kimi K2.7 Code | Completions | Text + Image | 262K | 262K | $0.95 | $4.00 |
|
|
80
|
+
| Kimi K3 (2x usage) | Completions | Text + Image | 1.0M | 131K | $3.00 | $15.00 |
|
|
77
81
|
| MiMo V2.5 | Completions | Text + Image | 1.0M | 128K | $0.14 | $0.28 |
|
|
78
|
-
| MiMo V2.5 Pro | Completions | Text | 1.0M | 128K | $
|
|
79
|
-
| MiniMax-M2.7 |
|
|
82
|
+
| MiMo V2.5 Pro | Completions | Text | 1.0M | 128K | $0.43 | $0.87 |
|
|
83
|
+
| MiniMax-M2.7 | Completions | Text | 205K | 131K | $0.30 | $1.20 |
|
|
80
84
|
| MiniMax-M3 | Anthropic | Text + Image | 1.0M | 131K | $0.30 | $1.20 |
|
|
81
|
-
| Qwen3.6 Plus |
|
|
85
|
+
| Qwen3.6 Plus | Completions | Text + Image | 1.0M | 66K | $0.50 | $3.00 |
|
|
82
86
|
| Qwen3.7 Max | Anthropic | Text | 1.0M | 66K | $2.50 | $7.50 |
|
|
83
87
|
| Qwen3.7 Plus | Anthropic | Text + Image | 1.0M | 66K | $0.40 | $1.60 |
|
|
84
88
|
*Costs are per million tokens. Prices subject to change - check [opencode.ai](https://opencode.ai) for current pricing.*
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{}
|
package/index.ts
CHANGED
|
@@ -26,6 +26,7 @@ import { getAgentDir, type ExtensionAPI, type ModelRegistry } from "@earendil-wo
|
|
|
26
26
|
import modelsData from "./models.json" with { type: "json" };
|
|
27
27
|
import customModelsData from "./custom-models.json" with { type: "json" };
|
|
28
28
|
import patchData from "./patch.json" with { type: "json" };
|
|
29
|
+
import deprecatedData from "./deprecated-models.json" with { type: "json" };
|
|
29
30
|
import fs from "fs";
|
|
30
31
|
import path from "path";
|
|
31
32
|
|
|
@@ -116,7 +117,10 @@ function applyPatch(model: JsonModel, patch: PatchEntry): JsonModel {
|
|
|
116
117
|
function buildModels(base: JsonModel[], custom: JsonModel[], patch: PatchData): JsonModel[] {
|
|
117
118
|
const modelMap = new Map<string, JsonModel>();
|
|
118
119
|
|
|
119
|
-
|
|
120
|
+
// Seed with the base list plus grace-period deprecated models so patch.json
|
|
121
|
+
// entries apply to deprecated models exactly as while the model was live
|
|
122
|
+
// (withDeprecated keeps live data on id conflicts).
|
|
123
|
+
for (const model of withDeprecated(base)) {
|
|
120
124
|
modelMap.set(model.id, model);
|
|
121
125
|
}
|
|
122
126
|
|
|
@@ -257,6 +261,35 @@ function mergeWithEmbedded(liveModels: JsonModel[], embeddedModels: JsonModel[])
|
|
|
257
261
|
return result;
|
|
258
262
|
}
|
|
259
263
|
|
|
264
|
+
// Grace period for delisted models. When the provider API stops listing a
|
|
265
|
+
// model, update-models.js moves its last-known definition into
|
|
266
|
+
// deprecated-models.json (stamped with deprecatedAt) instead of dropping it.
|
|
267
|
+
// For 14 days the model keeps working here so in-flight sessions and saved
|
|
268
|
+
// model settings do not break; afterwards it is evicted permanently.
|
|
269
|
+
const DEPRECATED_MODEL_TTL_MS = 14 * 24 * 60 * 60 * 1000;
|
|
270
|
+
|
|
271
|
+
// Grace-period deprecated models with deprecation metadata stripped.
|
|
272
|
+
function activeDeprecatedModels(): JsonModel[] {
|
|
273
|
+
const now = Date.now();
|
|
274
|
+
const result: JsonModel[] = [];
|
|
275
|
+
for (const entry of Object.values(deprecatedData as Record<string, JsonModel & { deprecatedAt?: string }>)) {
|
|
276
|
+
if (!entry?.id) continue;
|
|
277
|
+
const removedAt = Date.parse(entry.deprecatedAt ?? "");
|
|
278
|
+
if (Number.isNaN(removedAt) || now - removedAt > DEPRECATED_MODEL_TTL_MS) continue;
|
|
279
|
+
const model = { ...entry } as JsonModel & { deprecatedAt?: string };
|
|
280
|
+
delete model.deprecatedAt;
|
|
281
|
+
result.push(model);
|
|
282
|
+
}
|
|
283
|
+
return result;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Append grace-period deprecated models the list does not already have (live data wins).
|
|
287
|
+
function withDeprecated(models: JsonModel[]): JsonModel[] {
|
|
288
|
+
const seen = new Set(models.map((m) => m.id));
|
|
289
|
+
const extras = activeDeprecatedModels().filter((m) => !seen.has(m.id));
|
|
290
|
+
return extras.length > 0 ? [...models, ...extras] : models;
|
|
291
|
+
}
|
|
292
|
+
|
|
260
293
|
function loadStaleModels(embeddedModels: JsonModel[]): JsonModel[] {
|
|
261
294
|
const cached = loadCachedModels();
|
|
262
295
|
if (!cached || cached.length === 0) return embeddedModels;
|
package/models.json
CHANGED
|
@@ -1,7 +1,44 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"id": "qwen3.7-plus",
|
|
4
|
+
"name": "Qwen3.7 Plus",
|
|
5
|
+
"api": "anthropic-messages",
|
|
6
|
+
"baseUrl": "https://opencode.ai/zen/go",
|
|
7
|
+
"reasoning": true,
|
|
8
|
+
"input": [
|
|
9
|
+
"text",
|
|
10
|
+
"image"
|
|
11
|
+
],
|
|
12
|
+
"cost": {
|
|
13
|
+
"input": 0.4,
|
|
14
|
+
"output": 1.6,
|
|
15
|
+
"cacheRead": 0.04,
|
|
16
|
+
"cacheWrite": 0.5
|
|
17
|
+
},
|
|
18
|
+
"contextWindow": 1000000,
|
|
19
|
+
"maxTokens": 65536
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"id": "glm-5.1",
|
|
23
|
+
"name": "GLM-5.1",
|
|
24
|
+
"api": "openai-completions",
|
|
25
|
+
"baseUrl": "https://opencode.ai/zen/go/v1",
|
|
26
|
+
"reasoning": true,
|
|
27
|
+
"input": [
|
|
28
|
+
"text"
|
|
29
|
+
],
|
|
30
|
+
"cost": {
|
|
31
|
+
"input": 1.4,
|
|
32
|
+
"output": 4.4,
|
|
33
|
+
"cacheRead": 0.26,
|
|
34
|
+
"cacheWrite": 0
|
|
35
|
+
},
|
|
36
|
+
"contextWindow": 202752,
|
|
37
|
+
"maxTokens": 32768
|
|
38
|
+
},
|
|
2
39
|
{
|
|
3
40
|
"id": "deepseek-v4-flash",
|
|
4
|
-
"name": "DeepSeek V4 Flash",
|
|
41
|
+
"name": "DeepSeek V4 Flash (New)",
|
|
5
42
|
"api": "openai-completions",
|
|
6
43
|
"baseUrl": "https://opencode.ai/zen/go/v1",
|
|
7
44
|
"reasoning": true,
|
|
@@ -18,23 +55,40 @@
|
|
|
18
55
|
"maxTokens": 384000
|
|
19
56
|
},
|
|
20
57
|
{
|
|
21
|
-
"id": "
|
|
22
|
-
"name": "
|
|
58
|
+
"id": "minimax-m2.7",
|
|
59
|
+
"name": "MiniMax-M2.7",
|
|
23
60
|
"api": "anthropic-messages",
|
|
24
61
|
"baseUrl": "https://opencode.ai/zen/go",
|
|
25
62
|
"reasoning": true,
|
|
26
63
|
"input": [
|
|
27
|
-
"text"
|
|
28
|
-
"image"
|
|
64
|
+
"text"
|
|
29
65
|
],
|
|
30
66
|
"cost": {
|
|
31
|
-
"input": 0.
|
|
32
|
-
"output": 1.
|
|
33
|
-
"cacheRead": 0.
|
|
34
|
-
"cacheWrite": 0
|
|
67
|
+
"input": 0.3,
|
|
68
|
+
"output": 1.2,
|
|
69
|
+
"cacheRead": 0.06,
|
|
70
|
+
"cacheWrite": 0
|
|
71
|
+
},
|
|
72
|
+
"contextWindow": 204800,
|
|
73
|
+
"maxTokens": 131072
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"id": "glm-5.2",
|
|
77
|
+
"name": "GLM-5.2",
|
|
78
|
+
"api": "openai-completions",
|
|
79
|
+
"baseUrl": "https://opencode.ai/zen/go/v1",
|
|
80
|
+
"reasoning": true,
|
|
81
|
+
"input": [
|
|
82
|
+
"text"
|
|
83
|
+
],
|
|
84
|
+
"cost": {
|
|
85
|
+
"input": 1.4,
|
|
86
|
+
"output": 4.4,
|
|
87
|
+
"cacheRead": 0.26,
|
|
88
|
+
"cacheWrite": 0
|
|
35
89
|
},
|
|
36
90
|
"contextWindow": 1000000,
|
|
37
|
-
"maxTokens":
|
|
91
|
+
"maxTokens": 131072
|
|
38
92
|
},
|
|
39
93
|
{
|
|
40
94
|
"id": "qwen3.7-max",
|
|
@@ -55,8 +109,8 @@
|
|
|
55
109
|
"maxTokens": 65536
|
|
56
110
|
},
|
|
57
111
|
{
|
|
58
|
-
"id": "kimi-k2.
|
|
59
|
-
"name": "Kimi K2.
|
|
112
|
+
"id": "kimi-k2.6",
|
|
113
|
+
"name": "Kimi K2.6",
|
|
60
114
|
"api": "openai-completions",
|
|
61
115
|
"baseUrl": "https://opencode.ai/zen/go/v1",
|
|
62
116
|
"reasoning": true,
|
|
@@ -67,15 +121,34 @@
|
|
|
67
121
|
"cost": {
|
|
68
122
|
"input": 0.95,
|
|
69
123
|
"output": 4,
|
|
70
|
-
"cacheRead": 0.
|
|
124
|
+
"cacheRead": 0.16,
|
|
71
125
|
"cacheWrite": 0
|
|
72
126
|
},
|
|
73
127
|
"contextWindow": 262144,
|
|
74
|
-
"maxTokens":
|
|
128
|
+
"maxTokens": 65536
|
|
75
129
|
},
|
|
76
130
|
{
|
|
77
|
-
"id": "
|
|
78
|
-
"name": "
|
|
131
|
+
"id": "minimax-m3",
|
|
132
|
+
"name": "MiniMax-M3",
|
|
133
|
+
"api": "anthropic-messages",
|
|
134
|
+
"baseUrl": "https://opencode.ai/zen/go",
|
|
135
|
+
"reasoning": true,
|
|
136
|
+
"input": [
|
|
137
|
+
"text",
|
|
138
|
+
"image"
|
|
139
|
+
],
|
|
140
|
+
"cost": {
|
|
141
|
+
"input": 0.3,
|
|
142
|
+
"output": 1.2,
|
|
143
|
+
"cacheRead": 0.06,
|
|
144
|
+
"cacheWrite": 0
|
|
145
|
+
},
|
|
146
|
+
"contextWindow": 1000000,
|
|
147
|
+
"maxTokens": 131072
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
"id": "hy3",
|
|
151
|
+
"name": "Hy3",
|
|
79
152
|
"api": "openai-completions",
|
|
80
153
|
"baseUrl": "https://opencode.ai/zen/go/v1",
|
|
81
154
|
"reasoning": true,
|
|
@@ -83,13 +156,13 @@
|
|
|
83
156
|
"text"
|
|
84
157
|
],
|
|
85
158
|
"cost": {
|
|
86
|
-
"input":
|
|
87
|
-
"output":
|
|
88
|
-
"cacheRead": 0.
|
|
159
|
+
"input": 0.14,
|
|
160
|
+
"output": 0.58,
|
|
161
|
+
"cacheRead": 0.035,
|
|
89
162
|
"cacheWrite": 0
|
|
90
163
|
},
|
|
91
|
-
"contextWindow":
|
|
92
|
-
"maxTokens":
|
|
164
|
+
"contextWindow": 256000,
|
|
165
|
+
"maxTokens": 64000
|
|
93
166
|
},
|
|
94
167
|
{
|
|
95
168
|
"id": "deepseek-v4-pro",
|
|
@@ -101,72 +174,74 @@
|
|
|
101
174
|
"text"
|
|
102
175
|
],
|
|
103
176
|
"cost": {
|
|
104
|
-
"input":
|
|
105
|
-
"output":
|
|
106
|
-
"cacheRead": 0.
|
|
177
|
+
"input": 0.435,
|
|
178
|
+
"output": 0.87,
|
|
179
|
+
"cacheRead": 0.003625,
|
|
107
180
|
"cacheWrite": 0
|
|
108
181
|
},
|
|
109
182
|
"contextWindow": 1000000,
|
|
110
183
|
"maxTokens": 384000
|
|
111
184
|
},
|
|
112
185
|
{
|
|
113
|
-
"id": "
|
|
114
|
-
"name": "
|
|
186
|
+
"id": "mimo-v2.5",
|
|
187
|
+
"name": "MiMo V2.5",
|
|
115
188
|
"api": "openai-completions",
|
|
116
189
|
"baseUrl": "https://opencode.ai/zen/go/v1",
|
|
117
190
|
"reasoning": true,
|
|
118
191
|
"input": [
|
|
119
|
-
"text"
|
|
192
|
+
"text",
|
|
193
|
+
"image"
|
|
120
194
|
],
|
|
121
195
|
"cost": {
|
|
122
|
-
"input":
|
|
123
|
-
"output":
|
|
124
|
-
"cacheRead": 0.
|
|
196
|
+
"input": 0.14,
|
|
197
|
+
"output": 0.28,
|
|
198
|
+
"cacheRead": 0.0028,
|
|
125
199
|
"cacheWrite": 0
|
|
126
200
|
},
|
|
127
201
|
"contextWindow": 1000000,
|
|
128
|
-
"maxTokens":
|
|
202
|
+
"maxTokens": 128000
|
|
129
203
|
},
|
|
130
204
|
{
|
|
131
|
-
"id": "
|
|
132
|
-
"name": "
|
|
133
|
-
"api": "
|
|
134
|
-
"baseUrl": "https://opencode.ai/zen/go",
|
|
205
|
+
"id": "gpt-5.6-luna",
|
|
206
|
+
"name": "GPT-5.6 Luna (2x usage)",
|
|
207
|
+
"api": "openai-completions",
|
|
208
|
+
"baseUrl": "https://opencode.ai/zen/go/v1",
|
|
135
209
|
"reasoning": true,
|
|
136
210
|
"input": [
|
|
137
211
|
"text",
|
|
138
212
|
"image"
|
|
139
213
|
],
|
|
140
214
|
"cost": {
|
|
141
|
-
"input": 0.
|
|
142
|
-
"output":
|
|
143
|
-
"cacheRead": 0.
|
|
144
|
-
"cacheWrite": 0
|
|
215
|
+
"input": 0.1,
|
|
216
|
+
"output": 0.6,
|
|
217
|
+
"cacheRead": 0.01,
|
|
218
|
+
"cacheWrite": 0.125
|
|
145
219
|
},
|
|
146
|
-
"contextWindow":
|
|
147
|
-
"maxTokens":
|
|
220
|
+
"contextWindow": 1050000,
|
|
221
|
+
"maxTokens": 128000
|
|
148
222
|
},
|
|
149
223
|
{
|
|
150
|
-
"id": "
|
|
151
|
-
"name": "
|
|
152
|
-
"api": "
|
|
153
|
-
"baseUrl": "https://opencode.ai/zen/go",
|
|
224
|
+
"id": "grok-4.5",
|
|
225
|
+
"name": "Grok 4.5",
|
|
226
|
+
"api": "openai-completions",
|
|
227
|
+
"baseUrl": "https://opencode.ai/zen/go/v1",
|
|
154
228
|
"reasoning": true,
|
|
155
229
|
"input": [
|
|
156
|
-
"text"
|
|
230
|
+
"text",
|
|
231
|
+
"image"
|
|
157
232
|
],
|
|
158
233
|
"cost": {
|
|
159
|
-
"input":
|
|
160
|
-
"output":
|
|
161
|
-
"cacheRead": 0.
|
|
234
|
+
"input": 2,
|
|
235
|
+
"output": 6,
|
|
236
|
+
"cacheRead": 0.5,
|
|
162
237
|
"cacheWrite": 0
|
|
163
238
|
},
|
|
164
|
-
"contextWindow":
|
|
165
|
-
"maxTokens":
|
|
239
|
+
"contextWindow": 500000,
|
|
240
|
+
"maxTokens": 500000
|
|
166
241
|
},
|
|
167
242
|
{
|
|
168
|
-
"id": "
|
|
169
|
-
"name": "
|
|
243
|
+
"id": "kimi-k2.7-code",
|
|
244
|
+
"name": "Kimi K2.7 Code",
|
|
170
245
|
"api": "openai-completions",
|
|
171
246
|
"baseUrl": "https://opencode.ai/zen/go/v1",
|
|
172
247
|
"reasoning": true,
|
|
@@ -175,17 +250,17 @@
|
|
|
175
250
|
"image"
|
|
176
251
|
],
|
|
177
252
|
"cost": {
|
|
178
|
-
"input": 0.
|
|
179
|
-
"output":
|
|
180
|
-
"cacheRead": 0.
|
|
253
|
+
"input": 0.95,
|
|
254
|
+
"output": 4,
|
|
255
|
+
"cacheRead": 0.19,
|
|
181
256
|
"cacheWrite": 0
|
|
182
257
|
},
|
|
183
|
-
"contextWindow":
|
|
184
|
-
"maxTokens":
|
|
258
|
+
"contextWindow": 262144,
|
|
259
|
+
"maxTokens": 262144
|
|
185
260
|
},
|
|
186
261
|
{
|
|
187
|
-
"id": "kimi-
|
|
188
|
-
"name": "Kimi
|
|
262
|
+
"id": "kimi-k3",
|
|
263
|
+
"name": "Kimi K3",
|
|
189
264
|
"api": "openai-completions",
|
|
190
265
|
"baseUrl": "https://opencode.ai/zen/go/v1",
|
|
191
266
|
"reasoning": true,
|
|
@@ -194,13 +269,13 @@
|
|
|
194
269
|
"image"
|
|
195
270
|
],
|
|
196
271
|
"cost": {
|
|
197
|
-
"input":
|
|
198
|
-
"output":
|
|
199
|
-
"cacheRead": 0.
|
|
272
|
+
"input": 3,
|
|
273
|
+
"output": 15,
|
|
274
|
+
"cacheRead": 0.3,
|
|
200
275
|
"cacheWrite": 0
|
|
201
276
|
},
|
|
202
|
-
"contextWindow":
|
|
203
|
-
"maxTokens":
|
|
277
|
+
"contextWindow": 1048576,
|
|
278
|
+
"maxTokens": 131072
|
|
204
279
|
},
|
|
205
280
|
{
|
|
206
281
|
"id": "mimo-v2.5-pro",
|
|
@@ -212,9 +287,9 @@
|
|
|
212
287
|
"text"
|
|
213
288
|
],
|
|
214
289
|
"cost": {
|
|
215
|
-
"input":
|
|
216
|
-
"output":
|
|
217
|
-
"cacheRead": 0.
|
|
290
|
+
"input": 0.435,
|
|
291
|
+
"output": 0.87,
|
|
292
|
+
"cacheRead": 0.003625,
|
|
218
293
|
"cacheWrite": 0
|
|
219
294
|
},
|
|
220
295
|
"contextWindow": 1048576,
|
package/package.json
CHANGED
package/patch.json
CHANGED
|
@@ -1,17 +1,161 @@
|
|
|
1
1
|
{
|
|
2
|
+
"glm-5.1": {
|
|
3
|
+
"compat": {
|
|
4
|
+
"supportsStore": false,
|
|
5
|
+
"supportsDeveloperRole": false,
|
|
6
|
+
"maxTokensField": "max_tokens"
|
|
7
|
+
}
|
|
8
|
+
},
|
|
2
9
|
"deepseek-v4-flash": {
|
|
3
|
-
"
|
|
4
|
-
"thinkingLevelMap": {
|
|
10
|
+
"name": "DeepSeek V4 Flash",
|
|
11
|
+
"thinkingLevelMap": {
|
|
12
|
+
"minimal": null,
|
|
13
|
+
"low": null,
|
|
14
|
+
"medium": null,
|
|
15
|
+
"high": "high",
|
|
16
|
+
"max": "max"
|
|
17
|
+
},
|
|
18
|
+
"compat": {
|
|
19
|
+
"supportsStore": false,
|
|
20
|
+
"supportsDeveloperRole": false,
|
|
21
|
+
"maxTokensField": "max_tokens",
|
|
22
|
+
"requiresReasoningContentOnAssistantMessages": true,
|
|
23
|
+
"thinkingFormat": "deepseek"
|
|
24
|
+
}
|
|
5
25
|
},
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
26
|
+
"minimax-m2.7": {
|
|
27
|
+
"api": "openai-completions",
|
|
28
|
+
"baseUrl": "https://opencode.ai/zen/go/v1",
|
|
29
|
+
"compat": {
|
|
30
|
+
"supportsStore": false,
|
|
31
|
+
"supportsDeveloperRole": false,
|
|
32
|
+
"maxTokensField": "max_tokens"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"glm-5.2": {
|
|
36
|
+
"thinkingLevelMap": {
|
|
37
|
+
"off": null,
|
|
38
|
+
"minimal": null,
|
|
39
|
+
"low": null,
|
|
40
|
+
"medium": null,
|
|
41
|
+
"high": "high",
|
|
42
|
+
"xhigh": null,
|
|
43
|
+
"max": "max"
|
|
44
|
+
},
|
|
45
|
+
"compat": {
|
|
46
|
+
"supportsStore": false,
|
|
47
|
+
"supportsDeveloperRole": false,
|
|
48
|
+
"maxTokensField": "max_tokens"
|
|
49
|
+
}
|
|
9
50
|
},
|
|
10
51
|
"kimi-k2.6": {
|
|
11
|
-
"
|
|
12
|
-
|
|
52
|
+
"thinkingLevelMap": {
|
|
53
|
+
"minimal": null,
|
|
54
|
+
"low": null,
|
|
55
|
+
"medium": null
|
|
56
|
+
},
|
|
57
|
+
"compat": {
|
|
58
|
+
"supportsStore": false,
|
|
59
|
+
"supportsDeveloperRole": false,
|
|
60
|
+
"thinkingFormat": "deepseek",
|
|
61
|
+
"supportsReasoningEffort": false,
|
|
62
|
+
"maxTokensField": "max_tokens",
|
|
63
|
+
"supportsLongCacheRetention": false
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"hy3": {
|
|
67
|
+
"thinkingLevelMap": {
|
|
68
|
+
"off": "none",
|
|
69
|
+
"minimal": null,
|
|
70
|
+
"low": "low",
|
|
71
|
+
"medium": null,
|
|
72
|
+
"high": "high",
|
|
73
|
+
"xhigh": null,
|
|
74
|
+
"max": null
|
|
75
|
+
},
|
|
76
|
+
"compat": {
|
|
77
|
+
"supportsStore": false,
|
|
78
|
+
"supportsDeveloperRole": false,
|
|
79
|
+
"maxTokensField": "max_tokens"
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
"deepseek-v4-pro": {
|
|
83
|
+
"thinkingLevelMap": {
|
|
84
|
+
"minimal": null,
|
|
85
|
+
"low": null,
|
|
86
|
+
"medium": null,
|
|
87
|
+
"high": "high",
|
|
88
|
+
"max": "max"
|
|
89
|
+
},
|
|
90
|
+
"compat": {
|
|
91
|
+
"supportsStore": false,
|
|
92
|
+
"supportsDeveloperRole": false,
|
|
93
|
+
"maxTokensField": "max_tokens",
|
|
94
|
+
"requiresReasoningContentOnAssistantMessages": true,
|
|
95
|
+
"thinkingFormat": "deepseek"
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
"mimo-v2.5": {
|
|
99
|
+
"compat": {
|
|
100
|
+
"supportsStore": false,
|
|
101
|
+
"supportsDeveloperRole": false,
|
|
102
|
+
"maxTokensField": "max_tokens"
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
"grok-4.5": {
|
|
106
|
+
"api": "openai-responses",
|
|
107
|
+
"thinkingLevelMap": {
|
|
108
|
+
"off": null,
|
|
109
|
+
"minimal": null,
|
|
110
|
+
"low": "low",
|
|
111
|
+
"medium": "medium",
|
|
112
|
+
"high": "high",
|
|
113
|
+
"xhigh": null,
|
|
114
|
+
"max": null
|
|
115
|
+
},
|
|
116
|
+
"compat": {
|
|
117
|
+
"sessionAffinityFormat": "openai-nosession"
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
"kimi-k2.7-code": {
|
|
121
|
+
"compat": {
|
|
122
|
+
"supportsStore": false,
|
|
123
|
+
"supportsDeveloperRole": false,
|
|
124
|
+
"maxTokensField": "max_tokens"
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
"kimi-k3": {
|
|
128
|
+
"name": "Kimi K3 (2x usage)",
|
|
129
|
+
"thinkingLevelMap": {
|
|
130
|
+
"off": null,
|
|
131
|
+
"minimal": null,
|
|
132
|
+
"low": null,
|
|
133
|
+
"medium": null,
|
|
134
|
+
"high": null,
|
|
135
|
+
"xhigh": null,
|
|
136
|
+
"max": "max"
|
|
137
|
+
},
|
|
138
|
+
"compat": {
|
|
139
|
+
"supportsStore": false,
|
|
140
|
+
"supportsDeveloperRole": false,
|
|
141
|
+
"maxTokensField": "max_tokens"
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
"mimo-v2.5-pro": {
|
|
145
|
+
"compat": {
|
|
146
|
+
"supportsStore": false,
|
|
147
|
+
"supportsDeveloperRole": false,
|
|
148
|
+
"maxTokensField": "max_tokens"
|
|
149
|
+
}
|
|
13
150
|
},
|
|
14
151
|
"qwen3.6-plus": {
|
|
15
|
-
"
|
|
152
|
+
"api": "openai-completions",
|
|
153
|
+
"baseUrl": "https://opencode.ai/zen/go/v1",
|
|
154
|
+
"compat": {
|
|
155
|
+
"supportsStore": false,
|
|
156
|
+
"supportsDeveloperRole": false,
|
|
157
|
+
"thinkingFormat": "qwen",
|
|
158
|
+
"maxTokensField": "max_tokens"
|
|
159
|
+
}
|
|
16
160
|
}
|
|
17
161
|
}
|
package/scripts/update-models.js
CHANGED
|
@@ -101,6 +101,46 @@ function convertModel(model) {
|
|
|
101
101
|
};
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
+
// Load a layered JSON model file.
|
|
105
|
+
function loadJson(fileName) {
|
|
106
|
+
try {
|
|
107
|
+
return JSON.parse(fs.readFileSync(path.join(process.cwd(), fileName), 'utf8'));
|
|
108
|
+
} catch {
|
|
109
|
+
return fileName === 'patch.json' ? {} : [];
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Deep-merge patch overrides into a model for README documentation. The
|
|
114
|
+
// generated models.json remains API-derived; only the displayed model map uses patches.
|
|
115
|
+
function applyPatch(model, patch) {
|
|
116
|
+
if (!patch) return model;
|
|
117
|
+
const result = { ...model };
|
|
118
|
+
for (const [key, value] of Object.entries(patch)) {
|
|
119
|
+
if (key === 'cost' || key === 'compat' || key === 'thinkingLevelMap') {
|
|
120
|
+
result[key] = { ...(result[key] || {}), ...value };
|
|
121
|
+
} else {
|
|
122
|
+
result[key] = value;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (!result.reasoning) {
|
|
126
|
+
delete result.thinkingLevelMap;
|
|
127
|
+
if (result.compat?.thinkingFormat) delete result.compat.thinkingFormat;
|
|
128
|
+
}
|
|
129
|
+
return result;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Merge API models, patches, and custom models in the same order as index.ts.
|
|
133
|
+
function buildModels(baseModels, customModels, patch) {
|
|
134
|
+
const byId = new Map(baseModels.map(model => [model.id, model]));
|
|
135
|
+
for (const [id, entry] of Object.entries(patch)) {
|
|
136
|
+
if (byId.has(id)) byId.set(id, applyPatch(byId.get(id), entry));
|
|
137
|
+
}
|
|
138
|
+
for (const model of customModels) {
|
|
139
|
+
byId.set(model.id, applyPatch(model, patch[model.id]));
|
|
140
|
+
}
|
|
141
|
+
return Array.from(byId.values());
|
|
142
|
+
}
|
|
143
|
+
|
|
104
144
|
// Generate README model table row
|
|
105
145
|
function generateReadmeRow(model) {
|
|
106
146
|
const cost = model.cost || {};
|
|
@@ -149,6 +189,67 @@ ${tableRows}`;
|
|
|
149
189
|
console.log(` Updated README.md with ${models.length} models`);
|
|
150
190
|
}
|
|
151
191
|
|
|
192
|
+
// Grace period for delisted models: update-models.js moves models the API no
|
|
193
|
+
// longer lists into deprecated-models.json (stamped with deprecatedAt) instead
|
|
194
|
+
// of dropping them; the runtime appends them back so sessions and saved model
|
|
195
|
+
// settings keep working, and after 14 days they are evicted permanently.
|
|
196
|
+
const DEPRECATED_MODEL_TTL_MS = 14 * 24 * 60 * 60 * 1000;
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Reconcile deprecated-models.json against the freshly fetched model list.
|
|
200
|
+
* - in old models.json but not the API: moved into the deprecated file
|
|
201
|
+
* (deprecatedAt = now; preserved on repeat runs so the grace clock is not reset)
|
|
202
|
+
* - back in the API: resurrected (dropped from the deprecated file)
|
|
203
|
+
* - deprecatedAt older than 14 days: evicted permanently
|
|
204
|
+
* Must run BEFORE the new models.json is written; it reads the old file itself.
|
|
205
|
+
*/
|
|
206
|
+
function updateDeprecatedModels(modelsJsonPath, newModels) {
|
|
207
|
+
const deprecatedPath = path.join(path.dirname(modelsJsonPath), 'deprecated-models.json');
|
|
208
|
+
|
|
209
|
+
let oldModels = [];
|
|
210
|
+
try {
|
|
211
|
+
const parsed = JSON.parse(fs.readFileSync(modelsJsonPath, 'utf8'));
|
|
212
|
+
if (Array.isArray(parsed)) oldModels = parsed;
|
|
213
|
+
} catch { /* first run: no previous models.json */ }
|
|
214
|
+
|
|
215
|
+
let deprecated = {};
|
|
216
|
+
try {
|
|
217
|
+
const parsed = JSON.parse(fs.readFileSync(deprecatedPath, 'utf8'));
|
|
218
|
+
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) deprecated = parsed;
|
|
219
|
+
} catch { /* no graveyard yet */ }
|
|
220
|
+
|
|
221
|
+
const currentIds = new Set(newModels.map(m => m.id));
|
|
222
|
+
const now = new Date().toISOString();
|
|
223
|
+
const added = [];
|
|
224
|
+
const resurrected = [];
|
|
225
|
+
const evicted = [];
|
|
226
|
+
|
|
227
|
+
for (const old of oldModels) {
|
|
228
|
+
if (old && old.id && !currentIds.has(old.id) && !deprecated[old.id]) {
|
|
229
|
+
deprecated[old.id] = { ...old, deprecatedAt: now };
|
|
230
|
+
added.push(old.id);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
for (const [id, entry] of Object.entries(deprecated)) {
|
|
235
|
+
if (currentIds.has(id)) {
|
|
236
|
+
delete deprecated[id];
|
|
237
|
+
resurrected.push(id);
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
const removedAt = Date.parse(entry && entry.deprecatedAt ? entry.deprecatedAt : '');
|
|
241
|
+
if (Number.isNaN(removedAt) || Date.now() - removedAt > DEPRECATED_MODEL_TTL_MS) {
|
|
242
|
+
delete deprecated[id];
|
|
243
|
+
evicted.push(id);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
if (added.length > 0 || resurrected.length > 0 || evicted.length > 0) {
|
|
248
|
+
fs.writeFileSync(deprecatedPath, JSON.stringify(deprecated, null, 2) + '\n');
|
|
249
|
+
console.log('Updated deprecated-models.json ' + JSON.stringify({ added, resurrected, evicted }));
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
152
253
|
async function main() {
|
|
153
254
|
console.log('Fetching models from API...');
|
|
154
255
|
|
|
@@ -172,11 +273,15 @@ async function main() {
|
|
|
172
273
|
// Convert to Pi-native format and save to models.json
|
|
173
274
|
const models = apiModels.map(convertModel);
|
|
174
275
|
const modelsPath = path.join(process.cwd(), 'models.json');
|
|
276
|
+
// Move delisted models to deprecated-models.json BEFORE models.json is overwritten
|
|
277
|
+
updateDeprecatedModels(modelsPath, models);
|
|
175
278
|
fs.writeFileSync(modelsPath, JSON.stringify(models, null, 2) + '\n');
|
|
176
279
|
console.log(` Saved ${models.length} models to models.json`);
|
|
177
280
|
|
|
178
|
-
//
|
|
179
|
-
|
|
281
|
+
// Apply layered overrides for documentation: models.json → patch.json → custom-models.json.
|
|
282
|
+
const patch = loadJson('patch.json');
|
|
283
|
+
const customModels = Array.isArray(loadJson('custom-models.json')) ? loadJson('custom-models.json') : [];
|
|
284
|
+
updateReadme(buildModels(models, customModels, patch));
|
|
180
285
|
|
|
181
286
|
console.log('\nDone!');
|
|
182
287
|
} catch (error) {
|