dsh-codearts 1.2.6 → 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,32 @@
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
+
21
+ ## [1.2.7] - 2026-11-05
22
+
23
+ ### 变更
24
+
25
+ - **侧边栏图标改成「纸 + 斜杠」**:上一版换成的 `</>` 虽然不再和宿主的「编辑」图标撞脸,
26
+ 但三条线在 16px 下就是一个瘦括号,看不出是干什么的。现在画成一张纸(左上缺角、右下
27
+ 收口)里压一道斜杠 —— 纸是产出物,斜杠是「写代码」这个动作。笔画仍是 1px、
28
+ `currentColor` 跟随主题,16 / 18 / 24 / 32 各档都验过不会糊。
29
+ 试过更接近手稿的版本(纸框 + 一对尖括号 + 一条曲线,共 7 条 path),16px 下会黏成
30
+ 一团黑的,所以砍到 3 条。图标本身没有配置项,跟着插件走。
31
+
6
32
  ## [1.2.6] - 2026-11-05
7
33
 
8
34
  ### 新增
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.6";
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
- "header": "xoziZG_header",
76
- "modelChart": "xoziZG_modelChart",
77
- "trendBar": "xoziZG_trendBar",
78
- "creditHint": "xoziZG_creditHint",
75
+ "heatWeekday": "xoziZG_heatWeekday",
76
+ "headText": "xoziZG_headText",
77
+ "sectionLabel": "xoziZG_sectionLabel",
78
+ "avatar": "xoziZG_avatar",
79
+ "usageFill": "xoziZG_usageFill",
79
80
  "creditLink": "xoziZG_creditLink",
80
- "tabs": "xoziZG_tabs",
81
- "accountCard": "xoziZG_accountCard",
81
+ "modelRequests": "xoziZG_modelRequests",
82
+ "hint": "xoziZG_hint",
82
83
  "usageTipSep": "xoziZG_usageTipSep",
84
+ "usageTipRow": "xoziZG_usageTipRow",
83
85
  "expiryLabel": "xoziZG_expiryLabel",
86
+ "area": "xoziZG_area",
87
+ "balanceUnit": "xoziZG_balanceUnit",
88
+ "sectionHead": "xoziZG_sectionHead",
89
+ "danger": "xoziZG_danger",
90
+ "modelFill": "xoziZG_modelFill",
84
91
  "creditRow": "xoziZG_creditRow",
85
- "skeletonRow": "xoziZG_skeletonRow",
86
- "updated": "xoziZG_updated",
87
- "manual": "xoziZG_manual",
88
- "desc": "xoziZG_desc",
89
- "usageFill": "xoziZG_usageFill",
90
- "trendTip": "xoziZG_trendTip",
91
- "balanceRow": "xoziZG_balanceRow",
92
- "modelShare": "xoziZG_modelShare",
93
- "accountNameRow": "xoziZG_accountNameRow",
94
- "usageTip": "xoziZG_usageTip",
95
- "accountToolbar": "xoziZG_accountToolbar",
96
- "balance": "xoziZG_balance",
97
- "actions": "xoziZG_actions",
98
92
  "choices": "xoziZG_choices",
99
- "meta": "xoziZG_meta",
100
- "section": "xoziZG_section",
101
93
  "modelRow": "xoziZG_modelRow",
102
- "expiryRow": "xoziZG_expiryRow",
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",
102
+ "statusLine": "xoziZG_statusLine",
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",
111
+ "tabs": "xoziZG_tabs",
112
+ "count": "xoziZG_count",
113
+ "usageTip": "xoziZG_usageTip",
103
114
  "claimAllRow": "xoziZG_claimAllRow",
104
- "sectionHead": "xoziZG_sectionHead",
115
+ "creditRows": "xoziZG_creditRows",
116
+ "link": "xoziZG_link",
117
+ "accountNameRow": "xoziZG_accountNameRow",
118
+ "accountName": "xoziZG_accountName",
119
+ "modelShare": "xoziZG_modelShare",
120
+ "choiceRow": "xoziZG_choiceRow",
121
+ "manual": "xoziZG_manual",
105
122
  "modelTokens": "xoziZG_modelTokens",
106
- "trendBars": "xoziZG_trendBars",
107
123
  "skeleton": "xoziZG_skeleton",
108
- "skeletonBreath": "xoziZG_skeletonBreath",
124
+ "statSub": "xoziZG_statSub",
125
+ "usageTipName": "xoziZG_usageTipName",
126
+ "heatAxis": "xoziZG_heatAxis",
127
+ "name": "xoziZG_name",
128
+ "card": "xoziZG_card",
129
+ "manualForm": "xoziZG_manualForm",
130
+ "accountCard": "xoziZG_accountCard",
109
131
  "statGrid": "xoziZG_statGrid",
110
- "hint": "xoziZG_hint",
132
+ "modelTrack": "xoziZG_modelTrack",
111
133
  "accountRowActions": "xoziZG_accountRowActions",
112
- "choiceRow": "xoziZG_choiceRow",
134
+ "actions": "xoziZG_actions",
135
+ "trendTip": "xoziZG_trendTip",
136
+ "field": "xoziZG_field",
137
+ "creditBlock": "xoziZG_creditBlock",
113
138
  "error": "xoziZG_error",
114
- "headText": "xoziZG_headText",
115
- "card": "xoziZG_card",
116
- "accountEntry": "xoziZG_accountEntry",
117
- "statValue": "xoziZG_statValue",
118
- "statSub": "xoziZG_statSub",
119
- "body": "xoziZG_body",
120
- "accountHint": "xoziZG_accountHint",
121
- "usageTipName": "xoziZG_usageTipName",
122
- "trendSlot": "xoziZG_trendSlot",
123
- "modelRequests": "xoziZG_modelRequests",
124
- "avatar": "xoziZG_avatar",
139
+ "statCard": "xoziZG_statCard",
140
+ "heatLegend": "xoziZG_heatLegend",
141
+ "statLabel": "xoziZG_statLabel",
125
142
  "barFill": "xoziZG_barFill",
126
- "sectionLabel": "xoziZG_sectionLabel",
127
- "danger": "xoziZG_danger",
128
- "statusLine": "xoziZG_statusLine",
129
- "creditRows": "xoziZG_creditRows",
130
- "accountInfo": "xoziZG_accountInfo",
131
- "trendAxisSlot": "xoziZG_trendAxisSlot",
132
- "check": "xoziZG_check",
133
- "field": "xoziZG_field",
134
- "creditFooter": "xoziZG_creditFooter",
135
- "balanceMeta": "xoziZG_balanceMeta",
136
- "trendAxis": "xoziZG_trendAxis",
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",
137
151
  "manualSummary": "xoziZG_manualSummary",
138
- "balanceUnit": "xoziZG_balanceUnit",
139
- "manualForm": "xoziZG_manualForm",
152
+ "body": "xoziZG_body",
153
+ "balanceMeta": "xoziZG_balanceMeta",
154
+ "expiryRow": "xoziZG_expiryRow",
155
+ "skeletonBreath": "xoziZG_skeletonBreath",
156
+ "accountEntry": "xoziZG_accountEntry",
140
157
  "accountRow": "xoziZG_accountRow",
141
- "creditBlock": "xoziZG_creditBlock",
142
- "name": "xoziZG_name",
143
- "modelName": "xoziZG_modelName",
144
- "tabPanel": "xoziZG_tabPanel",
145
- "bar": "xoziZG_bar",
146
- "statLabel": "xoziZG_statLabel",
147
- "statCard": "xoziZG_statCard",
148
- "usageBar": "xoziZG_usageBar",
149
- "link": "xoziZG_link",
150
- "fieldLabel": "xoziZG_fieldLabel",
151
- "accountName": "xoziZG_accountName",
152
- "usageTipRow": "xoziZG_usageTipRow",
153
- "count": "xoziZG_count",
154
- "modelTrack": "xoziZG_modelTrack",
155
- "modelFill": "xoziZG_modelFill",
156
- "area": "xoziZG_area"
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,
@@ -2290,14 +2363,14 @@ if (typeof document !== "undefined" && document.querySelector("style[data-plugin
2290
2363
  document.head.appendChild(tag);
2291
2364
  }
2292
2365
  var CodeArtsPanel_module_css_default = {
2293
- "title": "Z66cgG_title",
2294
2366
  "icon": "Z66cgG_icon",
2295
2367
  "back": "Z66cgG_back",
2296
- "page": "Z66cgG_page",
2297
2368
  "backCaret": "Z66cgG_backCaret",
2369
+ "title": "Z66cgG_title",
2370
+ "desc": "Z66cgG_desc",
2371
+ "page": "Z66cgG_page",
2298
2372
  "body": "Z66cgG_body",
2299
- "head": "Z66cgG_head",
2300
- "desc": "Z66cgG_desc"
2373
+ "head": "Z66cgG_head"
2301
2374
  };
2302
2375
  //#endregion
2303
2376
  //#region src/client/CodeArtsPanel.tsx
@@ -2314,21 +2387,21 @@ function CodeArtsPanelIcon({ size }) {
2314
2387
  focusable: "false",
2315
2388
  children: [
2316
2389
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
2317
- d: "M5.1 3.9 1.9 8l3.2 4.1",
2390
+ d: "M6 2.6h6.5A1.5 1.5 0 0 1 14 4.1V10.8",
2318
2391
  stroke: "currentColor",
2319
2392
  strokeWidth: "1",
2320
2393
  strokeLinecap: "round",
2321
2394
  strokeLinejoin: "round"
2322
2395
  }),
2323
2396
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
2324
- d: "M10.9 3.9 14.1 8l-3.2 4.1",
2397
+ d: "M2 6.2v6.1a1.5 1.5 0 0 0 1.5 1.5h6.1",
2325
2398
  stroke: "currentColor",
2326
2399
  strokeWidth: "1",
2327
2400
  strokeLinecap: "round",
2328
2401
  strokeLinejoin: "round"
2329
2402
  }),
2330
2403
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
2331
- d: "M9 3.2 7 12.8",
2404
+ d: "M9.3 5.9 6.7 10.9",
2332
2405
  stroke: "currentColor",
2333
2406
  strokeWidth: "1",
2334
2407
  strokeLinecap: "round"
@@ -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.6",
5
+ "version": "1.2.8",
6
6
  "packageManager": "pnpm@11.24.0",
7
7
  "author": "elegant01",
8
8
  "keywords": [