dsh-router-core 0.3.3 → 0.3.5

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.
@@ -0,0 +1,339 @@
1
+ import { join } from "node:path";
2
+ import { mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
3
+ //#region src/suppliers/nvidia/plugin.ts
4
+ /**
5
+ * nvidia 供应商插件 —— 参考 9Router(open-sse) 的 nvidia 实现。
6
+ *
7
+ * 上游:https://integrate.api.nvidia.com/v1(OpenAI 兼容)
8
+ * - chat: POST /v1/chat/completions(SSE 流式 / 非流式)
9
+ * - models: GET /v1/models(公开,无需鉴权,返回全量模型)
10
+ *
11
+ * API key 账号:走「添加链接 + 连接池」(同 openrouter),弹窗填名字+key,
12
+ * 一个供应商可有多个命名 key,按池顺序/策略尝试。凭证存通用 CredentialStore
13
+ * (SQLite:auths/credentials.sqlite,{ name, apiKey })。key 有效性用 chat 探测
14
+ * (无 key → 400,无效 key → 401,有效 → 200)。
15
+ *
16
+ * 模型不内置、不缓存:listModels 每次从上游 /v1/models 拉取(全量,不过滤),
17
+ * 缓存由 dsh-router 核心统一管。
18
+ */
19
+ const id = "nvidia";
20
+ const name = "NVIDIA NIM";
21
+ const priority = 20;
22
+ /**
23
+ * 面板图标(NVIDIA 官方 logo,128×128 PNG,base64 内联)。
24
+ *
25
+ * **必须内联,不能放网络 URL**:之前是 `http://localhost:20128/...`(9router
26
+ * 的端口),9router 没跑时就是一张坏图 —— 面板图标不该依赖另一个服务活着,
27
+ * 更不该依赖特定端口。跟 opencode / openrouter / traework 的做法保持一致。
28
+ */
29
+ const icon = "data:image/png;base64,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";
30
+ const BASE = "https://integrate.api.nvidia.com/v1";
31
+ const MODELS_URL = `${BASE}/models`;
32
+ const CHAT_URL = `${BASE}/chat/completions`;
33
+ /** 默认前缀(用户可在面板改;loader 包装会优先用 store 里的值)。 */
34
+ /** 非聊天用途的模型(护栏/翻译/解析/检测/图像生成等),聊天路由用不上,拉列表时过滤掉。 */
35
+ const NON_CHAT_MODEL = /(guard|safety|moderation|translate|transcription|parse|detector|embed|rerank|diffusion|tts|asr|calibration)/i;
36
+ /** 剥 alias 前缀(nv/xxx → xxx)。 */
37
+ /** 剥本供应商 alias 前缀(只剥自己的,模型 id 自带的斜杠保留)。 */
38
+ function stripAlias(model, alias) {
39
+ return alias !== "" && model.startsWith(`${alias}/`) ? model.slice(alias.length + 1) : model;
40
+ }
41
+ function factory(env) {
42
+ let modelsCache;
43
+ /** 上次 chatOnce 失败原因(供核心测试模型汇总诊断)。 */
44
+ function listKeys() {
45
+ return env.credentials.list(id);
46
+ }
47
+ function getKey(uid) {
48
+ return env.credentials.get(id, uid);
49
+ }
50
+ /** 账号顺序:池顺序优先,未配置按凭证原始顺序。 */
51
+ function orderedKeys() {
52
+ const byUid = new Map(listKeys().map((uid) => [uid, uid]));
53
+ const order = env.store.get(id).poolOrder;
54
+ return [...order.filter((u) => byUid.has(u)), ...listKeys().filter((u) => !order.includes(u))].map((uid) => ({
55
+ uid,
56
+ acct: getKey(uid)
57
+ })).filter((x) => x.acct !== void 0);
58
+ }
59
+ /** 当前前缀(与 loader 包装一致:store 覆盖默认值)。 */
60
+ function currentAlias() {
61
+ return env.store.get("nvidia").alias || "nvidia";
62
+ }
63
+ /** 已确认不可用的模型(下线/未授权)。 */
64
+ const deadModels = /* @__PURE__ */ new Set();
65
+ /** 已确认可用的模型(避免重复探测)。 */
66
+ const okModels = /* @__PURE__ */ new Set();
67
+ const PROBE_CONCURRENCY = 8;
68
+ function probeFile() {
69
+ return join(env.dataDir, "nvidia-models.json");
70
+ }
71
+ function loadProbeState() {
72
+ try {
73
+ const j = JSON.parse(readFileSync(probeFile(), "utf8"));
74
+ for (const m of j.dead ?? []) deadModels.add(m);
75
+ for (const m of j.ok ?? []) okModels.add(m);
76
+ } catch {}
77
+ }
78
+ function saveProbeState() {
79
+ try {
80
+ mkdirSync(env.dataDir, { recursive: true });
81
+ const tmp = `${probeFile()}.tmp`;
82
+ writeFileSync(tmp, JSON.stringify({
83
+ dead: [...deadModels],
84
+ ok: [...okModels],
85
+ at: Date.now()
86
+ }));
87
+ renameSync(tmp, probeFile());
88
+ } catch {}
89
+ }
90
+ loadProbeState();
91
+ /** 探测单个模型:'ok' | 'dead' | 'unauthorized' | 'unknown'。 */
92
+ async function probeModel(apiKey, model) {
93
+ try {
94
+ const r = await fetch(CHAT_URL, {
95
+ method: "POST",
96
+ headers: {
97
+ "Content-Type": "application/json",
98
+ Authorization: `Bearer ${apiKey}`,
99
+ "User-Agent": "dsh-router"
100
+ },
101
+ body: JSON.stringify({
102
+ model,
103
+ messages: [{
104
+ role: "user",
105
+ content: "ping"
106
+ }],
107
+ stream: false,
108
+ max_tokens: 1
109
+ }),
110
+ signal: AbortSignal.timeout(15e3)
111
+ });
112
+ if (r.ok) return "ok";
113
+ if (r.status === 401 || r.status === 403) return "unauthorized";
114
+ if (r.status === 404 || r.status === 410) return "dead";
115
+ return "unknown";
116
+ } catch {
117
+ return "unknown";
118
+ }
119
+ }
120
+ /** 并发探测全部「未探测过」的模型,更新 dead/ok 并持久化。 */
121
+ async function probeAll(ids) {
122
+ const acct = orderedKeys()[0];
123
+ if (acct === void 0) return;
124
+ const todo = ids.filter((m) => !deadModels.has(m) && !okModels.has(m) && !NON_CHAT_MODEL.test(m));
125
+ if (todo.length === 0) return;
126
+ let cursor = 0;
127
+ let unauthorized = false;
128
+ let changed = false;
129
+ await Promise.all(Array.from({ length: Math.min(PROBE_CONCURRENCY, todo.length) }, async () => {
130
+ for (;;) {
131
+ const i = cursor++;
132
+ if (i >= todo.length || unauthorized) return;
133
+ const model = todo[i];
134
+ const r = await probeModel(acct.acct.apiKey, model);
135
+ if (r === "unauthorized") unauthorized = true;
136
+ else if (r === "ok") {
137
+ okModels.add(model);
138
+ changed = true;
139
+ } else if (r === "dead") {
140
+ deadModels.add(model);
141
+ changed = true;
142
+ }
143
+ }
144
+ }));
145
+ if (changed) saveProbeState();
146
+ env.log(`nvidia probe: ${okModels.size} ok / ${deadModels.size} dead`);
147
+ }
148
+ async function refreshModels(force = false) {
149
+ try {
150
+ const resp = await fetch(MODELS_URL, {
151
+ headers: { "User-Agent": "dsh-router" },
152
+ signal: AbortSignal.timeout(15e3)
153
+ });
154
+ if (!resp.ok) return [];
155
+ const raw = (await resp.json()).data ?? [];
156
+ const models = [];
157
+ const ids = /* @__PURE__ */ new Set();
158
+ for (const m of raw) {
159
+ if (m.id === "" || ids.has(m.id)) continue;
160
+ ids.add(m.id);
161
+ const entry = { id: m.id };
162
+ if ((m.context_length ?? 0) > 0) entry.context_length = Math.round((m.context_length ?? 0) / 1e3);
163
+ models.push(entry);
164
+ }
165
+ if (models.length > 0) modelsCache = models;
166
+ if (force && models.length > 0) await probeAll(models.map((m) => m.id));
167
+ return models.filter((m) => !deadModels.has(m.id) && !NON_CHAT_MODEL.test(m.id));
168
+ } catch {
169
+ return (modelsCache ?? []).filter((m) => !deadModels.has(m.id) && !NON_CHAT_MODEL.test(m.id));
170
+ }
171
+ }
172
+ async function allModels(force) {
173
+ return refreshModels(force);
174
+ }
175
+ /** key 有效性探测:只有 401/403 才算 key 无效。
176
+ * NIM 模型下线很快(410)或没授权给该账号(404),那是模型问题不是 key 问题——
177
+ * 固定探测某个模型迟早腐化,故 404/410 视为 key 有效。 */
178
+ async function probeKey(apiKey) {
179
+ const probe = await fetch(CHAT_URL, {
180
+ method: "POST",
181
+ headers: {
182
+ "Content-Type": "application/json",
183
+ Authorization: `Bearer ${apiKey}`,
184
+ "User-Agent": "dsh-router"
185
+ },
186
+ body: JSON.stringify({
187
+ model: "nvidia/nemotron-3-ultra-550b-a55b",
188
+ messages: [{
189
+ role: "user",
190
+ content: "ping"
191
+ }],
192
+ stream: false,
193
+ max_tokens: 1
194
+ }),
195
+ signal: AbortSignal.timeout(3e4)
196
+ });
197
+ if (probe.ok) return { ok: true };
198
+ if (probe.status === 401 || probe.status === 403) {
199
+ const text = await probe.text().catch(() => "");
200
+ return {
201
+ ok: false,
202
+ error: `key 无效: ${probe.status} ${text.slice(0, 200)}`
203
+ };
204
+ }
205
+ return { ok: true };
206
+ }
207
+ return {
208
+ id,
209
+ name,
210
+ priority: 20,
211
+ icon,
212
+ status: () => {
213
+ const accounts = orderedKeys().map(({ uid, acct }) => ({
214
+ uid,
215
+ nickname: acct.name || "API Key",
216
+ credits: 0,
217
+ state: "ok"
218
+ }));
219
+ return {
220
+ id,
221
+ name,
222
+ accounts
223
+ };
224
+ },
225
+ listModels: (force) => allModels(!!force),
226
+ async addApiKey(input) {
227
+ const key = input.apiKey.trim();
228
+ if (key === "") return {
229
+ ok: false,
230
+ error: "API key 不能为空"
231
+ };
232
+ try {
233
+ const r = await probeKey(key);
234
+ if (!r.ok) return r;
235
+ } catch (err) {
236
+ return {
237
+ ok: false,
238
+ error: `验证失败: ${err.message}`
239
+ };
240
+ }
241
+ let n = listKeys().length + 1;
242
+ let uid = `key-${n}`;
243
+ while (getKey(uid) !== void 0) uid = `key-${++n}`;
244
+ env.credentials.save(id, uid, {
245
+ name: input.name.trim() || `Key ${n}`,
246
+ apiKey: key
247
+ });
248
+ env.log(`nvidia add api key ${uid}`);
249
+ return {
250
+ ok: true,
251
+ account: {
252
+ uid,
253
+ nickname: input.name.trim() || `Key ${n}`
254
+ }
255
+ };
256
+ },
257
+ async removeLink(uid) {
258
+ if (getKey(uid) === void 0) return false;
259
+ env.credentials.remove(id, uid);
260
+ return true;
261
+ },
262
+ /** 对单个 key 调一次上游。选号/冷却/换号是核心的活,这里只报结果。 */
263
+ async chatOnce(uid, req) {
264
+ const base = stripAlias(req.model, currentAlias());
265
+ if (!(await allModels(false)).some((m) => m.id === base)) return {
266
+ ok: false,
267
+ state: "no_such_model",
268
+ message: `unknown model ${JSON.stringify(req.model)}`
269
+ };
270
+ const acct = getKey(uid);
271
+ if (acct === void 0) return {
272
+ ok: false,
273
+ state: "no_such_model",
274
+ message: `unknown account ${JSON.stringify(uid)}`
275
+ };
276
+ let body = req.rawBody;
277
+ try {
278
+ const obj = JSON.parse(body);
279
+ obj.model = base;
280
+ body = JSON.stringify(obj);
281
+ } catch {}
282
+ let upstream;
283
+ try {
284
+ upstream = await fetch(CHAT_URL, {
285
+ method: "POST",
286
+ headers: {
287
+ "Content-Type": "application/json",
288
+ Authorization: `Bearer ${acct.apiKey}`,
289
+ "User-Agent": "dsh-router"
290
+ },
291
+ body,
292
+ signal: AbortSignal.timeout(12e4)
293
+ });
294
+ } catch (err) {
295
+ return {
296
+ ok: false,
297
+ state: "transport",
298
+ message: err.message
299
+ };
300
+ }
301
+ if (upstream.status < 200 || upstream.status >= 300) {
302
+ const text = await upstream.text().catch(() => "");
303
+ const msg = `upstream ${upstream.status}: ${text.slice(0, 120)}`;
304
+ return {
305
+ ok: false,
306
+ state: upstream.status === 429 ? "rate_limit" : upstream.status === 401 || upstream.status === 403 ? "session_dead" : upstream.status === 404 ? "unavailable" : "unknown",
307
+ message: msg
308
+ };
309
+ }
310
+ if (req.stream) {
311
+ if (!upstream.body) return {
312
+ ok: false,
313
+ state: "transport",
314
+ message: "nvidia upstream: empty stream body"
315
+ };
316
+ return {
317
+ ok: true,
318
+ stream: upstream.body
319
+ };
320
+ }
321
+ const text = await upstream.text().catch(() => "");
322
+ if (text === "") return {
323
+ ok: false,
324
+ state: "transport",
325
+ message: "nvidia upstream: empty body"
326
+ };
327
+ return {
328
+ ok: true,
329
+ status: upstream.status,
330
+ body: text
331
+ };
332
+ },
333
+ dispose: () => {
334
+ modelsCache = void 0;
335
+ }
336
+ };
337
+ }
338
+ //#endregion
339
+ export { factory as default, icon, id, name, priority };
@@ -0,0 +1,137 @@
1
+ //#region src/suppliers/opencode/plugin.ts
2
+ const id = "opencode";
3
+ const name = "OpenCode Free";
4
+ const priority = 0;
5
+ /** 面板图标。 */
6
+ const icon = "data:image/png;base64,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";
7
+ const BASE = "https://opencode.ai/zen/v1";
8
+ const MODELS_URL = `${BASE}/models`;
9
+ const CHAT_URL = `${BASE}/chat/completions`;
10
+ const UA = "opencode";
11
+ /** 免费模型识别:id 以 -free 结尾,或已知不带后缀的免费模型。 */
12
+ const KNOWN_FREE = /* @__PURE__ */ new Set(["big-pickle"]);
13
+ function factory(env) {
14
+ let modelsCache;
15
+ /** 上次 chatOnce 失败原因(供核心测试模型汇总诊断)。 */
16
+ async function refreshModels() {
17
+ try {
18
+ const resp = await fetch(MODELS_URL, {
19
+ headers: {
20
+ "User-Agent": UA,
21
+ "x-opencode-client": "desktop"
22
+ },
23
+ signal: AbortSignal.timeout(15e3)
24
+ });
25
+ if (!resp.ok) return [];
26
+ const raw = (await resp.json()).data ?? [];
27
+ const models = [];
28
+ for (const m of raw) {
29
+ if (m.id === "") continue;
30
+ if (!m.id.endsWith("-free") && !KNOWN_FREE.has(m.id)) continue;
31
+ models.push({ id: m.id });
32
+ }
33
+ if (models.length > 0) modelsCache = models;
34
+ return models;
35
+ } catch {
36
+ return modelsCache ?? [];
37
+ }
38
+ }
39
+ async function allModels(force) {
40
+ return refreshModels();
41
+ }
42
+ /** 当前前缀(与 loader 包装一致:store 覆盖默认值)。 */
43
+ function currentAlias() {
44
+ return env.store.get("opencode").alias || "opencode";
45
+ }
46
+ /** 剥本供应商 alias 前缀(只剥自己的,模型 id 自带的斜杠保留)。 */
47
+ function stripAlias(model, alias) {
48
+ return alias !== "" && model.startsWith(`${alias}/`) ? model.slice(alias.length + 1) : model;
49
+ }
50
+ /** 剥 alias 前缀(oc/xxx → xxx)后判断是否 free 模型。 */
51
+ function isFreeModel(model) {
52
+ const base = stripAlias(model.trim(), currentAlias());
53
+ return base.endsWith("-free") || KNOWN_FREE.has(base);
54
+ }
55
+ return {
56
+ id,
57
+ name,
58
+ priority: 0,
59
+ icon,
60
+ status: () => ({
61
+ id,
62
+ name,
63
+ accounts: []
64
+ }),
65
+ listModels: (force) => allModels(!!force),
66
+ /** 无账号供应商:uid 恒为空,只认 free 模型。 */
67
+ async chatOnce(_uid, req) {
68
+ if (!isFreeModel(req.model)) return {
69
+ ok: false,
70
+ state: "no_such_model",
71
+ message: `unknown free model ${JSON.stringify(req.model)}`
72
+ };
73
+ let body = req.rawBody;
74
+ try {
75
+ const obj = JSON.parse(body);
76
+ obj.model = stripAlias(String(obj.model ?? req.model), currentAlias());
77
+ body = JSON.stringify(obj);
78
+ } catch {}
79
+ let upstream;
80
+ try {
81
+ upstream = await fetch(CHAT_URL, {
82
+ method: "POST",
83
+ headers: {
84
+ "Content-Type": "application/json",
85
+ Authorization: "Bearer public",
86
+ "User-Agent": UA,
87
+ "x-opencode-client": "desktop"
88
+ },
89
+ body,
90
+ signal: AbortSignal.timeout(12e4)
91
+ });
92
+ } catch (err) {
93
+ return {
94
+ ok: false,
95
+ state: "transport",
96
+ message: `opencode upstream: ${err.message}`
97
+ };
98
+ }
99
+ if (upstream.status < 200 || upstream.status >= 300) {
100
+ const text = await upstream.text().catch(() => "");
101
+ const msg = `upstream ${upstream.status}: ${text.slice(0, 200)}`;
102
+ return {
103
+ ok: false,
104
+ state: upstream.status === 429 ? "rate_limit" : upstream.status === 404 ? "unavailable" : "unknown",
105
+ message: msg
106
+ };
107
+ }
108
+ if (req.stream) {
109
+ if (!upstream.body) return {
110
+ ok: false,
111
+ state: "transport",
112
+ message: "opencode upstream: empty stream body"
113
+ };
114
+ return {
115
+ ok: true,
116
+ stream: upstream.body
117
+ };
118
+ }
119
+ const text = await upstream.text().catch(() => "");
120
+ if (text === "") return {
121
+ ok: false,
122
+ state: "transport",
123
+ message: "opencode upstream: empty body"
124
+ };
125
+ return {
126
+ ok: true,
127
+ status: upstream.status,
128
+ body: text
129
+ };
130
+ },
131
+ dispose: () => {
132
+ modelsCache = void 0;
133
+ }
134
+ };
135
+ }
136
+ //#endregion
137
+ export { factory as default, icon, id, name, priority };