dsh-codearts 1.2.7 → 1.2.8

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
@@ -3,6 +3,21 @@
3
3
  本文件记录本插件的重要改动。格式参考 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/),
4
4
  版本号遵循 [语义化版本](https://semver.org/lang/zh-CN/)。
5
5
 
6
+ ## [1.2.8] - 2026-11-05
7
+
8
+ ### 变更
9
+
10
+ - **用量页的柱状图改成当月日历热力图**:7 列是周一到周日,从 1 号铺到最后一天,
11
+ 格子里的数字是「几号」,底色深浅是那天的 token 量分 5 档。绿阶取自 agent-acta
12
+ 的活跃热力图(`#ddf4e7` → `#16a34a`),不再拿主题灰做档位 —— 灰阶在深色卡片上
13
+ 根本分不出档。没用量但属于本月的格子留浅底,本月未来的日子只留压暗的日期数字,
14
+ 今天用加粗 + 底部一条同色短线标出来(不画边框:浅色主题下内描边会被读成一圈黑边)。
15
+ 图例「少 ▢▢▢▢▢ 多」在日历正上方(不在日历和明细行之间),色块和格子同源。
16
+ 悬停任意一格,底部那行显示当天的输入 / 缓存 / 命中率 / 请求数,和 `title` 一致。
17
+ - **逐小时也改成一格一格的**:今天 24 格一行,同一套绿阶,轴每 6 格标一个钟点。
18
+ - **趋势窗口从 7 天扩到 35 天**:`usage.recentDays` 由 7 格变 35 格(刚好覆盖任意一个
19
+ 自然月);旧宿主只给 7 格时照常画,月历里没数据的日子会退成压暗的日期。
20
+
6
21
  ## [1.2.7] - 2026-11-05
7
22
 
8
23
  ### 变更
package/lib/bin.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import { R as isBenefitModel, V as CodeArtsAccountStore, W as codeartsAccountsPath, d as fetchCallerIdentity, n as codeartsUsagePath, r as discoverModels, t as CodeArtsUsageTracker } from "./usage-4B0o-CQN.mjs";
2
+ import { R as isBenefitModel, V as CodeArtsAccountStore, W as codeartsAccountsPath, d as fetchCallerIdentity, n as codeartsUsagePath, r as discoverModels, t as CodeArtsUsageTracker } from "./usage-B2LNsUuR.mjs";
3
3
  import { existsSync, statSync } from "node:fs";
4
4
  //#region src/version.ts
5
- const CODEARTS_VERSION = "1.2.7";
5
+ const CODEARTS_VERSION = "1.2.8";
6
6
  //#endregion
7
7
  //#region src/bin.ts
8
8
  /**
@@ -89,6 +89,11 @@ interface CodeArtsSettingsKey {
89
89
  usageTrendHint: string;
90
90
  /** 逐小时是本次新增口径,启用前的小时不回填。 */
91
91
  usageTrendHourEmpty: string;
92
+ /** 热力图顶上的星期行(周一…周日,空格分隔,前端 split(' ') 成 7 列)。 */
93
+ usageHeatWeekdays: string;
94
+ /** 热力图档位图例的两端:少 ▢▢▢▢▢ 多。 */
95
+ usageHeatLess: string;
96
+ usageHeatMore: string;
92
97
  usageRequests: string;
93
98
  usageByAccount: string;
94
99
  usageRequestCount: string;
@@ -62,7 +62,7 @@ function subscribeSidebarPanelWanted(listener) {
62
62
  }
63
63
  //#endregion
64
64
  //#region \0dsh-css:/home/runner/work/dsh-codearts/dsh-codearts/src/client/CodeArtsPluginCard.module.css.mjs
65
- const css$1 = ".xoziZG_card{border:.5px solid var(--dsw-alias-settings-card-stroke);border-radius:var(--dsw-radius-lg);background:var(--dsw-alias-settings-card-fill);max-width:720px}.xoziZG_header{align-items:flex-start;gap:12px;padding:14px 16px;display:flex}.xoziZG_headText{flex-direction:column;flex:1;gap:6px;min-width:0;display:flex}.xoziZG_name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:22px}.xoziZG_desc{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:20px}.xoziZG_statusLine{color:var(--dsw-alias-label-primary);align-items:center;gap:6px;font-size:14px;font-weight:500;line-height:22px;display:inline-flex}.xoziZG_meta{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;font-size:12px;line-height:18px}.xoziZG_body{border-top:.5px solid var(--dsw-alias-border-l2);margin:0 16px;padding:4px 0 16px}.xoziZG_tabs{margin-top:12px}.xoziZG_tabPanel{padding-top:2px}.xoziZG_accountToolbar{gap:8px;margin-top:12px;display:flex}.xoziZG_accountToolbar>*{flex:1}.xoziZG_manualForm{border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-md);margin-top:12px;padding:12px}.xoziZG_accountCard{flex-direction:column;gap:10px;margin-top:12px;display:flex}.xoziZG_accountEntry{border:.5px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-2)}.xoziZG_accountRow{align-items:center;gap:10px;padding:12px;display:flex}.xoziZG_claimAllRow{border-top:.5px solid var(--dsw-alias-border-l2);justify-content:flex-end;padding:10px 12px 0;display:flex}.xoziZG_avatar{background:var(--dsw-alias-bg-layer-3);width:32px;height:32px;color:var(--dsw-alias-label-primary);border-radius:50%;flex:none;justify-content:center;align-items:center;font-size:14px;font-weight:600;display:inline-flex}.xoziZG_accountInfo{flex-direction:column;flex:1;gap:2px;min-width:0;display:flex}.xoziZG_accountNameRow{align-items:center;gap:6px;min-width:0;display:flex}.xoziZG_accountName{color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;font-size:14px;font-weight:600;line-height:20px;overflow:hidden}.xoziZG_accountRowActions{flex:none;gap:6px;display:flex}.xoziZG_accountHint{color:var(--dsw-alias-label-tertiary);margin:0;padding:0 12px 12px;font-size:12px;line-height:18px}.xoziZG_creditBlock{border-top:.5px solid var(--dsw-alias-border-l2);padding:12px}.xoziZG_balanceRow{flex-wrap:wrap;align-items:baseline;gap:6px;display:flex}.xoziZG_balance{color:var(--dsw-alias-label-primary);letter-spacing:-.02em;font-variant-numeric:tabular-nums;font-size:28px;font-weight:600;line-height:34px}.xoziZG_balanceUnit{color:var(--dsw-alias-label-secondary);font-size:12px}.xoziZG_balanceMeta{color:var(--dsw-alias-label-tertiary);margin-left:2px;font-size:12px}.xoziZG_updated{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;margin-left:auto;font-size:12px}.xoziZG_creditRows{flex-direction:column;gap:4px;margin-top:8px;display:flex}.xoziZG_creditRow{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;justify-content:space-between;align-items:baseline;gap:12px;font-size:12px;line-height:18px;display:flex}.xoziZG_usageBar{background:var(--dsw-alias-border-l2);border-radius:2px;height:4px;margin-top:4px;display:block;overflow:hidden}.xoziZG_usageFill{background:var(--dsw-alias-brand-primary);border-radius:2px;height:100%;transition:width .2s;display:block}.xoziZG_expiryRow{margin-top:2px}.xoziZG_expiryLabel{color:var(--dsw-alias-state-warn-label)}.xoziZG_bar{background:var(--dsw-alias-bg-layer-3);border-radius:2px;height:4px;margin-top:6px;display:block;overflow:hidden}.xoziZG_barFill{background:var(--dsw-alias-state-warn-primary);border-radius:2px;height:100%;display:block}.xoziZG_creditLink{margin-top:8px;display:inline-block}.xoziZG_creditFooter{border-top:.5px solid var(--dsw-alias-border-l2);justify-content:space-between;align-items:center;gap:8px;margin-top:12px;padding-top:10px;display:flex}.xoziZG_creditHint{color:var(--dsw-alias-label-tertiary);margin:8px 0 0;font-size:12px;line-height:18px}.xoziZG_section{margin-top:16px}.xoziZG_sectionHead{justify-content:space-between;align-items:baseline;gap:12px;display:flex}.xoziZG_sectionLabel{color:var(--dsw-alias-label-tertiary);font-size:11px;font-weight:500}.xoziZG_count{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;flex:none;font-size:12px}.xoziZG_hint{color:var(--dsw-alias-label-secondary);margin:8px 0 0;font-size:13px;line-height:20px}.xoziZG_error{color:var(--dsw-alias-state-error-primary);margin:10px 0 0;font-size:13px;line-height:20px}.xoziZG_actions{flex-wrap:wrap;align-items:center;gap:8px;margin-top:12px;display:flex}.xoziZG_danger{color:var(--dsw-alias-state-error-primary)}.xoziZG_link{appearance:none;color:var(--dsw-alias-brand-text);font:inherit;text-align:left;word-break:break-all;cursor:pointer;background:0 0;border:none;padding:0;font-size:12px}.xoziZG_link:hover{text-decoration:underline}.xoziZG_choices{flex-direction:column;gap:2px;margin-top:8px;display:flex}.xoziZG_choiceRow{border-radius:var(--dsw-radius-sm);align-items:center;gap:8px;margin:0 -6px;padding:5px 6px;display:flex}.xoziZG_choiceRow:hover{background:var(--dsw-alias-interactive-bg-hover)}.xoziZG_statGrid{grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;margin:10px 0 14px;display:grid}.xoziZG_statCard{border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-md);flex-direction:column;gap:1px;padding:8px 10px;display:flex}.xoziZG_statLabel{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px}.xoziZG_statValue{color:var(--dsw-alias-label-primary);font-variant-numeric:tabular-nums;font-size:15px;line-height:20px}.xoziZG_statSub{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;font-size:11px;line-height:16px}.xoziZG_modelChart{flex-direction:column;gap:2px;margin-top:8px;display:flex}.xoziZG_modelRow{font-variant-numeric:tabular-nums;border-radius:6px;grid-template-columns:minmax(0,1.2fr) minmax(48px,1fr) 56px 52px 64px;align-items:center;gap:8px;padding:4px 0;display:grid;position:relative}.xoziZG_modelRow:hover{background:var(--dsw-alias-interactive-bg-hover)}.xoziZG_usageTip{z-index:5;border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-3);min-width:180px;max-width:260px;color:var(--dsw-alias-label-secondary);text-align:left;font-variant-numeric:tabular-nums;pointer-events:none;padding:8px 10px;font-size:12px;line-height:1.9;position:absolute;bottom:calc(100% + 6px);right:0;box-shadow:0 10px 28px #00000073}.xoziZG_usageTipName{max-width:240px;color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.xoziZG_usageTipSep{background:var(--dsw-alias-border-l2);height:1px;margin:4px 0}.xoziZG_usageTipRow{justify-content:space-between;gap:24px;display:flex}.xoziZG_usageTipRow span:last-child{color:var(--dsw-alias-label-primary);font-weight:600}.xoziZG_modelName{color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;font-size:12px;line-height:18px;overflow:hidden}.xoziZG_modelTrack{background:var(--dsw-alias-border-l2);border-radius:4px;height:8px;display:block;overflow:hidden}.xoziZG_modelFill{background:var(--dsw-alias-brand-primary);border-radius:4px;height:100%;transition:width .16s;display:block}.xoziZG_modelTokens,.xoziZG_modelShare,.xoziZG_modelRequests{color:var(--dsw-alias-label-secondary);text-align:right;white-space:nowrap;font-size:11px;line-height:16px}.xoziZG_modelRequests{color:var(--dsw-alias-label-tertiary)}.xoziZG_trendBars{align-items:flex-end;gap:3px;height:44px;margin:8px 0 2px;display:flex}.xoziZG_trendSlot{flex-direction:column;flex:1;justify-content:flex-end;min-width:0;height:100%;display:flex}.xoziZG_trendBar{background:var(--dsw-alias-brand-primary);border-radius:2px 2px 0 0;min-height:2px;transition:height .16s,background .16s}.xoziZG_trendBar[data-tone=mid]{background:var(--dsw-alias-state-warn-label)}.xoziZG_trendBar[data-tone=low]{background:var(--dsw-alias-state-error-primary,var(--dsw-alias-state-warn-label))}.xoziZG_trendBar[data-tone=empty]{background:var(--dsw-alias-border-l2)}.xoziZG_trendAxis{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;gap:3px;font-size:10px;line-height:14px;display:flex}.xoziZG_trendAxisSlot{text-align:center;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.xoziZG_trendTip{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;margin:2px 0 0;font-size:11px;line-height:16px}.xoziZG_check{flex:1;min-width:0}.xoziZG_check>span{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.xoziZG_manual{border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-md);margin-top:12px;padding:0 12px}.xoziZG_manual[open]{padding-bottom:12px}.xoziZG_manualSummary{color:var(--dsw-alias-label-secondary);cursor:pointer;align-items:center;gap:6px;padding:9px 0;font-size:13px;list-style:none;display:flex}.xoziZG_manualSummary::-webkit-details-marker{display:none}.xoziZG_field{flex-direction:column;gap:5px;margin-top:10px;display:flex}.xoziZG_fieldLabel{color:var(--dsw-alias-label-tertiary);font-size:12px}.xoziZG_area{box-sizing:border-box;resize:vertical;border:.5px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-1);width:100%;color:var(--dsw-alias-label-primary);padding:6px 8px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:13px;line-height:20px}.xoziZG_area::placeholder{color:var(--dsw-alias-label-dimmed)}.xoziZG_area:focus{border-color:var(--dsw-alias-state-business-primary);outline:none}.xoziZG_skeleton{flex-direction:column;gap:10px;padding:4px 0;display:flex}.xoziZG_skeletonRow{border-radius:var(--dsw-radius-sm,4px);background:var(--dsw-alias-border-l2);height:12px;animation:1.4s ease-in-out infinite xoziZG_skeletonBreath}.xoziZG_skeletonRow:nth-child(2){width:72%}.xoziZG_skeletonRow:nth-child(3){width:46%}@keyframes xoziZG_skeletonBreath{0%,to{opacity:.45}50%{opacity:.9}}@media (prefers-reduced-motion:reduce){.xoziZG_skeletonRow{animation:none}}";
65
+ const css$1 = ".xoziZG_card{border:.5px solid var(--dsw-alias-settings-card-stroke);border-radius:var(--dsw-radius-lg);background:var(--dsw-alias-settings-card-fill);max-width:720px}.xoziZG_header{align-items:flex-start;gap:12px;padding:14px 16px;display:flex}.xoziZG_headText{flex-direction:column;flex:1;gap:6px;min-width:0;display:flex}.xoziZG_name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:22px}.xoziZG_desc{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:20px}.xoziZG_statusLine{color:var(--dsw-alias-label-primary);align-items:center;gap:6px;font-size:14px;font-weight:500;line-height:22px;display:inline-flex}.xoziZG_meta{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;font-size:12px;line-height:18px}.xoziZG_body{border-top:.5px solid var(--dsw-alias-border-l2);margin:0 16px;padding:4px 0 16px}.xoziZG_tabs{margin-top:12px}.xoziZG_tabPanel{padding-top:2px}.xoziZG_accountToolbar{gap:8px;margin-top:12px;display:flex}.xoziZG_accountToolbar>*{flex:1}.xoziZG_manualForm{border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-md);margin-top:12px;padding:12px}.xoziZG_accountCard{flex-direction:column;gap:10px;margin-top:12px;display:flex}.xoziZG_accountEntry{border:.5px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-2)}.xoziZG_accountRow{align-items:center;gap:10px;padding:12px;display:flex}.xoziZG_claimAllRow{border-top:.5px solid var(--dsw-alias-border-l2);justify-content:flex-end;padding:10px 12px 0;display:flex}.xoziZG_avatar{background:var(--dsw-alias-bg-layer-3);width:32px;height:32px;color:var(--dsw-alias-label-primary);border-radius:50%;flex:none;justify-content:center;align-items:center;font-size:14px;font-weight:600;display:inline-flex}.xoziZG_accountInfo{flex-direction:column;flex:1;gap:2px;min-width:0;display:flex}.xoziZG_accountNameRow{align-items:center;gap:6px;min-width:0;display:flex}.xoziZG_accountName{color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;font-size:14px;font-weight:600;line-height:20px;overflow:hidden}.xoziZG_accountRowActions{flex:none;gap:6px;display:flex}.xoziZG_accountHint{color:var(--dsw-alias-label-tertiary);margin:0;padding:0 12px 12px;font-size:12px;line-height:18px}.xoziZG_creditBlock{border-top:.5px solid var(--dsw-alias-border-l2);padding:12px}.xoziZG_balanceRow{flex-wrap:wrap;align-items:baseline;gap:6px;display:flex}.xoziZG_balance{color:var(--dsw-alias-label-primary);letter-spacing:-.02em;font-variant-numeric:tabular-nums;font-size:28px;font-weight:600;line-height:34px}.xoziZG_balanceUnit{color:var(--dsw-alias-label-secondary);font-size:12px}.xoziZG_balanceMeta{color:var(--dsw-alias-label-tertiary);margin-left:2px;font-size:12px}.xoziZG_updated{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;margin-left:auto;font-size:12px}.xoziZG_creditRows{flex-direction:column;gap:4px;margin-top:8px;display:flex}.xoziZG_creditRow{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;justify-content:space-between;align-items:baseline;gap:12px;font-size:12px;line-height:18px;display:flex}.xoziZG_usageBar{background:var(--dsw-alias-border-l2);border-radius:2px;height:4px;margin-top:4px;display:block;overflow:hidden}.xoziZG_usageFill{background:var(--dsw-alias-brand-primary);border-radius:2px;height:100%;transition:width .2s;display:block}.xoziZG_expiryRow{margin-top:2px}.xoziZG_expiryLabel{color:var(--dsw-alias-state-warn-label)}.xoziZG_bar{background:var(--dsw-alias-bg-layer-3);border-radius:2px;height:4px;margin-top:6px;display:block;overflow:hidden}.xoziZG_barFill{background:var(--dsw-alias-state-warn-primary);border-radius:2px;height:100%;display:block}.xoziZG_creditLink{margin-top:8px;display:inline-block}.xoziZG_creditFooter{border-top:.5px solid var(--dsw-alias-border-l2);justify-content:space-between;align-items:center;gap:8px;margin-top:12px;padding-top:10px;display:flex}.xoziZG_creditHint{color:var(--dsw-alias-label-tertiary);margin:8px 0 0;font-size:12px;line-height:18px}.xoziZG_section{margin-top:16px}.xoziZG_sectionHead{justify-content:space-between;align-items:baseline;gap:12px;display:flex}.xoziZG_sectionLabel{color:var(--dsw-alias-label-tertiary);font-size:11px;font-weight:500}.xoziZG_count{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;flex:none;font-size:12px}.xoziZG_hint{color:var(--dsw-alias-label-secondary);margin:8px 0 0;font-size:13px;line-height:20px}.xoziZG_error{color:var(--dsw-alias-state-error-primary);margin:10px 0 0;font-size:13px;line-height:20px}.xoziZG_actions{flex-wrap:wrap;align-items:center;gap:8px;margin-top:12px;display:flex}.xoziZG_danger{color:var(--dsw-alias-state-error-primary)}.xoziZG_link{appearance:none;color:var(--dsw-alias-brand-text);font:inherit;text-align:left;word-break:break-all;cursor:pointer;background:0 0;border:none;padding:0;font-size:12px}.xoziZG_link:hover{text-decoration:underline}.xoziZG_choices{flex-direction:column;gap:2px;margin-top:8px;display:flex}.xoziZG_choiceRow{border-radius:var(--dsw-radius-sm);align-items:center;gap:8px;margin:0 -6px;padding:5px 6px;display:flex}.xoziZG_choiceRow:hover{background:var(--dsw-alias-interactive-bg-hover)}.xoziZG_statGrid{grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;margin:10px 0 14px;display:grid}.xoziZG_statCard{border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-md);flex-direction:column;gap:1px;padding:8px 10px;display:flex}.xoziZG_statLabel{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px}.xoziZG_statValue{color:var(--dsw-alias-label-primary);font-variant-numeric:tabular-nums;font-size:15px;line-height:20px}.xoziZG_statSub{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;font-size:11px;line-height:16px}.xoziZG_modelChart{flex-direction:column;gap:2px;margin-top:8px;display:flex}.xoziZG_modelRow{font-variant-numeric:tabular-nums;border-radius:6px;grid-template-columns:minmax(0,1.2fr) minmax(48px,1fr) 56px 52px 64px;align-items:center;gap:8px;padding:4px 0;display:grid;position:relative}.xoziZG_modelRow:hover{background:var(--dsw-alias-interactive-bg-hover)}.xoziZG_usageTip{z-index:5;border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-3);min-width:180px;max-width:260px;color:var(--dsw-alias-label-secondary);text-align:left;font-variant-numeric:tabular-nums;pointer-events:none;padding:8px 10px;font-size:12px;line-height:1.9;position:absolute;bottom:calc(100% + 6px);right:0;box-shadow:0 10px 28px #00000073}.xoziZG_usageTipName{max-width:240px;color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.xoziZG_usageTipSep{background:var(--dsw-alias-border-l2);height:1px;margin:4px 0}.xoziZG_usageTipRow{justify-content:space-between;gap:24px;display:flex}.xoziZG_usageTipRow span:last-child{color:var(--dsw-alias-label-primary);font-weight:600}.xoziZG_modelName{color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;font-size:12px;line-height:18px;overflow:hidden}.xoziZG_modelTrack{background:var(--dsw-alias-border-l2);border-radius:4px;height:8px;display:block;overflow:hidden}.xoziZG_modelFill{background:var(--dsw-alias-brand-primary);border-radius:4px;height:100%;transition:width .16s;display:block}.xoziZG_modelTokens,.xoziZG_modelShare,.xoziZG_modelRequests{color:var(--dsw-alias-label-secondary);text-align:right;white-space:nowrap;font-size:11px;line-height:16px}.xoziZG_modelRequests{color:var(--dsw-alias-label-tertiary)}.xoziZG_heatGrid{grid-template-columns:repeat(7,minmax(0,1fr));gap:4px;margin:8px 0 2px;display:grid}.xoziZG_heatWeekday{color:var(--dsw-alias-label-tertiary);text-align:center;font-size:10px;line-height:14px}.xoziZG_heatCell{background:color-mix(in srgb, var(--dsw-alias-label-primary) 6%, transparent);height:36px;color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;border:0;border-radius:8px;outline:0;justify-content:center;align-items:center;font-size:12px;transition:background .12s ease-out;display:flex}.xoziZG_heatCell[data-tone=empty]{color:var(--dsw-alias-label-tertiary)}.xoziZG_heatCell[data-tone=pad]{background:0 0}.xoziZG_heatCell[data-tone=out]{color:var(--dsw-alias-label-tertiary);opacity:.45;background:0 0}.xoziZG_heatCell[data-tone=lv1]{color:#0f1115;background:#ddf4e7}.xoziZG_heatCell[data-tone=lv2]{color:#0f1115;background:#b3e8cc}.xoziZG_heatCell[data-tone=lv3]{color:#0f1115;background:#7dd8ac}.xoziZG_heatCell[data-tone=lv4]{color:#fff;background:#40c584}.xoziZG_heatCell[data-tone=lv5]{color:#fff;background:#16a34a}.xoziZG_heatCell[data-today=true]{font-weight:700;box-shadow:inset 0 -2px}.xoziZG_heatHours{grid-template-columns:repeat(24,minmax(0,1fr));gap:3px;margin:8px 0 0;display:grid}.xoziZG_heatHourCell{background:color-mix(in srgb, var(--dsw-alias-label-primary) 6%, transparent);border-radius:4px;height:26px;transition:background .12s ease-out}.xoziZG_heatHourCell[data-tone=lv1]{background:#ddf4e7}.xoziZG_heatHourCell[data-tone=lv2]{background:#b3e8cc}.xoziZG_heatHourCell[data-tone=lv3]{background:#7dd8ac}.xoziZG_heatHourCell[data-tone=lv4]{background:#40c584}.xoziZG_heatHourCell[data-tone=lv5]{background:#16a34a}.xoziZG_heatAxis{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;grid-template-columns:repeat(24,minmax(0,1fr));gap:3px;font-size:10px;line-height:14px;display:grid}.xoziZG_heatAxisSlot{text-align:center;white-space:nowrap;overflow:hidden}.xoziZG_heatLegend{color:var(--dsw-alias-label-tertiary);justify-content:flex-start;align-items:center;gap:3px;margin:0 0 6px;font-size:10px;display:flex}.xoziZG_heatLegendChip{border-radius:3px;width:10px;height:10px}.xoziZG_heatLegendChip[data-tone=lv1]{background:#ddf4e7}.xoziZG_heatLegendChip[data-tone=lv2]{background:#b3e8cc}.xoziZG_heatLegendChip[data-tone=lv3]{background:#7dd8ac}.xoziZG_heatLegendChip[data-tone=lv4]{background:#40c584}.xoziZG_heatLegendChip[data-tone=lv5]{background:#16a34a}.xoziZG_trendTip{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;margin:2px 0 0;font-size:11px;line-height:16px}.xoziZG_check{flex:1;min-width:0}.xoziZG_check>span{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.xoziZG_manual{border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-md);margin-top:12px;padding:0 12px}.xoziZG_manual[open]{padding-bottom:12px}.xoziZG_manualSummary{color:var(--dsw-alias-label-secondary);cursor:pointer;align-items:center;gap:6px;padding:9px 0;font-size:13px;list-style:none;display:flex}.xoziZG_manualSummary::-webkit-details-marker{display:none}.xoziZG_field{flex-direction:column;gap:5px;margin-top:10px;display:flex}.xoziZG_fieldLabel{color:var(--dsw-alias-label-tertiary);font-size:12px}.xoziZG_area{box-sizing:border-box;resize:vertical;border:.5px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-1);width:100%;color:var(--dsw-alias-label-primary);padding:6px 8px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:13px;line-height:20px}.xoziZG_area::placeholder{color:var(--dsw-alias-label-dimmed)}.xoziZG_area:focus{border-color:var(--dsw-alias-state-business-primary);outline:none}.xoziZG_skeleton{flex-direction:column;gap:10px;padding:4px 0;display:flex}.xoziZG_skeletonRow{border-radius:var(--dsw-radius-sm,4px);background:var(--dsw-alias-border-l2);height:12px;animation:1.4s ease-in-out infinite xoziZG_skeletonBreath}.xoziZG_skeletonRow:nth-child(2){width:72%}.xoziZG_skeletonRow:nth-child(3){width:46%}@keyframes xoziZG_skeletonBreath{0%,to{opacity:.45}50%{opacity:.9}}@media (prefers-reduced-motion:reduce){.xoziZG_skeletonRow{animation:none}}";
66
66
  const tagId$1 = "dsh-codearts/CodeArtsPluginCard.module.css";
67
67
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
68
68
  const tag = document.createElement("style");
@@ -72,88 +72,92 @@ if (typeof document !== "undefined" && document.querySelector("style[data-plugin
72
72
  document.head.appendChild(tag);
73
73
  }
74
74
  var CodeArtsPluginCard_module_css_default = {
75
- "section": "xoziZG_section",
76
- "creditBlock": "xoziZG_creditBlock",
77
- "balance": "xoziZG_balance",
75
+ "heatWeekday": "xoziZG_heatWeekday",
76
+ "headText": "xoziZG_headText",
77
+ "sectionLabel": "xoziZG_sectionLabel",
78
+ "avatar": "xoziZG_avatar",
79
+ "usageFill": "xoziZG_usageFill",
80
+ "creditLink": "xoziZG_creditLink",
81
+ "modelRequests": "xoziZG_modelRequests",
82
+ "hint": "xoziZG_hint",
78
83
  "usageTipSep": "xoziZG_usageTipSep",
79
- "trendAxisSlot": "xoziZG_trendAxisSlot",
80
- "skeletonRow": "xoziZG_skeletonRow",
81
- "updated": "xoziZG_updated",
82
- "desc": "xoziZG_desc",
83
- "creditHint": "xoziZG_creditHint",
84
- "modelChart": "xoziZG_modelChart",
84
+ "usageTipRow": "xoziZG_usageTipRow",
85
+ "expiryLabel": "xoziZG_expiryLabel",
86
+ "area": "xoziZG_area",
87
+ "balanceUnit": "xoziZG_balanceUnit",
88
+ "sectionHead": "xoziZG_sectionHead",
89
+ "danger": "xoziZG_danger",
90
+ "modelFill": "xoziZG_modelFill",
85
91
  "creditRow": "xoziZG_creditRow",
86
- "bar": "xoziZG_bar",
92
+ "choices": "xoziZG_choices",
93
+ "modelRow": "xoziZG_modelRow",
94
+ "creditHint": "xoziZG_creditHint",
95
+ "desc": "xoziZG_desc",
96
+ "header": "xoziZG_header",
97
+ "accountHint": "xoziZG_accountHint",
98
+ "heatCell": "xoziZG_heatCell",
99
+ "heatLegendChip": "xoziZG_heatLegendChip",
100
+ "check": "xoziZG_check",
101
+ "fieldLabel": "xoziZG_fieldLabel",
87
102
  "statusLine": "xoziZG_statusLine",
88
- "trendAxis": "xoziZG_trendAxis",
89
- "modelShare": "xoziZG_modelShare",
90
- "statSub": "xoziZG_statSub",
103
+ "skeletonRow": "xoziZG_skeletonRow",
104
+ "tabPanel": "xoziZG_tabPanel",
105
+ "accountInfo": "xoziZG_accountInfo",
106
+ "usageBar": "xoziZG_usageBar",
107
+ "heatHourCell": "xoziZG_heatHourCell",
108
+ "creditFooter": "xoziZG_creditFooter",
109
+ "statValue": "xoziZG_statValue",
110
+ "balance": "xoziZG_balance",
91
111
  "tabs": "xoziZG_tabs",
92
- "accountRow": "xoziZG_accountRow",
93
- "choices": "xoziZG_choices",
112
+ "count": "xoziZG_count",
94
113
  "usageTip": "xoziZG_usageTip",
95
- "balanceUnit": "xoziZG_balanceUnit",
96
- "accountNameRow": "xoziZG_accountNameRow",
97
- "accountRowActions": "xoziZG_accountRowActions",
114
+ "claimAllRow": "xoziZG_claimAllRow",
98
115
  "creditRows": "xoziZG_creditRows",
99
- "usageTipName": "xoziZG_usageTipName",
100
- "creditFooter": "xoziZG_creditFooter",
101
- "error": "xoziZG_error",
102
- "modelFill": "xoziZG_modelFill",
103
- "expiryLabel": "xoziZG_expiryLabel",
104
- "manualSummary": "xoziZG_manualSummary",
105
- "expiryRow": "xoziZG_expiryRow",
106
- "check": "xoziZG_check",
107
116
  "link": "xoziZG_link",
108
- "sectionLabel": "xoziZG_sectionLabel",
109
- "area": "xoziZG_area",
117
+ "accountNameRow": "xoziZG_accountNameRow",
118
+ "accountName": "xoziZG_accountName",
119
+ "modelShare": "xoziZG_modelShare",
120
+ "choiceRow": "xoziZG_choiceRow",
121
+ "manual": "xoziZG_manual",
122
+ "modelTokens": "xoziZG_modelTokens",
110
123
  "skeleton": "xoziZG_skeleton",
111
- "trendBars": "xoziZG_trendBars",
112
- "field": "xoziZG_field",
113
- "modelName": "xoziZG_modelName",
114
- "usageTipRow": "xoziZG_usageTipRow",
124
+ "statSub": "xoziZG_statSub",
125
+ "usageTipName": "xoziZG_usageTipName",
126
+ "heatAxis": "xoziZG_heatAxis",
127
+ "name": "xoziZG_name",
115
128
  "card": "xoziZG_card",
116
- "meta": "xoziZG_meta",
117
- "claimAllRow": "xoziZG_claimAllRow",
118
- "sectionHead": "xoziZG_sectionHead",
119
- "usageFill": "xoziZG_usageFill",
120
- "modelRequests": "xoziZG_modelRequests",
121
- "trendTip": "xoziZG_trendTip",
122
- "fieldLabel": "xoziZG_fieldLabel",
129
+ "manualForm": "xoziZG_manualForm",
130
+ "accountCard": "xoziZG_accountCard",
123
131
  "statGrid": "xoziZG_statGrid",
124
- "skeletonBreath": "xoziZG_skeletonBreath",
125
- "modelTokens": "xoziZG_modelTokens",
126
- "trendBar": "xoziZG_trendBar",
127
- "tabPanel": "xoziZG_tabPanel",
128
- "creditLink": "xoziZG_creditLink",
129
- "name": "xoziZG_name",
130
- "accountHint": "xoziZG_accountHint",
131
- "choiceRow": "xoziZG_choiceRow",
132
132
  "modelTrack": "xoziZG_modelTrack",
133
- "accountToolbar": "xoziZG_accountToolbar",
134
- "accountCard": "xoziZG_accountCard",
135
- "accountEntry": "xoziZG_accountEntry",
136
- "danger": "xoziZG_danger",
137
- "trendSlot": "xoziZG_trendSlot",
138
- "headText": "xoziZG_headText",
139
- "count": "xoziZG_count",
140
- "manual": "xoziZG_manual",
141
- "accountName": "xoziZG_accountName",
142
- "balanceRow": "xoziZG_balanceRow",
143
- "avatar": "xoziZG_avatar",
144
- "manualForm": "xoziZG_manualForm",
145
- "hint": "xoziZG_hint",
146
- "statValue": "xoziZG_statValue",
147
- "header": "xoziZG_header",
148
- "accountInfo": "xoziZG_accountInfo",
133
+ "accountRowActions": "xoziZG_accountRowActions",
134
+ "actions": "xoziZG_actions",
135
+ "trendTip": "xoziZG_trendTip",
136
+ "field": "xoziZG_field",
137
+ "creditBlock": "xoziZG_creditBlock",
138
+ "error": "xoziZG_error",
139
+ "statCard": "xoziZG_statCard",
140
+ "heatLegend": "xoziZG_heatLegend",
149
141
  "statLabel": "xoziZG_statLabel",
150
- "modelRow": "xoziZG_modelRow",
142
+ "barFill": "xoziZG_barFill",
143
+ "meta": "xoziZG_meta",
144
+ "modelChart": "xoziZG_modelChart",
145
+ "balanceRow": "xoziZG_balanceRow",
146
+ "bar": "xoziZG_bar",
147
+ "section": "xoziZG_section",
148
+ "heatGrid": "xoziZG_heatGrid",
149
+ "heatAxisSlot": "xoziZG_heatAxisSlot",
150
+ "heatHours": "xoziZG_heatHours",
151
+ "manualSummary": "xoziZG_manualSummary",
151
152
  "body": "xoziZG_body",
152
153
  "balanceMeta": "xoziZG_balanceMeta",
153
- "barFill": "xoziZG_barFill",
154
- "actions": "xoziZG_actions",
155
- "statCard": "xoziZG_statCard",
156
- "usageBar": "xoziZG_usageBar"
154
+ "expiryRow": "xoziZG_expiryRow",
155
+ "skeletonBreath": "xoziZG_skeletonBreath",
156
+ "accountEntry": "xoziZG_accountEntry",
157
+ "accountRow": "xoziZG_accountRow",
158
+ "accountToolbar": "xoziZG_accountToolbar",
159
+ "updated": "xoziZG_updated",
160
+ "modelName": "xoziZG_modelName"
157
161
  };
158
162
  //#endregion
159
163
  //#region src/client/CodeArtsPluginCard.tsx
@@ -535,50 +539,133 @@ function UsageBars({ rows, t }) {
535
539
  })
536
540
  });
537
541
  }
542
+ /** 一格 token 量在整组里的深浅档:0 是空格,其余按相对最大值分 5 档。 */
543
+ function toneOf(volume, max) {
544
+ if (volume <= 0 || max <= 0) return "empty";
545
+ const ratio = volume / max;
546
+ if (ratio < .15) return "lv1";
547
+ if (ratio < .35) return "lv2";
548
+ if (ratio < .6) return "lv3";
549
+ if (ratio < .85) return "lv4";
550
+ return "lv5";
551
+ }
552
+ /** 「YYYY-MM-DD」是本地日历日,不能丢给 `new Date(string)`(会被当成 UTC)。返回周一=0…周日=6。 */
553
+ function weekdayOf(date) {
554
+ const [year, month, day] = date.split("-").map(Number);
555
+ return (new Date(year, month - 1, day).getDay() + 6) % 7;
556
+ }
538
557
  /**
539
- * 趋势柱:近 7 天按天、今天按小时。
558
+ * 当月的每日热力图:7 列是周一到周日,格子里的数字是「几号」,底色深浅是那天的 token 量。
540
559
  *
541
- * 两张图共用一套柱子,但编码不同,因为要看的问题不同:
542
- * - `hit`:柱高就是命中率,颜色分档 —— 命中率一掉就能看见,这是诊断「系统提示词
543
- * 前缀变了 / 上下文突然变长」最直接的信号;
544
- * - `volume`:柱高按组内最大值归一化 —— 只用来看「什么时候在跑」,绝对值看悬停。
560
+ * 画整月而不是「最近 N 天」:日历是熟人界面,缺的格子一眼就知道是「还没到」还是「没用量」;
561
+ * 颜色用 agent-acta 那套绿阶。精确数字(输入 / 缓存 / 命中率 / 条数)全放进悬停提示。
562
+ */
563
+ function UsageHeat({ days, t }) {
564
+ const [hovered, setHovered] = (0, react.useState)(null);
565
+ const last = days.at(-1);
566
+ const month = last?.date.slice(0, 7) ?? "";
567
+ const inMonth = days.filter((day) => day.date.startsWith(month));
568
+ const max = inMonth.reduce((peak, day) => Math.max(peak, day.totals.totalTokens), 0);
569
+ const [year, monthNo] = month.split("-").map(Number);
570
+ const span = month === "" ? [] : Array.from({ length: new Date(year, monthNo, 0).getDate() }, (_, index) => {
571
+ const day = index + 1;
572
+ const date = `${month}-${String(day).padStart(2, "0")}`;
573
+ return {
574
+ date,
575
+ day,
576
+ totals: inMonth.find((entry) => entry.date === date)?.totals,
577
+ future: last !== void 0 && date > last.date
578
+ };
579
+ });
580
+ const offset = month === "" ? 0 : weekdayOf(`${month}-01`);
581
+ const shown = span.find((entry) => entry.date === hovered);
582
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
583
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
584
+ className: CodeArtsPluginCard_module_css_default.heatLegend,
585
+ children: [
586
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("usageHeatLess") }),
587
+ [
588
+ "lv1",
589
+ "lv2",
590
+ "lv3",
591
+ "lv4",
592
+ "lv5"
593
+ ].map((tone) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
594
+ className: CodeArtsPluginCard_module_css_default.heatLegendChip,
595
+ "data-tone": tone
596
+ }, tone)),
597
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("usageHeatMore") })
598
+ ]
599
+ }),
600
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
601
+ className: CodeArtsPluginCard_module_css_default.heatGrid,
602
+ children: [
603
+ t("usageHeatWeekdays").split(" ").map((label) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
604
+ className: CodeArtsPluginCard_module_css_default.heatWeekday,
605
+ children: label
606
+ }, label)),
607
+ Array.from({ length: offset }, (_, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
608
+ className: CodeArtsPluginCard_module_css_default.heatCell,
609
+ "data-tone": "pad"
610
+ }, `pad-${String(index)}`)),
611
+ span.map((entry) => {
612
+ const tone = entry.future ? "out" : entry.totals === void 0 ? "empty" : toneOf(entry.totals.totalTokens, max);
613
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
614
+ className: CodeArtsPluginCard_module_css_default.heatCell,
615
+ "data-tone": tone,
616
+ "data-today": entry.date === last?.date ? "true" : void 0,
617
+ title: entry.totals === void 0 ? void 0 : `${entry.date} · ${trendDetail(entry.totals, t)}`,
618
+ onMouseEnter: entry.totals === void 0 ? void 0 : () => {
619
+ setHovered(entry.date);
620
+ },
621
+ onMouseLeave: entry.totals === void 0 ? void 0 : () => {
622
+ setHovered(null);
623
+ },
624
+ children: entry.day
625
+ }, entry.date);
626
+ })
627
+ ]
628
+ }),
629
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
630
+ className: CodeArtsPluginCard_module_css_default.trendTip,
631
+ children: shown?.totals === void 0 ? t("usageTrendHint") : `${shown.date} · ${trendDetail(shown.totals, t)}`
632
+ })
633
+ ] });
634
+ }
635
+ /**
636
+ * 今天逐小时:一行 24 格,深浅同样是相对最大值的档位,轴标签每 6 格画一个。
545
637
  *
546
- * 悬停柱子时下面那行换成该格明细,移开回到提示语。轴标签只画整数倍格,24 格全画会挤成一片。
638
+ * 只在有真实小时桶时画 —— 功能上线前的小时没有回填,全画成空格会被误读成「跑了但没用量」。
547
639
  */
548
- function UsageTrend({ points, mode, axisEvery, hint, t }) {
640
+ function UsageHours({ hours, t }) {
549
641
  const [hovered, setHovered] = (0, react.useState)(null);
550
- const max = points.reduce((peak, point) => Math.max(peak, point.totals.totalTokens), 0);
551
- const shown = hovered === null ? void 0 : points[hovered];
642
+ const max = hours.reduce((peak, hour) => Math.max(peak, hour.totals.totalTokens), 0);
643
+ const shown = hovered === null ? void 0 : hours.find((entry) => entry.hour === hovered);
552
644
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
553
645
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
554
- className: CodeArtsPluginCard_module_css_default.trendBars,
555
- children: points.map((point, index) => {
556
- const pct = hitPercentOf(point.totals);
557
- const share = mode === "hit" ? pct === void 0 ? 0 : Math.max(pct, 2) : max === 0 ? 0 : point.totals.totalTokens / max * 100;
558
- const tone = mode === "hit" ? pct === void 0 ? "empty" : pct >= 80 ? "ok" : pct >= 50 ? "mid" : "low" : point.totals.totalTokens === 0 ? "empty" : "ok";
559
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
560
- className: CodeArtsPluginCard_module_css_default.trendSlot,
561
- title: `${point.label} · ${trendDetail(point.totals, t)}`,
562
- onMouseEnter: () => setHovered(index),
563
- onMouseLeave: () => setHovered(null),
564
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
565
- className: CodeArtsPluginCard_module_css_default.trendBar,
566
- "data-tone": tone,
567
- style: { height: `${share}%` }
568
- })
569
- }, point.key);
570
- })
646
+ className: CodeArtsPluginCard_module_css_default.heatHours,
647
+ children: hours.map((entry) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
648
+ className: CodeArtsPluginCard_module_css_default.heatHourCell,
649
+ "data-tone": toneOf(entry.totals.totalTokens, max),
650
+ title: `${String(entry.hour)}:00 · ${trendDetail(entry.totals, t)}`,
651
+ onMouseEnter: () => {
652
+ setHovered(entry.hour);
653
+ },
654
+ onMouseLeave: () => {
655
+ setHovered(null);
656
+ }
657
+ }, entry.hour))
571
658
  }),
572
659
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
573
- className: CodeArtsPluginCard_module_css_default.trendAxis,
574
- children: points.map((point, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
575
- className: CodeArtsPluginCard_module_css_default.trendAxisSlot,
576
- children: index % axisEvery === 0 ? point.label : ""
577
- }, point.key))
660
+ className: CodeArtsPluginCard_module_css_default.heatAxis,
661
+ children: hours.map((entry) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
662
+ className: CodeArtsPluginCard_module_css_default.heatAxisSlot,
663
+ children: entry.hour % 6 === 0 ? entry.hour : ""
664
+ }, entry.hour))
578
665
  }),
579
666
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
580
667
  className: CodeArtsPluginCard_module_css_default.trendTip,
581
- children: shown === void 0 ? hint : `${shown.label} · ${trendDetail(shown.totals, t)}`
668
+ children: shown === void 0 ? t("usageTrendHint") : `${String(shown.hour).padStart(2, "0")}:00 · ${trendDetail(shown.totals, t)}`
582
669
  })
583
670
  ] });
584
671
  }
@@ -685,29 +772,15 @@ function UsageSection({ usage, accounts, t }) {
685
772
  (usage.recentDays ?? []).length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
686
773
  className: CodeArtsPluginCard_module_css_default.hint,
687
774
  children: t("usageTrendWeek")
688
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UsageTrend, {
689
- mode: "hit",
690
- axisEvery: 1,
691
- hint: t("usageTrendHint"),
692
- points: (usage.recentDays ?? []).map((day) => ({
693
- key: day.date,
694
- label: day.date.slice(5),
695
- totals: day.totals
696
- })),
775
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UsageHeat, {
776
+ days: usage.recentDays ?? [],
697
777
  t
698
778
  })] }),
699
779
  (usage.todayByHour ?? []).length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
700
780
  className: CodeArtsPluginCard_module_css_default.hint,
701
781
  children: t("usageTrendHour")
702
- }), (usage.todayByHour ?? []).some((entry) => entry.totals.requests > 0) ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UsageTrend, {
703
- mode: "volume",
704
- axisEvery: 6,
705
- hint: t("usageTrendHint"),
706
- points: (usage.todayByHour ?? []).map((entry) => ({
707
- key: String(entry.hour),
708
- label: String(entry.hour),
709
- totals: entry.totals
710
- })),
782
+ }), (usage.todayByHour ?? []).some((entry) => entry.totals.requests > 0) ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UsageHours, {
783
+ hours: usage.todayByHour ?? [],
711
784
  t
712
785
  }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
713
786
  className: CodeArtsPluginCard_module_css_default.trendTip,
@@ -2291,13 +2364,13 @@ if (typeof document !== "undefined" && document.querySelector("style[data-plugin
2291
2364
  }
2292
2365
  var CodeArtsPanel_module_css_default = {
2293
2366
  "icon": "Z66cgG_icon",
2294
- "page": "Z66cgG_page",
2295
- "body": "Z66cgG_body",
2296
2367
  "back": "Z66cgG_back",
2297
2368
  "backCaret": "Z66cgG_backCaret",
2298
2369
  "title": "Z66cgG_title",
2299
- "head": "Z66cgG_head",
2300
- "desc": "Z66cgG_desc"
2370
+ "desc": "Z66cgG_desc",
2371
+ "page": "Z66cgG_page",
2372
+ "body": "Z66cgG_body",
2373
+ "head": "Z66cgG_head"
2301
2374
  };
2302
2375
  //#endregion
2303
2376
  //#region src/client/CodeArtsPanel.tsx
@@ -2450,10 +2523,13 @@ const zh = {
2450
2523
  usageStatHit: "缓存命中",
2451
2524
  usageStatRequests: "今日请求",
2452
2525
  usageRequests: "{n} 次请求",
2453
- usageTrendWeek: "近 7 天 · 缓存命中率",
2526
+ usageTrendWeek: "本月 · 每日 token",
2454
2527
  usageTrendHour: "今天 · 逐小时 token",
2455
- usageTrendHint: "悬停柱子看那一格明细",
2528
+ usageTrendHint: "悬停格子看那一格明细",
2456
2529
  usageTrendHourEmpty: "今天还没有逐小时数据(启用前的小时不回填)",
2530
+ usageHeatWeekdays: "一 二 三 四 五 六 日",
2531
+ usageHeatLess: "少",
2532
+ usageHeatMore: "多",
2457
2533
  usageByAccount: "今日按账号",
2458
2534
  usageRequestCount: "{n} 条",
2459
2535
  usageTokens: "输入 {prompt} · 输出 {completion}",
@@ -2597,10 +2673,13 @@ const en = {
2597
2673
  usageStatHit: "Cache hit",
2598
2674
  usageStatRequests: "Today requests",
2599
2675
  usageRequests: "{n} request(s)",
2600
- usageTrendWeek: "Last 7 days · cache hit rate",
2676
+ usageTrendWeek: "This month · tokens per day",
2601
2677
  usageTrendHour: "Today · tokens by hour",
2602
- usageTrendHint: "Hover a bar for that slot",
2678
+ usageTrendHint: "Hover a cell for that day",
2603
2679
  usageTrendHourEmpty: "No hourly data yet today (hours before this feature are not backfilled)",
2680
+ usageHeatWeekdays: "Mo Tu We Th Fr Sa Su",
2681
+ usageHeatLess: "Less",
2682
+ usageHeatMore: "More",
2604
2683
  usageByAccount: "Today by account",
2605
2684
  usageRequestCount: "{n} reqs",
2606
2685
  usageTokens: "in {prompt} · out {completion}",
package/lib/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { A as upstreamErrorMessage, B as modelUnavailableReason, C as isWelfareClaimedStatus, D as prepareChatBody, E as pickDailyWelfareCampaign, F as filterEnabledModels, G as codeartsAuthPath, H as CodeArtsCredentialStore, I as forgetModelUnavailable, K as startLogin, L as isBenefitBlocked, M as FALLBACK_CODEARTS_MODELS, N as clearBenefitBlocked, O as rateLimitFrame, P as creditRatioLabel, R as isBenefitModel, S as isTpmLimit, T as modelUnavailableReasonText, U as MANUAL_ACCOUNT_ID, V as CodeArtsAccountStore, W as codeartsAccountsPath, _ as isIamTokenError, a as SNAP_HOST, b as isParamInvalidFrame, c as claimDailyWelfare, d as fetchCallerIdentity, f as fetchModels, g as isConcurrencyCap, h as firstFrameError, i as refreshCatalog, j as CodeArtsCatalog, k as signedGet, l as clearQueueStatus, m as fetchWelfareCampaigns, n as codeartsUsagePath, o as canonicalModel, p as fetchQueueStatus, r as discoverModels, s as chatStream, t as CodeArtsUsageTracker, u as degradeTokenCeiling, v as isModelNotAccessible, w as maxTokensCeilingFor, x as isQueueableRate, y as isNotMultimodal, z as markModelUnavailable } from "./usage-4B0o-CQN.mjs";
1
+ import { A as upstreamErrorMessage, B as modelUnavailableReason, C as isWelfareClaimedStatus, D as prepareChatBody, E as pickDailyWelfareCampaign, F as filterEnabledModels, G as codeartsAuthPath, H as CodeArtsCredentialStore, I as forgetModelUnavailable, K as startLogin, L as isBenefitBlocked, M as FALLBACK_CODEARTS_MODELS, N as clearBenefitBlocked, O as rateLimitFrame, P as creditRatioLabel, R as isBenefitModel, S as isTpmLimit, T as modelUnavailableReasonText, U as MANUAL_ACCOUNT_ID, V as CodeArtsAccountStore, W as codeartsAccountsPath, _ as isIamTokenError, a as SNAP_HOST, b as isParamInvalidFrame, c as claimDailyWelfare, d as fetchCallerIdentity, f as fetchModels, g as isConcurrencyCap, h as firstFrameError, i as refreshCatalog, j as CodeArtsCatalog, k as signedGet, l as clearQueueStatus, m as fetchWelfareCampaigns, n as codeartsUsagePath, o as canonicalModel, p as fetchQueueStatus, r as discoverModels, s as chatStream, t as CodeArtsUsageTracker, u as degradeTokenCeiling, v as isModelNotAccessible, w as maxTokensCeilingFor, x as isQueueableRate, y as isNotMultimodal, z as markModelUnavailable } from "./usage-B2LNsUuR.mjs";
2
2
  import { i as lazyApi, r as createProvider } from "./models-CgKCibpk.mjs";
3
3
  import z from "@deepseek-ai/schemastery";
4
4
  import { randomBytes, timingSafeEqual } from "node:crypto";
@@ -2996,7 +2996,7 @@ var CodeArtsUsageTracker = class {
2996
2996
  /** 最近 TREND_DAYS 天的每日合计(按日期升序,缺账目的日子补 0)。 */
2997
2997
  recentDaysOf(at) {
2998
2998
  const out = [];
2999
- for (let back = 6; back >= 0; back -= 1) {
2999
+ for (let back = 34; back >= 0; back -= 1) {
3000
3000
  const date = localDateKey(at - back * 864e5);
3001
3001
  const day = this.days.get(date);
3002
3002
  out.push({
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "dsh-codearts",
3
3
  "displayName": "DSH CodeArts Connect",
4
4
  "description": "把华为云 CodeArts 接入 DeepSeek Harness —— 内置 OAuth2 登录(PKCE + DPoP),登录后即可在 DSH 对话窗口使用 CodeArts 的模型。",
5
- "version": "1.2.7",
5
+ "version": "1.2.8",
6
6
  "packageManager": "pnpm@11.24.0",
7
7
  "author": "elegant01",
8
8
  "keywords": [