dsh-model-usage 0.8.4 → 0.8.6
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 +8 -0
- package/README.md +4 -0
- package/lib/client.js +93 -21
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this package are documented in this file. Versions follow Semantic Versioning.
|
|
4
4
|
|
|
5
|
+
## 0.8.6
|
|
6
|
+
|
|
7
|
+
- Documentation: recommend `dsh-assistant-suite` for new installations and explain migration.
|
|
8
|
+
|
|
9
|
+
## 0.8.5
|
|
10
|
+
|
|
11
|
+
- Balance spend trend: add a centered enlarged chart view, a points-only toggle, and clearer spacing between dense ten-minute samples.
|
|
12
|
+
|
|
5
13
|
## 0.8.4
|
|
6
14
|
|
|
7
15
|
- Command Code balance history: sample on ten-minute clock marks, retain the current and two
|
package/README.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# dsh-model-usage
|
|
2
2
|
|
|
3
|
+
> **推荐使用 [dsh-assistant-suite](https://github.com/liuchaoxu/dsh-assistant-suite):** 本插件的用量查询能力已整合进助手套件,并新增系统提醒、Command Code 余额趋势和统一设置。新安装建议直接使用套件;从本插件迁移时,请停用本插件,避免重复用量入口。
|
|
4
|
+
|
|
5
|
+
> **Recommended: [dsh-assistant-suite](https://github.com/liuchaoxu/dsh-assistant-suite).** It includes this plugin's usage features alongside system notifications, Command Code balance history, and unified settings. New installations should use the suite. Disable this standalone plugin after migrating to avoid duplicate usage entries.
|
|
6
|
+
|
|
3
7
|
Provider-account usage for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)
|
|
4
8
|
sessions. The plugin adds a **Usage** (`用量`) entry to the session header and reports the quota
|
|
5
9
|
windows, balance and request counters of the provider account behind the model the conversation is
|
package/lib/client.js
CHANGED
|
@@ -122,6 +122,8 @@ window.__ModuleLoader__.load({
|
|
|
122
122
|
"card.hideRaw": "隐藏原始返回",
|
|
123
123
|
"card.unrecognized": "接口返回的字段还没被识别,下面是原始返回(可以发给我做校准)",
|
|
124
124
|
"history.title": "余额消耗趋势",
|
|
125
|
+
"history.expand": "全屏查看余额消耗趋势",
|
|
126
|
+
"history.pointsOnly": "仅显示消耗点",
|
|
125
127
|
"history.range.today": "今天",
|
|
126
128
|
"history.range.yesterday": "昨天",
|
|
127
129
|
"history.range.week": "近一周",
|
|
@@ -240,6 +242,8 @@ window.__ModuleLoader__.load({
|
|
|
240
242
|
"card.hideRaw": "Hide raw response",
|
|
241
243
|
"card.unrecognized": "These fields are not recognized yet — the raw response is below (send it over to calibrate)",
|
|
242
244
|
"history.title": "Balance spend trend",
|
|
245
|
+
"history.expand": "View balance spend trend full screen",
|
|
246
|
+
"history.pointsOnly": "Show points only",
|
|
243
247
|
"history.range.today": "Today",
|
|
244
248
|
"history.range.yesterday": "Yesterday",
|
|
245
249
|
"history.range.week": "Last 7 days",
|
|
@@ -380,13 +384,27 @@ window.__ModuleLoader__.load({
|
|
|
380
384
|
".dsh-usage-history-ranges { display: inline-flex; align-self: flex-start; gap: 2px; padding: 3px; border: 1px solid var(--dsw-alias-border-l2); border-radius: 10px; background: var(--dsw-alias-bg-layer-2); flex-wrap: wrap; }",
|
|
381
385
|
".dsh-usage-history-ranges .dsh-usage-mode-btn { min-height: 27px; padding: 0 10px; border-color: transparent; border-radius: 7px; background: transparent; font-size: 11px; }",
|
|
382
386
|
".dsh-usage-history-ranges .dsh-usage-mode-btn-active { background: var(--dsw-alias-bg-layer-1); border-color: var(--dsw-alias-border-l2); color: var(--dsw-alias-label-primary); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.14); }",
|
|
387
|
+
".dsh-usage-history-controls { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }",
|
|
388
|
+
".dsh-usage-history-points-toggle { display: inline-flex; align-items: center; gap: 7px; color: var(--dsw-alias-label-secondary); font-size: 12px; line-height: 18px; cursor: pointer; user-select: none; }",
|
|
389
|
+
".dsh-usage-history-points-toggle input { appearance: none; position: relative; width: 30px; height: 18px; flex: 0 0 30px; margin: 0; border: 1px solid var(--dsw-alias-border-l2); border-radius: 999px; background: var(--dsw-alias-bg-layer-2); cursor: pointer; transition: background 140ms ease, border-color 140ms ease; }",
|
|
390
|
+
".dsh-usage-history-points-toggle input::after { content: ''; position: absolute; top: 2px; left: 2px; width: 12px; height: 12px; border-radius: 50%; background: var(--dsw-alias-bg-layer-1); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); transition: transform 140ms ease; }",
|
|
391
|
+
".dsh-usage-history-points-toggle input:checked { border-color: #0A84FF; background: #0A84FF; }",
|
|
392
|
+
".dsh-usage-history-points-toggle input:checked::after { transform: translateX(12px); }",
|
|
393
|
+
".dsh-usage-history-points-toggle input:focus-visible { outline: 2px solid rgba(10, 132, 255, 0.45); outline-offset: 2px; }",
|
|
383
394
|
".dsh-usage-history-form { display: flex; align-items: end; gap: 6px; flex-wrap: wrap; }",
|
|
384
395
|
".dsh-usage-history-date { display: flex; flex-direction: column; gap: 3px; color: var(--dsw-alias-label-secondary); font-size: 11px; line-height: 16px; }",
|
|
385
396
|
".dsh-usage-history-date input, .dsh-usage-history-month { height: 30px; min-width: 112px; padding: 0 8px; border: 1px solid var(--dsw-alias-border-l2); border-radius: 8px; background: var(--dsw-alias-bg-layer-1); color: var(--dsw-alias-label-primary); font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Segoe UI', sans-serif; font-size: 12px; }",
|
|
386
397
|
".dsh-usage-history-date input:focus, .dsh-usage-history-month:focus, .dsh-usage-input:focus { outline: 2px solid rgba(10, 132, 255, 0.45); outline-offset: 1px; }",
|
|
387
398
|
".dsh-usage-history-manage { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }",
|
|
388
399
|
".dsh-usage-history-manage .dsh-usage-action { height: 28px; padding: 0 9px; font-size: 11px; }",
|
|
389
|
-
".dsh-usage-history-chart { width: 100%; height:
|
|
400
|
+
".dsh-usage-history-chart { display: block; width: 100%; height: auto; aspect-ratio: 360 / 132; max-height: 220px; overflow: visible; }",
|
|
401
|
+
".dsh-usage-history-chart-trigger { display: block; width: 100%; padding: 0; border: 0; border-radius: 8px; background: transparent; cursor: zoom-in; }",
|
|
402
|
+
".dsh-usage-history-chart-trigger:focus-visible { outline: 2px solid #0A84FF; outline-offset: 3px; }",
|
|
403
|
+
".dsh-usage-history-fullscreen-dialog { width: min(960px, 88vw); height: min(480px, 60vh); max-height: calc(100dvh - 40px); }",
|
|
404
|
+
".dsh-usage-history-fullscreen-content { display: flex; flex: 1 1 auto; min-height: 0; flex-direction: column; gap: 12px; padding: 14px 18px 18px; overflow: auto; }",
|
|
405
|
+
".dsh-usage-history-fullscreen-content .dsh-usage-history-chart { width: 100%; height: min(34vh, 300px); min-height: 200px; max-height: none; aspect-ratio: auto; }",
|
|
406
|
+
".dsh-usage-history-fullscreen-content .dsh-usage-history-ranges { align-self: flex-start; }",
|
|
407
|
+
"@media (max-width: 640px) { .dsh-usage-history-fullscreen-dialog { width: calc(100vw - 24px); height: min(70vh, 560px); } .dsh-usage-history-fullscreen-content { padding: 12px 14px 16px; } .dsh-usage-history-fullscreen-content .dsh-usage-history-chart { height: max(32vh, 180px); min-height: 180px; } }",
|
|
390
408
|
".dsh-usage-history-empty { color: var(--dsw-alias-label-secondary); font-size: 12px; line-height: 18px; padding: 8px 0; }",
|
|
391
409
|
".dsh-usage-modal-body { max-height: max(140px, calc(100vh - 260px)); overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; scrollbar-color: var(--dsw-alias-border-l2) transparent; }",
|
|
392
410
|
".dsh-usage-provider-list { display: flex; flex-direction: column; border: 1px solid var(--dsw-alias-border-l2); border-radius: 12px; overflow: hidden; }",
|
|
@@ -664,7 +682,7 @@ window.__ModuleLoader__.load({
|
|
|
664
682
|
* re-running it there would steal focus every few seconds.
|
|
665
683
|
*/
|
|
666
684
|
function UsageModal(props) {
|
|
667
|
-
const { open, onClose, title, closeLabel, className, footer, children } = props;
|
|
685
|
+
const { open, onClose, title, closeLabel, className, overlayClassName, footer, children } = props;
|
|
668
686
|
const dialogRef = React.useRef(null);
|
|
669
687
|
const restoreRef = React.useRef(null);
|
|
670
688
|
const closeRef = React.useRef(onClose);
|
|
@@ -722,7 +740,7 @@ window.__ModuleLoader__.load({
|
|
|
722
740
|
|
|
723
741
|
if (!open) return null;
|
|
724
742
|
return React.createElement("div", {
|
|
725
|
-
className: "dsh-usage-modal-overlay",
|
|
743
|
+
className: "dsh-usage-modal-overlay" + (overlayClassName ? ` ${overlayClassName}` : ""),
|
|
726
744
|
onMouseDown: (event) => { if (event.target === event.currentTarget) closeRef.current(); },
|
|
727
745
|
},
|
|
728
746
|
React.createElement("div", {
|
|
@@ -836,6 +854,8 @@ window.__ModuleLoader__.load({
|
|
|
836
854
|
}
|
|
837
855
|
|
|
838
856
|
function BalanceHistory({ points, range, customRange, appliedCustomRange, selectedMonth, onRange, onCustomRange, onApplyCustomRange, onSelectMonth, onClearMonth, onReset, t }) {
|
|
857
|
+
const [expanded, setExpanded] = React.useState(false);
|
|
858
|
+
const [pointsOnly, setPointsOnly] = React.useState(false);
|
|
839
859
|
const now = Date.now();
|
|
840
860
|
const todayStart = new Date(new Date(now).setHours(0, 0, 0, 0)).getTime();
|
|
841
861
|
let start = todayStart;
|
|
@@ -888,44 +908,81 @@ window.__ModuleLoader__.load({
|
|
|
888
908
|
const x = 42 + ratio * 306;
|
|
889
909
|
const value = start + ratio * span;
|
|
890
910
|
children.push(
|
|
891
|
-
React.createElement("line", { key: `grid-${index}`, x1: x, x2: x, y1:
|
|
911
|
+
React.createElement("line", { key: `grid-${index}`, x1: x, x2: x, y1: 26, y2: 104, stroke: "var(--dsw-alias-border-l2)", strokeWidth: 1, strokeOpacity: 0.32, strokeDasharray: "2 4" }),
|
|
892
912
|
React.createElement("text", { key: `tick-${index}`, x, y: 126, textAnchor: index === 0 ? "start" : index === tickCount - 1 ? "end" : "middle", fill: "var(--dsw-alias-label-secondary)", fontSize: 10 }, tickLabel(value)),
|
|
893
913
|
);
|
|
894
914
|
}
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
915
|
+
for (let index = 0; index <= 4; index += 1) {
|
|
916
|
+
const ratio = index / 4;
|
|
917
|
+
const y = 104 - ratio * 78;
|
|
918
|
+
children.push(
|
|
919
|
+
React.createElement("line", { key: `amount-grid-${index}`, x1: 42, x2: 348, y1: y, y2: y, stroke: "var(--dsw-alias-border-l2)", strokeWidth: 1, strokeOpacity: 0.62 }),
|
|
920
|
+
React.createElement("text", { key: `amount-${index}`, x: 36, y: y + 3, textAnchor: "end", fill: "var(--dsw-alias-label-secondary)", fontSize: 9 }, `$${(maxSpend * ratio).toFixed(2)}`),
|
|
921
|
+
);
|
|
922
|
+
}
|
|
899
923
|
if (chartPoints.length > 0) {
|
|
900
|
-
children.push(React.createElement("polyline", {
|
|
924
|
+
if (!pointsOnly) children.push(React.createElement("polyline", {
|
|
901
925
|
key: "line", points: chartPoints.map(({ x, y }) => `${x},${y}`).join(" "), fill: "none",
|
|
902
|
-
stroke: "var(--dsw-alias-state-success-primary)", strokeWidth:
|
|
926
|
+
stroke: "var(--dsw-alias-state-success-primary)", strokeWidth: 1.35,
|
|
927
|
+
vectorEffect: "non-scaling-stroke", strokeLinecap: "round", strokeLinejoin: "round",
|
|
903
928
|
}));
|
|
904
929
|
chartPoints.forEach(({ x, y, point }, index) => children.push(
|
|
905
930
|
React.createElement("g", { key: `point-${index}` },
|
|
906
|
-
React.createElement("circle", {
|
|
931
|
+
React.createElement("circle", {
|
|
932
|
+
cx: x, cy: y, r: 1.8,
|
|
933
|
+
fill: "var(--dsw-alias-state-success-primary)",
|
|
934
|
+
stroke: "var(--dsw-alias-bg-layer-1)", strokeWidth: 1.4,
|
|
935
|
+
vectorEffect: "non-scaling-stroke",
|
|
936
|
+
}),
|
|
907
937
|
React.createElement("title", null, `${new Date(point.at).toLocaleString()} · $${point.spend.toFixed(2)}`),
|
|
908
938
|
),
|
|
909
939
|
));
|
|
910
940
|
}
|
|
911
941
|
const months = storedMonths(points);
|
|
912
942
|
const activeMonth = months.includes(selectedMonth) ? selectedMonth : (months[0] ?? "");
|
|
943
|
+
const rangeControls = React.createElement("div", { className: "dsh-usage-history-controls" },
|
|
944
|
+
React.createElement("div", { className: "dsh-usage-history-ranges" }, HISTORY_RANGES.map((item) =>
|
|
945
|
+
React.createElement("button", { key: item, type: "button", className: "dsh-usage-mode-btn" + (range === item ? " dsh-usage-mode-btn-active" : ""), onClick: () => onRange(item) }, t(`history.range.${item}`)))),
|
|
946
|
+
React.createElement("label", { className: "dsh-usage-history-points-toggle" },
|
|
947
|
+
React.createElement("input", {
|
|
948
|
+
type: "checkbox",
|
|
949
|
+
role: "switch",
|
|
950
|
+
checked: pointsOnly,
|
|
951
|
+
onChange: (event) => setPointsOnly(event.target.checked),
|
|
952
|
+
"aria-label": t("history.pointsOnly"),
|
|
953
|
+
}),
|
|
954
|
+
t("history.pointsOnly"),
|
|
955
|
+
),
|
|
956
|
+
);
|
|
957
|
+
const customRangeForm = range === "custom"
|
|
958
|
+
? React.createElement("div", { className: "dsh-usage-history-form" },
|
|
959
|
+
React.createElement("label", { className: "dsh-usage-history-date" }, t("history.start"), React.createElement("input", { type: "date", value: customRange.start, onChange: (event) => onCustomRange({ ...customRange, start: event.target.value }) })),
|
|
960
|
+
React.createElement("label", { className: "dsh-usage-history-date" }, t("history.end"), React.createElement("input", { type: "date", value: customRange.end, onChange: (event) => onCustomRange({ ...customRange, end: event.target.value }) })),
|
|
961
|
+
React.createElement(ActionButton, { variant: "outline", onClick: onApplyCustomRange }, t("history.apply")),
|
|
962
|
+
)
|
|
963
|
+
: null;
|
|
964
|
+
const chart = (className, isExpanded = false) => React.createElement("svg", {
|
|
965
|
+
className,
|
|
966
|
+
viewBox: "0 0 360 132",
|
|
967
|
+
preserveAspectRatio: isExpanded ? "none" : "xMidYMid meet",
|
|
968
|
+
role: "img",
|
|
969
|
+
"aria-label": t("history.title"),
|
|
970
|
+
}, children);
|
|
913
971
|
return React.createElement("div", { className: "dsh-usage-balance-card dsh-usage-history" },
|
|
914
972
|
React.createElement("div", { className: "dsh-usage-history-head" },
|
|
915
973
|
React.createElement("span", { className: "dsh-usage-history-title" }, t("history.title")),
|
|
916
974
|
visible.length > 0 ? React.createElement("span", { className: "dsh-usage-balance-status" }, `${t("history.amount")} $${sum.toFixed(2)}`) : null,
|
|
917
975
|
),
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
range === "custom"
|
|
921
|
-
? React.createElement("div", { className: "dsh-usage-history-form" },
|
|
922
|
-
React.createElement("label", { className: "dsh-usage-history-date" }, t("history.start"), React.createElement("input", { type: "date", value: customRange.start, onChange: (event) => onCustomRange({ ...customRange, start: event.target.value }) })),
|
|
923
|
-
React.createElement("label", { className: "dsh-usage-history-date" }, t("history.end"), React.createElement("input", { type: "date", value: customRange.end, onChange: (event) => onCustomRange({ ...customRange, end: event.target.value }) })),
|
|
924
|
-
React.createElement(ActionButton, { variant: "outline", onClick: onApplyCustomRange }, t("history.apply")),
|
|
925
|
-
)
|
|
926
|
-
: null,
|
|
976
|
+
rangeControls,
|
|
977
|
+
customRangeForm,
|
|
927
978
|
visible.length > 0
|
|
928
|
-
? React.createElement("
|
|
979
|
+
? React.createElement("button", {
|
|
980
|
+
type: "button",
|
|
981
|
+
className: "dsh-usage-history-chart-trigger",
|
|
982
|
+
title: t("history.expand"),
|
|
983
|
+
"aria-label": t("history.expand"),
|
|
984
|
+
onClick: () => setExpanded(true),
|
|
985
|
+
}, chart("dsh-usage-history-chart"))
|
|
929
986
|
: React.createElement("div", { className: "dsh-usage-history-empty" }, t("history.empty")),
|
|
930
987
|
React.createElement("div", { className: "dsh-usage-history-manage" },
|
|
931
988
|
React.createElement("span", { className: "dsh-usage-history-title" }, t("history.month")),
|
|
@@ -935,6 +992,21 @@ window.__ModuleLoader__.load({
|
|
|
935
992
|
months.length > 0 ? React.createElement(ActionButton, { variant: "ghost", onClick: () => onClearMonth(activeMonth) }, t("history.clearMonth")) : null,
|
|
936
993
|
React.createElement(ActionButton, { variant: "ghost", onClick: onReset }, t("history.reset")),
|
|
937
994
|
),
|
|
995
|
+
React.createElement(UsageModal, {
|
|
996
|
+
open: expanded,
|
|
997
|
+
onClose: () => setExpanded(false),
|
|
998
|
+
title: t("history.title"),
|
|
999
|
+
closeLabel: t("action.close"),
|
|
1000
|
+
className: "dsh-usage-history-fullscreen-dialog",
|
|
1001
|
+
overlayClassName: "dsh-usage-history-fullscreen-overlay",
|
|
1002
|
+
},
|
|
1003
|
+
React.createElement("div", { className: "dsh-usage-history-fullscreen-content" },
|
|
1004
|
+
rangeControls,
|
|
1005
|
+
customRangeForm,
|
|
1006
|
+
React.createElement("span", { className: "dsh-usage-balance-status" }, `${t("history.amount")} $${sum.toFixed(2)}`),
|
|
1007
|
+
visible.length > 0 ? chart("dsh-usage-history-chart", true) : React.createElement("div", { className: "dsh-usage-history-empty" }, t("history.empty")),
|
|
1008
|
+
),
|
|
1009
|
+
),
|
|
938
1010
|
);
|
|
939
1011
|
}
|
|
940
1012
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-model-usage",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.6",
|
|
4
4
|
"description": "Provider-account usage for DeepSeek Harness: quota windows, credit balance and request counts for the model a conversation runs on, with per-provider adapters and manual target selection.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "liuchaoxu <ischaoxu@163.com>",
|