pi-provider-qoder-cn 0.2.25 → 0.2.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 +31 -3
- package/dist/index.js +135 -245
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -25,14 +25,15 @@ pi install npm:pi-provider-qoder-cn
|
|
|
25
25
|
| Seamless token refresh (deviceToken/refresh for drt- & PAT exchange) | ❌ (broken 403) | ✅ |
|
|
26
26
|
| Enterprise (VPC) selection during `/login qoder-cn` | ❌ | ✅ |
|
|
27
27
|
| Current CN model catalog (`qwen3.8-max` / `qwen3.8-flash`, …) | ❌ | ✅ |
|
|
28
|
-
|
|
|
28
|
+
| Model ids follow the live catalog (an upgrade gets a new id; retired models disappear) | ❌ | ✅ |
|
|
29
|
+
| `/qoder-cn.models` & `/qoder.models` manual catalog refresh | ❌ | ✅ |
|
|
29
30
|
| Capacity-queue detection (`isQueued` / `RESOURCE_LIMIT` / lane) | ❌ | ✅ (recognised, honoured, adjustable) |
|
|
30
31
|
| Per-turn wait budget + lane cooldown knobs | ❌ | ✅ |
|
|
31
32
|
| Cache ownership tag (foreign catalogs discarded, not half-read) | ❌ | ✅ |
|
|
32
33
|
|
|
33
34
|
Both `qoder` (Global) and `qoder-cn` (Domestic) providers are registered.
|
|
34
|
-
- To use Global: run `/login qoder` and use `/model qoder/<id>`. Commands: `/qoder.usage`, `/qoder.claim
|
|
35
|
-
- To use CN: run `/login qoder-cn` and use `/model qoder-cn/<id>`. Commands: `/qoder-cn.usage`, `/qoder-cn.claim
|
|
35
|
+
- To use Global: run `/login qoder` and use `/model qoder/<id>`. Commands: `/qoder.usage`, `/qoder.claim`., `/qoder.models`
|
|
36
|
+
- To use CN: run `/login qoder-cn` and use `/model qoder-cn/<id>`. Commands: `/qoder-cn.usage`, `/qoder-cn.claim`., `/qoder-cn.models`
|
|
36
37
|
|
|
37
38
|
> Check with `pi list` and inspect `~/.pi/agent/extensions/`: a leftover
|
|
38
39
|
> `pi-provider-qoder` extension directory registers the same provider ids.
|
|
@@ -161,6 +162,33 @@ Notes:
|
|
|
161
162
|
- The command uses the same stored token as chat requests, refreshing it first,
|
|
162
163
|
so it reports the same quota the model is actually billed against.
|
|
163
164
|
|
|
165
|
+
### `/qoder-cn.models`
|
|
166
|
+
|
|
167
|
+
Refreshes the model catalog from `/algo/api/v2/model/list` and reports what moved:
|
|
168
|
+
|
|
169
|
+
```text
|
|
170
|
+
Qoder CN Plan models · 11 offered by the catalog
|
|
171
|
+
|
|
172
|
+
New (4)
|
|
173
|
+
+ kimi-k3.1-pro Kimi-K3.1-Pro · Qoder CN
|
|
174
|
+
+ minimax-m3.1-flash MiniMax-M3.1-Flash · Qoder CN
|
|
175
|
+
Renamed upstream (1)
|
|
176
|
+
~ deepseek-v4-pro DeepSeek V4 Pro · Qoder CN -> DeepSeek-V4-Pro · Qoder CN
|
|
177
|
+
Gone (4)
|
|
178
|
+
- kimi-k3 Kimi-K3 · Qoder CN
|
|
179
|
+
- minimax-m2.7 MiniMax M2.7 · Qoder CN
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
The provider list is re-registered in the running session, so the change is usable
|
|
183
|
+
in `/model` immediately — no restart. Append `list` to print the models pi currently
|
|
184
|
+
has cached, without touching the network.
|
|
185
|
+
|
|
186
|
+
The catalog key is a slot, not a model: upstream has served Kimi-K2.6 through
|
|
187
|
+
Kimi-K3.1-Pro under `kmodel_latest`. Ids are therefore slugs of the display name, so
|
|
188
|
+
an upgrade arrives as a new id (`kimi-k3` -> `kimi-k3.1-pro`) and a model upstream
|
|
189
|
+
stops offering leaves the list. Retired ids still resolve for an existing
|
|
190
|
+
`settings.json` (they route to the key they always used) but are no longer advertised.
|
|
191
|
+
|
|
164
192
|
### `/qoder-cn.claim`
|
|
165
193
|
|
|
166
194
|
Daily check-in command to claim the 100 free Credits reward on Qoder CN personal
|
package/dist/index.js
CHANGED
|
@@ -15,16 +15,16 @@ var __export = (target, all) => {
|
|
|
15
15
|
|
|
16
16
|
// src/cn-naming.ts
|
|
17
17
|
function slugifyQoderCNModel(displayName) {
|
|
18
|
-
const slug = (displayName || "").trim().toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9._-]/g, "").replace(/^-+|-+$/g, "");
|
|
18
|
+
const slug = (displayName || "").trim().toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9._-]/g, "").replace(/^-+|-+$/g, "").replace(/-{2,}/g, "-");
|
|
19
19
|
return slug || "qodermodel";
|
|
20
20
|
}
|
|
21
21
|
function prettifyQoderCNModelName(displayName) {
|
|
22
|
-
const pretty = (displayName || "Qoder CN Model").replace(/Qwen(\d)/g, "Qwen $1").replace(/Qwen([\d.]+)-/g, "Qwen $1 ").replace(/DeepSeek
|
|
22
|
+
const pretty = (displayName || "Qoder CN Model").replace(/Qwen(\d)/g, "Qwen $1").replace(/Qwen([\d.]+)-/g, "Qwen $1 ").replace(/DeepSeek([Vv]\d)-/g, "DeepSeek $1 ").replace(/\s+/g, " ").trim();
|
|
23
23
|
return pretty.includes("Qoder CN") ? pretty : `${pretty} \xB7 Qoder CN`;
|
|
24
24
|
}
|
|
25
25
|
function toQoderCNModelInfo(upstreamKey, displayName) {
|
|
26
|
-
const
|
|
27
|
-
if (
|
|
26
|
+
const fixed = upstreamKey ? FIXED_CN_MODEL_IDS[upstreamKey] : void 0;
|
|
27
|
+
if (fixed) return fixed;
|
|
28
28
|
return {
|
|
29
29
|
id: slugifyQoderCNModel(displayName || upstreamKey),
|
|
30
30
|
name: prettifyQoderCNModelName(displayName || upstreamKey)
|
|
@@ -32,10 +32,9 @@ function toQoderCNModelInfo(upstreamKey, displayName) {
|
|
|
32
32
|
}
|
|
33
33
|
function toQoderCNUpstreamKey(modelId) {
|
|
34
34
|
const id = modelId || "";
|
|
35
|
-
const
|
|
36
|
-
if (
|
|
37
|
-
if (
|
|
38
|
-
if (Object.hasOwn(QODER_CN_FRIENDLY_MODELS, id)) return id;
|
|
35
|
+
const legacy = LEGACY_CN_MODEL_IDS[id];
|
|
36
|
+
if (legacy) return legacy;
|
|
37
|
+
if (FIXED_CN_MODEL_IDS[id]) return id;
|
|
39
38
|
return id || "auto";
|
|
40
39
|
}
|
|
41
40
|
function isQoderCNModelId(entry, modelId) {
|
|
@@ -43,52 +42,33 @@ function isQoderCNModelId(entry, modelId) {
|
|
|
43
42
|
const info = toQoderCNModelInfo(entry.key, entry.display_name);
|
|
44
43
|
if (info.id === modelId) return true;
|
|
45
44
|
if (entry.key === modelId) return true;
|
|
45
|
+
const legacyKey = LEGACY_CN_MODEL_IDS[modelId];
|
|
46
|
+
if (legacyKey !== void 0 && legacyKey === entry.key) return true;
|
|
46
47
|
const stripped = (entry.display_name || "").replace(/\s+/g, "");
|
|
47
48
|
return stripped.toLowerCase() === modelId.toLowerCase();
|
|
48
49
|
}
|
|
49
|
-
var
|
|
50
|
+
var LEGACY_CN_MODEL_IDS, FIXED_CN_MODEL_IDS;
|
|
50
51
|
var init_cn_naming = __esm({
|
|
51
52
|
"src/cn-naming.ts"() {
|
|
52
53
|
"use strict";
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
"
|
|
56
|
-
qmodel_38max: { id: "qwen3.8-max", name: "Qwen 3.8-Max \xB7 Qoder CN" },
|
|
57
|
-
qfmodel: { id: "qwen3.8-flash", name: "Qwen 3.8-Flash \xB7 Qoder CN" },
|
|
58
|
-
qmodel_latest: { id: "qwen3.7-max", name: "Qwen 3.7-Max \xB7 Qoder CN" },
|
|
59
|
-
qmodel: { id: "qwen3.7-plus", name: "Qwen 3.7-Plus \xB7 Qoder CN" },
|
|
60
|
-
q37fmodel: { id: "qwen3.7-flash", name: "Qwen 3.7-Flash \xB7 Qoder CN" },
|
|
61
|
-
dmodel: { id: "deepseek-v4-pro", name: "DeepSeek V4 Pro \xB7 Qoder CN" },
|
|
62
|
-
dfmodel: { id: "deepseek-v4-flash", name: "DeepSeek V4 Flash \xB7 Qoder CN" },
|
|
63
|
-
gmodel: { id: "glm-5.3", name: "GLM-5.3 \xB7 Qoder CN" },
|
|
64
|
-
gfmodel: { id: "glm-5.3-flash", name: "GLM-5.3-Flash \xB7 Qoder CN" },
|
|
65
|
-
gm51model: { id: "glm-5.2", name: "GLM 5.2 \xB7 Qoder CN" },
|
|
66
|
-
kmodel_latest: { id: "kimi-k3", name: "Kimi-K3 \xB7 Qoder CN" },
|
|
67
|
-
kmodel: { id: "kimi-k2.7-code", name: "Kimi-K2.7-Code \xB7 Qoder CN" },
|
|
68
|
-
mmodel: { id: "minimax-m2.7", name: "MiniMax M2.7 \xB7 Qoder CN" }
|
|
69
|
-
});
|
|
70
|
-
CN_MODEL_KEY_ALIASES = Object.freeze({
|
|
71
|
-
"qwen3.8-max": "qmodel_38max",
|
|
72
|
-
"qwen3.8-flash": "qfmodel",
|
|
73
|
-
"qwen3.7-max": "qmodel_latest",
|
|
74
|
-
"qwen3.7-plus": "qmodel",
|
|
54
|
+
LEGACY_CN_MODEL_IDS = Object.freeze({
|
|
55
|
+
"qwen3.6-flash": "qfmodel",
|
|
56
|
+
"qwen3.6-plus": "qmodel",
|
|
75
57
|
"qwen3.7-flash": "q37fmodel",
|
|
76
|
-
"
|
|
77
|
-
"deepseek-v4-flash": "dfmodel",
|
|
78
|
-
"glm-5.3": "gmodel",
|
|
79
|
-
"glm-5.3-flash": "gfmodel",
|
|
80
|
-
"glm-5.2": "gm51model",
|
|
58
|
+
"qwen3.7-max": "qmodel_latest",
|
|
81
59
|
"glm-5.1": "gm51model",
|
|
82
|
-
"
|
|
83
|
-
"kimi-k2.7-code": "kmodel",
|
|
84
|
-
"kimi-k2.7": "kmodel",
|
|
60
|
+
"glm-5.2": "gm51model",
|
|
85
61
|
"kimi-k2.6": "kmodel",
|
|
62
|
+
"kimi-k2.7": "kmodel",
|
|
63
|
+
"kimi-k2.7-code": "kmodel",
|
|
86
64
|
"kimi-k2.8-preview": "kmodel",
|
|
87
|
-
"
|
|
88
|
-
"qwen3.6-plus": "qmodel",
|
|
65
|
+
"kimi-k3": "kmodel_latest",
|
|
89
66
|
"minimax-m2.7": "mmodel",
|
|
90
67
|
"minimax-m3": "mmodel"
|
|
91
68
|
});
|
|
69
|
+
FIXED_CN_MODEL_IDS = Object.freeze({
|
|
70
|
+
auto: { id: "auto", name: "Auto \xB7 Qoder CN" }
|
|
71
|
+
});
|
|
92
72
|
}
|
|
93
73
|
});
|
|
94
74
|
|
|
@@ -453,6 +433,9 @@ function getHomeDir3() {
|
|
|
453
433
|
function getQoderCachePath(mode) {
|
|
454
434
|
return join3(getHomeDir3(), ".pi", "agent", getQoderRegionConfig(mode).modelCacheFile);
|
|
455
435
|
}
|
|
436
|
+
function clearQoderModelsMemCache() {
|
|
437
|
+
modelCacheMem.clear();
|
|
438
|
+
}
|
|
456
439
|
function readParsedModelCache(mode) {
|
|
457
440
|
const cachePath = getQoderCachePath(mode);
|
|
458
441
|
if (modelCacheMem.has(cachePath)) {
|
|
@@ -629,11 +612,11 @@ async function updateQoderModelsCache(authToken, userID, name, email, mode) {
|
|
|
629
612
|
}
|
|
630
613
|
});
|
|
631
614
|
if (!response.ok) {
|
|
632
|
-
return;
|
|
615
|
+
return null;
|
|
633
616
|
}
|
|
634
617
|
const resData = await response.json();
|
|
635
618
|
const chatModels = resData.chat || [];
|
|
636
|
-
if (chatModels.length === 0) return;
|
|
619
|
+
if (chatModels.length === 0) return null;
|
|
637
620
|
const newModels = [];
|
|
638
621
|
const configs = {};
|
|
639
622
|
for (const entry of chatModels) {
|
|
@@ -664,14 +647,28 @@ async function updateQoderModelsCache(authToken, userID, name, email, mode) {
|
|
|
664
647
|
maxTokens: MAX_OUTPUT_TOKENS
|
|
665
648
|
});
|
|
666
649
|
}
|
|
667
|
-
if (newModels.length === 0) return;
|
|
650
|
+
if (newModels.length === 0) return null;
|
|
651
|
+
const previous = readParsedModelCache(mode);
|
|
652
|
+
const previousModels = new Map((previous?.models ?? []).map((model) => [model.id, model.name]));
|
|
653
|
+
const nextIds = new Set(newModels.map((model) => model.id));
|
|
654
|
+
const diff = {
|
|
655
|
+
added: newModels.filter((model) => !previousModels.has(model.id)).map((model) => ({ id: model.id, name: model.name })),
|
|
656
|
+
renamed: newModels.filter((model) => {
|
|
657
|
+
const before = previousModels.get(model.id);
|
|
658
|
+
return before !== void 0 && before !== model.name;
|
|
659
|
+
}).map((model) => ({ id: model.id, from: previousModels.get(model.id) ?? "", to: model.name })),
|
|
660
|
+
removed: [...previousModels].filter(([id]) => !nextIds.has(id)).map(([id, previousName]) => ({ id, name: previousName })),
|
|
661
|
+
total: newModels.length
|
|
662
|
+
};
|
|
668
663
|
const cacheData = {
|
|
669
664
|
updatedAt: Date.now(),
|
|
670
665
|
models: newModels,
|
|
671
666
|
configs
|
|
672
667
|
};
|
|
673
668
|
writeParsedModelCache(mode, cacheData);
|
|
669
|
+
return diff;
|
|
674
670
|
} catch {
|
|
671
|
+
return null;
|
|
675
672
|
}
|
|
676
673
|
}
|
|
677
674
|
var ZERO_COST, MAX_OUTPUT_TOKENS, DEFAULT_CONTEXT_WINDOW, QODER_CACHE_WRITER, modelCacheMem, staticModels, staticCnModels, PI_THINKING_LEVELS;
|
|
@@ -915,203 +912,6 @@ var init_catalog = __esm({
|
|
|
915
912
|
contextWindow: 2e5,
|
|
916
913
|
maxTokens: MAX_OUTPUT_TOKENS,
|
|
917
914
|
description: "Qoder CN smart routing; live catalog reports 200K max input."
|
|
918
|
-
},
|
|
919
|
-
{
|
|
920
|
-
id: "qwen3.8-max",
|
|
921
|
-
upstreamKey: "qmodel_38max",
|
|
922
|
-
name: "Qwen 3.8-Max \xB7 Qoder CN",
|
|
923
|
-
api: "qoder-api",
|
|
924
|
-
provider: "qoder-cn",
|
|
925
|
-
baseUrl: getQoderBaseUrl("cn"),
|
|
926
|
-
reasoning: true,
|
|
927
|
-
supportsEffort: true,
|
|
928
|
-
input: ["text", "image"],
|
|
929
|
-
cost: ZERO_COST,
|
|
930
|
-
contextWindow: DEFAULT_CONTEXT_WINDOW,
|
|
931
|
-
maxTokens: MAX_OUTPUT_TOKENS,
|
|
932
|
-
description: "Qwen 3.8-Max (qmodel_38max); 1M context."
|
|
933
|
-
},
|
|
934
|
-
{
|
|
935
|
-
id: "qwen3.8-flash",
|
|
936
|
-
upstreamKey: "qfmodel",
|
|
937
|
-
name: "Qwen 3.8-Flash \xB7 Qoder CN",
|
|
938
|
-
api: "qoder-api",
|
|
939
|
-
provider: "qoder-cn",
|
|
940
|
-
baseUrl: getQoderBaseUrl("cn"),
|
|
941
|
-
reasoning: true,
|
|
942
|
-
supportsEffort: true,
|
|
943
|
-
input: ["text", "image"],
|
|
944
|
-
cost: ZERO_COST,
|
|
945
|
-
contextWindow: DEFAULT_CONTEXT_WINDOW,
|
|
946
|
-
maxTokens: MAX_OUTPUT_TOKENS,
|
|
947
|
-
description: "Qwen 3.8-Flash (qfmodel); multimodal MoE, 1M context."
|
|
948
|
-
},
|
|
949
|
-
{
|
|
950
|
-
id: "qwen3.7-max",
|
|
951
|
-
upstreamKey: "qmodel_latest",
|
|
952
|
-
name: "Qwen 3.7-Max \xB7 Qoder CN",
|
|
953
|
-
api: "qoder-api",
|
|
954
|
-
provider: "qoder-cn",
|
|
955
|
-
baseUrl: getQoderBaseUrl("cn"),
|
|
956
|
-
reasoning: true,
|
|
957
|
-
supportsEffort: false,
|
|
958
|
-
input: ["text", "image"],
|
|
959
|
-
cost: ZERO_COST,
|
|
960
|
-
contextWindow: DEFAULT_CONTEXT_WINDOW,
|
|
961
|
-
maxTokens: MAX_OUTPUT_TOKENS,
|
|
962
|
-
description: "Qwen 3.7-Max (qmodel_latest); context options 200K/400K/1M."
|
|
963
|
-
},
|
|
964
|
-
{
|
|
965
|
-
id: "qwen3.7-plus",
|
|
966
|
-
upstreamKey: "qmodel",
|
|
967
|
-
name: "Qwen 3.7-Plus \xB7 Qoder CN",
|
|
968
|
-
api: "qoder-api",
|
|
969
|
-
provider: "qoder-cn",
|
|
970
|
-
baseUrl: getQoderBaseUrl("cn"),
|
|
971
|
-
reasoning: true,
|
|
972
|
-
supportsEffort: false,
|
|
973
|
-
input: ["text", "image"],
|
|
974
|
-
cost: ZERO_COST,
|
|
975
|
-
contextWindow: DEFAULT_CONTEXT_WINDOW,
|
|
976
|
-
maxTokens: MAX_OUTPUT_TOKENS,
|
|
977
|
-
description: "Qwen 3.7-Plus (qmodel); context options 200K/400K/1M."
|
|
978
|
-
},
|
|
979
|
-
{
|
|
980
|
-
id: "qwen3.7-flash",
|
|
981
|
-
upstreamKey: "q37fmodel",
|
|
982
|
-
name: "Qwen 3.7-Flash \xB7 Qoder CN",
|
|
983
|
-
api: "qoder-api",
|
|
984
|
-
provider: "qoder-cn",
|
|
985
|
-
baseUrl: getQoderBaseUrl("cn"),
|
|
986
|
-
reasoning: true,
|
|
987
|
-
supportsEffort: false,
|
|
988
|
-
input: ["text", "image"],
|
|
989
|
-
cost: ZERO_COST,
|
|
990
|
-
contextWindow: DEFAULT_CONTEXT_WINDOW,
|
|
991
|
-
maxTokens: MAX_OUTPUT_TOKENS,
|
|
992
|
-
description: "Qwen 3.7-Flash (q37fmodel); vision-language Flash, 1M context."
|
|
993
|
-
},
|
|
994
|
-
{
|
|
995
|
-
id: "deepseek-v4-pro",
|
|
996
|
-
upstreamKey: "dmodel",
|
|
997
|
-
name: "DeepSeek V4 Pro \xB7 Qoder CN",
|
|
998
|
-
api: "qoder-api",
|
|
999
|
-
provider: "qoder-cn",
|
|
1000
|
-
baseUrl: getQoderBaseUrl("cn"),
|
|
1001
|
-
reasoning: true,
|
|
1002
|
-
supportsEffort: true,
|
|
1003
|
-
input: ["text", "image"],
|
|
1004
|
-
cost: ZERO_COST,
|
|
1005
|
-
contextWindow: DEFAULT_CONTEXT_WINDOW,
|
|
1006
|
-
maxTokens: MAX_OUTPUT_TOKENS,
|
|
1007
|
-
description: "DeepSeek V4 Pro (dmodel); 1M context."
|
|
1008
|
-
},
|
|
1009
|
-
{
|
|
1010
|
-
id: "deepseek-v4-flash",
|
|
1011
|
-
upstreamKey: "dfmodel",
|
|
1012
|
-
name: "DeepSeek V4 Flash \xB7 Qoder CN",
|
|
1013
|
-
api: "qoder-api",
|
|
1014
|
-
provider: "qoder-cn",
|
|
1015
|
-
baseUrl: getQoderBaseUrl("cn"),
|
|
1016
|
-
reasoning: true,
|
|
1017
|
-
supportsEffort: true,
|
|
1018
|
-
input: ["text", "image"],
|
|
1019
|
-
cost: ZERO_COST,
|
|
1020
|
-
contextWindow: DEFAULT_CONTEXT_WINDOW,
|
|
1021
|
-
maxTokens: MAX_OUTPUT_TOKENS,
|
|
1022
|
-
description: "DeepSeek V4 Flash (dfmodel); 1M context."
|
|
1023
|
-
},
|
|
1024
|
-
{
|
|
1025
|
-
id: "glm-5.3",
|
|
1026
|
-
upstreamKey: "gmodel",
|
|
1027
|
-
name: "GLM-5.3 \xB7 Qoder CN",
|
|
1028
|
-
api: "qoder-api",
|
|
1029
|
-
provider: "qoder-cn",
|
|
1030
|
-
baseUrl: getQoderBaseUrl("cn"),
|
|
1031
|
-
reasoning: true,
|
|
1032
|
-
supportsEffort: true,
|
|
1033
|
-
input: ["text", "image"],
|
|
1034
|
-
cost: ZERO_COST,
|
|
1035
|
-
contextWindow: DEFAULT_CONTEXT_WINDOW,
|
|
1036
|
-
maxTokens: MAX_OUTPUT_TOKENS,
|
|
1037
|
-
description: "GLM-5.3 (gmodel); Zhipu flagship open-source, 1M context."
|
|
1038
|
-
},
|
|
1039
|
-
{
|
|
1040
|
-
id: "glm-5.3-flash",
|
|
1041
|
-
upstreamKey: "gfmodel",
|
|
1042
|
-
name: "GLM-5.3-Flash \xB7 Qoder CN",
|
|
1043
|
-
api: "qoder-api",
|
|
1044
|
-
provider: "qoder-cn",
|
|
1045
|
-
baseUrl: getQoderBaseUrl("cn"),
|
|
1046
|
-
reasoning: true,
|
|
1047
|
-
supportsEffort: true,
|
|
1048
|
-
input: ["text", "image"],
|
|
1049
|
-
cost: ZERO_COST,
|
|
1050
|
-
contextWindow: DEFAULT_CONTEXT_WINDOW,
|
|
1051
|
-
maxTokens: MAX_OUTPUT_TOKENS,
|
|
1052
|
-
description: "GLM-5.3-Flash (gfmodel); 1M context."
|
|
1053
|
-
},
|
|
1054
|
-
{
|
|
1055
|
-
id: "glm-5.2",
|
|
1056
|
-
upstreamKey: "gm51model",
|
|
1057
|
-
name: "GLM 5.2 \xB7 Qoder CN",
|
|
1058
|
-
api: "qoder-api",
|
|
1059
|
-
provider: "qoder-cn",
|
|
1060
|
-
baseUrl: getQoderBaseUrl("cn"),
|
|
1061
|
-
reasoning: true,
|
|
1062
|
-
supportsEffort: true,
|
|
1063
|
-
input: ["text", "image"],
|
|
1064
|
-
cost: ZERO_COST,
|
|
1065
|
-
contextWindow: DEFAULT_CONTEXT_WINDOW,
|
|
1066
|
-
maxTokens: MAX_OUTPUT_TOKENS,
|
|
1067
|
-
description: "GLM 5.2 (gm51model); 1M context."
|
|
1068
|
-
},
|
|
1069
|
-
{
|
|
1070
|
-
id: "kimi-k3",
|
|
1071
|
-
upstreamKey: "kmodel_latest",
|
|
1072
|
-
name: "Kimi-K3 \xB7 Qoder CN",
|
|
1073
|
-
api: "qoder-api",
|
|
1074
|
-
provider: "qoder-cn",
|
|
1075
|
-
baseUrl: getQoderBaseUrl("cn"),
|
|
1076
|
-
reasoning: true,
|
|
1077
|
-
supportsEffort: true,
|
|
1078
|
-
input: ["text", "image"],
|
|
1079
|
-
cost: ZERO_COST,
|
|
1080
|
-
contextWindow: DEFAULT_CONTEXT_WINDOW,
|
|
1081
|
-
maxTokens: MAX_OUTPUT_TOKENS,
|
|
1082
|
-
description: "Kimi-K3 (kmodel_latest); 1M context."
|
|
1083
|
-
},
|
|
1084
|
-
{
|
|
1085
|
-
id: "kimi-k2.7-code",
|
|
1086
|
-
upstreamKey: "kmodel",
|
|
1087
|
-
name: "Kimi-K2.7-Code \xB7 Qoder CN",
|
|
1088
|
-
api: "qoder-api",
|
|
1089
|
-
provider: "qoder-cn",
|
|
1090
|
-
baseUrl: getQoderBaseUrl("cn"),
|
|
1091
|
-
reasoning: true,
|
|
1092
|
-
supportsEffort: false,
|
|
1093
|
-
input: ["text", "image"],
|
|
1094
|
-
cost: ZERO_COST,
|
|
1095
|
-
// Live catalog advertises 256K for this entry.
|
|
1096
|
-
contextWindow: 256e3,
|
|
1097
|
-
maxTokens: MAX_OUTPUT_TOKENS,
|
|
1098
|
-
description: "Kimi-K2.7-Code (kmodel); 256K context."
|
|
1099
|
-
},
|
|
1100
|
-
{
|
|
1101
|
-
id: "minimax-m2.7",
|
|
1102
|
-
upstreamKey: "mmodel",
|
|
1103
|
-
name: "MiniMax M2.7 \xB7 Qoder CN",
|
|
1104
|
-
api: "qoder-api",
|
|
1105
|
-
provider: "qoder-cn",
|
|
1106
|
-
baseUrl: getQoderBaseUrl("cn"),
|
|
1107
|
-
reasoning: false,
|
|
1108
|
-
supportsEffort: false,
|
|
1109
|
-
input: ["text"],
|
|
1110
|
-
cost: ZERO_COST,
|
|
1111
|
-
// Live CN catalog reports 200K; not confirmed at 1M.
|
|
1112
|
-
contextWindow: 2e5,
|
|
1113
|
-
maxTokens: MAX_OUTPUT_TOKENS,
|
|
1114
|
-
description: "MiniMax M2.7 (mmodel); 200K context."
|
|
1115
915
|
}
|
|
1116
916
|
];
|
|
1117
917
|
PI_THINKING_LEVELS = ["minimal", "low", "medium", "high", "xhigh", "max"];
|
|
@@ -2647,6 +2447,81 @@ async function runClaimCommand(mode, args, ctx) {
|
|
|
2647
2447
|
}
|
|
2648
2448
|
}
|
|
2649
2449
|
|
|
2450
|
+
// src/commands/models.ts
|
|
2451
|
+
init_catalog();
|
|
2452
|
+
init_region();
|
|
2453
|
+
function formatCatalogDiff(diff, mode, color = false) {
|
|
2454
|
+
const region = getQoderRegionConfig(mode);
|
|
2455
|
+
const paint3 = (text, code) => color ? `${code}${text}\x1B[0m` : text;
|
|
2456
|
+
const lines = [`${region.usageTitle} models \xB7 ${diff.total} offered by the catalog`];
|
|
2457
|
+
if (diff.added.length > 0) {
|
|
2458
|
+
lines.push("", paint3(`New (${diff.added.length})`, "\x1B[32m"));
|
|
2459
|
+
for (const model of diff.added) lines.push(` + ${model.id} ${model.name}`);
|
|
2460
|
+
}
|
|
2461
|
+
if (diff.renamed.length > 0) {
|
|
2462
|
+
lines.push("", paint3(`Renamed upstream (${diff.renamed.length})`, "\x1B[33m"));
|
|
2463
|
+
for (const model of diff.renamed) lines.push(` ~ ${model.id} ${model.from} -> ${model.to}`);
|
|
2464
|
+
}
|
|
2465
|
+
if (diff.removed.length > 0) {
|
|
2466
|
+
lines.push("", paint3(`Gone (${diff.removed.length})`, "\x1B[31m"));
|
|
2467
|
+
for (const model of diff.removed) lines.push(` - ${model.id} ${model.name}`);
|
|
2468
|
+
}
|
|
2469
|
+
if (diff.added.length === 0 && diff.renamed.length === 0 && diff.removed.length === 0) {
|
|
2470
|
+
lines.push("", "No change since the last refresh.");
|
|
2471
|
+
}
|
|
2472
|
+
lines.push("", `Provider list refreshed in this session; /model now shows ${diff.total} entries.`);
|
|
2473
|
+
return lines;
|
|
2474
|
+
}
|
|
2475
|
+
async function refreshCatalog(mode, accessToken, identity, refreshProvider) {
|
|
2476
|
+
const region = getQoderRegionConfig(mode);
|
|
2477
|
+
clearQoderModelsMemCache();
|
|
2478
|
+
const diff = await updateQoderModelsCache(
|
|
2479
|
+
accessToken,
|
|
2480
|
+
identity.userID || "qoder-user",
|
|
2481
|
+
identity.name || region.userNameFallback,
|
|
2482
|
+
identity.email || region.userEmailFallback,
|
|
2483
|
+
mode
|
|
2484
|
+
);
|
|
2485
|
+
if (diff) {
|
|
2486
|
+
clearQoderModelsMemCache();
|
|
2487
|
+
refreshProvider?.();
|
|
2488
|
+
}
|
|
2489
|
+
return diff;
|
|
2490
|
+
}
|
|
2491
|
+
async function runModelsCommand(mode, args, ctx, refreshProvider) {
|
|
2492
|
+
const region = getQoderRegionConfig(mode);
|
|
2493
|
+
const providerID = region.providerID;
|
|
2494
|
+
const target = (args || "").trim().toLowerCase();
|
|
2495
|
+
const plain = target === "plain";
|
|
2496
|
+
const wantsList = target === "list";
|
|
2497
|
+
try {
|
|
2498
|
+
const accessToken = await ctx?.modelRegistry?.getApiKeyForProvider(providerID);
|
|
2499
|
+
if (!accessToken) {
|
|
2500
|
+
ctx?.ui?.notify(`No ${providerID} credentials. Run /login ${providerID} first.`, "warning");
|
|
2501
|
+
return;
|
|
2502
|
+
}
|
|
2503
|
+
if (wantsList) {
|
|
2504
|
+
const models = getCachedModels(mode);
|
|
2505
|
+
ctx?.ui?.notify(
|
|
2506
|
+
[`${region.usageTitle} models`, ...models.map((model) => ` ${model.id} ${model.name}`)].join("\n")
|
|
2507
|
+
);
|
|
2508
|
+
return;
|
|
2509
|
+
}
|
|
2510
|
+
const diff = await refreshCatalog(mode, accessToken, {}, refreshProvider);
|
|
2511
|
+
if (!diff) {
|
|
2512
|
+
ctx?.ui?.notify(
|
|
2513
|
+
`Could not refresh the ${providerID} model catalog (network, credentials, or an unexpected payload). The existing list is unchanged.`,
|
|
2514
|
+
"warning"
|
|
2515
|
+
);
|
|
2516
|
+
return;
|
|
2517
|
+
}
|
|
2518
|
+
ctx?.ui?.notify(formatCatalogDiff(diff, mode, !plain).join("\n"));
|
|
2519
|
+
} catch (error) {
|
|
2520
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2521
|
+
ctx?.ui?.notify(`Model refresh failed: ${message}`, "error");
|
|
2522
|
+
}
|
|
2523
|
+
}
|
|
2524
|
+
|
|
2650
2525
|
// src/commands/usage.ts
|
|
2651
2526
|
init_region();
|
|
2652
2527
|
var DEFAULT_GRANT_CREDITS = 100;
|
|
@@ -2655,7 +2530,7 @@ function positiveOr(value, fallback) {
|
|
|
2655
2530
|
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : fallback;
|
|
2656
2531
|
}
|
|
2657
2532
|
function estimateRollingAddOnExpiry(addOn, grant, now = Date.now()) {
|
|
2658
|
-
if (!addOn
|
|
2533
|
+
if (!addOn?.total || addOn.total <= 0 || !addOn.remaining || addOn.remaining <= 0) {
|
|
2659
2534
|
return null;
|
|
2660
2535
|
}
|
|
2661
2536
|
const shape = typeof grant === "number" ? { expiryMs: grant } : grant ?? {};
|
|
@@ -4158,13 +4033,16 @@ function registerQoderProvider(pi, mode) {
|
|
|
4158
4033
|
streamSimple: streamQoder
|
|
4159
4034
|
});
|
|
4160
4035
|
}
|
|
4036
|
+
function reregisterQoderProvider(pi, mode) {
|
|
4037
|
+
registerQoderProvider(pi, mode);
|
|
4038
|
+
}
|
|
4161
4039
|
async function refreshModelsAtStartup(mode) {
|
|
4162
4040
|
const providerID = getQoderRegionConfig(mode).providerID;
|
|
4163
|
-
if (!isCacheStale(mode)) return;
|
|
4041
|
+
if (!isCacheStale(mode)) return null;
|
|
4164
4042
|
const credentials = getCachedCredentials("", providerID);
|
|
4165
|
-
if (!credentials?.access) return;
|
|
4043
|
+
if (!credentials?.access) return null;
|
|
4166
4044
|
const region = getQoderRegionConfig(mode);
|
|
4167
|
-
|
|
4045
|
+
return updateQoderModelsCache(
|
|
4168
4046
|
credentials.access,
|
|
4169
4047
|
credentials.userID || "qoder-user",
|
|
4170
4048
|
credentials.name || region.userNameFallback,
|
|
@@ -4216,6 +4094,12 @@ function registerCommands(pi) {
|
|
|
4216
4094
|
await runClaimCommand("cn", args, ctx);
|
|
4217
4095
|
}
|
|
4218
4096
|
});
|
|
4097
|
+
pi.registerCommand("qoder-cn.models", {
|
|
4098
|
+
description: "Refresh the Qoder CN model catalog and report new, renamed and retired models (append 'list' for the cached list)",
|
|
4099
|
+
handler: async (args, ctx) => {
|
|
4100
|
+
await runModelsCommand("cn", args, ctx, () => reregisterQoderProvider(pi, "cn"));
|
|
4101
|
+
}
|
|
4102
|
+
});
|
|
4219
4103
|
pi.registerCommand("qoder.usage", {
|
|
4220
4104
|
description: "Show Qoder Global quota: plan + add-on credits and check-in status (append 'json' for raw payload)",
|
|
4221
4105
|
handler: async (args, ctx) => {
|
|
@@ -4228,6 +4112,12 @@ function registerCommands(pi) {
|
|
|
4228
4112
|
await runClaimCommand("global", args, ctx);
|
|
4229
4113
|
}
|
|
4230
4114
|
});
|
|
4115
|
+
pi.registerCommand("qoder.models", {
|
|
4116
|
+
description: "Refresh the Qoder Global model catalog and report new, renamed and retired models (append 'list' for the cached list)",
|
|
4117
|
+
handler: async (args, ctx) => {
|
|
4118
|
+
await runModelsCommand("global", args, ctx, () => reregisterQoderProvider(pi, "global"));
|
|
4119
|
+
}
|
|
4120
|
+
});
|
|
4231
4121
|
}
|
|
4232
4122
|
export {
|
|
4233
4123
|
index_default as default
|
package/package.json
CHANGED