dsh-multi-router 0.5.3 → 0.5.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.
- package/CHANGELOG.md +16 -0
- package/README.md +32 -18
- package/lib/accounts.js +2 -2
- package/lib/{chunk-JYVJJ7OX.js → chunk-CT6ZYIAF.js} +4 -4
- package/lib/{chunk-JYVJJ7OX.js.map → chunk-CT6ZYIAF.js.map} +2 -2
- package/lib/{chunk-RPW6DI6O.js → chunk-EGLF4CWD.js} +33 -8
- package/lib/{chunk-RPW6DI6O.js.map → chunk-EGLF4CWD.js.map} +3 -3
- package/lib/{chunk-XA3V2DGT.js → chunk-J3XO7RTF.js} +90 -13
- package/lib/chunk-J3XO7RTF.js.map +7 -0
- package/lib/{chunk-U7J4ABAM.js → chunk-MCHV2R25.js} +5 -2
- package/lib/{chunk-U7J4ABAM.js.map → chunk-MCHV2R25.js.map} +2 -2
- package/lib/{chunk-4H6ZXK75.js → chunk-OFFVP6YN.js} +2 -2
- package/lib/{chunk-EJWYFWIT.js → chunk-PQETKUGT.js} +75 -15
- package/lib/chunk-PQETKUGT.js.map +7 -0
- package/lib/cli.js +4 -4
- package/lib/client.js +570 -197
- package/lib/client.js.map +3 -3
- package/lib/clients.js +3 -3
- package/lib/host.js +24 -10
- package/lib/index.js +24 -10
- package/lib/index.js.map +2 -2
- package/lib/manager.js +5 -5
- package/lib/router.js +2 -2
- package/lib/shim.js +3 -3
- package/package.json +1 -1
- package/router.example.json +1 -1
- package/lib/chunk-EJWYFWIT.js.map +0 -7
- package/lib/chunk-XA3V2DGT.js.map +0 -7
- /package/lib/{chunk-4H6ZXK75.js.map → chunk-OFFVP6YN.js.map} +0 -0
|
@@ -3,20 +3,20 @@ import {
|
|
|
3
3
|
jsonCredential,
|
|
4
4
|
qoderPluginDataDir,
|
|
5
5
|
supportsCheckin
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-EGLF4CWD.js";
|
|
7
7
|
import {
|
|
8
8
|
discoverLocalAccounts,
|
|
9
9
|
importAccount,
|
|
10
10
|
localAccountKey,
|
|
11
11
|
readPortableCredential
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-OFFVP6YN.js";
|
|
13
13
|
import {
|
|
14
14
|
hostIsLoopback
|
|
15
15
|
} from "./chunk-DNQPZMPF.js";
|
|
16
16
|
import {
|
|
17
17
|
Telemetry,
|
|
18
18
|
matchModel
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-J3XO7RTF.js";
|
|
20
20
|
import {
|
|
21
21
|
PROVIDERS,
|
|
22
22
|
PROVIDER_NAMES,
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
routeReasoning,
|
|
28
28
|
validateConfig,
|
|
29
29
|
writePrivateJson
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-MCHV2R25.js";
|
|
31
31
|
import {
|
|
32
32
|
modelWithCurrentPromotion
|
|
33
33
|
} from "./chunk-TEZ2FMEO.js";
|
|
@@ -36,7 +36,7 @@ import {
|
|
|
36
36
|
import { createHash, randomBytes as randomBytes2, timingSafeEqual } from "node:crypto";
|
|
37
37
|
|
|
38
38
|
// package.json
|
|
39
|
-
var version = "0.5.
|
|
39
|
+
var version = "0.5.5";
|
|
40
40
|
|
|
41
41
|
// src/manager.mjs
|
|
42
42
|
import { readFile as readFile2, mkdir as mkdir2, mkdtemp as mkdtemp2, rm as rm3 } from "node:fs/promises";
|
|
@@ -98,7 +98,7 @@ var derive = promisify(scrypt);
|
|
|
98
98
|
var FORMAT = "dsh-multi-router";
|
|
99
99
|
var MAX_BYTES = 512 * 1024;
|
|
100
100
|
var pick = (value, keys) => Object.fromEntries(keys.filter((k) => Object.hasOwn(value ?? {}, k)).map((k) => [k, value[k]]));
|
|
101
|
-
var options = ["cooldownMs", "requestTimeoutMs", "catalogTtlMs", "retryServerErrors", "modelVisibility", "usageRetentionDays"];
|
|
101
|
+
var options = ["cooldownMs", "requestTimeoutMs", "catalogTtlMs", "retryServerErrors", "modelVisibility", "usageRetentionDays", "checkinSchedule"];
|
|
102
102
|
function settings(config) {
|
|
103
103
|
return {
|
|
104
104
|
...pick(config, options),
|
|
@@ -414,7 +414,12 @@ async function refreshGitPlugin(service, profile, row, options2, signal) {
|
|
|
414
414
|
}, { waitMs: 12e4 });
|
|
415
415
|
}
|
|
416
416
|
var PluginUpdates = class {
|
|
417
|
-
constructor({ service = () => void 0, profile = () => void 0, fetchImpl = (...args) => fetch(...args), lookup = registryVersion, refreshGit = refreshGitPlugin } = {}) {
|
|
417
|
+
constructor({ service = () => void 0, profile = () => void 0, fetchImpl = (...args) => fetch(...args), lookup = registryVersion, refreshGit = refreshGitPlugin, stateFile, now = Date.now } = {}) {
|
|
418
|
+
this.stateFile = stateFile;
|
|
419
|
+
this.now = now;
|
|
420
|
+
this.dismissed = {};
|
|
421
|
+
this.lastAttempt = 0;
|
|
422
|
+
this.saveQueue = Promise.resolve();
|
|
418
423
|
this.service = service;
|
|
419
424
|
this.profile = profile;
|
|
420
425
|
this.fetchImpl = fetchImpl;
|
|
@@ -423,10 +428,47 @@ var PluginUpdates = class {
|
|
|
423
428
|
this.lookup = lookup;
|
|
424
429
|
this.refreshGit = refreshGit;
|
|
425
430
|
}
|
|
431
|
+
async load() {
|
|
432
|
+
const saved = this.stateFile && await jsonFile(this.stateFile);
|
|
433
|
+
if (saved?.version === 1) {
|
|
434
|
+
this.lastAttempt = Number.isFinite(saved.lastAttempt) ? saved.lastAttempt : 0;
|
|
435
|
+
this.checkedAt = saved.checkedAt;
|
|
436
|
+
this.dismissed = saved.dismissed && typeof saved.dismissed === "object" && !Array.isArray(saved.dismissed) ? saved.dismissed : {};
|
|
437
|
+
this.rows = Array.isArray(saved.rows) ? saved.rows.filter((r) => ["github", "npm"].includes(r.source?.kind)) : [];
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
persist() {
|
|
441
|
+
if (!this.stateFile) return Promise.resolve();
|
|
442
|
+
const saved = structuredClone({ version: 1, lastAttempt: this.lastAttempt, checkedAt: this.checkedAt, dismissed: this.dismissed, rows: this.rows.filter((r) => ["github", "npm"].includes(r.source.kind)) });
|
|
443
|
+
this.saveQueue = this.saveQueue.catch(() => {
|
|
444
|
+
}).then(() => writePrivateJson(this.stateFile, saved));
|
|
445
|
+
return this.saveQueue;
|
|
446
|
+
}
|
|
447
|
+
reminderKey(row) {
|
|
448
|
+
return JSON.stringify([row.name, row.source, row.version, row.latestVersion ?? row.latestCommit]);
|
|
449
|
+
}
|
|
450
|
+
reminders() {
|
|
451
|
+
return this.rows.filter((r) => r.status === "available" && (!Object.hasOwn(this.dismissed, r.name) || this.dismissed[r.name] !== this.reminderKey(r))).map((r) => ({ key: this.reminderKey(r), name: r.name, version: r.version, latestVersion: r.latestVersion, latestCommit: r.latestCommit }));
|
|
452
|
+
}
|
|
453
|
+
async dismiss(keys) {
|
|
454
|
+
if (!Array.isArray(keys) || keys.length > 200 || keys.some((k) => typeof k !== "string")) throw Error("\u65E0\u6548\u7684\u63D0\u9192\u5217\u8868");
|
|
455
|
+
for (const row of this.reminders()) if (keys.includes(row.key)) Object.defineProperty(this.dismissed, row.name, { value: row.key, enumerable: true, configurable: true, writable: true });
|
|
456
|
+
await this.persist();
|
|
457
|
+
}
|
|
458
|
+
async tick() {
|
|
459
|
+
if (this.flight || !this.state().available) return;
|
|
460
|
+
await this.list();
|
|
461
|
+
if (this.flight || this.now() >= this.lastAttempt && this.now() - this.lastAttempt < 864e5) return;
|
|
462
|
+
this.lastAttempt = this.now();
|
|
463
|
+
await this.persist();
|
|
464
|
+
if (!this.flight && !this.abort.signal.aborted) this.check();
|
|
465
|
+
}
|
|
426
466
|
state() {
|
|
427
467
|
return {
|
|
428
468
|
available: !!this.service()?.listBundles && !!this.profile()?.dir,
|
|
429
469
|
checkedAt: this.checkedAt,
|
|
470
|
+
reminders: this.reminders(),
|
|
471
|
+
autoCheckHours: 24,
|
|
430
472
|
rows: this.rows.map(({ spec, ...row }) => ({ ...row, source: row.source.kind === "unsupported" ? { kind: "unsupported" } : row.source })),
|
|
431
473
|
job: this.job,
|
|
432
474
|
error: this.error
|
|
@@ -440,9 +482,9 @@ var PluginUpdates = class {
|
|
|
440
482
|
}
|
|
441
483
|
const [manifest, bundles, lock] = await Promise.all([jsonFile(join3(profile.dir, "package.json")), service.listBundles(), locks(profile.dir)]);
|
|
442
484
|
if (!manifest) throw Error("\u5F53\u524D DSH \u914D\u7F6E\u7684\u63D2\u4EF6\u6E05\u5355\u65E0\u6CD5\u8BFB\u53D6");
|
|
443
|
-
this.rows = bundles.filter((b) => b.installed || b.version).map((b) => {
|
|
485
|
+
this.rows = bundles.filter((b) => (b.installed || b.version) && manifest.dependencies?.[b.name] && b.removable !== false).map((b) => {
|
|
444
486
|
const spec = manifest.dependencies?.[b.name];
|
|
445
|
-
const source =
|
|
487
|
+
const source = parsePluginSource(b.name, spec);
|
|
446
488
|
const npm = lock.npm?.packages?.[`node_modules/${b.name}`]?.resolved;
|
|
447
489
|
const pnpm = lock.pnpm?.importers?.["."]?.dependencies?.[b.name]?.version;
|
|
448
490
|
const installed = lock.preferNpm ? npm ?? pnpm : pnpm ?? npm;
|
|
@@ -455,8 +497,7 @@ var PluginUpdates = class {
|
|
|
455
497
|
spec,
|
|
456
498
|
source,
|
|
457
499
|
commit: githubCommit(installed),
|
|
458
|
-
status: previous?.status ?? (source.kind === "
|
|
459
|
-
...source.kind === "builtin" ? { message: "DSH \u81EA\u5E26 / \u53D7\u4FDD\u62A4\u7EC4\u4EF6\uFF0C\u8BF7\u901A\u8FC7\u66F4\u65B0 DeepSeek Harness \u5347\u7EA7" } : {},
|
|
500
|
+
status: previous?.status ?? (source.kind === "unsupported" ? "unsupported" : "unchecked"),
|
|
460
501
|
...source.kind === "unsupported" ? { message: "\u672C\u5730\u6587\u4EF6 / \u94FE\u63A5\u6765\u6E90\uFF0C\u8BF7\u901A\u8FC7\u539F\u5B89\u88C5\u65B9\u5F0F\u66F4\u65B0" } : {}
|
|
461
502
|
};
|
|
462
503
|
});
|
|
@@ -503,13 +544,20 @@ var PluginUpdates = class {
|
|
|
503
544
|
}, (e) => {
|
|
504
545
|
this.job.state = this.job.cancelRequested ? "cancelled" : "failed";
|
|
505
546
|
this.job.message = e.message;
|
|
506
|
-
}).finally(() => {
|
|
547
|
+
}).finally(async () => {
|
|
507
548
|
this.job.finishedAt = Date.now();
|
|
549
|
+
try {
|
|
550
|
+
await this.persist();
|
|
551
|
+
} catch {
|
|
552
|
+
this.error = "\u66F4\u65B0\u68C0\u67E5\u8BB0\u5F55\u672A\u80FD\u4FDD\u5B58\uFF0C\u8BF7\u68C0\u67E5\u672C\u5730\u76EE\u5F55\u6743\u9650";
|
|
553
|
+
}
|
|
508
554
|
this.flight = void 0;
|
|
509
555
|
});
|
|
510
556
|
}
|
|
511
557
|
check() {
|
|
512
558
|
this.start("check", async (job) => {
|
|
559
|
+
this.lastAttempt = this.now();
|
|
560
|
+
await this.persist();
|
|
513
561
|
await this.list();
|
|
514
562
|
const rows = this.rows.filter((r) => ["npm", "github"].includes(r.source.kind));
|
|
515
563
|
job.total = rows.length;
|
|
@@ -618,7 +666,8 @@ var PluginUpdates = class {
|
|
|
618
666
|
if (input.registry && !["https://registry.npmjs.org/", "https://registry.npmmirror.com/"].includes(input.registry)) throw Error("\u65E0\u6548\u7684 npm \u6765\u6E90");
|
|
619
667
|
if (input.action === "plugins.list") {
|
|
620
668
|
if (!this.flight) await this.list();
|
|
621
|
-
} else if (input.action === "plugins.
|
|
669
|
+
} else if (input.action === "plugins.dismiss") await this.dismiss(input.keys);
|
|
670
|
+
else if (input.action === "plugins.check") this.check();
|
|
622
671
|
else if (input.action === "plugins.update") this.update(input.names, input.registry);
|
|
623
672
|
else if (input.action === "plugins.install") this.install(input.spec, input.registry);
|
|
624
673
|
else if (input.action === "plugins.cancel") {
|
|
@@ -682,7 +731,7 @@ var Manager = class {
|
|
|
682
731
|
this.monitorFlights = /* @__PURE__ */ new Map();
|
|
683
732
|
this.loginInfo = /* @__PURE__ */ new Map();
|
|
684
733
|
this.telemetry = new Telemetry(join4(dirname3(file), "usage.json"));
|
|
685
|
-
this.plugins = new PluginUpdates(pluginAccess);
|
|
734
|
+
this.plugins = new PluginUpdates({ ...pluginAccess, stateFile: join4(dirname3(file), "plugin-updates.json") });
|
|
686
735
|
this.checkins = new Checkins(join4(dirname3(file), "checkins.json"), this);
|
|
687
736
|
this.setupFile = join4(dirname3(file), "initial-setup.json");
|
|
688
737
|
router.telemetry = this.telemetry;
|
|
@@ -699,6 +748,10 @@ var Manager = class {
|
|
|
699
748
|
}
|
|
700
749
|
this.config = validateConfig(this.raw, this.file);
|
|
701
750
|
await this.checkins.load();
|
|
751
|
+
await this.plugins.load();
|
|
752
|
+
if (this.plugins.state().available) await this.plugins.list().catch(() => {
|
|
753
|
+
this.plugins.rows = [];
|
|
754
|
+
});
|
|
702
755
|
try {
|
|
703
756
|
const saved = JSON.parse(await readFile2(this.catalogFile, "utf8"));
|
|
704
757
|
for (const account of this.config.accounts) {
|
|
@@ -1264,6 +1317,9 @@ var Manager = class {
|
|
|
1264
1317
|
}
|
|
1265
1318
|
if (input.name !== void 0) account.name = input.name;
|
|
1266
1319
|
if (input.enabled !== void 0) account.enabled = input.enabled;
|
|
1320
|
+
} else if (input.action === "accounts.enabled") {
|
|
1321
|
+
if (input.provider !== void 0 && !PROVIDERS.includes(input.provider) || typeof input.enabled !== "boolean") bad("\u4F9B\u5E94\u5546\u6216\u8DEF\u7531\u53C2\u4E0E\u5F00\u5173\u65E0\u6548");
|
|
1322
|
+
for (const a of raw.accounts.filter((a2) => !input.provider || a2.provider === input.provider)) a.enabled = input.enabled;
|
|
1267
1323
|
} else if (input.action === "account.move") {
|
|
1268
1324
|
if (!account || ![-1, 1].includes(input.direction)) bad("\u8D26\u53F7\u6216\u987A\u5E8F\u65E0\u6548");
|
|
1269
1325
|
const group = raw.accounts.filter((a) => a.provider === account.provider), position = group.indexOf(account) + input.direction;
|
|
@@ -1334,6 +1390,10 @@ var Manager = class {
|
|
|
1334
1390
|
raw.routes[id] = structuredClone(ROUTE_PRESETS[id]);
|
|
1335
1391
|
} else if (input.action === "preset.add-all") {
|
|
1336
1392
|
for (const [id, route] of Object.entries(ROUTE_PRESETS)) if (!Object.hasOwn(raw.routes, id)) raw.routes[id] = structuredClone(route);
|
|
1393
|
+
} else if (input.action === "checkins.settings") {
|
|
1394
|
+
if (this.checkins.flight) bad("\u8BF7\u7B49\u5F85\u5F53\u524D\u7B7E\u5230\u5B8C\u6210\u540E\u4FEE\u6539\u8BA1\u5212");
|
|
1395
|
+
if (!input.schedule) bad("\u8BF7\u586B\u5199\u7B7E\u5230\u8BA1\u5212");
|
|
1396
|
+
raw.checkinSchedule = input.schedule;
|
|
1337
1397
|
} else if (input.action === "options.save") {
|
|
1338
1398
|
for (const key of ["cooldownMs", "requestTimeoutMs", "retryServerErrors", "usageRetentionDays"]) if (input[key] !== void 0) raw[key] = input[key];
|
|
1339
1399
|
} else bad("\u672A\u77E5\u64CD\u4F5C");
|
|
@@ -1452,4 +1512,4 @@ export {
|
|
|
1452
1512
|
Manager,
|
|
1453
1513
|
managementHandler
|
|
1454
1514
|
};
|
|
1455
|
-
//# sourceMappingURL=chunk-
|
|
1515
|
+
//# sourceMappingURL=chunk-PQETKUGT.js.map
|