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 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: 148px; overflow: visible; }",
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: 20, y2: 108, stroke: "var(--dsw-alias-border-l2)", strokeWidth: 1 }),
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
- children.push(
896
- React.createElement("text", { key: "y-max", x: 36, y: 25, textAnchor: "end", fill: "var(--dsw-alias-label-secondary)", fontSize: 10 }, `$${maxSpend.toFixed(2)}`),
897
- React.createElement("text", { key: "y-zero", x: 36, y: 108, textAnchor: "end", fill: "var(--dsw-alias-label-secondary)", fontSize: 10 }, "$0"),
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: 2.5, strokeLinecap: "round", strokeLinejoin: "round",
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", { cx: x, cy: y, r: 3.5, fill: "var(--dsw-alias-state-success-primary)" }),
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
- React.createElement("div", { className: "dsh-usage-history-ranges" }, HISTORY_RANGES.map((item) =>
919
- 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}`)))),
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("svg", { className: "dsh-usage-history-chart", viewBox: "0 0 360 132", role: "img", "aria-label": t("history.title") }, children)
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.4",
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>",