dsh-codearts 0.5.3 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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_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}";
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,32 +33,70 @@ 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
- "manualSummary": "xoziZG_manualSummary",
37
- "headActions": "xoziZG_headActions",
38
- "error": "xoziZG_error",
39
- "area": "xoziZG_area",
40
- "headText": "xoziZG_headText",
36
+ "accountCard": "xoziZG_accountCard",
37
+ "accountRow": "xoziZG_accountRow",
38
+ "creditBlock": "xoziZG_creditBlock",
39
+ "section": "xoziZG_section",
40
+ "accountRowActions": "xoziZG_accountRowActions",
41
+ "creditLink": "xoziZG_creditLink",
42
+ "choiceRow": "xoziZG_choiceRow",
41
43
  "danger": "xoziZG_danger",
42
- "body": "xoziZG_body",
43
- "name": "xoziZG_name",
44
- "actions": "xoziZG_actions",
45
- "statusLine": "xoziZG_statusLine",
44
+ "modelName": "xoziZG_modelName",
45
+ "manual": "xoziZG_manual",
46
+ "modelChart": "xoziZG_modelChart",
47
+ "creditHint": "xoziZG_creditHint",
48
+ "avatar": "xoziZG_avatar",
46
49
  "card": "xoziZG_card",
50
+ "fieldLabel": "xoziZG_fieldLabel",
51
+ "updated": "xoziZG_updated",
52
+ "name": "xoziZG_name",
53
+ "barFill": "xoziZG_barFill",
54
+ "expiryLabel": "xoziZG_expiryLabel",
55
+ "area": "xoziZG_area",
56
+ "manualForm": "xoziZG_manualForm",
57
+ "sectionLabel": "xoziZG_sectionLabel",
58
+ "choices": "xoziZG_choices",
59
+ "body": "xoziZG_body",
60
+ "accountInfo": "xoziZG_accountInfo",
61
+ "balanceRow": "xoziZG_balanceRow",
47
62
  "check": "xoziZG_check",
48
- "field": "xoziZG_field",
49
- "sectionHead": "xoziZG_sectionHead",
50
- "meta": "xoziZG_meta",
51
- "choiceRow": "xoziZG_choiceRow",
52
- "section": "xoziZG_section",
63
+ "tabPanel": "xoziZG_tabPanel",
64
+ "modelShare": "xoziZG_modelShare",
65
+ "accountName": "xoziZG_accountName",
66
+ "link": "xoziZG_link",
67
+ "modelFill": "xoziZG_modelFill",
68
+ "modelTrack": "xoziZG_modelTrack",
53
69
  "desc": "xoziZG_desc",
54
- "manual": "xoziZG_manual",
55
70
  "header": "xoziZG_header",
56
- "sectionLabel": "xoziZG_sectionLabel",
57
- "choices": "xoziZG_choices",
58
- "fieldLabel": "xoziZG_fieldLabel",
59
71
  "hint": "xoziZG_hint",
72
+ "accountToolbar": "xoziZG_accountToolbar",
73
+ "balanceUnit": "xoziZG_balanceUnit",
74
+ "claimAllRow": "xoziZG_claimAllRow",
75
+ "creditRow": "xoziZG_creditRow",
76
+ "modelTokens": "xoziZG_modelTokens",
77
+ "bar": "xoziZG_bar",
78
+ "expiryRow": "xoziZG_expiryRow",
79
+ "statusLine": "xoziZG_statusLine",
80
+ "accountHint": "xoziZG_accountHint",
81
+ "sectionHead": "xoziZG_sectionHead",
82
+ "tabs": "xoziZG_tabs",
83
+ "balanceMeta": "xoziZG_balanceMeta",
84
+ "meta": "xoziZG_meta",
85
+ "usageBar": "xoziZG_usageBar",
86
+ "error": "xoziZG_error",
87
+ "field": "xoziZG_field",
88
+ "balance": "xoziZG_balance",
89
+ "creditFooter": "xoziZG_creditFooter",
90
+ "creditRows": "xoziZG_creditRows",
91
+ "headText": "xoziZG_headText",
92
+ "actions": "xoziZG_actions",
60
93
  "count": "xoziZG_count",
61
- "link": "xoziZG_link"
94
+ "accountNameRow": "xoziZG_accountNameRow",
95
+ "usageFill": "xoziZG_usageFill",
96
+ "accountEntry": "xoziZG_accountEntry",
97
+ "modelRow": "xoziZG_modelRow",
98
+ "modelRequests": "xoziZG_modelRequests",
99
+ "manualSummary": "xoziZG_manualSummary"
62
100
  };
63
101
  //#endregion
64
102
  //#region src/client/CodeArtsPluginCard.tsx
@@ -76,13 +114,6 @@ function modelName(choice) {
76
114
  }
77
115
  /** 官方用量明细页。 */
78
116
  const OFFICIAL_USAGE_URL = "https://codearts.huaweicloud.com/portal/settings/personal-usage";
79
- /**
80
- * 账号身份默认遮蔽后的占位符。
81
- *
82
- * 卡片经常被截图贴进问题反馈,账号名(label / userName / id)与获取、过期时间
83
- * 没有出现在截图里的必要,所以默认遮住,点一下才展开。
84
- */
85
- const ACCOUNT_MASK = "*******";
86
117
  /** token 数按人类习惯缩写:12345 -> 12.3k。 */
87
118
  function formatTokens(value) {
88
119
  if (!Number.isFinite(value)) return "0";
@@ -97,6 +128,32 @@ function formatCount(value) {
97
128
  function formatCredits(value) {
98
129
  return Number.isFinite(value) ? new Intl.NumberFormat().format(Math.round(value)) : "0";
99
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
+ }
100
157
  /**
101
158
  * 领取结果 → 文案。
102
159
  *
@@ -109,99 +166,253 @@ function claimText(data, t) {
109
166
  if (data?.state === "unavailable") return t("claimUnavailable");
110
167
  return t("claimFailed", { message: typeof data?.message === "string" && data.message !== "" ? data.message : "request failed" });
111
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
+ }
112
190
  /**
113
- * 积分区块。
191
+ * 账号卡片里的积分块。
114
192
  *
115
- * 2026-10 从官方 CodeArts Agent 客户端挖出积分接口并实测通过(见 src/credits.ts),
116
- * 所以这里能直接显示账号总额度 —— 与下面的「本机用量」互补:一个是账号级、一个是
117
- * 本机级。拉不到时显示原因(creditsError),不静默吞掉。
193
+ * 积分并进账号页:视线从上到下就是「谁登录着 → 这个号还有多少积分 → 去签到」。
194
+ * 拉不到时只把原因留在块里,别把上面的账号一起拖没。
118
195
  */
119
- function CreditsSection({ credits, error, t, onClaim, claiming, claimResult, justClaimed }) {
196
+ function CreditBlock({ credits, error, t, onClaim, claiming, claimResult, justClaimed }) {
120
197
  if (credits === void 0 && error === void 0) return null;
121
198
  const c = credits?.credits;
122
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);
123
208
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
124
- className: CodeArtsPluginCard_module_css_default.section,
209
+ className: CodeArtsPluginCard_module_css_default.creditBlock,
125
210
  children: [
126
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
127
- className: CodeArtsPluginCard_module_css_default.sectionHead,
128
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
129
- className: CodeArtsPluginCard_module_css_default.sectionLabel,
130
- children: t("creditsTitle")
131
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
132
- className: CodeArtsPluginCard_module_css_default.headActions,
133
- children: [c !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
134
- className: CodeArtsPluginCard_module_css_default.count,
135
- children: t("creditsRemaining", {
136
- remain: formatCredits(c.total.remain),
137
- 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 })
138
230
  })
139
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
140
- variant: "outline",
141
- size: "sm",
142
- disabled: claiming || claimedToday,
143
- onClick: onClaim,
144
- children: claiming ? t("claimPending") : claimedToday ? t("claimButtonDone") : t("claimButton")
145
- })]
146
- })]
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) })
147
288
  }),
148
- error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
149
- className: CodeArtsPluginCard_module_css_default.hint,
150
- 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
+ })]
151
301
  }),
152
302
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
153
- className: CodeArtsPluginCard_module_css_default.hint,
303
+ className: CodeArtsPluginCard_module_css_default.creditHint,
154
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
+ })]
155
328
  }),
156
- c !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
157
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
158
- className: CodeArtsPluginCard_module_css_default.choiceRow,
159
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
160
- className: CodeArtsPluginCard_module_css_default.name,
161
- children: c.planName
162
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
163
- className: CodeArtsPluginCard_module_css_default.meta,
164
- children: t("creditsUsed", { used: formatCredits(c.total.used) })
165
- })]
166
- }),
167
- c.periodEnd !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
168
- className: CodeArtsPluginCard_module_css_default.choiceRow,
169
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
170
- className: CodeArtsPluginCard_module_css_default.name,
171
- children: t("creditsReset", { date: c.periodEnd })
172
- }), c.total.expiring > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
173
- className: CodeArtsPluginCard_module_css_default.meta,
174
- children: t("creditsExpiring", {
175
- expiring: formatCredits(c.total.expiring),
176
- date: c.periodEnd
177
- })
178
- })]
179
- }),
180
- credits?.tokens !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
181
- className: CodeArtsPluginCard_module_css_default.choiceRow,
182
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
183
- className: CodeArtsPluginCard_module_css_default.name,
184
- children: t("creditsTokensToday", {
185
- used: formatCredits(credits.tokens.dailyUsed),
186
- limit: formatCredits(credits.tokens.dailyLimit)
187
- })
188
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
189
- className: CodeArtsPluginCard_module_css_default.meta,
190
- children: t("creditsTokensBalance", { balance: formatCredits(credits.tokens.balance) })
191
- })]
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")
192
350
  })
193
- ] })
351
+ })
194
352
  ]
195
353
  });
196
354
  }
197
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
+ /**
198
409
  * 用量区块。
199
410
  *
200
411
  * 只展示**本机经插件发出**的请求(不等于账号总额度 —— 账号额度见上方积分区块);
201
412
  * 会话槽位是真事实 —— 每账号 3 个并发会话、被占时要等约 52 秒才释放,这也正是
202
413
  * 「打断后重新提问要等」的原因。
203
414
  */
204
- function UsageSection({ usage, t }) {
415
+ function UsageSection({ usage, accounts, t }) {
205
416
  const total = usage.today.requests;
206
417
  const stateLabel = {
207
418
  ok: t("usageStateOk"),
@@ -209,6 +420,18 @@ function UsageSection({ usage, t }) {
209
420
  cooling: t("usageStateCooling"),
210
421
  disabled: t("usageStateDisabled")
211
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;
212
435
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
213
436
  className: CodeArtsPluginCard_module_css_default.section,
214
437
  children: [
@@ -222,7 +445,7 @@ function UsageSection({ usage, t }) {
222
445
  children: t("usageRequests", { n: formatCount(total) })
223
446
  })]
224
447
  }),
225
- total === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
448
+ !hasUsage ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
226
449
  className: CodeArtsPluginCard_module_css_default.hint,
227
450
  children: t("usageEmpty")
228
451
  }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
@@ -230,52 +453,50 @@ function UsageSection({ usage, t }) {
230
453
  className: CodeArtsPluginCard_module_css_default.choiceRow,
231
454
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
232
455
  className: CodeArtsPluginCard_module_css_default.name,
233
- children: t("usageToday")
234
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
235
- className: CodeArtsPluginCard_module_css_default.meta,
236
- children: t("usageTokens", {
237
- prompt: formatTokens(usage.today.promptTokens),
238
- completion: formatTokens(usage.today.completionTokens)
239
- })
240
- })]
241
- }),
242
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
243
- className: CodeArtsPluginCard_module_css_default.choiceRow,
244
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
245
- className: CodeArtsPluginCard_module_css_default.name,
246
- children: t("usageAllTime", { days: formatCount(usage.days) })
456
+ children: t("usageTodayTotal")
247
457
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
248
458
  className: CodeArtsPluginCard_module_css_default.meta,
249
459
  children: [
250
- t("usageRequests", { n: formatCount(usage.allTime.requests) }),
460
+ t("usageRequests", { n: formatCount(total) }),
251
461
  " · ",
252
462
  t("usageTokens", {
253
- prompt: formatTokens(usage.allTime.promptTokens),
254
- completion: formatTokens(usage.allTime.completionTokens)
463
+ prompt: formatTokens(usage.today.promptTokens),
464
+ completion: formatTokens(usage.today.completionTokens)
255
465
  })
256
466
  ]
257
467
  })]
258
468
  }),
259
- usage.byModelToday.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
260
- className: CodeArtsPluginCard_module_css_default.hint,
261
- children: t("usageByModel")
262
- }), usage.byModelToday.slice(0, 5).map((entry) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
469
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
263
470
  className: CodeArtsPluginCard_module_css_default.choiceRow,
264
471
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
265
472
  className: CodeArtsPluginCard_module_css_default.name,
266
- children: entry.id
473
+ children: t("usageLast30")
267
474
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
268
475
  className: CodeArtsPluginCard_module_css_default.meta,
269
476
  children: [
270
- t("usageRequests", { n: formatCount(entry.totals.requests) }),
477
+ t("usageRequests", { n: formatCount(usage.last30.requests) }),
271
478
  " · ",
272
479
  t("usageTokens", {
273
- prompt: formatTokens(entry.totals.promptTokens),
274
- completion: formatTokens(entry.totals.completionTokens)
480
+ prompt: formatTokens(usage.last30.promptTokens),
481
+ completion: formatTokens(usage.last30.completionTokens)
275
482
  })
276
483
  ]
277
484
  })]
278
- }, 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
+ })] })
279
500
  ] }),
280
501
  usage.slots.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
281
502
  className: CodeArtsPluginCard_module_css_default.hint,
@@ -322,30 +543,53 @@ function CodeArtsPluginCard({ t }) {
322
543
  const [modelError, setModelError] = (0, react.useState)(null);
323
544
  const [refreshing, setRefreshing] = (0, react.useState)(false);
324
545
  const [refreshMsg, setRefreshMsg] = (0, react.useState)(null);
325
- /** 账号身份是否展开:默认遮蔽(false = 显示 *******)。 */
326
- const [accountsRevealed, setAccountsRevealed] = (0, react.useState)(false);
327
- const [claiming, setClaiming] = (0, react.useState)(false);
328
- const [claimResult, setClaimResult] = (0, react.useState)(null);
329
- const [justClaimed, setJustClaimed] = (0, react.useState)(false);
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)();
330
555
  /**
331
- * 领一次每日签到积分。
556
+ * 领每日签到积分。给 id 就只领那个号,不给就逐个号都领一遍。
332
557
  *
333
558
  * 除了这一次刚领成,「今天已领」都来自上游的福利活动状态(积分快照里的 welfare),
334
559
  * 所以刷新、重开窗口都不会把按钮说错。领完不记日期:去重在上游按天做。
335
560
  */
336
- async function claim() {
337
- 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);
338
564
  try {
339
- const data = await (await fetch("/api/codearts/claim", { method: "POST" })).json().catch(() => null);
340
- setClaimResult(claimText(data, t));
341
- if (data?.claimed === true) {
342
- 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
+ });
343
582
  await refresh();
344
583
  }
345
584
  } catch (error) {
346
- 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
+ });
347
591
  } finally {
348
- setClaiming(false);
592
+ setClaimingId(null);
349
593
  }
350
594
  }
351
595
  async function refresh() {
@@ -537,8 +781,6 @@ function CodeArtsPluginCard({ t }) {
537
781
  const expired = status?.status === "expired";
538
782
  const accounts = status?.accounts ?? [];
539
783
  const accountName = (account) => account.label?.trim() || account.userName?.trim() || account.id;
540
- /** 遮蔽态下账号身份一律换成占位符:原值连 DOM 都不进。 */
541
- const reveal = (value) => accountsRevealed ? value : ACCOUNT_MASK;
542
784
  /**
543
785
  * 每个账号的「获取时间 + 过期状态」。同一账号重复登录可能留下多条记录(上游不给
544
786
  * 稳定身份时的妥协),把时间摆出来用户才能一眼认出哪条是旧的、放心删。
@@ -555,10 +797,55 @@ function CodeArtsPluginCard({ t }) {
555
797
  const statusText = signedIn ? t("statusSignedIn") : expired ? t("statusExpired") : t("statusSignedOut");
556
798
  const storedTime = formatStored(status?.storedAt);
557
799
  const storedLabel = status?.label?.trim() ?? "";
558
- const meta = !signedIn || storedTime === "" ? "" : storedLabel === "" || !accountsRevealed ? t("storedMetaNoLabel", { time: storedTime }) : t("storedMeta", {
800
+ const meta = !signedIn || storedTime === "" ? "" : storedLabel === "" ? t("storedMetaNoLabel", { time: storedTime }) : t("storedMeta", {
559
801
  label: storedLabel,
560
802
  time: storedTime
561
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";
562
849
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
563
850
  className: CodeArtsPluginCard_module_css_default.card,
564
851
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -592,276 +879,311 @@ function CodeArtsPluginCard({ t }) {
592
879
  })]
593
880
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
594
881
  className: CodeArtsPluginCard_module_css_default.body,
595
- children: [
596
- signedIn ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
597
- className: CodeArtsPluginCard_module_css_default.section,
598
- children: [
599
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
600
- className: CodeArtsPluginCard_module_css_default.sectionHead,
601
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
602
- className: CodeArtsPluginCard_module_css_default.sectionLabel,
603
- children: t("accountsTitle")
604
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
605
- 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,
606
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", {
607
903
  className: CodeArtsPluginCard_module_css_default.count,
608
904
  children: accounts.length
609
- }), /* @__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, {
610
910
  variant: "outline",
611
911
  size: "sm",
612
- "aria-pressed": accountsRevealed,
613
- onClick: () => setAccountsRevealed((revealed) => !revealed),
614
- 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")
615
922
  })]
616
- })]
617
- }),
618
- accounts.length > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
619
- className: CodeArtsPluginCard_module_css_default.hint,
620
- children: t("accountsRotateHint")
621
- }),
622
- accounts.map((account) => {
623
- const meta = accountMeta(account);
624
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
625
- className: CodeArtsPluginCard_module_css_default.choiceRow,
923
+ }),
924
+ loginUrl !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
925
+ className: CodeArtsPluginCard_module_css_default.hint,
626
926
  children: [
627
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
628
- className: CodeArtsPluginCard_module_css_default.name,
629
- children: reveal(accountName(account))
630
- }),
631
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
632
- className: CodeArtsPluginCard_module_css_default.meta,
633
- children: reveal(meta)
634
- }),
635
- account.stale && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, { children: t("accountNeedsSignIn") }),
636
- !account.signable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, { children: t("accountNoKey") }),
637
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
638
- variant: "outline",
639
- size: "sm",
640
- className: CodeArtsPluginCard_module_css_default.danger,
641
- disabled: busy,
642
- onClick: () => void removeAccount(account.id),
643
- 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
644
935
  })
645
936
  ]
646
- }, account.id);
647
- }),
648
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
649
- className: CodeArtsPluginCard_module_css_default.actions,
650
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
651
- variant: "primary",
652
- size: "sm",
653
- disabled: busy || loginPending,
654
- onClick: () => void startOAuthLogin(),
655
- children: loginPending ? t("signingIn") : t("addAccount")
656
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
657
- variant: "outline",
658
- size: "sm",
659
- className: CodeArtsPluginCard_module_css_default.danger,
660
- disabled: busy,
661
- onClick: () => void clearToken(),
662
- children: t("clearToken")
663
- })]
664
- }),
665
- loginUrl !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
666
- className: CodeArtsPluginCard_module_css_default.hint,
667
- children: [
668
- t("openManually"),
669
- " ",
670
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
671
- className: CodeArtsPluginCard_module_css_default.link,
672
- href: loginUrl,
673
- target: "_blank",
674
- rel: "noreferrer",
675
- 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)
676
948
  })
677
- ]
678
- })
679
- ]
680
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
681
- className: CodeArtsPluginCard_module_css_default.section,
682
- children: [
683
- expired && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
684
- className: CodeArtsPluginCard_module_css_default.hint,
685
- children: t("expiredHint")
686
- }),
687
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
688
- className: CodeArtsPluginCard_module_css_default.actions,
689
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
690
- variant: "primary",
691
- disabled: busy || loginPending,
692
- onClick: () => void startOAuthLogin(),
693
- children: loginPending ? t("signingIn") : t("signIn")
694
- })
695
- }),
696
- loginUrl !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
697
- className: CodeArtsPluginCard_module_css_default.hint,
698
- children: [
699
- t("openManually"),
700
- " ",
701
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
702
- className: CodeArtsPluginCard_module_css_default.link,
703
- href: loginUrl,
704
- target: "_blank",
705
- rel: "noreferrer",
706
- children: loginUrl
707
- })
708
- ]
709
- }),
710
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
711
- className: CodeArtsPluginCard_module_css_default.manual,
712
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", {
713
- className: CodeArtsPluginCard_module_css_default.manualSummary,
714
- children: t("manualToken")
715
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("form", {
716
- onSubmit: (e) => void saveToken(e),
949
+ }),
950
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
951
+ className: CodeArtsPluginCard_module_css_default.accountCard,
717
952
  children: [
718
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
719
- className: CodeArtsPluginCard_module_css_default.field,
720
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
721
- className: CodeArtsPluginCard_module_css_default.fieldLabel,
722
- htmlFor: "codearts-token",
723
- children: t("tokenLabel")
724
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
725
- id: "codearts-token",
726
- className: CodeArtsPluginCard_module_css_default.area,
727
- value: token,
728
- onChange: (e) => setToken(e.target.value),
729
- placeholder: t("tokenPlaceholder"),
730
- rows: 4
731
- })]
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);
732
1005
  }),
733
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
734
- className: CodeArtsPluginCard_module_css_default.field,
735
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
736
- className: CodeArtsPluginCard_module_css_default.fieldLabel,
737
- htmlFor: "codearts-label",
738
- children: t("labelLabel")
739
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
740
- id: "codearts-label",
741
- value: label,
742
- onChange: (e) => setLabel(e.target.value),
743
- placeholder: t("labelPlaceholder")
744
- })]
745
- }),
746
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
747
- className: CodeArtsPluginCard_module_css_default.actions,
1006
+ accounts.length > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1007
+ className: CodeArtsPluginCard_module_css_default.claimAllRow,
748
1008
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
749
- variant: "primary",
1009
+ variant: "outline",
750
1010
  size: "sm",
751
- type: "submit",
752
- disabled: busy || token.trim() === "",
753
- children: t("saveToken")
1011
+ disabled: claimingId !== null,
1012
+ onClick: () => void claim(),
1013
+ children: claimingId === CLAIM_ALL ? t("claimPending") : t("claimAll")
754
1014
  })
1015
+ }),
1016
+ accounts.length > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1017
+ className: CodeArtsPluginCard_module_css_default.accountHint,
1018
+ children: t("accountsRotateHint")
755
1019
  })
756
1020
  ]
757
- })]
758
- })
759
- ]
760
- }),
761
- msg !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
762
- className: CodeArtsPluginCard_module_css_default.error,
763
- children: msg
764
- }),
765
- selection ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
766
- className: CodeArtsPluginCard_module_css_default.section,
767
- children: [
768
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
769
- className: CodeArtsPluginCard_module_css_default.sectionHead,
770
- children: [
771
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
772
- className: CodeArtsPluginCard_module_css_default.sectionLabel,
773
- children: t("modelsTitle")
774
- }),
775
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
776
- className: CodeArtsPluginCard_module_css_default.count,
777
- children: t("selectedCount", {
778
- n: draft.length,
779
- total: all
780
- })
781
- }),
782
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
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, {
783
1025
  variant: "outline",
784
1026
  size: "sm",
785
- disabled: refreshing,
786
- onClick: () => void refreshCatalog(),
787
- children: refreshing ? t("refreshing") : t("refreshModels")
1027
+ className: CodeArtsPluginCard_module_css_default.danger,
1028
+ disabled: busy,
1029
+ onClick: () => void clearToken(),
1030
+ children: t("clearToken")
788
1031
  })
789
- ]
790
- }),
791
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
792
- className: CodeArtsPluginCard_module_css_default.hint,
793
- children: selection.restricted ? t("optionalModelsHint") : t("optionalModelsAllHint")
794
- }),
795
- blockedCount > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
796
- className: CodeArtsPluginCard_module_css_default.hint,
797
- children: t("benefitBlockedHint", { n: blockedCount })
798
- }),
799
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
800
- className: CodeArtsPluginCard_module_css_default.choices,
801
- children: selection.choices.map((choice) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
802
- className: CodeArtsPluginCard_module_css_default.choiceRow,
1032
+ })
1033
+ ]
1034
+ })
1035
+ }),
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,
803
1045
  children: [
804
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Checkbox, {
805
- className: CodeArtsPluginCard_module_css_default.check,
806
- checked: draft.includes(choice.id),
807
- disabled: !selection.writable || savingModels,
808
- onChange: (on) => setModel(choice.id, on),
809
- label: modelName(choice)
1046
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1047
+ className: CodeArtsPluginCard_module_css_default.sectionLabel,
1048
+ children: t("modelsTitle")
810
1049
  }),
811
- choice.benefit === true && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, {
812
- tone: choice.blocked === true ? "warning" : "success",
813
- children: choice.blocked === true ? t("benefitBlocked") : t("benefit")
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
+ })
814
1056
  }),
815
- choice.ratio !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, {
816
- tone: "quiet",
817
- children: choice.ratio
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")
818
1063
  })
819
1064
  ]
820
- }, choice.id))
821
- }),
822
- selection.writable && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
823
- className: CodeArtsPluginCard_module_css_default.actions,
824
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
825
- variant: "outline",
826
- size: "sm",
827
- disabled: draft.length === all,
828
- onClick: () => {
829
- setSavedModels(false);
830
- setModelError(null);
831
- setDraft(selection.choices.map((c) => c.id));
832
- },
833
- children: t("selectAll")
834
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
835
- variant: "primary",
836
- size: "sm",
837
- disabled: !dirty || savingModels,
838
- onClick: () => void saveModels(),
839
- children: savingModels ? t("saving") : savedModels && !dirty ? t("saved") : t("saveModels")
840
- })]
841
- }),
842
- modelError !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
843
- className: CodeArtsPluginCard_module_css_default.error,
844
- children: modelError
845
- })
846
- ]
847
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
848
- className: CodeArtsPluginCard_module_css_default.hint,
849
- children: t("modelsLoading")
850
- }),
851
- signedIn && (status?.credits !== void 0 || status?.creditsError !== void 0) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CreditsSection, {
852
- credits: status?.credits,
853
- error: status?.creditsError,
854
- t,
855
- onClaim: () => void claim(),
856
- claiming,
857
- claimResult,
858
- justClaimed
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
+ })
859
1126
  }),
860
- status?.usage !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UsageSection, {
861
- usage: status.usage,
862
- 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
+ })
863
1136
  })
864
- ]
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
+ })]
865
1187
  })]
866
1188
  });
867
1189
  }
@@ -919,10 +1241,13 @@ function CodeArtsCreditDock({ useProjection, t }) {
919
1241
  });
920
1242
  if (!res.ok) return;
921
1243
  const data = await res.json().catch(() => void 0);
922
- 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;
923
1248
  if (mounted.current) {
924
- setRemain(Math.round(data.credits.credits.total.remain));
925
- 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)));
926
1251
  }
927
1252
  } catch {}
928
1253
  };
@@ -959,6 +1284,10 @@ function CodeArtsCreditDock({ useProjection, t }) {
959
1284
  //#region src/client/locales.ts
960
1285
  const zh = {
961
1286
  tabLabel: "CodeArts",
1287
+ tabsLabel: "CodeArts 设置",
1288
+ tabAccounts: "账号 · {n}",
1289
+ tabModels: "模型 · {n}/{total}",
1290
+ tabUsage: "用量",
962
1291
  cardTitle: "DSH CodeArts Connect",
963
1292
  statusSignedIn: "已登录",
964
1293
  statusSignedOut: "未登录",
@@ -968,7 +1297,7 @@ const zh = {
968
1297
  storedMeta: "{label} · 存于 {time}",
969
1298
  storedMetaNoLabel: "存于 {time}",
970
1299
  refresh: "刷新",
971
- clearToken: "清除凭证",
1300
+ clearToken: "清除全部凭据",
972
1301
  tokenLabel: "cloud_dragon_token",
973
1302
  tokenPlaceholder: "粘贴从 CodeArts 网页/桌面端拿到的 token……",
974
1303
  labelLabel: "备注(可选)",
@@ -976,10 +1305,9 @@ const zh = {
976
1305
  saveToken: "保存 token",
977
1306
  expiredHint: "凭证已过期,请重新登录以继续使用;已勾选的模型设置会保留。",
978
1307
  accountsTitle: "账号",
979
- accountsShow: "显示账号",
980
- accountsHide: "隐藏账号",
981
1308
  accountRemove: "删除",
982
1309
  addAccount: "添加账号",
1310
+ pasteTokenAdd: "粘贴 Token 添加",
983
1311
  accountsRotateHint: "已存多个账号:请求会自动轮转,某个账号忙时改用下一个,不用干等。",
984
1312
  accountNeedsSignIn: "需重新登录",
985
1313
  accountNoKey: "无 AK/SK",
@@ -1010,7 +1338,11 @@ const zh = {
1010
1338
  modelsLoading: "模型勾选区加载中…(若长期不出现,请确认已登录且 DSH 已完全重启)",
1011
1339
  usageTitle: "本机用量",
1012
1340
  usageToday: "今日",
1341
+ usageTodayTotal: "今日合计",
1342
+ usageLast30: "近 30 天",
1343
+ usageByAccount: "今日按账号",
1013
1344
  usageRequests: "{n} 次请求",
1345
+ usageRequestCount: "{n} 条",
1014
1346
  usageTokens: "输入 {prompt} · 输出 {completion}",
1015
1347
  usageAllTime: "累计({days} 天)",
1016
1348
  usageByModel: "今日按模型",
@@ -1021,19 +1353,24 @@ const zh = {
1021
1353
  usageStateDisabled: "已停用",
1022
1354
  usageNoQuota: "这里是本机经插件发出的请求统计(不等于账号总额度);官方用量明细见",
1023
1355
  usageEmpty: "还没有记录:发一条消息就会开始累计。",
1024
- creditsTitle: "积分",
1025
- creditsRemaining: "剩余 {remain} / {total}",
1356
+ creditsUnit: "积分",
1026
1357
  creditsUsed: "已用 {used}",
1027
- creditsExpiring: "其中 {expiring} 将在 {date} 重置时作废",
1358
+ creditsUsedOfTotal: "已用 {used} / {total}",
1359
+ creditsTotal: "总额度 {total}",
1360
+ creditsExpiringShort: "即将到期 {expiring}",
1361
+ creditsUpdated: "{time} 更新",
1028
1362
  creditsReset: "额度重置 {date}",
1363
+ creditsDetailLink: "查看积分明细 →",
1029
1364
  creditsTokensToday: "今日 token {used} / {limit}",
1030
1365
  creditsTokensBalance: "余额 {balance}",
1031
1366
  creditsUnavailable: "积分不可用:{message}",
1367
+ creditsNeedSignIn: "这个账号需要重新登录",
1032
1368
  creditsDock: "积分 {remain}",
1033
1369
  creditsDockTitle: "CodeArts 剩余积分 {remain} / {total}",
1034
1370
  claimButton: "签到领积分",
1035
1371
  claimButtonDone: "今日已领",
1036
1372
  claimPending: "领取中…",
1373
+ claimAll: "全部账号领取",
1037
1374
  claimHint: "每天领一次 1000 积分,走官方福利中心接口(与客户端里那个「每日签到」同一件事)。",
1038
1375
  claimDone: "已领取 {amount} 积分",
1039
1376
  claimAlready: "今日已领,明天再来",
@@ -1042,6 +1379,10 @@ const zh = {
1042
1379
  };
1043
1380
  const en = {
1044
1381
  tabLabel: "CodeArts",
1382
+ tabsLabel: "CodeArts settings",
1383
+ tabAccounts: "Accounts · {n}",
1384
+ tabModels: "Models · {n}/{total}",
1385
+ tabUsage: "Usage",
1045
1386
  cardTitle: "DSH CodeArts Connect",
1046
1387
  statusSignedIn: "Signed in",
1047
1388
  statusSignedOut: "Not signed in",
@@ -1051,7 +1392,7 @@ const en = {
1051
1392
  storedMeta: "{label} · stored {time}",
1052
1393
  storedMetaNoLabel: "stored {time}",
1053
1394
  refresh: "Refresh",
1054
- clearToken: "Clear credential",
1395
+ clearToken: "Clear all credentials",
1055
1396
  tokenLabel: "cloud_dragon_token",
1056
1397
  tokenPlaceholder: "Paste the token taken from the CodeArts web/desktop client……",
1057
1398
  labelLabel: "Label (optional)",
@@ -1059,10 +1400,9 @@ const en = {
1059
1400
  saveToken: "Save token",
1060
1401
  expiredHint: "Your credential has expired. Sign in again to continue; your model selection is kept.",
1061
1402
  accountsTitle: "Accounts",
1062
- accountsShow: "Show accounts",
1063
- accountsHide: "Hide accounts",
1064
1403
  accountRemove: "Remove",
1065
1404
  addAccount: "Add account",
1405
+ pasteTokenAdd: "Paste a token",
1066
1406
  accountsRotateHint: "Multiple accounts stored: requests rotate automatically, so a busy account hands over to the next one instead of making you wait.",
1067
1407
  accountNeedsSignIn: "Needs sign-in",
1068
1408
  accountNoKey: "No AK/SK",
@@ -1093,7 +1433,11 @@ const en = {
1093
1433
  modelsLoading: "Loading model selection… (if it never appears, make sure you are signed in and DSH was fully restarted)",
1094
1434
  usageTitle: "Local usage",
1095
1435
  usageToday: "Today",
1436
+ usageTodayTotal: "Today",
1437
+ usageLast30: "Last 30 days",
1438
+ usageByAccount: "Today by account",
1096
1439
  usageRequests: "{n} request(s)",
1440
+ usageRequestCount: "{n} reqs",
1097
1441
  usageTokens: "in {prompt} · out {completion}",
1098
1442
  usageAllTime: "All time ({days} days)",
1099
1443
  usageByModel: "Today by model",
@@ -1104,19 +1448,24 @@ const en = {
1104
1448
  usageStateDisabled: "Disabled",
1105
1449
  usageNoQuota: "Counts the requests this machine sent through the plugin (not the account balance). Official usage:",
1106
1450
  usageEmpty: "Nothing recorded yet: send a message to start counting.",
1107
- creditsTitle: "Credits",
1108
- creditsRemaining: "{remain} of {total} left",
1451
+ creditsUnit: "credits",
1109
1452
  creditsUsed: "{used} used",
1110
- 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}",
1111
1457
  creditsReset: "Quota resets {date}",
1458
+ creditsDetailLink: "View credit details →",
1112
1459
  creditsTokensToday: "Today {used} / {limit} tokens",
1113
1460
  creditsTokensBalance: "{balance} left",
1114
1461
  creditsUnavailable: "Credits unavailable: {message}",
1462
+ creditsNeedSignIn: "This account needs signing in again",
1115
1463
  creditsDock: "Credits {remain}",
1116
1464
  creditsDockTitle: "CodeArts credits left {remain} / {total}",
1117
1465
  claimButton: "Claim daily credits",
1118
1466
  claimButtonDone: "Claimed today",
1119
1467
  claimPending: "Claiming…",
1468
+ claimAll: "Claim for all accounts",
1120
1469
  claimHint: "Claim 1,000 credits once a day through CodeArts’ welfare centre — the same check-in the official client does.",
1121
1470
  claimDone: "Claimed {amount} credits",
1122
1471
  claimAlready: "Already claimed today — come back tomorrow",