dsh-multi-router 0.6.0 → 0.6.1
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 +10 -0
- package/README.md +21 -6
- package/THIRD_PARTY_NOTICES.md +4 -0
- package/cordis.patch.yml +2 -2
- package/lib/accounts.js +2 -2
- package/lib/api-service.js +3 -3
- package/lib/{chunk-NSKCFVHP.js → chunk-2LH6TD2U.js} +15 -7
- package/lib/chunk-2LH6TD2U.js.map +7 -0
- package/lib/{chunk-SNEZMYNU.js → chunk-625KMEYS.js} +3 -3
- package/lib/{chunk-LLDJVBTQ.js → chunk-BSAI3SW5.js} +3 -3
- package/lib/{chunk-ROZINFTV.js → chunk-DZ4ZUAYH.js} +49 -6
- package/lib/chunk-DZ4ZUAYH.js.map +7 -0
- package/lib/{chunk-WVNY4LSL.js → chunk-NGVWVIBM.js} +20 -6
- package/lib/chunk-NGVWVIBM.js.map +7 -0
- package/lib/{chunk-JUOESKAK.js → chunk-VZPXRK7Q.js} +2 -2
- package/lib/{chunk-OCMOMSB4.js → chunk-ZQZSXCVR.js} +125 -41
- package/lib/chunk-ZQZSXCVR.js.map +7 -0
- package/lib/cli.js +4 -4
- package/lib/client.js +125 -40
- package/lib/client.js.map +2 -2
- package/lib/clients.js +6 -3
- package/lib/{host-v0.6.0.js → host-v0.6.1.js} +8 -7
- package/lib/host.js +8 -7
- package/lib/index.js +8 -7
- package/lib/index.js.map +2 -2
- package/lib/manager.js +6 -6
- package/lib/router.js +2 -2
- package/lib/shim.js +3 -3
- package/package.json +1 -1
- package/lib/chunk-NSKCFVHP.js.map +0 -7
- package/lib/chunk-OCMOMSB4.js.map +0 -7
- package/lib/chunk-ROZINFTV.js.map +0 -7
- package/lib/chunk-WVNY4LSL.js.map +0 -7
- /package/lib/{chunk-SNEZMYNU.js.map → chunk-625KMEYS.js.map} +0 -0
- /package/lib/{chunk-LLDJVBTQ.js.map → chunk-BSAI3SW5.js.map} +0 -0
- /package/lib/{chunk-JUOESKAK.js.map → chunk-VZPXRK7Q.js.map} +0 -0
|
@@ -6,44 +6,45 @@ import {
|
|
|
6
6
|
refreshWorkBuddyCheckinCredential,
|
|
7
7
|
supportsCheckin,
|
|
8
8
|
workbuddyToken
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-2LH6TD2U.js";
|
|
10
10
|
import {
|
|
11
11
|
discoverLocalAccounts,
|
|
12
12
|
importAccount,
|
|
13
13
|
localAccountKey,
|
|
14
14
|
normalizeLocalAccountKey,
|
|
15
15
|
readPortableCredential
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-VZPXRK7Q.js";
|
|
17
17
|
import {
|
|
18
18
|
modelWithCurrentPromotion
|
|
19
19
|
} from "./chunk-TEZ2FMEO.js";
|
|
20
20
|
import {
|
|
21
21
|
ApiService
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-625KMEYS.js";
|
|
23
23
|
import {
|
|
24
24
|
hostIsLoopback
|
|
25
25
|
} from "./chunk-DNQPZMPF.js";
|
|
26
26
|
import {
|
|
27
27
|
Telemetry,
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
contextInfo,
|
|
29
|
+
matchModel,
|
|
30
|
+
resolveContext
|
|
31
|
+
} from "./chunk-DZ4ZUAYH.js";
|
|
30
32
|
import {
|
|
31
33
|
PROVIDERS,
|
|
32
34
|
PROVIDER_NAMES,
|
|
33
35
|
ROUTE_PRESETS,
|
|
34
36
|
beijingDay,
|
|
35
37
|
isFreeModel,
|
|
36
|
-
reasoningModes,
|
|
37
38
|
routeReasoning,
|
|
38
39
|
validateConfig,
|
|
39
40
|
writePrivateJson
|
|
40
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-NGVWVIBM.js";
|
|
41
42
|
|
|
42
43
|
// src/manager.mjs
|
|
43
44
|
import { createHash, randomBytes as randomBytes3, timingSafeEqual } from "node:crypto";
|
|
44
45
|
|
|
45
46
|
// package.json
|
|
46
|
-
var version = "0.6.
|
|
47
|
+
var version = "0.6.1";
|
|
47
48
|
|
|
48
49
|
// src/manager.mjs
|
|
49
50
|
import { readFile as readFile4, mkdir as mkdir2, mkdtemp as mkdtemp2, rm as rm3 } from "node:fs/promises";
|
|
@@ -109,10 +110,10 @@ var options = ["cooldownMs", "requestTimeoutMs", "catalogTtlMs", "retryServerErr
|
|
|
109
110
|
function settings(config) {
|
|
110
111
|
return {
|
|
111
112
|
...pick(config, options),
|
|
112
|
-
models: Object.fromEntries(Object.entries(config.models ?? {}).map(([p, rows]) => [p, Object.fromEntries(Object.entries(rows).map(([id, pref]) => [id, pick(pref, ["name", "visible"])]))])),
|
|
113
|
+
models: Object.fromEntries(Object.entries(config.models ?? {}).map(([p, rows]) => [p, Object.fromEntries(Object.entries(rows).map(([id, pref]) => [id, pick(pref, ["name", "visible", "contextWindow", "supportsImages", "reasoningEffort"])]))])),
|
|
113
114
|
accounts: config.accounts.map((a) => pick(a, ["id", "provider", "name", "enabled", "autoCheckin"])),
|
|
114
115
|
routes: Object.fromEntries(Object.entries(config.routes).map(([id, r]) => [id, {
|
|
115
|
-
...pick(r, ["name", "visible", "strategy", "contextWindow", "maxTokens", "preferExpiringCredits", "expiringWithinDays", "freeOnly", "freeModels"]),
|
|
116
|
+
...pick(r, ["name", "visible", "strategy", "contextMode", "contextWindow", "maxTokens", "preferExpiringCredits", "expiringWithinDays", "freeOnly", "freeModels"]),
|
|
116
117
|
targets: r.targets.map((t) => pick(t, ["provider", "account", "model", "models", "weight", "tokenBudget", "creditBudget"]))
|
|
117
118
|
}]))
|
|
118
119
|
};
|
|
@@ -1033,8 +1034,8 @@ function modelInfo(row) {
|
|
|
1033
1034
|
return {
|
|
1034
1035
|
id: row.id,
|
|
1035
1036
|
name: row.name || row.id,
|
|
1036
|
-
|
|
1037
|
-
maxTokens: Math.min(finite(row.maxTokens, 32e3),
|
|
1037
|
+
...contextInfo(row),
|
|
1038
|
+
maxTokens: Math.min(finite(row.maxTokens, 32e3), contextInfo(row).maxContextWindow),
|
|
1038
1039
|
supportsImages: row.supportsImages === true || row.multimodal === true || row.input?.includes("image") === true,
|
|
1039
1040
|
...reasoning ? { reasoning } : {},
|
|
1040
1041
|
...billing ? { billing } : {},
|
|
@@ -1085,7 +1086,7 @@ var Manager = class {
|
|
|
1085
1086
|
for (const account of this.config.accounts) {
|
|
1086
1087
|
const item = saved[account.id];
|
|
1087
1088
|
if (item?.credentialFile === account.credentialFile && Array.isArray(item.models)) {
|
|
1088
|
-
this.catalogs.set(account.id, { ...item, models: item.models.filter((m) => typeof m.id === "string" && m.id.length > 0).map(modelInfo) });
|
|
1089
|
+
this.catalogs.set(account.id, { ...item, ...item.contextVersion !== 1 ? { fetchedAt: 0 } : {}, models: item.models.filter((m) => typeof m.id === "string" && m.id.length > 0).map(modelInfo) });
|
|
1089
1090
|
}
|
|
1090
1091
|
}
|
|
1091
1092
|
} catch {
|
|
@@ -1284,16 +1285,25 @@ var Manager = class {
|
|
|
1284
1285
|
const id = `free_${createHash("sha256").update(JSON.stringify([parentId, account.provider, model.id])).digest("hex").slice(0, 24)}`;
|
|
1285
1286
|
if (!groups.has(id)) groups.set(id, { id, models: [], targets: [], accountNames: [], modelName: model.name, provider: account.provider, modelId: model.id });
|
|
1286
1287
|
const group = groups.get(id);
|
|
1287
|
-
group.models.push({ model, provider: account.provider });
|
|
1288
|
+
group.models.push({ model, provider: account.provider, accountId: account.id });
|
|
1288
1289
|
group.targets.push({ provider: account.provider, account: account.id, model: model.id });
|
|
1289
1290
|
group.accountNames.push(account.name ?? account.id);
|
|
1290
1291
|
}
|
|
1291
1292
|
}
|
|
1292
1293
|
return [...groups.values()].map(({ models, ...group }) => {
|
|
1293
|
-
const preference = row.freeModels?.[group.id] ?? {}
|
|
1294
|
+
const preference = row.freeModels?.[group.id] ?? {};
|
|
1295
|
+
const context = resolveContext(models.map((s) => s.model), preference.contextWindow ?? (row.contextMode === "custom" ? row.contextWindow : null), row.contextWindow);
|
|
1296
|
+
const eligible = models.filter((s) => contextInfo(s.model).maxContextWindow >= context.contextWindow);
|
|
1297
|
+
const eligibleAccountIds = eligible.map((s) => s.accountId);
|
|
1298
|
+
const reasoning = routeReasoning(eligible);
|
|
1294
1299
|
const selected = preference.reasoningEffort;
|
|
1295
1300
|
return {
|
|
1296
1301
|
...group,
|
|
1302
|
+
...context,
|
|
1303
|
+
eligibleAccountIds,
|
|
1304
|
+
targets: group.targets.filter((t) => eligibleAccountIds.includes(t.account)),
|
|
1305
|
+
accountNames: group.accountNames.filter((_, i) => eligibleAccountIds.includes(models[i].accountId)),
|
|
1306
|
+
enforceContext: true,
|
|
1297
1307
|
parentId,
|
|
1298
1308
|
dynamicFree: true,
|
|
1299
1309
|
freeOnly: true,
|
|
@@ -1306,9 +1316,8 @@ var Manager = class {
|
|
|
1306
1316
|
effortUnavailable: !!selected && !reasoning?.supportedEfforts.includes(selected),
|
|
1307
1317
|
visible: row.visible !== false && preference.visible !== false,
|
|
1308
1318
|
selected: preference.visible !== false,
|
|
1309
|
-
supportsImages:
|
|
1310
|
-
|
|
1311
|
-
maxTokens: Math.min(row.maxTokens, ...models.map(({ model }) => model.maxTokens), ...models.map(({ model }) => model.contextWindow))
|
|
1319
|
+
supportsImages: eligible.every(({ model }) => model.supportsImages),
|
|
1320
|
+
maxTokens: Math.min(row.maxTokens, context.contextWindow, ...eligible.map(({ model }) => model.maxTokens))
|
|
1312
1321
|
};
|
|
1313
1322
|
});
|
|
1314
1323
|
}
|
|
@@ -1323,7 +1332,7 @@ var Manager = class {
|
|
|
1323
1332
|
publish() {
|
|
1324
1333
|
this.telemetry.configure(this.config.usageRetentionDays);
|
|
1325
1334
|
this.revision = revisionOf(this.raw);
|
|
1326
|
-
const routes =
|
|
1335
|
+
const routes = Object.fromEntries(this.routeModels().map((row) => [row.id, row]));
|
|
1327
1336
|
for (const model of this.adapterModels().filter((m) => m.dynamicFree)) routes[model.id] = model;
|
|
1328
1337
|
for (const provider of PROVIDERS) for (const model of this.providerModels(provider)) {
|
|
1329
1338
|
routes[`${provider}::${model.id}`] = { ...model, targets: [{ provider, model: model.id }] };
|
|
@@ -1335,23 +1344,30 @@ var Manager = class {
|
|
|
1335
1344
|
const rows = /* @__PURE__ */ new Map();
|
|
1336
1345
|
for (const account of this.config.accounts.filter((a) => a.provider === provider && a.enabled !== false)) {
|
|
1337
1346
|
for (const model of this.catalogs.get(account.id)?.models ?? []) {
|
|
1338
|
-
|
|
1339
|
-
rows.
|
|
1340
|
-
...old,
|
|
1341
|
-
contextWindow: Math.min(old.contextWindow, model.contextWindow),
|
|
1342
|
-
maxTokens: Math.min(old.maxTokens, model.maxTokens),
|
|
1343
|
-
supportsImages: old.supportsImages && model.supportsImages,
|
|
1344
|
-
reasoning: routeReasoning([{ model: old, provider }, { model, provider }])
|
|
1345
|
-
} : {
|
|
1346
|
-
...model,
|
|
1347
|
-
...reasoningModes(model, provider).length ? { reasoning: routeReasoning([{ model, provider }]) } : {}
|
|
1348
|
-
});
|
|
1347
|
+
if (!rows.has(model.id)) rows.set(model.id, []);
|
|
1348
|
+
rows.get(model.id).push(model);
|
|
1349
1349
|
}
|
|
1350
1350
|
}
|
|
1351
|
-
return [...rows.values()].map((
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1351
|
+
return [...rows.values()].map((models) => {
|
|
1352
|
+
const model = models[0], preference = this.config.models[provider]?.[model.id] ?? {};
|
|
1353
|
+
const context = resolveContext(models, preference.contextWindow);
|
|
1354
|
+
const eligible = models.filter((m) => contextInfo(m).maxContextWindow >= context.contextWindow);
|
|
1355
|
+
const reasoning = routeReasoning(eligible.map((model2) => ({ model: model2, provider })));
|
|
1356
|
+
const selected = preference.reasoningEffort;
|
|
1357
|
+
return {
|
|
1358
|
+
...model,
|
|
1359
|
+
...context,
|
|
1360
|
+
enforceContext: true,
|
|
1361
|
+
name: preference.name ?? model.name,
|
|
1362
|
+
reasoning,
|
|
1363
|
+
supportsImages: preference.supportsImages !== false && eligible.every((m) => m.supportsImages),
|
|
1364
|
+
imageCapable: eligible.every((m) => m.supportsImages),
|
|
1365
|
+
...selected && reasoning?.supportedEfforts.includes(selected) ? { reasoningEffort: selected } : {},
|
|
1366
|
+
configuredEffort: selected ?? null,
|
|
1367
|
+
effortUnavailable: !!selected && !reasoning?.supportedEfforts.includes(selected),
|
|
1368
|
+
maxTokens: Math.min(context.contextWindow, ...eligible.map((m) => m.maxTokens))
|
|
1369
|
+
};
|
|
1370
|
+
});
|
|
1355
1371
|
}
|
|
1356
1372
|
hiddenModels(provider) {
|
|
1357
1373
|
return this.providerModels(provider).filter((m) => !this.modelVisible(provider, m.id)).map((m) => m.id);
|
|
@@ -1365,14 +1381,19 @@ var Manager = class {
|
|
|
1365
1381
|
const sources = effectiveTargets.flatMap((target) => this.config.accounts.filter((a) => a.enabled !== false && a.provider === target.provider && (!target.account || target.account === a.id)).flatMap((a) => {
|
|
1366
1382
|
const catalog = this.catalogs.get(a.id)?.models ?? [];
|
|
1367
1383
|
const models2 = target.models ? target.models.map((model) => catalog.find((m) => m.id === model)).filter(Boolean) : [matchModel(id, target, catalog)].filter(Boolean);
|
|
1368
|
-
return models2.map((model) => ({ model, provider: a.provider }));
|
|
1384
|
+
return models2.map((model) => ({ model, provider: a.provider, accountId: a.id }));
|
|
1369
1385
|
}));
|
|
1370
|
-
const
|
|
1386
|
+
const context = resolveContext(sources.map((s) => s.model), row.contextMode === "custom" ? row.contextWindow : null, row.contextWindow);
|
|
1387
|
+
const eligible = sources.filter((s) => contextInfo(s.model).maxContextWindow >= context.contextWindow);
|
|
1388
|
+
const models = eligible.map((s) => s.model), reasoning = routeReasoning(eligible);
|
|
1371
1389
|
return {
|
|
1372
1390
|
...row,
|
|
1391
|
+
...context,
|
|
1392
|
+
enforceContext: true,
|
|
1373
1393
|
supportsImages: models.length > 0 && models.every((m) => m.supportsImages),
|
|
1374
1394
|
reasoning,
|
|
1375
|
-
|
|
1395
|
+
eligibleAccountIds: [...new Set(eligible.map((s) => s.accountId))],
|
|
1396
|
+
maxTokens: Math.min(row.maxTokens, context.contextWindow, ...models.map((m) => m.maxTokens)),
|
|
1376
1397
|
id,
|
|
1377
1398
|
name: row.name ?? id,
|
|
1378
1399
|
expiringStatus: { ...this.telemetry.data.expiringRounds[id] },
|
|
@@ -1394,7 +1415,7 @@ var Manager = class {
|
|
|
1394
1415
|
const client = await this.router.client(account);
|
|
1395
1416
|
const models = (await client.models(AbortSignal.timeout(6e4), !!force)).map(modelInfo);
|
|
1396
1417
|
if (this.closed || !this.config.accounts.some((a) => a.id === account.id && a.credentialFile === account.credentialFile)) return;
|
|
1397
|
-
this.catalogs.set(account.id, { credentialFile: account.credentialFile, fetchedAt: Date.now(), pricingVersion: 1, models });
|
|
1418
|
+
this.catalogs.set(account.id, { credentialFile: account.credentialFile, fetchedAt: Date.now(), pricingVersion: 1, contextVersion: 1, models });
|
|
1398
1419
|
this.catalogErrors.delete(account.id);
|
|
1399
1420
|
await withFileLock3(this.catalogFile, () => writePrivateJson(this.catalogFile, Object.fromEntries(this.catalogs)));
|
|
1400
1421
|
} catch (error) {
|
|
@@ -1451,6 +1472,7 @@ var Manager = class {
|
|
|
1451
1472
|
presets: Object.entries(ROUTE_PRESETS).map(([id, route]) => ({
|
|
1452
1473
|
id,
|
|
1453
1474
|
...structuredClone(route),
|
|
1475
|
+
providerCount: route.targets.length,
|
|
1454
1476
|
added: Object.hasOwn(this.config.routes, id),
|
|
1455
1477
|
availableProviders: [...new Set(route.targets.filter((t) => route.freeOnly ? this.config.accounts.some((a) => a.enabled !== false && a.provider === t.provider && this.freeModels(a).length) : matchModel(id, t, this.providerModels(t.provider))).map((t) => t.provider))]
|
|
1456
1478
|
})),
|
|
@@ -1466,6 +1488,63 @@ var Manager = class {
|
|
|
1466
1488
|
}
|
|
1467
1489
|
async action(input) {
|
|
1468
1490
|
if (!input || typeof input !== "object" || Array.isArray(input)) bad("\u8BF7\u6C42\u683C\u5F0F\u65E0\u6548");
|
|
1491
|
+
if (input.action === "model.test") {
|
|
1492
|
+
const model = this.providerModels(input.provider).find((m) => m.id === input.id);
|
|
1493
|
+
if (!model) bad("\u8BF7\u5148\u5237\u65B0\u5E76\u9009\u62E9\u5DF2\u53D1\u73B0\u7684\u6A21\u578B");
|
|
1494
|
+
if (this.modelTestFlight || Date.now() - (this.modelTestAt ?? 0) < 1e4) bad("\u8BF7\u7B49\u5F85\u5F53\u524D\u6D4B\u8BD5\u5B8C\u6210\uFF0C\u6D4B\u8BD5\u95F4\u9694\u81F3\u5C11 10 \u79D2");
|
|
1495
|
+
this.modelTestFlight = true;
|
|
1496
|
+
this.modelTestAt = Date.now();
|
|
1497
|
+
this.modelTestAbort = new AbortController();
|
|
1498
|
+
const started = performance.now();
|
|
1499
|
+
let modelTest;
|
|
1500
|
+
try {
|
|
1501
|
+
const { response } = await this.router.chat(
|
|
1502
|
+
{
|
|
1503
|
+
model: `${input.provider}::${input.id}`,
|
|
1504
|
+
stream: true,
|
|
1505
|
+
messages: [{ role: "system", content: "Answer briefly." }, { role: "user", content: "Reply with OK." }],
|
|
1506
|
+
max_tokens: 16
|
|
1507
|
+
},
|
|
1508
|
+
AbortSignal.any([this.modelTestAbort.signal, AbortSignal.timeout(45e3)])
|
|
1509
|
+
);
|
|
1510
|
+
const reader = response.body.getReader();
|
|
1511
|
+
let size = 0, text = "";
|
|
1512
|
+
const decoder = new TextDecoder();
|
|
1513
|
+
try {
|
|
1514
|
+
for (; ; ) {
|
|
1515
|
+
const chunk = await reader.read();
|
|
1516
|
+
if (chunk.done) break;
|
|
1517
|
+
size += chunk.value.byteLength;
|
|
1518
|
+
if (size > 1024 * 1024) throw Error("probe_response_too_large");
|
|
1519
|
+
text += decoder.decode(chunk.value, { stream: true });
|
|
1520
|
+
}
|
|
1521
|
+
text += decoder.decode();
|
|
1522
|
+
let answered = false;
|
|
1523
|
+
for (const line of text.split(/\r?\n/).filter((l) => l.startsWith("data:"))) {
|
|
1524
|
+
if (line.slice(5).trim() === "[DONE]") continue;
|
|
1525
|
+
const payload = JSON.parse(line.slice(5));
|
|
1526
|
+
if (payload.error || payload.choices?.some((c) => c.finish_reason === "error")) throw Error("probe_stream_failed");
|
|
1527
|
+
answered ||= payload.choices?.some((c) => c.delta?.content || c.delta?.reasoning_content || c.delta?.tool_calls?.length) ?? false;
|
|
1528
|
+
}
|
|
1529
|
+
if (!answered || !/^data:\s*\[DONE\]\s*$/m.test(text)) throw Error("probe_incomplete");
|
|
1530
|
+
} finally {
|
|
1531
|
+
await reader.cancel().catch(() => {
|
|
1532
|
+
});
|
|
1533
|
+
reader.releaseLock();
|
|
1534
|
+
}
|
|
1535
|
+
modelTest = { ok: true, elapsedMs: Math.round(performance.now() - started) };
|
|
1536
|
+
} catch (error) {
|
|
1537
|
+
modelTest = {
|
|
1538
|
+
ok: false,
|
|
1539
|
+
status: Number(error.status) || 502,
|
|
1540
|
+
hint: error.hint || "\u6D4B\u8BD5\u672A\u901A\u8FC7\uFF0C\u8BF7\u67E5\u770B\u8D26\u53F7\u72B6\u6001\uFF1B\u4E0D\u4F1A\u81EA\u52A8\u91CD\u8BD5\u3002"
|
|
1541
|
+
};
|
|
1542
|
+
} finally {
|
|
1543
|
+
this.modelTestFlight = false;
|
|
1544
|
+
this.modelTestAbort = void 0;
|
|
1545
|
+
}
|
|
1546
|
+
return { ...this.state(), modelTest };
|
|
1547
|
+
}
|
|
1469
1548
|
if (input.action?.startsWith("api.")) {
|
|
1470
1549
|
let result;
|
|
1471
1550
|
try {
|
|
@@ -1769,22 +1848,27 @@ var Manager = class {
|
|
|
1769
1848
|
}
|
|
1770
1849
|
} else if (input.action === "model.update") {
|
|
1771
1850
|
if (!PROVIDERS.includes(input.provider) || typeof input.id !== "string" || !input.id || input.id.length > 256) bad("\u6A21\u578B\u65E0\u6548");
|
|
1851
|
+
const model = this.providerModels(input.provider).find((m) => m.id === input.id);
|
|
1852
|
+
if (input.contextWindow != null && (!Number.isSafeInteger(input.contextWindow) || input.contextWindow <= 0 || !model || input.contextWindow > model.maxContextWindow)) bad("\u4E0A\u4E0B\u6587\u9884\u7B97\u4E0D\u80FD\u8D85\u8FC7\u8BE5\u6E20\u9053\u6A21\u578B\u7684\u6700\u5927\u5BB9\u91CF");
|
|
1853
|
+
if (input.supportsImages === true && !model?.imageCapable) bad("\u8BE5\u6A21\u578B\u672A\u58F0\u660E\u56FE\u7247\u8F93\u5165\u80FD\u529B");
|
|
1854
|
+
if (input.reasoningEffort != null && !model?.reasoning?.supportedEfforts.includes(input.reasoningEffort)) bad("\u6B64\u6A21\u578B\u4E0D\u652F\u6301\u6240\u9009\u63A8\u7406\u7B49\u7EA7");
|
|
1772
1855
|
raw.models = { ...raw.models, [input.provider]: {
|
|
1773
1856
|
...raw.models?.[input.provider],
|
|
1774
1857
|
[input.id]: {
|
|
1775
1858
|
...raw.models?.[input.provider]?.[input.id],
|
|
1776
|
-
...
|
|
1777
|
-
...input.visible !== void 0 ? { visible: input.visible } : {}
|
|
1859
|
+
...Object.fromEntries(["name", "visible", "contextWindow", "supportsImages", "reasoningEffort"].filter((k) => input[k] !== void 0).map((k) => [k, input[k]]))
|
|
1778
1860
|
}
|
|
1779
1861
|
} };
|
|
1780
1862
|
} else if (input.action === "free.model.update") {
|
|
1781
1863
|
const parent = raw.routes[input.parentId];
|
|
1782
1864
|
if (!parent?.freeOnly || !this.freeRoutes(input.parentId, this.config.routes[input.parentId]).some((m) => m.id === input.id)) bad("\u514D\u8D39\u6A21\u578B\u5DF2\u66F4\u65B0\uFF0C\u8BF7\u5237\u65B0\u9875\u9762");
|
|
1783
1865
|
const model = this.freeRoutes(input.parentId, this.config.routes[input.parentId]).find((m) => m.id === input.id);
|
|
1866
|
+
if (input.contextWindow != null && (!Number.isSafeInteger(input.contextWindow) || input.contextWindow <= 0 || input.contextWindow > model.maxContextWindow)) bad("\u4E0A\u4E0B\u6587\u9884\u7B97\u4E0D\u80FD\u8D85\u8FC7\u8BE5\u514D\u8D39\u6A21\u578B\u7684\u6700\u5927\u5BB9\u91CF");
|
|
1784
1867
|
if (input.reasoningEffort !== void 0 && input.reasoningEffort !== null && !model.reasoning?.supportedEfforts.includes(input.reasoningEffort)) bad("\u6B64\u514D\u8D39\u6A21\u578B\u4E0D\u652F\u6301\u6240\u9009\u63A8\u7406\u7B49\u7EA7");
|
|
1785
1868
|
parent.freeModels = { ...parent.freeModels, [input.id]: {
|
|
1786
1869
|
...parent.freeModels?.[input.id],
|
|
1787
1870
|
...input.visible !== void 0 ? { visible: input.visible } : {},
|
|
1871
|
+
...input.contextWindow !== void 0 ? { contextWindow: input.contextWindow } : {},
|
|
1788
1872
|
...input.reasoningEffort !== void 0 ? { reasoningEffort: input.reasoningEffort } : {}
|
|
1789
1873
|
} };
|
|
1790
1874
|
} else if (input.action === "route.save") {
|
|
@@ -1941,4 +2025,4 @@ export {
|
|
|
1941
2025
|
Manager,
|
|
1942
2026
|
managementHandler
|
|
1943
2027
|
};
|
|
1944
|
-
//# sourceMappingURL=chunk-
|
|
2028
|
+
//# sourceMappingURL=chunk-ZQZSXCVR.js.map
|