dsh-codearts 0.0.0-stage → 0.3.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.
@@ -0,0 +1,1008 @@
1
+ window.__ModuleLoader__.load({
2
+ id: "dsh-codearts",
3
+ factory(require) {
4
+ var module = { exports: {} };
5
+ var exports = module.exports;
6
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
7
+ let react = require("react");
8
+ let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
9
+ let react_jsx_runtime = require("react/jsx-runtime");
10
+ //#region \0dsh-css:F:\centos\dsh-codearts\src\client\CodeArtsPluginCard.module.css.mjs
11
+ const css = ".DZPfya_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}.DZPfya_header{align-items:flex-start;gap:12px;padding:14px 16px;display:flex}.DZPfya_headText{flex-direction:column;flex:1;gap:6px;min-width:0;display:flex}.DZPfya_name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:22px}.DZPfya_desc{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:20px}.DZPfya_statusLine{color:var(--dsw-alias-label-primary);align-items:center;gap:6px;font-size:14px;font-weight:500;line-height:22px;display:inline-flex}.DZPfya_meta{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;font-size:12px;line-height:18px}.DZPfya_body{border-top:.5px solid var(--dsw-alias-border-l2);margin:0 16px;padding:4px 0 16px}.DZPfya_section{margin-top:16px}.DZPfya_sectionHead{justify-content:space-between;align-items:baseline;gap:12px;display:flex}.DZPfya_sectionLabel{color:var(--dsw-alias-label-tertiary);font-size:11px;font-weight:500}.DZPfya_headActions{flex:none;align-items:center;gap:8px;display:flex}.DZPfya_count{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;flex:none;font-size:12px}.DZPfya_hint{color:var(--dsw-alias-label-secondary);margin:8px 0 0;font-size:13px;line-height:20px}.DZPfya_error{color:var(--dsw-alias-state-error-primary);margin:10px 0 0;font-size:13px;line-height:20px}.DZPfya_actions{flex-wrap:wrap;align-items:center;gap:8px;margin-top:12px;display:flex}.DZPfya_danger{color:var(--dsw-alias-state-error-primary)}.DZPfya_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}.DZPfya_link:hover{text-decoration:underline}.DZPfya_choices{flex-direction:column;gap:2px;margin-top:8px;display:flex}.DZPfya_choiceRow{border-radius:var(--dsw-radius-sm);align-items:center;gap:8px;margin:0 -6px;padding:5px 6px;display:flex}.DZPfya_choiceRow:hover{background:var(--dsw-alias-interactive-bg-hover)}.DZPfya_check{flex:1;min-width:0}.DZPfya_check>span{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.DZPfya_manual{border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-md);margin-top:12px;padding:0 12px}.DZPfya_manual[open]{padding-bottom:12px}.DZPfya_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}.DZPfya_manualSummary::-webkit-details-marker{display:none}.DZPfya_field{flex-direction:column;gap:5px;margin-top:10px;display:flex}.DZPfya_fieldLabel{color:var(--dsw-alias-label-tertiary);font-size:12px}.DZPfya_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}.DZPfya_area::placeholder{color:var(--dsw-alias-label-dimmed)}.DZPfya_area:focus{border-color:var(--dsw-alias-state-business-primary);outline:none}";
12
+ const tagId = "dsh-codearts/CodeArtsPluginCard.module.css";
13
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
14
+ const tag = document.createElement("style");
15
+ tag.dataset.plugin = "dsh-codearts";
16
+ tag.dataset.pluginCss = tagId;
17
+ tag.textContent = css;
18
+ document.head.appendChild(tag);
19
+ }
20
+ var CodeArtsPluginCard_module_css_default = {
21
+ "fieldLabel": "DZPfya_fieldLabel",
22
+ "danger": "DZPfya_danger",
23
+ "card": "DZPfya_card",
24
+ "hint": "DZPfya_hint",
25
+ "header": "DZPfya_header",
26
+ "link": "DZPfya_link",
27
+ "body": "DZPfya_body",
28
+ "headText": "DZPfya_headText",
29
+ "name": "DZPfya_name",
30
+ "meta": "DZPfya_meta",
31
+ "section": "DZPfya_section",
32
+ "sectionLabel": "DZPfya_sectionLabel",
33
+ "error": "DZPfya_error",
34
+ "choices": "DZPfya_choices",
35
+ "desc": "DZPfya_desc",
36
+ "sectionHead": "DZPfya_sectionHead",
37
+ "choiceRow": "DZPfya_choiceRow",
38
+ "check": "DZPfya_check",
39
+ "manual": "DZPfya_manual",
40
+ "manualSummary": "DZPfya_manualSummary",
41
+ "statusLine": "DZPfya_statusLine",
42
+ "field": "DZPfya_field",
43
+ "actions": "DZPfya_actions",
44
+ "area": "DZPfya_area",
45
+ "headActions": "DZPfya_headActions",
46
+ "count": "DZPfya_count"
47
+ };
48
+ //#endregion
49
+ //#region src/client/CodeArtsPluginCard.tsx
50
+ function formatStored(ts) {
51
+ if (ts === void 0 || !Number.isFinite(ts)) return "";
52
+ try {
53
+ return new Date(ts).toLocaleString();
54
+ } catch {
55
+ return String(ts);
56
+ }
57
+ }
58
+ /** 上游给的 name 自带「 (免费)」尾巴,已经用 Tag 表达了就别重复一遍。 */
59
+ const TRAILING_FREE = /\s*[((]\s*免费\s*[))]\s*$/;
60
+ function modelName(choice) {
61
+ return choice.free === true ? choice.name.replace(TRAILING_FREE, "") : choice.name;
62
+ }
63
+ /** 官方用量明细页。 */
64
+ 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
+ /** token 数按人类习惯缩写:12345 -> 12.3k。 */
73
+ function formatTokens(value) {
74
+ if (!Number.isFinite(value)) return "0";
75
+ if (value >= 1e6) return `${(value / 1e6).toFixed(1)}M`;
76
+ if (value >= 1e3) return `${(value / 1e3).toFixed(1)}k`;
77
+ return String(Math.round(value));
78
+ }
79
+ function formatCount(value) {
80
+ return Number.isFinite(value) ? String(Math.round(value)) : "0";
81
+ }
82
+ /** 积分/token 千分位格式化(2000 → "2,000")。 */
83
+ function formatCredits(value) {
84
+ return Number.isFinite(value) ? new Intl.NumberFormat().format(Math.round(value)) : "0";
85
+ }
86
+ /**
87
+ * 积分区块。
88
+ *
89
+ * 2026-10 从官方 CodeArts Agent 客户端挖出积分接口并实测通过(见 src/credits.ts),
90
+ * 所以这里能直接显示账号总额度 —— 与下面的「本机用量」互补:一个是账号级、一个是
91
+ * 本机级。拉不到时显示原因(creditsError),不静默吞掉。
92
+ */
93
+ function CreditsSection({ credits, error, t }) {
94
+ if (credits === void 0 && error === void 0) return null;
95
+ const c = credits?.credits;
96
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
97
+ className: CodeArtsPluginCard_module_css_default.section,
98
+ children: [
99
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
100
+ className: CodeArtsPluginCard_module_css_default.sectionHead,
101
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
102
+ className: CodeArtsPluginCard_module_css_default.sectionLabel,
103
+ children: t("creditsTitle")
104
+ }), c !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
105
+ className: CodeArtsPluginCard_module_css_default.count,
106
+ children: t("creditsRemaining", {
107
+ remain: formatCredits(c.total.remain),
108
+ total: formatCredits(c.total.total)
109
+ })
110
+ })]
111
+ }),
112
+ error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
113
+ className: CodeArtsPluginCard_module_css_default.hint,
114
+ children: t("creditsUnavailable", { message: error })
115
+ }),
116
+ c !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
117
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
118
+ className: CodeArtsPluginCard_module_css_default.choiceRow,
119
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
120
+ className: CodeArtsPluginCard_module_css_default.name,
121
+ children: c.planName
122
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
123
+ className: CodeArtsPluginCard_module_css_default.meta,
124
+ children: t("creditsUsed", { used: formatCredits(c.total.used) })
125
+ })]
126
+ }),
127
+ c.periodEnd !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
128
+ className: CodeArtsPluginCard_module_css_default.choiceRow,
129
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
130
+ className: CodeArtsPluginCard_module_css_default.name,
131
+ children: t("creditsReset", { date: c.periodEnd })
132
+ }), c.total.expiring > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
133
+ className: CodeArtsPluginCard_module_css_default.meta,
134
+ children: t("creditsExpiring", {
135
+ expiring: formatCredits(c.total.expiring),
136
+ date: c.periodEnd
137
+ })
138
+ })]
139
+ }),
140
+ credits?.tokens !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
141
+ className: CodeArtsPluginCard_module_css_default.choiceRow,
142
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
143
+ className: CodeArtsPluginCard_module_css_default.name,
144
+ children: t("creditsTokensToday", {
145
+ used: formatCredits(credits.tokens.dailyUsed),
146
+ limit: formatCredits(credits.tokens.dailyLimit)
147
+ })
148
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
149
+ className: CodeArtsPluginCard_module_css_default.meta,
150
+ children: t("creditsTokensBalance", { balance: formatCredits(credits.tokens.balance) })
151
+ })]
152
+ })
153
+ ] })
154
+ ]
155
+ });
156
+ }
157
+ /**
158
+ * 用量区块。
159
+ *
160
+ * 只展示**本机经插件发出**的请求(不等于账号总额度 —— 账号额度见上方积分区块);
161
+ * 会话槽位是真事实 —— 每账号 3 个并发会话、被占时要等约 52 秒才释放,这也正是
162
+ * 「打断后重新提问要等」的原因。
163
+ */
164
+ function UsageSection({ usage, t }) {
165
+ const total = usage.today.requests;
166
+ const stateLabel = {
167
+ ok: t("usageStateOk"),
168
+ capped: t("usageStateCapped"),
169
+ cooling: t("usageStateCooling"),
170
+ disabled: t("usageStateDisabled")
171
+ };
172
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
173
+ className: CodeArtsPluginCard_module_css_default.section,
174
+ children: [
175
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
176
+ className: CodeArtsPluginCard_module_css_default.sectionHead,
177
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
178
+ className: CodeArtsPluginCard_module_css_default.sectionLabel,
179
+ children: t("usageTitle")
180
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
181
+ className: CodeArtsPluginCard_module_css_default.count,
182
+ children: t("usageRequests", { n: formatCount(total) })
183
+ })]
184
+ }),
185
+ total === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
186
+ className: CodeArtsPluginCard_module_css_default.hint,
187
+ children: t("usageEmpty")
188
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
189
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
190
+ className: CodeArtsPluginCard_module_css_default.choiceRow,
191
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
192
+ className: CodeArtsPluginCard_module_css_default.name,
193
+ children: t("usageToday")
194
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
195
+ className: CodeArtsPluginCard_module_css_default.meta,
196
+ children: t("usageTokens", {
197
+ prompt: formatTokens(usage.today.promptTokens),
198
+ completion: formatTokens(usage.today.completionTokens)
199
+ })
200
+ })]
201
+ }),
202
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
203
+ className: CodeArtsPluginCard_module_css_default.choiceRow,
204
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
205
+ className: CodeArtsPluginCard_module_css_default.name,
206
+ children: t("usageAllTime", { days: formatCount(usage.days) })
207
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
208
+ className: CodeArtsPluginCard_module_css_default.meta,
209
+ children: [
210
+ t("usageRequests", { n: formatCount(usage.allTime.requests) }),
211
+ " · ",
212
+ t("usageTokens", {
213
+ prompt: formatTokens(usage.allTime.promptTokens),
214
+ completion: formatTokens(usage.allTime.completionTokens)
215
+ })
216
+ ]
217
+ })]
218
+ }),
219
+ usage.byModelToday.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
220
+ className: CodeArtsPluginCard_module_css_default.hint,
221
+ children: t("usageByModel")
222
+ }), usage.byModelToday.slice(0, 5).map((entry) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
223
+ className: CodeArtsPluginCard_module_css_default.choiceRow,
224
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
225
+ className: CodeArtsPluginCard_module_css_default.name,
226
+ children: entry.id
227
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
228
+ className: CodeArtsPluginCard_module_css_default.meta,
229
+ children: [
230
+ t("usageRequests", { n: formatCount(entry.totals.requests) }),
231
+ " · ",
232
+ t("usageTokens", {
233
+ prompt: formatTokens(entry.totals.promptTokens),
234
+ completion: formatTokens(entry.totals.completionTokens)
235
+ })
236
+ ]
237
+ })]
238
+ }, entry.id))] })
239
+ ] }),
240
+ usage.slots.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
241
+ className: CodeArtsPluginCard_module_css_default.hint,
242
+ children: t("usageSlots")
243
+ }), usage.slots.map((slot) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
244
+ className: CodeArtsPluginCard_module_css_default.choiceRow,
245
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
246
+ className: CodeArtsPluginCard_module_css_default.name,
247
+ children: `${slot.active}/${slot.max}`
248
+ }), slot.state === "ok" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, {
249
+ tone: "success",
250
+ children: stateLabel.ok
251
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, { children: stateLabel[slot.state] })]
252
+ }, slot.id))] }),
253
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
254
+ className: CodeArtsPluginCard_module_css_default.hint,
255
+ children: [
256
+ t("usageNoQuota"),
257
+ " ",
258
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
259
+ className: CodeArtsPluginCard_module_css_default.link,
260
+ href: OFFICIAL_USAGE_URL,
261
+ target: "_blank",
262
+ rel: "noreferrer",
263
+ children: OFFICIAL_USAGE_URL
264
+ })
265
+ ]
266
+ })
267
+ ]
268
+ });
269
+ }
270
+ function CodeArtsPluginCard({ t }) {
271
+ const [status, setStatus] = (0, react.useState)(null);
272
+ const [token, setToken] = (0, react.useState)("");
273
+ const [label, setLabel] = (0, react.useState)("");
274
+ const [busy, setBusy] = (0, react.useState)(false);
275
+ const [msg, setMsg] = (0, react.useState)(null);
276
+ const [loginUrl, setLoginUrl] = (0, react.useState)(null);
277
+ const [loginPending, setLoginPending] = (0, react.useState)(false);
278
+ const [selection, setSelection] = (0, react.useState)(null);
279
+ const [draft, setDraft] = (0, react.useState)([]);
280
+ const [savingModels, setSavingModels] = (0, react.useState)(false);
281
+ const [savedModels, setSavedModels] = (0, react.useState)(false);
282
+ const [modelError, setModelError] = (0, react.useState)(null);
283
+ /** 账号身份是否展开:默认遮蔽(false = 显示 *******)。 */
284
+ const [accountsRevealed, setAccountsRevealed] = (0, react.useState)(false);
285
+ async function refresh() {
286
+ try {
287
+ const data = await (await fetch("/api/codearts/status", { headers: { Accept: "application/json" } })).json();
288
+ setStatus(data);
289
+ } catch {
290
+ setStatus({
291
+ status: "signed-out",
292
+ models: [],
293
+ accounts: []
294
+ });
295
+ }
296
+ }
297
+ async function refreshSelection() {
298
+ try {
299
+ const data = await (await fetch("/api/codearts/enabled-models", { headers: { Accept: "application/json" } })).json();
300
+ setSelection(data.selection);
301
+ setDraft(data.selection.choices.filter((c) => c.enabled).map((c) => c.id));
302
+ setSavedModels(true);
303
+ } catch {
304
+ setSelection(null);
305
+ }
306
+ }
307
+ (0, react.useEffect)(() => {
308
+ refresh();
309
+ }, []);
310
+ (0, react.useEffect)(() => {
311
+ refreshSelection();
312
+ }, []);
313
+ (0, react.useEffect)(() => {
314
+ if (status?.status === "signed-in") refreshSelection();
315
+ }, [status?.status]);
316
+ async function saveToken(e) {
317
+ e.preventDefault();
318
+ setBusy(true);
319
+ setMsg(null);
320
+ try {
321
+ const res = await fetch("/api/codearts/token", {
322
+ method: "POST",
323
+ headers: { "Content-Type": "application/json" },
324
+ body: JSON.stringify({
325
+ token: token.trim(),
326
+ label: label.trim() || void 0
327
+ })
328
+ });
329
+ if (!res.ok) {
330
+ const data = await res.json().catch(() => ({}));
331
+ setMsg(data.error ?? `HTTP ${res.status}`);
332
+ } else {
333
+ setToken("");
334
+ setLabel("");
335
+ await refresh();
336
+ }
337
+ } catch (err) {
338
+ setMsg(err instanceof Error ? err.message : String(err));
339
+ } finally {
340
+ setBusy(false);
341
+ }
342
+ }
343
+ async function clearToken() {
344
+ setBusy(true);
345
+ try {
346
+ await fetch("/api/codearts/token", { method: "DELETE" });
347
+ await refresh();
348
+ } finally {
349
+ setBusy(false);
350
+ }
351
+ }
352
+ async function removeAccount(id) {
353
+ setBusy(true);
354
+ try {
355
+ await fetch(`/api/codearts/accounts?id=${encodeURIComponent(id)}`, { method: "DELETE" });
356
+ await refresh();
357
+ } finally {
358
+ setBusy(false);
359
+ }
360
+ }
361
+ const all = selection?.choices.length ?? 0;
362
+ const wire = draft.length === all ? [] : draft;
363
+ const savedIds = selection?.choices.filter((c) => c.enabled).map((c) => c.id) ?? [];
364
+ const dirty = savedIds.length !== draft.length || savedIds.some((id) => !draft.includes(id));
365
+ function setModel(id, on) {
366
+ setSavedModels(false);
367
+ setModelError(null);
368
+ setDraft((current) => on ? [...current, id] : current.filter((e) => e !== id));
369
+ }
370
+ async function saveModels() {
371
+ setSavingModels(true);
372
+ setModelError(null);
373
+ try {
374
+ const res = await fetch("/api/codearts/enabled-models", {
375
+ method: "POST",
376
+ headers: {
377
+ "Content-Type": "application/json",
378
+ Accept: "application/json"
379
+ },
380
+ body: JSON.stringify({ enabledModels: wire })
381
+ });
382
+ if (!res.ok) {
383
+ const data = await res.json().catch(() => ({}));
384
+ throw new Error(data.error ?? `HTTP ${res.status}`);
385
+ }
386
+ const data = await res.json();
387
+ setSelection(data.selection);
388
+ setDraft(data.selection.choices.filter((c) => c.enabled).map((c) => c.id));
389
+ setSavedModels(true);
390
+ } catch (err) {
391
+ setModelError(err instanceof Error ? err.message : String(err));
392
+ } finally {
393
+ setSavingModels(false);
394
+ }
395
+ }
396
+ async function startOAuthLogin() {
397
+ setBusy(true);
398
+ setMsg(null);
399
+ setLoginPending(true);
400
+ try {
401
+ const res = await fetch("/api/codearts/login", { method: "POST" });
402
+ const data = await res.json().catch(() => ({}));
403
+ if (!res.ok || typeof data.url !== "string") {
404
+ setMsg(data.error ?? `HTTP ${res.status}`);
405
+ setLoginPending(false);
406
+ return;
407
+ }
408
+ setLoginUrl(data.url);
409
+ if (typeof window !== "undefined") window.open(data.url, "_blank");
410
+ const poll = async () => {
411
+ const st = await (await fetch(`/api/codearts/login/status?url=${encodeURIComponent(data.url)}`, { headers: { Accept: "application/json" } })).json().catch(() => ({ status: "pending" }));
412
+ if (st.status === "done") {
413
+ setLoginUrl(null);
414
+ setLoginPending(false);
415
+ await refresh();
416
+ return;
417
+ }
418
+ if (st.status === "error") {
419
+ setLoginUrl(null);
420
+ setLoginPending(false);
421
+ setMsg(t("loginFailed"));
422
+ return;
423
+ }
424
+ if (st.status === "idle") {
425
+ setLoginUrl(null);
426
+ setLoginPending(false);
427
+ await refresh();
428
+ return;
429
+ }
430
+ setTimeout(() => void poll(), 1500);
431
+ };
432
+ poll();
433
+ } catch (err) {
434
+ setMsg(err instanceof Error ? err.message : String(err));
435
+ setLoginPending(false);
436
+ } finally {
437
+ setBusy(false);
438
+ }
439
+ }
440
+ const signedIn = status?.status === "signed-in";
441
+ const expired = status?.status === "expired";
442
+ const accounts = status?.accounts ?? [];
443
+ const accountName = (account) => account.label?.trim() || account.userName?.trim() || account.id;
444
+ /** 遮蔽态下账号身份一律换成占位符:原值连 DOM 都不进。 */
445
+ const reveal = (value) => accountsRevealed ? value : ACCOUNT_MASK;
446
+ /**
447
+ * 每个账号的「获取时间 + 过期状态」。同一账号重复登录可能留下多条记录(上游不给
448
+ * 稳定身份时的妥协),把时间摆出来用户才能一眼认出哪条是旧的、放心删。
449
+ */
450
+ const accountMeta = (account) => {
451
+ const parts = [];
452
+ const stored = formatStored(account.storedAt);
453
+ if (stored !== "") parts.push(t("accountStored", { time: stored }));
454
+ const exp = typeof account.expiration === "string" ? Date.parse(account.expiration) : NaN;
455
+ if (Number.isFinite(exp)) parts.push(exp <= Date.now() ? t("accountExpired", { time: formatStored(exp) }) : t("accountExpires", { time: formatStored(exp) }));
456
+ return parts.join(" · ");
457
+ };
458
+ const dotState = signedIn ? "done" : expired ? "warning" : "idle";
459
+ const statusText = signedIn ? t("statusSignedIn") : expired ? t("statusExpired") : t("statusSignedOut");
460
+ const storedTime = formatStored(status?.storedAt);
461
+ const storedLabel = status?.label?.trim() ?? "";
462
+ const meta = !signedIn || storedTime === "" ? "" : storedLabel === "" || !accountsRevealed ? t("storedMetaNoLabel", { time: storedTime }) : t("storedMeta", {
463
+ label: storedLabel,
464
+ time: storedTime
465
+ });
466
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
467
+ className: CodeArtsPluginCard_module_css_default.card,
468
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
469
+ className: CodeArtsPluginCard_module_css_default.header,
470
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
471
+ className: CodeArtsPluginCard_module_css_default.headText,
472
+ children: [
473
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
474
+ className: CodeArtsPluginCard_module_css_default.name,
475
+ children: t("cardTitle")
476
+ }),
477
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
478
+ className: CodeArtsPluginCard_module_css_default.statusLine,
479
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, { state: dotState }), statusText]
480
+ }),
481
+ meta !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
482
+ className: CodeArtsPluginCard_module_css_default.meta,
483
+ children: meta
484
+ }),
485
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
486
+ className: CodeArtsPluginCard_module_css_default.desc,
487
+ children: signedIn ? t("descSignedIn") : t("descSignedOut")
488
+ })
489
+ ]
490
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
491
+ variant: "outline",
492
+ size: "sm",
493
+ disabled: busy,
494
+ onClick: () => void refresh(),
495
+ children: t("refresh")
496
+ })]
497
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
498
+ className: CodeArtsPluginCard_module_css_default.body,
499
+ children: [
500
+ signedIn ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
501
+ className: CodeArtsPluginCard_module_css_default.section,
502
+ children: [
503
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
504
+ className: CodeArtsPluginCard_module_css_default.sectionHead,
505
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
506
+ className: CodeArtsPluginCard_module_css_default.sectionLabel,
507
+ children: t("accountsTitle")
508
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
509
+ className: CodeArtsPluginCard_module_css_default.headActions,
510
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
511
+ className: CodeArtsPluginCard_module_css_default.count,
512
+ children: accounts.length
513
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
514
+ variant: "outline",
515
+ size: "sm",
516
+ "aria-pressed": accountsRevealed,
517
+ onClick: () => setAccountsRevealed((revealed) => !revealed),
518
+ children: accountsRevealed ? t("accountsHide") : t("accountsShow")
519
+ })]
520
+ })]
521
+ }),
522
+ accounts.length > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
523
+ className: CodeArtsPluginCard_module_css_default.hint,
524
+ children: t("accountsRotateHint")
525
+ }),
526
+ accounts.map((account) => {
527
+ const meta = accountMeta(account);
528
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
529
+ className: CodeArtsPluginCard_module_css_default.choiceRow,
530
+ children: [
531
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
532
+ className: CodeArtsPluginCard_module_css_default.name,
533
+ children: reveal(accountName(account))
534
+ }),
535
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
536
+ className: CodeArtsPluginCard_module_css_default.meta,
537
+ children: reveal(meta)
538
+ }),
539
+ account.stale && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, { children: t("accountNeedsSignIn") }),
540
+ !account.signable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, { children: t("accountNoKey") }),
541
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
542
+ variant: "outline",
543
+ size: "sm",
544
+ className: CodeArtsPluginCard_module_css_default.danger,
545
+ disabled: busy,
546
+ onClick: () => void removeAccount(account.id),
547
+ children: t("accountRemove")
548
+ })
549
+ ]
550
+ }, account.id);
551
+ }),
552
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
553
+ className: CodeArtsPluginCard_module_css_default.actions,
554
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
555
+ variant: "primary",
556
+ size: "sm",
557
+ disabled: busy || loginPending,
558
+ onClick: () => void startOAuthLogin(),
559
+ children: loginPending ? t("signingIn") : t("addAccount")
560
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
561
+ variant: "outline",
562
+ size: "sm",
563
+ className: CodeArtsPluginCard_module_css_default.danger,
564
+ disabled: busy,
565
+ onClick: () => void clearToken(),
566
+ children: t("clearToken")
567
+ })]
568
+ }),
569
+ loginUrl !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
570
+ className: CodeArtsPluginCard_module_css_default.hint,
571
+ children: [
572
+ t("openManually"),
573
+ " ",
574
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
575
+ className: CodeArtsPluginCard_module_css_default.link,
576
+ href: loginUrl,
577
+ target: "_blank",
578
+ rel: "noreferrer",
579
+ children: loginUrl
580
+ })
581
+ ]
582
+ })
583
+ ]
584
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
585
+ className: CodeArtsPluginCard_module_css_default.section,
586
+ children: [
587
+ expired && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
588
+ className: CodeArtsPluginCard_module_css_default.hint,
589
+ children: t("expiredHint")
590
+ }),
591
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
592
+ className: CodeArtsPluginCard_module_css_default.actions,
593
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
594
+ variant: "primary",
595
+ disabled: busy || loginPending,
596
+ onClick: () => void startOAuthLogin(),
597
+ children: loginPending ? t("signingIn") : t("signIn")
598
+ })
599
+ }),
600
+ loginUrl !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
601
+ className: CodeArtsPluginCard_module_css_default.hint,
602
+ children: [
603
+ t("openManually"),
604
+ " ",
605
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
606
+ className: CodeArtsPluginCard_module_css_default.link,
607
+ href: loginUrl,
608
+ target: "_blank",
609
+ rel: "noreferrer",
610
+ children: loginUrl
611
+ })
612
+ ]
613
+ }),
614
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
615
+ className: CodeArtsPluginCard_module_css_default.manual,
616
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", {
617
+ className: CodeArtsPluginCard_module_css_default.manualSummary,
618
+ children: t("manualToken")
619
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("form", {
620
+ onSubmit: (e) => void saveToken(e),
621
+ children: [
622
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
623
+ className: CodeArtsPluginCard_module_css_default.field,
624
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
625
+ className: CodeArtsPluginCard_module_css_default.fieldLabel,
626
+ htmlFor: "codearts-token",
627
+ children: t("tokenLabel")
628
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
629
+ id: "codearts-token",
630
+ className: CodeArtsPluginCard_module_css_default.area,
631
+ value: token,
632
+ onChange: (e) => setToken(e.target.value),
633
+ placeholder: t("tokenPlaceholder"),
634
+ rows: 4
635
+ })]
636
+ }),
637
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
638
+ className: CodeArtsPluginCard_module_css_default.field,
639
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
640
+ className: CodeArtsPluginCard_module_css_default.fieldLabel,
641
+ htmlFor: "codearts-label",
642
+ children: t("labelLabel")
643
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
644
+ id: "codearts-label",
645
+ value: label,
646
+ onChange: (e) => setLabel(e.target.value),
647
+ placeholder: t("labelPlaceholder")
648
+ })]
649
+ }),
650
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
651
+ className: CodeArtsPluginCard_module_css_default.actions,
652
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
653
+ variant: "primary",
654
+ size: "sm",
655
+ type: "submit",
656
+ disabled: busy || token.trim() === "",
657
+ children: t("saveToken")
658
+ })
659
+ })
660
+ ]
661
+ })]
662
+ })
663
+ ]
664
+ }),
665
+ msg !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
666
+ className: CodeArtsPluginCard_module_css_default.error,
667
+ children: msg
668
+ }),
669
+ selection ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
670
+ className: CodeArtsPluginCard_module_css_default.section,
671
+ children: [
672
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
673
+ className: CodeArtsPluginCard_module_css_default.sectionHead,
674
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
675
+ className: CodeArtsPluginCard_module_css_default.sectionLabel,
676
+ children: t("modelsTitle")
677
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
678
+ className: CodeArtsPluginCard_module_css_default.count,
679
+ children: t("selectedCount", {
680
+ n: draft.length,
681
+ total: all
682
+ })
683
+ })]
684
+ }),
685
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
686
+ className: CodeArtsPluginCard_module_css_default.hint,
687
+ children: selection.restricted ? t("optionalModelsHint") : t("optionalModelsAllHint")
688
+ }),
689
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
690
+ className: CodeArtsPluginCard_module_css_default.choices,
691
+ children: selection.choices.map((choice) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
692
+ className: CodeArtsPluginCard_module_css_default.choiceRow,
693
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Checkbox, {
694
+ className: CodeArtsPluginCard_module_css_default.check,
695
+ checked: draft.includes(choice.id),
696
+ disabled: !selection.writable || savingModels,
697
+ onChange: (on) => setModel(choice.id, on),
698
+ label: modelName(choice)
699
+ }), choice.free === true && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, {
700
+ tone: "success",
701
+ children: t("free")
702
+ })]
703
+ }, choice.id))
704
+ }),
705
+ selection.writable && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
706
+ className: CodeArtsPluginCard_module_css_default.actions,
707
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
708
+ variant: "outline",
709
+ size: "sm",
710
+ disabled: draft.length === all,
711
+ onClick: () => {
712
+ setSavedModels(false);
713
+ setModelError(null);
714
+ setDraft(selection.choices.map((c) => c.id));
715
+ },
716
+ children: t("selectAll")
717
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
718
+ variant: "primary",
719
+ size: "sm",
720
+ disabled: !dirty || savingModels,
721
+ onClick: () => void saveModels(),
722
+ children: savingModels ? t("saving") : savedModels && !dirty ? t("saved") : t("saveModels")
723
+ })]
724
+ }),
725
+ modelError !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
726
+ className: CodeArtsPluginCard_module_css_default.error,
727
+ children: modelError
728
+ })
729
+ ]
730
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
731
+ className: CodeArtsPluginCard_module_css_default.hint,
732
+ children: t("modelsLoading")
733
+ }),
734
+ signedIn && (status?.credits !== void 0 || status?.creditsError !== void 0) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CreditsSection, {
735
+ credits: status?.credits,
736
+ error: status?.creditsError,
737
+ t
738
+ }),
739
+ status?.usage !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UsageSection, {
740
+ usage: status.usage,
741
+ t
742
+ })
743
+ ]
744
+ })]
745
+ });
746
+ }
747
+ //#endregion
748
+ //#region src/client/CodeArtsCreditDock.tsx
749
+ /**
750
+ * 对话底部的积分条。
751
+ *
752
+ * 用户最初的诉求就是「对话底部要显示积分」—— 这一条挂在
753
+ * `conversation.composer.dock` 槽位上(与宿主 session-stats strip 同位)。
754
+ * 只在当前 provider 是 codearts 时才拉取并显示一行「积分 N」,别的 provider 下
755
+ * 完全不渲染,不抢别人的行。
756
+ *
757
+ * 积分数据走插件自己的 `/api/codearts/status`(带 TTL 缓存,见 src/credits.ts),
758
+ * 不会因为这条 dock 让上游多挨一次请求。
759
+ */
760
+ /** 与 src/adapter.ts 的 CODEARTS_PROVIDER 对齐 —— client 不能 import host 模块。 */
761
+ const CODEARTS_PROVIDER = "codearts";
762
+ const STATUS_PATH = "/api/codearts/status";
763
+ /** 轮询间隔:与缓存 TTL(60s)对齐,再短也只是反复命中缓存。 */
764
+ const REFRESH_INTERVAL_MS = 6e4;
765
+ function readSelection(useProjection) {
766
+ if (useProjection === void 0) return void 0;
767
+ try {
768
+ return useProjection("modelSelection");
769
+ } catch {
770
+ return;
771
+ }
772
+ }
773
+ function isCodeArts(selection) {
774
+ return (selection?.next ?? selection?.lastUsed)?.provider === CODEARTS_PROVIDER;
775
+ }
776
+ function CodeArtsCreditDock({ useProjection, t }) {
777
+ const active = isCodeArts(readSelection(useProjection));
778
+ const [remain, setRemain] = (0, react.useState)(null);
779
+ const [total, setTotal] = (0, react.useState)(0);
780
+ const mounted = (0, react.useRef)(true);
781
+ (0, react.useEffect)(() => {
782
+ mounted.current = true;
783
+ return () => {
784
+ mounted.current = false;
785
+ };
786
+ }, []);
787
+ (0, react.useEffect)(() => {
788
+ if (!active) {
789
+ setRemain(null);
790
+ return;
791
+ }
792
+ let timer;
793
+ const refresh = async () => {
794
+ try {
795
+ const res = await fetch(STATUS_PATH, {
796
+ headers: { Accept: "application/json" },
797
+ credentials: "same-origin"
798
+ });
799
+ if (!res.ok) return;
800
+ const data = await res.json().catch(() => void 0);
801
+ if (data === void 0 || data.credits === void 0) return;
802
+ if (mounted.current) {
803
+ setRemain(Math.round(data.credits.credits.total.remain));
804
+ setTotal(Math.round(data.credits.credits.total.total));
805
+ }
806
+ } catch {}
807
+ };
808
+ refresh();
809
+ timer = window.setInterval(refresh, REFRESH_INTERVAL_MS);
810
+ return () => {
811
+ if (timer !== void 0) window.clearInterval(timer);
812
+ };
813
+ }, [active]);
814
+ if (!active || remain === null) return null;
815
+ const text = t("creditsDock", { remain: new Intl.NumberFormat().format(remain) });
816
+ const title = t("creditsDockTitle", {
817
+ remain,
818
+ total
819
+ });
820
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
821
+ style: {
822
+ display: "inline-flex",
823
+ alignItems: "center",
824
+ gap: 6,
825
+ color: "var(--dsw-alias-label-tertiary)",
826
+ fontSize: "var(--dsh-content-font-size-secondary, 13px)",
827
+ lineHeight: "18px",
828
+ fontVariantNumeric: "tabular-nums",
829
+ whiteSpace: "nowrap"
830
+ },
831
+ title,
832
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: text })
833
+ });
834
+ }
835
+ //#endregion
836
+ //#region src/client/locales.ts
837
+ const zh = {
838
+ tabLabel: "CodeArts",
839
+ cardTitle: "DSH CodeArts Connect",
840
+ statusSignedIn: "已登录",
841
+ statusSignedOut: "未登录",
842
+ statusExpired: "凭证已过期",
843
+ descSignedIn: "凭证已就绪,勾选的模型会出现在模型选择器里。",
844
+ descSignedOut: "用华为云账号登录,或手动粘贴一个 CodeArts cloud_dragon_token。",
845
+ storedMeta: "{label} · 存于 {time}",
846
+ storedMetaNoLabel: "存于 {time}",
847
+ refresh: "刷新",
848
+ clearToken: "清除凭证",
849
+ tokenLabel: "cloud_dragon_token",
850
+ tokenPlaceholder: "粘贴从 CodeArts 网页/桌面端拿到的 token……",
851
+ labelLabel: "备注(可选)",
852
+ labelPlaceholder: "例如账号昵称,便于区分",
853
+ saveToken: "保存 token",
854
+ expiredHint: "凭证已过期,请重新登录以继续使用;已勾选的模型设置会保留。",
855
+ accountsTitle: "账号",
856
+ accountsShow: "显示账号",
857
+ accountsHide: "隐藏账号",
858
+ accountRemove: "删除",
859
+ addAccount: "添加账号",
860
+ accountsRotateHint: "已存多个账号:请求会自动轮转,某个账号忙时改用下一个,不用干等。",
861
+ accountNeedsSignIn: "需重新登录",
862
+ accountNoKey: "无 AK/SK",
863
+ accountStored: "获取于 {time}",
864
+ accountExpires: "{time} 过期",
865
+ accountExpired: "已于 {time} 过期",
866
+ modelsTitle: "可选模型",
867
+ optionalModelsHint: "仅勾选的模型会出现在模型选择器里。",
868
+ optionalModelsAllHint: "所有模型默认都出现在选择器里;取消勾选不想用的即可。",
869
+ selectedCount: "已选 {n} / {total}",
870
+ selectAll: "全选",
871
+ free: "免费",
872
+ saveModels: "保存模型选择",
873
+ saving: "保存中…",
874
+ saved: "已保存",
875
+ signIn: "使用华为云账号登录",
876
+ signingIn: "登录中…(请在浏览器完成授权)",
877
+ openManually: "若未自动打开,请手动访问:",
878
+ manualToken: "手动粘贴 token(降级)",
879
+ loginFailed: "登录失败,请重试",
880
+ modelsLoading: "模型勾选区加载中…(若长期不出现,请确认已登录且 DSH 已完全重启)",
881
+ usageTitle: "本机用量",
882
+ usageToday: "今日",
883
+ usageRequests: "{n} 次请求",
884
+ usageTokens: "输入 {prompt} · 输出 {completion}",
885
+ usageAllTime: "累计({days} 天)",
886
+ usageByModel: "今日按模型",
887
+ usageSlots: "会话槽位",
888
+ usageStateOk: "可用",
889
+ usageStateCapped: "撞上限,优先避开",
890
+ usageStateCooling: "冷却中",
891
+ usageStateDisabled: "已停用",
892
+ usageNoQuota: "这里是本机经插件发出的请求统计(不等于账号总额度);官方用量明细见",
893
+ usageEmpty: "还没有记录:发一条消息就会开始累计。",
894
+ creditsTitle: "积分",
895
+ creditsRemaining: "剩余 {remain} / {total}",
896
+ creditsUsed: "已用 {used}",
897
+ creditsExpiring: "其中 {expiring} 将在 {date} 重置时作废",
898
+ creditsReset: "额度重置 {date}",
899
+ creditsTokensToday: "今日 token {used} / {limit}",
900
+ creditsTokensBalance: "余额 {balance}",
901
+ creditsUnavailable: "积分不可用:{message}",
902
+ creditsDock: "积分 {remain}",
903
+ creditsDockTitle: "CodeArts 剩余积分 {remain} / {total}"
904
+ };
905
+ const en = {
906
+ tabLabel: "CodeArts",
907
+ cardTitle: "DSH CodeArts Connect",
908
+ statusSignedIn: "Signed in",
909
+ statusSignedOut: "Not signed in",
910
+ statusExpired: "Credential expired",
911
+ descSignedIn: "Credential is ready. Checked models show up in the model picker.",
912
+ descSignedOut: "Sign in with your Huawei Cloud account, or paste a CodeArts cloud_dragon_token.",
913
+ storedMeta: "{label} · stored {time}",
914
+ storedMetaNoLabel: "stored {time}",
915
+ refresh: "Refresh",
916
+ clearToken: "Clear credential",
917
+ tokenLabel: "cloud_dragon_token",
918
+ tokenPlaceholder: "Paste the token taken from the CodeArts web/desktop client……",
919
+ labelLabel: "Label (optional)",
920
+ labelPlaceholder: "e.g. account nickname",
921
+ saveToken: "Save token",
922
+ expiredHint: "Your credential has expired. Sign in again to continue; your model selection is kept.",
923
+ accountsTitle: "Accounts",
924
+ accountsShow: "Show accounts",
925
+ accountsHide: "Hide accounts",
926
+ accountRemove: "Remove",
927
+ addAccount: "Add account",
928
+ accountsRotateHint: "Multiple accounts stored: requests rotate automatically, so a busy account hands over to the next one instead of making you wait.",
929
+ accountNeedsSignIn: "Needs sign-in",
930
+ accountNoKey: "No AK/SK",
931
+ accountStored: "stored {time}",
932
+ accountExpires: "expires {time}",
933
+ accountExpired: "expired {time}",
934
+ modelsTitle: "Models",
935
+ optionalModelsHint: "Only checked models appear in the model picker.",
936
+ optionalModelsAllHint: "All models show in the picker by default; uncheck the ones you don’t want.",
937
+ selectedCount: "{n} of {total} selected",
938
+ selectAll: "Select all",
939
+ free: "Free",
940
+ saveModels: "Save selection",
941
+ saving: "Saving…",
942
+ saved: "Saved",
943
+ signIn: "Sign in with Huawei Cloud",
944
+ signingIn: "Signing in… (finish authorization in your browser)",
945
+ openManually: "If it did not open automatically, visit:",
946
+ manualToken: "Paste token manually (fallback)",
947
+ loginFailed: "Sign-in failed, please retry",
948
+ modelsLoading: "Loading model selection… (if it never appears, make sure you are signed in and DSH was fully restarted)",
949
+ usageTitle: "Local usage",
950
+ usageToday: "Today",
951
+ usageRequests: "{n} request(s)",
952
+ usageTokens: "in {prompt} · out {completion}",
953
+ usageAllTime: "All time ({days} days)",
954
+ usageByModel: "Today by model",
955
+ usageSlots: "Session slots",
956
+ usageStateOk: "Ready",
957
+ usageStateCapped: "Cap hit, avoiding",
958
+ usageStateCooling: "Cooling down",
959
+ usageStateDisabled: "Disabled",
960
+ usageNoQuota: "Counts the requests this machine sent through the plugin (not the account balance). Official usage:",
961
+ usageEmpty: "Nothing recorded yet: send a message to start counting.",
962
+ creditsTitle: "Credits",
963
+ creditsRemaining: "{remain} of {total} left",
964
+ creditsUsed: "{used} used",
965
+ creditsExpiring: "{expiring} of them expire at the next reset on {date}",
966
+ creditsReset: "Quota resets {date}",
967
+ creditsTokensToday: "Today {used} / {limit} tokens",
968
+ creditsTokensBalance: "{balance} left",
969
+ creditsUnavailable: "Credits unavailable: {message}",
970
+ creditsDock: "Credits {remain}",
971
+ creditsDockTitle: "CodeArts credits left {remain} / {total}"
972
+ };
973
+ //#endregion
974
+ //#region src/client/index.tsx
975
+ const name = "dsh-codearts-client";
976
+ const inject = ["slots", "locale"];
977
+ function apply(ctx) {
978
+ try {
979
+ const namespace = "settings.codearts";
980
+ ctx.effect(() => ctx.locale.register(namespace, {
981
+ zh,
982
+ en
983
+ }), "dsh-codearts: settings copy");
984
+ const t = ctx.locale.bind(namespace);
985
+ ctx.slots.inject("plugins.bundle.config", () => ctx.slots.register({
986
+ name: "plugins.bundle.config",
987
+ key: "dsh-codearts",
988
+ locale: namespace
989
+ }, () => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CodeArtsPluginCard, { t })));
990
+ ctx.slots.inject("conversation.composer.dock", () => ctx.slots.register({
991
+ name: "conversation.composer.dock",
992
+ id: "codearts-credits",
993
+ order: 20,
994
+ locale: namespace,
995
+ inject: () => ({ t })
996
+ }, CodeArtsCreditDock));
997
+ } catch (error) {
998
+ console.error("[dsh-codearts] client card failed to load (host provider unaffected):", error);
999
+ }
1000
+ }
1001
+ //#endregion
1002
+ exports.apply = apply;
1003
+ exports.inject = inject;
1004
+ exports.name = name;
1005
+
1006
+ return module.exports;
1007
+ }
1008
+ });