@dsh-agent-toolkit/token-usage 0.2.0 → 0.3.0

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/lib/client.js CHANGED
@@ -39,8 +39,8 @@ window.__ModuleLoader__.load({
39
39
  };
40
40
  var __toCommonJS = (mod) => __hasOwnProp.call(mod, "module.exports") ? mod["module.exports"] : __copyProps(__defProp({}, "__esModule", { value: true }), mod);
41
41
  //#endregion
42
- let react = require("react");
43
42
  let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
43
+ let react = require("react");
44
44
  let react_jsx_runtime = require("react/jsx-runtime");
45
45
  //#region ../../node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
46
46
  function r(e) {
@@ -57,7 +57,52 @@ window.__ModuleLoader__.load({
57
57
  return n;
58
58
  }
59
59
  //#endregion
60
- //#region src/aggregate.ts
60
+ //#region \0dsh-css:D:\work\github\dsh\dsh-agent-toolkit\packages\usage\src\client\shared\entry.module.css.mjs
61
+ const css$3 = ".QVHFVG_trigger{box-sizing:border-box;cursor:pointer;width:auto;height:42px;color:var(--dsw-alias-label-primary);background:0 0;border:none;border-radius:12px;flex:none;align-items:center;gap:8px;margin:4px 0;padding:0 8px;font-family:inherit;font-size:14px;line-height:22px;display:flex;overflow:hidden}.QVHFVG_trigger:hover{background:var(--dsw-alias-interactive-bg-hover)}.QVHFVG_trigger.QVHFVG_rail{border-radius:50%;justify-content:center;gap:0;width:36px;height:36px;margin:8px 0 10px;padding:0}";
62
+ const tagId$3 = "@dsh-agent-toolkit/token-usage/entry.module.css-27285725";
63
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$3) + "]") === null) {
64
+ const tag = document.createElement("style");
65
+ tag.dataset.plugin = "@dsh-agent-toolkit/token-usage";
66
+ tag.dataset.pluginCss = tagId$3;
67
+ tag.textContent = css$3;
68
+ document.head.appendChild(tag);
69
+ }
70
+ var entry_module_css_default = {
71
+ "rail": "QVHFVG_rail",
72
+ "trigger": "QVHFVG_trigger"
73
+ };
74
+ //#endregion
75
+ //#region src/client/shared/entry.tsx
76
+ /** 侧边栏底栏入口工厂:宽栏窄栏统一仅图标 + Tooltip,点击经 renderModal 打开模态框。 */
77
+ function createSidebarEntry(deps) {
78
+ const { icon, title, renderModal } = deps;
79
+ return function SidebarEntry(props) {
80
+ const { wide } = props;
81
+ const extra = props;
82
+ const [open, setOpen] = (0, react.useState)(false);
83
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
84
+ label: title,
85
+ delayMs: 500,
86
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
87
+ type: "button",
88
+ className: clsx(entry_module_css_default.trigger, !wide && entry_module_css_default.rail),
89
+ "aria-label": title,
90
+ onClick: () => {
91
+ setOpen(true);
92
+ },
93
+ children: icon
94
+ })
95
+ }), renderModal({
96
+ open,
97
+ onClose: () => {
98
+ setOpen(false);
99
+ },
100
+ ...extra
101
+ })] });
102
+ };
103
+ }
104
+ //#endregion
105
+ //#region src/usage/aggregate.ts
61
106
  /** 桶的计费总量(含估算)。 */
62
107
  function billedOf(b) {
63
108
  return b.input + b.output + b.cacheRead + b.cacheWrite + b.estimated;
@@ -83,7 +128,7 @@ window.__ModuleLoader__.load({
83
128
  return unit === 0 ? String(n) : `${value.toFixed(1)}${units[unit]}`;
84
129
  }
85
130
  //#endregion
86
- //#region src/heatmap.ts
131
+ //#region src/usage/heatmap.ts
87
132
  const DAY_MS = 864e5;
88
133
  /** 分档:0 用量 → 0;非零按 max 线性 1..4 档(max <= 0 时兜底 1)。 */
89
134
  function levelOf(billed, max) {
@@ -123,48 +168,79 @@ window.__ModuleLoader__.load({
123
168
  return denom === 0 ? null : totals.cacheRead / denom;
124
169
  }
125
170
  //#endregion
126
- //#region \0dsh-css:D:\work\github\dsh\dsh-agent-toolkit\packages\token-usage\src\client\chart.module.css.mjs
127
- const css$3 = ".IhkY8q_chartTheme{--chart-1:var(--dsw-alias-state-business-primary);--chart-2:var(--dsw-alias-state-business-tertiary);--chart-label:var(--dsw-alias-label-tertiary);--chart-empty:var(--dsw-alias-bg-skeleton)}.IhkY8q_tooltip{background:var(--dsw-alias-bg-overlay);color:var(--dsw-alias-label-primary);border-radius:8px;padding:6px 10px;font-size:12px;line-height:18px;box-shadow:0 2px 8px #00000026}.IhkY8q_tooltipTitle{color:var(--dsw-alias-label-secondary)}.IhkY8q_tooltipTotal{margin-top:2px;font-weight:600}.IhkY8q_legend{color:var(--dsw-alias-label-secondary);justify-content:center;gap:16px;margin-top:4px;font-size:12px;line-height:18px;display:flex}.IhkY8q_legend i{border-radius:2px;width:8px;height:8px;margin-right:4px;display:inline-block}.IhkY8q_swatchFresh{background:var(--chart-1)}.IhkY8q_swatchCached{background:var(--chart-2)}";
128
- const tagId$3 = "@dsh-agent-toolkit/token-usage/chart.module.css";
129
- if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$3) + "]") === null) {
171
+ //#region src/client/shared/load-state.ts
172
+ /** shared 数据加载状态机:loading/error/ok 三态 + stale 标志 + reload 计数器。 */
173
+ function useLoadState(load, deps) {
174
+ const [state, setState] = (0, react.useState)({ kind: "loading" });
175
+ const [tick, setTick] = (0, react.useState)(0);
176
+ (0, react.useEffect)(() => {
177
+ let stale = false;
178
+ setState({ kind: "loading" });
179
+ load().then((data) => {
180
+ if (!stale) setState({
181
+ kind: "ok",
182
+ data
183
+ });
184
+ }).catch((error) => {
185
+ if (!stale) setState({
186
+ kind: "error",
187
+ message: error instanceof Error ? error.message : String(error)
188
+ });
189
+ });
190
+ return () => {
191
+ stale = true;
192
+ };
193
+ }, [...deps, tick]);
194
+ return {
195
+ state,
196
+ reload: () => {
197
+ setTick((n) => n + 1);
198
+ }
199
+ };
200
+ }
201
+ //#endregion
202
+ //#region \0dsh-css:D:\work\github\dsh\dsh-agent-toolkit\packages\usage\src\client\usage\chart.module.css.mjs
203
+ const css$2 = "._8LXSJW_chartTheme{--chart-1:var(--dsw-alias-state-business-primary);--chart-2:var(--dsw-alias-state-business-tertiary);--chart-label:var(--dsw-alias-label-tertiary);--chart-empty:var(--dsw-alias-bg-skeleton)}._8LXSJW_tooltip{background:var(--dsw-alias-bg-overlay);color:var(--dsw-alias-label-primary);border-radius:8px;padding:6px 10px;font-size:12px;line-height:18px;box-shadow:0 2px 8px #00000026}._8LXSJW_tooltipTitle{color:var(--dsw-alias-label-secondary)}._8LXSJW_tooltipTotal{margin-top:2px;font-weight:600}._8LXSJW_legend{color:var(--dsw-alias-label-secondary);justify-content:center;gap:16px;margin-top:4px;font-size:12px;line-height:18px;display:flex}._8LXSJW_legend i{border-radius:2px;width:8px;height:8px;margin-right:4px;display:inline-block}._8LXSJW_swatchFresh{background:var(--chart-1)}._8LXSJW_swatchCached{background:var(--chart-2)}";
204
+ const tagId$2 = "@dsh-agent-toolkit/token-usage/chart.module.css-a305f9e5";
205
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$2) + "]") === null) {
130
206
  const tag = document.createElement("style");
131
207
  tag.dataset.plugin = "@dsh-agent-toolkit/token-usage";
132
- tag.dataset.pluginCss = tagId$3;
133
- tag.textContent = css$3;
208
+ tag.dataset.pluginCss = tagId$2;
209
+ tag.textContent = css$2;
134
210
  document.head.appendChild(tag);
135
211
  }
136
212
  var chart_module_css_default = {
137
- "chartTheme": "IhkY8q_chartTheme",
138
- "tooltipTotal": "IhkY8q_tooltipTotal",
139
- "legend": "IhkY8q_legend",
140
- "swatchFresh": "IhkY8q_swatchFresh",
141
- "swatchCached": "IhkY8q_swatchCached",
142
- "tooltip": "IhkY8q_tooltip",
143
- "tooltipTitle": "IhkY8q_tooltipTitle"
213
+ "tooltip": "_8LXSJW_tooltip",
214
+ "chartTheme": "_8LXSJW_chartTheme",
215
+ "tooltipTotal": "_8LXSJW_tooltipTotal",
216
+ "legend": "_8LXSJW_legend",
217
+ "swatchFresh": "_8LXSJW_swatchFresh",
218
+ "swatchCached": "_8LXSJW_swatchCached",
219
+ "tooltipTitle": "_8LXSJW_tooltipTitle"
144
220
  };
145
221
  //#endregion
146
- //#region \0dsh-css:D:\work\github\dsh\dsh-agent-toolkit\packages\token-usage\src\client\ActivityHeatmap.module.css.mjs
147
- const css$2 = ".s7NO0G_months{color:var(--dsw-alias-label-tertiary);grid-template-columns:repeat(13,1fr);gap:3px;margin-bottom:4px;font-size:11px;line-height:16px;display:grid}.s7NO0G_grid{grid-template-columns:repeat(13,1fr);gap:3px;display:grid}.s7NO0G_week{grid-template-rows:repeat(7,1fr);gap:3px;display:grid}.s7NO0G_week>div{aspect-ratio:1;border-radius:2px;width:100%}.s7NO0G_week>div[aria-disabled=true]{opacity:.35}.s7NO0G_week>.s7NO0G_level0{background:var(--chart-empty)}.s7NO0G_week>.s7NO0G_level1{background:color-mix(in srgb, var(--chart-1) 25%, transparent)}.s7NO0G_week>.s7NO0G_level2{background:color-mix(in srgb, var(--chart-1) 50%, transparent)}.s7NO0G_week>.s7NO0G_level3{background:color-mix(in srgb, var(--chart-1) 75%, transparent)}.s7NO0G_week>.s7NO0G_level4{background:var(--chart-1)}";
148
- const tagId$2 = "@dsh-agent-toolkit/token-usage/ActivityHeatmap.module.css";
149
- if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$2) + "]") === null) {
222
+ //#region \0dsh-css:D:\work\github\dsh\dsh-agent-toolkit\packages\usage\src\client\usage\ActivityHeatmap.module.css.mjs
223
+ const css$1 = ".hjrYrq_months{color:var(--dsw-alias-label-tertiary);grid-template-columns:repeat(13,1fr);gap:3px;margin-bottom:4px;font-size:11px;line-height:16px;display:grid}.hjrYrq_grid{grid-template-columns:repeat(13,1fr);gap:3px;display:grid}.hjrYrq_week{grid-template-rows:repeat(7,1fr);gap:3px;display:grid}.hjrYrq_week>div{aspect-ratio:1;border-radius:2px;width:100%}.hjrYrq_week>div[aria-disabled=true]{opacity:.35}.hjrYrq_week>.hjrYrq_level0{background:var(--chart-empty)}.hjrYrq_week>.hjrYrq_level1{background:color-mix(in srgb, var(--chart-1) 25%, transparent)}.hjrYrq_week>.hjrYrq_level2{background:color-mix(in srgb, var(--chart-1) 50%, transparent)}.hjrYrq_week>.hjrYrq_level3{background:color-mix(in srgb, var(--chart-1) 75%, transparent)}.hjrYrq_week>.hjrYrq_level4{background:var(--chart-1)}";
224
+ const tagId$1 = "@dsh-agent-toolkit/token-usage/ActivityHeatmap.module.css-aab58cb9";
225
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
150
226
  const tag = document.createElement("style");
151
227
  tag.dataset.plugin = "@dsh-agent-toolkit/token-usage";
152
- tag.dataset.pluginCss = tagId$2;
153
- tag.textContent = css$2;
228
+ tag.dataset.pluginCss = tagId$1;
229
+ tag.textContent = css$1;
154
230
  document.head.appendChild(tag);
155
231
  }
156
232
  var ActivityHeatmap_module_css_default = {
157
- "level2": "s7NO0G_level2",
158
- "level4": "s7NO0G_level4",
159
- "months": "s7NO0G_months",
160
- "grid": "s7NO0G_grid",
161
- "level0": "s7NO0G_level0",
162
- "week": "s7NO0G_week",
163
- "level3": "s7NO0G_level3",
164
- "level1": "s7NO0G_level1"
233
+ "week": "hjrYrq_week",
234
+ "level0": "hjrYrq_level0",
235
+ "months": "hjrYrq_months",
236
+ "level1": "hjrYrq_level1",
237
+ "grid": "hjrYrq_grid",
238
+ "level3": "hjrYrq_level3",
239
+ "level2": "hjrYrq_level2",
240
+ "level4": "hjrYrq_level4"
165
241
  };
166
242
  //#endregion
167
- //#region src/client/ActivityHeatmap.tsx
243
+ //#region src/client/usage/ActivityHeatmap.tsx
168
244
  function ActivityHeatmap({ today, days }) {
169
245
  const columns = heatmapGrid(today, days);
170
246
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -50408,7 +50484,7 @@ ${te.current.stack}
50408
50484
  } };
50409
50485
  }));
50410
50486
  //#endregion
50411
- //#region src/client/DailyBarChart.tsx
50487
+ //#region src/client/usage/DailyBarChart.tsx
50412
50488
  var import_lib = (/* @__PURE__ */ __commonJSMin(((exports) => {
50413
50489
  Object.defineProperty(exports, "__esModule", { value: true });
50414
50490
  Object.defineProperty(exports, "AnimationControllerProvider", {
@@ -51187,46 +51263,42 @@ ${te.current.stack}
51187
51263
  });
51188
51264
  }
51189
51265
  //#endregion
51190
- //#region \0dsh-css:D:\work\github\dsh\dsh-agent-toolkit\packages\token-usage\src\client\UsageModal.module.css.mjs
51191
- const css$1 = ".DGSElG_dialog.DGSElG_dialog{width:min(720px,100%)}.DGSElG_pager{justify-content:flex-start;align-items:center;gap:8px;display:flex}.DGSElG_pagerButton{cursor:pointer;width:28px;height:28px;color:var(--dsw-alias-label-primary);background:0 0;border:none;border-radius:8px;justify-content:center;align-items:center;font-family:inherit;font-size:14px;line-height:20px;display:inline-flex}.DGSElG_pagerButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.DGSElG_pagerButton:disabled{color:var(--dsw-alias-label-dimmed);cursor:default}.DGSElG_tabs{background:var(--dsw-alias-bg-skeleton);border-radius:8px;gap:2px;margin-bottom:8px;padding:2px;display:inline-flex}.DGSElG_tab{cursor:pointer;height:28px;color:var(--dsw-alias-label-secondary);background:0 0;border:none;border-radius:6px;align-items:center;padding:0 12px;font-family:inherit;font-size:12px;line-height:18px;display:inline-flex}.DGSElG_tab:hover{background:var(--dsw-alias-interactive-bg-hover)}.DGSElG_tabActive{background:var(--dsw-alias-bg-overlay);color:var(--dsw-alias-label-primary)}.DGSElG_tabActive:hover{background:var(--dsw-alias-bg-overlay)}.DGSElG_dateLabel{font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-primary);font-size:14px;line-height:22px}.DGSElG_total{color:var(--dsw-alias-label-primary);margin-top:12px;font-size:14px;font-weight:600;line-height:22px}.DGSElG_sectionTitle{color:var(--dsw-alias-label-secondary);margin:12px 0 4px;font-size:12px;line-height:18px}.DGSElG_row{color:var(--dsw-alias-label-primary);justify-content:space-between;gap:12px;font-size:12px;line-height:18px;display:flex}.DGSElG_rowName{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.DGSElG_rowCalls{color:var(--dsw-alias-label-tertiary)}.DGSElG_compaction{color:var(--dsw-alias-label-secondary);margin-top:8px;font-size:12px;line-height:18px}";
51192
- const tagId$1 = "@dsh-agent-toolkit/token-usage/UsageModal.module.css";
51193
- if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
51266
+ //#region \0dsh-css:D:\work\github\dsh\dsh-agent-toolkit\packages\usage\src\client\usage\UsageModal.module.css.mjs
51267
+ const css = ".MODeXa_dialog.MODeXa_dialog{width:min(720px,100%)}.MODeXa_pager{justify-content:flex-start;align-items:center;gap:8px;display:flex}.MODeXa_pagerButton{cursor:pointer;width:28px;height:28px;color:var(--dsw-alias-label-primary);background:0 0;border:none;border-radius:8px;justify-content:center;align-items:center;font-family:inherit;font-size:14px;line-height:20px;display:inline-flex}.MODeXa_pagerButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.MODeXa_pagerButton:disabled{color:var(--dsw-alias-label-dimmed);cursor:default}.MODeXa_tabs{background:var(--dsw-alias-bg-skeleton);border-radius:8px;gap:2px;margin-bottom:8px;padding:2px;display:inline-flex}.MODeXa_tab{cursor:pointer;height:28px;color:var(--dsw-alias-label-secondary);background:0 0;border:none;border-radius:6px;align-items:center;padding:0 12px;font-family:inherit;font-size:12px;line-height:18px;display:inline-flex}.MODeXa_tab:hover{background:var(--dsw-alias-interactive-bg-hover)}.MODeXa_tabActive{background:var(--dsw-alias-bg-overlay);color:var(--dsw-alias-label-primary)}.MODeXa_tabActive:hover{background:var(--dsw-alias-bg-overlay)}.MODeXa_dateLabel{font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-primary);font-size:14px;line-height:22px}.MODeXa_total{color:var(--dsw-alias-label-primary);margin-top:12px;font-size:14px;font-weight:600;line-height:22px}.MODeXa_sectionTitle{color:var(--dsw-alias-label-secondary);margin:12px 0 4px;font-size:12px;line-height:18px}.MODeXa_row{color:var(--dsw-alias-label-primary);justify-content:space-between;gap:12px;font-size:12px;line-height:18px;display:flex}.MODeXa_rowName{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.MODeXa_rowCalls{color:var(--dsw-alias-label-tertiary)}.MODeXa_compaction{color:var(--dsw-alias-label-secondary);margin-top:8px;font-size:12px;line-height:18px}";
51268
+ const tagId = "@dsh-agent-toolkit/token-usage/UsageModal.module.css-3b7b09e9";
51269
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
51194
51270
  const tag = document.createElement("style");
51195
51271
  tag.dataset.plugin = "@dsh-agent-toolkit/token-usage";
51196
- tag.dataset.pluginCss = tagId$1;
51197
- tag.textContent = css$1;
51272
+ tag.dataset.pluginCss = tagId;
51273
+ tag.textContent = css;
51198
51274
  document.head.appendChild(tag);
51199
51275
  }
51200
51276
  var UsageModal_module_css_default = {
51201
- "sectionTitle": "DGSElG_sectionTitle",
51202
- "compaction": "DGSElG_compaction",
51203
- "row": "DGSElG_row",
51204
- "tabActive": "DGSElG_tabActive",
51205
- "rowCalls": "DGSElG_rowCalls",
51206
- "rowName": "DGSElG_rowName",
51207
- "tab": "DGSElG_tab",
51208
- "tabs": "DGSElG_tabs",
51209
- "dialog": "DGSElG_dialog",
51210
- "pagerButton": "DGSElG_pagerButton",
51211
- "pager": "DGSElG_pager",
51212
- "total": "DGSElG_total",
51213
- "dateLabel": "DGSElG_dateLabel"
51277
+ "compaction": "MODeXa_compaction",
51278
+ "dialog": "MODeXa_dialog",
51279
+ "pagerButton": "MODeXa_pagerButton",
51280
+ "pager": "MODeXa_pager",
51281
+ "dateLabel": "MODeXa_dateLabel",
51282
+ "tabs": "MODeXa_tabs",
51283
+ "rowName": "MODeXa_rowName",
51284
+ "row": "MODeXa_row",
51285
+ "tabActive": "MODeXa_tabActive",
51286
+ "sectionTitle": "MODeXa_sectionTitle",
51287
+ "total": "MODeXa_total",
51288
+ "rowCalls": "MODeXa_rowCalls",
51289
+ "tab": "MODeXa_tab"
51214
51290
  };
51215
51291
  //#endregion
51216
- //#region src/client/UsageModal.tsx
51292
+ //#region src/client/usage/UsageModal.tsx
51217
51293
  /** Token 用量模态框:活动热力图(近 13 周)与单日详情双 tab,tab 完全独立切换。 */
51294
+ /** fetch JSON:非 2xx 与网络错误都抛错(useLoadState 转 error 态)。 */
51218
51295
  async function fetchJson(url) {
51219
- try {
51220
- const res = await fetch(url);
51221
- if (!res.ok) return { status: "error" };
51222
- return {
51223
- status: "ok",
51224
- value: await res.json()
51225
- };
51226
- } catch {
51227
- return { status: "error" };
51228
- }
51296
+ const res = await fetch(url);
51297
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
51298
+ return await res.json();
51229
51299
  }
51300
+ /** 永不落定的占位 promise:dayDate 未定时跳过拉取(保持 loading,dayDate 落定后 deps 变化重拉)。 */
51301
+ const PENDING = new Promise(() => {});
51230
51302
  function Breakdown({ title, rows }) {
51231
51303
  if (rows.length === 0) return null;
51232
51304
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
@@ -51248,207 +51320,166 @@ ${te.current.stack}
51248
51320
  }, name))] });
51249
51321
  }
51250
51322
  function UsageModal({ open, onClose, initialDate }) {
51251
- const [tab, setTab] = (0, react.useState)(initialDate === null ? "activity" : "day");
51252
- /** 单日 tab 的日期;null = 未定(跟随 today)。 */
51253
- const [date, setDate] = (0, react.useState)(initialDate);
51254
- const [range, setRange] = (0, react.useState)({ status: "loading" });
51255
- const [day, setDay] = (0, react.useState)({ status: "loading" });
51256
- (0, react.useEffect)(() => {
51257
- if (!open) return;
51258
- setTab(initialDate === null ? "activity" : "day");
51259
- setDate(initialDate);
51260
- }, [open, initialDate]);
51261
- (0, react.useEffect)(() => {
51262
- if (!open) return;
51263
- let stale = false;
51264
- setRange({ status: "loading" });
51265
- fetchJson("/token-usage/api/range?days=91").then((s) => {
51266
- if (!stale) setRange(s);
51267
- });
51268
- return () => {
51269
- stale = true;
51270
- };
51271
- }, [open]);
51272
- const today = range.status === "ok" ? range.value.today : day.status === "ok" ? day.value.today : void 0;
51273
- /** 单日 tab 当前日期:pager 选过的日期优先,否则 today(等 range/day payload 到达)。 */
51274
- const dayDate = date ?? today;
51275
- (0, react.useEffect)(() => {
51276
- if (!open || dayDate === void 0) return;
51277
- let stale = false;
51278
- setDay({ status: "loading" });
51279
- fetchJson(`/token-usage/api/daily?date=${dayDate}`).then((s) => {
51280
- if (!stale) setDay(s);
51281
- });
51282
- return () => {
51283
- stale = true;
51284
- };
51285
- }, [open, dayDate]);
51286
- const record = dayDate !== void 0 && day.status === "ok" ? day.value.record : void 0;
51287
- const hit = record === void 0 ? null : cacheHitRate(record.totals);
51288
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
51323
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
51289
51324
  open,
51290
51325
  onClose,
51291
51326
  title: "Token 用量",
51292
51327
  closeLabel: "关闭",
51293
51328
  className: UsageModal_module_css_default.dialog,
51294
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
51295
- className: UsageModal_module_css_default.tabs,
51296
- role: "tablist",
51297
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
51298
- type: "button",
51299
- role: "tab",
51300
- "aria-selected": tab === "activity",
51301
- className: tab === "activity" ? `${UsageModal_module_css_default.tab} ${UsageModal_module_css_default.tabActive}` : UsageModal_module_css_default.tab,
51302
- onClick: () => {
51303
- setTab("activity");
51304
- },
51305
- children: "活动"
51306
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
51307
- type: "button",
51308
- role: "tab",
51309
- "aria-selected": tab === "day",
51310
- className: tab === "day" ? `${UsageModal_module_css_default.tab} ${UsageModal_module_css_default.tabActive}` : UsageModal_module_css_default.tab,
51311
- onClick: () => {
51312
- setTab("day");
51313
- },
51314
- children: "单日"
51315
- })]
51316
- }), tab === "activity" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
51317
- range.status === "loading" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: "加载中…" }),
51318
- range.status === "error" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: "加载失败,请重试" }),
51319
- range.status === "ok" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
51320
- className: UsageModal_module_css_default.sectionTitle,
51321
- children: "近 13 周活动"
51322
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ActivityHeatmap, {
51323
- today: range.value.today,
51324
- days: range.value.days
51325
- })] })
51326
- ] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
51327
- dayDate !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
51328
- className: UsageModal_module_css_default.pager,
51329
- children: [
51330
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
51331
- type: "button",
51332
- className: UsageModal_module_css_default.pagerButton,
51333
- "aria-label": "前一天",
51334
- onClick: () => {
51335
- setDate(shiftDate(dayDate, -1));
51336
- },
51337
- children: ""
51338
- }),
51339
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
51340
- className: UsageModal_module_css_default.dateLabel,
51341
- children: dayDate
51342
- }),
51343
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
51344
- type: "button",
51345
- className: UsageModal_module_css_default.pagerButton,
51346
- "aria-label": "后一天",
51347
- disabled: today === void 0 || shiftDate(dayDate, 1) > today,
51348
- onClick: () => {
51349
- setDate(shiftDate(dayDate, 1));
51350
- },
51351
- children: "→"
51352
- })
51353
- ]
51354
- }),
51355
- day.status === "loading" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: "加载中…" }),
51356
- day.status === "error" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: "加载失败,请重试" }),
51357
- record !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
51358
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DailyBarChart, { record }),
51359
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
51360
- className: UsageModal_module_css_default.total,
51361
- children: [
51362
- "当日总量 ",
51363
- formatTokens(billedOf(record.totals)),
51364
- " · ",
51365
- record.totals.calls,
51366
- " 次调用",
51367
- record.totals.estimated > 0 && `(含估算 ${formatTokens(record.totals.estimated)})`,
51368
- hit !== null && `(缓存命中率 ${Math.round(hit * 100)}%)`,
51369
- record.totals.calls === 0 && " · 当日无用量"
51370
- ]
51371
- }),
51372
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Breakdown, {
51373
- title: "按模型",
51374
- rows: Object.entries(record.byModel).sort((a, b) => billedOf(b[1]) - billedOf(a[1]))
51329
+ children: open && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UsageModalBody, { initialDate: initialDate ?? null })
51330
+ });
51331
+ }
51332
+ function UsageModalBody({ initialDate }) {
51333
+ const [tab, setTab] = (0, react.useState)(initialDate === null ? "activity" : "day");
51334
+ /** 单日 tab 的日期;null = 未定(跟随 today)。 */
51335
+ const [date, setDate] = (0, react.useState)(initialDate);
51336
+ /** 打开即取 91 天范围数据;缓存在 state,tab 来回切换不重取。 */
51337
+ const range = useLoadState(() => fetchJson("/dsh-agent-toolkit/api/usage/range?days=91"), []);
51338
+ const today = range.state.kind === "ok" ? range.state.data.today : void 0;
51339
+ /** 单日 tab 当前日期:pager 选过的日期优先,否则 today(等 range payload 到达)。 */
51340
+ const dayDate = date ?? today;
51341
+ /** date 未定时(等 today)不拉取:挂 PENDING 保持 loading,dayDate 落定后 deps 变化重拉。 */
51342
+ const day = useLoadState(() => {
51343
+ if (dayDate === void 0) return PENDING;
51344
+ return fetchJson(`/dsh-agent-toolkit/api/usage/daily?date=${dayDate}`);
51345
+ }, [dayDate]);
51346
+ const record = dayDate !== void 0 && day.state.kind === "ok" ? day.state.data.record : void 0;
51347
+ const hit = record === void 0 ? null : cacheHitRate(record.totals);
51348
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
51349
+ className: UsageModal_module_css_default.tabs,
51350
+ role: "tablist",
51351
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
51352
+ type: "button",
51353
+ role: "tab",
51354
+ "aria-selected": tab === "activity",
51355
+ className: tab === "activity" ? `${UsageModal_module_css_default.tab} ${UsageModal_module_css_default.tabActive}` : UsageModal_module_css_default.tab,
51356
+ onClick: () => {
51357
+ setTab("activity");
51358
+ },
51359
+ children: "活动"
51360
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
51361
+ type: "button",
51362
+ role: "tab",
51363
+ "aria-selected": tab === "day",
51364
+ className: tab === "day" ? `${UsageModal_module_css_default.tab} ${UsageModal_module_css_default.tabActive}` : UsageModal_module_css_default.tab,
51365
+ onClick: () => {
51366
+ setTab("day");
51367
+ },
51368
+ children: "单日"
51369
+ })]
51370
+ }), tab === "activity" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
51371
+ range.state.kind === "loading" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: "加载中…" }),
51372
+ range.state.kind === "error" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: "加载失败,请重试" }),
51373
+ range.state.kind === "ok" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
51374
+ className: UsageModal_module_css_default.sectionTitle,
51375
+ children: "近 13 周活动"
51376
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ActivityHeatmap, {
51377
+ today: range.state.data.today,
51378
+ days: range.state.data.days
51379
+ })] })
51380
+ ] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
51381
+ dayDate !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
51382
+ className: UsageModal_module_css_default.pager,
51383
+ children: [
51384
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
51385
+ type: "button",
51386
+ className: UsageModal_module_css_default.pagerButton,
51387
+ "aria-label": "前一天",
51388
+ onClick: () => {
51389
+ setDate(shiftDate(dayDate, -1));
51390
+ },
51391
+ children: ""
51375
51392
  }),
51376
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Breakdown, {
51377
- title: "按项目",
51378
- rows: Object.entries(record.byProject).sort((a, b) => billedOf(b[1]) - billedOf(a[1]))
51393
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
51394
+ className: UsageModal_module_css_default.dateLabel,
51395
+ children: dayDate
51379
51396
  }),
51380
- record.compaction.calls > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
51381
- className: UsageModal_module_css_default.compaction,
51382
- children: [
51383
- "上下文压缩 ",
51384
- formatTokens(billedOf(record.compaction)),
51385
- " · ",
51386
- record.compaction.calls,
51387
- " 次"
51388
- ]
51397
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
51398
+ type: "button",
51399
+ className: UsageModal_module_css_default.pagerButton,
51400
+ "aria-label": "后一天",
51401
+ disabled: today === void 0 || shiftDate(dayDate, 1) > today,
51402
+ onClick: () => {
51403
+ setDate(shiftDate(dayDate, 1));
51404
+ },
51405
+ children: "→"
51389
51406
  })
51390
- ] })
51391
- ] })]
51392
- });
51407
+ ]
51408
+ }),
51409
+ day.state.kind === "loading" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: "加载中…" }),
51410
+ day.state.kind === "error" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: "加载失败,请重试" }),
51411
+ record !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
51412
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DailyBarChart, { record }),
51413
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
51414
+ className: UsageModal_module_css_default.total,
51415
+ children: [
51416
+ "当日总量 ",
51417
+ formatTokens(billedOf(record.totals)),
51418
+ " · ",
51419
+ record.totals.calls,
51420
+ " 次调用",
51421
+ record.totals.estimated > 0 && `(含估算 ${formatTokens(record.totals.estimated)})`,
51422
+ hit !== null && `(缓存命中率 ${Math.round(hit * 100)}%)`,
51423
+ record.totals.calls === 0 && " · 当日无用量"
51424
+ ]
51425
+ }),
51426
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Breakdown, {
51427
+ title: "按模型",
51428
+ rows: Object.entries(record.byModel).sort((a, b) => billedOf(b[1]) - billedOf(a[1]))
51429
+ }),
51430
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Breakdown, {
51431
+ title: "按项目",
51432
+ rows: Object.entries(record.byProject).sort((a, b) => billedOf(b[1]) - billedOf(a[1]))
51433
+ }),
51434
+ record.compaction.calls > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
51435
+ className: UsageModal_module_css_default.compaction,
51436
+ children: [
51437
+ "上下文压缩 ",
51438
+ formatTokens(billedOf(record.compaction)),
51439
+ " · ",
51440
+ record.compaction.calls,
51441
+ " 次"
51442
+ ]
51443
+ })
51444
+ ] })
51445
+ ] })] });
51393
51446
  }
51394
51447
  //#endregion
51395
- //#region \0dsh-css:D:\work\github\dsh\dsh-agent-toolkit\packages\token-usage\src\client\UsageEntry.module.css.mjs
51396
- const css = "._0uegfW_trigger{box-sizing:border-box;cursor:pointer;width:calc(100% + 4px);height:42px;color:var(--dsw-alias-label-primary);background:0 0;border:none;border-radius:12px;flex:none;align-items:center;gap:8px;margin:4px -2px;padding:0 10px 0 8px;font-family:inherit;font-size:14px;line-height:22px;display:flex;overflow:hidden}._0uegfW_trigger:hover{background:var(--dsw-alias-interactive-bg-hover)}._0uegfW_trigger._0uegfW_rail{border-radius:50%;justify-content:center;gap:0;width:36px;height:36px;margin:8px 0 10px;padding:0}._0uegfW_triggerLabel{white-space:nowrap;overflow:hidden}";
51397
- const tagId = "@dsh-agent-toolkit/token-usage/UsageEntry.module.css";
51398
- if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
51399
- const tag = document.createElement("style");
51400
- tag.dataset.plugin = "@dsh-agent-toolkit/token-usage";
51401
- tag.dataset.pluginCss = tagId;
51402
- tag.textContent = css;
51403
- document.head.appendChild(tag);
51448
+ //#region src/client/usage/entry.tsx
51449
+ const SidebarEntry = createSidebarEntry({
51450
+ id: "dsh-agent-toolkit:usage",
51451
+ order: 0,
51452
+ icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconDataOutline16, { size: 18 }),
51453
+ title: "Token 用量",
51454
+ renderModal: (p) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UsageModal, { ...p })
51455
+ });
51456
+ /** 槽注册要求完整 composed props(含运行时 share useSessions/useWorkspaces);实现只消费 wide。 */
51457
+ function UsageEntry(props) {
51458
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SidebarEntry, { wide: props.wide });
51404
51459
  }
51405
- var UsageEntry_module_css_default = {
51406
- "triggerLabel": "_0uegfW_triggerLabel",
51407
- "rail": "_0uegfW_rail",
51408
- "trigger": "_0uegfW_trigger"
51409
- };
51410
51460
  //#endregion
51411
- //#region src/client/UsageEntry.tsx
51412
- /** Sidebar footer entry: wide icon+label row vs rail icon-only; opens the usage modal. */
51413
- function UsageEntry({ wide }) {
51414
- const [open, setOpen] = (0, react.useState)(false);
51415
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
51416
- label: "Token 用量",
51417
- delayMs: 500,
51418
- disabled: wide,
51419
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
51420
- type: "button",
51421
- className: clsx(UsageEntry_module_css_default.trigger, !wide && UsageEntry_module_css_default.rail),
51422
- "aria-label": "Token 用量",
51423
- onClick: () => {
51424
- setOpen(true);
51425
- },
51426
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconDataOutline16, { size: wide ? 16 : 18 }), wide && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
51427
- className: UsageEntry_module_css_default.triggerLabel,
51428
- children: "Token 用量"
51429
- })]
51430
- })
51431
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UsageModal, {
51432
- open,
51433
- onClose: () => {
51434
- setOpen(false);
51435
- },
51436
- initialDate: null
51437
- })] });
51461
+ //#region src/client/usage/index.ts
51462
+ function setupUsageClient(ctx) {
51463
+ ctx.slots.inject("sidebar.footer.action", () => ctx.slots.register({
51464
+ name: "sidebar.footer.action",
51465
+ id: "dsh-agent-toolkit:usage",
51466
+ order: 0
51467
+ }, UsageEntry));
51438
51468
  }
51439
51469
  //#endregion
51440
51470
  //#region src/client/index.ts
51441
51471
  const inject = ["slots"];
51442
51472
  function apply(ctx) {
51443
- ctx.slots.inject("sidebar.footer.action", () => ctx.slots.register({
51444
- name: "sidebar.footer.action",
51445
- id: "token-usage",
51446
- order: 0
51447
- }, UsageEntry));
51473
+ try {
51474
+ setupUsageClient(ctx);
51475
+ } catch (error) {
51476
+ console.warn("[dsh-agent-toolkit/token-usage] 侧边栏「Token 用量」入口已由先到实例注册,本实例停用用量面板", error);
51477
+ }
51448
51478
  }
51449
51479
  //#endregion
51450
51480
  exports.apply = apply;
51451
51481
  exports.inject = inject;
51482
+ exports.setupUsageClient = setupUsageClient;
51452
51483
  return module.exports;
51453
51484
  }
51454
51485
  });