dsh-connect-trae 4.6.9 → 4.6.10
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 +63 -0
- package/lib/client.js +110 -53
- package/lib/index.d.ts +7 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,68 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 4.6.10 (2026-10-30)
|
|
4
|
+
|
|
5
|
+
> **到期提示加了一档「3 天内」。** 一个两天后过期的套餐,之前显示的是「7 天内过期」
|
|
6
|
+
> ——话没错,但粗了三倍,而这句通知唯一的职责就是告诉你**还剩多久**。上游一直有
|
|
7
|
+
> `within3d` 这个桶,插件却没用它。
|
|
8
|
+
|
|
9
|
+
### 变更
|
|
10
|
+
|
|
11
|
+
- **到期提示新增「3 天内」一档**(issue #71 的第三条建议)。
|
|
12
|
+
- **动机**:档位只有 24 小时和 7 天两档,而上游的桶是三个。两天后到期的积分
|
|
13
|
+
落进 7 天桶,于是被报成「7 天内过期」——真话,但粗了三倍。要么现在用掉这个
|
|
14
|
+
桶,要么永远让「还剩多久」这件事只能精确到 24 小时或 7 天这种量级。
|
|
15
|
+
- **口径:累积,每档报自己那个桶。** 上游的三个桶是**嵌套且累积**的
|
|
16
|
+
(`within24h` ⊆ `within3d` ⊆ `within7d`),所以每一档报的
|
|
17
|
+
「N 天内过期的总额」单独看都是真的;而且**同一时刻只显示一档**,读者永远
|
|
18
|
+
不需要把两个数字相加。
|
|
19
|
+
- **为什么不报排他金额**:曾考虑让 3 天档只报「1~3 天那一段」的金额,好处是
|
|
20
|
+
各档互不重叠、可相加。但那会与现有两档的语义**不一致**(7 天档报的一直是
|
|
21
|
+
`within7d.total` 这种累积额),而且平白多出一个数据字段和一处「档位顺序 +
|
|
22
|
+
档位口径」要同时维护的地方。累积口径下每句话单独成立,更简单也更不容易错。
|
|
23
|
+
- **数据层零改动**:`within3d` 桶本来就在上游摘要里算好了,本次只是把它接进
|
|
24
|
+
阶梯。`src/web-status.ts` 的取数逻辑一行未动。
|
|
25
|
+
- **文案**:新增 `row.expiryWarningDays`(中英各一条)。
|
|
26
|
+
「24 小时内」「3 天内」「7 天内」三档读起来是同一套量词,不引入新的说法。
|
|
27
|
+
- **语气**:新增 `dsm-trae-expiry-days`,视觉上**介于另外两档之间**——保留警示
|
|
28
|
+
边框(三天内到期不该被一眼扫过去),但不要警示底色(三天的量级不是 24 小时
|
|
29
|
+
那种急事)。于是四档从急到缓是:soon(警示底色)→ days(警示边框)→
|
|
30
|
+
week(普通)→ lapsed(更淡)。
|
|
31
|
+
|
|
32
|
+
### 顺带修掉的两处结构性隐患
|
|
33
|
+
|
|
34
|
+
**一、卡片与面板现在共用同一个阶梯**(新增 `src/client/expiry-ladder.ts`)。
|
|
35
|
+
|
|
36
|
+
两处渲染的是**同一批 locale key**(`row.expiryWarning*`、`row.expiryEarliest`)、
|
|
37
|
+
同一份上游桶,却各自写了一套档位判断。这正是 4.6.7 那个 bug 的根源——那张卡上
|
|
38
|
+
写 `2026/10/31 23:59`、面板写 `23:59`,**差了一整天**,而当时没有一个测试
|
|
39
|
+
失败。现在档位由一个模块选出(`expiryNotice`),两处都调用它,并且新增一条
|
|
40
|
+
测试**从源码层面**钉住这件事:两个界面都不得直接读 `expiry.within24h` /
|
|
41
|
+
`within3d` / `within7d` / `expired`,必须走共享阶梯。变异验证:让卡片私自读一个
|
|
42
|
+
桶,该用例立刻红并点名是哪个界面读的哪个桶。
|
|
43
|
+
|
|
44
|
+
**二、卡片的样式表缺一条守卫**。
|
|
45
|
+
|
|
46
|
+
面板侧有「面板渲染的每个 class 都得有规则」的守卫(`composer-styles.spec.tsx`),
|
|
47
|
+
卡片侧**没有**对应的——而卡片渲染的是同一批 `dsm-trae-expiry-*` class,规则却在
|
|
48
|
+
另一个常量 `TRAE_CARD_CSS` 里。实测:删掉卡片的 `dsm-trae-expiry-days` 规则,
|
|
49
|
+
全仓测试依然全绿。现补一条守卫覆盖卡片的四个语气 class 与两条共享规则。
|
|
50
|
+
|
|
51
|
+
### 测试
|
|
52
|
+
|
|
53
|
+
- 新增 **8** 例(1232 总例,较 4.6.9 净增 8):
|
|
54
|
+
- 24 小时 / 3 天 / 7 天三档各自被选中,且报的是**自己那个桶**的金额与份数
|
|
55
|
+
(不是更宽的桶的数字);
|
|
56
|
+
- 3 天档的「最早到期」报的是该档自己的时刻;
|
|
57
|
+
- 卡片与面板共用阶梯的**源码级**守卫;
|
|
58
|
+
- 卡片样式表覆盖四个语气 class 的守卫。
|
|
59
|
+
- **变异验证**(每一项都确认会转红):
|
|
60
|
+
- 删掉 3 天档的分支 → 档位测试红;
|
|
61
|
+
- 让卡片私自读一个桶 → 一致性守卫红并点名;
|
|
62
|
+
- 删掉面板侧的 `dsm-trae-expiry-days` 规则 → 面板样式守卫红;
|
|
63
|
+
- 删掉卡片侧的同一条规则 → 新增的卡片样式守卫红。
|
|
64
|
+
- 全仓 **1232** 例通过(96 文件),双 tsconfig 类型检查通过。
|
|
65
|
+
|
|
3
66
|
## 4.6.9 (2026-10-30)
|
|
4
67
|
|
|
5
68
|
> **三家插件的积分读数现已统一在 `conversation.input.right`(模型选择器左边)。**
|
package/lib/client.js
CHANGED
|
@@ -1196,11 +1196,17 @@ window.__ModuleLoader__.load({
|
|
|
1196
1196
|
.dsm-trae-usage-switch-button:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,rgba(127,127,127,.14))}
|
|
1197
1197
|
.dsm-trae-usage-switch-button:disabled{opacity:.5;cursor:not-allowed}
|
|
1198
1198
|
.dsm-trae-usage-note{margin:8px 0 0;color:var(--dsw-alias-label-tertiary,#999);font-size:11px;line-height:16px}
|
|
1199
|
-
/* Credit-expiry notice, card copy.
|
|
1200
|
-
cannot be mistaken for the
|
|
1201
|
-
an error: the account works fine, the
|
|
1199
|
+
/* Credit-expiry notice, card copy. Four tones by urgency, so the 24-hour case
|
|
1200
|
+
cannot be mistaken for the 3-day one, nor either for the 7-day one, at a
|
|
1201
|
+
glance. Reads as an advisory, not an error: the account works fine, the
|
|
1202
|
+
credit is simply about to lapse.
|
|
1203
|
+
The 3-day tone sits BETWEEN the other two on purpose: it carries the
|
|
1204
|
+
warning border (the reader must not scroll past a 3-day expiry without
|
|
1205
|
+
noticing) but not the warning fill (a 3-day pack is not the emergency a
|
|
1206
|
+
24-hour pack is). */
|
|
1202
1207
|
.dsm-trae-expiry{display:flex;flex-direction:column;gap:2px;margin-top:10px;padding:10px 12px;border:1px solid;border-radius:10px;font-size:12px;line-height:18px}
|
|
1203
1208
|
.dsm-trae-expiry-soon{border-color:var(--dsw-alias-state-warn-secondary,#fbbf24);background:var(--dsw-alias-state-warn-tertiary,#fef3c7);color:var(--dsw-alias-label-primary,#e6e6e6)}
|
|
1209
|
+
.dsm-trae-expiry-days{border-color:var(--dsw-alias-state-warn-secondary,#fbbf24);background:transparent;color:var(--dsw-alias-label-primary,#e6e6e6)}
|
|
1204
1210
|
.dsm-trae-expiry-week{border-color:var(--dsw-alias-border-l2,#3a3d45);background:var(--dsw-alias-bg-layer-3,#2c2f36);color:var(--dsw-alias-label-primary,#e6e6e6)}
|
|
1205
1211
|
.dsm-trae-expiry-lapsed{border-color:var(--dsw-alias-border-l2,#3a3d45);background:var(--dsw-alias-bg-layer-3,#2c2f36);color:var(--dsw-alias-label-tertiary,#999)}
|
|
1206
1212
|
.dsm-trae-expiry-detail{font-size:11px;line-height:16px;opacity:.8}
|
|
@@ -1664,6 +1670,11 @@ window.__ModuleLoader__.load({
|
|
|
1664
1670
|
background:var(--dsw-alias-state-warn-tertiary,#fef3c7);
|
|
1665
1671
|
color:var(--dsw-alias-label-primary,#1f2329);
|
|
1666
1672
|
}
|
|
1673
|
+
.dsm-trae-expiry-days{
|
|
1674
|
+
border-color:var(--dsw-alias-state-warn-secondary,#fbbf24);
|
|
1675
|
+
background:transparent;
|
|
1676
|
+
color:var(--dsw-alias-label-primary,#1f2329);
|
|
1677
|
+
}
|
|
1667
1678
|
.dsm-trae-expiry-week{
|
|
1668
1679
|
border-color:var(--dsw-alias-border-l2,rgba(127,127,127,.36));
|
|
1669
1680
|
background:transparent;
|
|
@@ -3502,6 +3513,74 @@ window.__ModuleLoader__.load({
|
|
|
3502
3513
|
};
|
|
3503
3514
|
}
|
|
3504
3515
|
//#endregion
|
|
3516
|
+
//#region src/client/expiry-ladder.ts
|
|
3517
|
+
/**
|
|
3518
|
+
* Choose the notice's tier and its figures.
|
|
3519
|
+
*
|
|
3520
|
+
* Escalation order matters: a live expiry the user can still act on outranks
|
|
3521
|
+
* a lapsed one they cannot, even when the lapsed amount is larger.
|
|
3522
|
+
*
|
|
3523
|
+
* The 3-day tier exists because the 7-day bucket covers it. Without it, credit
|
|
3524
|
+
* expiring in two days was reported as "within 7 days" — true, but three times
|
|
3525
|
+
* too coarse to plan around, in the one sentence whose job is "how long do I
|
|
3526
|
+
* have left".
|
|
3527
|
+
*/
|
|
3528
|
+
function expiryNotice(expiry) {
|
|
3529
|
+
if (expiry.within24h.packs > 0) return {
|
|
3530
|
+
tier: "soon",
|
|
3531
|
+
total: expiry.within24h.total,
|
|
3532
|
+
packs: expiry.within24h.packs,
|
|
3533
|
+
...expiry.within24h.earliestExpiresAtMs === void 0 ? {} : { soonestExpiresAtMs: expiry.within24h.earliestExpiresAtMs }
|
|
3534
|
+
};
|
|
3535
|
+
if (expiry.within3d.packs > 0) return {
|
|
3536
|
+
tier: "days",
|
|
3537
|
+
total: expiry.within3d.total,
|
|
3538
|
+
packs: expiry.within3d.packs,
|
|
3539
|
+
...expiry.within3d.earliestExpiresAtMs === void 0 ? {} : { soonestExpiresAtMs: expiry.within3d.earliestExpiresAtMs }
|
|
3540
|
+
};
|
|
3541
|
+
if (expiry.within7d.packs > 0) return {
|
|
3542
|
+
tier: "week",
|
|
3543
|
+
total: expiry.within7d.total,
|
|
3544
|
+
packs: expiry.within7d.packs,
|
|
3545
|
+
...expiry.within7d.earliestExpiresAtMs === void 0 ? {} : { soonestExpiresAtMs: expiry.within7d.earliestExpiresAtMs }
|
|
3546
|
+
};
|
|
3547
|
+
if (expiry.expired.packs > 0) return {
|
|
3548
|
+
tier: "lapsed",
|
|
3549
|
+
total: expiry.expired.total,
|
|
3550
|
+
packs: expiry.expired.packs
|
|
3551
|
+
};
|
|
3552
|
+
}
|
|
3553
|
+
/**
|
|
3554
|
+
* The locale key that states this tier's headline.
|
|
3555
|
+
*
|
|
3556
|
+
* Kept beside the tier choice so a new tier cannot be added without its copy.
|
|
3557
|
+
*/
|
|
3558
|
+
function expiryHeadlineKey(tier) {
|
|
3559
|
+
switch (tier) {
|
|
3560
|
+
case "soon": return "row.expiryWarningSoon";
|
|
3561
|
+
case "days": return "row.expiryWarningDays";
|
|
3562
|
+
case "week": return "row.expiryWarningWeek";
|
|
3563
|
+
case "lapsed": return "row.expiryWarningLapsed";
|
|
3564
|
+
}
|
|
3565
|
+
}
|
|
3566
|
+
/**
|
|
3567
|
+
* The CSS class that gives this tier its urgency tone.
|
|
3568
|
+
*
|
|
3569
|
+
* Four tones so the 24-hour case cannot be mistaken for the 3-day one, nor
|
|
3570
|
+
* either for the 7-day one, at a glance. The 3-day tone sits BETWEEN the other
|
|
3571
|
+
* two: it carries the warning border (a 3-day expiry must not be scrolled past
|
|
3572
|
+
* unnoticed) but not the warning fill (a 3-day pack is not the emergency a
|
|
3573
|
+
* 24-hour pack is).
|
|
3574
|
+
*/
|
|
3575
|
+
function expiryToneClass(tier) {
|
|
3576
|
+
switch (tier) {
|
|
3577
|
+
case "soon": return "dsm-trae-expiry-soon";
|
|
3578
|
+
case "days": return "dsm-trae-expiry-days";
|
|
3579
|
+
case "week": return "dsm-trae-expiry-week";
|
|
3580
|
+
case "lapsed": return "dsm-trae-expiry-lapsed";
|
|
3581
|
+
}
|
|
3582
|
+
}
|
|
3583
|
+
//#endregion
|
|
3505
3584
|
//#region src/client/TraeAccountPanel.tsx
|
|
3506
3585
|
/**
|
|
3507
3586
|
* A warning that credit is about to lapse.
|
|
@@ -3516,37 +3595,19 @@ window.__ModuleLoader__.load({
|
|
|
3516
3595
|
* rather than reassuring.
|
|
3517
3596
|
*/
|
|
3518
3597
|
function ExpiryNotice({ expiry, t }) {
|
|
3519
|
-
const
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
packs: String(within24h.packs)
|
|
3527
|
-
});
|
|
3528
|
-
soonest = within24h.earliestExpiresAtMs;
|
|
3529
|
-
tone = "dsm-trae-expiry-soon";
|
|
3530
|
-
} else if (within7d.packs > 0) {
|
|
3531
|
-
message = t("row.expiryWarningWeek", {
|
|
3532
|
-
total: formatNumber(within7d.total),
|
|
3533
|
-
packs: String(within7d.packs)
|
|
3534
|
-
});
|
|
3535
|
-
soonest = within7d.earliestExpiresAtMs;
|
|
3536
|
-
tone = "dsm-trae-expiry-week";
|
|
3537
|
-
} else if (expired.packs > 0) {
|
|
3538
|
-
message = t("row.expiryWarningLapsed", {
|
|
3539
|
-
total: formatNumber(expired.total),
|
|
3540
|
-
packs: String(expired.packs)
|
|
3541
|
-
});
|
|
3542
|
-
tone = "dsm-trae-expiry-lapsed";
|
|
3543
|
-
} else return null;
|
|
3598
|
+
const notice = expiryNotice(expiry);
|
|
3599
|
+
if (notice === void 0) return null;
|
|
3600
|
+
const message = t(expiryHeadlineKey(notice.tier), {
|
|
3601
|
+
total: formatNumber(notice.total),
|
|
3602
|
+
packs: String(notice.packs)
|
|
3603
|
+
});
|
|
3604
|
+
const tone = expiryToneClass(notice.tier);
|
|
3544
3605
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3545
3606
|
className: `dsm-trae-expiry ${tone}`,
|
|
3546
3607
|
role: "status",
|
|
3547
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: message }),
|
|
3608
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: message }), notice.soonestExpiresAtMs === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3548
3609
|
className: "dsm-trae-expiry-detail",
|
|
3549
|
-
children: t("row.expiryEarliest", { time: formatDateTime(
|
|
3610
|
+
children: t("row.expiryEarliest", { time: formatDateTime(notice.soonestExpiresAtMs) })
|
|
3550
3611
|
})]
|
|
3551
3612
|
});
|
|
3552
3613
|
}
|
|
@@ -6369,34 +6430,28 @@ window.__ModuleLoader__.load({
|
|
|
6369
6430
|
function formatCredits(value) {
|
|
6370
6431
|
return value.toLocaleString("en-US", { maximumFractionDigits: 0 });
|
|
6371
6432
|
}
|
|
6372
|
-
/**
|
|
6433
|
+
/**
|
|
6434
|
+
* The soonest expiry the chosen tier names, or undefined when none carries one.
|
|
6435
|
+
*
|
|
6436
|
+
* Read from the tier the shared ladder picked, so the time shown always belongs
|
|
6437
|
+
* to the horizon the headline claims — the two cannot disagree.
|
|
6438
|
+
*/
|
|
6373
6439
|
function soonestExpiryOf(expiry) {
|
|
6374
|
-
return expiry
|
|
6440
|
+
return expiryNotice(expiry)?.soonestExpiresAtMs;
|
|
6375
6441
|
}
|
|
6376
6442
|
/**
|
|
6377
|
-
*
|
|
6443
|
+
* The notice's headline sentence, naming the amount and the pack count.
|
|
6378
6444
|
*
|
|
6379
|
-
*
|
|
6380
|
-
*
|
|
6445
|
+
* The TIER is chosen by the shared ladder (see `./expiry-ladder.ts`), which the
|
|
6446
|
+
* card's account panel uses too — the two surfaces render the same locale
|
|
6447
|
+
* keys, so the choice must not be made twice.
|
|
6381
6448
|
*/
|
|
6382
|
-
function expiryToneOf(expiry) {
|
|
6383
|
-
if (expiry.within24h.packs > 0) return "dsm-trae-expiry-soon";
|
|
6384
|
-
if (expiry.within7d.packs > 0) return "dsm-trae-expiry-week";
|
|
6385
|
-
return "dsm-trae-expiry-lapsed";
|
|
6386
|
-
}
|
|
6387
|
-
/** The notice's headline sentence, naming the amount and the pack count. */
|
|
6388
6449
|
function expiryMessageOf(expiry, t) {
|
|
6389
|
-
|
|
6390
|
-
|
|
6391
|
-
|
|
6392
|
-
|
|
6393
|
-
|
|
6394
|
-
total: formatCredits(expiry.within7d.total),
|
|
6395
|
-
packs: String(expiry.within7d.packs)
|
|
6396
|
-
});
|
|
6397
|
-
return t("row.expiryWarningLapsed", {
|
|
6398
|
-
total: formatCredits(expiry.expired.total),
|
|
6399
|
-
packs: String(expiry.expired.packs)
|
|
6450
|
+
const notice = expiryNotice(expiry);
|
|
6451
|
+
if (notice === void 0) return "";
|
|
6452
|
+
return t(expiryHeadlineKey(notice.tier), {
|
|
6453
|
+
total: formatCredits(notice.total),
|
|
6454
|
+
packs: String(notice.packs)
|
|
6400
6455
|
});
|
|
6401
6456
|
}
|
|
6402
6457
|
/**
|
|
@@ -6737,7 +6792,7 @@ window.__ModuleLoader__.load({
|
|
|
6737
6792
|
}) })]
|
|
6738
6793
|
}),
|
|
6739
6794
|
activeRegion === "cn" && signedIn?.credits?.expiry !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6740
|
-
className: `dsm-trae-expiry ${
|
|
6795
|
+
className: `dsm-trae-expiry ${expiryToneClass(expiryNotice(signedIn.credits.expiry)?.tier ?? "lapsed")}`,
|
|
6741
6796
|
role: "status",
|
|
6742
6797
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: expiryMessageOf(signedIn.credits.expiry, t) }), soonestExpiryOf(signedIn.credits.expiry) === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6743
6798
|
className: "dsm-trae-expiry-detail",
|
|
@@ -7055,6 +7110,7 @@ window.__ModuleLoader__.load({
|
|
|
7055
7110
|
"row.creditsAlternative": "Another account on this machine still has credit: {accounts}",
|
|
7056
7111
|
"row.creditsAlternativeSwitch": "Switch to it",
|
|
7057
7112
|
"row.expiryWarningSoon": "{total} credit lapses within 24 hours ({packs} packs)",
|
|
7113
|
+
"row.expiryWarningDays": "{total} credit lapses within 3 days ({packs} packs)",
|
|
7058
7114
|
"row.expiryWarningWeek": "{total} credit lapses within 7 days ({packs} packs)",
|
|
7059
7115
|
"row.expiryWarningLapsed": "{total} credit has already lapsed but is still counted in the balance ({packs} packs)",
|
|
7060
7116
|
"row.expiryEarliest": "Earliest: {time}",
|
|
@@ -7442,6 +7498,7 @@ window.__ModuleLoader__.load({
|
|
|
7442
7498
|
"row.creditsAlternative": "本机还有可用账号:{accounts}",
|
|
7443
7499
|
"row.creditsAlternativeSwitch": "切换到它",
|
|
7444
7500
|
"row.expiryWarningSoon": "有 {total} 积分将在 24 小时内过期({packs} 个套餐)",
|
|
7501
|
+
"row.expiryWarningDays": "有 {total} 积分将在 3 天内过期({packs} 个套餐)",
|
|
7445
7502
|
"row.expiryWarningWeek": "有 {total} 积分将在 7 天内过期({packs} 个套餐)",
|
|
7446
7503
|
"row.expiryWarningLapsed": "有 {total} 积分已过期但仍计入余额({packs} 个套餐)",
|
|
7447
7504
|
"row.expiryEarliest": "最早到期:{time}",
|
package/lib/index.d.ts
CHANGED
|
@@ -915,6 +915,13 @@ interface TraeWebExpiringCredits {
|
|
|
915
915
|
* Only present when at least one pack carried a usable `expiresAtMs` — a card
|
|
916
916
|
* must never read "we were not told when anything expires" as "nothing is
|
|
917
917
|
* about to lapse".
|
|
918
|
+
*
|
|
919
|
+
* The three forward buckets are NESTED and CUMULATIVE: `within24h` ⊆
|
|
920
|
+
* `within3d` ⊆ `within7d`, each counting every pack inside its own horizon.
|
|
921
|
+
* So each bucket answers "how much lapses within N" and the copy states that
|
|
922
|
+
* bucket's own figure — which is why ONE bucket's number is always true on
|
|
923
|
+
* its own terms, and why the reader never has to add two figures together (the
|
|
924
|
+
* notice shows exactly one tier at a time).
|
|
918
925
|
*/
|
|
919
926
|
interface TraeWebCreditExpiry {
|
|
920
927
|
within24h: TraeWebExpiringCredits;
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "dsh-connect-trae",
|
|
3
3
|
"displayName": "DSH Connect Trae",
|
|
4
4
|
"description": "把本机登录的 Trae 模型接入 DeepSeek Harness:国内版与国际版双供应商并行,提供用量/积分概览与每日签到领取。",
|
|
5
|
-
"version": "4.6.
|
|
5
|
+
"version": "4.6.10",
|
|
6
6
|
"author": "dingminhua",
|
|
7
7
|
"copyright": "Copyright (c) 2026 LaoDing",
|
|
8
8
|
"license": "MIT",
|