dsh-codearts 1.2.2 → 1.2.4

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.
@@ -23,7 +23,7 @@ function stripModelSuffixes(name) {
23
23
  }
24
24
  //#endregion
25
25
  //#region \0dsh-css:/home/runner/work/dsh-codearts/dsh-codearts/src/client/CodeArtsPluginCard.module.css.mjs
26
- const css = ".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_modelChart{flex-direction:column;gap:2px;margin-top:8px;display:flex}.xoziZG_modelRow{font-variant-numeric:tabular-nums;grid-template-columns:minmax(0,1.2fr) minmax(48px,1fr) 56px 52px 64px;align-items:center;gap:8px;padding:4px 0;display:grid}.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_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}";
26
+ const css = ".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_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}";
27
27
  const tagId = "dsh-codearts/CodeArtsPluginCard.module.css";
28
28
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
29
29
  const tag = document.createElement("style");
@@ -33,70 +33,79 @@ if (typeof document !== "undefined" && document.querySelector("style[data-plugin
33
33
  document.head.appendChild(tag);
34
34
  }
35
35
  var CodeArtsPluginCard_module_css_default = {
36
- "accountToolbar": "xoziZG_accountToolbar",
37
- "choices": "xoziZG_choices",
38
- "bar": "xoziZG_bar",
39
- "modelTokens": "xoziZG_modelTokens",
40
- "modelRequests": "xoziZG_modelRequests",
41
- "tabPanel": "xoziZG_tabPanel",
42
- "accountCard": "xoziZG_accountCard",
36
+ "field": "xoziZG_field",
37
+ "manualForm": "xoziZG_manualForm",
38
+ "accountRow": "xoziZG_accountRow",
39
+ "section": "xoziZG_section",
40
+ "expiryLabel": "xoziZG_expiryLabel",
43
41
  "check": "xoziZG_check",
44
- "sectionHead": "xoziZG_sectionHead",
42
+ "balance": "xoziZG_balance",
43
+ "accountToolbar": "xoziZG_accountToolbar",
44
+ "barFill": "xoziZG_barFill",
45
+ "statLabel": "xoziZG_statLabel",
46
+ "meta": "xoziZG_meta",
47
+ "accountNameRow": "xoziZG_accountNameRow",
48
+ "expiryRow": "xoziZG_expiryRow",
49
+ "balanceUnit": "xoziZG_balanceUnit",
50
+ "accountInfo": "xoziZG_accountInfo",
45
51
  "hint": "xoziZG_hint",
46
- "modelShare": "xoziZG_modelShare",
47
- "creditBlock": "xoziZG_creditBlock",
48
- "manualForm": "xoziZG_manualForm",
49
- "updated": "xoziZG_updated",
50
- "accountRowActions": "xoziZG_accountRowActions",
51
- "name": "xoziZG_name",
52
- "creditRows": "xoziZG_creditRows",
53
- "usageFill": "xoziZG_usageFill",
54
- "modelName": "xoziZG_modelName",
55
- "statusLine": "xoziZG_statusLine",
56
52
  "count": "xoziZG_count",
57
- "modelFill": "xoziZG_modelFill",
58
- "accountInfo": "xoziZG_accountInfo",
59
- "avatar": "xoziZG_avatar",
60
- "headText": "xoziZG_headText",
53
+ "choices": "xoziZG_choices",
54
+ "usageFill": "xoziZG_usageFill",
61
55
  "card": "xoziZG_card",
62
- "expiryLabel": "xoziZG_expiryLabel",
56
+ "usageTipName": "xoziZG_usageTipName",
57
+ "balanceRow": "xoziZG_balanceRow",
58
+ "creditBlock": "xoziZG_creditBlock",
59
+ "header": "xoziZG_header",
60
+ "statSub": "xoziZG_statSub",
61
+ "usageTip": "xoziZG_usageTip",
62
+ "modelRequests": "xoziZG_modelRequests",
63
+ "usageBar": "xoziZG_usageBar",
64
+ "bar": "xoziZG_bar",
65
+ "creditRow": "xoziZG_creditRow",
63
66
  "sectionLabel": "xoziZG_sectionLabel",
64
- "desc": "xoziZG_desc",
65
- "body": "xoziZG_body",
66
- "claimAllRow": "xoziZG_claimAllRow",
67
- "modelTrack": "xoziZG_modelTrack",
68
- "manual": "xoziZG_manual",
69
67
  "accountEntry": "xoziZG_accountEntry",
70
- "creditLink": "xoziZG_creditLink",
71
- "accountRow": "xoziZG_accountRow",
68
+ "modelTrack": "xoziZG_modelTrack",
69
+ "link": "xoziZG_link",
70
+ "updated": "xoziZG_updated",
71
+ "desc": "xoziZG_desc",
72
+ "avatar": "xoziZG_avatar",
72
73
  "creditHint": "xoziZG_creditHint",
73
- "header": "xoziZG_header",
74
- "accountName": "xoziZG_accountName",
75
- "modelChart": "xoziZG_modelChart",
76
- "creditFooter": "xoziZG_creditFooter",
77
- "section": "xoziZG_section",
74
+ "tabPanel": "xoziZG_tabPanel",
78
75
  "fieldLabel": "xoziZG_fieldLabel",
79
- "manualSummary": "xoziZG_manualSummary",
76
+ "modelName": "xoziZG_modelName",
77
+ "danger": "xoziZG_danger",
78
+ "statValue": "xoziZG_statValue",
79
+ "area": "xoziZG_area",
80
+ "claimAllRow": "xoziZG_claimAllRow",
81
+ "tabs": "xoziZG_tabs",
82
+ "usageTipSep": "xoziZG_usageTipSep",
83
+ "name": "xoziZG_name",
84
+ "headText": "xoziZG_headText",
85
+ "accountRowActions": "xoziZG_accountRowActions",
86
+ "sectionHead": "xoziZG_sectionHead",
80
87
  "modelRow": "xoziZG_modelRow",
88
+ "modelFill": "xoziZG_modelFill",
81
89
  "accountHint": "xoziZG_accountHint",
82
- "expiryRow": "xoziZG_expiryRow",
90
+ "modelChart": "xoziZG_modelChart",
83
91
  "error": "xoziZG_error",
84
- "actions": "xoziZG_actions",
85
- "meta": "xoziZG_meta",
86
- "balanceRow": "xoziZG_balanceRow",
87
- "tabs": "xoziZG_tabs",
88
- "link": "xoziZG_link",
89
- "choiceRow": "xoziZG_choiceRow",
90
- "balanceUnit": "xoziZG_balanceUnit",
91
- "creditRow": "xoziZG_creditRow",
92
- "field": "xoziZG_field",
93
- "accountNameRow": "xoziZG_accountNameRow",
94
- "balance": "xoziZG_balance",
95
- "usageBar": "xoziZG_usageBar",
92
+ "body": "xoziZG_body",
93
+ "manualSummary": "xoziZG_manualSummary",
96
94
  "balanceMeta": "xoziZG_balanceMeta",
97
- "barFill": "xoziZG_barFill",
98
- "area": "xoziZG_area",
99
- "danger": "xoziZG_danger"
95
+ "statGrid": "xoziZG_statGrid",
96
+ "choiceRow": "xoziZG_choiceRow",
97
+ "modelShare": "xoziZG_modelShare",
98
+ "accountName": "xoziZG_accountName",
99
+ "modelTokens": "xoziZG_modelTokens",
100
+ "creditLink": "xoziZG_creditLink",
101
+ "creditFooter": "xoziZG_creditFooter",
102
+ "manual": "xoziZG_manual",
103
+ "statusLine": "xoziZG_statusLine",
104
+ "creditRows": "xoziZG_creditRows",
105
+ "statCard": "xoziZG_statCard",
106
+ "accountCard": "xoziZG_accountCard",
107
+ "usageTipRow": "xoziZG_usageTipRow",
108
+ "actions": "xoziZG_actions"
100
109
  };
101
110
  //#endregion
102
111
  //#region src/client/CodeArtsPluginCard.tsx
@@ -115,7 +124,7 @@ function modelName(choice) {
115
124
  /** 官方用量明细页。 */
116
125
  const OFFICIAL_USAGE_URL = "https://codearts.huaweicloud.com/portal/settings/personal-usage";
117
126
  /** token 数按人类习惯缩写:12345 -> 12.3k。 */
118
- function formatTokens(value) {
127
+ function formatTokens$1(value) {
119
128
  if (!Number.isFinite(value)) return "0";
120
129
  if (value >= 1e6) return `${(value / 1e6).toFixed(1)}M`;
121
130
  if (value >= 1e3) return `${(value / 1e3).toFixed(1)}k`;
@@ -128,6 +137,10 @@ function formatCount(value) {
128
137
  function formatCredits(value) {
129
138
  return Number.isFinite(value) ? new Intl.NumberFormat().format(Math.round(value)) : "0";
130
139
  }
140
+ /** 浮层里的明细数字要精确到个位并带千分位,不用 k/M 缩写。 */
141
+ function exactCount(value) {
142
+ return formatCredits(value);
143
+ }
131
144
  /** 批量领取的 claimingId 哨兵(真实账号 id 不会等于它)。 */
132
145
  const CLAIM_ALL = "*";
133
146
  /** 一次领取操作的文案:优先用后端逐号结果,老后端只回一条时按 id 归位。 */
@@ -358,12 +371,25 @@ function ManualTokenForm({ t, token, label, busy, onToken, onLabel, onSubmit })
358
371
  });
359
372
  }
360
373
  /**
374
+ * 缓存命中率:缓存输入 / 全部输入,钳在 0~100。
375
+ *
376
+ * 上游没给缓存字段、或今天压根没有输入时返回 undefined —— 统计块里显示「—」,
377
+ * 不要把「没有数据」写成「0%」。
378
+ */
379
+ function hitPercentOf(totals) {
380
+ const cached = totals.cachedTokens ?? 0;
381
+ if (cached <= 0 || totals.promptTokens <= 0) return void 0;
382
+ return Math.min(100, Math.round(cached / totals.promptTokens * 100));
383
+ }
384
+ /**
361
385
  * 横向条形列表:名称 / 条 / token / 占比 / 请求数。
362
386
  *
363
387
  * 条长按「占组内总量的比例」画(不是按最大值归一化),所以几条加起来就是全部。
364
388
  * token 全 0 的日子(只有请求数、没收到 usage 帧)退回按请求数画。
365
389
  */
366
390
  function UsageBars({ rows, t }) {
391
+ /** 当前悬停的那一行;卡片浮层只在它上面出现。 */
392
+ const [hovered, setHovered] = (0, react.useState)(null);
367
393
  const tokenMode = rows.some((row) => row.totals.totalTokens > 0);
368
394
  const valueOf = (row) => tokenMode ? row.totals.totalTokens : row.totals.requests;
369
395
  const sum = rows.reduce((total, row) => total + valueOf(row), 0);
@@ -374,13 +400,18 @@ function UsageBars({ rows, t }) {
374
400
  children: top.map((row) => {
375
401
  const value = valueOf(row);
376
402
  const share = sum > 0 ? value / sum * 100 : 0;
377
- const detail = [t("usageRequests", { n: formatCount(row.totals.requests) }), t("usageTokens", {
378
- prompt: formatTokens(row.totals.promptTokens),
379
- completion: formatTokens(row.totals.completionTokens)
403
+ const totals = row.totals;
404
+ const cached = totals.cachedTokens;
405
+ const pct = hitPercentOf(totals);
406
+ const detail = [t("usageRequests", { n: formatCount(totals.requests) }), t("usageTokens", {
407
+ prompt: formatTokens$1(totals.promptTokens),
408
+ completion: formatTokens$1(totals.completionTokens)
380
409
  })].join(" · ");
381
410
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
382
411
  className: CodeArtsPluginCard_module_css_default.modelRow,
383
412
  title: `${row.label} · ${detail}`,
413
+ onMouseEnter: () => setHovered(row.id),
414
+ onMouseLeave: () => setHovered((prev) => prev === row.id ? null : prev),
384
415
  children: [
385
416
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
386
417
  className: CodeArtsPluginCard_module_css_default.modelName,
@@ -395,7 +426,7 @@ function UsageBars({ rows, t }) {
395
426
  }),
396
427
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
397
428
  className: CodeArtsPluginCard_module_css_default.modelTokens,
398
- children: tokenMode ? formatTokens(value) : formatCount(value)
429
+ children: tokenMode ? formatTokens$1(value) : formatCount(value)
399
430
  }),
400
431
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
401
432
  className: CodeArtsPluginCard_module_css_default.modelShare,
@@ -403,7 +434,43 @@ function UsageBars({ rows, t }) {
403
434
  }),
404
435
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
405
436
  className: CodeArtsPluginCard_module_css_default.modelRequests,
406
- children: t("usageRequestCount", { n: formatCount(row.totals.requests) })
437
+ children: t("usageRequestCount", { n: formatCount(totals.requests) })
438
+ }),
439
+ hovered === row.id && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
440
+ className: CodeArtsPluginCard_module_css_default.usageTip,
441
+ role: "tooltip",
442
+ children: [
443
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
444
+ className: CodeArtsPluginCard_module_css_default.usageTipName,
445
+ children: row.label
446
+ }),
447
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: CodeArtsPluginCard_module_css_default.usageTipSep }),
448
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
449
+ className: CodeArtsPluginCard_module_css_default.usageTipRow,
450
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("usageTipInput") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: exactCount(totals.promptTokens) })]
451
+ }),
452
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
453
+ className: CodeArtsPluginCard_module_css_default.usageTipRow,
454
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("usageTipOutput") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: exactCount(totals.completionTokens) })]
455
+ }),
456
+ (totals.reasoningTokens ?? 0) > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
457
+ className: CodeArtsPluginCard_module_css_default.usageTipRow,
458
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("usageTipReasoning") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: exactCount(totals.reasoningTokens ?? 0) })]
459
+ }),
460
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
461
+ className: CodeArtsPluginCard_module_css_default.usageTipRow,
462
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("usageTipCached") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: cached === void 0 ? t("usageTipNoCache") : exactCount(cached) })]
463
+ }),
464
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: CodeArtsPluginCard_module_css_default.usageTipSep }),
465
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
466
+ className: CodeArtsPluginCard_module_css_default.usageTipRow,
467
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("usageTipRequests") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("usageRequestCount", { n: formatCount(totals.requests) }) })]
468
+ }),
469
+ pct !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
470
+ className: CodeArtsPluginCard_module_css_default.usageTipRow,
471
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("usageTipHit") }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [pct, "%"] })]
472
+ })
473
+ ]
407
474
  })
408
475
  ]
409
476
  }, row.id);
@@ -418,7 +485,6 @@ function UsageBars({ rows, t }) {
418
485
  * 「打断后重新提问要等」的原因。
419
486
  */
420
487
  function UsageSection({ usage, accounts, t }) {
421
- const total = usage.today.requests;
422
488
  const stateLabel = {
423
489
  ok: t("usageStateOk"),
424
490
  capped: t("usageStateCapped"),
@@ -436,7 +502,9 @@ function UsageSection({ usage, accounts, t }) {
436
502
  label: entry.id.split(" · ")[0],
437
503
  totals: entry.totals
438
504
  }));
439
- const hasUsage = usage.allTime.requests > 0 || total > 0;
505
+ const today = usage.today;
506
+ const hasUsage = usage.allTime.requests > 0 || today.requests > 0;
507
+ const hit = hitPercentOf(today);
440
508
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
441
509
  className: CodeArtsPluginCard_module_css_default.section,
442
510
  children: [
@@ -447,7 +515,10 @@ function UsageSection({ usage, accounts, t }) {
447
515
  children: t("usageTitle")
448
516
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
449
517
  className: CodeArtsPluginCard_module_css_default.count,
450
- children: t("usageRequests", { n: formatCount(total) })
518
+ children: t("usageRange", {
519
+ today: formatCount(today.requests),
520
+ last30: formatCount(usage.last30.requests)
521
+ })
451
522
  })]
452
523
  }),
453
524
  !hasUsage ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
@@ -455,38 +526,46 @@ function UsageSection({ usage, accounts, t }) {
455
526
  children: t("usageEmpty")
456
527
  }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
457
528
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
458
- className: CodeArtsPluginCard_module_css_default.choiceRow,
459
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
460
- className: CodeArtsPluginCard_module_css_default.name,
461
- children: t("usageTodayTotal")
462
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
463
- className: CodeArtsPluginCard_module_css_default.meta,
464
- children: [
465
- t("usageRequests", { n: formatCount(total) }),
466
- " · ",
467
- t("usageTokens", {
468
- prompt: formatTokens(usage.today.promptTokens),
469
- completion: formatTokens(usage.today.completionTokens)
470
- })
471
- ]
472
- })]
473
- }),
474
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
475
- className: CodeArtsPluginCard_module_css_default.choiceRow,
476
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
477
- className: CodeArtsPluginCard_module_css_default.name,
478
- children: t("usageLast30")
479
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
480
- className: CodeArtsPluginCard_module_css_default.meta,
481
- children: [
482
- t("usageRequests", { n: formatCount(usage.last30.requests) }),
483
- " · ",
484
- t("usageTokens", {
485
- prompt: formatTokens(usage.last30.promptTokens),
486
- completion: formatTokens(usage.last30.completionTokens)
487
- })
488
- ]
489
- })]
529
+ className: CodeArtsPluginCard_module_css_default.statGrid,
530
+ children: [
531
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
532
+ className: CodeArtsPluginCard_module_css_default.statCard,
533
+ children: [
534
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
535
+ className: CodeArtsPluginCard_module_css_default.statLabel,
536
+ children: t("usageStatTokens")
537
+ }),
538
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
539
+ className: CodeArtsPluginCard_module_css_default.statValue,
540
+ children: formatTokens$1(today.totalTokens)
541
+ }),
542
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
543
+ className: CodeArtsPluginCard_module_css_default.statSub,
544
+ children: [t("usageStatIn", { n: formatTokens$1(today.promptTokens) }), (today.reasoningTokens ?? 0) > 0 ? ` · ${t("usageStatThinking", { n: formatTokens$1(today.reasoningTokens ?? 0) })}` : ""]
545
+ })
546
+ ]
547
+ }),
548
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
549
+ className: CodeArtsPluginCard_module_css_default.statCard,
550
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
551
+ className: CodeArtsPluginCard_module_css_default.statLabel,
552
+ children: t("usageStatHit")
553
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
554
+ className: CodeArtsPluginCard_module_css_default.statValue,
555
+ children: hit === void 0 ? "—" : `${hit}%`
556
+ })]
557
+ }),
558
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
559
+ className: CodeArtsPluginCard_module_css_default.statCard,
560
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
561
+ className: CodeArtsPluginCard_module_css_default.statLabel,
562
+ children: t("usageStatRequests")
563
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
564
+ className: CodeArtsPluginCard_module_css_default.statValue,
565
+ children: formatCount(today.requests)
566
+ })]
567
+ })
568
+ ]
490
569
  }),
491
570
  accounts.length > 1 && accountRows.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
492
571
  className: CodeArtsPluginCard_module_css_default.hint,
@@ -548,6 +627,10 @@ function CodeArtsPluginCard({ t }) {
548
627
  const [modelError, setModelError] = (0, react.useState)(null);
549
628
  const [refreshing, setRefreshing] = (0, react.useState)(false);
550
629
  const [refreshMsg, setRefreshMsg] = (0, react.useState)(null);
630
+ /** 正在实测的模型 id;同一时间只测一个,避免把上游并发槽位占满。 */
631
+ const [testingId, setTestingId] = (0, react.useState)(null);
632
+ /** 逐模型的测试结果(通过/失败 + 原因)。 */
633
+ const [testResults, setTestResults] = (0, react.useState)({});
551
634
  /** 正在领取的账号 id;批量领取时是 CLAIM_ALL。null 表示没有在飞。 */
552
635
  const [claimingId, setClaimingId] = (0, react.useState)(null);
553
636
  /** 逐账号的领取结果文案。 */
@@ -763,6 +846,51 @@ function CodeArtsPluginCard({ t }) {
763
846
  }
764
847
  }
765
848
  /**
849
+ * 实测某个模型现在能不能调用。
850
+ *
851
+ * 上游的清单会列出调不动的模型(81003.401),刷新救不了;只有真发一次最小请求
852
+ * 才知道。测试成功会清掉后端记的「异常」标记,所以结束后重拉一次 selection。
853
+ */
854
+ async function testModel(id) {
855
+ setTestingId(id);
856
+ setTestResults((current) => {
857
+ const next = { ...current };
858
+ delete next[id];
859
+ return next;
860
+ });
861
+ try {
862
+ const res = await fetch("/api/codearts/test-model", {
863
+ method: "POST",
864
+ headers: {
865
+ "Content-Type": "application/json",
866
+ Accept: "application/json"
867
+ },
868
+ body: JSON.stringify({ id })
869
+ });
870
+ const data = await res.json().catch(() => null);
871
+ if (!res.ok) throw new Error(data?.message ?? `HTTP ${res.status}`);
872
+ setTestResults((current) => ({
873
+ ...current,
874
+ [id]: {
875
+ ok: data?.ok === true,
876
+ message: data?.message ?? "",
877
+ ms: data?.ms
878
+ }
879
+ }));
880
+ await refreshSelection();
881
+ } catch (err) {
882
+ setTestResults((current) => ({
883
+ ...current,
884
+ [id]: {
885
+ ok: false,
886
+ message: err instanceof Error ? err.message : String(err)
887
+ }
888
+ }));
889
+ } finally {
890
+ setTestingId(null);
891
+ }
892
+ }
893
+ /**
766
894
  * 手动重拉一次模型目录。
767
895
  *
768
896
  * 存在的理由:限时福利名单会轮换(模型被移出、被转正),后台每小时才拉一次,
@@ -1143,30 +1271,55 @@ function CodeArtsPluginCard({ t }) {
1143
1271
  }),
1144
1272
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1145
1273
  className: CodeArtsPluginCard_module_css_default.choices,
1146
- children: selection.choices.map((choice) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1147
- className: CodeArtsPluginCard_module_css_default.choiceRow,
1148
- children: [
1149
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Checkbox, {
1150
- className: CodeArtsPluginCard_module_css_default.check,
1151
- checked: draft.includes(choice.id),
1152
- disabled: !selection.writable || savingModels,
1153
- onChange: (on) => setModel(choice.id, on),
1154
- label: modelName(choice)
1155
- }),
1156
- choice.benefit === true && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, {
1157
- tone: choice.blocked === true ? "warning" : "success",
1158
- children: choice.blocked === true ? t("benefitBlocked") : t("benefit")
1159
- }),
1160
- choice.ratio !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, {
1161
- tone: "quiet",
1162
- children: choice.ratio
1163
- }),
1164
- choice.supportsImages === true && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, {
1165
- tone: "quiet",
1166
- children: t("modelImages")
1167
- })
1168
- ]
1169
- }, choice.id))
1274
+ children: selection.choices.map((choice) => {
1275
+ const result = testResults[choice.id];
1276
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1277
+ className: CodeArtsPluginCard_module_css_default.choiceRow,
1278
+ children: [
1279
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Checkbox, {
1280
+ className: CodeArtsPluginCard_module_css_default.check,
1281
+ checked: draft.includes(choice.id),
1282
+ disabled: !selection.writable || savingModels,
1283
+ onChange: (on) => setModel(choice.id, on),
1284
+ label: modelName(choice)
1285
+ }),
1286
+ choice.benefit === true && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, {
1287
+ tone: choice.blocked === true ? "warning" : "success",
1288
+ children: choice.blocked === true ? t("benefitBlocked") : t("benefit")
1289
+ }),
1290
+ choice.error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1291
+ title: choice.error,
1292
+ style: { cursor: "help" },
1293
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, {
1294
+ tone: "warning",
1295
+ children: t("modelError")
1296
+ })
1297
+ }),
1298
+ choice.ratio !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, {
1299
+ tone: "quiet",
1300
+ children: choice.ratio
1301
+ }),
1302
+ choice.supportsImages === true && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, {
1303
+ tone: "quiet",
1304
+ children: t("modelImages")
1305
+ }),
1306
+ draft.includes(choice.id) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1307
+ variant: "outline",
1308
+ size: "sm",
1309
+ disabled: testingId !== null,
1310
+ onClick: () => void testModel(choice.id),
1311
+ children: testingId === choice.id ? t("testingModel") : t("testModel")
1312
+ }),
1313
+ result !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1314
+ title: result.ms === void 0 ? result.message : `${result.message}(${result.ms} ms)`,
1315
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, {
1316
+ tone: result.ok ? "success" : "warning",
1317
+ children: result.ok ? t("testOk") : t("testFailed")
1318
+ })
1319
+ })
1320
+ ]
1321
+ }, choice.id);
1322
+ })
1170
1323
  }),
1171
1324
  selection.writable && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1172
1325
  className: CodeArtsPluginCard_module_css_default.actions,
@@ -1420,10 +1573,27 @@ const QUEUE_PATH = "/api/codearts/queue";
1420
1573
  const REFRESH_INTERVAL_MS = 6e4;
1421
1574
  /** 排队位置变得快:官方客户端也是 5 秒一次;这是本机路由,打不疼上游。 */
1422
1575
  const QUEUE_INTERVAL_MS = 5e3;
1423
- /** 弹层宽度固定,好算它会不会顶出屏幕右边。 */
1424
- const PANEL_WIDTH = 280;
1576
+ /**
1577
+ * 弹层宽度:只放「账号 + 积分」两列,所以按同类插件(dsh-connect-trae 的
1578
+ * `min(248px, …)`)取一档窄宽度 —— 这一层回答的是「哪个号还有多少积分」,
1579
+ * 用量数字不该把它撑成一张报表。
1580
+ */
1581
+ const PANEL_WIDTH = 260;
1425
1582
  /** 弹层与那一行之间的缝隙。 */
1426
1583
  const PANEL_GAP = 8;
1584
+ /**
1585
+ * 弹层里每行的列模板:账号 | 积分。
1586
+ *
1587
+ * 数字列用 `auto`:它跟着最宽的那个余额自适应,面板不必为「12,600」预留固定宽度。
1588
+ * 输入 / 输出 / 缓存这些用量数字不进表格,收进整行的悬浮提示({@link usageLine}),
1589
+ * 完整明细在设置卡片里看。
1590
+ */
1591
+ const PANEL_ROW_COLUMNS = "minmax(0, 1fr) auto";
1592
+ /** 数字格统一右对齐 + 等宽数字,列才对得齐。 */
1593
+ const PANEL_NUM_CELL = {
1594
+ justifySelf: "end",
1595
+ fontVariantNumeric: "tabular-nums"
1596
+ };
1427
1597
  /** 那一行在输入框下方,往上开才够空间;给弹层留的最小高度,不够就翻到下面。 */
1428
1598
  const PANEL_MIN_ABOVE = 260;
1429
1599
  function readSelection(useProjection) {
@@ -1443,6 +1613,13 @@ function isCodeArts(selection) {
1443
1613
  function formatNumber(value) {
1444
1614
  return new Intl.NumberFormat().format(Math.round(value));
1445
1615
  }
1616
+ /** 与设置卡片「用量」区块同一口径:12345 -> 12.3k。 */
1617
+ function formatTokens(value) {
1618
+ if (!Number.isFinite(value)) return "0";
1619
+ if (value >= 1e6) return `${(value / 1e6).toFixed(1)}M`;
1620
+ if (value >= 1e3) return `${(value / 1e3).toFixed(1)}k`;
1621
+ return String(Math.round(value));
1622
+ }
1446
1623
  function formatClock(ts) {
1447
1624
  if (ts === void 0 || !Number.isFinite(ts)) return "";
1448
1625
  try {
@@ -1454,6 +1631,24 @@ function formatClock(ts) {
1454
1631
  return "";
1455
1632
  }
1456
1633
  }
1634
+ /**
1635
+ * 弹层里那行用量:`入 12.3k · 出 697(思 505)· 命中 94% · 37 条`。
1636
+ *
1637
+ * 刻意比设置卡片里的完整版短:面板只有 260px,把「缓存 11.5k」也列上就会折成
1638
+ * 两三行,比原来那个悬浮提示还难看。缓存值本身由命中率表达(它是输入的占比),
1639
+ * 思考 token 也不在这里——它是输出的子集,放在设置卡片的统计块里。上游不给缓存
1640
+ * 字段就不显示命中率:显示成 0% 会被当成「没命中」而不是「没数据」。
1641
+ */
1642
+ function usageLine(usage, t) {
1643
+ const cached = usage.cachedTokens ?? 0;
1644
+ const parts = [t("usageCompact", {
1645
+ prompt: formatTokens(usage.promptTokens),
1646
+ completion: formatTokens(usage.completionTokens)
1647
+ })];
1648
+ if (cached > 0 && usage.promptTokens > 0) parts.push(t("usageCacheHit", { pct: Math.min(100, Math.round(cached / usage.promptTokens * 100)) }));
1649
+ parts.push(t("usageRequestCount", { n: formatNumber(usage.requests) }));
1650
+ return parts.join(" · ");
1651
+ }
1457
1652
  /** 账号名与设置卡片同一套取法:备注 > 用户名 > id。 */
1458
1653
  function accountName(account) {
1459
1654
  return account.label?.trim() || account.userName?.trim() || account.id;
@@ -1473,31 +1668,32 @@ function rowsOf(data) {
1473
1668
  creditsError: data.creditsError
1474
1669
  } : void 0);
1475
1670
  const snapshot = entry?.credits;
1671
+ const usage = data.usage?.byAccountToday?.[account.id];
1476
1672
  return {
1477
1673
  id: account.id,
1478
1674
  name: accountName(account),
1479
1675
  remain: snapshot?.credits.total.remain ?? null,
1480
1676
  expiring: snapshot?.credits.total.expiring ?? 0,
1677
+ ...usage === void 0 ? {} : { usage },
1481
1678
  ...snapshot?.credits.fetchedAt === void 0 ? {} : { fetchedAt: snapshot.credits.fetchedAt },
1482
1679
  ...entry?.creditsError === void 0 ? {} : { error: entry.creditsError }
1483
1680
  };
1484
1681
  });
1485
1682
  }
1486
- /** 把弹层钉在按钮边上:优先往上开(那一行本来就在输入框下面),放不下就翻到下面。 */
1487
- function anchorOf(rect) {
1488
- const above = rect.top > PANEL_MIN_ABOVE;
1489
- const width = Math.min(PANEL_WIDTH, window.innerWidth - 16);
1490
- return {
1491
- left: Math.max(8, Math.min(rect.left, window.innerWidth - width - 8)),
1492
- top: above ? rect.top - PANEL_GAP : rect.bottom + PANEL_GAP,
1493
- above
1494
- };
1683
+ /**
1684
+ * 弹层往上开还是往下开。
1685
+ *
1686
+ * 位置不在这里算:fixed 元素遇到带 transform / backdrop-filter 的祖先时,坐标会
1687
+ * 相对那个祖先而不是视口(工具行就长在输入框卡片里),所以真实偏移要渲染后实测
1688
+ * (见组件里的 layout effect),这里只决定朝哪边翻。
1689
+ */
1690
+ function placeAbove(rect) {
1691
+ return rect.top > PANEL_MIN_ABOVE;
1495
1692
  }
1496
- function CodeArtsCreditDock({ useProjection, t }) {
1693
+ function CodeArtsCreditDock({ useProjection, t, zone = "dock" }) {
1497
1694
  const selection = readSelection(useProjection);
1498
1695
  const active = isCodeArts(selection);
1499
1696
  const [remain, setRemain] = (0, react.useState)(null);
1500
- const [total, setTotal] = (0, react.useState)(0);
1501
1697
  const [rows, setRows] = (0, react.useState)([]);
1502
1698
  /**
1503
1699
  * 模型 id -> 目录条目(显示名 + 已格式化的倍率)。
@@ -1512,6 +1708,15 @@ function CodeArtsCreditDock({ useProjection, t }) {
1512
1708
  });
1513
1709
  const [queued, setQueued] = (0, react.useState)(null);
1514
1710
  const [anchor, setAnchor] = (0, react.useState)(null);
1711
+ /**
1712
+ * 弹层的包含块原点(视口坐标)。
1713
+ *
1714
+ * fixed 只有在祖先没有 transform / backdrop-filter 时才是视口坐标;工具行长在输入框
1715
+ * 卡片里,一旦撞上这类祖先,left/top 就会相对那个祖先算,弹层会飞到窗口外。做法是
1716
+ * 先按 0,0 渲染但不可见,量出面板实际落在哪(就是包含块原点),再把目标坐标减掉它;
1717
+ * 视口情形下量到 (0,0),等于没动。
1718
+ */
1719
+ const [origin, setOrigin] = (0, react.useState)(null);
1515
1720
  const [refreshing, setRefreshing] = (0, react.useState)(false);
1516
1721
  const mounted = (0, react.useRef)(true);
1517
1722
  const triggerRef = (0, react.useRef)(null);
@@ -1549,7 +1754,6 @@ function CodeArtsCreditDock({ useProjection, t }) {
1549
1754
  return;
1550
1755
  }
1551
1756
  setRemain(Math.round(pool.reduce((sum, item) => sum + item.credits.total.remain, 0)));
1552
- setTotal(Math.round(pool.reduce((sum, item) => sum + item.credits.total.total, 0)));
1553
1757
  } catch {}
1554
1758
  }, []);
1555
1759
  (0, react.useEffect)(() => {
@@ -1612,6 +1816,19 @@ function CodeArtsCreditDock({ useProjection, t }) {
1612
1816
  window.removeEventListener("scroll", close, true);
1613
1817
  };
1614
1818
  }, [anchor, close]);
1819
+ (0, react.useLayoutEffect)(() => {
1820
+ if (anchor === null) {
1821
+ setOrigin(null);
1822
+ return;
1823
+ }
1824
+ const el = panelRef.current;
1825
+ if (el === null) return;
1826
+ const rect = el.getBoundingClientRect();
1827
+ setOrigin((prev) => prev !== null && Math.abs(prev.x - rect.left) < .5 && Math.abs(prev.y - rect.top) < .5 ? prev : {
1828
+ x: rect.left,
1829
+ y: rect.top
1830
+ });
1831
+ }, [anchor]);
1615
1832
  (0, react.useEffect)(() => {
1616
1833
  if (!active) return;
1617
1834
  const self = rootRef.current;
@@ -1636,26 +1853,18 @@ function CodeArtsCreditDock({ useProjection, t }) {
1636
1853
  if (!active) return null;
1637
1854
  const showCredits = flags.credits && remain !== null;
1638
1855
  const showQueue = flags.queue && queued !== null;
1856
+ if (zone === "bar" && !showCredits) return null;
1639
1857
  const modelId = currentOf(selection)?.model;
1640
1858
  const entry = modelId === void 0 ? void 0 : modelInfo[modelId];
1641
1859
  const modelLabel = entry === void 0 ? modelId ?? "" : stripModelSuffixes(entry.name);
1642
1860
  const ratio = entry?.ratio;
1643
1861
  const line = buildDockLine({
1644
- ...showCredits ? { credits: t("creditsDock", { remain: formatNumber(remain ?? 0) }) } : {},
1862
+ ...zone === "bar" && showCredits ? { credits: t("creditsDock", { remain: formatNumber(remain ?? 0) }) } : {},
1645
1863
  provider: "CodeArts",
1646
1864
  ...modelLabel === "" ? {} : { model: modelLabel },
1647
1865
  ...ratio === void 0 ? {} : { ratio },
1648
- ...showQueue && queued !== null ? { queue: t("queueDock", { position: queued.position }) } : {}
1866
+ ...zone === "dock" && showQueue && queued !== null ? { queue: t("queueDock", { position: queued.position }) } : {}
1649
1867
  }, t);
1650
- const queueTitle = queued === null ? void 0 : t("queueDockTitle", {
1651
- model: queued.model,
1652
- position: queued.position,
1653
- length: queued.length
1654
- });
1655
- const creditsTitle = showCredits ? t("creditsDockTitle", {
1656
- remain: remain ?? 0,
1657
- total
1658
- }) : void 0;
1659
1868
  const fetchedAt = rows.reduce((latest, row) => Math.max(latest, row.fetchedAt ?? 0), 0);
1660
1869
  const lastUpdated = fetchedAt > 0 ? formatClock(fetchedAt) : "";
1661
1870
  const toggle = (event) => {
@@ -1663,7 +1872,13 @@ function CodeArtsCreditDock({ useProjection, t }) {
1663
1872
  close();
1664
1873
  return;
1665
1874
  }
1666
- setAnchor(anchorOf(event.currentTarget.getBoundingClientRect()));
1875
+ const rect = event.currentTarget.getBoundingClientRect();
1876
+ const above = placeAbove(rect);
1877
+ setAnchor({
1878
+ left: rect.left,
1879
+ top: above ? rect.top - PANEL_GAP : rect.bottom + PANEL_GAP,
1880
+ above
1881
+ });
1667
1882
  };
1668
1883
  const forceRefresh = async () => {
1669
1884
  setRefreshing(true);
@@ -1687,7 +1902,6 @@ function CodeArtsCreditDock({ useProjection, t }) {
1687
1902
  flex: "0 0 auto",
1688
1903
  minWidth: "max-content"
1689
1904
  },
1690
- title: queueTitle ?? creditsTitle,
1691
1905
  children: [
1692
1906
  line.credits !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1693
1907
  ref: triggerRef,
@@ -1695,7 +1909,6 @@ function CodeArtsCreditDock({ useProjection, t }) {
1695
1909
  "aria-haspopup": "dialog",
1696
1910
  "aria-expanded": anchor !== null,
1697
1911
  "aria-label": t("creditsDockPanelTitle"),
1698
- title: creditsTitle,
1699
1912
  onClick: toggle,
1700
1913
  style: {
1701
1914
  all: "unset",
@@ -1707,20 +1920,21 @@ function CodeArtsCreditDock({ useProjection, t }) {
1707
1920
  whiteSpace: "inherit"
1708
1921
  },
1709
1922
  children: line.credits
1710
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1923
+ }), zone === "dock" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1711
1924
  "aria-hidden": "true",
1712
1925
  children: " · "
1713
1926
  })] }),
1714
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: line.rest }),
1927
+ zone === "dock" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: line.rest }),
1715
1928
  anchor !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1716
1929
  ref: panelRef,
1717
1930
  role: "dialog",
1718
1931
  "aria-label": t("creditsDockPanelTitle"),
1719
1932
  style: {
1720
1933
  position: "fixed",
1721
- left: anchor.left,
1722
- top: anchor.top,
1723
- transform: anchor.above ? "translateY(-100%)" : void 0,
1934
+ left: origin === null ? 0 : anchor.left - origin.x,
1935
+ top: origin === null ? 0 : anchor.top - origin.y,
1936
+ transform: anchor.above && origin !== null ? "translateY(-100%)" : void 0,
1937
+ visibility: origin === null ? "hidden" : "visible",
1724
1938
  width: PANEL_WIDTH,
1725
1939
  maxWidth: "calc(100vw - 16px)",
1726
1940
  zIndex: 1e3,
@@ -1759,31 +1973,34 @@ function CodeArtsCreditDock({ useProjection, t }) {
1759
1973
  }),
1760
1974
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1761
1975
  style: {
1762
- display: "grid",
1763
- gridTemplateColumns: "minmax(0, 1fr) auto",
1764
- gap: "4px 12px",
1765
- alignItems: "center",
1976
+ display: "flex",
1977
+ flexDirection: "column",
1978
+ gap: 10,
1766
1979
  borderTop: "0.5px solid var(--dsw-alias-border-l2, rgba(127, 127, 127, 0.22))",
1767
1980
  paddingTop: 8,
1981
+ fontSize: 12,
1768
1982
  color: "var(--dsw-alias-label-tertiary)"
1769
1983
  },
1770
- children: [
1771
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("creditsDockColAccount") }),
1772
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1773
- style: { justifySelf: "end" },
1774
- children: t("creditsDockColBalance")
1775
- }),
1776
- rows.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1777
- style: { gridColumn: "1 / -1" },
1778
- children: t("creditsDockEmpty")
1779
- }),
1780
- rows.map((row) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1781
- style: { display: "contents" },
1984
+ children: [rows.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("creditsDockEmpty") }), rows.map((row) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1985
+ style: {
1986
+ display: "flex",
1987
+ flexDirection: "column",
1988
+ gap: 2,
1989
+ minWidth: 0
1990
+ },
1991
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1992
+ style: {
1993
+ display: "grid",
1994
+ gridTemplateColumns: PANEL_ROW_COLUMNS,
1995
+ gap: "0 8px",
1996
+ alignItems: "center",
1997
+ minWidth: 0
1998
+ },
1782
1999
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1783
2000
  style: {
1784
2001
  display: "flex",
1785
2002
  alignItems: "center",
1786
- gap: 6,
2003
+ gap: 5,
1787
2004
  minWidth: 0
1788
2005
  },
1789
2006
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, { state: row.remain === null ? "warning" : "done" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
@@ -1797,14 +2014,19 @@ function CodeArtsCreditDock({ useProjection, t }) {
1797
2014
  children: row.name
1798
2015
  })]
1799
2016
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1800
- style: {
1801
- justifySelf: "end",
1802
- fontVariantNumeric: "tabular-nums"
1803
- },
2017
+ style: PANEL_NUM_CELL,
1804
2018
  children: row.remain === null ? "—" : formatNumber(row.remain)
1805
2019
  })]
1806
- }, row.id))
1807
- ]
2020
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2021
+ style: {
2022
+ paddingLeft: 11,
2023
+ fontSize: 11,
2024
+ lineHeight: "15px",
2025
+ color: "var(--dsw-alias-label-tertiary)"
2026
+ },
2027
+ children: row.usage === void 0 ? t("creditsDockNoTokens") : `${t("usageToday")} ${usageLine(row.usage, t)}`
2028
+ })]
2029
+ }, row.id))]
1808
2030
  }),
1809
2031
  rows.filter((row) => row.expiring > 0).map((row) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1810
2032
  style: {
@@ -1868,6 +2090,11 @@ const zh = {
1868
2090
  benefitBlocked: "福利今日不可用",
1869
2091
  benefitBlockedHint: "{n} 个福利模型今天被上游判定没有权益(活动领完或渠道未开),发出去会直接报 benefit not found。",
1870
2092
  modelImages: "识图",
2093
+ modelError: "异常",
2094
+ testModel: "测试",
2095
+ testingModel: "测试中…",
2096
+ testOk: "通过",
2097
+ testFailed: "失败",
1871
2098
  refreshModels: "刷新模型列表",
1872
2099
  refreshing: "刷新中…",
1873
2100
  refreshed: "已刷新:{n} 个模型,其中 {benefit} 个走福利路由",
@@ -1884,12 +2111,25 @@ const zh = {
1884
2111
  modelsLoading: "模型勾选区加载中…(若长期不出现,请确认已登录且 DSH 已完全重启)",
1885
2112
  usageTitle: "本机用量",
1886
2113
  usageToday: "今日",
1887
- usageTodayTotal: "今日合计",
1888
- usageLast30: "近 30 天",
1889
- usageByAccount: "今日按账号",
2114
+ usageRange: "今日 {today} 条 · 近 30 天 {last30} 条",
2115
+ usageStatTokens: "今日 token",
2116
+ usageStatIn: "输入 {n}",
2117
+ usageStatThinking: "思考 {n}",
2118
+ usageTipInput: "输入",
2119
+ usageTipOutput: "输出",
2120
+ usageTipReasoning: "思考",
2121
+ usageTipCached: "缓存命中",
2122
+ usageTipNoCache: "上游未下发",
2123
+ usageTipRequests: "请求",
2124
+ usageTipHit: "命中率",
2125
+ usageStatHit: "缓存命中",
2126
+ usageStatRequests: "今日请求",
1890
2127
  usageRequests: "{n} 次请求",
2128
+ usageByAccount: "今日按账号",
1891
2129
  usageRequestCount: "{n} 条",
1892
2130
  usageTokens: "输入 {prompt} · 输出 {completion}",
2131
+ usageCompact: "入 {prompt} · 出 {completion}",
2132
+ usageCacheHit: "命中 {pct}%",
1893
2133
  usageAllTime: "累计({days} 天)",
1894
2134
  usageByModel: "今日按模型",
1895
2135
  usageSlots: "会话槽位",
@@ -1916,8 +2156,7 @@ const zh = {
1916
2156
  creditsDockPanelTitle: "CodeArts 积分",
1917
2157
  creditsDockRefresh: "刷新积分",
1918
2158
  creditsDockRefreshing: "刷新中…",
1919
- creditsDockColAccount: "账号",
1920
- creditsDockColBalance: "剩余积分",
2159
+ creditsDockNoTokens: "今天还没有经插件发出的请求",
1921
2160
  creditsDockEmpty: "暂时没有积分数据",
1922
2161
  creditsDockExpiring: "{account}:{expiring} 积分将在本周期结束时作废",
1923
2162
  creditsDockUpdated: "最近刷新 {time}",
@@ -1925,9 +2164,9 @@ const zh = {
1925
2164
  dockModel: "Model {model}",
1926
2165
  dockNoModel: "未选择模型",
1927
2166
  tabDisplay: "显示",
1928
- displayTitle: "对话底部显示",
2167
+ displayTitle: "输入框两侧显示",
1929
2168
  displayHint: "这两项只管输入框下方那一行的积分与排队两段;中间那段「Provider CodeArts · Model 模型 · 倍率」一直显示,不受开关影响。底部那条每 60 秒读一次设置,所以关掉最多要等一分钟才见效。",
1930
- displayCreditsToggle: "显示剩余积分(点开可看各账号明细)",
2169
+ displayCreditsToggle: "在输入框工具行显示剩余积分(点开可看各账号明细)",
1931
2170
  displayQueueToggle: "显示上游排队位置",
1932
2171
  displayNotWritable: "这个宿主没给插件开配置存储,开关只能看不能改。",
1933
2172
  displayFailed: "保存失败:{message}",
@@ -1984,6 +2223,11 @@ const en = {
1984
2223
  benefitBlocked: "Benefit unavailable today",
1985
2224
  benefitBlockedHint: "{n} benefit model(s) were told they have no entitlement today (campaign exhausted or channel not opened); sending to them fails with benefit not found.",
1986
2225
  modelImages: "Images",
2226
+ modelError: "Unavailable",
2227
+ testModel: "Test",
2228
+ testingModel: "Testing…",
2229
+ testOk: "Passed",
2230
+ testFailed: "Failed",
1987
2231
  refreshModels: "Refresh models",
1988
2232
  refreshing: "Refreshing…",
1989
2233
  refreshed: "Refreshed: {n} models, {benefit} on the benefit route",
@@ -2000,12 +2244,25 @@ const en = {
2000
2244
  modelsLoading: "Loading model selection… (if it never appears, make sure you are signed in and DSH was fully restarted)",
2001
2245
  usageTitle: "Local usage",
2002
2246
  usageToday: "Today",
2003
- usageTodayTotal: "Today",
2004
- usageLast30: "Last 30 days",
2005
- usageByAccount: "Today by account",
2247
+ usageRange: "Today {today} · last 30 days {last30}",
2248
+ usageStatTokens: "Today tokens",
2249
+ usageStatIn: "in {n}",
2250
+ usageStatThinking: "thinking {n}",
2251
+ usageTipInput: "Input",
2252
+ usageTipOutput: "Output",
2253
+ usageTipReasoning: "Reasoning",
2254
+ usageTipCached: "Cached",
2255
+ usageTipNoCache: "not reported",
2256
+ usageTipRequests: "Requests",
2257
+ usageTipHit: "Hit rate",
2258
+ usageStatHit: "Cache hit",
2259
+ usageStatRequests: "Today requests",
2006
2260
  usageRequests: "{n} request(s)",
2261
+ usageByAccount: "Today by account",
2007
2262
  usageRequestCount: "{n} reqs",
2008
2263
  usageTokens: "in {prompt} · out {completion}",
2264
+ usageCompact: "in {prompt} · out {completion}",
2265
+ usageCacheHit: "{pct}% cached",
2009
2266
  usageAllTime: "All time ({days} days)",
2010
2267
  usageByModel: "Today by model",
2011
2268
  usageSlots: "Session slots",
@@ -2032,8 +2289,7 @@ const en = {
2032
2289
  creditsDockPanelTitle: "CodeArts credits",
2033
2290
  creditsDockRefresh: "Refresh credits",
2034
2291
  creditsDockRefreshing: "Refreshing…",
2035
- creditsDockColAccount: "Account",
2036
- creditsDockColBalance: "Credits left",
2292
+ creditsDockNoTokens: "No requests through the plugin today yet",
2037
2293
  creditsDockEmpty: "No credit data yet",
2038
2294
  creditsDockExpiring: "{account}: {expiring} credits expire when this cycle ends",
2039
2295
  creditsDockUpdated: "Last updated {time}",
@@ -2041,9 +2297,9 @@ const en = {
2041
2297
  dockModel: "Model {model}",
2042
2298
  dockNoModel: "No model selected",
2043
2299
  tabDisplay: "Display",
2044
- displayTitle: "Under the chat input box",
2300
+ displayTitle: "Around the chat input box",
2045
2301
  displayHint: "These two only control the credits and queue segments of that line under the input box; the middle “Provider CodeArts · Model … · rate” segments always show. The bar re-reads settings every 60 seconds, so hiding the rest can take up to a minute.",
2046
- displayCreditsToggle: "Show remaining credits (click it for per-account details)",
2302
+ displayCreditsToggle: "Show remaining credits in the composer tool row (click for per-account details)",
2047
2303
  displayQueueToggle: "Show the upstream queue position",
2048
2304
  displayNotWritable: "This host gives the plugin nowhere to persist settings, so the switches are read-only.",
2049
2305
  displayFailed: "Failed to save: {message}",
@@ -2076,12 +2332,25 @@ function apply(ctx) {
2076
2332
  key: "dsh-codearts",
2077
2333
  locale: namespace
2078
2334
  }, () => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CodeArtsPluginCard, { t })));
2335
+ ctx.slots.inject("conversation.input.left", () => ctx.slots.register({
2336
+ name: "conversation.input.left",
2337
+ id: "codearts-credits-bar",
2338
+ order: 20,
2339
+ locale: namespace,
2340
+ inject: () => ({
2341
+ t,
2342
+ zone: "bar"
2343
+ })
2344
+ }, CodeArtsCreditDock));
2079
2345
  ctx.slots.inject("conversation.composer.dock", () => ctx.slots.register({
2080
2346
  name: "conversation.composer.dock",
2081
2347
  id: "codearts-credits",
2082
2348
  order: 20,
2083
2349
  locale: namespace,
2084
- inject: () => ({ t })
2350
+ inject: () => ({
2351
+ t,
2352
+ zone: "dock"
2353
+ })
2085
2354
  }, CodeArtsCreditDock));
2086
2355
  } catch (error) {
2087
2356
  console.error("[dsh-codearts] client card failed to load (host provider unaffected):", error);