dsh-connect-modelscope-token-plan 0.5.0 → 0.6.2
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 +244 -208
- package/README.md +3 -1
- package/client.js +152 -29
- package/cordis.patch.yml +36 -5
- package/lib/host-config.js +194 -33
- package/lib/index.js +364 -105
- package/lib/llm-adapter.js +8 -2
- package/locale/en.json +2 -2
- package/locale/zh.json +2 -2
- package/package.json +115 -115
package/client.js
CHANGED
|
@@ -136,7 +136,7 @@ var dsh_connect_modelscope_token_plan_client = (function() {
|
|
|
136
136
|
var zh, en;
|
|
137
137
|
var init_i18n = __esmMin((() => {
|
|
138
138
|
zh = {
|
|
139
|
-
"panel.title": "
|
|
139
|
+
"panel.title": "魔搭模型接入",
|
|
140
140
|
"panel.refresh": "刷新",
|
|
141
141
|
"panel.updated": "更新于 {time}",
|
|
142
142
|
"panel.loading": "加载中…",
|
|
@@ -212,6 +212,9 @@ var dsh_connect_modelscope_token_plan_client = (function() {
|
|
|
212
212
|
"provider.contextDefault": "不覆盖(默认)",
|
|
213
213
|
"provider.contextHint": "目录未声明窗口时套用此值(会盖过内置策展表);保存后立即重新注册",
|
|
214
214
|
"provider.contextCuratedTitle": "窗口来自内置策展表(models.dev 交叉真值),平台未亲口声明;带 * 标记",
|
|
215
|
+
"provider.maxOutput": "最大输出",
|
|
216
|
+
"provider.maxOutputOverrideTitle": "最大输出:来自 maxTokensOverrides 里你写的值(盖过目录声明)",
|
|
217
|
+
"provider.maxOutputHint": "魔搭目录不返回输出上限,未覆盖的模型按 harness 默认(32768)截断;要更大就在 maxTokensOverrides 里逐模型写实测值(面板徽章用「最大输出」显示生效值)",
|
|
215
218
|
"section.draw": "出图工具",
|
|
216
219
|
"draw.enable": "开启后,agent 可在对话里用 modelscope_draw_image 生成或编辑图片",
|
|
217
220
|
"draw.on": "已开启",
|
|
@@ -242,13 +245,20 @@ var dsh_connect_modelscope_token_plan_client = (function() {
|
|
|
242
245
|
"draw.absent.peerLoad": "开关已开,但 tools 模块加载失败,出图工具缺席(Host 问题,非配置)。",
|
|
243
246
|
"draw.absent.registry": "开关已开,但工具注册被 Host 拒绝,出图工具缺席(Host 问题,非配置)。",
|
|
244
247
|
"draw.absent.unknown": "开关已开,但出图工具未挂载,原因未知。",
|
|
248
|
+
"draw.preferredGone": "已保存的默认模型 {model} 已不在当前目录(下架或改名)——出图会用它失败,请在下面重选。",
|
|
245
249
|
"trend.none": "还没有本地调用记录。",
|
|
250
|
+
"trend.unreadable": "本地计数读不到,趋势图无法显示(不是 0 次)。",
|
|
246
251
|
"trend.legend": "柱长相对区间内最大值,仅本地口径。",
|
|
252
|
+
"trend.metric": "趋势指标",
|
|
253
|
+
"trend.metricCalls": "调用次数",
|
|
254
|
+
"trend.metricTokens": "token 数",
|
|
255
|
+
"trend.legendTokens": "按 token 数相对区间内最大值画柱,仅本地口径;失败调用没有用量记录,与「该日无数据」一样显示为 0。",
|
|
247
256
|
"trend.window": "显示天数",
|
|
248
257
|
"trend.windowDefault": "默认(跟随配置)",
|
|
249
258
|
"trend.windowDays": "{days} 天",
|
|
250
259
|
"trend.windowHint": "只决定画多少天;能回看多久另有一个保留窗口(留得比画得多才画得出更远)。",
|
|
251
260
|
"events.none": "暂无事件。",
|
|
261
|
+
"events.unreadable": "本地计数读不到,事件流无法显示(不是没有事件)。",
|
|
252
262
|
"events.quota": "额度",
|
|
253
263
|
"events.rate_limit": "限频",
|
|
254
264
|
"events.error": "错误",
|
|
@@ -278,7 +288,7 @@ var dsh_connect_modelscope_token_plan_client = (function() {
|
|
|
278
288
|
"composer.stale": "上次数据"
|
|
279
289
|
};
|
|
280
290
|
en = {
|
|
281
|
-
"panel.title": "ModelScope Access
|
|
291
|
+
"panel.title": "ModelScope Model Access",
|
|
282
292
|
"panel.refresh": "Refresh",
|
|
283
293
|
"panel.updated": "Updated {time}",
|
|
284
294
|
"panel.loading": "Loading…",
|
|
@@ -354,6 +364,9 @@ var dsh_connect_modelscope_token_plan_client = (function() {
|
|
|
354
364
|
"provider.contextDefault": "No override (default)",
|
|
355
365
|
"provider.contextHint": "Applied when the catalog declares no window (it overrides the built-in curated table); re-registers immediately",
|
|
356
366
|
"provider.contextCuratedTitle": "Window from the built-in curated table (models.dev cross-check), not declared by the platform; marked with *",
|
|
367
|
+
"provider.maxOutput": "Max output",
|
|
368
|
+
"provider.maxOutputOverrideTitle": "Max output: the value you wrote in maxTokensOverrides (it wins over the catalogue)",
|
|
369
|
+
"provider.maxOutputHint": "The ModelScope catalogue returns no output ceiling, so models without an override are cut off at the harness default (32768); write per-model measured values in maxTokensOverrides for more (the badge shows the effective value)",
|
|
357
370
|
"section.draw": "Draw tool",
|
|
358
371
|
"draw.enable": "Once on, the agent can generate or edit images with modelscope_draw_image",
|
|
359
372
|
"draw.on": "On",
|
|
@@ -384,13 +397,20 @@ var dsh_connect_modelscope_token_plan_client = (function() {
|
|
|
384
397
|
"draw.absent.peerLoad": "The switch is on, but the tools module failed to load; the draw tool is absent (a Host fault, not config).",
|
|
385
398
|
"draw.absent.registry": "The switch is on, but the Host refused the tool registration; the draw tool is absent (a Host fault, not config).",
|
|
386
399
|
"draw.absent.unknown": "The switch is on, but the draw tool is not mounted; the reason is unknown.",
|
|
400
|
+
"draw.preferredGone": "The saved default model {model} is no longer in the catalogue (delisted or renamed) — drawing with it will fail. Pick another one below.",
|
|
387
401
|
"trend.none": "No local call records yet.",
|
|
402
|
+
"trend.unreadable": "Local counts could not be read; the trend chart is unavailable (this is not zero calls).",
|
|
388
403
|
"trend.legend": "Bar lengths are relative to the maximum in the range (local scope only).",
|
|
404
|
+
"trend.metric": "Trend metric",
|
|
405
|
+
"trend.metricCalls": "Calls",
|
|
406
|
+
"trend.metricTokens": "Tokens",
|
|
407
|
+
"trend.legendTokens": "Bar lengths are relative to the largest token count in the range (local scope only). Failed calls record no usage, and days with no data also read as 0.",
|
|
389
408
|
"trend.window": "Days shown",
|
|
390
409
|
"trend.windowDefault": "Default (follow config)",
|
|
391
410
|
"trend.windowDays": "{days} days",
|
|
392
411
|
"trend.windowHint": "Only sets how many days are drawn; how far back history is kept is a separate retention window.",
|
|
393
412
|
"events.none": "No events.",
|
|
413
|
+
"events.unreadable": "Local counters unreadable; event stream cannot be shown (not \"no events\").",
|
|
394
414
|
"events.quota": "Quota",
|
|
395
415
|
"events.rate_limit": "Rate limit",
|
|
396
416
|
"events.error": "Error",
|
|
@@ -455,6 +475,36 @@ var dsh_connect_modelscope_token_plan_client = (function() {
|
|
|
455
475
|
if (number >= 1e4) return Math.round(number).toLocaleString();
|
|
456
476
|
return String(Math.round(number * 100) / 100);
|
|
457
477
|
}
|
|
478
|
+
/**
|
|
479
|
+
* 大数字的紧凑文本:`< 1000` 原样,`< 1e6` 用 `k`,`≥ 1e6` 用 `m`(各留 1~2 位小数,
|
|
480
|
+
* 去尾零)。**只给 token 这类会自然到百万级的读数用**——调用次数一天几十上百,千分位
|
|
481
|
+
* 逗号反而更好读,那条路径继续走 `count()`。
|
|
482
|
+
*
|
|
483
|
+
* 单位用小写 k/m:视觉上与 SI 前缀一致,也避开「兆」的歧义(`M` 在中文语境里常被读成
|
|
484
|
+
* 万亿)。负值与 NaN 分别返回 `-1.2k` 与 `NaN`——不做掩饰,异常值该在面板上现形。
|
|
485
|
+
*
|
|
486
|
+
* **与 `const.ts` 的 `formatWindow()` 刻意不同,不是漏统一**:那个印的是**上下文窗口
|
|
487
|
+
* 规格**(`128K` / `256K` / `1M`,按上游与市场的叫法、K=1024 口径),回答「大概能放
|
|
488
|
+
* 多少上下文」;这里印的是**实测用量读数**(`1.2k` / `3.4m`,十进制、小写),回答
|
|
489
|
+
* 「实际用了多少」。同一数字在两处印法不同,是因为它们量纲不同(规格 vs 读数)。
|
|
490
|
+
*/
|
|
491
|
+
function compactCount(value) {
|
|
492
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return String(value);
|
|
493
|
+
const trim = (number) => String(Number(number.toFixed(number >= 100 ? 0 : number >= 10 ? 1 : 2)));
|
|
494
|
+
const sign = value < 0 ? "-" : "";
|
|
495
|
+
const abs = Math.abs(value);
|
|
496
|
+
if (abs < 1e3) return `${sign}${trim(abs)}`;
|
|
497
|
+
const tiers = [
|
|
498
|
+
[1e3, "k"],
|
|
499
|
+
[1e6, "m"],
|
|
500
|
+
[1e9, "b"]
|
|
501
|
+
];
|
|
502
|
+
for (const [i, [divisor, unit]] of tiers.entries()) {
|
|
503
|
+
const shown = trim(abs / divisor);
|
|
504
|
+
if (i === tiers.length - 1 || Number(shown) < 1e3) return `${sign}${shown}${unit}`;
|
|
505
|
+
}
|
|
506
|
+
return `${sign}${trim(abs)}b`;
|
|
507
|
+
}
|
|
458
508
|
/** 填 `{key}` 模板:vars 的每个键对应模板里的同名占位符。 */
|
|
459
509
|
function format(template, vars) {
|
|
460
510
|
let text = template;
|
|
@@ -760,6 +810,28 @@ var dsh_connect_modelscope_token_plan_client = (function() {
|
|
|
760
810
|
fontSize: 11,
|
|
761
811
|
color: "var(--dsw-alias-label-secondary)"
|
|
762
812
|
},
|
|
813
|
+
trendMetricBar: {
|
|
814
|
+
display: "flex",
|
|
815
|
+
gap: 2,
|
|
816
|
+
marginBottom: 6,
|
|
817
|
+
alignItems: "center"
|
|
818
|
+
},
|
|
819
|
+
trendMetricBtn: {
|
|
820
|
+
appearance: "none",
|
|
821
|
+
background: "none",
|
|
822
|
+
border: "none",
|
|
823
|
+
borderBottom: "1px solid transparent",
|
|
824
|
+
padding: "2px 8px",
|
|
825
|
+
fontSize: 11,
|
|
826
|
+
color: "var(--dsw-alias-label-secondary)",
|
|
827
|
+
cursor: "pointer",
|
|
828
|
+
outlineOffset: -2
|
|
829
|
+
},
|
|
830
|
+
trendMetricBtnActive: {
|
|
831
|
+
color: "var(--dsw-alias-label-primary)",
|
|
832
|
+
fontWeight: 600,
|
|
833
|
+
borderBottom: `1px solid ${BRAND}`
|
|
834
|
+
},
|
|
763
835
|
muted: { color: "var(--dsw-alias-label-secondary)" },
|
|
764
836
|
error: { color: "var(--dsw-alias-state-error-primary)" },
|
|
765
837
|
empty: {
|
|
@@ -1021,13 +1093,15 @@ var dsh_connect_modelscope_token_plan_client = (function() {
|
|
|
1021
1093
|
};
|
|
1022
1094
|
case "quota": return {
|
|
1023
1095
|
daily: { usedLocal: null },
|
|
1024
|
-
perModel:
|
|
1096
|
+
perModel: null,
|
|
1025
1097
|
countingNote: "local-counting"
|
|
1026
1098
|
};
|
|
1027
|
-
case "events": return
|
|
1099
|
+
case "events": return null;
|
|
1028
1100
|
case "trend": return {
|
|
1029
1101
|
days: 0,
|
|
1030
|
-
|
|
1102
|
+
windowDays: null,
|
|
1103
|
+
maxDays: 0,
|
|
1104
|
+
buckets: null
|
|
1031
1105
|
};
|
|
1032
1106
|
case "models": return {
|
|
1033
1107
|
available: false,
|
|
@@ -1101,6 +1175,8 @@ var dsh_connect_modelscope_token_plan_client = (function() {
|
|
|
1101
1175
|
const id = String(row.id ?? "");
|
|
1102
1176
|
const w = row.contextWindow;
|
|
1103
1177
|
const contextSource = row.contextSource === "override" || row.contextSource === "curated" ? row.contextSource : "catalog";
|
|
1178
|
+
const maxOutputSource = row.maxOutputSource === "override" ? "override" : "catalog";
|
|
1179
|
+
const out = row.maxOutputLength;
|
|
1104
1180
|
return {
|
|
1105
1181
|
id,
|
|
1106
1182
|
name: typeof row.name === "string" && row.name !== "" ? row.name : id,
|
|
@@ -1108,7 +1184,9 @@ var dsh_connect_modelscope_token_plan_client = (function() {
|
|
|
1108
1184
|
available: row.available !== false,
|
|
1109
1185
|
quotaExhausted: row.quotaExhausted === true,
|
|
1110
1186
|
contextSource,
|
|
1111
|
-
|
|
1187
|
+
maxOutputSource,
|
|
1188
|
+
...typeof w === "number" && Number.isFinite(w) && w > 0 ? { contextWindow: w } : {},
|
|
1189
|
+
...typeof out === "number" && Number.isFinite(out) && out > 0 ? { maxOutputLength: out } : {}
|
|
1112
1190
|
};
|
|
1113
1191
|
}).filter((entry) => entry.id !== "") : [];
|
|
1114
1192
|
return {
|
|
@@ -1169,6 +1247,7 @@ var dsh_connect_modelscope_token_plan_client = (function() {
|
|
|
1169
1247
|
..."effectiveSource" in d ? { effectiveSource } : {},
|
|
1170
1248
|
absentReason,
|
|
1171
1249
|
mountPending: d.mountPending === true,
|
|
1250
|
+
preferredInCatalog: d.preferredInCatalog === true ? true : d.preferredInCatalog === false ? false : null,
|
|
1172
1251
|
toolName: typeof d.toolName === "string" && d.toolName !== "" ? d.toolName : "modelscope_draw_image"
|
|
1173
1252
|
};
|
|
1174
1253
|
}
|
|
@@ -1228,6 +1307,7 @@ var dsh_connect_modelscope_token_plan_client = (function() {
|
|
|
1228
1307
|
effectiveSource: null,
|
|
1229
1308
|
absentReason: null,
|
|
1230
1309
|
mountPending: false,
|
|
1310
|
+
preferredInCatalog: null,
|
|
1231
1311
|
toolName: "modelscope_draw_image"
|
|
1232
1312
|
});
|
|
1233
1313
|
GUIDANCE_BY_CODE = Object.freeze({
|
|
@@ -1453,17 +1533,19 @@ var dsh_connect_modelscope_token_plan_client = (function() {
|
|
|
1453
1533
|
function LocalDailyCard({ snapshot, tt }) {
|
|
1454
1534
|
const quota = snapshot.quota;
|
|
1455
1535
|
const daily = quota?.daily ?? { usedLocal: null };
|
|
1456
|
-
const perModel =
|
|
1536
|
+
const perModel = quota?.perModel;
|
|
1537
|
+
const perModelRows = Array.isArray(perModel) ? perModel : perModel === null ? null : [];
|
|
1457
1538
|
const unknownUsed = !(typeof daily.usedLocal === "number" && Number.isFinite(daily.usedLocal));
|
|
1458
1539
|
const usedText = unknownUsed ? "—" : count(daily.usedLocal);
|
|
1540
|
+
const perModelUnknown = perModelRows === null;
|
|
1459
1541
|
return h("div", { style: S.card }, h("div", { style: S.poolName }, format(tt("quota.headline"), {
|
|
1460
1542
|
calls: usedText,
|
|
1461
|
-
models: count(
|
|
1462
|
-
})), unknownUsed ? h("div", { style: {
|
|
1543
|
+
models: perModelUnknown ? "—" : count(perModelRows.length)
|
|
1544
|
+
})), unknownUsed || perModelUnknown ? h("div", { style: {
|
|
1463
1545
|
...S.formNote,
|
|
1464
1546
|
color: "var(--dsw-alias-state-warn-primary)"
|
|
1465
|
-
} }, tt("quota.unavailable")) : null, h(ModelUsageTable, {
|
|
1466
|
-
rows:
|
|
1547
|
+
} }, tt("quota.unavailable")) : null, perModelUnknown ? null : h(ModelUsageTable, {
|
|
1548
|
+
rows: perModelRows,
|
|
1467
1549
|
tt
|
|
1468
1550
|
}), h("div", { style: S.trendLegend }, tt("quota.note")));
|
|
1469
1551
|
}
|
|
@@ -1479,7 +1561,7 @@ var dsh_connect_modelscope_token_plan_client = (function() {
|
|
|
1479
1561
|
}, h("div", { style: S.trendRowHead }, h("span", {
|
|
1480
1562
|
style: S.trendModel,
|
|
1481
1563
|
title: row.modelId
|
|
1482
|
-
}, row.modelId), h("span", { style: S.trendCredits }, format(tt("quota.rowCalls"), { calls: count(row.calls) }) + (row.tokens !== null ? ` · ${format(tt("quota.rowTokens"), { tokens:
|
|
1564
|
+
}, row.modelId), h("span", { style: S.trendCredits }, format(tt("quota.rowCalls"), { calls: count(row.calls) }) + (row.tokens !== null ? ` · ${format(tt("quota.rowTokens"), { tokens: compactCount(row.tokens) })}` : ""))), pct >= 1 ? h("div", {
|
|
1483
1565
|
style: S.trendBar,
|
|
1484
1566
|
role: "progressbar",
|
|
1485
1567
|
"aria-valuenow": Math.round(pct),
|
|
@@ -1526,33 +1608,63 @@ var dsh_connect_modelscope_token_plan_client = (function() {
|
|
|
1526
1608
|
}
|
|
1527
1609
|
return out;
|
|
1528
1610
|
}
|
|
1529
|
-
/**
|
|
1611
|
+
/**
|
|
1612
|
+
* 近 N 天本地调用趋势(天桶;缺桶 = 该日 0 次,真实零)——**竖向柱状图**。
|
|
1613
|
+
*
|
|
1614
|
+
* token 与调用次数共用同一根柱子但**各自归一化**(`max` 按当前指标现算):两者量级
|
|
1615
|
+
* 差三四个数量级,若共用一把尺,次数柱会被 token 柱压成贴地的一条线——那图就撒谎了。
|
|
1616
|
+
* 一次只画一个指标(不放双柱),窄容器里双柱既挤又难读,且对比还得再解释一遍。
|
|
1617
|
+
*
|
|
1618
|
+
* 切换态活在组件内的 useState:它是纯显示偏好,不落盘——与「显示天数」不同,那个
|
|
1619
|
+
* 会改变 Host 的取数窗口(真要持久化就该走 usage-prefs,别混进这里)。
|
|
1620
|
+
*/
|
|
1530
1621
|
function TrendBars({ buckets, tt }) {
|
|
1622
|
+
const [metric, setMetric] = useState("calls");
|
|
1623
|
+
if (buckets === null) return h("div", { style: S.trendLegend }, tt("trend.unreadable"));
|
|
1531
1624
|
if (!Array.isArray(buckets) || buckets.length === 0) return h("div", { style: S.trendLegend }, tt("trend.none"));
|
|
1532
1625
|
const rows = buckets.map((bucket) => ({
|
|
1533
1626
|
dateKey: bucket.dateKey,
|
|
1534
|
-
calls: Number.isFinite(bucket.calls) ? Math.max(0, bucket.calls) : 0
|
|
1627
|
+
calls: Number.isFinite(bucket.calls) ? Math.max(0, bucket.calls) : 0,
|
|
1628
|
+
tokens: Number.isFinite(bucket.tokens) ? Math.max(0, bucket.tokens) : 0
|
|
1535
1629
|
}));
|
|
1536
|
-
const
|
|
1537
|
-
|
|
1538
|
-
|
|
1630
|
+
const tokenMode = metric === "tokens";
|
|
1631
|
+
const values = rows.map((row) => tokenMode ? row.tokens : row.calls);
|
|
1632
|
+
const max = Math.max(0, ...values);
|
|
1633
|
+
/** 读数文本:次数走 count(千分位),token 走 compactCount(`1.2k` / `3.4m`)。 */
|
|
1634
|
+
const readout = (value) => tokenMode ? compactCount(value) : count(value);
|
|
1635
|
+
return h("div", null, h("div", {
|
|
1636
|
+
style: S.trendMetricBar,
|
|
1637
|
+
role: "group",
|
|
1638
|
+
"aria-label": tt("trend.metric")
|
|
1639
|
+
}, ...[["calls", "trend.metricCalls"], ["tokens", "trend.metricTokens"]].map(([key, labelKey]) => h("button", {
|
|
1640
|
+
key,
|
|
1641
|
+
type: "button",
|
|
1642
|
+
"aria-pressed": metric === key,
|
|
1643
|
+
style: metric === key ? {
|
|
1644
|
+
...S.trendMetricBtn,
|
|
1645
|
+
...S.trendMetricBtnActive
|
|
1646
|
+
} : S.trendMetricBtn,
|
|
1647
|
+
onClick: () => setMetric(key)
|
|
1648
|
+
}, tt(labelKey)))), h("div", { style: S.trendChartBars }, rows.map((row, index) => {
|
|
1649
|
+
const value = values[index] ?? 0;
|
|
1650
|
+
const pct = max > 0 ? value / max * 100 : 0;
|
|
1539
1651
|
return h("div", {
|
|
1540
1652
|
key: row.dateKey,
|
|
1541
1653
|
style: S.trendChartBar,
|
|
1542
|
-
title: `${row.dateKey}: ${
|
|
1543
|
-
},
|
|
1654
|
+
title: `${row.dateKey}: ${readout(value)}`
|
|
1655
|
+
}, value > 0 ? h("span", {
|
|
1544
1656
|
style: {
|
|
1545
1657
|
...S.trendChartValue,
|
|
1546
1658
|
bottom: `calc(${pct}% + 3px)`
|
|
1547
1659
|
},
|
|
1548
1660
|
"aria-hidden": "true"
|
|
1549
|
-
},
|
|
1661
|
+
}, readout(value)) : null, h("div", {
|
|
1550
1662
|
style: {
|
|
1551
1663
|
...S.trendChartFill,
|
|
1552
1664
|
height: `${pct}%`
|
|
1553
1665
|
},
|
|
1554
1666
|
role: "progressbar",
|
|
1555
|
-
"aria-label": `${row.dateKey} ${
|
|
1667
|
+
"aria-label": `${row.dateKey} ${readout(value)}`,
|
|
1556
1668
|
"aria-valuenow": Math.round(pct),
|
|
1557
1669
|
"aria-valuemin": 0,
|
|
1558
1670
|
"aria-valuemax": 100
|
|
@@ -1564,7 +1676,7 @@ var dsh_connect_modelscope_token_plan_client = (function() {
|
|
|
1564
1676
|
title: key,
|
|
1565
1677
|
style: { whiteSpace: "nowrap" }
|
|
1566
1678
|
}, shortDateKey(key));
|
|
1567
|
-
})), h("div", { style: S.trendLegend }, tt("trend.legend")));
|
|
1679
|
+
})), h("div", { style: S.trendLegend }, tt(tokenMode ? "trend.legendTokens" : "trend.legend")));
|
|
1568
1680
|
}
|
|
1569
1681
|
/**
|
|
1570
1682
|
* 趋势显示窗口选择器:默认(跟随 `trendDays` 配置)/ 7 / 14 / 30 / 90 天。
|
|
@@ -1622,8 +1734,9 @@ var dsh_connect_modelscope_token_plan_client = (function() {
|
|
|
1622
1734
|
role: "alert"
|
|
1623
1735
|
}, error) : null);
|
|
1624
1736
|
}
|
|
1625
|
-
/** 事件流(429/错误),Newest-first
|
|
1737
|
+
/** 事件流(429/错误),Newest-first。`events` 为 null = 读不到,渲染「—」(读不到 ≠ 0)。 */
|
|
1626
1738
|
function EventsList({ events, tt }) {
|
|
1739
|
+
if (events === null) return h("div", { style: S.trendLegend }, tt("events.unreadable"));
|
|
1627
1740
|
if (!Array.isArray(events) || events.length === 0) return h("div", { style: S.trendLegend }, tt("events.none"));
|
|
1628
1741
|
return h("div", null, events.map((event, index) => h("div", {
|
|
1629
1742
|
key: `${event.at}-${index}`,
|
|
@@ -1889,7 +2002,10 @@ var dsh_connect_modelscope_token_plan_client = (function() {
|
|
|
1889
2002
|
color: "var(--dsw-alias-label-secondary)"
|
|
1890
2003
|
} : S.modelBadge,
|
|
1891
2004
|
title: row.contextSource === "curated" ? tt("provider.contextCuratedTitle") : tt("provider.contextWindow")
|
|
1892
|
-
}, row.contextSource === "curated" ? formatWindow(row.contextWindow) + " *" : formatWindow(row.contextWindow)) : null, row.
|
|
2005
|
+
}, row.contextSource === "curated" ? formatWindow(row.contextWindow) + " *" : formatWindow(row.contextWindow)) : null, typeof row.maxOutputLength === "number" ? h("span", {
|
|
2006
|
+
style: S.modelBadge,
|
|
2007
|
+
title: row.maxOutputSource === "override" ? tt("provider.maxOutputOverrideTitle") : tt("provider.maxOutput")
|
|
2008
|
+
}, formatWindow(row.maxOutputLength)) : null, row.quotaExhausted === true ? h("span", { style: {
|
|
1893
2009
|
...S.modelBadge,
|
|
1894
2010
|
color: "var(--dsw-alias-state-error-primary)"
|
|
1895
2011
|
} }, tt("provider.quotaExhausted")) : null, h("a", {
|
|
@@ -1957,7 +2073,7 @@ var dsh_connect_modelscope_token_plan_client = (function() {
|
|
|
1957
2073
|
style: S.primary,
|
|
1958
2074
|
disabled: busy,
|
|
1959
2075
|
onClick: () => onSaveList(draft.slice())
|
|
1960
|
-
}, tt("provider.saveList"))), visibleRows.length === 0 ? h("div", { style: {
|
|
2076
|
+
}, tt("provider.saveList"))), h("div", { style: S.advancedHint }, tt("provider.maxOutputHint")), visibleRows.length === 0 ? h("div", { style: {
|
|
1961
2077
|
...S.muted,
|
|
1962
2078
|
fontSize: 12,
|
|
1963
2079
|
padding: "10px 4px"
|
|
@@ -2074,7 +2190,7 @@ var dsh_connect_modelscope_token_plan_client = (function() {
|
|
|
2074
2190
|
},
|
|
2075
2191
|
role: "status"
|
|
2076
2192
|
}, tt("draw.notMounted"));
|
|
2077
|
-
const restartHint = enabled ? h("div", { style: {
|
|
2193
|
+
const restartHint = enabled && status.mountPending === true ? h("div", { style: {
|
|
2078
2194
|
...S.formNote,
|
|
2079
2195
|
color: "var(--dsw-alias-state-warn-primary)"
|
|
2080
2196
|
} }, tt("draw.restartHint")) : null;
|
|
@@ -2082,6 +2198,13 @@ var dsh_connect_modelscope_token_plan_client = (function() {
|
|
|
2082
2198
|
...S.formNote,
|
|
2083
2199
|
color: "var(--dsw-alias-state-warn-primary)"
|
|
2084
2200
|
} }, tt("draw.needsKey")) : null;
|
|
2201
|
+
const preferredGoneHint = status.preferredModel !== null && status.preferredInCatalog === false ? h("div", {
|
|
2202
|
+
style: {
|
|
2203
|
+
...S.formNote,
|
|
2204
|
+
color: "var(--dsw-alias-state-warn-primary)"
|
|
2205
|
+
},
|
|
2206
|
+
role: "status"
|
|
2207
|
+
}, format(tt("draw.preferredGone"), { model: status.preferredModel })) : null;
|
|
2085
2208
|
const autoDescription = !hasEffectiveKey || status.preferredModel !== null ? null : effectiveModel === null || effectiveModel === "" ? h("div", { style: {
|
|
2086
2209
|
...S.muted,
|
|
2087
2210
|
fontSize: 11,
|
|
@@ -2199,7 +2322,7 @@ var dsh_connect_modelscope_token_plan_client = (function() {
|
|
|
2199
2322
|
}, tt("draw.reset"))), error !== null ? h("div", {
|
|
2200
2323
|
style: S.formError,
|
|
2201
2324
|
role: "alert"
|
|
2202
|
-
}, error) : null, restartHint, tokenHint);
|
|
2325
|
+
}, error) : null, restartHint, tokenHint, preferredGoneHint);
|
|
2203
2326
|
}
|
|
2204
2327
|
var MAX_TICKS, TREND_WINDOW_TIERS, EVENT_KIND_KEY, DRAW_ABSENT_KEY;
|
|
2205
2328
|
var init_cards = __esmMin((() => {
|
|
@@ -2662,7 +2785,7 @@ var dsh_connect_modelscope_token_plan_client = (function() {
|
|
|
2662
2785
|
onChange: (windowDays) => void saveTrendWindow(windowDays),
|
|
2663
2786
|
tt
|
|
2664
2787
|
}), h(TrendBars, {
|
|
2665
|
-
buckets: snap.trend?.buckets ??
|
|
2788
|
+
buckets: snap.trend?.buckets ?? null,
|
|
2666
2789
|
tt
|
|
2667
2790
|
})), h(SectionCard, {
|
|
2668
2791
|
title: tt("section.events"),
|
|
@@ -2670,7 +2793,7 @@ var dsh_connect_modelscope_token_plan_client = (function() {
|
|
|
2670
2793
|
onToggle: () => toggleSection("events"),
|
|
2671
2794
|
tt
|
|
2672
2795
|
}, h(EventsList, {
|
|
2673
|
-
events: snap.events ??
|
|
2796
|
+
events: snap.events ?? null,
|
|
2674
2797
|
tt
|
|
2675
2798
|
})));
|
|
2676
2799
|
};
|
package/cordis.patch.yml
CHANGED
|
@@ -32,6 +32,17 @@
|
|
|
32
32
|
retentionDays: 90
|
|
33
33
|
# 429/错误事件环形缓冲的上限(面板只展示最近的)。上界 1000,硬夹。
|
|
34
34
|
maxEvents: 50
|
|
35
|
+
# 单模型「额度耗尽」推断窗口(分钟)。官方只有账户级魔粒余额、没有
|
|
36
|
+
# per-model 额度端点,所以「哪个模型刚才在限频」从本插件的 429 事件流
|
|
37
|
+
# 推断(纯函数见 src/host/usage-store.ts 的 exhaustedModelIds):某模型
|
|
38
|
+
# 最近在这个窗口内出现过 kind=quota 的事件(重分类后的口径——被误判成
|
|
39
|
+
# QUOTA 的 rpm 限频已在此之前纠正为 rate_limit,不算证据),选择器就不再
|
|
40
|
+
# 提供它、面板 roster 灰显;事件移出窗口即恢复。**恢复不可观测是已知
|
|
41
|
+
# 代价**:成功的调用不发事件,额度若在窗口内恢复(按天重置恰好如此),
|
|
42
|
+
# 模型最多灰显满一个窗口——方向保守(不提供注定 429 的模型),且灰显
|
|
43
|
+
# 带着原因。下界 5 分钟(再短规则形同虚设),上界 1440(一天,额度按天
|
|
44
|
+
# 重置,更长的窗口没有对应的恢复语义)。硬夹。
|
|
45
|
+
exhaustionWindowMinutes: 60
|
|
35
46
|
# Host 侧对 /v1/models 的缓存秒数;面板脚注直接引用此值。上界 600。
|
|
36
47
|
cacheSeconds: 60
|
|
37
48
|
# 面板轮询间隔,由 Host 下发、面板跟随。上界 3600(1 小时)。
|
|
@@ -47,11 +58,12 @@
|
|
|
47
58
|
# tab 的「接入为 DSH 模型」开关可随时翻转,面板保存值优先于这里的默认。
|
|
48
59
|
# 注册后魔搭模型进入 DSH 模型选择器。
|
|
49
60
|
#
|
|
50
|
-
#
|
|
51
|
-
#
|
|
52
|
-
#
|
|
53
|
-
#
|
|
54
|
-
#
|
|
61
|
+
# 计数范围:注册开关打开后,本客户端(本 profile)的魔搭对话经本插件的
|
|
62
|
+
# 适配器出去,每一次调用与每一条 429/错误事件都由 src/host/usage-observer.ts
|
|
63
|
+
# 在流的出口记进同一个 usage-store。口径是**本客户端**:桌面端与 Web 端是
|
|
64
|
+
# 两个 profile,各记各的账、互不可见(`npm run doctor` 并排列出各 profile),
|
|
65
|
+
# 别把它当跨端总量。直连魔搭的其它客户端同样不计入(本插件看不见它们),
|
|
66
|
+
# 消耗总量以官方魔粒余额为准。
|
|
55
67
|
#
|
|
56
68
|
# 偏差方向是**按流计次**:重试不在流内部发生,而是流被消费完后由
|
|
57
69
|
# agent/request-error 瀑布决定重发,因而每次重试各记一次(按「魔搭按
|
|
@@ -59,6 +71,25 @@
|
|
|
59
71
|
# 与 README「诚实声明」。
|
|
60
72
|
registerProvider: false
|
|
61
73
|
# ------------------------------------------------------------------
|
|
74
|
+
# 逐模型的单次输出上限覆盖(模型 id → tokens)。空对象 = 目录说了算。
|
|
75
|
+
#
|
|
76
|
+
# **为什么必须有它**:本插件对输出上限的策略是「目录声明了才声明」,而魔搭
|
|
77
|
+
# `/v1/models` **从不返回**这个字段(实测每条只有 id / object / owned_by /
|
|
78
|
+
# created,见 docs/REFERENCES.md)。两条合起来 = **每一个**模型的 descriptor
|
|
79
|
+
# 都不带 maxTokens,harness 于是用它的 `defaultMaxTokens ?? 32768` 兜底:
|
|
80
|
+
# 32768 既不是魔搭声明的数,也不是实测过的数,它只是 harness 的缺省值。
|
|
81
|
+
# 目录给不出真值时,只有操作者知道某个模型实测能吐多少——没有这个字段,
|
|
82
|
+
# 那份知识无处可写(写进目录缓存会被下一轮轮询覆盖)。
|
|
83
|
+
#
|
|
84
|
+
# 优先级 `覆盖 > 目录声明 > 不声明`。键是**精确模型 id**,不做子串匹配——
|
|
85
|
+
# 上限是请求参数,宽松的键会顺手改掉一批没被点名的模型(键写 flash 会命中
|
|
86
|
+
# 七八条);值必须是正整数(0 = 未声明;非法值丢弃而不是夹取)。
|
|
87
|
+
# 面板模型清单行会用「最大输出」徽章显示生效值,来源是覆盖还是目录一目了然。
|
|
88
|
+
#
|
|
89
|
+
# 例(把下面这行整行复制出去、去掉 `#` 即可):
|
|
90
|
+
# maxTokensOverrides: { "deepseek-ai/DeepSeek-V4.1-Flash": 65536 }
|
|
91
|
+
maxTokensOverrides: {}
|
|
92
|
+
# ------------------------------------------------------------------
|
|
62
93
|
# 给 agent 注册出图工具(`modelscope_draw_image`)。**与上面的
|
|
63
94
|
# registerProvider 是两条独立开关**:那个管「魔搭作为 chat provider」,
|
|
64
95
|
# 这个管「agent 能不能出图」。默认同样关(opt-in)。
|