@duke-dsh-plugins/dsh-token-stats 1.7.0 → 1.7.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/client.js +77 -23
- package/package.json +1 -1
package/client.js
CHANGED
|
@@ -72,7 +72,7 @@ window.__ModuleLoader__.load({
|
|
|
72
72
|
.ts-legend-val{color:var(--dsw-alias-label-secondary);white-space:nowrap}
|
|
73
73
|
.ts-heat{stroke:var(--dsw-alias-border-l1);stroke-width:0.5}
|
|
74
74
|
.ts-quota{position:relative;display:inline-flex}
|
|
75
|
-
.ts-quota-pop{position:absolute;bottom:calc(100% + 8px);right:0;width:230px;box-sizing:border-box;background:var(--dsw-alias-bg-overlay);border:1px solid var(--dsw-alias-border-l1);border-radius:10px;box-shadow:var(--dsw-elevation-soft,0 6px 24px rgba(0,0,0,0.18));padding:10px 12px;display:flex;flex-direction:column;gap:6px;font-size:12px;line-height:18px;color:var(--dsw-alias-label-primary);z-index:60;pointer-events:none;animation:ts-pop-in .12s ease-out}
|
|
75
|
+
.ts-quota-pop{position:absolute;bottom:calc(100% + 8px);right:0;min-width:230px;max-width:340px;width:max-content;box-sizing:border-box;background:var(--dsw-alias-bg-overlay);border:1px solid var(--dsw-alias-border-l1);border-radius:10px;box-shadow:var(--dsw-elevation-soft,0 6px 24px rgba(0,0,0,0.18));padding:10px 12px;display:flex;flex-direction:column;gap:6px;font-size:12px;line-height:18px;color:var(--dsw-alias-label-primary);z-index:60;pointer-events:none;animation:ts-pop-in .12s ease-out}
|
|
76
76
|
.ts-quota-pop-head{display:flex;align-items:center;justify-content:space-between;gap:12px;font-weight:600;font-size:12px}
|
|
77
77
|
.ts-quota-pop-sub{color:var(--dsw-alias-label-secondary);font-size:11px}
|
|
78
78
|
.ts-quota-pop-row{display:flex;align-items:center;justify-content:space-between;gap:12px;color:var(--dsw-alias-label-secondary)}
|
|
@@ -754,6 +754,15 @@ window.__ModuleLoader__.load({
|
|
|
754
754
|
];
|
|
755
755
|
}
|
|
756
756
|
|
|
757
|
+
/** 悬浮窗标题行(QuotaHoverCard 与加载态共用)。 */
|
|
758
|
+
function quotaPopHead(label) {
|
|
759
|
+
return React.createElement(
|
|
760
|
+
"div", { className: "ts-quota-pop-head" },
|
|
761
|
+
React.createElement("span", null, label),
|
|
762
|
+
React.createElement("span", { className: "ts-quota-pop-sub" }, "套餐余额"),
|
|
763
|
+
);
|
|
764
|
+
}
|
|
765
|
+
|
|
757
766
|
/** 自定义悬停面板 (替代原生 title): 结构化展示余额/窗口用量 + 进度条. */
|
|
758
767
|
function QuotaHoverCard(props) {
|
|
759
768
|
const label = quotaProviderLabel(props.provider);
|
|
@@ -761,10 +770,12 @@ window.__ModuleLoader__.load({
|
|
|
761
770
|
if (props.ok && props.display) {
|
|
762
771
|
const d = props.display;
|
|
763
772
|
if (typeof d.balanceText === "string" && d.balanceText) {
|
|
764
|
-
// mimo 的 balanceText
|
|
773
|
+
// mimo 的 balanceText 可能是「本地用量」(今日/7d 自带说明)也可能是官方「剩余 X%」。
|
|
765
774
|
const cap =
|
|
766
775
|
props.provider === "mimo"
|
|
767
|
-
? (typeof d.weeklyPct === "number"
|
|
776
|
+
? (typeof d.weeklyPct === "number" || typeof d.fiveHrPct === "number"
|
|
777
|
+
? "官方剩余用量"
|
|
778
|
+
: "本地用量")
|
|
768
779
|
: "账户余额" + (d.currency ? " (" + d.currency + ")" : "");
|
|
769
780
|
rows.push(
|
|
770
781
|
React.createElement(
|
|
@@ -774,15 +785,29 @@ window.__ModuleLoader__.load({
|
|
|
774
785
|
),
|
|
775
786
|
);
|
|
776
787
|
}
|
|
777
|
-
// mimo
|
|
778
|
-
//
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
788
|
+
// mimo 窗口行:新端点 /api/v1/user/usage(percent=剩余,host 换算成已用%)
|
|
789
|
+
// 把单一窗口放在 weeklyPct;旧端点 tokenPlan/usage 回退路径把套餐已用放在
|
|
790
|
+
// fiveHrPct(套餐与月度同额度时 weeklyPct 被去重为 null)。两个都认,缺一
|
|
791
|
+
// 不跳过——v1.7.0 只读 weeklyPct,导致旧端点形状下悬浮窗只剩标题(无进度条
|
|
792
|
+
// 无重置时间,设置页却有)。两者都在且数值不同时显示两行(套餐 + 本月)。
|
|
793
|
+
let windows;
|
|
794
|
+
if (props.provider === "mimo") {
|
|
795
|
+
windows = [];
|
|
796
|
+
if (typeof d.fiveHrPct === "number") {
|
|
797
|
+
windows.push(["Token Plan", d.fiveHrPct, d.fiveHrResetsIn]);
|
|
798
|
+
}
|
|
799
|
+
if (typeof d.weeklyPct === "number") {
|
|
800
|
+
const dup = windows.length > 0 && Math.abs(d.weeklyPct - d.fiveHrPct) < 0.5;
|
|
801
|
+
if (!dup) {
|
|
802
|
+
windows.push([windows.length > 0 ? "本月" : "Token Plan", d.weeklyPct, d.weeklyResetsIn]);
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
} else {
|
|
806
|
+
windows = [
|
|
807
|
+
["5h 窗口", d.fiveHrPct, d.fiveHrResetsIn],
|
|
808
|
+
["7d 窗口", d.weeklyPct, d.weeklyResetsIn],
|
|
809
|
+
];
|
|
810
|
+
}
|
|
786
811
|
for (const w of windows) {
|
|
787
812
|
if (typeof w[1] !== "number") continue;
|
|
788
813
|
rows.push(
|
|
@@ -800,18 +825,19 @@ window.__ModuleLoader__.load({
|
|
|
800
825
|
),
|
|
801
826
|
);
|
|
802
827
|
}
|
|
828
|
+
if (rows.length === 0) {
|
|
829
|
+
// 兜底:display 在但没有任何可渲染字段时也给一行,悬浮窗不能只剩标题。
|
|
830
|
+
rows.push(
|
|
831
|
+
React.createElement(
|
|
832
|
+
"div", { key: "empty", className: "ts-quota-pop-row" },
|
|
833
|
+
React.createElement("span", null, "暂无配额数据"),
|
|
834
|
+
),
|
|
835
|
+
);
|
|
836
|
+
}
|
|
803
837
|
} else {
|
|
804
838
|
rows.push(React.createElement("div", { key: "err", className: "ts-quota-pop-err" }, props.message || "获取失败"));
|
|
805
839
|
}
|
|
806
|
-
return React.createElement(
|
|
807
|
-
"div", { className: "ts-quota-pop" },
|
|
808
|
-
React.createElement(
|
|
809
|
-
"div", { className: "ts-quota-pop-head" },
|
|
810
|
-
React.createElement("span", null, label),
|
|
811
|
-
React.createElement("span", { className: "ts-quota-pop-sub" }, "套餐余额"),
|
|
812
|
-
),
|
|
813
|
-
...rows,
|
|
814
|
-
);
|
|
840
|
+
return React.createElement("div", { className: "ts-quota-pop" }, quotaPopHead(label), ...rows);
|
|
815
841
|
}
|
|
816
842
|
|
|
817
843
|
function QuotaReadout(props) {
|
|
@@ -920,11 +946,22 @@ window.__ModuleLoader__.load({
|
|
|
920
946
|
: null;
|
|
921
947
|
|
|
922
948
|
if (!state.loaded) {
|
|
949
|
+
// 加载态也渲染悬浮窗(此前只有一行 ···,悬停时面板完全不出)。
|
|
923
950
|
return React.createElement(
|
|
924
951
|
"div",
|
|
925
952
|
Object.assign({ className: "ts-quota", style: containerStyle }, hoverProps),
|
|
926
953
|
React.createElement("span", { style: { fontWeight: 500 } }, label),
|
|
927
954
|
React.createElement("span", { style: { opacity: 0.6, fontSize: 10 } }, "···"),
|
|
955
|
+
hover
|
|
956
|
+
? React.createElement(
|
|
957
|
+
"div", { className: "ts-quota-pop" },
|
|
958
|
+
quotaPopHead(label),
|
|
959
|
+
React.createElement(
|
|
960
|
+
"div", { className: "ts-quota-pop-row" },
|
|
961
|
+
React.createElement("span", null, "加载中…"),
|
|
962
|
+
),
|
|
963
|
+
)
|
|
964
|
+
: null,
|
|
928
965
|
);
|
|
929
966
|
}
|
|
930
967
|
|
|
@@ -981,8 +1018,24 @@ window.__ModuleLoader__.load({
|
|
|
981
1018
|
// mimo 复用 balanceText 承载两种读数:本地用量(无窗口百分比)或
|
|
982
1019
|
// 官方「剩余 X%」(有 weeklyPct),所以标题不能写死「账户余额」。
|
|
983
1020
|
const head = p === "mimo"
|
|
984
|
-
? (typeof d.weeklyPct === "number" ? "Token Plan" : "本地用量")
|
|
1021
|
+
? ((typeof d.weeklyPct === "number" || typeof d.fiveHrPct === "number") ? "Token Plan" : "本地用量")
|
|
985
1022
|
: "账户余额" + (d.currency ? " · " + d.currency : "");
|
|
1023
|
+
// 官方读数(新端点)把单一窗口放在 weeklyPct:数值下面补进度条 + 重置时间,
|
|
1024
|
+
// 与其它 provider 的窗口卡片及悬浮窗对齐。
|
|
1025
|
+
const planWindow = p === "mimo" && typeof d.weeklyPct === "number"
|
|
1026
|
+
? React.createElement(
|
|
1027
|
+
"div", { style: { display: "flex", flexDirection: "column", gap: 4 } },
|
|
1028
|
+
React.createElement(
|
|
1029
|
+
"div", { className: "ts-quota-pop-row" },
|
|
1030
|
+
React.createElement("span", null, "Token Plan已用"),
|
|
1031
|
+
React.createElement("b", null, d.weeklyPct + "%" + (d.weeklyResetsIn ? " · " + d.weeklyResetsIn : "")),
|
|
1032
|
+
),
|
|
1033
|
+
React.createElement(
|
|
1034
|
+
"div", { className: "ts-quota-card-bar" },
|
|
1035
|
+
React.createElement("i", { style: { width: Math.max(0, Math.min(100, d.weeklyPct)) + "%" } }),
|
|
1036
|
+
),
|
|
1037
|
+
)
|
|
1038
|
+
: null;
|
|
986
1039
|
return React.createElement(
|
|
987
1040
|
"div", { className: "ts-card ts-quota-card" },
|
|
988
1041
|
React.createElement(
|
|
@@ -991,12 +1044,13 @@ window.__ModuleLoader__.load({
|
|
|
991
1044
|
React.createElement("span", { className: "ts-quota-card-status" }, head),
|
|
992
1045
|
),
|
|
993
1046
|
React.createElement("div", { className: "ts-quota-card-value" }, d.balanceText),
|
|
1047
|
+
planWindow,
|
|
994
1048
|
);
|
|
995
1049
|
}
|
|
996
1050
|
const windows =
|
|
997
1051
|
p === "mimo"
|
|
998
1052
|
? [
|
|
999
|
-
["
|
|
1053
|
+
["套餐", d.fiveHrPct, d.fiveHrResetsIn],
|
|
1000
1054
|
["本月总额度", d.weeklyPct, d.weeklyResetsIn],
|
|
1001
1055
|
]
|
|
1002
1056
|
: [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@duke-dsh-plugins/dsh-token-stats",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.1",
|
|
4
4
|
"description": "Token usage statistics for DeepSeek Harness (7/30-day per-model charts + yearly heatmap) plus an inline coding-plan balance/quota readout in the composer (minimax/deepseek/kimi/openrouter/zhipu/mimo; mimo falls back to local usage since MiMo exposes no API-key quota API).",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|