dsh-multi-router 0.5.8 → 0.6.0
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 +20 -0
- package/README.md +49 -8
- package/cordis.patch.yml +2 -2
- package/lib/accounts.js +6 -4
- package/lib/api-service.js +11 -0
- package/lib/api-service.js.map +7 -0
- package/lib/chunk-4V52V5GO.js +105 -0
- package/lib/chunk-4V52V5GO.js.map +7 -0
- package/lib/{chunk-OFFVP6YN.js → chunk-JUOESKAK.js} +22 -5
- package/lib/chunk-JUOESKAK.js.map +7 -0
- package/lib/{chunk-P43AWJ4Q.js → chunk-LLDJVBTQ.js} +3 -3
- package/lib/{chunk-U2MU2M5C.js → chunk-NSKCFVHP.js} +13 -111
- package/lib/chunk-NSKCFVHP.js.map +7 -0
- package/lib/{chunk-ILRW3ELD.js → chunk-OCMOMSB4.js} +293 -77
- package/lib/chunk-OCMOMSB4.js.map +7 -0
- package/lib/{chunk-FTM7RHQV.js → chunk-OK2T2UAZ.js} +4 -4
- package/lib/{chunk-J3XO7RTF.js → chunk-ROZINFTV.js} +3 -2
- package/lib/chunk-ROZINFTV.js.map +7 -0
- package/lib/chunk-SNEZMYNU.js +332 -0
- package/lib/chunk-SNEZMYNU.js.map +7 -0
- package/lib/{chunk-MCHV2R25.js → chunk-WVNY4LSL.js} +3 -1
- package/lib/{chunk-MCHV2R25.js.map → chunk-WVNY4LSL.js.map} +2 -2
- package/lib/cli.js +7 -6
- package/lib/cli.js.map +1 -1
- package/lib/client.js +743 -315
- package/lib/client.js.map +2 -2
- package/lib/clients.js +6 -5
- package/lib/{host-v0.5.8.js → host-v0.6.0.js} +22 -123
- package/lib/host.js +22 -123
- package/lib/index.js +22 -123
- package/lib/index.js.map +4 -4
- package/lib/manager.js +11 -7
- package/lib/router.js +2 -2
- package/lib/shim.js +3 -3
- package/package.json +1 -1
- package/lib/chunk-ILRW3ELD.js.map +0 -7
- package/lib/chunk-J3XO7RTF.js.map +0 -7
- package/lib/chunk-OFFVP6YN.js.map +0 -7
- package/lib/chunk-U2MU2M5C.js.map +0 -7
- /package/lib/{chunk-P43AWJ4Q.js.map → chunk-LLDJVBTQ.js.map} +0 -0
- /package/lib/{chunk-FTM7RHQV.js.map → chunk-OK2T2UAZ.js.map} +0 -0
package/lib/clients.js
CHANGED
|
@@ -7,12 +7,13 @@ import {
|
|
|
7
7
|
jsonCredential,
|
|
8
8
|
refreshWorkBuddyCheckinCredential,
|
|
9
9
|
workbuddyToken
|
|
10
|
-
} from "./chunk-
|
|
11
|
-
import "./chunk-
|
|
12
|
-
import "./chunk-S5KMFAQM.js";
|
|
13
|
-
import "./chunk-J3XO7RTF.js";
|
|
14
|
-
import "./chunk-MCHV2R25.js";
|
|
10
|
+
} from "./chunk-NSKCFVHP.js";
|
|
11
|
+
import "./chunk-OK2T2UAZ.js";
|
|
15
12
|
import "./chunk-TEZ2FMEO.js";
|
|
13
|
+
import "./chunk-S5KMFAQM.js";
|
|
14
|
+
import "./chunk-4V52V5GO.js";
|
|
15
|
+
import "./chunk-ROZINFTV.js";
|
|
16
|
+
import "./chunk-WVNY4LSL.js";
|
|
16
17
|
export {
|
|
17
18
|
cachedModels,
|
|
18
19
|
claimTraeCheckin,
|
|
@@ -1,38 +1,42 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createShim
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-LLDJVBTQ.js";
|
|
4
4
|
import {
|
|
5
5
|
MANAGEMENT_PATH,
|
|
6
6
|
Manager,
|
|
7
|
+
PluginReload,
|
|
8
|
+
SUMMARY_PATH,
|
|
7
9
|
managementHandler,
|
|
8
10
|
version
|
|
9
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-OCMOMSB4.js";
|
|
10
12
|
import {
|
|
11
13
|
createAccountClient
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-
|
|
14
|
+
} from "./chunk-NSKCFVHP.js";
|
|
15
|
+
import "./chunk-JUOESKAK.js";
|
|
16
|
+
import "./chunk-OK2T2UAZ.js";
|
|
17
|
+
import {
|
|
18
|
+
normalizeCredits
|
|
19
|
+
} from "./chunk-TEZ2FMEO.js";
|
|
15
20
|
import "./chunk-S5KMFAQM.js";
|
|
21
|
+
import "./chunk-SNEZMYNU.js";
|
|
22
|
+
import "./chunk-4V52V5GO.js";
|
|
16
23
|
import "./chunk-DNQPZMPF.js";
|
|
17
24
|
import {
|
|
18
25
|
Router,
|
|
19
26
|
SessionMetrics,
|
|
20
27
|
abortable
|
|
21
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-ROZINFTV.js";
|
|
22
29
|
import {
|
|
23
30
|
PROVIDERS,
|
|
24
31
|
PROVIDER_NAMES,
|
|
25
32
|
ensureConfig
|
|
26
|
-
} from "./chunk-
|
|
27
|
-
import {
|
|
28
|
-
normalizeCredits
|
|
29
|
-
} from "./chunk-TEZ2FMEO.js";
|
|
33
|
+
} from "./chunk-WVNY4LSL.js";
|
|
30
34
|
|
|
31
35
|
// src/index.mjs
|
|
32
36
|
import z from "@deepseek-ai/schemastery";
|
|
33
37
|
import { resolveDshHome } from "@deepseek-ai/dsh-home-paths";
|
|
34
38
|
import { resolveRetryPolicy as resolveRetryPolicy2, resolveImageAttachmentAccess } from "@deepseek-ai/dsh-llm";
|
|
35
|
-
import { join
|
|
39
|
+
import { join, resolve } from "node:path";
|
|
36
40
|
|
|
37
41
|
// upstream/workbuddy/src/adapter.ts
|
|
38
42
|
import { createProvider } from "@earendil-works/pi-ai";
|
|
@@ -246,117 +250,10 @@ var WorkBuddyPiAiAdapter = class extends PiAiAdapter {
|
|
|
246
250
|
}
|
|
247
251
|
};
|
|
248
252
|
|
|
249
|
-
// src/plugin-reload.mjs
|
|
250
|
-
import { readFile } from "node:fs/promises";
|
|
251
|
-
import { watch } from "node:fs";
|
|
252
|
-
import { join } from "node:path";
|
|
253
|
-
function outsideActivation(hmr, operation) {
|
|
254
|
-
const scope = hmr?.executing;
|
|
255
|
-
return typeof scope?.exit === "function" ? scope.exit(operation) : operation();
|
|
256
|
-
}
|
|
257
|
-
var PluginReload = class {
|
|
258
|
-
constructor({ service, profile, canReload, hmr = () => void 0, busy = () => false, now = Date.now, runningVersion }) {
|
|
259
|
-
Object.assign(this, { service, profile, canReload, hmr, busy, now, runningVersion });
|
|
260
|
-
this.phase = "current";
|
|
261
|
-
this.installedVersion = runningVersion;
|
|
262
|
-
this.retryAt = 0;
|
|
263
|
-
}
|
|
264
|
-
state() {
|
|
265
|
-
return { runningVersion: this.runningVersion, installedVersion: this.installedVersion, phase: this.phase, canReload: !!this.canReload(), message: this.message };
|
|
266
|
-
}
|
|
267
|
-
start() {
|
|
268
|
-
const dir = this.profile()?.dir;
|
|
269
|
-
if (dir) try {
|
|
270
|
-
this.watcher = watch(dir, () => this.schedule());
|
|
271
|
-
this.watcher.unref();
|
|
272
|
-
} catch {
|
|
273
|
-
}
|
|
274
|
-
this.schedule();
|
|
275
|
-
}
|
|
276
|
-
schedule(delay = 500) {
|
|
277
|
-
if (this.closed) return;
|
|
278
|
-
clearTimeout(this.timer);
|
|
279
|
-
this.timer = setTimeout(() => {
|
|
280
|
-
void this.check().catch(() => {
|
|
281
|
-
});
|
|
282
|
-
}, delay);
|
|
283
|
-
this.timer.unref();
|
|
284
|
-
}
|
|
285
|
-
stop() {
|
|
286
|
-
this.closed = true;
|
|
287
|
-
clearTimeout(this.timer);
|
|
288
|
-
this.watcher?.close();
|
|
289
|
-
}
|
|
290
|
-
check() {
|
|
291
|
-
if (this.closed) return Promise.resolve();
|
|
292
|
-
if (this.flight) return this.flight;
|
|
293
|
-
this.flight = this.inspect().finally(() => {
|
|
294
|
-
this.flight = void 0;
|
|
295
|
-
});
|
|
296
|
-
return this.flight;
|
|
297
|
-
}
|
|
298
|
-
async inspect() {
|
|
299
|
-
const dir = this.profile()?.dir;
|
|
300
|
-
if (!dir) return;
|
|
301
|
-
let manifest, installed;
|
|
302
|
-
try {
|
|
303
|
-
manifest = JSON.parse(await readFile(join(dir, "package.json"), "utf8"));
|
|
304
|
-
installed = JSON.parse(await readFile(join(dir, "node_modules/dsh-multi-router/package.json"), "utf8"));
|
|
305
|
-
} catch {
|
|
306
|
-
return;
|
|
307
|
-
}
|
|
308
|
-
if (this.closed || !manifest.dsh?.profile?.bundles?.includes("dsh-multi-router")) return;
|
|
309
|
-
if (installed.name !== "dsh-multi-router" || !/^\d+\.\d+\.\d+(?:-[\w.-]+)?$/.test(installed.version)) return;
|
|
310
|
-
this.installedVersion = installed.version;
|
|
311
|
-
if (installed.version === this.runningVersion) {
|
|
312
|
-
this.phase = "current";
|
|
313
|
-
this.message = void 0;
|
|
314
|
-
return;
|
|
315
|
-
}
|
|
316
|
-
if (!this.canReload() || !this.service()?.setBundleEnabled) {
|
|
317
|
-
this.phase = "restart-required";
|
|
318
|
-
this.message = "\u5F53\u524D DSH \u672A\u63D0\u4F9B\u8FD0\u884C\u4E2D\u91CD\u8F7D\uFF0C\u8BF7\u5347\u7EA7 DSH \u6216\u91CD\u542F\u5E94\u7528\u3002";
|
|
319
|
-
return;
|
|
320
|
-
}
|
|
321
|
-
if (this.busy()) {
|
|
322
|
-
this.phase = "waiting";
|
|
323
|
-
this.message = "\u65B0\u7248\u672C\u5DF2\u5B89\u88C5\uFF0C\u7B49\u5F85\u5F53\u524D\u8BF7\u6C42\u548C\u8D26\u53F7\u64CD\u4F5C\u7ED3\u675F\u540E\u81EA\u52A8\u751F\u6548\u3002";
|
|
324
|
-
this.schedule(1e3);
|
|
325
|
-
return;
|
|
326
|
-
}
|
|
327
|
-
const root = join(dir, "node_modules/dsh-multi-router");
|
|
328
|
-
try {
|
|
329
|
-
const patch = await readFile(join(root, "cordis.patch.yml"), "utf8");
|
|
330
|
-
if (!patch.includes(`id: llm-multi-router-v2-${installed.version}
|
|
331
|
-
`) || !patch.includes(`name: ./lib/host-v${installed.version}.js`)) throw Error("legacy entry");
|
|
332
|
-
await readFile(join(root, `lib/host-v${installed.version}.js`));
|
|
333
|
-
} catch {
|
|
334
|
-
this.phase = "restart-required";
|
|
335
|
-
this.message = "\u5B89\u88C5\u7248\u672C\u7F3A\u5C11\u7248\u672C\u5316\u5165\u53E3\uFF0C\u91CD\u65B0\u5B89\u88C5\u6700\u65B0\u7248\u540E\u518D\u8BD5\u3002";
|
|
336
|
-
return;
|
|
337
|
-
}
|
|
338
|
-
if (this.now() < this.retryAt) return;
|
|
339
|
-
this.phase = "reloading";
|
|
340
|
-
this.message = "\u6B63\u5728\u91CD\u65B0\u52A0\u8F7D\u63D2\u4EF6\u4E0E\u914D\u7F6E\u9762\u677F\u2026";
|
|
341
|
-
this.retryAt = this.now() + 6e4;
|
|
342
|
-
try {
|
|
343
|
-
const result = await outsideActivation(this.hmr(), () => this.service().setBundleEnabled("dsh-multi-router", true));
|
|
344
|
-
if (this.closed) return;
|
|
345
|
-
this.phase = "restart-required";
|
|
346
|
-
this.message = result.application === "applied" ? "DSH \u5C1A\u672A\u5207\u6362\u5230\u65B0\u7248\u672C\uFF0C\u8BF7\u91CD\u65B0\u52A0\u8F7D\u63D2\u4EF6\u6216\u67E5\u770B\u7EC4\u4EF6\u9519\u8BEF\u3002" : "DSH \u672A\u80FD\u91CD\u8F7D\u63D2\u4EF6\uFF0C\u8BF7\u5347\u7EA7 DSH \u6216\u91CD\u542F\u5E94\u7528\u3002";
|
|
347
|
-
} catch {
|
|
348
|
-
if (!this.closed) {
|
|
349
|
-
this.phase = "failed";
|
|
350
|
-
this.message = "\u63D2\u4EF6\u91CD\u8F7D\u672A\u5B8C\u6210\uFF0C\u53EF\u7A0D\u540E\u91CD\u8BD5\uFF1B\u5DF2\u4FDD\u5B58\u7684\u914D\u7F6E\u4FDD\u6301\u4E0D\u53D8\u3002";
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
};
|
|
355
|
-
|
|
356
253
|
// src/index.mjs
|
|
357
254
|
var name = "dsh-multi-router";
|
|
358
255
|
var inject = ["llm"];
|
|
359
|
-
var defaultConfigFile = () =>
|
|
256
|
+
var defaultConfigFile = () => join(resolveDshHome(), "multi-router", "router.json");
|
|
360
257
|
var Config = z.object({ configFile: z.string().description("Absolute path to multi-account router.json") });
|
|
361
258
|
async function apply(ctx, options = {}) {
|
|
362
259
|
let disposed = false, manager, stopWatch, monitorTimer, startup;
|
|
@@ -371,7 +268,7 @@ async function apply(ctx, options = {}) {
|
|
|
371
268
|
manager?.checkins.abort.abort();
|
|
372
269
|
manager?.workbuddyLogin.abort.abort();
|
|
373
270
|
for (const release of releases) release();
|
|
374
|
-
return Promise.all([...shims.map((shim) => shim.close()), ...manager?.refreshes.values() ?? [], ...manager?.monitorFlights.values() ?? [], startup, manager?.localScan, manager?.checkins.flight, manager?.plugins.flight, manager?.plugins.saveQueue.catch(() => {
|
|
271
|
+
return Promise.all([manager?.api.close(), ...shims.map((shim) => shim.close()), ...manager?.refreshes.values() ?? [], ...manager?.monitorFlights.values() ?? [], startup, manager?.localScan, manager?.checkins.flight, manager?.plugins.flight, manager?.plugins.saveQueue.catch(() => {
|
|
375
272
|
}), manager?.telemetry.queue.catch(() => {
|
|
376
273
|
})]);
|
|
377
274
|
});
|
|
@@ -387,7 +284,7 @@ async function apply(ctx, options = {}) {
|
|
|
387
284
|
manager = new Manager(file, router, () => {
|
|
388
285
|
for (const wrapper of wrappers) wrapper.invalidate();
|
|
389
286
|
ctx.emit("llm/adapters-updated");
|
|
390
|
-
}, { service: () => ctx.get("pluginManager"), profile: () => ctx.get("profileContext") });
|
|
287
|
+
}, { service: () => ctx.get("pluginManager"), profile: () => ctx.get("profileContext"), hmr: () => ctx.get("hmr") });
|
|
391
288
|
await manager.load();
|
|
392
289
|
if (disposed) return;
|
|
393
290
|
manager.startup = { phase: "discovering" };
|
|
@@ -397,9 +294,10 @@ async function apply(ctx, options = {}) {
|
|
|
397
294
|
profile: () => ctx.get("profileContext"),
|
|
398
295
|
canReload: () => !!ctx.get("hmr"),
|
|
399
296
|
hmr: () => ctx.get("hmr"),
|
|
400
|
-
busy: () => !!(manager.localScan || manager.requests || manager.plugins.flight || manager.checkins.flight || manager.workbuddyLogin.flight || manager.workbuddyLogin.pending || manager.refreshes.size || manager.monitorFlights.size || shims.some((s) => s.active()))
|
|
297
|
+
busy: () => !!(manager.localScan || manager.requests || manager.api.controllers.size || manager.plugins.flight || manager.checkins.flight || manager.workbuddyLogin.flight || manager.workbuddyLogin.pending || manager.refreshes.size || manager.monitorFlights.size || shims.some((s) => s.active()))
|
|
401
298
|
});
|
|
402
299
|
ctx.inject?.(["webServer"], (webCtx) => {
|
|
300
|
+
webCtx.effect(() => webCtx.webServer.register({ kind: "exact", path: SUMMARY_PATH, handler: managementHandler(manager, { summaryOnly: true }) }));
|
|
403
301
|
webCtx.effect(() => webCtx.webServer.register({ kind: "exact", path: MANAGEMENT_PATH, handler: managementHandler(manager) }));
|
|
404
302
|
});
|
|
405
303
|
const metrics = new SessionMetrics(manager.telemetry);
|
|
@@ -469,6 +367,7 @@ async function apply(ctx, options = {}) {
|
|
|
469
367
|
releases.push(ctx.llm.registerAdapter([provider], wrapper.adapter));
|
|
470
368
|
}
|
|
471
369
|
stopWatch = manager.watch(() => ctx.logger.warn("multi-router: invalid config change; keeping last valid configuration"));
|
|
370
|
+
await manager.api.reconcile();
|
|
472
371
|
startup = (async () => {
|
|
473
372
|
await manager.syncLocalAccounts().catch(() => ctx.logger.warn("multi-router: local login discovery failed; manual import remains available"));
|
|
474
373
|
if (disposed) return;
|
|
@@ -499,7 +398,7 @@ async function apply(ctx, options = {}) {
|
|
|
499
398
|
stopWatch?.();
|
|
500
399
|
manager?.runtime?.stop();
|
|
501
400
|
for (const release of releases) release();
|
|
502
|
-
await Promise.all(shims.map((shim) => shim.close()));
|
|
401
|
+
await Promise.all([manager?.api.close(), ...shims.map((shim) => shim.close())]);
|
|
503
402
|
ctx.logger.error("multi-router: initialization failed", error.code ?? error.message);
|
|
504
403
|
throw error;
|
|
505
404
|
}
|
package/lib/host.js
CHANGED
|
@@ -1,38 +1,42 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createShim
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-LLDJVBTQ.js";
|
|
4
4
|
import {
|
|
5
5
|
MANAGEMENT_PATH,
|
|
6
6
|
Manager,
|
|
7
|
+
PluginReload,
|
|
8
|
+
SUMMARY_PATH,
|
|
7
9
|
managementHandler,
|
|
8
10
|
version
|
|
9
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-OCMOMSB4.js";
|
|
10
12
|
import {
|
|
11
13
|
createAccountClient
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-
|
|
14
|
+
} from "./chunk-NSKCFVHP.js";
|
|
15
|
+
import "./chunk-JUOESKAK.js";
|
|
16
|
+
import "./chunk-OK2T2UAZ.js";
|
|
17
|
+
import {
|
|
18
|
+
normalizeCredits
|
|
19
|
+
} from "./chunk-TEZ2FMEO.js";
|
|
15
20
|
import "./chunk-S5KMFAQM.js";
|
|
21
|
+
import "./chunk-SNEZMYNU.js";
|
|
22
|
+
import "./chunk-4V52V5GO.js";
|
|
16
23
|
import "./chunk-DNQPZMPF.js";
|
|
17
24
|
import {
|
|
18
25
|
Router,
|
|
19
26
|
SessionMetrics,
|
|
20
27
|
abortable
|
|
21
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-ROZINFTV.js";
|
|
22
29
|
import {
|
|
23
30
|
PROVIDERS,
|
|
24
31
|
PROVIDER_NAMES,
|
|
25
32
|
ensureConfig
|
|
26
|
-
} from "./chunk-
|
|
27
|
-
import {
|
|
28
|
-
normalizeCredits
|
|
29
|
-
} from "./chunk-TEZ2FMEO.js";
|
|
33
|
+
} from "./chunk-WVNY4LSL.js";
|
|
30
34
|
|
|
31
35
|
// src/index.mjs
|
|
32
36
|
import z from "@deepseek-ai/schemastery";
|
|
33
37
|
import { resolveDshHome } from "@deepseek-ai/dsh-home-paths";
|
|
34
38
|
import { resolveRetryPolicy as resolveRetryPolicy2, resolveImageAttachmentAccess } from "@deepseek-ai/dsh-llm";
|
|
35
|
-
import { join
|
|
39
|
+
import { join, resolve } from "node:path";
|
|
36
40
|
|
|
37
41
|
// upstream/workbuddy/src/adapter.ts
|
|
38
42
|
import { createProvider } from "@earendil-works/pi-ai";
|
|
@@ -246,117 +250,10 @@ var WorkBuddyPiAiAdapter = class extends PiAiAdapter {
|
|
|
246
250
|
}
|
|
247
251
|
};
|
|
248
252
|
|
|
249
|
-
// src/plugin-reload.mjs
|
|
250
|
-
import { readFile } from "node:fs/promises";
|
|
251
|
-
import { watch } from "node:fs";
|
|
252
|
-
import { join } from "node:path";
|
|
253
|
-
function outsideActivation(hmr, operation) {
|
|
254
|
-
const scope = hmr?.executing;
|
|
255
|
-
return typeof scope?.exit === "function" ? scope.exit(operation) : operation();
|
|
256
|
-
}
|
|
257
|
-
var PluginReload = class {
|
|
258
|
-
constructor({ service, profile, canReload, hmr = () => void 0, busy = () => false, now = Date.now, runningVersion }) {
|
|
259
|
-
Object.assign(this, { service, profile, canReload, hmr, busy, now, runningVersion });
|
|
260
|
-
this.phase = "current";
|
|
261
|
-
this.installedVersion = runningVersion;
|
|
262
|
-
this.retryAt = 0;
|
|
263
|
-
}
|
|
264
|
-
state() {
|
|
265
|
-
return { runningVersion: this.runningVersion, installedVersion: this.installedVersion, phase: this.phase, canReload: !!this.canReload(), message: this.message };
|
|
266
|
-
}
|
|
267
|
-
start() {
|
|
268
|
-
const dir = this.profile()?.dir;
|
|
269
|
-
if (dir) try {
|
|
270
|
-
this.watcher = watch(dir, () => this.schedule());
|
|
271
|
-
this.watcher.unref();
|
|
272
|
-
} catch {
|
|
273
|
-
}
|
|
274
|
-
this.schedule();
|
|
275
|
-
}
|
|
276
|
-
schedule(delay = 500) {
|
|
277
|
-
if (this.closed) return;
|
|
278
|
-
clearTimeout(this.timer);
|
|
279
|
-
this.timer = setTimeout(() => {
|
|
280
|
-
void this.check().catch(() => {
|
|
281
|
-
});
|
|
282
|
-
}, delay);
|
|
283
|
-
this.timer.unref();
|
|
284
|
-
}
|
|
285
|
-
stop() {
|
|
286
|
-
this.closed = true;
|
|
287
|
-
clearTimeout(this.timer);
|
|
288
|
-
this.watcher?.close();
|
|
289
|
-
}
|
|
290
|
-
check() {
|
|
291
|
-
if (this.closed) return Promise.resolve();
|
|
292
|
-
if (this.flight) return this.flight;
|
|
293
|
-
this.flight = this.inspect().finally(() => {
|
|
294
|
-
this.flight = void 0;
|
|
295
|
-
});
|
|
296
|
-
return this.flight;
|
|
297
|
-
}
|
|
298
|
-
async inspect() {
|
|
299
|
-
const dir = this.profile()?.dir;
|
|
300
|
-
if (!dir) return;
|
|
301
|
-
let manifest, installed;
|
|
302
|
-
try {
|
|
303
|
-
manifest = JSON.parse(await readFile(join(dir, "package.json"), "utf8"));
|
|
304
|
-
installed = JSON.parse(await readFile(join(dir, "node_modules/dsh-multi-router/package.json"), "utf8"));
|
|
305
|
-
} catch {
|
|
306
|
-
return;
|
|
307
|
-
}
|
|
308
|
-
if (this.closed || !manifest.dsh?.profile?.bundles?.includes("dsh-multi-router")) return;
|
|
309
|
-
if (installed.name !== "dsh-multi-router" || !/^\d+\.\d+\.\d+(?:-[\w.-]+)?$/.test(installed.version)) return;
|
|
310
|
-
this.installedVersion = installed.version;
|
|
311
|
-
if (installed.version === this.runningVersion) {
|
|
312
|
-
this.phase = "current";
|
|
313
|
-
this.message = void 0;
|
|
314
|
-
return;
|
|
315
|
-
}
|
|
316
|
-
if (!this.canReload() || !this.service()?.setBundleEnabled) {
|
|
317
|
-
this.phase = "restart-required";
|
|
318
|
-
this.message = "\u5F53\u524D DSH \u672A\u63D0\u4F9B\u8FD0\u884C\u4E2D\u91CD\u8F7D\uFF0C\u8BF7\u5347\u7EA7 DSH \u6216\u91CD\u542F\u5E94\u7528\u3002";
|
|
319
|
-
return;
|
|
320
|
-
}
|
|
321
|
-
if (this.busy()) {
|
|
322
|
-
this.phase = "waiting";
|
|
323
|
-
this.message = "\u65B0\u7248\u672C\u5DF2\u5B89\u88C5\uFF0C\u7B49\u5F85\u5F53\u524D\u8BF7\u6C42\u548C\u8D26\u53F7\u64CD\u4F5C\u7ED3\u675F\u540E\u81EA\u52A8\u751F\u6548\u3002";
|
|
324
|
-
this.schedule(1e3);
|
|
325
|
-
return;
|
|
326
|
-
}
|
|
327
|
-
const root = join(dir, "node_modules/dsh-multi-router");
|
|
328
|
-
try {
|
|
329
|
-
const patch = await readFile(join(root, "cordis.patch.yml"), "utf8");
|
|
330
|
-
if (!patch.includes(`id: llm-multi-router-v2-${installed.version}
|
|
331
|
-
`) || !patch.includes(`name: ./lib/host-v${installed.version}.js`)) throw Error("legacy entry");
|
|
332
|
-
await readFile(join(root, `lib/host-v${installed.version}.js`));
|
|
333
|
-
} catch {
|
|
334
|
-
this.phase = "restart-required";
|
|
335
|
-
this.message = "\u5B89\u88C5\u7248\u672C\u7F3A\u5C11\u7248\u672C\u5316\u5165\u53E3\uFF0C\u91CD\u65B0\u5B89\u88C5\u6700\u65B0\u7248\u540E\u518D\u8BD5\u3002";
|
|
336
|
-
return;
|
|
337
|
-
}
|
|
338
|
-
if (this.now() < this.retryAt) return;
|
|
339
|
-
this.phase = "reloading";
|
|
340
|
-
this.message = "\u6B63\u5728\u91CD\u65B0\u52A0\u8F7D\u63D2\u4EF6\u4E0E\u914D\u7F6E\u9762\u677F\u2026";
|
|
341
|
-
this.retryAt = this.now() + 6e4;
|
|
342
|
-
try {
|
|
343
|
-
const result = await outsideActivation(this.hmr(), () => this.service().setBundleEnabled("dsh-multi-router", true));
|
|
344
|
-
if (this.closed) return;
|
|
345
|
-
this.phase = "restart-required";
|
|
346
|
-
this.message = result.application === "applied" ? "DSH \u5C1A\u672A\u5207\u6362\u5230\u65B0\u7248\u672C\uFF0C\u8BF7\u91CD\u65B0\u52A0\u8F7D\u63D2\u4EF6\u6216\u67E5\u770B\u7EC4\u4EF6\u9519\u8BEF\u3002" : "DSH \u672A\u80FD\u91CD\u8F7D\u63D2\u4EF6\uFF0C\u8BF7\u5347\u7EA7 DSH \u6216\u91CD\u542F\u5E94\u7528\u3002";
|
|
347
|
-
} catch {
|
|
348
|
-
if (!this.closed) {
|
|
349
|
-
this.phase = "failed";
|
|
350
|
-
this.message = "\u63D2\u4EF6\u91CD\u8F7D\u672A\u5B8C\u6210\uFF0C\u53EF\u7A0D\u540E\u91CD\u8BD5\uFF1B\u5DF2\u4FDD\u5B58\u7684\u914D\u7F6E\u4FDD\u6301\u4E0D\u53D8\u3002";
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
};
|
|
355
|
-
|
|
356
253
|
// src/index.mjs
|
|
357
254
|
var name = "dsh-multi-router";
|
|
358
255
|
var inject = ["llm"];
|
|
359
|
-
var defaultConfigFile = () =>
|
|
256
|
+
var defaultConfigFile = () => join(resolveDshHome(), "multi-router", "router.json");
|
|
360
257
|
var Config = z.object({ configFile: z.string().description("Absolute path to multi-account router.json") });
|
|
361
258
|
async function apply(ctx, options = {}) {
|
|
362
259
|
let disposed = false, manager, stopWatch, monitorTimer, startup;
|
|
@@ -371,7 +268,7 @@ async function apply(ctx, options = {}) {
|
|
|
371
268
|
manager?.checkins.abort.abort();
|
|
372
269
|
manager?.workbuddyLogin.abort.abort();
|
|
373
270
|
for (const release of releases) release();
|
|
374
|
-
return Promise.all([...shims.map((shim) => shim.close()), ...manager?.refreshes.values() ?? [], ...manager?.monitorFlights.values() ?? [], startup, manager?.localScan, manager?.checkins.flight, manager?.plugins.flight, manager?.plugins.saveQueue.catch(() => {
|
|
271
|
+
return Promise.all([manager?.api.close(), ...shims.map((shim) => shim.close()), ...manager?.refreshes.values() ?? [], ...manager?.monitorFlights.values() ?? [], startup, manager?.localScan, manager?.checkins.flight, manager?.plugins.flight, manager?.plugins.saveQueue.catch(() => {
|
|
375
272
|
}), manager?.telemetry.queue.catch(() => {
|
|
376
273
|
})]);
|
|
377
274
|
});
|
|
@@ -387,7 +284,7 @@ async function apply(ctx, options = {}) {
|
|
|
387
284
|
manager = new Manager(file, router, () => {
|
|
388
285
|
for (const wrapper of wrappers) wrapper.invalidate();
|
|
389
286
|
ctx.emit("llm/adapters-updated");
|
|
390
|
-
}, { service: () => ctx.get("pluginManager"), profile: () => ctx.get("profileContext") });
|
|
287
|
+
}, { service: () => ctx.get("pluginManager"), profile: () => ctx.get("profileContext"), hmr: () => ctx.get("hmr") });
|
|
391
288
|
await manager.load();
|
|
392
289
|
if (disposed) return;
|
|
393
290
|
manager.startup = { phase: "discovering" };
|
|
@@ -397,9 +294,10 @@ async function apply(ctx, options = {}) {
|
|
|
397
294
|
profile: () => ctx.get("profileContext"),
|
|
398
295
|
canReload: () => !!ctx.get("hmr"),
|
|
399
296
|
hmr: () => ctx.get("hmr"),
|
|
400
|
-
busy: () => !!(manager.localScan || manager.requests || manager.plugins.flight || manager.checkins.flight || manager.workbuddyLogin.flight || manager.workbuddyLogin.pending || manager.refreshes.size || manager.monitorFlights.size || shims.some((s) => s.active()))
|
|
297
|
+
busy: () => !!(manager.localScan || manager.requests || manager.api.controllers.size || manager.plugins.flight || manager.checkins.flight || manager.workbuddyLogin.flight || manager.workbuddyLogin.pending || manager.refreshes.size || manager.monitorFlights.size || shims.some((s) => s.active()))
|
|
401
298
|
});
|
|
402
299
|
ctx.inject?.(["webServer"], (webCtx) => {
|
|
300
|
+
webCtx.effect(() => webCtx.webServer.register({ kind: "exact", path: SUMMARY_PATH, handler: managementHandler(manager, { summaryOnly: true }) }));
|
|
403
301
|
webCtx.effect(() => webCtx.webServer.register({ kind: "exact", path: MANAGEMENT_PATH, handler: managementHandler(manager) }));
|
|
404
302
|
});
|
|
405
303
|
const metrics = new SessionMetrics(manager.telemetry);
|
|
@@ -469,6 +367,7 @@ async function apply(ctx, options = {}) {
|
|
|
469
367
|
releases.push(ctx.llm.registerAdapter([provider], wrapper.adapter));
|
|
470
368
|
}
|
|
471
369
|
stopWatch = manager.watch(() => ctx.logger.warn("multi-router: invalid config change; keeping last valid configuration"));
|
|
370
|
+
await manager.api.reconcile();
|
|
472
371
|
startup = (async () => {
|
|
473
372
|
await manager.syncLocalAccounts().catch(() => ctx.logger.warn("multi-router: local login discovery failed; manual import remains available"));
|
|
474
373
|
if (disposed) return;
|
|
@@ -499,7 +398,7 @@ async function apply(ctx, options = {}) {
|
|
|
499
398
|
stopWatch?.();
|
|
500
399
|
manager?.runtime?.stop();
|
|
501
400
|
for (const release of releases) release();
|
|
502
|
-
await Promise.all(shims.map((shim) => shim.close()));
|
|
401
|
+
await Promise.all([manager?.api.close(), ...shims.map((shim) => shim.close())]);
|
|
503
402
|
ctx.logger.error("multi-router: initialization failed", error.code ?? error.message);
|
|
504
403
|
throw error;
|
|
505
404
|
}
|
package/lib/index.js
CHANGED
|
@@ -1,38 +1,42 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createShim
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-LLDJVBTQ.js";
|
|
4
4
|
import {
|
|
5
5
|
MANAGEMENT_PATH,
|
|
6
6
|
Manager,
|
|
7
|
+
PluginReload,
|
|
8
|
+
SUMMARY_PATH,
|
|
7
9
|
managementHandler,
|
|
8
10
|
version
|
|
9
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-OCMOMSB4.js";
|
|
10
12
|
import {
|
|
11
13
|
createAccountClient
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-
|
|
14
|
+
} from "./chunk-NSKCFVHP.js";
|
|
15
|
+
import "./chunk-JUOESKAK.js";
|
|
16
|
+
import "./chunk-OK2T2UAZ.js";
|
|
17
|
+
import {
|
|
18
|
+
normalizeCredits
|
|
19
|
+
} from "./chunk-TEZ2FMEO.js";
|
|
15
20
|
import "./chunk-S5KMFAQM.js";
|
|
21
|
+
import "./chunk-SNEZMYNU.js";
|
|
22
|
+
import "./chunk-4V52V5GO.js";
|
|
16
23
|
import "./chunk-DNQPZMPF.js";
|
|
17
24
|
import {
|
|
18
25
|
Router,
|
|
19
26
|
SessionMetrics,
|
|
20
27
|
abortable
|
|
21
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-ROZINFTV.js";
|
|
22
29
|
import {
|
|
23
30
|
PROVIDERS,
|
|
24
31
|
PROVIDER_NAMES,
|
|
25
32
|
ensureConfig
|
|
26
|
-
} from "./chunk-
|
|
27
|
-
import {
|
|
28
|
-
normalizeCredits
|
|
29
|
-
} from "./chunk-TEZ2FMEO.js";
|
|
33
|
+
} from "./chunk-WVNY4LSL.js";
|
|
30
34
|
|
|
31
35
|
// src/index.mjs
|
|
32
36
|
import z from "@deepseek-ai/schemastery";
|
|
33
37
|
import { resolveDshHome } from "@deepseek-ai/dsh-home-paths";
|
|
34
38
|
import { resolveRetryPolicy as resolveRetryPolicy2, resolveImageAttachmentAccess } from "@deepseek-ai/dsh-llm";
|
|
35
|
-
import { join
|
|
39
|
+
import { join, resolve } from "node:path";
|
|
36
40
|
|
|
37
41
|
// upstream/workbuddy/src/adapter.ts
|
|
38
42
|
import { createProvider } from "@earendil-works/pi-ai";
|
|
@@ -246,117 +250,10 @@ var WorkBuddyPiAiAdapter = class extends PiAiAdapter {
|
|
|
246
250
|
}
|
|
247
251
|
};
|
|
248
252
|
|
|
249
|
-
// src/plugin-reload.mjs
|
|
250
|
-
import { readFile } from "node:fs/promises";
|
|
251
|
-
import { watch } from "node:fs";
|
|
252
|
-
import { join } from "node:path";
|
|
253
|
-
function outsideActivation(hmr, operation) {
|
|
254
|
-
const scope = hmr?.executing;
|
|
255
|
-
return typeof scope?.exit === "function" ? scope.exit(operation) : operation();
|
|
256
|
-
}
|
|
257
|
-
var PluginReload = class {
|
|
258
|
-
constructor({ service, profile, canReload, hmr = () => void 0, busy = () => false, now = Date.now, runningVersion }) {
|
|
259
|
-
Object.assign(this, { service, profile, canReload, hmr, busy, now, runningVersion });
|
|
260
|
-
this.phase = "current";
|
|
261
|
-
this.installedVersion = runningVersion;
|
|
262
|
-
this.retryAt = 0;
|
|
263
|
-
}
|
|
264
|
-
state() {
|
|
265
|
-
return { runningVersion: this.runningVersion, installedVersion: this.installedVersion, phase: this.phase, canReload: !!this.canReload(), message: this.message };
|
|
266
|
-
}
|
|
267
|
-
start() {
|
|
268
|
-
const dir = this.profile()?.dir;
|
|
269
|
-
if (dir) try {
|
|
270
|
-
this.watcher = watch(dir, () => this.schedule());
|
|
271
|
-
this.watcher.unref();
|
|
272
|
-
} catch {
|
|
273
|
-
}
|
|
274
|
-
this.schedule();
|
|
275
|
-
}
|
|
276
|
-
schedule(delay = 500) {
|
|
277
|
-
if (this.closed) return;
|
|
278
|
-
clearTimeout(this.timer);
|
|
279
|
-
this.timer = setTimeout(() => {
|
|
280
|
-
void this.check().catch(() => {
|
|
281
|
-
});
|
|
282
|
-
}, delay);
|
|
283
|
-
this.timer.unref();
|
|
284
|
-
}
|
|
285
|
-
stop() {
|
|
286
|
-
this.closed = true;
|
|
287
|
-
clearTimeout(this.timer);
|
|
288
|
-
this.watcher?.close();
|
|
289
|
-
}
|
|
290
|
-
check() {
|
|
291
|
-
if (this.closed) return Promise.resolve();
|
|
292
|
-
if (this.flight) return this.flight;
|
|
293
|
-
this.flight = this.inspect().finally(() => {
|
|
294
|
-
this.flight = void 0;
|
|
295
|
-
});
|
|
296
|
-
return this.flight;
|
|
297
|
-
}
|
|
298
|
-
async inspect() {
|
|
299
|
-
const dir = this.profile()?.dir;
|
|
300
|
-
if (!dir) return;
|
|
301
|
-
let manifest, installed;
|
|
302
|
-
try {
|
|
303
|
-
manifest = JSON.parse(await readFile(join(dir, "package.json"), "utf8"));
|
|
304
|
-
installed = JSON.parse(await readFile(join(dir, "node_modules/dsh-multi-router/package.json"), "utf8"));
|
|
305
|
-
} catch {
|
|
306
|
-
return;
|
|
307
|
-
}
|
|
308
|
-
if (this.closed || !manifest.dsh?.profile?.bundles?.includes("dsh-multi-router")) return;
|
|
309
|
-
if (installed.name !== "dsh-multi-router" || !/^\d+\.\d+\.\d+(?:-[\w.-]+)?$/.test(installed.version)) return;
|
|
310
|
-
this.installedVersion = installed.version;
|
|
311
|
-
if (installed.version === this.runningVersion) {
|
|
312
|
-
this.phase = "current";
|
|
313
|
-
this.message = void 0;
|
|
314
|
-
return;
|
|
315
|
-
}
|
|
316
|
-
if (!this.canReload() || !this.service()?.setBundleEnabled) {
|
|
317
|
-
this.phase = "restart-required";
|
|
318
|
-
this.message = "\u5F53\u524D DSH \u672A\u63D0\u4F9B\u8FD0\u884C\u4E2D\u91CD\u8F7D\uFF0C\u8BF7\u5347\u7EA7 DSH \u6216\u91CD\u542F\u5E94\u7528\u3002";
|
|
319
|
-
return;
|
|
320
|
-
}
|
|
321
|
-
if (this.busy()) {
|
|
322
|
-
this.phase = "waiting";
|
|
323
|
-
this.message = "\u65B0\u7248\u672C\u5DF2\u5B89\u88C5\uFF0C\u7B49\u5F85\u5F53\u524D\u8BF7\u6C42\u548C\u8D26\u53F7\u64CD\u4F5C\u7ED3\u675F\u540E\u81EA\u52A8\u751F\u6548\u3002";
|
|
324
|
-
this.schedule(1e3);
|
|
325
|
-
return;
|
|
326
|
-
}
|
|
327
|
-
const root = join(dir, "node_modules/dsh-multi-router");
|
|
328
|
-
try {
|
|
329
|
-
const patch = await readFile(join(root, "cordis.patch.yml"), "utf8");
|
|
330
|
-
if (!patch.includes(`id: llm-multi-router-v2-${installed.version}
|
|
331
|
-
`) || !patch.includes(`name: ./lib/host-v${installed.version}.js`)) throw Error("legacy entry");
|
|
332
|
-
await readFile(join(root, `lib/host-v${installed.version}.js`));
|
|
333
|
-
} catch {
|
|
334
|
-
this.phase = "restart-required";
|
|
335
|
-
this.message = "\u5B89\u88C5\u7248\u672C\u7F3A\u5C11\u7248\u672C\u5316\u5165\u53E3\uFF0C\u91CD\u65B0\u5B89\u88C5\u6700\u65B0\u7248\u540E\u518D\u8BD5\u3002";
|
|
336
|
-
return;
|
|
337
|
-
}
|
|
338
|
-
if (this.now() < this.retryAt) return;
|
|
339
|
-
this.phase = "reloading";
|
|
340
|
-
this.message = "\u6B63\u5728\u91CD\u65B0\u52A0\u8F7D\u63D2\u4EF6\u4E0E\u914D\u7F6E\u9762\u677F\u2026";
|
|
341
|
-
this.retryAt = this.now() + 6e4;
|
|
342
|
-
try {
|
|
343
|
-
const result = await outsideActivation(this.hmr(), () => this.service().setBundleEnabled("dsh-multi-router", true));
|
|
344
|
-
if (this.closed) return;
|
|
345
|
-
this.phase = "restart-required";
|
|
346
|
-
this.message = result.application === "applied" ? "DSH \u5C1A\u672A\u5207\u6362\u5230\u65B0\u7248\u672C\uFF0C\u8BF7\u91CD\u65B0\u52A0\u8F7D\u63D2\u4EF6\u6216\u67E5\u770B\u7EC4\u4EF6\u9519\u8BEF\u3002" : "DSH \u672A\u80FD\u91CD\u8F7D\u63D2\u4EF6\uFF0C\u8BF7\u5347\u7EA7 DSH \u6216\u91CD\u542F\u5E94\u7528\u3002";
|
|
347
|
-
} catch {
|
|
348
|
-
if (!this.closed) {
|
|
349
|
-
this.phase = "failed";
|
|
350
|
-
this.message = "\u63D2\u4EF6\u91CD\u8F7D\u672A\u5B8C\u6210\uFF0C\u53EF\u7A0D\u540E\u91CD\u8BD5\uFF1B\u5DF2\u4FDD\u5B58\u7684\u914D\u7F6E\u4FDD\u6301\u4E0D\u53D8\u3002";
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
};
|
|
355
|
-
|
|
356
253
|
// src/index.mjs
|
|
357
254
|
var name = "dsh-multi-router";
|
|
358
255
|
var inject = ["llm"];
|
|
359
|
-
var defaultConfigFile = () =>
|
|
256
|
+
var defaultConfigFile = () => join(resolveDshHome(), "multi-router", "router.json");
|
|
360
257
|
var Config = z.object({ configFile: z.string().description("Absolute path to multi-account router.json") });
|
|
361
258
|
async function apply(ctx, options = {}) {
|
|
362
259
|
let disposed = false, manager, stopWatch, monitorTimer, startup;
|
|
@@ -371,7 +268,7 @@ async function apply(ctx, options = {}) {
|
|
|
371
268
|
manager?.checkins.abort.abort();
|
|
372
269
|
manager?.workbuddyLogin.abort.abort();
|
|
373
270
|
for (const release of releases) release();
|
|
374
|
-
return Promise.all([...shims.map((shim) => shim.close()), ...manager?.refreshes.values() ?? [], ...manager?.monitorFlights.values() ?? [], startup, manager?.localScan, manager?.checkins.flight, manager?.plugins.flight, manager?.plugins.saveQueue.catch(() => {
|
|
271
|
+
return Promise.all([manager?.api.close(), ...shims.map((shim) => shim.close()), ...manager?.refreshes.values() ?? [], ...manager?.monitorFlights.values() ?? [], startup, manager?.localScan, manager?.checkins.flight, manager?.plugins.flight, manager?.plugins.saveQueue.catch(() => {
|
|
375
272
|
}), manager?.telemetry.queue.catch(() => {
|
|
376
273
|
})]);
|
|
377
274
|
});
|
|
@@ -387,7 +284,7 @@ async function apply(ctx, options = {}) {
|
|
|
387
284
|
manager = new Manager(file, router, () => {
|
|
388
285
|
for (const wrapper of wrappers) wrapper.invalidate();
|
|
389
286
|
ctx.emit("llm/adapters-updated");
|
|
390
|
-
}, { service: () => ctx.get("pluginManager"), profile: () => ctx.get("profileContext") });
|
|
287
|
+
}, { service: () => ctx.get("pluginManager"), profile: () => ctx.get("profileContext"), hmr: () => ctx.get("hmr") });
|
|
391
288
|
await manager.load();
|
|
392
289
|
if (disposed) return;
|
|
393
290
|
manager.startup = { phase: "discovering" };
|
|
@@ -397,9 +294,10 @@ async function apply(ctx, options = {}) {
|
|
|
397
294
|
profile: () => ctx.get("profileContext"),
|
|
398
295
|
canReload: () => !!ctx.get("hmr"),
|
|
399
296
|
hmr: () => ctx.get("hmr"),
|
|
400
|
-
busy: () => !!(manager.localScan || manager.requests || manager.plugins.flight || manager.checkins.flight || manager.workbuddyLogin.flight || manager.workbuddyLogin.pending || manager.refreshes.size || manager.monitorFlights.size || shims.some((s) => s.active()))
|
|
297
|
+
busy: () => !!(manager.localScan || manager.requests || manager.api.controllers.size || manager.plugins.flight || manager.checkins.flight || manager.workbuddyLogin.flight || manager.workbuddyLogin.pending || manager.refreshes.size || manager.monitorFlights.size || shims.some((s) => s.active()))
|
|
401
298
|
});
|
|
402
299
|
ctx.inject?.(["webServer"], (webCtx) => {
|
|
300
|
+
webCtx.effect(() => webCtx.webServer.register({ kind: "exact", path: SUMMARY_PATH, handler: managementHandler(manager, { summaryOnly: true }) }));
|
|
403
301
|
webCtx.effect(() => webCtx.webServer.register({ kind: "exact", path: MANAGEMENT_PATH, handler: managementHandler(manager) }));
|
|
404
302
|
});
|
|
405
303
|
const metrics = new SessionMetrics(manager.telemetry);
|
|
@@ -469,6 +367,7 @@ async function apply(ctx, options = {}) {
|
|
|
469
367
|
releases.push(ctx.llm.registerAdapter([provider], wrapper.adapter));
|
|
470
368
|
}
|
|
471
369
|
stopWatch = manager.watch(() => ctx.logger.warn("multi-router: invalid config change; keeping last valid configuration"));
|
|
370
|
+
await manager.api.reconcile();
|
|
472
371
|
startup = (async () => {
|
|
473
372
|
await manager.syncLocalAccounts().catch(() => ctx.logger.warn("multi-router: local login discovery failed; manual import remains available"));
|
|
474
373
|
if (disposed) return;
|
|
@@ -499,7 +398,7 @@ async function apply(ctx, options = {}) {
|
|
|
499
398
|
stopWatch?.();
|
|
500
399
|
manager?.runtime?.stop();
|
|
501
400
|
for (const release of releases) release();
|
|
502
|
-
await Promise.all(shims.map((shim) => shim.close()));
|
|
401
|
+
await Promise.all([manager?.api.close(), ...shims.map((shim) => shim.close())]);
|
|
503
402
|
ctx.logger.error("multi-router: initialization failed", error.code ?? error.message);
|
|
504
403
|
throw error;
|
|
505
404
|
}
|