@cassius0924/dsh-usage-dashboard 0.8.0 → 0.8.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/lib/client.js CHANGED
@@ -26,7 +26,7 @@ __export(index_exports, {
26
26
  name: () => name
27
27
  });
28
28
  module.exports = __toCommonJS(index_exports);
29
- var import_react7 = require("react");
29
+ var import_react8 = require("react");
30
30
 
31
31
  // src/client/boundary.tsx
32
32
  var import_react = require("react");
@@ -554,6 +554,9 @@ var zh = {
554
554
  "widget.expandAria": "\u5C55\u5F00\u989D\u5EA6\u7A97\u53E3",
555
555
  "widget.collapseAria": "\u6536\u8D77\u989D\u5EA6\u7A97\u53E3",
556
556
  "messageCost.label": "\u672C\u8F6E\u8D39\u7528",
557
+ "sessionCost.title": "\u4F1A\u8BDD\u8D39\u7528",
558
+ "sessionCost.aria": "\u672C\u4F1A\u8BDD\u4F30\u7B97\u8D39\u7528 {amount}",
559
+ "sessionCost.active": "\u6D3B\u8DC3\u65F6\u95F4",
557
560
  "messageCost.tooltip": "\u7531 dsh-usage-dashboard \u63D0\u4F9B \xB7 \u672C\u8F6E\u5BF9\u8BDD\u8D39\u7528\u4E3A\u4F30\u7B97\u503C",
558
561
  "messageCost.aria": "{amount}\uFF0C\u672C\u8F6E\u5BF9\u8BDD\u4F30\u7B97\u8D39\u7528\uFF0C\u7531 dsh-usage-dashboard \u63D0\u4F9B",
559
562
  "boundary.title": "\u989D\u5EA6\u9762\u677F\u51FA\u9519\u4E86",
@@ -822,6 +825,9 @@ var en = {
822
825
  "widget.expandAria": "Expand balance widget",
823
826
  "widget.collapseAria": "Collapse balance widget",
824
827
  "messageCost.label": "Turn cost",
828
+ "sessionCost.title": "Session cost",
829
+ "sessionCost.aria": "Estimated session cost {amount}",
830
+ "sessionCost.active": "Active time",
825
831
  "messageCost.tooltip": "Provided by dsh-usage-dashboard \xB7 estimated cost for this turn",
826
832
  "messageCost.aria": "{amount}, estimated cost for this turn, provided by dsh-usage-dashboard",
827
833
  "boundary.title": "The usage dashboard crashed",
@@ -2894,7 +2900,7 @@ function BalanceDashboard(props) {
2894
2900
  ] })
2895
2901
  ] })
2896
2902
  ] }),
2897
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "dq-footer", children: "@cassius0924/dsh-usage-dashboard v0.8.0" })
2903
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "dq-footer", children: "@cassius0924/dsh-usage-dashboard v0.8.1" })
2898
2904
  ] });
2899
2905
  }
2900
2906
 
@@ -2938,6 +2944,254 @@ function MessageCost({ sessionId, messageId }) {
2938
2944
  );
2939
2945
  }
2940
2946
 
2947
+ // src/client/session-cost-pill.tsx
2948
+ var import_react6 = require("react");
2949
+ var import_react_dom = require("react-dom");
2950
+
2951
+ // src/pricing.ts
2952
+ var PEAK_PRICING_FROM_MS = Date.UTC(2026, 7, 16, 16, 0, 0);
2953
+ var V41_FLASH_PRICING_FROM_MS = Date.UTC(2026, 8, 10, 4, 0, 0);
2954
+ var PRO_ROUTED_TO_FLASH_FROM_MS = Date.UTC(2026, 8, 14, 4, 0, 0);
2955
+ var PEAK_WINDOWS = [[9, 12], [14, 18]];
2956
+ var BEIJING_OFFSET_MS3 = 8 * 36e5;
2957
+ var FLAT_RATES = {
2958
+ pro: { cacheHit: 0.025, input: 3, output: 6 },
2959
+ flash: { cacheHit: 0.02, input: 1, output: 2 },
2960
+ // The vision model billed at flash rates from day one, so its pre-switch
2961
+ // history is costed at the same flat prices as flash.
2962
+ vision: { cacheHit: 0.02, input: 1, output: 2 }
2963
+ };
2964
+ var PEAK_RATES_08_17 = {
2965
+ pro: { cacheHit: 0.3, input: 9, output: 27 },
2966
+ flash: { cacheHit: 0.1, input: 3, output: 9 },
2967
+ // Official policy: the vision model is priced identically to flash; images
2968
+ // cost tokens, not their own multiplier.
2969
+ vision: { cacheHit: 0.1, input: 3, output: 9 }
2970
+ };
2971
+ var PEAK_RATES_09_10 = {
2972
+ pro: { cacheHit: 0.3, input: 9, output: 27 },
2973
+ flash: { cacheHit: 0.04, input: 2, output: 8 },
2974
+ vision: { cacheHit: 0.04, input: 2, output: 8 }
2975
+ };
2976
+ var PRICE_ERAS = [
2977
+ { fromMs: PEAK_PRICING_FROM_MS, peak: PEAK_RATES_08_17, weekdaysOnly: false },
2978
+ { fromMs: V41_FLASH_PRICING_FROM_MS, peak: PEAK_RATES_09_10, weekdaysOnly: true }
2979
+ ];
2980
+ function eraAt(timeMs) {
2981
+ let era = PRICE_ERAS[0];
2982
+ for (const candidate of PRICE_ERAS) if (timeMs >= candidate.fromMs) era = candidate;
2983
+ return era;
2984
+ }
2985
+ var halved = (rates) => ({
2986
+ cacheHit: rates.cacheHit / 2,
2987
+ input: rates.input / 2,
2988
+ output: rates.output / 2
2989
+ });
2990
+ function tierOf(model) {
2991
+ const name2 = model.toLowerCase();
2992
+ if (name2.includes("vision")) return "vision";
2993
+ if (name2.includes("flash")) return "flash";
2994
+ return "pro";
2995
+ }
2996
+ function billedTierOf(timeMs, model) {
2997
+ const tier = tierOf(model);
2998
+ return tier === "pro" && timeMs >= PRO_ROUTED_TO_FLASH_FROM_MS ? "flash" : tier;
2999
+ }
3000
+ function isBeijingWeekday(timeMs) {
3001
+ const day = new Date(timeMs + BEIJING_OFFSET_MS3).getUTCDay();
3002
+ return day >= 1 && day <= 5;
3003
+ }
3004
+ function isPeak(timeMs) {
3005
+ if (eraAt(timeMs).weekdaysOnly && !isBeijingWeekday(timeMs)) return false;
3006
+ const hour = Math.floor(((timeMs + BEIJING_OFFSET_MS3) % 864e5 + 864e5) % 864e5 / 36e5);
3007
+ return PEAK_WINDOWS.some(([from, to]) => hour >= from && hour < to);
3008
+ }
3009
+ function ratesAt(timeMs, model) {
3010
+ if (timeMs < PEAK_PRICING_FROM_MS) return FLAT_RATES[tierOf(model)];
3011
+ const peak = eraAt(timeMs).peak[billedTierOf(timeMs, model)];
3012
+ return isPeak(timeMs) ? peak : halved(peak);
3013
+ }
3014
+
3015
+ // src/client/session-cost-pill.tsx
3016
+ var import_jsx_runtime6 = require("react/jsx-runtime");
3017
+ var PANEL_MARGIN = 12;
3018
+ var PANEL_GAP = 8;
3019
+ var cachedData2 = (sessionId) => {
3020
+ const response = getCachedSessionUsage(sessionId);
3021
+ return response?.ok === true ? response.data ?? null : null;
3022
+ };
3023
+ function CostIcon() {
3024
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
3025
+ "svg",
3026
+ {
3027
+ width: "14",
3028
+ height: "14",
3029
+ viewBox: "0 0 16 16",
3030
+ fill: "none",
3031
+ stroke: "currentColor",
3032
+ strokeWidth: "1",
3033
+ strokeLinecap: "round",
3034
+ strokeLinejoin: "round",
3035
+ "aria-hidden": "true",
3036
+ focusable: "false",
3037
+ children: [
3038
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "8", cy: "8", r: "6" }),
3039
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M5.5 5.3 8 8.4l2.5-3.1" }),
3040
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M8 8.4v2.9" }),
3041
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M5.8 9.5h4.4" }),
3042
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M5.8 10.9h4.4" })
3043
+ ]
3044
+ }
3045
+ );
3046
+ }
3047
+ function SessionCostPill({ sessionId }) {
3048
+ const { t, locale } = useI18n();
3049
+ const [data, setData] = (0, import_react6.useState)(
3050
+ () => sessionId === void 0 || sessionId === "" ? null : cachedData2(sessionId)
3051
+ );
3052
+ const [open, setOpen] = (0, import_react6.useState)(false);
3053
+ const anchorRef = (0, import_react6.useRef)(null);
3054
+ const panelRef = (0, import_react6.useRef)(null);
3055
+ const [pos, setPos] = (0, import_react6.useState)(null);
3056
+ (0, import_react6.useEffect)(() => {
3057
+ if (sessionId === void 0 || sessionId === "") return;
3058
+ setData(cachedData2(sessionId));
3059
+ const unsubscribe = subscribeSessionUsage(sessionId, () => setData(cachedData2(sessionId)));
3060
+ if (getCachedSessionUsage(sessionId) === null) void fetchSessionUsage(sessionId);
3061
+ return unsubscribe;
3062
+ }, [sessionId]);
3063
+ (0, import_react6.useLayoutEffect)(() => {
3064
+ if (!open) {
3065
+ setPos(null);
3066
+ return;
3067
+ }
3068
+ const anchor = anchorRef.current;
3069
+ const panel = panelRef.current;
3070
+ if (anchor === null || panel === null) return;
3071
+ const pill = anchor.getBoundingClientRect();
3072
+ const width = panel.getBoundingClientRect().width;
3073
+ setPos({
3074
+ left: Math.min(Math.max(pill.left, PANEL_MARGIN), Math.max(PANEL_MARGIN, window.innerWidth - width - PANEL_MARGIN)),
3075
+ bottom: window.innerHeight - pill.top + PANEL_GAP
3076
+ });
3077
+ }, [open, data]);
3078
+ (0, import_react6.useEffect)(() => {
3079
+ if (!open) return;
3080
+ const close = () => setOpen(false);
3081
+ const onPointerDown = (event) => {
3082
+ const target = event.target;
3083
+ if (!(target instanceof Node)) return;
3084
+ if (anchorRef.current?.contains(target) === true || panelRef.current?.contains(target) === true) return;
3085
+ close();
3086
+ };
3087
+ const onKeyDown = (event) => {
3088
+ if (event.key === "Escape") close();
3089
+ };
3090
+ document.addEventListener("pointerdown", onPointerDown, true);
3091
+ document.addEventListener("keydown", onKeyDown);
3092
+ window.addEventListener("resize", close);
3093
+ document.addEventListener("scroll", close, true);
3094
+ return () => {
3095
+ document.removeEventListener("pointerdown", onPointerDown, true);
3096
+ document.removeEventListener("keydown", onKeyDown);
3097
+ window.removeEventListener("resize", close);
3098
+ document.removeEventListener("scroll", close, true);
3099
+ };
3100
+ }, [open]);
3101
+ if (sessionId === void 0 || sessionId === "" || data === null || data.calls === 0) return null;
3102
+ const amount = `\xA5${fmtTurnCost(data.cost)}`;
3103
+ const priceAt = data.lastActive ?? Date.now();
3104
+ const split = data.models.reduce(
3105
+ (sum, model) => {
3106
+ const rates = ratesAt(priceAt, model.model);
3107
+ const weighted = {
3108
+ input: model.input * rates.input,
3109
+ cache: model.cache * rates.cacheHit,
3110
+ output: model.output * rates.output
3111
+ };
3112
+ const weight = weighted.input + weighted.cache + weighted.output;
3113
+ if (weight <= 0) return sum;
3114
+ sum.input += model.cost * (weighted.input / weight);
3115
+ sum.cache += model.cost * (weighted.cache / weight);
3116
+ sum.output += model.cost * (weighted.output / weight);
3117
+ return sum;
3118
+ },
3119
+ { input: 0, cache: 0, output: 0 }
3120
+ );
3121
+ const rangeTime = new Intl.DateTimeFormat(locale === "en" ? "en-US" : "zh-CN", {
3122
+ timeZone: "Asia/Shanghai",
3123
+ month: "numeric",
3124
+ day: "numeric",
3125
+ hour: "2-digit",
3126
+ minute: "2-digit",
3127
+ hour12: false
3128
+ });
3129
+ const range = data.firstActive !== null && data.lastActive !== null ? `${rangeTime.format(data.firstActive)} \u2013 ${rangeTime.format(data.lastActive)}` : null;
3130
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
3131
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { ref: anchorRef, className: "dq-cost-anchor", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
3132
+ "button",
3133
+ {
3134
+ type: "button",
3135
+ className: "dq-cost-pill",
3136
+ "aria-haspopup": "dialog",
3137
+ "aria-expanded": open,
3138
+ "aria-label": t("sessionCost.aria", { amount }),
3139
+ onClick: () => setOpen((value) => !value),
3140
+ children: [
3141
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CostIcon, {}),
3142
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dq-cost-pill-label", children: amount })
3143
+ ]
3144
+ }
3145
+ ) }),
3146
+ open && (0, import_react_dom.createPortal)(
3147
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
3148
+ "div",
3149
+ {
3150
+ ref: panelRef,
3151
+ className: "dq-cost-panel",
3152
+ role: "dialog",
3153
+ "aria-label": t("sessionCost.title"),
3154
+ style: pos === null ? { visibility: "hidden", left: 0, top: 0 } : { visibility: "visible", left: pos.left, bottom: pos.bottom, top: "auto" },
3155
+ children: [
3156
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "dq-cost-panel-title", children: [
3157
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "dq-cost-panel-title-label", children: [
3158
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CostIcon, {}),
3159
+ t("sessionCost.title")
3160
+ ] }),
3161
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dq-cost-panel-value", children: amount })
3162
+ ] }),
3163
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "dq-cost-panel-rule", "aria-hidden": true }),
3164
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("dl", { className: "dq-cost-details", children: [
3165
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("dt", { children: t("common.input") }),
3166
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("dd", { children: [
3167
+ "\xA5",
3168
+ fmtTurnCost(split.input)
3169
+ ] }),
3170
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("dt", { children: t("common.cacheHit") }),
3171
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("dd", { children: [
3172
+ "\xA5",
3173
+ fmtTurnCost(split.cache)
3174
+ ] }),
3175
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("dt", { children: t("common.output") }),
3176
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("dd", { children: [
3177
+ "\xA5",
3178
+ fmtTurnCost(split.output)
3179
+ ] }),
3180
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("dt", { children: t("sessionUsage.calls") }),
3181
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("dd", { children: fmtInt(data.calls) }),
3182
+ range !== null && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
3183
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("dt", { children: t("sessionCost.active") }),
3184
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("dd", { children: range })
3185
+ ] })
3186
+ ] })
3187
+ ]
3188
+ }
3189
+ ),
3190
+ document.body
3191
+ )
3192
+ ] });
3193
+ }
3194
+
2941
3195
  // src/client/styles.ts
2942
3196
  var css = `
2943
3197
  .dsh-quota-root{-webkit-text-size-adjust:100%;text-size-adjust:100%;position:absolute;right:16px;bottom:16px;z-index:2147483000;pointer-events:auto;opacity:1;visibility:visible;font-family:var(--dsw-font-family,-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Hiragino Sans GB","Microsoft YaHei","Helvetica Neue",Helvetica,Arial,sans-serif);font-size:13px;line-height:1.45;font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-primary,#1f2328);--dq-text-success:#1a7f37;--dq-text-success:color-mix(in oklab,var(--dsw-alias-state-success-primary,#2da44e) 52%,var(--dsw-alias-label-primary,#1f2328) 48%);--dq-text-warn:#9a6700;--dq-text-warn:color-mix(in oklab,var(--dsw-alias-state-warn-primary,#bf8700) 52%,var(--dsw-alias-label-primary,#1f2328) 48%);transition:left .28s cubic-bezier(.22,1,.36,1),top .28s cubic-bezier(.22,1,.36,1),opacity .16s ease-out,visibility 0s linear}
@@ -2976,12 +3230,31 @@ var css = `
2976
3230
  .dq-message-cost-amount{text-decoration-line:underline;text-decoration-style:dotted;text-decoration-color:currentColor;text-underline-offset:4px}
2977
3231
  .dq-message-cost:hover{color:var(--dsw-alias-label-secondary,#3f4852)}
2978
3232
  .dq-message-cost:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:2px;border-radius:4px}
2979
- .dq-message-cost::after{content:attr(data-dq-tooltip);position:absolute;left:0;top:calc(100% + 6px);z-index:2147483001;width:max-content;max-width:min(240px,calc(100vw - 24px));padding:6px 9px;border-radius:8px;background:var(--dsw-alias-tooltip-bg,#1f2328);color:var(--dsw-static-neutral-bluish-00,#fff);box-shadow:0 6px 18px rgba(0,0,0,.22);font-size:12px;font-weight:400;line-height:1.5;text-align:left;white-space:normal;pointer-events:none;opacity:0;visibility:hidden;transform:translateY(-3px);transition:opacity .12s ease-out,transform .12s cubic-bezier(.22,1,.36,1),visibility 0s linear .12s}
3233
+ .dq-message-cost::after{content:attr(data-dq-tooltip);position:absolute;left:0;bottom:calc(100% + 6px);top:auto;z-index:2147483001;width:max-content;max-width:min(240px,calc(100vw - 24px));padding:6px 9px;border-radius:8px;background:var(--dsw-alias-tooltip-bg,#1f2328);color:var(--dsw-static-neutral-bluish-00,#fff);box-shadow:0 6px 18px rgba(0,0,0,.22);font-size:12px;font-weight:400;line-height:1.5;text-align:left;white-space:normal;pointer-events:none;opacity:0;visibility:hidden;transform:translateY(3px);transition:opacity .12s ease-out,transform .12s cubic-bezier(.22,1,.36,1),visibility 0s linear .12s}
2980
3234
  .dq-message-cost:hover::after,.dq-message-cost:focus-visible::after{opacity:1;visibility:visible;transform:translateY(0);transition:opacity .12s ease-out,transform .12s cubic-bezier(.22,1,.36,1),visibility 0s linear}
2981
3235
  @media (hover:hover){
2982
3236
  [data-time-hover-root] .dq-message-cost{opacity:0;transition:opacity 80ms ease}
2983
3237
  [data-time-hover-root]:hover .dq-message-cost,[data-time-hover-root]:focus-within .dq-message-cost{opacity:1}
2984
3238
  }
3239
+ /* Composer-dock session cost pill: one more reading beside the host's own
3240
+ \u300C\u4F1A\u8BDD\u7EDF\u8BA1\u300D/\u300CToken \u7528\u91CF\u300Dpills (same slot, same compact skin). */
3241
+ .dq-cost-anchor{display:inline-flex;min-width:0;font-size:calc(var(--dsh-content-font-size-secondary,13px) - 1px);line-height:calc(20px + var(--dsh-content-font-delta-secondary,0px))}
3242
+ .dq-cost-pill{display:inline-flex;align-items:center;gap:6px;box-sizing:border-box;max-width:100%;padding:1px 8px;border:0;border-radius:var(--dsw-radius-sm,8px);background:transparent;color:var(--dsw-alias-label-tertiary,#59636e);font:inherit;font-variant-numeric:tabular-nums;line-height:inherit;white-space:nowrap;cursor:pointer}
3243
+ .dq-cost-pill:hover,.dq-cost-pill[aria-expanded="true"]{background:var(--dsw-alias-interactive-bg-hover,rgba(120,130,150,.12));color:var(--dsw-alias-label-secondary,#59636e)}
3244
+ .dq-cost-pill:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:2px}
3245
+ .dq-cost-pill svg{flex:none}
3246
+ .dq-cost-pill-label{min-width:0;overflow:hidden;text-overflow:ellipsis}
3247
+ /* Click-open breakdown: the host stat-dialog skin (menu surface, prominent
3248
+ elevation, 12/18 rows), portaled to the body and placed above the pill. */
3249
+ .dq-cost-panel{position:fixed;z-index:1100;box-sizing:border-box;width:max-content;min-width:min(300px,calc(100vw - 24px));max-width:min(440px,calc(100vw - 24px));padding:16px;border:0;border-radius:var(--dsw-radius-lg,16px);background:var(--dsw-specific-menu,var(--dsw-alias-bg-overlay,#fff));-webkit-backdrop-filter:var(--dsw-menu-backdrop-filter,blur(40px) saturate(150%));backdrop-filter:var(--dsw-menu-backdrop-filter,blur(40px) saturate(150%));box-shadow:var(--dsw-elevation-prominent,0 12px 32px rgba(0,0,0,.24));font-family:var(--dsw-font-family,-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Hiragino Sans GB","Microsoft YaHei","Helvetica Neue",Helvetica,Arial,sans-serif);font-size:12px;line-height:18px;color:var(--dsw-alias-label-secondary,#59636e);cursor:default}
3250
+ .dq-cost-panel-title{display:flex;justify-content:space-between;gap:16px;margin-bottom:8px;color:var(--dsw-alias-label-primary,#1f2328);font-weight:500}
3251
+ .dq-cost-panel-title-label{display:inline-flex;align-items:center;gap:6px;min-width:0}
3252
+ .dq-cost-panel-title-label svg{flex:none}
3253
+ .dq-cost-panel-value{font-variant-numeric:tabular-nums}
3254
+ .dq-cost-panel-rule{margin-bottom:10px;border-top:.5px solid var(--dsw-alias-border-l2,rgba(0,0,0,.1))}
3255
+ .dq-cost-details{display:grid;grid-template-columns:minmax(76px,auto) minmax(0,1fr);gap:6px 16px;margin:0;color:var(--dsw-alias-label-tertiary,#59636e)}
3256
+ .dq-cost-details dt,.dq-cost-details dd{min-width:0;margin:0}
3257
+ .dq-cost-details dd{color:var(--dsw-alias-label-secondary,#59636e);font-variant-numeric:tabular-nums;text-align:right}
2985
3258
  /* \u5361\u7247\u95F4\u8DDD\uFF08\u6B64\u5904 gap\uFF09\u523B\u610F\u5927\u4E8E\u5361\u5185\u5C0F\u8282\u95F4\u8DDD\uFF08margin-top:12/14/16px \u90A3\u4E00\u6863\uFF09\uFF0C\u5236\u9020"\u5361\u7247\u5916\u758F\u3001\u5361\u7247\u5185\u5BC6"\u7684
2986
3259
  \u758F\u5BC6\u5BF9\u6BD4\uFF1A24px \u76F8\u5BF9\u5361\u5185\u6700\u5927\u6863 16px \u4ECD\u6709 1.5 \u500D\u7EA7\u5DEE\uFF0C\u76F8\u5BF9\u5E38\u89C1\u6863 12px \u6709 2 \u500D\u7EA7\u5DEE\uFF0C\u4E0D\u4E0E .dq-card \u7684
2987
3260
  padding\uFF0816px/20px\uFF0C\u5361\u7247\u5185\u90E8\u547C\u5438\u611F\uFF0C\u8F6E\u6B21 36 \u5DF2\u5B9A\uFF09\u6DF7\u540C\u3002 */
@@ -3449,7 +3722,7 @@ html[data-dq-quota-view] .dq-balance{padding-bottom:48px}
3449
3722
  `;
3450
3723
 
3451
3724
  // src/client/widget.tsx
3452
- var import_react6 = require("react");
3725
+ var import_react7 = require("react");
3453
3726
 
3454
3727
  // src/client/sessions.ts
3455
3728
  function currentSessionIdOf(state) {
@@ -3458,7 +3731,7 @@ function currentSessionIdOf(state) {
3458
3731
  }
3459
3732
 
3460
3733
  // src/client/widget.tsx
3461
- var import_jsx_runtime6 = require("react/jsx-runtime");
3734
+ var import_jsx_runtime7 = require("react/jsx-runtime");
3462
3735
  var MARGIN = 16;
3463
3736
  var CORNER_KEY = "widget.corner";
3464
3737
  var COLLAPSED_KEY = "widget.collapsed";
@@ -3509,47 +3782,47 @@ function cornerPos(corner, node, bounds) {
3509
3782
  function QuotaWidget(props) {
3510
3783
  const { t } = useI18n();
3511
3784
  const sessionId = props.useSessions(currentSessionIdOf);
3512
- const [visible, setVisible] = (0, import_react6.useState)(widgetVisibleStore.get());
3513
- (0, import_react6.useEffect)(() => widgetVisibleStore.subscribe(() => setVisible(widgetVisibleStore.get())), []);
3514
- const [quotaViewActive2, setQuotaViewActive] = (0, import_react6.useState)(quotaViewActiveStore.get());
3515
- (0, import_react6.useEffect)(() => quotaViewActiveStore.subscribe(() => setQuotaViewActive(quotaViewActiveStore.get())), []);
3516
- const [lowBalance, setLowBalance] = (0, import_react6.useState)(lowBalanceStore.get());
3517
- (0, import_react6.useEffect)(() => lowBalanceStore.subscribe(() => setLowBalance(lowBalanceStore.get())), []);
3518
- const [selectedTabIds, setSelectedTabIds] = (0, import_react6.useState)(widgetTabIdsStore.get());
3519
- (0, import_react6.useEffect)(() => widgetTabIdsStore.subscribe(() => setSelectedTabIds(widgetTabIdsStore.get())), []);
3520
- const [viewTabs, setViewTabs] = (0, import_react6.useState)(() => props.views.list());
3521
- (0, import_react6.useEffect)(() => props.views.subscribe(() => setViewTabs(props.views.list())), [props.views]);
3522
- const [activeViewId, setActiveViewId] = (0, import_react6.useState)(null);
3785
+ const [visible, setVisible] = (0, import_react7.useState)(widgetVisibleStore.get());
3786
+ (0, import_react7.useEffect)(() => widgetVisibleStore.subscribe(() => setVisible(widgetVisibleStore.get())), []);
3787
+ const [quotaViewActive2, setQuotaViewActive] = (0, import_react7.useState)(quotaViewActiveStore.get());
3788
+ (0, import_react7.useEffect)(() => quotaViewActiveStore.subscribe(() => setQuotaViewActive(quotaViewActiveStore.get())), []);
3789
+ const [lowBalance, setLowBalance] = (0, import_react7.useState)(lowBalanceStore.get());
3790
+ (0, import_react7.useEffect)(() => lowBalanceStore.subscribe(() => setLowBalance(lowBalanceStore.get())), []);
3791
+ const [selectedTabIds, setSelectedTabIds] = (0, import_react7.useState)(widgetTabIdsStore.get());
3792
+ (0, import_react7.useEffect)(() => widgetTabIdsStore.subscribe(() => setSelectedTabIds(widgetTabIdsStore.get())), []);
3793
+ const [viewTabs, setViewTabs] = (0, import_react7.useState)(() => props.views.list());
3794
+ (0, import_react7.useEffect)(() => props.views.subscribe(() => setViewTabs(props.views.list())), [props.views]);
3795
+ const [activeViewId, setActiveViewId] = (0, import_react7.useState)(null);
3523
3796
  const cachedBalance = getCachedBalance();
3524
- const [data, setData] = (0, import_react6.useState)(cachedBalance?.data ?? null);
3525
- const [error, setError] = (0, import_react6.useState)(null);
3526
- const [loading, setLoading] = (0, import_react6.useState)(cachedBalance === null);
3527
- const [collapsed, setCollapsed] = (0, import_react6.useState)(() => loadPref(COLLAPSED_KEY, isBoolean, false));
3528
- const [pos, setPos] = (0, import_react6.useState)(null);
3529
- const [corner, setCorner] = (0, import_react6.useState)(() => loadPref(CORNER_KEY, isCorner, "br"));
3530
- const [dragging, setDragging] = (0, import_react6.useState)(false);
3531
- const rootRef = (0, import_react6.useRef)(null);
3532
- const dragRef = (0, import_react6.useRef)(null);
3797
+ const [data, setData] = (0, import_react7.useState)(cachedBalance?.data ?? null);
3798
+ const [error, setError] = (0, import_react7.useState)(null);
3799
+ const [loading, setLoading] = (0, import_react7.useState)(cachedBalance === null);
3800
+ const [collapsed, setCollapsed] = (0, import_react7.useState)(() => loadPref(COLLAPSED_KEY, isBoolean, false));
3801
+ const [pos, setPos] = (0, import_react7.useState)(null);
3802
+ const [corner, setCorner] = (0, import_react7.useState)(() => loadPref(CORNER_KEY, isCorner, "br"));
3803
+ const [dragging, setDragging] = (0, import_react7.useState)(false);
3804
+ const rootRef = (0, import_react7.useRef)(null);
3805
+ const dragRef = (0, import_react7.useRef)(null);
3533
3806
  const readUsage = () => {
3534
3807
  const cached = getCachedUsage();
3535
3808
  return { data: cached?.ok === true ? cached.data ?? null : null, at: getCachedUsageAt() };
3536
3809
  };
3537
- const [usage, setUsage] = (0, import_react6.useState)(readUsage);
3538
- (0, import_react6.useEffect)(() => subscribeUsage(() => setUsage(readUsage())), []);
3810
+ const [usage, setUsage] = (0, import_react7.useState)(readUsage);
3811
+ (0, import_react7.useEffect)(() => subscribeUsage(() => setUsage(readUsage())), []);
3539
3812
  const readSessionUsage = (id) => {
3540
3813
  if (id === void 0) return null;
3541
3814
  const response = getCachedSessionUsage(id);
3542
3815
  return response?.ok === true ? response.data ?? null : null;
3543
3816
  };
3544
- const [sessionUsage, setSessionUsage] = (0, import_react6.useState)(() => readSessionUsage(sessionId));
3545
- (0, import_react6.useEffect)(() => {
3817
+ const [sessionUsage, setSessionUsage] = (0, import_react7.useState)(() => readSessionUsage(sessionId));
3818
+ (0, import_react7.useEffect)(() => {
3546
3819
  setSessionUsage(readSessionUsage(sessionId));
3547
3820
  if (sessionId === void 0) return;
3548
3821
  const unsubscribe = subscribeSessionUsage(sessionId, () => setSessionUsage(readSessionUsage(sessionId)));
3549
3822
  void fetchSessionUsage(sessionId);
3550
3823
  return unsubscribe;
3551
3824
  }, [sessionId]);
3552
- (0, import_react6.useLayoutEffect)(() => {
3825
+ (0, import_react7.useLayoutEffect)(() => {
3553
3826
  const viewIds = viewTabs.map((tab) => tab.id);
3554
3827
  const read = () => {
3555
3828
  const next = getActiveConversationViewId(getShellFrame(rootRef.current), viewIds);
@@ -3586,14 +3859,14 @@ function QuotaWidget(props) {
3586
3859
  setLoading(false);
3587
3860
  }
3588
3861
  };
3589
- (0, import_react6.useEffect)(() => {
3862
+ (0, import_react7.useEffect)(() => {
3590
3863
  void load(true);
3591
3864
  const id = setInterval(() => {
3592
3865
  void load(false);
3593
3866
  }, 6e4);
3594
3867
  return () => clearInterval(id);
3595
3868
  }, []);
3596
- (0, import_react6.useLayoutEffect)(() => {
3869
+ (0, import_react7.useLayoutEffect)(() => {
3597
3870
  if (!visible || quotaViewActive2) return;
3598
3871
  const node = rootRef.current;
3599
3872
  if (node === null) return;
@@ -3721,9 +3994,9 @@ function QuotaWidget(props) {
3721
3994
  const dotClass = primary === null ? "dsh-quota-dot dsh-quota-dot--idle" : data?.isAvailable === false ? "dsh-quota-dot dsh-quota-dot--error" : low ? "dsh-quota-dot dsh-quota-dot--warn" : "dsh-quota-dot";
3722
3995
  const ageMinutes = usage.at === null ? null : Math.floor((Date.now() - usage.at) / 6e4);
3723
3996
  const usageAgeText = ageMinutes === null || ageMinutes < 1 ? t("widget.updatedNow") : t("widget.stale", { minutes: ageMinutes });
3724
- const sessionCostRow = sessionUsage === null ? null : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "dsh-quota-row", title: t("widget.sessionCostTitle"), children: [
3725
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dsh-quota-label", children: t("widget.sessionCost") }),
3726
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "dsh-quota-value", children: [
3997
+ const sessionCostRow = sessionUsage === null ? null : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "dsh-quota-row", title: t("widget.sessionCostTitle"), children: [
3998
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "dsh-quota-label", children: t("widget.sessionCost") }),
3999
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "dsh-quota-value", children: [
3727
4000
  "\xA5",
3728
4001
  fmtTurnCost(sessionUsage.cost)
3729
4002
  ] })
@@ -3731,50 +4004,50 @@ function QuotaWidget(props) {
3731
4004
  let body = null;
3732
4005
  if (!collapsed) {
3733
4006
  if (loading && data === null && error === null) {
3734
- body = /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "dsh-quota-body", children: [
3735
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { children: t("widget.loading") }),
4007
+ body = /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "dsh-quota-body", children: [
4008
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { children: t("widget.loading") }),
3736
4009
  sessionCostRow
3737
4010
  ] });
3738
4011
  } else if (error !== null && data === null) {
3739
- body = /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "dsh-quota-body", children: [
3740
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "dsh-quota-error", children: localizeApiError(error, t, "error.query") }),
4012
+ body = /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "dsh-quota-body", children: [
4013
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "dsh-quota-error", children: localizeApiError(error, t, "error.query") }),
3741
4014
  sessionCostRow
3742
4015
  ] });
3743
4016
  } else if (primary !== null) {
3744
- body = /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "dsh-quota-body", children: [
3745
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "dsh-quota-remaining-label", children: t("balance.remaining") }),
3746
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { title: low ? t("widget.lowTitle", { amount: fmt(lowBalance) }) : void 0, children: [
3747
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: `dsh-quota-total${low ? " dsh-quota-total--low" : ""}`, children: fmt(primary.total) }),
3748
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dsh-quota-currency", children: primary.currency })
4017
+ body = /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "dsh-quota-body", children: [
4018
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "dsh-quota-remaining-label", children: t("balance.remaining") }),
4019
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { title: low ? t("widget.lowTitle", { amount: fmt(lowBalance) }) : void 0, children: [
4020
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: `dsh-quota-total${low ? " dsh-quota-total--low" : ""}`, children: fmt(primary.total) }),
4021
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "dsh-quota-currency", children: primary.currency })
3749
4022
  ] }),
3750
- usage.data !== null && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "dsh-quota-row", title: t("widget.todayCostTitle", { age: usageAgeText }), children: [
3751
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dsh-quota-label", children: t("widget.todayCost") }),
3752
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "dsh-quota-value", children: [
4023
+ usage.data !== null && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "dsh-quota-row", title: t("widget.todayCostTitle", { age: usageAgeText }), children: [
4024
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "dsh-quota-label", children: t("widget.todayCost") }),
4025
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "dsh-quota-value", children: [
3753
4026
  "\xA5",
3754
4027
  fmt(usage.data.summary.today.cost)
3755
4028
  ] })
3756
4029
  ] }),
3757
4030
  sessionCostRow,
3758
- data?.isAvailable === false && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "dsh-quota-row", children: [
3759
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dsh-quota-label", children: t("common.status") }),
3760
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dsh-quota-value dsh-quota-error", children: t("common.unavailable") })
4031
+ data?.isAvailable === false && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "dsh-quota-row", children: [
4032
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "dsh-quota-label", children: t("common.status") }),
4033
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "dsh-quota-value dsh-quota-error", children: t("common.unavailable") })
3761
4034
  ] })
3762
4035
  ] });
3763
4036
  } else {
3764
- body = /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "dsh-quota-body", children: [
3765
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "dsh-quota-error", children: t("widget.noBalance") }),
4037
+ body = /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "dsh-quota-body", children: [
4038
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "dsh-quota-error", children: t("widget.noBalance") }),
3766
4039
  sessionCostRow
3767
4040
  ] });
3768
4041
  }
3769
4042
  }
3770
4043
  const style = pos !== null ? { left: `${pos.x}px`, top: `${pos.y}px`, right: "auto", bottom: "auto" } : void 0;
3771
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4044
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3772
4045
  "div",
3773
4046
  {
3774
4047
  className: `dsh-quota-root${dragging ? " dsh-quota-dragging" : ""}${hidden ? " dsh-quota-root--hidden" : ""}`,
3775
4048
  style,
3776
4049
  "aria-hidden": hidden,
3777
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
4050
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
3778
4051
  "div",
3779
4052
  {
3780
4053
  ref: rootRef,
@@ -3786,14 +4059,14 @@ function QuotaWidget(props) {
3786
4059
  onPointerCancel: () => endDrag(false),
3787
4060
  onLostPointerCapture: () => endDrag(false),
3788
4061
  children: [
3789
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "dsh-quota-header", children: [
3790
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "dsh-quota-title", children: [
3791
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dsh-quota-grip", title: t("widget.dragGrip"), children: "\u2807" }),
3792
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: dotClass }),
3793
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dsh-quota-name", children: t("widget.title") })
4062
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "dsh-quota-header", children: [
4063
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "dsh-quota-title", children: [
4064
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "dsh-quota-grip", title: t("widget.dragGrip"), children: "\u2807" }),
4065
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: dotClass }),
4066
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "dsh-quota-name", children: t("widget.title") })
3794
4067
  ] }),
3795
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "dsh-quota-actions", children: [
3796
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4068
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "dsh-quota-actions", children: [
4069
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3797
4070
  "button",
3798
4071
  {
3799
4072
  className: "dsh-quota-btn",
@@ -3809,7 +4082,7 @@ function QuotaWidget(props) {
3809
4082
  children: "\u21BB"
3810
4083
  }
3811
4084
  ),
3812
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4085
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3813
4086
  "button",
3814
4087
  {
3815
4088
  className: "dsh-quota-btn",
@@ -3827,7 +4100,7 @@ function QuotaWidget(props) {
3827
4100
  )
3828
4101
  ] })
3829
4102
  ] }),
3830
- collapsed && primary !== null && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "dsh-quota-collapsed-total-row", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: `dsh-quota-collapsed-total${low ? " dsh-quota-total--low" : ""}`, children: [
4103
+ collapsed && primary !== null && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "dsh-quota-collapsed-total-row", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: `dsh-quota-collapsed-total${low ? " dsh-quota-total--low" : ""}`, children: [
3831
4104
  fmt(primary.total),
3832
4105
  " ",
3833
4106
  primary.currency
@@ -3858,7 +4131,7 @@ function conversationViewsSource(slots) {
3858
4131
  }
3859
4132
 
3860
4133
  // src/client/index.tsx
3861
- var import_jsx_runtime7 = require("react/jsx-runtime");
4134
+ var import_jsx_runtime8 = require("react/jsx-runtime");
3862
4135
  var name = "dsh-usage-dashboard";
3863
4136
  var inject = ["slots", "locale", "layout"];
3864
4137
  var openQuotaTab = null;
@@ -3879,7 +4152,11 @@ function apply(ctx) {
3879
4152
  });
3880
4153
  ctx.slots.inject("shell.overlay", () => ctx.slots.register(
3881
4154
  { name: "shell.overlay", id: "deepseek-quota", order: 1e3, locale: NS, label: () => t("widget.title") },
3882
- ({ t: slotT, useSessions }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(LocaleProvider, { t: slotT, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ErrorBoundary, { t: slotT, silent: true, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(QuotaWidget, { useSessions, views }) }) })
4155
+ ({ t: slotT, useSessions }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(LocaleProvider, { t: slotT, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ErrorBoundary, { t: slotT, silent: true, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(QuotaWidget, { useSessions, views }) }) })
4156
+ ));
4157
+ ctx.slots.inject("conversation.composer.dock", () => ctx.slots.register(
4158
+ { name: "conversation.composer.dock", id: "quota-cost", order: 2, locale: NS },
4159
+ ({ t: slotT, sessionId }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(LocaleProvider, { t: slotT, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ErrorBoundary, { t: slotT, silent: true, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SessionCostPill, { sessionId }) }) })
3883
4160
  ));
3884
4161
  ctx.slots.inject("conversation.chat.assistant-actions", () => ctx.slots.register(
3885
4162
  {
@@ -3889,13 +4166,13 @@ function apply(ctx) {
3889
4166
  locale: NS,
3890
4167
  label: () => t("messageCost.label")
3891
4168
  },
3892
- ({ t: slotT, sessionId, messageId }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(LocaleProvider, { t: slotT, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ErrorBoundary, { t: slotT, silent: true, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MessageCost, { sessionId, messageId }) }) })
4169
+ ({ t: slotT, sessionId, messageId }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(LocaleProvider, { t: slotT, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ErrorBoundary, { t: slotT, silent: true, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(MessageCost, { sessionId, messageId }) }) })
3893
4170
  ));
3894
4171
  const QuotaView = ({ t: slotT, sessionId, openView }) => {
3895
- (0, import_react7.useEffect)(() => {
4172
+ (0, import_react8.useEffect)(() => {
3896
4173
  if (openView !== void 0) openQuotaTab = openView;
3897
4174
  }, [openView]);
3898
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(LocaleProvider, { t: slotT, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ErrorBoundary, { t: slotT, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(BalanceDashboard, { sessionId, views }) }) });
4175
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(LocaleProvider, { t: slotT, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ErrorBoundary, { t: slotT, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(BalanceDashboard, { sessionId, views }) }) });
3899
4176
  };
3900
4177
  ctx.effect(() => {
3901
4178
  let disposeView = null;
@@ -3931,14 +4208,14 @@ function apply(ctx) {
3931
4208
  disposeView?.();
3932
4209
  };
3933
4210
  }, "dsh-usage-dashboard: quota tab registration");
3934
- const QuotaPanel = ({ t: slotT }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "dq-panel", children: [
3935
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "dq-panel-head", "data-window-drag": true, children: [
3936
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h1", { className: "dq-panel-title", children: slotT("nav.quota") }),
3937
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "dq-panel-caption", children: slotT("panel.caption") })
4211
+ const QuotaPanel = ({ t: slotT }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "dq-panel", children: [
4212
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "dq-panel-head", "data-window-drag": true, children: [
4213
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h1", { className: "dq-panel-title", children: slotT("nav.quota") }),
4214
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "dq-panel-caption", children: slotT("panel.caption") })
3938
4215
  ] }),
3939
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(LocaleProvider, { t: slotT, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ErrorBoundary, { t: slotT, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(BalanceDashboard, { views }) }) })
4216
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(LocaleProvider, { t: slotT, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ErrorBoundary, { t: slotT, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(BalanceDashboard, { views }) }) })
3940
4217
  ] });
3941
- const QuotaGlyph = ({ size, active }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
4218
+ const QuotaGlyph = ({ size, active }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
3942
4219
  "svg",
3943
4220
  {
3944
4221
  className: "dq-side-icon",
@@ -3954,23 +4231,23 @@ function apply(ctx) {
3954
4231
  "aria-hidden": "true",
3955
4232
  focusable: "false",
3956
4233
  children: [
3957
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M3.5 3.3 8 8.7l4.5-5.4" }),
3958
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M8 8.7V13.2" }),
3959
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M3.5 10.2h9" }),
3960
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M3.5 12.1h9" })
4234
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M3.5 3.3 8 8.7l4.5-5.4" }),
4235
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M8 8.7V13.2" }),
4236
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M3.5 10.2h9" }),
4237
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M3.5 12.1h9" })
3961
4238
  ]
3962
4239
  }
3963
4240
  );
3964
4241
  const QuotaFooterButton = ({ wide, t: slotT }) => {
3965
- const [active, setActive] = (0, import_react7.useState)(() => ctx.layout.panelInfo.getSnapshot().activePanelId === QUOTA_PANEL_ID);
3966
- (0, import_react7.useEffect)(() => {
4242
+ const [active, setActive] = (0, import_react8.useState)(() => ctx.layout.panelInfo.getSnapshot().activePanelId === QUOTA_PANEL_ID);
4243
+ (0, import_react8.useEffect)(() => {
3967
4244
  const sync = () => {
3968
4245
  setActive(ctx.layout.panelInfo.getSnapshot().activePanelId === QUOTA_PANEL_ID);
3969
4246
  };
3970
4247
  sync();
3971
4248
  return ctx.layout.panelInfo.subscribe(sync);
3972
4249
  }, []);
3973
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
4250
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
3974
4251
  "button",
3975
4252
  {
3976
4253
  type: "button",
@@ -3982,8 +4259,8 @@ function apply(ctx) {
3982
4259
  ctx.layout.selectPanel(active ? null : QUOTA_PANEL_ID);
3983
4260
  },
3984
4261
  children: [
3985
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "dq-side-entry-icon", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(QuotaGlyph, { size: 16 }) }),
3986
- wide && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "dq-side-entry-label", children: slotT("nav.quota") })
4262
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "dq-side-entry-icon", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(QuotaGlyph, { size: 16 }) }),
4263
+ wide && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "dq-side-entry-label", children: slotT("nav.quota") })
3987
4264
  ]
3988
4265
  }
3989
4266
  );