dsh-connect-trae 1.4.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +45 -5
- package/README.en.md +15 -9
- package/README.md +15 -9
- package/lib/client.js +268 -76
- package/lib/index.d.ts +345 -51
- package/lib/index.js +781 -234
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -8,17 +8,36 @@ window.__ModuleLoader__.load({
|
|
|
8
8
|
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
9
9
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
10
10
|
//#region src/status-paths.ts
|
|
11
|
-
/**
|
|
12
|
-
* Node-free constants and types shared by the Host and browser halves.
|
|
13
|
-
* Mirrors the `dsh-workbuddy-connect` status-route pattern so the plugin card
|
|
14
|
-
* stays consistent with that project's external presentation.
|
|
15
|
-
*/
|
|
16
11
|
/** Plugin-owned usage endpoint consumed by its browser half. */
|
|
17
12
|
const TRAE_USAGE_PATH = "/plugins/dsh-connect-trae/usage";
|
|
18
13
|
/** Plugin-owned live model refresh endpoint. */
|
|
19
14
|
const TRAE_MODELS_REFRESH_PATH = "/plugins/dsh-connect-trae/models/refresh";
|
|
20
15
|
/** Plugin-owned local account rescan endpoint. */
|
|
21
16
|
const TRAE_ACCOUNTS_REFRESH_PATH = "/plugins/dsh-connect-trae/accounts/refresh";
|
|
17
|
+
/** Query parameter naming the region a card request addresses. */
|
|
18
|
+
const TRAE_REGION_PARAM = "region";
|
|
19
|
+
/** Every region, in card tab order. */
|
|
20
|
+
const TRAE_REGIONS = ["cn", "ai"];
|
|
21
|
+
/**
|
|
22
|
+
* Address one region's status route. The two regions are separate provider
|
|
23
|
+
* stacks; every card request carries the region whose tab the user is on.
|
|
24
|
+
*/
|
|
25
|
+
function withTraeRegion(path, region) {
|
|
26
|
+
return `${path}?${TRAE_REGION_PARAM}=${region}`;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Build the next `regions` settings value for the card's save. The write
|
|
30
|
+
* targets ONLY the signed-in account's region slot; every other region's slot
|
|
31
|
+
* is carried over untouched, so switching accounts never clobbers the other
|
|
32
|
+
* region's picks. Tolerates any stored shape (absent, non-object) by starting
|
|
33
|
+
* from an empty document.
|
|
34
|
+
*/
|
|
35
|
+
function nextRegionSlots(regions, region, slot) {
|
|
36
|
+
return {
|
|
37
|
+
...typeof regions === "object" && regions !== null && !Array.isArray(regions) ? regions : {},
|
|
38
|
+
[region]: slot
|
|
39
|
+
};
|
|
40
|
+
}
|
|
22
41
|
//#endregion
|
|
23
42
|
//#region src/client/icon.ts
|
|
24
43
|
/**
|
|
@@ -57,6 +76,13 @@ window.__ModuleLoader__.load({
|
|
|
57
76
|
.dsm-btn-primary{background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-3)}
|
|
58
77
|
.dsm-btn-primary:hover:not(:disabled){opacity:.9}
|
|
59
78
|
.dsm-trae-usage{display:flex;flex-direction:column;gap:16px;margin:0;padding:16px 0 4px}
|
|
79
|
+
.dsm-trae-tabs{display:flex;gap:6px;padding:4px;border:1px solid var(--dsw-alias-border-l2,#3a3d45);border-radius:10px;background:var(--dsw-alias-bg-layer-3,#2a2c33)}
|
|
80
|
+
.dsm-trae-tab{appearance:none;font:inherit;cursor:pointer;flex:1;border:0;border-radius:7px;padding:7px 10px;color:var(--dsw-alias-label-tertiary,#999);font-size:13px;font-weight:500;line-height:18px;background:transparent;transition:color .15s,background .15s;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
|
81
|
+
.dsm-trae-tab:hover:not(:disabled):not(.dsm-trae-tab-active){color:var(--dsw-alias-label-primary,#e6e6e6)}
|
|
82
|
+
.dsm-trae-tab:focus-visible{outline:2px solid var(--dsw-alias-brand-primary,#5686fe);outline-offset:1px}
|
|
83
|
+
.dsm-trae-tab-active{color:var(--dsw-alias-label-primary,#e6e6e6);background:var(--dsw-alias-bg-layer-2,#232529);box-shadow:inset 0 0 0 1px var(--dsw-alias-border-l2,#3a3d45)}
|
|
84
|
+
.dsm-trae-tab-dot{display:inline-block;width:7px;height:7px;border-radius:50%;margin-right:6px;vertical-align:baseline}
|
|
85
|
+
.dsm-trae-tab-hint{margin:0;color:var(--dsw-alias-label-tertiary,#999);font-size:12px;line-height:18px}
|
|
60
86
|
.dsm-trae-usage-account{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:12px 14px;border:1px solid var(--dsw-alias-border-l2,#3a3d45);border-radius:14px;background:var(--dsw-alias-bg-layer-2,#24262c)}
|
|
61
87
|
.dsm-trae-usage-account-copy{display:flex;flex-direction:column;gap:3px;min-width:0}
|
|
62
88
|
.dsm-trae-usage-expiry{padding-left:19px;color:var(--dsw-alias-label-tertiary,#9aa0a8);font-size:12px;line-height:18px}
|
|
@@ -133,6 +159,11 @@ window.__ModuleLoader__.load({
|
|
|
133
159
|
*/
|
|
134
160
|
const POLL_INTERVAL_MS = 6e4;
|
|
135
161
|
const TRAE_GITHUB_URL = "https://github.com/dingminhua/dsh-connect-trae";
|
|
162
|
+
/** Read the per-region account selections out of the settings snapshot. */
|
|
163
|
+
function configuredAccountsOf(configured) {
|
|
164
|
+
const accounts = configured?.accounts;
|
|
165
|
+
return typeof accounts === "object" && accounts !== null ? accounts : {};
|
|
166
|
+
}
|
|
136
167
|
/** Inject the shared card CSS once. */
|
|
137
168
|
if (typeof document !== "undefined") {
|
|
138
169
|
const cssId = "dsh-connect-trae/client.css";
|
|
@@ -172,16 +203,24 @@ window.__ModuleLoader__.load({
|
|
|
172
203
|
function TraeUsageCard({ t, settingsScope }) {
|
|
173
204
|
if (t === void 0) throw new Error("Trae usage card requires its translation function");
|
|
174
205
|
const [open, setOpen] = (0, react.useState)(false);
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
206
|
+
/** The region whose tab is on screen; each tab is its own provider stack. */
|
|
207
|
+
const [activeRegion, setActiveRegion] = (0, react.useState)("cn");
|
|
208
|
+
/** Last-known usage per region, so tab dots survive tab switches. */
|
|
209
|
+
const [statusByRegion, setStatusByRegion] = (0, react.useState)({
|
|
210
|
+
cn: {
|
|
211
|
+
status: "signed-out",
|
|
212
|
+
accounts: []
|
|
213
|
+
},
|
|
214
|
+
ai: {
|
|
215
|
+
status: "signed-out",
|
|
216
|
+
accounts: []
|
|
217
|
+
}
|
|
178
218
|
});
|
|
179
219
|
const [busy, setBusy] = (0, react.useState)(false);
|
|
180
220
|
const [settingsRevision, setSettingsRevision] = (0, react.useState)(0);
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
const [
|
|
184
|
-
const [draftContextBudgets, setDraftContextBudgets] = (0, react.useState)(void 0);
|
|
221
|
+
/** Per-region unsaved model edits; a draft on one tab is never dropped by
|
|
222
|
+
* switching to the other tab, only by that tab's discard/save. */
|
|
223
|
+
const [drafts, setDrafts] = (0, react.useState)({});
|
|
185
224
|
const [saving, setSaving] = (0, react.useState)(false);
|
|
186
225
|
const [switchingAccount, setSwitchingAccount] = (0, react.useState)(false);
|
|
187
226
|
const mounted = (0, react.useRef)(true);
|
|
@@ -194,38 +233,53 @@ window.__ModuleLoader__.load({
|
|
|
194
233
|
(0, react.useEffect)(() => settingsScope?.subscribe(() => {
|
|
195
234
|
setSettingsRevision((value) => value + 1);
|
|
196
235
|
}), [settingsScope]);
|
|
197
|
-
const refreshUsage = (0, react.useCallback)(async (signal) => {
|
|
236
|
+
const refreshUsage = (0, react.useCallback)(async (region, signal) => {
|
|
198
237
|
try {
|
|
199
|
-
const response = await fetch(TRAE_USAGE_PATH, {
|
|
238
|
+
const response = await fetch(withTraeRegion(TRAE_USAGE_PATH, region), {
|
|
200
239
|
headers: { accept: "application/json" },
|
|
201
240
|
credentials: "same-origin",
|
|
202
241
|
...signal === void 0 ? {} : { signal }
|
|
203
242
|
});
|
|
204
243
|
const value = await response.json().catch(() => void 0);
|
|
205
244
|
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
206
|
-
|
|
207
|
-
|
|
245
|
+
const usage = value;
|
|
246
|
+
if (mounted.current && signal?.aborted !== true) setStatusByRegion((prev) => ({
|
|
247
|
+
...prev,
|
|
248
|
+
[region]: usage
|
|
249
|
+
}));
|
|
250
|
+
return usage;
|
|
208
251
|
} catch (error) {
|
|
209
|
-
if (mounted.current && signal?.aborted !== true)
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
252
|
+
if (mounted.current && signal?.aborted !== true) setStatusByRegion((prev) => ({
|
|
253
|
+
...prev,
|
|
254
|
+
[region]: {
|
|
255
|
+
status: "error",
|
|
256
|
+
message: error instanceof Error ? error.message : t("row.requestFailed")
|
|
257
|
+
}
|
|
258
|
+
}));
|
|
213
259
|
return;
|
|
214
260
|
}
|
|
215
261
|
}, [t]);
|
|
216
262
|
(0, react.useEffect)(() => {
|
|
217
263
|
if (!open) return;
|
|
218
264
|
const controller = new AbortController();
|
|
219
|
-
refreshUsage(controller.signal);
|
|
265
|
+
refreshUsage(activeRegion, controller.signal);
|
|
220
266
|
return () => {
|
|
221
267
|
controller.abort();
|
|
222
268
|
};
|
|
223
|
-
}, [
|
|
269
|
+
}, [
|
|
270
|
+
open,
|
|
271
|
+
activeRegion,
|
|
272
|
+
refreshUsage
|
|
273
|
+
]);
|
|
274
|
+
const status = statusByRegion[activeRegion] ?? {
|
|
275
|
+
status: "signed-out",
|
|
276
|
+
accounts: []
|
|
277
|
+
};
|
|
224
278
|
(0, react.useEffect)(() => {
|
|
225
279
|
if (!open || status.status !== "signed-in") return;
|
|
226
280
|
const controller = new AbortController();
|
|
227
281
|
const timer = window.setInterval(() => {
|
|
228
|
-
refreshUsage(controller.signal);
|
|
282
|
+
refreshUsage(activeRegion, controller.signal);
|
|
229
283
|
}, POLL_INTERVAL_MS);
|
|
230
284
|
return () => {
|
|
231
285
|
window.clearInterval(timer);
|
|
@@ -233,13 +287,14 @@ window.__ModuleLoader__.load({
|
|
|
233
287
|
};
|
|
234
288
|
}, [
|
|
235
289
|
open,
|
|
290
|
+
activeRegion,
|
|
236
291
|
refreshUsage,
|
|
237
292
|
status.status
|
|
238
293
|
]);
|
|
239
294
|
const rescanAccounts = async () => {
|
|
240
295
|
setBusy(true);
|
|
241
296
|
try {
|
|
242
|
-
const response = await fetch(TRAE_ACCOUNTS_REFRESH_PATH, {
|
|
297
|
+
const response = await fetch(withTraeRegion(TRAE_ACCOUNTS_REFRESH_PATH, activeRegion), {
|
|
243
298
|
method: "POST",
|
|
244
299
|
headers: { accept: "application/json" },
|
|
245
300
|
credentials: "same-origin"
|
|
@@ -247,10 +302,12 @@ window.__ModuleLoader__.load({
|
|
|
247
302
|
const body = await response.json();
|
|
248
303
|
if (!response.ok || !Array.isArray(body.accounts)) throw new Error(`HTTP ${response.status}`);
|
|
249
304
|
const selected = body.accounts.find((account) => account.selected)?.id;
|
|
250
|
-
const configured = settingsScope?.getSnapshot().value;
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
305
|
+
const configured = configuredAccountsOf(settingsScope?.getSnapshot().value);
|
|
306
|
+
if (selected !== void 0 && selected !== configured[activeRegion] && settingsScope?.getSnapshot().writable === true) await settingsScope.set("accounts", {
|
|
307
|
+
...configured,
|
|
308
|
+
[activeRegion]: selected
|
|
309
|
+
});
|
|
310
|
+
await refreshUsage(activeRegion);
|
|
254
311
|
} finally {
|
|
255
312
|
if (mounted.current) setBusy(false);
|
|
256
313
|
}
|
|
@@ -259,8 +316,12 @@ window.__ModuleLoader__.load({
|
|
|
259
316
|
if (settingsScope === void 0) return;
|
|
260
317
|
setSwitchingAccount(true);
|
|
261
318
|
try {
|
|
262
|
-
|
|
263
|
-
await
|
|
319
|
+
const configured = configuredAccountsOf(settingsScope.getSnapshot().value);
|
|
320
|
+
await settingsScope.set("accounts", {
|
|
321
|
+
...configured,
|
|
322
|
+
[activeRegion]: accountId
|
|
323
|
+
});
|
|
324
|
+
await refreshUsage(activeRegion);
|
|
264
325
|
} finally {
|
|
265
326
|
if (mounted.current) setSwitchingAccount(false);
|
|
266
327
|
}
|
|
@@ -268,7 +329,7 @@ window.__ModuleLoader__.load({
|
|
|
268
329
|
const refreshModels = async () => {
|
|
269
330
|
setBusy(true);
|
|
270
331
|
try {
|
|
271
|
-
const response = await fetch(TRAE_MODELS_REFRESH_PATH, {
|
|
332
|
+
const response = await fetch(withTraeRegion(TRAE_MODELS_REFRESH_PATH, activeRegion), {
|
|
272
333
|
method: "POST",
|
|
273
334
|
headers: { accept: "application/json" },
|
|
274
335
|
credentials: "same-origin"
|
|
@@ -284,69 +345,114 @@ window.__ModuleLoader__.load({
|
|
|
284
345
|
const budget = activeContextBudgets[id];
|
|
285
346
|
if (typeof budget === "number") stillBudgets[id] = budget;
|
|
286
347
|
}
|
|
287
|
-
|
|
288
|
-
...
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
348
|
+
setDrafts((prev) => ({
|
|
349
|
+
...prev,
|
|
350
|
+
[activeRegion]: {
|
|
351
|
+
models: fresh.map((model) => ({
|
|
352
|
+
...model,
|
|
353
|
+
input: ["text"]
|
|
354
|
+
})),
|
|
355
|
+
enabledIds: new Set(stillEnabled),
|
|
356
|
+
imageIds: new Set(stillImages),
|
|
357
|
+
contextBudgets: stillBudgets
|
|
358
|
+
}
|
|
359
|
+
}));
|
|
294
360
|
} catch (error) {
|
|
295
|
-
if (mounted.current)
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
361
|
+
if (mounted.current) setStatusByRegion((prev) => ({
|
|
362
|
+
...prev,
|
|
363
|
+
[activeRegion]: {
|
|
364
|
+
status: "error",
|
|
365
|
+
message: error instanceof Error ? error.message : t("row.requestFailed")
|
|
366
|
+
}
|
|
367
|
+
}));
|
|
299
368
|
} finally {
|
|
300
369
|
if (mounted.current) setBusy(false);
|
|
301
370
|
}
|
|
302
371
|
};
|
|
303
372
|
const settingsValue = settingsScope?.getSnapshot().value;
|
|
304
|
-
const
|
|
305
|
-
const
|
|
306
|
-
const
|
|
373
|
+
const region = activeRegion;
|
|
374
|
+
const configuredRegions = typeof settingsValue === "object" && settingsValue !== null && typeof settingsValue.regions === "object" && settingsValue.regions !== null ? settingsValue.regions : {};
|
|
375
|
+
const regionSlot = configuredRegions[region];
|
|
376
|
+
const legacySlot = region === "cn" && regionSlot === void 0;
|
|
377
|
+
const slotContextBudgets = typeof regionSlot?.contextBudgets === "object" && regionSlot.contextBudgets !== null ? regionSlot.contextBudgets : void 0;
|
|
378
|
+
const legacyContextBudgets = legacySlot && typeof settingsValue === "object" && settingsValue !== null && typeof settingsValue.contextBudgets === "object" && settingsValue.contextBudgets !== null ? settingsValue.contextBudgets : void 0;
|
|
379
|
+
const savedContextBudgets = slotContextBudgets ?? legacyContextBudgets ?? {};
|
|
380
|
+
const slotImageIds = Array.isArray(regionSlot?.imageModelIds) ? regionSlot.imageModelIds.filter((id) => typeof id === "string") : void 0;
|
|
381
|
+
const legacyImageIds = legacySlot && typeof settingsValue === "object" && settingsValue !== null && Array.isArray(settingsValue.imageModelIds) ? settingsValue.imageModelIds.filter((id) => typeof id === "string") : [];
|
|
382
|
+
const savedImageIds = new Set(slotImageIds ?? legacyImageIds);
|
|
383
|
+
const draft = drafts[activeRegion];
|
|
384
|
+
const visibleModels = draft?.models ?? (status.status === "signed-in" ? status.models : []);
|
|
307
385
|
const savedEnabledIds = status.status === "signed-in" ? new Set(status.enabledModelIds) : /* @__PURE__ */ new Set();
|
|
308
|
-
const activeEnabledIds =
|
|
309
|
-
const activeImageIds =
|
|
310
|
-
const activeContextBudgets =
|
|
311
|
-
const dirty =
|
|
386
|
+
const activeEnabledIds = draft?.enabledIds ?? savedEnabledIds;
|
|
387
|
+
const activeImageIds = draft?.imageIds ?? savedImageIds;
|
|
388
|
+
const activeContextBudgets = draft?.contextBudgets ?? savedContextBudgets;
|
|
389
|
+
const dirty = draft !== void 0;
|
|
390
|
+
/** Apply an edit to the ACTIVE tab's draft, seeding it from the current view. */
|
|
391
|
+
const editDraft = (edit) => {
|
|
392
|
+
setDrafts((prev) => ({
|
|
393
|
+
...prev,
|
|
394
|
+
[activeRegion]: edit(prev[activeRegion] ?? {
|
|
395
|
+
models: [...visibleModels],
|
|
396
|
+
enabledIds: new Set(activeEnabledIds),
|
|
397
|
+
imageIds: new Set(activeImageIds),
|
|
398
|
+
contextBudgets: { ...activeContextBudgets }
|
|
399
|
+
})
|
|
400
|
+
}));
|
|
401
|
+
};
|
|
312
402
|
const toggleModel = (modelId) => {
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
403
|
+
editDraft((current) => {
|
|
404
|
+
const next = new Set(current.enabledIds);
|
|
405
|
+
if (!next.delete(modelId)) next.add(modelId);
|
|
406
|
+
return {
|
|
407
|
+
...current,
|
|
408
|
+
enabledIds: next
|
|
409
|
+
};
|
|
410
|
+
});
|
|
317
411
|
};
|
|
318
412
|
const toggleImage = (modelId) => {
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
413
|
+
editDraft((current) => {
|
|
414
|
+
const next = new Set(current.imageIds);
|
|
415
|
+
if (!next.delete(modelId)) next.add(modelId);
|
|
416
|
+
return {
|
|
417
|
+
...current,
|
|
418
|
+
imageIds: next
|
|
419
|
+
};
|
|
420
|
+
});
|
|
323
421
|
};
|
|
324
422
|
const setContextBudget = (modelId, budget) => {
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
423
|
+
editDraft((current) => {
|
|
424
|
+
const next = { ...current.contextBudgets };
|
|
425
|
+
if (budget === void 0) delete next[modelId];
|
|
426
|
+
else next[modelId] = budget;
|
|
427
|
+
return {
|
|
428
|
+
...current,
|
|
429
|
+
contextBudgets: next
|
|
430
|
+
};
|
|
431
|
+
});
|
|
330
432
|
};
|
|
331
433
|
const discardModels = () => {
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
434
|
+
setDrafts((prev) => {
|
|
435
|
+
const next = { ...prev };
|
|
436
|
+
delete next[activeRegion];
|
|
437
|
+
return next;
|
|
438
|
+
});
|
|
336
439
|
};
|
|
337
440
|
const saveModels = async () => {
|
|
338
441
|
if (settingsScope === void 0) return;
|
|
339
442
|
setSaving(true);
|
|
340
443
|
try {
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
444
|
+
if (status.status !== "signed-in") return;
|
|
445
|
+
await settingsScope.set("regions", nextRegionSlots(configuredRegions, activeRegion, {
|
|
446
|
+
lastCatalog: visibleModels.map((model) => ({
|
|
447
|
+
...model,
|
|
448
|
+
input: ["text"]
|
|
449
|
+
})),
|
|
450
|
+
enabledModelIds: [...activeEnabledIds],
|
|
451
|
+
imageModelIds: [...activeImageIds].filter((id) => activeEnabledIds.has(id)),
|
|
452
|
+
contextBudgets: activeContextBudgets
|
|
453
|
+
}));
|
|
348
454
|
discardModels();
|
|
349
|
-
await refreshUsage();
|
|
455
|
+
await refreshUsage(activeRegion);
|
|
350
456
|
} finally {
|
|
351
457
|
if (mounted.current) setSaving(false);
|
|
352
458
|
}
|
|
@@ -391,6 +497,32 @@ window.__ModuleLoader__.load({
|
|
|
391
497
|
children: open ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
392
498
|
className: "dsm-trae-usage",
|
|
393
499
|
children: [
|
|
500
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
501
|
+
className: "dsm-trae-tabs",
|
|
502
|
+
role: "tablist",
|
|
503
|
+
"aria-label": title,
|
|
504
|
+
children: TRAE_REGIONS.map((item) => {
|
|
505
|
+
const regionStatus = statusByRegion[item];
|
|
506
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
507
|
+
type: "button",
|
|
508
|
+
role: "tab",
|
|
509
|
+
"aria-selected": item === activeRegion,
|
|
510
|
+
className: `dsm-trae-tab${item === activeRegion ? " dsm-trae-tab-active" : ""}`,
|
|
511
|
+
onClick: () => {
|
|
512
|
+
setActiveRegion(item);
|
|
513
|
+
},
|
|
514
|
+
children: [regionStatus === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
515
|
+
"aria-hidden": "true",
|
|
516
|
+
className: "dsm-trae-tab-dot",
|
|
517
|
+
style: dotStyle(regionStatus.status)
|
|
518
|
+
}), item === "cn" ? t("row.tabCn") : t("row.tabAi")]
|
|
519
|
+
}, item);
|
|
520
|
+
})
|
|
521
|
+
}),
|
|
522
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
523
|
+
className: "dsm-trae-tab-hint",
|
|
524
|
+
children: t("row.tabHint")
|
|
525
|
+
}),
|
|
394
526
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
395
527
|
className: "dsm-trae-usage-account",
|
|
396
528
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -434,6 +566,8 @@ window.__ModuleLoader__.load({
|
|
|
434
566
|
children: [
|
|
435
567
|
account.accountName,
|
|
436
568
|
" · ",
|
|
569
|
+
account.region === "ai" ? t("row.regionAi") : t("row.regionCn"),
|
|
570
|
+
" · ",
|
|
437
571
|
account.edition
|
|
438
572
|
]
|
|
439
573
|
}, account.id))
|
|
@@ -441,6 +575,44 @@ window.__ModuleLoader__.load({
|
|
|
441
575
|
})
|
|
442
576
|
}) : null,
|
|
443
577
|
status.status === "signed-in" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
578
|
+
status.payStatus === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
579
|
+
className: "dsm-trae-usage-list",
|
|
580
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
581
|
+
className: "dsm-trae-usage-stats dsm-trae-usage-stats-two",
|
|
582
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
583
|
+
className: "dsm-trae-usage-stat dsm-trae-usage-stat-general",
|
|
584
|
+
children: [
|
|
585
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
586
|
+
className: "dsm-trae-usage-stat-head",
|
|
587
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
588
|
+
className: "dsm-trae-usage-stat-label",
|
|
589
|
+
children: t("row.subscriptionLabel")
|
|
590
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
591
|
+
className: `dsm-trae-usage-stat-badge ${status.payStatus.hasPackage ? "dsm-trae-usage-stat-badge-on" : "dsm-trae-usage-stat-badge-off"}`,
|
|
592
|
+
children: t(status.payStatus.hasPackage ? "row.subscribed" : "row.noPackage")
|
|
593
|
+
})]
|
|
594
|
+
}),
|
|
595
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
596
|
+
className: "dsm-trae-usage-stat-value dsm-trae-usage-stat-value-general",
|
|
597
|
+
children: status.payStatus.inTrial && status.payStatus.trialEndTimeMs > 0 ? t("row.trialUntil", { date: formatDateTime(status.payStatus.trialEndTimeMs) }) : t(status.payStatus.hasPackage ? "row.subscribed" : "row.noPackage")
|
|
598
|
+
}),
|
|
599
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
600
|
+
className: "dsm-trae-usage-stat-hint",
|
|
601
|
+
children: status.payStatus.enableSoloLite || status.payStatus.enableSoloCoder || status.payStatus.enableSoloBuilder || status.payStatus.enableSoloWeb ? [
|
|
602
|
+
status.payStatus.enableSoloLite ? "SOLO Lite" : "",
|
|
603
|
+
status.payStatus.enableSoloCoder ? "SOLO Coder" : "",
|
|
604
|
+
status.payStatus.enableSoloBuilder ? "SOLO Builder" : "",
|
|
605
|
+
status.payStatus.enableSoloWeb ? "SOLO Web" : ""
|
|
606
|
+
].filter(Boolean).join(" · ") : status.payStatus.isDollarUsageBilling ? "dollar usage billing" : ""
|
|
607
|
+
})
|
|
608
|
+
]
|
|
609
|
+
})
|
|
610
|
+
})
|
|
611
|
+
}),
|
|
612
|
+
status.payStatusError === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
613
|
+
className: "dsm-trae-usage-error",
|
|
614
|
+
children: t("row.payStatusError", { message: status.payStatusError })
|
|
615
|
+
}),
|
|
444
616
|
status.credits === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
445
617
|
className: "dsm-trae-usage-list",
|
|
446
618
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -672,9 +844,12 @@ window.__ModuleLoader__.load({
|
|
|
672
844
|
*/
|
|
673
845
|
const en = {
|
|
674
846
|
"row.title": "Trae credits & models (dsh-connect-trae)",
|
|
675
|
-
"row.desc": "Use
|
|
847
|
+
"row.desc": "Use Trae models in DSH and see your remaining credits; the domestic and international sides are two independent providers, each with its own account — use both at the same time.",
|
|
676
848
|
"row.expand": "Expand",
|
|
677
849
|
"row.collapse": "Collapse",
|
|
850
|
+
"row.tabCn": "Domestic",
|
|
851
|
+
"row.tabAi": "Global",
|
|
852
|
+
"row.tabHint": "Each tab is a separate provider (trae / trae-global) with its own account, usage, and models. Both sides are live at once: different sessions can pick from either side, and changes on one tab never touch the other.",
|
|
678
853
|
"row.signedOut": "Not signed in",
|
|
679
854
|
"row.signedOutHint": "Sign in once in the Trae desktop app; this plugin follows that sign-in automatically.",
|
|
680
855
|
"row.searchedTitle": "Paths checked",
|
|
@@ -698,6 +873,13 @@ window.__ModuleLoader__.load({
|
|
|
698
873
|
"row.creditsConsumedLabel": "Consumed",
|
|
699
874
|
"row.creditsTotalLabel": "Total",
|
|
700
875
|
"row.creditsError": "Usage unavailable: {message}",
|
|
876
|
+
"row.regionCn": "CN",
|
|
877
|
+
"row.regionAi": "International",
|
|
878
|
+
"row.subscriptionLabel": "Subscription",
|
|
879
|
+
"row.subscribed": "Active package",
|
|
880
|
+
"row.noPackage": "No active package",
|
|
881
|
+
"row.trialUntil": "Trial until {date}",
|
|
882
|
+
"row.payStatusError": "Subscription status unavailable: {message}",
|
|
701
883
|
"row.refresh": "Refresh",
|
|
702
884
|
"row.refreshTokens": "Refresh accounts & tokens",
|
|
703
885
|
"row.refreshCredits": "Refresh usage",
|
|
@@ -727,9 +909,12 @@ window.__ModuleLoader__.load({
|
|
|
727
909
|
};
|
|
728
910
|
const zh = {
|
|
729
911
|
"row.title": "接入使用Trae积分与模型(dsh-connect-trae)",
|
|
730
|
-
"row.desc": "在 DSH
|
|
912
|
+
"row.desc": "在 DSH 中使用 Trae 模型并随时查看剩余积分;国内版与国际版是两个独立供应商,各有自己的账号,可同时使用。",
|
|
731
913
|
"row.expand": "展开",
|
|
732
914
|
"row.collapse": "收起",
|
|
915
|
+
"row.tabCn": "国内版",
|
|
916
|
+
"row.tabAi": "国际版",
|
|
917
|
+
"row.tabHint": "每个 tab 是一个独立供应商(trae / trae-global),各有自己的账号、用量与模型。两边同时生效:不同会话可各选一边,一侧的改动不影响另一侧。",
|
|
733
918
|
"row.signedOut": "未登录",
|
|
734
919
|
"row.signedOutHint": "在 Trae 桌面 App 里登录一次即可,插件会自动跟随当前登录的账号。",
|
|
735
920
|
"row.searchedTitle": "已检查的路径",
|
|
@@ -753,6 +938,13 @@ window.__ModuleLoader__.load({
|
|
|
753
938
|
"row.creditsConsumedLabel": "消耗",
|
|
754
939
|
"row.creditsTotalLabel": "合计",
|
|
755
940
|
"row.creditsError": "用量查询失败:{message}",
|
|
941
|
+
"row.regionCn": "国内版",
|
|
942
|
+
"row.regionAi": "国际版",
|
|
943
|
+
"row.subscriptionLabel": "订阅状态",
|
|
944
|
+
"row.subscribed": "已有有效套餐",
|
|
945
|
+
"row.noPackage": "暂无有效套餐",
|
|
946
|
+
"row.trialUntil": "试用至 {date}",
|
|
947
|
+
"row.payStatusError": "订阅状态查询失败:{message}",
|
|
756
948
|
"row.refresh": "刷新",
|
|
757
949
|
"row.refreshTokens": "刷新账号与 Token",
|
|
758
950
|
"row.refreshCredits": "刷新用量",
|