dsh-codearts 0.5.2 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,8 +7,23 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
7
7
  let react = require("react");
8
8
  let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
9
9
  let react_jsx_runtime = require("react/jsx-runtime");
10
+ //#region src/catalog.ts
11
+ /**
12
+ * 剥掉模型名尾巴上的标记:` · x0.18`、` · x0.00 · 福利`、`(福利)`、`(免费)`、
13
+ * `(x0.18)` 等(兼容旧格式)。
14
+ */
15
+ function stripModelSuffixes(name) {
16
+ let base = name;
17
+ for (;;) {
18
+ const next = base.replace(/\s*·\s*(?:x\d+(?:\.\d+)?|(?:限时)?(?:免费|福利)(?:\s+x\d+(?:\.\d+)?)?)\s*$/, "");
19
+ if (next === base) break;
20
+ base = next;
21
+ }
22
+ return base.replace(/\s*[((]\s*(?:(?:免费|福利)(?:\s+x\d+(?:\.\d+)?)?|x\d+(?:\.\d+)?)\s*[))]\s*$/, "").trim();
23
+ }
24
+ //#endregion
10
25
  //#region \0dsh-css:/home/runner/work/dsh-codearts/dsh-codearts/src/client/CodeArtsPluginCard.module.css.mjs
11
- 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_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_headActions{flex:none;align-items:center;gap:8px;display:flex}.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_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_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) auto auto auto;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}";
12
27
  const tagId = "dsh-codearts/CodeArtsPluginCard.module.css";
13
28
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
14
29
  const tag = document.createElement("style");
@@ -18,32 +33,70 @@ if (typeof document !== "undefined" && document.querySelector("style[data-plugin
18
33
  document.head.appendChild(tag);
19
34
  }
20
35
  var CodeArtsPluginCard_module_css_default = {
21
- "manualSummary": "xoziZG_manualSummary",
36
+ "headText": "xoziZG_headText",
37
+ "tabPanel": "xoziZG_tabPanel",
38
+ "modelRow": "xoziZG_modelRow",
39
+ "modelTokens": "xoziZG_modelTokens",
22
40
  "body": "xoziZG_body",
23
- "section": "xoziZG_section",
24
- "sectionLabel": "xoziZG_sectionLabel",
25
- "check": "xoziZG_check",
26
- "fieldLabel": "xoziZG_fieldLabel",
27
- "hint": "xoziZG_hint",
28
- "card": "xoziZG_card",
29
- "field": "xoziZG_field",
41
+ "barFill": "xoziZG_barFill",
30
42
  "sectionHead": "xoziZG_sectionHead",
31
- "choices": "xoziZG_choices",
32
- "area": "xoziZG_area",
43
+ "manualSummary": "xoziZG_manualSummary",
44
+ "accountToolbar": "xoziZG_accountToolbar",
45
+ "balanceMeta": "xoziZG_balanceMeta",
33
46
  "count": "xoziZG_count",
34
- "headText": "xoziZG_headText",
35
- "error": "xoziZG_error",
36
- "choiceRow": "xoziZG_choiceRow",
47
+ "balanceUnit": "xoziZG_balanceUnit",
48
+ "card": "xoziZG_card",
49
+ "balanceRow": "xoziZG_balanceRow",
50
+ "claimAllRow": "xoziZG_claimAllRow",
51
+ "expiryLabel": "xoziZG_expiryLabel",
52
+ "creditLink": "xoziZG_creditLink",
53
+ "link": "xoziZG_link",
54
+ "accountEntry": "xoziZG_accountEntry",
55
+ "modelName": "xoziZG_modelName",
56
+ "modelTrack": "xoziZG_modelTrack",
37
57
  "manual": "xoziZG_manual",
38
- "desc": "xoziZG_desc",
58
+ "accountName": "xoziZG_accountName",
59
+ "modelFill": "xoziZG_modelFill",
60
+ "section": "xoziZG_section",
61
+ "modelChart": "xoziZG_modelChart",
62
+ "creditHint": "xoziZG_creditHint",
63
+ "usageBar": "xoziZG_usageBar",
64
+ "choiceRow": "xoziZG_choiceRow",
65
+ "creditRow": "xoziZG_creditRow",
66
+ "updated": "xoziZG_updated",
67
+ "modelRequests": "xoziZG_modelRequests",
39
68
  "name": "xoziZG_name",
40
- "danger": "xoziZG_danger",
41
- "link": "xoziZG_link",
69
+ "fieldLabel": "xoziZG_fieldLabel",
70
+ "error": "xoziZG_error",
71
+ "bar": "xoziZG_bar",
72
+ "accountInfo": "xoziZG_accountInfo",
73
+ "usageFill": "xoziZG_usageFill",
74
+ "actions": "xoziZG_actions",
75
+ "creditFooter": "xoziZG_creditFooter",
76
+ "choices": "xoziZG_choices",
77
+ "balance": "xoziZG_balance",
42
78
  "meta": "xoziZG_meta",
79
+ "header": "xoziZG_header",
80
+ "desc": "xoziZG_desc",
81
+ "danger": "xoziZG_danger",
82
+ "accountRow": "xoziZG_accountRow",
83
+ "expiryRow": "xoziZG_expiryRow",
84
+ "manualForm": "xoziZG_manualForm",
85
+ "avatar": "xoziZG_avatar",
43
86
  "statusLine": "xoziZG_statusLine",
44
- "actions": "xoziZG_actions",
45
- "headActions": "xoziZG_headActions",
46
- "header": "xoziZG_header"
87
+ "area": "xoziZG_area",
88
+ "field": "xoziZG_field",
89
+ "check": "xoziZG_check",
90
+ "accountCard": "xoziZG_accountCard",
91
+ "tabs": "xoziZG_tabs",
92
+ "accountNameRow": "xoziZG_accountNameRow",
93
+ "accountRowActions": "xoziZG_accountRowActions",
94
+ "sectionLabel": "xoziZG_sectionLabel",
95
+ "hint": "xoziZG_hint",
96
+ "creditRows": "xoziZG_creditRows",
97
+ "modelShare": "xoziZG_modelShare",
98
+ "accountHint": "xoziZG_accountHint",
99
+ "creditBlock": "xoziZG_creditBlock"
47
100
  };
48
101
  //#endregion
49
102
  //#region src/client/CodeArtsPluginCard.tsx
@@ -55,20 +108,12 @@ function formatStored(ts) {
55
108
  return String(ts);
56
109
  }
57
110
  }
58
- /** 上游给的 name 自带「 (免费)」尾巴,已经用 Tag 表达了就别重复一遍。 */
59
- const TRAILING_FREE = /\s*[((]\s*免费\s*[))]\s*$/;
111
+ /** 目录里的 name 自带「 · x0.18 · 福利」尾巴,这里已经用 Tag 表达了就别重复。 */
60
112
  function modelName(choice) {
61
- return choice.free === true ? choice.name.replace(TRAILING_FREE, "") : choice.name;
113
+ return stripModelSuffixes(choice.name);
62
114
  }
63
115
  /** 官方用量明细页。 */
64
116
  const OFFICIAL_USAGE_URL = "https://codearts.huaweicloud.com/portal/settings/personal-usage";
65
- /**
66
- * 账号身份默认遮蔽后的占位符。
67
- *
68
- * 卡片经常被截图贴进问题反馈,账号名(label / userName / id)与获取、过期时间
69
- * 没有出现在截图里的必要,所以默认遮住,点一下才展开。
70
- */
71
- const ACCOUNT_MASK = "*******";
72
117
  /** token 数按人类习惯缩写:12345 -> 12.3k。 */
73
118
  function formatTokens(value) {
74
119
  if (!Number.isFinite(value)) return "0";
@@ -83,6 +128,32 @@ function formatCount(value) {
83
128
  function formatCredits(value) {
84
129
  return Number.isFinite(value) ? new Intl.NumberFormat().format(Math.round(value)) : "0";
85
130
  }
131
+ /** 批量领取的 claimingId 哨兵(真实账号 id 不会等于它)。 */
132
+ const CLAIM_ALL = "*";
133
+ /** 一次领取操作的文案:优先用后端逐号结果,老后端只回一条时按 id 归位。 */
134
+ function claimMessagesOf(data, accountIds, t) {
135
+ const out = {};
136
+ if (data === null) return out;
137
+ const results = data.results ?? [];
138
+ if (results.length > 0) {
139
+ for (const result of results) if (result.id !== void 0) out[result.id] = claimText(result, t);
140
+ return out;
141
+ }
142
+ for (const id of accountIds) out[id] = claimText(data, t);
143
+ return out;
144
+ }
145
+ /** 一个 Tab 面板;未选中的用 hidden 留在 DOM 里,草稿和滚动位置都别丢。 */
146
+ function TabPanel({ id, labelledBy, active, children }) {
147
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
148
+ role: "tabpanel",
149
+ id,
150
+ "aria-labelledby": labelledBy,
151
+ hidden: !active,
152
+ tabIndex: 0,
153
+ className: CodeArtsPluginCard_module_css_default.tabPanel,
154
+ children
155
+ });
156
+ }
86
157
  /**
87
158
  * 领取结果 → 文案。
88
159
  *
@@ -95,99 +166,253 @@ function claimText(data, t) {
95
166
  if (data?.state === "unavailable") return t("claimUnavailable");
96
167
  return t("claimFailed", { message: typeof data?.message === "string" && data.message !== "" ? data.message : "request failed" });
97
168
  }
169
+ function formatClock(ts) {
170
+ if (ts === void 0 || !Number.isFinite(ts)) return "";
171
+ try {
172
+ return new Date(ts).toLocaleTimeString([], {
173
+ hour: "2-digit",
174
+ minute: "2-digit"
175
+ });
176
+ } catch {
177
+ return "";
178
+ }
179
+ }
180
+ /** 后端拿不到积分时的几种「账号本身不可用」原因,换成用户能懂的一句话。 */
181
+ function creditErrorText(message, t) {
182
+ switch (message) {
183
+ case "account needs sign-in":
184
+ case "no usable credential":
185
+ case "account not found":
186
+ case "account no longer stored": return t("creditsNeedSignIn");
187
+ default: return message;
188
+ }
189
+ }
98
190
  /**
99
- * 积分区块。
191
+ * 账号卡片里的积分块。
100
192
  *
101
- * 2026-10 从官方 CodeArts Agent 客户端挖出积分接口并实测通过(见 src/credits.ts),
102
- * 所以这里能直接显示账号总额度 —— 与下面的「本机用量」互补:一个是账号级、一个是
103
- * 本机级。拉不到时显示原因(creditsError),不静默吞掉。
193
+ * 积分并进账号页:视线从上到下就是「谁登录着 → 这个号还有多少积分 → 去签到」。
194
+ * 拉不到时只把原因留在块里,别把上面的账号一起拖没。
104
195
  */
105
- function CreditsSection({ credits, error, t, onClaim, claiming, claimResult, justClaimed }) {
196
+ function CreditBlock({ credits, error, t, onClaim, claiming, claimResult, justClaimed }) {
106
197
  if (credits === void 0 && error === void 0) return null;
107
198
  const c = credits?.credits;
108
199
  const claimedToday = justClaimed || credits?.welfare?.claimedToday === true;
200
+ const expiring = c?.total.expiring ?? 0;
201
+ const expiringRatio = c !== void 0 && c.total.total > 0 ? Math.min(100, Math.max(0, expiring / c.total.total * 100)) : 0;
202
+ const usedRatio = c !== void 0 && c.total.total > 0 ? Math.min(100, Math.max(0, c.total.used / c.total.total * 100)) : 0;
203
+ const usedLabel = c === void 0 ? "" : t("creditsUsedOfTotal", {
204
+ used: formatCredits(c.total.used),
205
+ total: formatCredits(c.total.total)
206
+ });
207
+ const updated = formatClock(c?.fetchedAt);
109
208
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
110
- className: CodeArtsPluginCard_module_css_default.section,
209
+ className: CodeArtsPluginCard_module_css_default.creditBlock,
111
210
  children: [
112
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
113
- className: CodeArtsPluginCard_module_css_default.sectionHead,
114
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
115
- className: CodeArtsPluginCard_module_css_default.sectionLabel,
116
- children: t("creditsTitle")
117
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
118
- className: CodeArtsPluginCard_module_css_default.headActions,
119
- children: [c !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
120
- className: CodeArtsPluginCard_module_css_default.count,
121
- children: t("creditsRemaining", {
122
- remain: formatCredits(c.total.remain),
123
- total: formatCredits(c.total.total)
211
+ c !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
212
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
213
+ className: CodeArtsPluginCard_module_css_default.balanceRow,
214
+ children: [
215
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
216
+ className: CodeArtsPluginCard_module_css_default.balance,
217
+ children: formatCredits(c.total.remain)
218
+ }),
219
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
220
+ className: CodeArtsPluginCard_module_css_default.balanceUnit,
221
+ children: t("creditsUnit")
222
+ }),
223
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
224
+ className: CodeArtsPluginCard_module_css_default.balanceMeta,
225
+ children: t("creditsUsed", { used: formatCredits(c.total.used) })
226
+ }),
227
+ updated !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
228
+ className: CodeArtsPluginCard_module_css_default.updated,
229
+ children: t("creditsUpdated", { time: updated })
124
230
  })
125
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
126
- variant: "outline",
127
- size: "sm",
128
- disabled: claiming || claimedToday,
129
- onClick: onClaim,
130
- children: claiming ? t("claimPending") : claimedToday ? t("claimButtonDone") : t("claimButton")
131
- })]
132
- })]
231
+ ]
232
+ }),
233
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
234
+ className: CodeArtsPluginCard_module_css_default.creditRows,
235
+ children: [
236
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
237
+ className: CodeArtsPluginCard_module_css_default.creditRow,
238
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("creditsTotal", { total: formatCredits(c.total.total) }) }), c.periodEnd !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("creditsReset", { date: c.periodEnd }) })]
239
+ }),
240
+ c.total.total > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
241
+ className: CodeArtsPluginCard_module_css_default.usageBar,
242
+ role: "progressbar",
243
+ "aria-valuemin": 0,
244
+ "aria-valuemax": c.total.total,
245
+ "aria-valuenow": Math.min(c.total.used, c.total.total),
246
+ "aria-label": usedLabel,
247
+ title: usedLabel,
248
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
249
+ className: CodeArtsPluginCard_module_css_default.usageFill,
250
+ style: { width: `${usedRatio}%` }
251
+ })
252
+ }),
253
+ expiring > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
254
+ className: CodeArtsPluginCard_module_css_default.expiryRow,
255
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
256
+ className: CodeArtsPluginCard_module_css_default.creditRow,
257
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
258
+ className: CodeArtsPluginCard_module_css_default.expiryLabel,
259
+ children: t("creditsExpiringShort", { expiring: formatCredits(expiring) })
260
+ }), c.periodEnd !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("creditsReset", { date: c.periodEnd }) })]
261
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
262
+ className: CodeArtsPluginCard_module_css_default.bar,
263
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
264
+ className: CodeArtsPluginCard_module_css_default.barFill,
265
+ style: { width: `${expiringRatio}%` }
266
+ })
267
+ })]
268
+ }),
269
+ credits?.tokens !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
270
+ className: CodeArtsPluginCard_module_css_default.creditRow,
271
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("creditsTokensToday", {
272
+ used: formatCredits(credits.tokens.dailyUsed),
273
+ limit: formatCredits(credits.tokens.dailyLimit)
274
+ }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("creditsTokensBalance", { balance: formatCredits(credits.tokens.balance) }) })]
275
+ })
276
+ ]
277
+ }),
278
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
279
+ className: `${CodeArtsPluginCard_module_css_default.link} ${CodeArtsPluginCard_module_css_default.creditLink}`,
280
+ href: c.packageUrl ?? OFFICIAL_USAGE_URL,
281
+ target: "_blank",
282
+ rel: "noreferrer",
283
+ children: t("creditsDetailLink")
284
+ })
285
+ ] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
286
+ className: CodeArtsPluginCard_module_css_default.creditHint,
287
+ children: t("creditsUnavailable", { message: creditErrorText(error ?? "", t) })
133
288
  }),
134
- error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
135
- className: CodeArtsPluginCard_module_css_default.hint,
136
- children: t("creditsUnavailable", { message: error })
289
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
290
+ className: CodeArtsPluginCard_module_css_default.creditFooter,
291
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
292
+ variant: "outline",
293
+ size: "sm",
294
+ disabled: claiming || claimedToday,
295
+ onClick: onClaim,
296
+ children: claiming ? t("claimPending") : claimedToday ? t("claimButtonDone") : t("claimButton")
297
+ }), c !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, {
298
+ tone: "quiet",
299
+ children: c.planName
300
+ })]
137
301
  }),
138
302
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
139
- className: CodeArtsPluginCard_module_css_default.hint,
303
+ className: CodeArtsPluginCard_module_css_default.creditHint,
140
304
  children: claimResult ?? t("claimHint")
305
+ })
306
+ ]
307
+ });
308
+ }
309
+ /** 登录前的手动填 token 表单;登录后从「粘贴 Token 添加」展开的也是这一份。 */
310
+ function ManualTokenForm({ t, token, label, busy, onToken, onLabel, onSubmit }) {
311
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("form", {
312
+ onSubmit,
313
+ children: [
314
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
315
+ className: CodeArtsPluginCard_module_css_default.field,
316
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
317
+ className: CodeArtsPluginCard_module_css_default.fieldLabel,
318
+ htmlFor: "codearts-token",
319
+ children: t("tokenLabel")
320
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
321
+ id: "codearts-token",
322
+ className: CodeArtsPluginCard_module_css_default.area,
323
+ value: token,
324
+ onChange: (e) => onToken(e.target.value),
325
+ placeholder: t("tokenPlaceholder"),
326
+ rows: 4
327
+ })]
141
328
  }),
142
- c !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
143
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
144
- className: CodeArtsPluginCard_module_css_default.choiceRow,
145
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
146
- className: CodeArtsPluginCard_module_css_default.name,
147
- children: c.planName
148
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
149
- className: CodeArtsPluginCard_module_css_default.meta,
150
- children: t("creditsUsed", { used: formatCredits(c.total.used) })
151
- })]
152
- }),
153
- c.periodEnd !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
154
- className: CodeArtsPluginCard_module_css_default.choiceRow,
155
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
156
- className: CodeArtsPluginCard_module_css_default.name,
157
- children: t("creditsReset", { date: c.periodEnd })
158
- }), c.total.expiring > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
159
- className: CodeArtsPluginCard_module_css_default.meta,
160
- children: t("creditsExpiring", {
161
- expiring: formatCredits(c.total.expiring),
162
- date: c.periodEnd
163
- })
164
- })]
165
- }),
166
- credits?.tokens !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
167
- className: CodeArtsPluginCard_module_css_default.choiceRow,
168
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
169
- className: CodeArtsPluginCard_module_css_default.name,
170
- children: t("creditsTokensToday", {
171
- used: formatCredits(credits.tokens.dailyUsed),
172
- limit: formatCredits(credits.tokens.dailyLimit)
173
- })
174
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
175
- className: CodeArtsPluginCard_module_css_default.meta,
176
- children: t("creditsTokensBalance", { balance: formatCredits(credits.tokens.balance) })
177
- })]
329
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
330
+ className: CodeArtsPluginCard_module_css_default.field,
331
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
332
+ className: CodeArtsPluginCard_module_css_default.fieldLabel,
333
+ htmlFor: "codearts-label",
334
+ children: t("labelLabel")
335
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
336
+ id: "codearts-label",
337
+ value: label,
338
+ onChange: (e) => onLabel(e.target.value),
339
+ placeholder: t("labelPlaceholder")
340
+ })]
341
+ }),
342
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
343
+ className: CodeArtsPluginCard_module_css_default.actions,
344
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
345
+ variant: "primary",
346
+ size: "sm",
347
+ type: "submit",
348
+ disabled: busy || token.trim() === "",
349
+ children: t("saveToken")
178
350
  })
179
- ] })
351
+ })
180
352
  ]
181
353
  });
182
354
  }
183
355
  /**
356
+ * 横向条形列表:名称 / 条 / token / 占比 / 请求数。
357
+ *
358
+ * 条长按「占组内总量的比例」画(不是按最大值归一化),所以几条加起来就是全部。
359
+ * token 全 0 的日子(只有请求数、没收到 usage 帧)退回按请求数画。
360
+ */
361
+ function UsageBars({ rows, t }) {
362
+ const tokenMode = rows.some((row) => row.totals.totalTokens > 0);
363
+ const valueOf = (row) => tokenMode ? row.totals.totalTokens : row.totals.requests;
364
+ const sum = rows.reduce((total, row) => total + valueOf(row), 0);
365
+ const top = [...rows].sort((a, b) => valueOf(b) - valueOf(a)).slice(0, 5);
366
+ if (top.length === 0) return null;
367
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
368
+ className: CodeArtsPluginCard_module_css_default.modelChart,
369
+ children: top.map((row) => {
370
+ const value = valueOf(row);
371
+ const share = sum > 0 ? value / sum * 100 : 0;
372
+ const detail = [t("usageRequests", { n: formatCount(row.totals.requests) }), t("usageTokens", {
373
+ prompt: formatTokens(row.totals.promptTokens),
374
+ completion: formatTokens(row.totals.completionTokens)
375
+ })].join(" · ");
376
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
377
+ className: CodeArtsPluginCard_module_css_default.modelRow,
378
+ title: `${row.label} · ${detail}`,
379
+ children: [
380
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
381
+ className: CodeArtsPluginCard_module_css_default.modelName,
382
+ children: row.label
383
+ }),
384
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
385
+ className: CodeArtsPluginCard_module_css_default.modelTrack,
386
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
387
+ className: CodeArtsPluginCard_module_css_default.modelFill,
388
+ style: { width: `${value > 0 ? Math.max(share, 1.5) : 0}%` }
389
+ })
390
+ }),
391
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
392
+ className: CodeArtsPluginCard_module_css_default.modelTokens,
393
+ children: tokenMode ? formatTokens(value) : formatCount(value)
394
+ }),
395
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
396
+ className: CodeArtsPluginCard_module_css_default.modelShare,
397
+ children: [share.toFixed(1), "%"]
398
+ }),
399
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
400
+ className: CodeArtsPluginCard_module_css_default.modelRequests,
401
+ children: t("usageRequestCount", { n: formatCount(row.totals.requests) })
402
+ })
403
+ ]
404
+ }, row.id);
405
+ })
406
+ });
407
+ }
408
+ /**
184
409
  * 用量区块。
185
410
  *
186
411
  * 只展示**本机经插件发出**的请求(不等于账号总额度 —— 账号额度见上方积分区块);
187
412
  * 会话槽位是真事实 —— 每账号 3 个并发会话、被占时要等约 52 秒才释放,这也正是
188
413
  * 「打断后重新提问要等」的原因。
189
414
  */
190
- function UsageSection({ usage, t }) {
415
+ function UsageSection({ usage, accounts, t }) {
191
416
  const total = usage.today.requests;
192
417
  const stateLabel = {
193
418
  ok: t("usageStateOk"),
@@ -195,6 +420,18 @@ function UsageSection({ usage, t }) {
195
420
  cooling: t("usageStateCooling"),
196
421
  disabled: t("usageStateDisabled")
197
422
  };
423
+ const nameOf = new Map(accounts.map((account) => [account.id, account.label?.trim() || account.userName?.trim() || account.id]));
424
+ const accountRows = Object.entries(usage.byAccountToday).map(([id, totals]) => ({
425
+ id,
426
+ label: nameOf.get(id) ?? id,
427
+ totals
428
+ }));
429
+ const modelRows = usage.byModelToday.map((entry) => ({
430
+ id: entry.id,
431
+ label: entry.id.split(" · ")[0],
432
+ totals: entry.totals
433
+ }));
434
+ const hasUsage = usage.allTime.requests > 0 || total > 0;
198
435
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
199
436
  className: CodeArtsPluginCard_module_css_default.section,
200
437
  children: [
@@ -208,7 +445,7 @@ function UsageSection({ usage, t }) {
208
445
  children: t("usageRequests", { n: formatCount(total) })
209
446
  })]
210
447
  }),
211
- total === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
448
+ !hasUsage ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
212
449
  className: CodeArtsPluginCard_module_css_default.hint,
213
450
  children: t("usageEmpty")
214
451
  }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
@@ -216,52 +453,50 @@ function UsageSection({ usage, t }) {
216
453
  className: CodeArtsPluginCard_module_css_default.choiceRow,
217
454
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
218
455
  className: CodeArtsPluginCard_module_css_default.name,
219
- children: t("usageToday")
220
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
221
- className: CodeArtsPluginCard_module_css_default.meta,
222
- children: t("usageTokens", {
223
- prompt: formatTokens(usage.today.promptTokens),
224
- completion: formatTokens(usage.today.completionTokens)
225
- })
226
- })]
227
- }),
228
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
229
- className: CodeArtsPluginCard_module_css_default.choiceRow,
230
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
231
- className: CodeArtsPluginCard_module_css_default.name,
232
- children: t("usageAllTime", { days: formatCount(usage.days) })
456
+ children: t("usageTodayTotal")
233
457
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
234
458
  className: CodeArtsPluginCard_module_css_default.meta,
235
459
  children: [
236
- t("usageRequests", { n: formatCount(usage.allTime.requests) }),
460
+ t("usageRequests", { n: formatCount(total) }),
237
461
  " · ",
238
462
  t("usageTokens", {
239
- prompt: formatTokens(usage.allTime.promptTokens),
240
- completion: formatTokens(usage.allTime.completionTokens)
463
+ prompt: formatTokens(usage.today.promptTokens),
464
+ completion: formatTokens(usage.today.completionTokens)
241
465
  })
242
466
  ]
243
467
  })]
244
468
  }),
245
- usage.byModelToday.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
246
- className: CodeArtsPluginCard_module_css_default.hint,
247
- children: t("usageByModel")
248
- }), usage.byModelToday.slice(0, 5).map((entry) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
469
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
249
470
  className: CodeArtsPluginCard_module_css_default.choiceRow,
250
471
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
251
472
  className: CodeArtsPluginCard_module_css_default.name,
252
- children: entry.id
473
+ children: t("usageLast30")
253
474
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
254
475
  className: CodeArtsPluginCard_module_css_default.meta,
255
476
  children: [
256
- t("usageRequests", { n: formatCount(entry.totals.requests) }),
477
+ t("usageRequests", { n: formatCount(usage.last30.requests) }),
257
478
  " · ",
258
479
  t("usageTokens", {
259
- prompt: formatTokens(entry.totals.promptTokens),
260
- completion: formatTokens(entry.totals.completionTokens)
480
+ prompt: formatTokens(usage.last30.promptTokens),
481
+ completion: formatTokens(usage.last30.completionTokens)
261
482
  })
262
483
  ]
263
484
  })]
264
- }, entry.id))] })
485
+ }),
486
+ accounts.length > 1 && accountRows.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
487
+ className: CodeArtsPluginCard_module_css_default.hint,
488
+ children: t("usageByAccount")
489
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UsageBars, {
490
+ rows: accountRows,
491
+ t
492
+ })] }),
493
+ modelRows.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
494
+ className: CodeArtsPluginCard_module_css_default.hint,
495
+ children: t("usageByModel")
496
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UsageBars, {
497
+ rows: modelRows,
498
+ t
499
+ })] })
265
500
  ] }),
266
501
  usage.slots.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
267
502
  className: CodeArtsPluginCard_module_css_default.hint,
@@ -306,30 +541,55 @@ function CodeArtsPluginCard({ t }) {
306
541
  const [savingModels, setSavingModels] = (0, react.useState)(false);
307
542
  const [savedModels, setSavedModels] = (0, react.useState)(false);
308
543
  const [modelError, setModelError] = (0, react.useState)(null);
309
- /** 账号身份是否展开:默认遮蔽(false = 显示 *******)。 */
310
- const [accountsRevealed, setAccountsRevealed] = (0, react.useState)(false);
311
- const [claiming, setClaiming] = (0, react.useState)(false);
312
- const [claimResult, setClaimResult] = (0, react.useState)(null);
313
- const [justClaimed, setJustClaimed] = (0, react.useState)(false);
544
+ const [refreshing, setRefreshing] = (0, react.useState)(false);
545
+ const [refreshMsg, setRefreshMsg] = (0, react.useState)(null);
546
+ /** 正在领取的账号 id;批量领取时是 CLAIM_ALL。null 表示没有在飞。 */
547
+ const [claimingId, setClaimingId] = (0, react.useState)(null);
548
+ /** 逐账号的领取结果文案。 */
549
+ const [claimResults, setClaimResults] = (0, react.useState)({});
550
+ /** 这次会话里刚领成的账号(快照刷新前先把按钮改成「今日已领」)。 */
551
+ const [claimedIds, setClaimedIds] = (0, react.useState)({});
552
+ const [manualOpen, setManualOpen] = (0, react.useState)(false);
553
+ const [tab, setTab] = (0, react.useState)("accounts");
554
+ const tabIdBase = (0, react.useId)();
314
555
  /**
315
- * 领一次每日签到积分。
556
+ * 领每日签到积分。给 id 就只领那个号,不给就逐个号都领一遍。
316
557
  *
317
558
  * 除了这一次刚领成,「今天已领」都来自上游的福利活动状态(积分快照里的 welfare),
318
559
  * 所以刷新、重开窗口都不会把按钮说错。领完不记日期:去重在上游按天做。
319
560
  */
320
- async function claim() {
321
- setClaiming(true);
561
+ async function claim(accountId) {
562
+ const ids = accountId === void 0 ? (status?.accounts ?? []).map((account) => account.id) : [accountId];
563
+ setClaimingId(accountId ?? CLAIM_ALL);
322
564
  try {
323
- const data = await (await fetch("/api/codearts/claim", { method: "POST" })).json().catch(() => null);
324
- setClaimResult(claimText(data, t));
325
- if (data?.claimed === true) {
326
- setJustClaimed(true);
565
+ const data = await (await fetch("/api/codearts/claim", {
566
+ method: "POST",
567
+ headers: { "Content-Type": "application/json" },
568
+ body: JSON.stringify(accountId === void 0 ? {} : { id: accountId })
569
+ })).json().catch(() => null);
570
+ const messages = claimMessagesOf(data, ids, t);
571
+ if (Object.keys(messages).length > 0) setClaimResults((prev) => ({
572
+ ...prev,
573
+ ...messages
574
+ }));
575
+ const won = data?.results !== void 0 && data.results.length > 0 ? data.results.filter((result) => result.claimed === true && result.id !== void 0) : data?.claimed === true ? ids.map((id) => ({ id })) : [];
576
+ if (won.length > 0) {
577
+ setClaimedIds((prev) => {
578
+ const next = { ...prev };
579
+ for (const result of won) next[result.id] = true;
580
+ return next;
581
+ });
327
582
  await refresh();
328
583
  }
329
584
  } catch (error) {
330
- setClaimResult(t("claimFailed", { message: error instanceof Error ? error.message : String(error) }));
585
+ const message = t("claimFailed", { message: error instanceof Error ? error.message : String(error) });
586
+ setClaimResults((prev) => {
587
+ const next = { ...prev };
588
+ for (const id of ids) next[id] = message;
589
+ return next;
590
+ });
331
591
  } finally {
332
- setClaiming(false);
592
+ setClaimingId(null);
333
593
  }
334
594
  }
335
595
  async function refresh() {
@@ -409,6 +669,7 @@ function CodeArtsPluginCard({ t }) {
409
669
  }
410
670
  }
411
671
  const all = selection?.choices.length ?? 0;
672
+ const blockedCount = selection?.choices.filter((c) => c.blocked === true).length ?? 0;
412
673
  const wire = draft.length === all ? [] : draft;
413
674
  const savedIds = selection?.choices.filter((c) => c.enabled).map((c) => c.id) ?? [];
414
675
  const dirty = savedIds.length !== draft.length || savedIds.some((id) => !draft.includes(id));
@@ -443,6 +704,35 @@ function CodeArtsPluginCard({ t }) {
443
704
  setSavingModels(false);
444
705
  }
445
706
  }
707
+ /**
708
+ * 手动重拉一次模型目录。
709
+ *
710
+ * 存在的理由:限时福利名单会轮换(模型被移出、被转正),后台每小时才拉一次,
711
+ * 干等或重启都不是办法。顺带清掉「福利今日不可用」标记 —— 活动回来时这是唯一
712
+ * 不用等第二天的出口。
713
+ */
714
+ async function refreshCatalog() {
715
+ setRefreshing(true);
716
+ setRefreshMsg(null);
717
+ try {
718
+ const res = await fetch("/api/codearts/refresh-models", { method: "POST" });
719
+ const data = await res.json().catch(() => null);
720
+ if (!res.ok) throw new Error(data?.message ?? `HTTP ${res.status}`);
721
+ if (data?.selection !== void 0) {
722
+ setSelection(data.selection);
723
+ setDraft(data.selection.choices.filter((c) => c.enabled).map((c) => c.id));
724
+ setSavedModels(true);
725
+ }
726
+ setRefreshMsg(data?.refreshed === false ? t("refreshStale", { n: data.models ?? 0 }) : t("refreshed", {
727
+ n: data?.models ?? 0,
728
+ benefit: data?.benefit ?? 0
729
+ }));
730
+ } catch (err) {
731
+ setRefreshMsg(t("refreshFailed", { message: err instanceof Error ? err.message : String(err) }));
732
+ } finally {
733
+ setRefreshing(false);
734
+ }
735
+ }
446
736
  async function startOAuthLogin() {
447
737
  setBusy(true);
448
738
  setMsg(null);
@@ -491,8 +781,6 @@ function CodeArtsPluginCard({ t }) {
491
781
  const expired = status?.status === "expired";
492
782
  const accounts = status?.accounts ?? [];
493
783
  const accountName = (account) => account.label?.trim() || account.userName?.trim() || account.id;
494
- /** 遮蔽态下账号身份一律换成占位符:原值连 DOM 都不进。 */
495
- const reveal = (value) => accountsRevealed ? value : ACCOUNT_MASK;
496
784
  /**
497
785
  * 每个账号的「获取时间 + 过期状态」。同一账号重复登录可能留下多条记录(上游不给
498
786
  * 稳定身份时的妥协),把时间摆出来用户才能一眼认出哪条是旧的、放心删。
@@ -509,10 +797,55 @@ function CodeArtsPluginCard({ t }) {
509
797
  const statusText = signedIn ? t("statusSignedIn") : expired ? t("statusExpired") : t("statusSignedOut");
510
798
  const storedTime = formatStored(status?.storedAt);
511
799
  const storedLabel = status?.label?.trim() ?? "";
512
- const meta = !signedIn || storedTime === "" ? "" : storedLabel === "" || !accountsRevealed ? t("storedMetaNoLabel", { time: storedTime }) : t("storedMeta", {
800
+ const meta = !signedIn || storedTime === "" ? "" : storedLabel === "" ? t("storedMetaNoLabel", { time: storedTime }) : t("storedMeta", {
513
801
  label: storedLabel,
514
802
  time: storedTime
515
803
  });
804
+ const tabId = (value) => `${tabIdBase}-tab-${value}`;
805
+ const panelId = (value) => `${tabIdBase}-panel-${value}`;
806
+ const creditEntries = new Map((status?.creditsByAccount ?? []).map((entry) => [entry.id, entry]));
807
+ /** 某账号的积分:新后端按 id 给;老后端只有全局快照,单账号时退回它。 */
808
+ const creditFor = (id) => {
809
+ const entry = creditEntries.get(id);
810
+ if (entry !== void 0) return entry;
811
+ if (creditEntries.size === 0 && accounts.length === 1) {
812
+ if (status?.credits === void 0 && status?.creditsError === void 0) return void 0;
813
+ return {
814
+ credits: status?.credits,
815
+ creditsError: status?.creditsError
816
+ };
817
+ }
818
+ };
819
+ const usageAvailable = status?.usage !== void 0;
820
+ const tabItems = {
821
+ accounts: {
822
+ value: "accounts",
823
+ label: t("tabAccounts", { n: accounts.length }),
824
+ id: tabId("accounts"),
825
+ panelId: panelId("accounts")
826
+ },
827
+ models: {
828
+ value: "models",
829
+ label: t("tabModels", {
830
+ n: draft.length,
831
+ total: all
832
+ }),
833
+ id: tabId("models"),
834
+ panelId: panelId("models")
835
+ },
836
+ usage: {
837
+ value: "usage",
838
+ label: t("tabUsage"),
839
+ id: tabId("usage"),
840
+ panelId: panelId("usage")
841
+ }
842
+ };
843
+ const tabs = [
844
+ tabItems.accounts,
845
+ tabItems.models,
846
+ ...usageAvailable ? [tabItems.usage] : []
847
+ ];
848
+ const activeTab = tabs.some((item) => item.value === tab) ? tab : "accounts";
516
849
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
517
850
  className: CodeArtsPluginCard_module_css_default.card,
518
851
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -546,255 +879,311 @@ function CodeArtsPluginCard({ t }) {
546
879
  })]
547
880
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
548
881
  className: CodeArtsPluginCard_module_css_default.body,
549
- children: [
550
- signedIn ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
551
- className: CodeArtsPluginCard_module_css_default.section,
552
- children: [
553
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
554
- className: CodeArtsPluginCard_module_css_default.sectionHead,
555
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
556
- className: CodeArtsPluginCard_module_css_default.sectionLabel,
557
- children: t("accountsTitle")
558
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
559
- className: CodeArtsPluginCard_module_css_default.headActions,
882
+ children: [signedIn ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
883
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.SegmentedTabs, {
884
+ className: CodeArtsPluginCard_module_css_default.tabs,
885
+ items: tabs,
886
+ value: activeTab,
887
+ onChange: setTab,
888
+ label: t("tabsLabel")
889
+ }),
890
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TabPanel, {
891
+ id: panelId("accounts"),
892
+ labelledBy: tabId("accounts"),
893
+ active: activeTab === "accounts",
894
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
895
+ className: CodeArtsPluginCard_module_css_default.section,
896
+ children: [
897
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
898
+ className: CodeArtsPluginCard_module_css_default.sectionHead,
560
899
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
900
+ className: CodeArtsPluginCard_module_css_default.sectionLabel,
901
+ children: t("accountsTitle")
902
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
561
903
  className: CodeArtsPluginCard_module_css_default.count,
562
904
  children: accounts.length
563
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
905
+ })]
906
+ }),
907
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
908
+ className: CodeArtsPluginCard_module_css_default.accountToolbar,
909
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
564
910
  variant: "outline",
565
911
  size: "sm",
566
- "aria-pressed": accountsRevealed,
567
- onClick: () => setAccountsRevealed((revealed) => !revealed),
568
- children: accountsRevealed ? t("accountsHide") : t("accountsShow")
912
+ "aria-expanded": manualOpen,
913
+ disabled: busy,
914
+ onClick: () => setManualOpen((open) => !open),
915
+ children: t("pasteTokenAdd")
916
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
917
+ variant: "primary",
918
+ size: "sm",
919
+ disabled: busy || loginPending,
920
+ onClick: () => void startOAuthLogin(),
921
+ children: loginPending ? t("signingIn") : t("addAccount")
569
922
  })]
570
- })]
571
- }),
572
- accounts.length > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
573
- className: CodeArtsPluginCard_module_css_default.hint,
574
- children: t("accountsRotateHint")
575
- }),
576
- accounts.map((account) => {
577
- const meta = accountMeta(account);
578
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
579
- className: CodeArtsPluginCard_module_css_default.choiceRow,
923
+ }),
924
+ loginUrl !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
925
+ className: CodeArtsPluginCard_module_css_default.hint,
580
926
  children: [
581
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
582
- className: CodeArtsPluginCard_module_css_default.name,
583
- children: reveal(accountName(account))
584
- }),
585
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
586
- className: CodeArtsPluginCard_module_css_default.meta,
587
- children: reveal(meta)
588
- }),
589
- account.stale && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, { children: t("accountNeedsSignIn") }),
590
- !account.signable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, { children: t("accountNoKey") }),
591
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
592
- variant: "outline",
593
- size: "sm",
594
- className: CodeArtsPluginCard_module_css_default.danger,
595
- disabled: busy,
596
- onClick: () => void removeAccount(account.id),
597
- children: t("accountRemove")
927
+ t("openManually"),
928
+ " ",
929
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
930
+ className: CodeArtsPluginCard_module_css_default.link,
931
+ href: loginUrl,
932
+ target: "_blank",
933
+ rel: "noreferrer",
934
+ children: loginUrl
598
935
  })
599
936
  ]
600
- }, account.id);
601
- }),
602
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
603
- className: CodeArtsPluginCard_module_css_default.actions,
604
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
605
- variant: "primary",
606
- size: "sm",
607
- disabled: busy || loginPending,
608
- onClick: () => void startOAuthLogin(),
609
- children: loginPending ? t("signingIn") : t("addAccount")
610
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
611
- variant: "outline",
612
- size: "sm",
613
- className: CodeArtsPluginCard_module_css_default.danger,
614
- disabled: busy,
615
- onClick: () => void clearToken(),
616
- children: t("clearToken")
617
- })]
618
- }),
619
- loginUrl !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
620
- className: CodeArtsPluginCard_module_css_default.hint,
621
- children: [
622
- t("openManually"),
623
- " ",
624
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
625
- className: CodeArtsPluginCard_module_css_default.link,
626
- href: loginUrl,
627
- target: "_blank",
628
- rel: "noreferrer",
629
- children: loginUrl
630
- })
631
- ]
632
- })
633
- ]
634
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
635
- className: CodeArtsPluginCard_module_css_default.section,
636
- children: [
637
- expired && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
638
- className: CodeArtsPluginCard_module_css_default.hint,
639
- children: t("expiredHint")
640
- }),
641
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
642
- className: CodeArtsPluginCard_module_css_default.actions,
643
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
644
- variant: "primary",
645
- disabled: busy || loginPending,
646
- onClick: () => void startOAuthLogin(),
647
- children: loginPending ? t("signingIn") : t("signIn")
648
- })
649
- }),
650
- loginUrl !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
651
- className: CodeArtsPluginCard_module_css_default.hint,
652
- children: [
653
- t("openManually"),
654
- " ",
655
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
656
- className: CodeArtsPluginCard_module_css_default.link,
657
- href: loginUrl,
658
- target: "_blank",
659
- rel: "noreferrer",
660
- children: loginUrl
937
+ }),
938
+ manualOpen && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
939
+ className: CodeArtsPluginCard_module_css_default.manualForm,
940
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ManualTokenForm, {
941
+ t,
942
+ token,
943
+ label,
944
+ busy,
945
+ onToken: setToken,
946
+ onLabel: setLabel,
947
+ onSubmit: (e) => void saveToken(e)
661
948
  })
662
- ]
663
- }),
664
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
665
- className: CodeArtsPluginCard_module_css_default.manual,
666
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", {
667
- className: CodeArtsPluginCard_module_css_default.manualSummary,
668
- children: t("manualToken")
669
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("form", {
670
- onSubmit: (e) => void saveToken(e),
949
+ }),
950
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
951
+ className: CodeArtsPluginCard_module_css_default.accountCard,
671
952
  children: [
672
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
673
- className: CodeArtsPluginCard_module_css_default.field,
674
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
675
- className: CodeArtsPluginCard_module_css_default.fieldLabel,
676
- htmlFor: "codearts-token",
677
- children: t("tokenLabel")
678
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
679
- id: "codearts-token",
680
- className: CodeArtsPluginCard_module_css_default.area,
681
- value: token,
682
- onChange: (e) => setToken(e.target.value),
683
- placeholder: t("tokenPlaceholder"),
684
- rows: 4
685
- })]
953
+ accounts.map((account) => {
954
+ const accountLine = accountMeta(account);
955
+ const credit = creditFor(account.id);
956
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
957
+ className: CodeArtsPluginCard_module_css_default.accountEntry,
958
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
959
+ className: CodeArtsPluginCard_module_css_default.accountRow,
960
+ children: [
961
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
962
+ className: CodeArtsPluginCard_module_css_default.avatar,
963
+ "aria-hidden": "true",
964
+ children: Array.from(accountName(account))[0] ?? "*"
965
+ }),
966
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
967
+ className: CodeArtsPluginCard_module_css_default.accountInfo,
968
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
969
+ className: CodeArtsPluginCard_module_css_default.accountNameRow,
970
+ children: [
971
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
972
+ className: CodeArtsPluginCard_module_css_default.accountName,
973
+ children: accountName(account)
974
+ }),
975
+ account.stale && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, { children: t("accountNeedsSignIn") }),
976
+ !account.signable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, { children: t("accountNoKey") })
977
+ ]
978
+ }), accountLine !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
979
+ className: CodeArtsPluginCard_module_css_default.meta,
980
+ children: accountLine
981
+ })]
982
+ }),
983
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
984
+ className: CodeArtsPluginCard_module_css_default.accountRowActions,
985
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
986
+ variant: "outline",
987
+ size: "sm",
988
+ className: CodeArtsPluginCard_module_css_default.danger,
989
+ disabled: busy,
990
+ onClick: () => void removeAccount(account.id),
991
+ children: t("accountRemove")
992
+ })
993
+ })
994
+ ]
995
+ }), credit !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CreditBlock, {
996
+ credits: credit.credits,
997
+ error: credit.creditsError,
998
+ t,
999
+ onClaim: () => void claim(account.id),
1000
+ claiming: claimingId === account.id || claimingId === CLAIM_ALL,
1001
+ claimResult: claimResults[account.id] ?? null,
1002
+ justClaimed: claimedIds[account.id] === true
1003
+ })]
1004
+ }, account.id);
686
1005
  }),
687
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
688
- className: CodeArtsPluginCard_module_css_default.field,
689
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
690
- className: CodeArtsPluginCard_module_css_default.fieldLabel,
691
- htmlFor: "codearts-label",
692
- children: t("labelLabel")
693
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
694
- id: "codearts-label",
695
- value: label,
696
- onChange: (e) => setLabel(e.target.value),
697
- placeholder: t("labelPlaceholder")
698
- })]
699
- }),
700
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
701
- className: CodeArtsPluginCard_module_css_default.actions,
1006
+ accounts.length > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1007
+ className: CodeArtsPluginCard_module_css_default.claimAllRow,
702
1008
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
703
- variant: "primary",
1009
+ variant: "outline",
704
1010
  size: "sm",
705
- type: "submit",
706
- disabled: busy || token.trim() === "",
707
- children: t("saveToken")
1011
+ disabled: claimingId !== null,
1012
+ onClick: () => void claim(),
1013
+ children: claimingId === CLAIM_ALL ? t("claimPending") : t("claimAll")
708
1014
  })
1015
+ }),
1016
+ accounts.length > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1017
+ className: CodeArtsPluginCard_module_css_default.accountHint,
1018
+ children: t("accountsRotateHint")
709
1019
  })
710
1020
  ]
711
- })]
712
- })
713
- ]
714
- }),
715
- msg !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
716
- className: CodeArtsPluginCard_module_css_default.error,
717
- children: msg
718
- }),
719
- selection ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
720
- className: CodeArtsPluginCard_module_css_default.section,
721
- children: [
722
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
723
- className: CodeArtsPluginCard_module_css_default.sectionHead,
724
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
725
- className: CodeArtsPluginCard_module_css_default.sectionLabel,
726
- children: t("modelsTitle")
727
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
728
- className: CodeArtsPluginCard_module_css_default.count,
729
- children: t("selectedCount", {
730
- n: draft.length,
731
- total: all
1021
+ }),
1022
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1023
+ className: CodeArtsPluginCard_module_css_default.actions,
1024
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1025
+ variant: "outline",
1026
+ size: "sm",
1027
+ className: CodeArtsPluginCard_module_css_default.danger,
1028
+ disabled: busy,
1029
+ onClick: () => void clearToken(),
1030
+ children: t("clearToken")
732
1031
  })
733
- })]
734
- }),
735
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
736
- className: CodeArtsPluginCard_module_css_default.hint,
737
- children: selection.restricted ? t("optionalModelsHint") : t("optionalModelsAllHint")
738
- }),
739
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
740
- className: CodeArtsPluginCard_module_css_default.choices,
741
- children: selection.choices.map((choice) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
742
- className: CodeArtsPluginCard_module_css_default.choiceRow,
743
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Checkbox, {
744
- className: CodeArtsPluginCard_module_css_default.check,
745
- checked: draft.includes(choice.id),
746
- disabled: !selection.writable || savingModels,
747
- onChange: (on) => setModel(choice.id, on),
748
- label: modelName(choice)
749
- }), choice.free === true && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, {
750
- tone: "success",
751
- children: t("free")
752
- })]
753
- }, choice.id))
754
- }),
755
- selection.writable && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
756
- className: CodeArtsPluginCard_module_css_default.actions,
757
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
758
- variant: "outline",
759
- size: "sm",
760
- disabled: draft.length === all,
761
- onClick: () => {
762
- setSavedModels(false);
763
- setModelError(null);
764
- setDraft(selection.choices.map((c) => c.id));
765
- },
766
- children: t("selectAll")
767
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
768
- variant: "primary",
769
- size: "sm",
770
- disabled: !dirty || savingModels,
771
- onClick: () => void saveModels(),
772
- children: savingModels ? t("saving") : savedModels && !dirty ? t("saved") : t("saveModels")
773
- })]
774
- }),
775
- modelError !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
776
- className: CodeArtsPluginCard_module_css_default.error,
777
- children: modelError
778
- })
779
- ]
780
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
781
- className: CodeArtsPluginCard_module_css_default.hint,
782
- children: t("modelsLoading")
1032
+ })
1033
+ ]
1034
+ })
783
1035
  }),
784
- signedIn && (status?.credits !== void 0 || status?.creditsError !== void 0) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CreditsSection, {
785
- credits: status?.credits,
786
- error: status?.creditsError,
787
- t,
788
- onClaim: () => void claim(),
789
- claiming,
790
- claimResult,
791
- justClaimed
1036
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TabPanel, {
1037
+ id: panelId("models"),
1038
+ labelledBy: tabId("models"),
1039
+ active: activeTab === "models",
1040
+ children: selection ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1041
+ className: CodeArtsPluginCard_module_css_default.section,
1042
+ children: [
1043
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1044
+ className: CodeArtsPluginCard_module_css_default.sectionHead,
1045
+ children: [
1046
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1047
+ className: CodeArtsPluginCard_module_css_default.sectionLabel,
1048
+ children: t("modelsTitle")
1049
+ }),
1050
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1051
+ className: CodeArtsPluginCard_module_css_default.count,
1052
+ children: t("selectedCount", {
1053
+ n: draft.length,
1054
+ total: all
1055
+ })
1056
+ }),
1057
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1058
+ variant: "outline",
1059
+ size: "sm",
1060
+ disabled: refreshing,
1061
+ onClick: () => void refreshCatalog(),
1062
+ children: refreshing ? t("refreshing") : t("refreshModels")
1063
+ })
1064
+ ]
1065
+ }),
1066
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1067
+ className: CodeArtsPluginCard_module_css_default.hint,
1068
+ children: selection.restricted ? t("optionalModelsHint") : t("optionalModelsAllHint")
1069
+ }),
1070
+ blockedCount > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1071
+ className: CodeArtsPluginCard_module_css_default.hint,
1072
+ children: t("benefitBlockedHint", { n: blockedCount })
1073
+ }),
1074
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1075
+ className: CodeArtsPluginCard_module_css_default.choices,
1076
+ children: selection.choices.map((choice) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1077
+ className: CodeArtsPluginCard_module_css_default.choiceRow,
1078
+ children: [
1079
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Checkbox, {
1080
+ className: CodeArtsPluginCard_module_css_default.check,
1081
+ checked: draft.includes(choice.id),
1082
+ disabled: !selection.writable || savingModels,
1083
+ onChange: (on) => setModel(choice.id, on),
1084
+ label: modelName(choice)
1085
+ }),
1086
+ choice.benefit === true && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, {
1087
+ tone: choice.blocked === true ? "warning" : "success",
1088
+ children: choice.blocked === true ? t("benefitBlocked") : t("benefit")
1089
+ }),
1090
+ choice.ratio !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, {
1091
+ tone: "quiet",
1092
+ children: choice.ratio
1093
+ })
1094
+ ]
1095
+ }, choice.id))
1096
+ }),
1097
+ selection.writable && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1098
+ className: CodeArtsPluginCard_module_css_default.actions,
1099
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1100
+ variant: "outline",
1101
+ size: "sm",
1102
+ disabled: draft.length === all,
1103
+ onClick: () => {
1104
+ setSavedModels(false);
1105
+ setModelError(null);
1106
+ setDraft(selection.choices.map((c) => c.id));
1107
+ },
1108
+ children: t("selectAll")
1109
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1110
+ variant: "primary",
1111
+ size: "sm",
1112
+ disabled: !dirty || savingModels,
1113
+ onClick: () => void saveModels(),
1114
+ children: savingModels ? t("saving") : savedModels && !dirty ? t("saved") : t("saveModels")
1115
+ })]
1116
+ }),
1117
+ modelError !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1118
+ className: CodeArtsPluginCard_module_css_default.error,
1119
+ children: modelError
1120
+ })
1121
+ ]
1122
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1123
+ className: CodeArtsPluginCard_module_css_default.hint,
1124
+ children: t("modelsLoading")
1125
+ })
792
1126
  }),
793
- status?.usage !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UsageSection, {
794
- usage: status.usage,
795
- t
1127
+ status?.usage !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TabPanel, {
1128
+ id: panelId("usage"),
1129
+ labelledBy: tabId("usage"),
1130
+ active: activeTab === "usage",
1131
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UsageSection, {
1132
+ usage: status.usage,
1133
+ accounts,
1134
+ t
1135
+ })
796
1136
  })
797
- ]
1137
+ ] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1138
+ className: CodeArtsPluginCard_module_css_default.section,
1139
+ children: [
1140
+ expired && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1141
+ className: CodeArtsPluginCard_module_css_default.hint,
1142
+ children: t("expiredHint")
1143
+ }),
1144
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1145
+ className: CodeArtsPluginCard_module_css_default.actions,
1146
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1147
+ variant: "primary",
1148
+ disabled: busy || loginPending,
1149
+ onClick: () => void startOAuthLogin(),
1150
+ children: loginPending ? t("signingIn") : t("signIn")
1151
+ })
1152
+ }),
1153
+ loginUrl !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
1154
+ className: CodeArtsPluginCard_module_css_default.hint,
1155
+ children: [
1156
+ t("openManually"),
1157
+ " ",
1158
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
1159
+ className: CodeArtsPluginCard_module_css_default.link,
1160
+ href: loginUrl,
1161
+ target: "_blank",
1162
+ rel: "noreferrer",
1163
+ children: loginUrl
1164
+ })
1165
+ ]
1166
+ }),
1167
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
1168
+ className: CodeArtsPluginCard_module_css_default.manual,
1169
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", {
1170
+ className: CodeArtsPluginCard_module_css_default.manualSummary,
1171
+ children: t("manualToken")
1172
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ManualTokenForm, {
1173
+ t,
1174
+ token,
1175
+ label,
1176
+ busy,
1177
+ onToken: setToken,
1178
+ onLabel: setLabel,
1179
+ onSubmit: (e) => void saveToken(e)
1180
+ })]
1181
+ })
1182
+ ]
1183
+ }), msg !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1184
+ className: CodeArtsPluginCard_module_css_default.error,
1185
+ children: msg
1186
+ })]
798
1187
  })]
799
1188
  });
800
1189
  }
@@ -852,10 +1241,13 @@ function CodeArtsCreditDock({ useProjection, t }) {
852
1241
  });
853
1242
  if (!res.ok) return;
854
1243
  const data = await res.json().catch(() => void 0);
855
- if (data === void 0 || data.credits === void 0) return;
1244
+ if (data === void 0) return;
1245
+ const snapshots = (data.creditsByAccount ?? []).map((entry) => entry.credits).filter((value) => value !== void 0);
1246
+ const pool = snapshots.length > 0 ? snapshots : data.credits === void 0 ? [] : [data.credits];
1247
+ if (pool.length === 0) return;
856
1248
  if (mounted.current) {
857
- setRemain(Math.round(data.credits.credits.total.remain));
858
- setTotal(Math.round(data.credits.credits.total.total));
1249
+ setRemain(Math.round(pool.reduce((sum, item) => sum + item.credits.total.remain, 0)));
1250
+ setTotal(Math.round(pool.reduce((sum, item) => sum + item.credits.total.total, 0)));
859
1251
  }
860
1252
  } catch {}
861
1253
  };
@@ -892,6 +1284,10 @@ function CodeArtsCreditDock({ useProjection, t }) {
892
1284
  //#region src/client/locales.ts
893
1285
  const zh = {
894
1286
  tabLabel: "CodeArts",
1287
+ tabsLabel: "CodeArts 设置",
1288
+ tabAccounts: "账号 · {n}",
1289
+ tabModels: "模型 · {n}/{total}",
1290
+ tabUsage: "用量",
895
1291
  cardTitle: "DSH CodeArts Connect",
896
1292
  statusSignedIn: "已登录",
897
1293
  statusSignedOut: "未登录",
@@ -901,7 +1297,7 @@ const zh = {
901
1297
  storedMeta: "{label} · 存于 {time}",
902
1298
  storedMetaNoLabel: "存于 {time}",
903
1299
  refresh: "刷新",
904
- clearToken: "清除凭证",
1300
+ clearToken: "清除全部凭据",
905
1301
  tokenLabel: "cloud_dragon_token",
906
1302
  tokenPlaceholder: "粘贴从 CodeArts 网页/桌面端拿到的 token……",
907
1303
  labelLabel: "备注(可选)",
@@ -909,10 +1305,9 @@ const zh = {
909
1305
  saveToken: "保存 token",
910
1306
  expiredHint: "凭证已过期,请重新登录以继续使用;已勾选的模型设置会保留。",
911
1307
  accountsTitle: "账号",
912
- accountsShow: "显示账号",
913
- accountsHide: "隐藏账号",
914
1308
  accountRemove: "删除",
915
1309
  addAccount: "添加账号",
1310
+ pasteTokenAdd: "粘贴 Token 添加",
916
1311
  accountsRotateHint: "已存多个账号:请求会自动轮转,某个账号忙时改用下一个,不用干等。",
917
1312
  accountNeedsSignIn: "需重新登录",
918
1313
  accountNoKey: "无 AK/SK",
@@ -924,7 +1319,14 @@ const zh = {
924
1319
  optionalModelsAllHint: "所有模型默认都出现在选择器里;取消勾选不想用的即可。",
925
1320
  selectedCount: "已选 {n} / {total}",
926
1321
  selectAll: "全选",
927
- free: "免费",
1322
+ benefit: "福利",
1323
+ benefitBlocked: "福利今日不可用",
1324
+ benefitBlockedHint: "{n} 个福利模型今天被上游判定没有权益(活动领完或渠道未开),发出去会直接报 benefit not found。",
1325
+ refreshModels: "刷新模型列表",
1326
+ refreshing: "刷新中…",
1327
+ refreshed: "已刷新:{n} 个模型,其中 {benefit} 个走福利路由",
1328
+ refreshStale: "上游没回应,仍是旧名单({n} 个模型)",
1329
+ refreshFailed: "刷新失败:{message}",
928
1330
  saveModels: "保存模型选择",
929
1331
  saving: "保存中…",
930
1332
  saved: "已保存",
@@ -936,7 +1338,11 @@ const zh = {
936
1338
  modelsLoading: "模型勾选区加载中…(若长期不出现,请确认已登录且 DSH 已完全重启)",
937
1339
  usageTitle: "本机用量",
938
1340
  usageToday: "今日",
1341
+ usageTodayTotal: "今日合计",
1342
+ usageLast30: "近 30 天",
1343
+ usageByAccount: "今日按账号",
939
1344
  usageRequests: "{n} 次请求",
1345
+ usageRequestCount: "{n} 条",
940
1346
  usageTokens: "输入 {prompt} · 输出 {completion}",
941
1347
  usageAllTime: "累计({days} 天)",
942
1348
  usageByModel: "今日按模型",
@@ -947,19 +1353,24 @@ const zh = {
947
1353
  usageStateDisabled: "已停用",
948
1354
  usageNoQuota: "这里是本机经插件发出的请求统计(不等于账号总额度);官方用量明细见",
949
1355
  usageEmpty: "还没有记录:发一条消息就会开始累计。",
950
- creditsTitle: "积分",
951
- creditsRemaining: "剩余 {remain} / {total}",
1356
+ creditsUnit: "积分",
952
1357
  creditsUsed: "已用 {used}",
953
- creditsExpiring: "其中 {expiring} 将在 {date} 重置时作废",
1358
+ creditsUsedOfTotal: "已用 {used} / {total}",
1359
+ creditsTotal: "总额度 {total}",
1360
+ creditsExpiringShort: "即将到期 {expiring}",
1361
+ creditsUpdated: "{time} 更新",
954
1362
  creditsReset: "额度重置 {date}",
1363
+ creditsDetailLink: "查看积分明细 →",
955
1364
  creditsTokensToday: "今日 token {used} / {limit}",
956
1365
  creditsTokensBalance: "余额 {balance}",
957
1366
  creditsUnavailable: "积分不可用:{message}",
1367
+ creditsNeedSignIn: "这个账号需要重新登录",
958
1368
  creditsDock: "积分 {remain}",
959
1369
  creditsDockTitle: "CodeArts 剩余积分 {remain} / {total}",
960
1370
  claimButton: "签到领积分",
961
1371
  claimButtonDone: "今日已领",
962
1372
  claimPending: "领取中…",
1373
+ claimAll: "全部账号领取",
963
1374
  claimHint: "每天领一次 1000 积分,走官方福利中心接口(与客户端里那个「每日签到」同一件事)。",
964
1375
  claimDone: "已领取 {amount} 积分",
965
1376
  claimAlready: "今日已领,明天再来",
@@ -968,6 +1379,10 @@ const zh = {
968
1379
  };
969
1380
  const en = {
970
1381
  tabLabel: "CodeArts",
1382
+ tabsLabel: "CodeArts settings",
1383
+ tabAccounts: "Accounts · {n}",
1384
+ tabModels: "Models · {n}/{total}",
1385
+ tabUsage: "Usage",
971
1386
  cardTitle: "DSH CodeArts Connect",
972
1387
  statusSignedIn: "Signed in",
973
1388
  statusSignedOut: "Not signed in",
@@ -977,7 +1392,7 @@ const en = {
977
1392
  storedMeta: "{label} · stored {time}",
978
1393
  storedMetaNoLabel: "stored {time}",
979
1394
  refresh: "Refresh",
980
- clearToken: "Clear credential",
1395
+ clearToken: "Clear all credentials",
981
1396
  tokenLabel: "cloud_dragon_token",
982
1397
  tokenPlaceholder: "Paste the token taken from the CodeArts web/desktop client……",
983
1398
  labelLabel: "Label (optional)",
@@ -985,10 +1400,9 @@ const en = {
985
1400
  saveToken: "Save token",
986
1401
  expiredHint: "Your credential has expired. Sign in again to continue; your model selection is kept.",
987
1402
  accountsTitle: "Accounts",
988
- accountsShow: "Show accounts",
989
- accountsHide: "Hide accounts",
990
1403
  accountRemove: "Remove",
991
1404
  addAccount: "Add account",
1405
+ pasteTokenAdd: "Paste a token",
992
1406
  accountsRotateHint: "Multiple accounts stored: requests rotate automatically, so a busy account hands over to the next one instead of making you wait.",
993
1407
  accountNeedsSignIn: "Needs sign-in",
994
1408
  accountNoKey: "No AK/SK",
@@ -1000,7 +1414,14 @@ const en = {
1000
1414
  optionalModelsAllHint: "All models show in the picker by default; uncheck the ones you don’t want.",
1001
1415
  selectedCount: "{n} of {total} selected",
1002
1416
  selectAll: "Select all",
1003
- free: "Free",
1417
+ benefit: "Benefit",
1418
+ benefitBlocked: "Benefit unavailable today",
1419
+ 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.",
1420
+ refreshModels: "Refresh models",
1421
+ refreshing: "Refreshing…",
1422
+ refreshed: "Refreshed: {n} models, {benefit} on the benefit route",
1423
+ refreshStale: "Upstream did not answer; still showing the old {n} models",
1424
+ refreshFailed: "Refresh failed: {message}",
1004
1425
  saveModels: "Save selection",
1005
1426
  saving: "Saving…",
1006
1427
  saved: "Saved",
@@ -1012,7 +1433,11 @@ const en = {
1012
1433
  modelsLoading: "Loading model selection… (if it never appears, make sure you are signed in and DSH was fully restarted)",
1013
1434
  usageTitle: "Local usage",
1014
1435
  usageToday: "Today",
1436
+ usageTodayTotal: "Today",
1437
+ usageLast30: "Last 30 days",
1438
+ usageByAccount: "Today by account",
1015
1439
  usageRequests: "{n} request(s)",
1440
+ usageRequestCount: "{n} reqs",
1016
1441
  usageTokens: "in {prompt} · out {completion}",
1017
1442
  usageAllTime: "All time ({days} days)",
1018
1443
  usageByModel: "Today by model",
@@ -1023,19 +1448,24 @@ const en = {
1023
1448
  usageStateDisabled: "Disabled",
1024
1449
  usageNoQuota: "Counts the requests this machine sent through the plugin (not the account balance). Official usage:",
1025
1450
  usageEmpty: "Nothing recorded yet: send a message to start counting.",
1026
- creditsTitle: "Credits",
1027
- creditsRemaining: "{remain} of {total} left",
1451
+ creditsUnit: "credits",
1028
1452
  creditsUsed: "{used} used",
1029
- creditsExpiring: "{expiring} of them expire at the next reset on {date}",
1453
+ creditsUsedOfTotal: "{used} of {total} used",
1454
+ creditsTotal: "{total} total",
1455
+ creditsExpiringShort: "{expiring} expiring",
1456
+ creditsUpdated: "updated {time}",
1030
1457
  creditsReset: "Quota resets {date}",
1458
+ creditsDetailLink: "View credit details →",
1031
1459
  creditsTokensToday: "Today {used} / {limit} tokens",
1032
1460
  creditsTokensBalance: "{balance} left",
1033
1461
  creditsUnavailable: "Credits unavailable: {message}",
1462
+ creditsNeedSignIn: "This account needs signing in again",
1034
1463
  creditsDock: "Credits {remain}",
1035
1464
  creditsDockTitle: "CodeArts credits left {remain} / {total}",
1036
1465
  claimButton: "Claim daily credits",
1037
1466
  claimButtonDone: "Claimed today",
1038
1467
  claimPending: "Claiming…",
1468
+ claimAll: "Claim for all accounts",
1039
1469
  claimHint: "Claim 1,000 credits once a day through CodeArts’ welfare centre — the same check-in the official client does.",
1040
1470
  claimDone: "Claimed {amount} credits",
1041
1471
  claimAlready: "Already claimed today — come back tomorrow",