dsh-connect-trae 3.10.2 → 4.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.
- package/CHANGELOG.md +73 -0
- package/README.en.md +6 -0
- package/README.md +6 -1
- package/lib/client.js +117 -164
- package/lib/index.d.ts +1 -80
- package/lib/index.js +2 -142
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,78 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 4.0.1 (2026-10-19)
|
|
4
|
+
|
|
5
|
+
> CN 区模型卡「最大输出」整列空白(issue #42)修复:上游**是**发布输出上限的——`get_detail_param` 的
|
|
6
|
+
> CN 80 个 config **80/80** 都带 `model_detail_list[].max_tokens`——但目录合并 `mergeTraeModelSources()`
|
|
7
|
+
> 把 wire 侧的 `maxTokens` 丢掉了。这个字段从合并函数诞生那天(1.1.0)起就没被复制过,卡片、
|
|
8
|
+
> `/models/refresh` 与 DSH 模型注册因此永远收到「未知」。附带落地同一 issue 的批量请求:整区上下文
|
|
9
|
+
> 一键切换两个按钮。
|
|
10
|
+
|
|
11
|
+
### 修复
|
|
12
|
+
|
|
13
|
+
- **目录合并带上 wire 的 `max_tokens`**(`fix(catalog)`)。合并时其余字段(contextWindow / maxContextWindow /
|
|
14
|
+
倍率 / reasoning / multimodal / config_name)一路都复制了,唯独漏了 `maxTokens` 一行。修复后 CN 实测
|
|
15
|
+
32 行目录 30 行带值;**仍空白的行是诚实的**——`kimi-k2.8-preview`、`qwen3.8-flash` 这类 TraeCode 通道行
|
|
16
|
+
在 SOLO 名单里没有对应 config,拿不到候选值,宁空白不编造。取值链其余部分不动:`collectModels` 读
|
|
17
|
+
`model_detail_list[0]` 实测无损(71/80 config 的双项 `__dev`/`__max` 上限恒等)。该值是**元数据**,
|
|
18
|
+
请求体照旧不下发 `max_tokens`(上限由 Trae 服务端决定),行为无变化。
|
|
19
|
+
- 报告人「想确认的一点」(输出上限是否挂在后面的 detail 项或别的键)已逐项 dump 排除,全文见
|
|
20
|
+
`docs/ISSUE42_DIAGNOSIS.md`,取证脚本 `scripts/probe-cn-maxtokens.mjs`(只读,随仓库提交)。
|
|
21
|
+
|
|
22
|
+
### 新增
|
|
23
|
+
|
|
24
|
+
- **卡片模型管理区两个批量上下文按钮**(`feat(card)`,issue #42 附带需求):「**整区切到 Max**」给本区
|
|
25
|
+
每个带 Max 档的模型一次性写入其 `maxContextWindow`(正是 `applyContextBudgets` 认的精确值),
|
|
26
|
+
没有 Max 档的行不动、已有手动预算保留;「**全部恢复默认上下文**」清空本区预算。二者作用于草稿、
|
|
27
|
+
按「保存」生效,落盘形状与逐行单选完全一致——因此**没有**新增 `contextBudgetMode` 配置键,
|
|
28
|
+
运行时零新分支、旧配置零迁移。报告人数的 18 次点击现在是一次。
|
|
29
|
+
- README 新增「最大输出与上下文预算」一节(issue #42 建议 1 换内容采纳:事实已变,文档写明上游发布该值、
|
|
30
|
+
空白行另有其因)。
|
|
31
|
+
|
|
32
|
+
### 测试
|
|
33
|
+
|
|
34
|
+
- 新增合并回归用例(修复前必红:wire 行带 `maxTokens` → 合并行必须保留;join-miss 行必须缺席)与
|
|
35
|
+
5 例卡片用例(批量按钮的落盘内容、既有手动预算的保留、两按钮各自禁用条件)。
|
|
36
|
+
- 全仓 **901** 例通过,0 skipped;`tsc` 两个工程干净;`build` 通过。修复前后各跑一次实时探针对照
|
|
37
|
+
(0/32 → 30/32)。
|
|
38
|
+
|
|
39
|
+
## 4.0.0 (2026-10-19)
|
|
40
|
+
|
|
41
|
+
> 移除 issue #29 的「跟随 Trae 桌面端当前登录」整套机制,连同它派生的两处 UI。
|
|
42
|
+
>
|
|
43
|
+
> **原因:账号池功能无法兼容原需求。** #29 要的是「插件始终跟着 App 当前的登录走」,而账号池要的是
|
|
44
|
+
> 「每个账号都能被长期保留、随时选中、按可用性换号」——池里选中的账号往往正是那个已经不在 App 里
|
|
45
|
+
> 登录的账号,它必须照常可用。「跟随当前登录」与「账号池」是互斥的两条规则,只能是后者。
|
|
46
|
+
>
|
|
47
|
+
> 这是**大版本**:一个配置字段与两处界面被移除。
|
|
48
|
+
|
|
49
|
+
### 移除
|
|
50
|
+
|
|
51
|
+
- **设置卡片里的「跟随 Trae 当前登录的账号」开关**。连带删除 `Config.followAppLogin` 字段、每次设置
|
|
52
|
+
生效时的自动重绑、以及启动时的那次跟随。插件不再有「不点也会自己换绑计费账号」的路径。
|
|
53
|
+
该开关默认关闭,所以从未打开过它的用户没有任何行为变化;存过 `true` 的旧配置里的这个键会被忽略。
|
|
54
|
+
- **账号区上方的「Trae 已登录 X,但本插件绑定的是 Y。改用 Y」提示条**。连带删除 Host 侧
|
|
55
|
+
`TraeCredentialStore.liveLogin()`、usage 文档的 `appLogin` 字段及其读取路径、`TraeWebAppLogin` 类型。
|
|
56
|
+
usage 文档不再携带这个字段。
|
|
57
|
+
- **账号池设置里的「每登录一个账号,就刷新一次」黄色警告框**。账号副本是每次读取就补齐一次的,
|
|
58
|
+
这句「没刷新就换号,上一个账号不会被保存」与实现不符。
|
|
59
|
+
- 顺带清掉只服务于跟随开关的 Host 侧 `writeSettings` 写入通道(`settings.update` + revision 冲突重试),
|
|
60
|
+
它的唯一消费者就是那个开关。
|
|
61
|
+
|
|
62
|
+
### 不变
|
|
63
|
+
|
|
64
|
+
- **没有显式选择账号时,仍然默认使用 App 当前登录的账号**(`preferred()` 对 `source === 'desktop'`
|
|
65
|
+
的凭据优先)。这是本次移除后仍然保留的「跟随」行为,且不需要任何开关。
|
|
66
|
+
- **账号副本机制不变**:本机每个 Trae 登录都会被复制成自己的一份(`~/.dsh/.trae-auth.<region>.json`),
|
|
67
|
+
换号不会顶掉任何账号,之前的账号仍可被重新选回来。
|
|
68
|
+
|
|
69
|
+
### 测试
|
|
70
|
+
|
|
71
|
+
- 删掉随功能退役的用例:`auth.spec.ts` 的 `liveLogin()` 三态、`web-status.spec.ts` 整个
|
|
72
|
+
`app sign-in follow hint (issue #29)` describe、`card-accounts-table` 的提示条两条、`card-pool` 的
|
|
73
|
+
警告框一条。`card-styles` 的遮罩用例改用 `showPointsInMainUi` 开关驱动。
|
|
74
|
+
- 全仓 **895** 例通过,0 skipped;`tsc` 两个工程干净;`build` 通过。
|
|
75
|
+
|
|
3
76
|
## 3.10.2 (2026-10-19)
|
|
4
77
|
|
|
5
78
|
> 设置页的账号列表**先出、积分后补**。打开卡片原本要等**一整份**用量文档组装完才画第一笔:那份文档的
|
package/README.en.md
CHANGED
|
@@ -127,6 +127,12 @@ That is the upstream refusal stated plainly, rather than a silent failure or som
|
|
|
127
127
|
|
|
128
128
|
To use these three models today, use the **Trae IDE itself**.
|
|
129
129
|
|
|
130
|
+
## Max output and context budgets
|
|
131
|
+
|
|
132
|
+
The "最大输出" (max output) on the model card comes from `model_detail_list[].max_tokens` in Trae's `get_detail_param` — upstream **does** publish it (live-verified: 80/80 CN configs carry it). As of 4.0.1 the value travels through the catalog merge all the way to the card, `/models/refresh` and DSH model registration; before that the merge step dropped the field, so the whole region rendered blank (issue #42 — full diagnosis in `docs/ISSUE42_DIAGNOSIS.md`). **Rows that are still blank are being honest**: models the directory lists but the SOLO roster has no config for (the three TraeCode rows above) have no candidate value to show — we prefer a blank over an invented cap. The value is metadata only; the plugin never puts `max_tokens` into request bodies (the server decides the real cap).
|
|
133
|
+
|
|
134
|
+
Context windows are a per-model choice between Trae's default (dev) window and its Max window, stored per panel as `contextBudgets`. For a whole-region switch, the model section now has two buttons: "**Switch all to Max**" (writes each Max-capable row's `maxContextWindow`, leaves no-Max rows and existing manual budgets alone) and "**Restore default context**" (clears the region's budget dict). Both act on the draft and take effect on Save, producing exactly the same stored shape as the per-row radios (issue #42 side request — 18 Max rows in CN used to mean 18 clicks).
|
|
135
|
+
|
|
130
136
|
## Install
|
|
131
137
|
|
|
132
138
|
```sh
|
package/README.md
CHANGED
|
@@ -46,7 +46,6 @@
|
|
|
46
46
|
- **目录与勾选按面板隔离** —— 三个面板各一套模型目录、勾选、图片开关与上下文预算,各自读各自的槽位。名录从**该面板所钉的那条网关**读取——原本钉在企业池的客户端去读消费池名录,会永远发现不了自己池的独占模型。
|
|
47
47
|
- **识图能力跟随 Trae 自身的标注** —— Trae 把某个模型标为 `multimodal` 时,插件直接按多模态对外声明,无需你在卡片上逐一手勾(issue #16)。判据是「**你手动勾选的 ∪ Trae 标注多模态的**」:Trae 明确标 `false` 或未标注的模型保持纯文本,你可以照旧手动为它们打开图片输入。卡片上被自动开启的那一行显示为已勾选且只读,并说明原因。详见下方「图片输入(识图)」。
|
|
48
48
|
- **多账号切换** —— 支持重新读取 Token 列表并选择账号;Token 不写入 DSH 设置。**你的选择会被记住并长期生效**:插件不会因为某个账号额度用尽、或检测到另一个可用账号就自作主张替你切换(换账号意味着换人计费)——唯一的例外是你**亲自打开**的账号池(见下一条),那是一个显式选择,而不是插件的自作主张。所以当绑定的账号额度耗尽时,卡片会**明确告诉你**,并把本机其他还有额度的账号连同其可用积分数列出来,由你一键切换——而不是让面板一直空着、也不自动把你切走。「刷新账号与 Token」每次都会回报结果(找到几个账号、当前仍绑定谁),不会再「点了没反应」。下拉里显示的是产品名(`Trae` / `TRAE SOLO` / 国际版),便于分辨凭据来自哪个安装。
|
|
49
|
-
- **跟随 Trae 当前登录的账号** —— 你在 Trae 桌面端**退出并换登录**后,卡片会检测到「插件绑定的账号」与「Trae 现在登录的账号」不一致,并给出一行提示与**一键切换**(复用账号下拉的同一次写入,不引入第二条切换路径)。想让插件**自动跟随**,可打开设置卡片里的「跟随 Trae 当前登录的账号」开关:此后每次配置生效都会把 `accounts.<region>` 重绑到 App 当前登录的账号。**该开关默认关闭**——已有配置保持原来的严格绑定,自动换绑意味着换人计费,必须由你主动勾选;未勾选时上面那行提示就是你的手动通道。(issue #29)
|
|
50
49
|
- **账号导入 / 导出** —— 不用再为了用第二个账号而把凭据手工写进默认路径、顶掉上一个。在卡片账号区的「导入 / 导出账号」里:**导出**勾选若干账号下载一份 JSON;**导入**选择文件后先看**脱敏预览**(只显示账号标识与「是否有 Token」,不含凭据本身)再勾选导入。文件格式与同族 `dsh-connect-workbuddy` **互通**,两边导出的文件可以互相导入。导入按账号去重(同一账号再导入即覆盖更新),**认不出所属区域或因缺 Token 的记录会被跳过并计数**——国内版与国际版是两条并行计费通道,跨区导入会导致跨区计费,所以这里只认同能**正向识别**的区域(企业版共用 CN 凭据池,不构成第三条导入通道)。导出文件里是**有效 Token,请当作密码保管**。(issue #37)
|
|
51
50
|
- **只读用量与模型管理** —— 国内版查看 Work 积分与通用积分,国际版查看订阅/试用状态;刷新/启用 Trae 模型;只读查询不消耗额度。
|
|
52
51
|
- **积分临近到期会提醒** —— 剩余额度只回答「还有多少」,回答不了「**哪一笔先到期**」;提醒条按到期紧迫程度逐级加重(**7 天 → 24 小时 → 已过期**),写明金额、套餐数和最早到期时间,避免只盯总额时悄悄丢掉最先到期的额度。国内版在用量页与输入框积分面板两处都显示(国际版是订阅制,没有逐包到期数据)。
|
|
@@ -141,6 +140,12 @@ Trae does not serve this model under the SOLO function the request used
|
|
|
141
140
|
|
|
142
141
|
如果你现在就要用这 3 个模型,请直接在 **Trae IDE 本体**中使用。
|
|
143
142
|
|
|
143
|
+
## 最大输出与上下文预算
|
|
144
|
+
|
|
145
|
+
模型卡上的「最大输出」来自 Trae `get_detail_param` 的 `model_detail_list[].max_tokens` —— 上游**是**发布这个值的(CN 实测 80/80 config 都带)。4.0.1 起它随目录合并一路带到卡片、`/models/refresh` 与 DSH 模型注册;此前合并层漏传了这个字段,整区模型全部显示空白(issue #42,诊断见 `docs/ISSUE42_DIAGNOSIS.md`)。**仍然空白的行是诚实的**:目录里有、但 SOLO 名单里没有对应 config 的模型(上面那 3 个 TraeCode 通道行)拿不到任何候选值,宁可空白也不编一个上限。这个值是元数据,插件不把它写进请求体(输出上限由 Trae 服务端决定)。
|
|
146
|
+
|
|
147
|
+
上下文窗口在 Trae 公布的默认(dev)档与 Max 档之间二选一,按面板逐模型存成 `contextBudgets`。想整区一次切换:模型管理区有「**整区切到 Max**」(给每个带 Max 档的行写入其 `maxContextWindow`,没有 Max 档的行不动)和「**全部恢复默认上下文**」(清空本区预算)两个按钮,作用在草稿上、按「保存」生效,与逐行单选落盘的结果完全一致(issue #42 附带需求——CN 有 18 个 Max 模型,以前要点 18 次)。
|
|
148
|
+
|
|
144
149
|
## 安装
|
|
145
150
|
|
|
146
151
|
推荐使用 DSH 插件命令安装 npm 已发布版本:
|
package/lib/client.js
CHANGED
|
@@ -207,20 +207,6 @@ window.__ModuleLoader__.load({
|
|
|
207
207
|
return typeof accounts === "object" && accounts !== null ? accounts : {};
|
|
208
208
|
}
|
|
209
209
|
/**
|
|
210
|
-
* Whether the host-side "follow the Trae app's sign-in" switch is on (issue
|
|
211
|
-
* #29). Absent reads as OFF, so an existing configuration keeps the strict
|
|
212
|
-
* bind it shipped with and the switch is an opt-in — the same opt-out
|
|
213
|
-
* semantics as {@link regionEnabledOf}, for the same reason: a config written
|
|
214
|
-
* before this field existed cannot ask for behavior it never declared.
|
|
215
|
-
*
|
|
216
|
-
* Reads the whole settings section (or the bare field); deep-unwraps first
|
|
217
|
-
* because on DSH 0.1.7 a volatile field arrives as a `{get(): T}` live
|
|
218
|
-
* reference, whose `typeof === 'object'` would otherwise pass a naive check.
|
|
219
|
-
*/
|
|
220
|
-
function followAppLoginEnabled(configured) {
|
|
221
|
-
return unwrapVolatileDeep(configured)?.followAppLogin === true;
|
|
222
|
-
}
|
|
223
|
-
/**
|
|
224
210
|
* Build the next `regions` settings value for the card's save. The write
|
|
225
211
|
* targets ONLY the signed-in account's region slot; every other region's slot
|
|
226
212
|
* is carried over untouched, so switching accounts never clobbers the other
|
|
@@ -481,7 +467,7 @@ window.__ModuleLoader__.load({
|
|
|
481
467
|
.dsm-trae-pref input{flex:none;cursor:pointer;accent-color:var(--dsw-alias-brand-primary,#5686fe)}
|
|
482
468
|
.dsm-trae-pref-check{inline-size:15px;block-size:15px;margin:3px 0 0}
|
|
483
469
|
/* The label and its explanation used to run together as one wrapped blob
|
|
484
|
-
("
|
|
470
|
+
("在输入框工具栏显示积分读数 在输入框工具栏显示可点击读数…"), which is what made
|
|
485
471
|
this block read as a wall of text. They are two lines now: what the switch
|
|
486
472
|
does, then what it means. */
|
|
487
473
|
.dsm-trae-pref-copy{display:flex;flex-direction:column;gap:3px;min-width:0}
|
|
@@ -693,6 +679,10 @@ window.__ModuleLoader__.load({
|
|
|
693
679
|
color:var(--dsw-alias-brand-primary,#2563eb);font-size:11px;line-height:16px;
|
|
694
680
|
}
|
|
695
681
|
.dsm-trae-models-hint{margin:4px 0 0;color:var(--dsw-alias-label-tertiary,#999);font-size:11px;line-height:16px}
|
|
682
|
+
/* Bulk context-budget row (issue #42): under the model list, above the
|
|
683
|
+
capability note. Wraps on narrow cards; keeps the two buttons visually a
|
|
684
|
+
pair and distinct from the save footer below. */
|
|
685
|
+
.dsm-trae-context-bulk{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px}
|
|
696
686
|
/* Verdict badge. Only a real refusal is coloured as a warning; an unknown
|
|
697
687
|
verdict stays neutral because an inconclusive probe is not evidence against
|
|
698
688
|
the model. */
|
|
@@ -915,9 +905,6 @@ window.__ModuleLoader__.load({
|
|
|
915
905
|
/* "Every member is unusable" is the one case that IS the pool's fault, so it
|
|
916
906
|
keeps the warn tone the base class sets. */
|
|
917
907
|
.dsm-trae-pool-warning-unusable{border-color:var(--dsw-alias-state-warn-secondary,#fbbf24);background:var(--dsw-alias-state-warn-tertiary,#fef3c7);color:var(--dsw-alias-state-warn-primary,#b45309)}
|
|
918
|
-
/* The sign-in/refresh workflow sits in the settings block: it keeps the warn
|
|
919
|
-
tone (getting it wrong loses an account) but is not a fault of the pool. */
|
|
920
|
-
.dsm-trae-pool-warning-workflow{margin:0 0 2px}
|
|
921
908
|
.dsm-trae-pool-save-row{display:flex;align-items:center;justify-content:space-between;gap:12px;border-top:1px solid var(--dsw-alias-border-l2,#36373b);padding-top:12px}
|
|
922
909
|
.dsm-trae-pool-save-buttons{display:flex;align-items:center;justify-content:flex-end;gap:8px}
|
|
923
910
|
.dsm-trae-pool-save-row .dsm-btn{padding:5px 14px;font-size:13px;line-height:1.5}
|
|
@@ -1938,17 +1925,6 @@ window.__ModuleLoader__.load({
|
|
|
1938
1925
|
className: "dsm-trae-pool-tools dsm-trae-pool-tools-dashed",
|
|
1939
1926
|
children: tools
|
|
1940
1927
|
}),
|
|
1941
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1942
|
-
className: "dsm-trae-pool-warning dsm-trae-pool-warning-workflow",
|
|
1943
|
-
role: "note",
|
|
1944
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1945
|
-
className: "dsm-trae-pool-warning-title",
|
|
1946
|
-
children: t("row.poolMirrorWorkflowTitle")
|
|
1947
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1948
|
-
className: "dsm-trae-pool-warning-hint",
|
|
1949
|
-
children: t("row.poolMirrorWorkflowHint")
|
|
1950
|
-
})]
|
|
1951
|
-
}),
|
|
1952
1928
|
pool.copies === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1953
1929
|
className: "dsm-trae-pool-note dsm-trae-pool-copyfile",
|
|
1954
1930
|
role: "note",
|
|
@@ -3179,10 +3155,7 @@ window.__ModuleLoader__.load({
|
|
|
3179
3155
|
* local state: a write made elsewhere (the DSH settings form, another window)
|
|
3180
3156
|
* then shows up here instead of being shadowed by a stale copy.
|
|
3181
3157
|
*/
|
|
3182
|
-
const committedSettings = {
|
|
3183
|
-
followAppLogin: followAppLoginEnabled(settingsScope?.getSnapshot().value),
|
|
3184
|
-
showPointsInMainUi: unwrapVolatileDeep(settingsScope?.getSnapshot().value)?.showPointsInMainUi === true
|
|
3185
|
-
};
|
|
3158
|
+
const committedSettings = { showPointsInMainUi: unwrapVolatileDeep(settingsScope?.getSnapshot().value)?.showPointsInMainUi === true };
|
|
3186
3159
|
/**
|
|
3187
3160
|
* Ids for the block's label/hint wiring. `useId`, not constants: DSH can mount
|
|
3188
3161
|
* this card twice at once (the settings ROW and the expanded PAGE), and two
|
|
@@ -3194,13 +3167,8 @@ window.__ModuleLoader__.load({
|
|
|
3194
3167
|
* over it. Reading BOTH sources here is what lets the write above stay simple —
|
|
3195
3168
|
* it never has to write into component state that a Host refresh would fight.
|
|
3196
3169
|
*/
|
|
3197
|
-
const settingsEdits = {
|
|
3198
|
-
followAppLogin: optimisticSettings.current.followAppLogin ?? committedSettings.followAppLogin,
|
|
3199
|
-
showPointsInMainUi: optimisticSettings.current.showPointsInMainUi ?? committedSettings.showPointsInMainUi
|
|
3200
|
-
};
|
|
3170
|
+
const settingsEdits = { showPointsInMainUi: optimisticSettings.current.showPointsInMainUi ?? committedSettings.showPointsInMainUi };
|
|
3201
3171
|
const settingsIds = (0, react.useId)();
|
|
3202
|
-
const followLabelId = `${settingsIds}-follow`;
|
|
3203
|
-
const followHintId = `${settingsIds}-follow-hint`;
|
|
3204
3172
|
const creditsLabelId = `${settingsIds}-credits`;
|
|
3205
3173
|
const creditsHintId = `${settingsIds}-credits-hint`;
|
|
3206
3174
|
/**
|
|
@@ -3226,7 +3194,7 @@ window.__ModuleLoader__.load({
|
|
|
3226
3194
|
};
|
|
3227
3195
|
setSettingsRevision((revision) => revision + 1);
|
|
3228
3196
|
try {
|
|
3229
|
-
await writeSettingsField(settingsScope, field, value, (readBack) =>
|
|
3197
|
+
await writeSettingsField(settingsScope, field, value, (readBack) => unwrapVolatileDeep(readBack)?.showPointsInMainUi === value);
|
|
3230
3198
|
} catch (error) {
|
|
3231
3199
|
if (mounted.current) setWriteError(error instanceof Error ? error.message : t("row.requestFailed"));
|
|
3232
3200
|
} finally {
|
|
@@ -3509,21 +3477,6 @@ window.__ModuleLoader__.load({
|
|
|
3509
3477
|
}
|
|
3510
3478
|
};
|
|
3511
3479
|
/**
|
|
3512
|
-
* Follow the Trae app's current sign-in from the hint row (issue #29).
|
|
3513
|
-
*
|
|
3514
|
-
* One click, and it goes through the SAME `switchAccount` write the account
|
|
3515
|
-
* dropdown uses — so the card has exactly one writer for `accounts`, the Host
|
|
3516
|
-
* sees the change through `loader/volatile-update` like every other card
|
|
3517
|
-
* write, and there is no second settings path to keep in sync. The app's
|
|
3518
|
-
* sign-in is `status.appLogin`, which the Host only reports when it differs
|
|
3519
|
-
* from the bound account, so a click here always moves the binding to what
|
|
3520
|
-
* the app is actually logged into.
|
|
3521
|
-
*/
|
|
3522
|
-
const followAppLogin = async () => {
|
|
3523
|
-
if (status.status !== "signed-in" || status.appLogin === void 0) return;
|
|
3524
|
-
await switchAccount(status.appLogin.id);
|
|
3525
|
-
};
|
|
3526
|
-
/**
|
|
3527
3480
|
* Load one account row's per-account state (check-in / balances /
|
|
3528
3481
|
* subscription) and cache it for the row. Called when the table renders and
|
|
3529
3482
|
* again after a claim so the reward/refusal lands on the row that owns it.
|
|
@@ -3930,6 +3883,39 @@ window.__ModuleLoader__.load({
|
|
|
3930
3883
|
};
|
|
3931
3884
|
});
|
|
3932
3885
|
};
|
|
3886
|
+
/**
|
|
3887
|
+
* Bulk context-budget switch (issue #42 side request). The per-model radios
|
|
3888
|
+
* stay exactly as they are; these two act on the whole region draft at once.
|
|
3889
|
+
* The reporter counted 18 CN models whose Max window differs from the
|
|
3890
|
+
* default and described clicking 18 times per region — 「整区切到 Max」 is
|
|
3891
|
+
* those 18 clicks as one button. It writes `maxContextWindow` per row, which
|
|
3892
|
+
* is precisely the spelling `applyContextBudgets` recognizes (a budget equal
|
|
3893
|
+
* to the native Max window widens the effective window), so bulk and per-row
|
|
3894
|
+
* paths land on identical saved state. Models without a Max window are left
|
|
3895
|
+
* untouched — inventing a budget for them would be filtered out anyway.
|
|
3896
|
+
*/
|
|
3897
|
+
const setAllContextMax = () => {
|
|
3898
|
+
editDraft((current) => {
|
|
3899
|
+
const next = { ...current.contextBudgets };
|
|
3900
|
+
for (const model of current.models) if (model.maxContextWindow !== void 0) next[model.id] = model.maxContextWindow;
|
|
3901
|
+
return {
|
|
3902
|
+
...current,
|
|
3903
|
+
contextBudgets: next
|
|
3904
|
+
};
|
|
3905
|
+
});
|
|
3906
|
+
};
|
|
3907
|
+
/**
|
|
3908
|
+
* 「恢复默认上下文」 clears every override in this region's draft. Empty
|
|
3909
|
+
* dict = every row falls back to its default window (the same state as a
|
|
3910
|
+
* region that was never configured), and clearing is what makes the bulk
|
|
3911
|
+
* action reversible without 18 more clicks.
|
|
3912
|
+
*/
|
|
3913
|
+
const resetAllContextBudgets = () => {
|
|
3914
|
+
editDraft((current) => ({
|
|
3915
|
+
...current,
|
|
3916
|
+
contextBudgets: {}
|
|
3917
|
+
}));
|
|
3918
|
+
};
|
|
3933
3919
|
const discardModels = () => {
|
|
3934
3920
|
setDrafts((prev) => {
|
|
3935
3921
|
const next = { ...prev };
|
|
@@ -4185,90 +4171,62 @@ window.__ModuleLoader__.load({
|
|
|
4185
4171
|
}),
|
|
4186
4172
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4187
4173
|
className: "dsm-trae-prefs",
|
|
4188
|
-
children: [
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
children: t("row.followAppLoginHint")
|
|
4211
|
-
})]
|
|
4174
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
4175
|
+
className: "dsm-trae-pref",
|
|
4176
|
+
title: t(isCnPool ? "row.showPointsInMainUiHint" : "row.showPointsInMainUiHintAi"),
|
|
4177
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
4178
|
+
type: "checkbox",
|
|
4179
|
+
className: "dsm-trae-pref-check",
|
|
4180
|
+
checked: settingsEdits.showPointsInMainUi,
|
|
4181
|
+
disabled: settingsScope?.getSnapshot().writable !== true || savingSettings,
|
|
4182
|
+
"aria-describedby": creditsHintId,
|
|
4183
|
+
onChange: (event) => {
|
|
4184
|
+
writePreference("showPointsInMainUi", event.currentTarget.checked);
|
|
4185
|
+
}
|
|
4186
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4187
|
+
className: "dsm-trae-pref-copy",
|
|
4188
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4189
|
+
className: "dsm-trae-pref-label",
|
|
4190
|
+
id: creditsLabelId,
|
|
4191
|
+
children: t("row.showPointsInMainUi")
|
|
4192
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4193
|
+
className: "dsm-trae-pref-hint",
|
|
4194
|
+
id: creditsHintId,
|
|
4195
|
+
children: t(isCnPool ? "row.showPointsInMainUiHint" : "row.showPointsInMainUiHintAi")
|
|
4212
4196
|
})]
|
|
4213
|
-
})
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
disabled: settingsScope?.getSnapshot().writable !== true || savingSettings,
|
|
4222
|
-
"aria-describedby": creditsHintId,
|
|
4223
|
-
onChange: (event) => {
|
|
4224
|
-
writePreference("showPointsInMainUi", event.currentTarget.checked);
|
|
4225
|
-
}
|
|
4226
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4227
|
-
className: "dsm-trae-pref-copy",
|
|
4197
|
+
})]
|
|
4198
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
|
|
4199
|
+
className: "dsm-trae-pref dsm-trae-credit-position-pref",
|
|
4200
|
+
title: t("row.creditPositionHint"),
|
|
4201
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4202
|
+
className: "dsm-trae-pref-copy",
|
|
4203
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4204
|
+
className: "dsm-trae-pref-lead",
|
|
4228
4205
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4229
4206
|
className: "dsm-trae-pref-label",
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
className: "dsm-trae-pref-lead",
|
|
4246
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4247
|
-
className: "dsm-trae-pref-label",
|
|
4248
|
-
children: t("row.creditPositionLabel")
|
|
4249
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
4250
|
-
className: "dsm-trae-credit-position",
|
|
4251
|
-
value: activeRegionOn ? creditPositionOn(activeRegion) : "composer",
|
|
4252
|
-
disabled: !activeRegionOn || settingsScope?.getSnapshot().writable !== true || savingSettings,
|
|
4253
|
-
"aria-label": t("row.creditPositionAria", { region: activeRegion === "cn" ? t("row.tabCn") : activeRegion === "enterprise" ? t("row.tabEnterprise") : t("row.tabAi") }),
|
|
4254
|
-
onChange: (event) => {
|
|
4255
|
-
changeCreditPosition(activeRegion, event.currentTarget.value === "stats" ? "stats" : "composer");
|
|
4256
|
-
},
|
|
4257
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
4258
|
-
value: "composer",
|
|
4259
|
-
children: t("row.creditPositionComposer")
|
|
4260
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
4261
|
-
value: "stats",
|
|
4262
|
-
children: t("row.creditPositionStats")
|
|
4263
|
-
})]
|
|
4207
|
+
children: t("row.creditPositionLabel")
|
|
4208
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
4209
|
+
className: "dsm-trae-credit-position",
|
|
4210
|
+
value: activeRegionOn ? creditPositionOn(activeRegion) : "composer",
|
|
4211
|
+
disabled: !activeRegionOn || settingsScope?.getSnapshot().writable !== true || savingSettings,
|
|
4212
|
+
"aria-label": t("row.creditPositionAria", { region: activeRegion === "cn" ? t("row.tabCn") : activeRegion === "enterprise" ? t("row.tabEnterprise") : t("row.tabAi") }),
|
|
4213
|
+
onChange: (event) => {
|
|
4214
|
+
changeCreditPosition(activeRegion, event.currentTarget.value === "stats" ? "stats" : "composer");
|
|
4215
|
+
},
|
|
4216
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
4217
|
+
value: "composer",
|
|
4218
|
+
children: t("row.creditPositionComposer")
|
|
4219
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
4220
|
+
value: "stats",
|
|
4221
|
+
children: t("row.creditPositionStats")
|
|
4264
4222
|
})]
|
|
4265
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4266
|
-
className: "dsm-trae-pref-hint",
|
|
4267
|
-
children: t("row.creditPositionHint")
|
|
4268
4223
|
})]
|
|
4269
|
-
})
|
|
4224
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4225
|
+
className: "dsm-trae-pref-hint",
|
|
4226
|
+
children: t("row.creditPositionHint")
|
|
4227
|
+
})]
|
|
4270
4228
|
})
|
|
4271
|
-
]
|
|
4229
|
+
})]
|
|
4272
4230
|
}),
|
|
4273
4231
|
status.status === "signed-in" && status.pool !== void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
4274
4232
|
className: "dsm-trae-accounts",
|
|
@@ -4443,25 +4401,6 @@ window.__ModuleLoader__.load({
|
|
|
4443
4401
|
formatNumber,
|
|
4444
4402
|
formatDateTime
|
|
4445
4403
|
}) : null,
|
|
4446
|
-
status.status === "signed-in" && status.appLogin !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4447
|
-
className: "dsm-trae-usage-alternative",
|
|
4448
|
-
role: "status",
|
|
4449
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4450
|
-
className: "dsm-trae-usage-alternative-text",
|
|
4451
|
-
children: t("row.appLoginMismatch", {
|
|
4452
|
-
account: status.appLogin.accountName,
|
|
4453
|
-
bound: status.accountName
|
|
4454
|
-
})
|
|
4455
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4456
|
-
type: "button",
|
|
4457
|
-
className: "dsm-trae-usage-switch-button",
|
|
4458
|
-
disabled: switchingAccount || settingsScope?.getSnapshot()?.writable !== true,
|
|
4459
|
-
onClick: () => {
|
|
4460
|
-
followAppLogin();
|
|
4461
|
-
},
|
|
4462
|
-
children: t("row.appLoginFollow", { account: status.appLogin.accountName })
|
|
4463
|
-
})]
|
|
4464
|
-
}) : null,
|
|
4465
4404
|
rescanNote === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4466
4405
|
className: "dsm-trae-usage-note",
|
|
4467
4406
|
role: "status",
|
|
@@ -4687,6 +4626,24 @@ window.__ModuleLoader__.load({
|
|
|
4687
4626
|
})]
|
|
4688
4627
|
}, model.id))
|
|
4689
4628
|
}),
|
|
4629
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4630
|
+
className: "dsm-trae-context-bulk",
|
|
4631
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4632
|
+
type: "button",
|
|
4633
|
+
className: "dsm-btn dsm-btn-outline",
|
|
4634
|
+
disabled: busy || saving || settingsScope?.getSnapshot().writable !== true || !visibleModels.some((model) => model.maxContextWindow !== void 0),
|
|
4635
|
+
title: t("row.contextAllMaxHint"),
|
|
4636
|
+
onClick: setAllContextMax,
|
|
4637
|
+
children: t("row.contextAllMax")
|
|
4638
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4639
|
+
type: "button",
|
|
4640
|
+
className: "dsm-btn dsm-btn-outline",
|
|
4641
|
+
disabled: busy || saving || settingsScope?.getSnapshot().writable !== true || Object.keys(activeContextBudgets).length === 0,
|
|
4642
|
+
title: t("row.contextAllDefaultHint"),
|
|
4643
|
+
onClick: resetAllContextBudgets,
|
|
4644
|
+
children: t("row.contextAllDefault")
|
|
4645
|
+
})]
|
|
4646
|
+
}),
|
|
4690
4647
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4691
4648
|
className: "dsm-trae-model-capability-note",
|
|
4692
4649
|
children: t("row.modelCapabilityPending")
|
|
@@ -5603,12 +5560,12 @@ window.__ModuleLoader__.load({
|
|
|
5603
5560
|
"row.expiryWarningWeek": "{total} credit lapses within 7 days ({packs} packs)",
|
|
5604
5561
|
"row.expiryWarningLapsed": "{total} credit has already lapsed but is still counted in the balance ({packs} packs)",
|
|
5605
5562
|
"row.expiryEarliest": "Earliest: {time}",
|
|
5606
|
-
"row.appLoginMismatch": "Trae is signed in to {account}, but this plugin is bound to {bound}.",
|
|
5607
|
-
"row.appLoginFollow": "Use {account}",
|
|
5608
|
-
"row.followAppLogin": "Follow the account Trae is signed in to",
|
|
5609
|
-
"row.followAppLoginHint": "Rebind automatically when you switch accounts in the Trae desktop app. Off by default, so the current binding is kept.",
|
|
5610
5563
|
"row.settingsDirty": "Unsaved changes",
|
|
5611
5564
|
"row.modelsTestEmpty": "Enable at least one model first.",
|
|
5565
|
+
"row.contextAllMax": "Switch all to Max",
|
|
5566
|
+
"row.contextAllMaxHint": "Sets the DSH context budget of every model in this region that has a Max window to its Max window at once. Still a draft — press Save to apply. Models without a Max window are left alone.",
|
|
5567
|
+
"row.contextAllDefault": "Restore default context",
|
|
5568
|
+
"row.contextAllDefaultHint": "Clears every context-budget override in this region, so all models go back to Trae's default window. Still a draft — press Save to apply.",
|
|
5612
5569
|
"row.modelsTestError": "Test failed: {message}",
|
|
5613
5570
|
"row.modelsTestDone": "{available} of {total} answered.",
|
|
5614
5571
|
"row.probeAvailable": "works",
|
|
@@ -5654,8 +5611,6 @@ window.__ModuleLoader__.load({
|
|
|
5654
5611
|
"row.poolCreditExpiry": "expires {when}",
|
|
5655
5612
|
"row.poolProbeMeasured": "measured {when}",
|
|
5656
5613
|
"row.poolProbeAt": "tested {when}",
|
|
5657
|
-
"row.poolMirrorWorkflowTitle": "Sign in one account, then refresh",
|
|
5658
|
-
"row.poolMirrorWorkflowHint": "The Trae app holds only one sign-in. After signing in to an account, refresh this card (or click “Detect accounts again”) so the plugin saves that login as its own copy. Switch accounts without refreshing and the previous login is not saved — the new one overwrites it in Trae.",
|
|
5659
5614
|
"row.poolSettingsNote": "Preferences below take effect when you save; test results are written by the plugin and are not affected by that button.",
|
|
5660
5615
|
"row.poolSelectedCount": "Selected {count} / {total}",
|
|
5661
5616
|
"row.poolNoCopyTag": "no copy here",
|
|
@@ -5925,12 +5880,12 @@ window.__ModuleLoader__.load({
|
|
|
5925
5880
|
"row.expiryWarningWeek": "有 {total} 积分将在 7 天内过期({packs} 个套餐)",
|
|
5926
5881
|
"row.expiryWarningLapsed": "有 {total} 积分已过期但仍计入余额({packs} 个套餐)",
|
|
5927
5882
|
"row.expiryEarliest": "最早到期:{time}",
|
|
5928
|
-
"row.appLoginMismatch": "Trae 已登录 {account},但本插件绑定的是 {bound}。",
|
|
5929
|
-
"row.appLoginFollow": "改用 {account}",
|
|
5930
|
-
"row.followAppLogin": "跟随 Trae 当前登录的账号",
|
|
5931
|
-
"row.followAppLoginHint": "在 Trae 桌面端切换登录后自动换绑到新账号。默认关闭,已有绑定保持不变。",
|
|
5932
5883
|
"row.settingsDirty": "有未保存的修改",
|
|
5933
5884
|
"row.modelsTestEmpty": "请先启用至少一个模型。",
|
|
5885
|
+
"row.contextAllMax": "整区切到 Max",
|
|
5886
|
+
"row.contextAllMaxHint": "把本区所有带 Max 档的模型的 DSH 上下文预算一次性设为各自的 Max 档。这只是草稿——要按「保存」才生效。没有 Max 档的模型不会被改动。",
|
|
5887
|
+
"row.contextAllDefault": "全部恢复默认上下文",
|
|
5888
|
+
"row.contextAllDefaultHint": "清掉本区所有上下文预算覆盖,让每个模型都回到 Trae 的默认窗口。这只是草稿——要按「保存」才生效。",
|
|
5934
5889
|
"row.modelsTestError": "测试失败:{message}",
|
|
5935
5890
|
"row.modelsTestDone": "{total} 个里有 {available} 个正常应答。",
|
|
5936
5891
|
"row.probeAvailable": "可用",
|
|
@@ -5976,8 +5931,6 @@ window.__ModuleLoader__.load({
|
|
|
5976
5931
|
"row.poolCreditExpiry": "{when} 过期",
|
|
5977
5932
|
"row.poolProbeMeasured": "测得 {when}",
|
|
5978
5933
|
"row.poolProbeAt": "测试于 {when}",
|
|
5979
|
-
"row.poolMirrorWorkflowTitle": "每登录一个账号,就刷新一次",
|
|
5980
|
-
"row.poolMirrorWorkflowHint": "Trae 应用只有一个登录位:每登录一个账号,就回到这里刷新一次(打开卡片或点「重新检测账号」),插件会把这次登录保存成一份自己的副本。没刷新就换号,上一个账号不会被保存——它会被 Trae 里的新登录覆盖。",
|
|
5981
5934
|
"row.poolSettingsNote": "下面是偏好设置:点保存才生效;测试结果由插件自动写入,不受这个保存按钮影响。",
|
|
5982
5935
|
"row.poolSelectedCount": "已选 {count} / {total}",
|
|
5983
5936
|
"row.poolNoCopyTag": "本机无副本",
|
package/lib/index.d.ts
CHANGED
|
@@ -833,24 +833,6 @@ interface TraeWebAccount {
|
|
|
833
833
|
refreshExpiresAtMs?: number;
|
|
834
834
|
selected: boolean;
|
|
835
835
|
}
|
|
836
|
-
/**
|
|
837
|
-
* The account the Trae desktop app is signed in to right now, when it differs
|
|
838
|
-
* from the one this plugin is bound to (issue #29).
|
|
839
|
-
*
|
|
840
|
-
* Reported on the usage document so the card can offer one-click follow without
|
|
841
|
-
* an extra round trip; also written back on a POST to the accounts refresh
|
|
842
|
-
* route when the client confirms it saw the hint. Absent whenever the two
|
|
843
|
-
* agree or the app is not readable — a healthy document carries no extra
|
|
844
|
-
* fields and the plugin never bills from this value directly: the FOLLOW is a
|
|
845
|
-
* settings write of `accounts.<region>`, made by the card or by the host's
|
|
846
|
-
* follow switch, never a silent rebind here.
|
|
847
|
-
*/
|
|
848
|
-
interface TraeWebAppLogin {
|
|
849
|
-
id: string;
|
|
850
|
-
accountName: string;
|
|
851
|
-
edition: 'cn' | 'sg' | 'solo' | 'solo-sg';
|
|
852
|
-
region: TraeRegion;
|
|
853
|
-
}
|
|
854
836
|
/**
|
|
855
837
|
* The per-account state shown inside an account row of the card's table.
|
|
856
838
|
*
|
|
@@ -931,18 +913,6 @@ declare function unwrapVolatileDeep<T>(value: T): T;
|
|
|
931
913
|
* function into the settings document.
|
|
932
914
|
*/
|
|
933
915
|
declare function configuredAccountsOf(configured: unknown): Record<string, string>;
|
|
934
|
-
/**
|
|
935
|
-
* Whether the host-side "follow the Trae app's sign-in" switch is on (issue
|
|
936
|
-
* #29). Absent reads as OFF, so an existing configuration keeps the strict
|
|
937
|
-
* bind it shipped with and the switch is an opt-in — the same opt-out
|
|
938
|
-
* semantics as {@link regionEnabledOf}, for the same reason: a config written
|
|
939
|
-
* before this field existed cannot ask for behavior it never declared.
|
|
940
|
-
*
|
|
941
|
-
* Reads the whole settings section (or the bare field); deep-unwraps first
|
|
942
|
-
* because on DSH 0.1.7 a volatile field arrives as a `{get(): T}` live
|
|
943
|
-
* reference, whose `typeof === 'object'` would otherwise pass a naive check.
|
|
944
|
-
*/
|
|
945
|
-
declare function followAppLoginEnabled(configured: unknown): boolean;
|
|
946
916
|
/**
|
|
947
917
|
* Build the next `regions` settings value for the card's save. The write
|
|
948
918
|
* targets ONLY the signed-in account's region slot; every other region's slot
|
|
@@ -1094,15 +1064,6 @@ type TraeWebUsage = {
|
|
|
1094
1064
|
* other case so a healthy account never pays for the extra read.
|
|
1095
1065
|
*/
|
|
1096
1066
|
alternatives?: readonly TraeWebCreditAlternative[];
|
|
1097
|
-
/**
|
|
1098
|
-
* Present only when the Trae app's CURRENT sign-in differs from the
|
|
1099
|
-
* account this plugin is bound to (issue #29): the card then offers a
|
|
1100
|
-
* one-click follow instead of making the user hunt the account dropdown
|
|
1101
|
-
* after every app-side sign-out. Absent in every other case — a healthy
|
|
1102
|
-
* document costs no extra read beyond the accounts scan the document
|
|
1103
|
-
* already runs.
|
|
1104
|
-
*/
|
|
1105
|
-
appLogin?: TraeWebAppLogin;
|
|
1106
1067
|
/**
|
|
1107
1068
|
* Daily check-in state (CN only). Absent on the international region,
|
|
1108
1069
|
* whose check-in surface does not exist — probed 2026-09-24: the
|
|
@@ -1759,18 +1720,6 @@ declare class TraeCredentialStore {
|
|
|
1759
1720
|
* the plugin performed is never discarded by this preference.
|
|
1760
1721
|
*/
|
|
1761
1722
|
private preferred;
|
|
1762
|
-
/**
|
|
1763
|
-
* The account the Trae app is signed in to right now, when that differs from
|
|
1764
|
-
* the account this store is bound to (issue #29).
|
|
1765
|
-
*
|
|
1766
|
-
* This is a READ, not a rebind: `current()` keeps resolving the bound
|
|
1767
|
-
* account verbatim so billing never moves without a decision — the store
|
|
1768
|
-
* only reports the mismatch, and the card (hint row) or the host (follow
|
|
1769
|
-
* switch) turns it into a settings write the user can see and undo. Absent
|
|
1770
|
-
* when nothing is live, when the live account IS the bound one, or when the
|
|
1771
|
-
* binding itself already fell through to the live account.
|
|
1772
|
-
*/
|
|
1773
|
-
liveLogin(): Promise<TraeAccountChoice | undefined>;
|
|
1774
1723
|
/**
|
|
1775
1724
|
* The accounts this store is willing to OFFER.
|
|
1776
1725
|
*
|
|
@@ -3398,14 +3347,6 @@ interface TraeUsageRouteOptions {
|
|
|
3398
3347
|
claim: TraeCheckinClaim;
|
|
3399
3348
|
checkin: TraeCheckinStatus;
|
|
3400
3349
|
} | undefined>;
|
|
3401
|
-
/**
|
|
3402
|
-
* The account the Trae app is signed in to right now, when it differs from
|
|
3403
|
-
* the bound one (issue #29). Optional: absent means the card's follow hint
|
|
3404
|
-
* simply is not offered (a test harness or a host without the store's scan).
|
|
3405
|
-
* Read-only — the HOST never rebinds from this value; the follow is a
|
|
3406
|
-
* settings write, made by the card or by the host's follow switch.
|
|
3407
|
-
*/
|
|
3408
|
-
liveLogin?(panel: TraePanel): Promise<TraeWebAppLogin | undefined>;
|
|
3409
3350
|
/** The requested region's last-refreshed raw directory (one entry per upstream model). */
|
|
3410
3351
|
displayModels(panel: TraePanel): readonly TraeModelInfo[];
|
|
3411
3352
|
/** The user's model selection in the requested panel, stored as model id (= Trae name). */
|
|
@@ -3674,26 +3615,6 @@ interface Config {
|
|
|
3674
3615
|
* settings form can both read and write it.
|
|
3675
3616
|
*/
|
|
3676
3617
|
showPointsInMainUi?: boolean;
|
|
3677
|
-
/**
|
|
3678
|
-
* Follow the Trae desktop app's CURRENT sign-in instead of staying bound to
|
|
3679
|
-
* the account the user (or the default) picked earlier (issue #29).
|
|
3680
|
-
*
|
|
3681
|
-
* When the app switches accounts, the old binding kept billing the previous
|
|
3682
|
-
* account forever while `dsh-connect-workbuddy` followed the app
|
|
3683
|
-
* automatically — every Trae sign-out then needed a manual switch here. With
|
|
3684
|
-
* this switch ON, each settings re-apply rebinds `accounts.<region>` to
|
|
3685
|
-
* whatever the app is signed in to right now (the live login outranks the
|
|
3686
|
-
* plugin's own refreshed copies, see `TraeCredentialStore.preferred`).
|
|
3687
|
-
*
|
|
3688
|
-
* OFF by default: an existing configuration keeps the strict bind it
|
|
3689
|
-
* shipped with, because silently switching billing accounts is exactly what
|
|
3690
|
-
* `current()`'s no-fallback rule exists to prevent — the user opts in. When
|
|
3691
|
-
* OFF, the card still shows a one-click hint (its own settings write), so
|
|
3692
|
-
* the report in #29 is solved on both paths without any behavior change
|
|
3693
|
-
* nobody asked for. Declared volatile so the card's switch can read and
|
|
3694
|
-
* write it on the 0.1.7 settings form.
|
|
3695
|
-
*/
|
|
3696
|
-
followAppLogin?: boolean;
|
|
3697
3618
|
/**
|
|
3698
3619
|
* Per-region model state, keyed `cn` | `ai`. The CN and international apps
|
|
3699
3620
|
* expose different rosters, so each keeps its own directory and selection
|
|
@@ -3776,4 +3697,4 @@ declare function asVolatile<S>(schema: S): S;
|
|
|
3776
3697
|
declare const Config: z<Config>;
|
|
3777
3698
|
declare function apply(ctx: Context$1, config: Config): void;
|
|
3778
3699
|
//#endregion
|
|
3779
|
-
export { Config, FALLBACK_TRAE_MODELS, FALLBACK_TRAE_MODELS_AI, MAX_PROBE_INPUT_TOKENS, type PiAiGeneration, type PiAiRuntimeInfo, REGION_GATEWAYS, type RawChatDelta, type RawChatMessage, type RawChatTool, SseDecoder, type SseEvent, TRAE_ACCOUNT_STATUS_PATH, TRAE_AI_PROVIDER, TRAE_CHECKIN_PATH, TRAE_CN_AGENT_TASK_PATH, TRAE_CN_TITLE_PATH, TRAE_ENTERPRISE_PROVIDER, TRAE_MODELS_TEST_PATH, TRAE_MODEL_DETAIL_FUNCTIONS, TRAE_MODEL_DETAIL_PATH, TRAE_PANELS, TRAE_PAY_BASE, TRAE_PROBE_TIMEOUT_MS, TRAE_PROVIDER, TRAE_PROVIDERS, TRAE_PROVIDER_DISPLAY_NAMES, TRAE_PROVIDER_IDS, TRAE_PROVIDER_ID_DISPLAY_NAMES, TRAE_PROVIDER_ROUTES, TRAE_RAW_CHAT_V1_PATH, TRAE_RAW_CHAT_V2_PATH, TRAE_REASONING_EFFORTS, TRAE_REGIONS, TRAE_REGION_PARAM, TRAE_SETTINGS_NS, TRAE_SOLO_CHAT_PATH, TRAE_SOLO_FUNCTION, TRAE_SOLO_MODELS_PATH, TRAE_SOLO_REMOTE_BASE, TRAE_STATE_DB_FILENAME, TRAE_STREAM_IDLE_TIMEOUT_MS, TRAE_USAGE_PATH, TRAE_VERSION_CODE_FALLBACK, type TraeActivityRule, type TraeAdapter, type TraeCachedModelConfig, TraeCatalog, type TraeChatResult, type TraeCheckinClaim, type TraeCheckinStatus, type TraeContextBudget, type TraeCredential, TraeCredentialStore, TraeDelegatingUpstreamClient, type TraeDiscoveredModel, type TraeDiscoveredReasoning, type TraeEdition, type TraeFailure, TraeFallbackUpstreamClient, type TraeFallbackUpstreamOptions, type TraeFusionRawChatEnvelope, TraeGatedUpstreamClient, type TraeGatedUpstreamOptions, type TraeIdentity, type TraeInputModality, type TraeModelDetailRequest, type TraeModelInfo, type TraeModelProbeVerdict, type TraeModelsTestResponse, type TraeObservedModelConfig, type TraePanel, type TraeProbeResult, type TraeProbeVerdict, type TraeProviderRoute, TraeRawCapabilityController, type TraeRawCapabilityControllerOptions, type TraeRawCapabilitySnapshot, TraeRawCapabilityState, type TraeRawChatBehaviorConfig, type TraeRawChatCapability, type TraeRawChatClientOptions, type TraeRawChatConfig, type TraeRawChatFailureReason, type TraeRawChatRuntimeConfig, TraeRawChatUpstreamClient, type TraeRawDiagnostic, type TraeRawDiagnosticState, type TraeRawGateway, type TraeRawGatewayOptions, type TraeRawResolverResult, type TraeReasoningCapability, type TraeReasoningEffort, type TraeRefreshDevice, type TraeRegion, type TraeRegionGateways, TraeRegionState, type TraeShim, TraeSoloBridge, type TraeSoloClientOptions, TraeSoloRemoteCatalogClient, type TraeSoloRemoteCatalogOptions, TraeSoloUpstreamClient, type TraeStorageCandidate, type TraeStreamEvent, type TraeUpstreamClient, TraeUsageClient, type TraeUsageOptions, type TraeUsagePack, type TraeUsageRouteOptions, type TraeUsageSnapshot, type TraeUsageSummary, type TraeUsageView, type TraeWebAccountState, type TraeWebActivity, type
|
|
3700
|
+
export { Config, FALLBACK_TRAE_MODELS, FALLBACK_TRAE_MODELS_AI, MAX_PROBE_INPUT_TOKENS, type PiAiGeneration, type PiAiRuntimeInfo, REGION_GATEWAYS, type RawChatDelta, type RawChatMessage, type RawChatTool, SseDecoder, type SseEvent, TRAE_ACCOUNT_STATUS_PATH, TRAE_AI_PROVIDER, TRAE_CHECKIN_PATH, TRAE_CN_AGENT_TASK_PATH, TRAE_CN_TITLE_PATH, TRAE_ENTERPRISE_PROVIDER, TRAE_MODELS_TEST_PATH, TRAE_MODEL_DETAIL_FUNCTIONS, TRAE_MODEL_DETAIL_PATH, TRAE_PANELS, TRAE_PAY_BASE, TRAE_PROBE_TIMEOUT_MS, TRAE_PROVIDER, TRAE_PROVIDERS, TRAE_PROVIDER_DISPLAY_NAMES, TRAE_PROVIDER_IDS, TRAE_PROVIDER_ID_DISPLAY_NAMES, TRAE_PROVIDER_ROUTES, TRAE_RAW_CHAT_V1_PATH, TRAE_RAW_CHAT_V2_PATH, TRAE_REASONING_EFFORTS, TRAE_REGIONS, TRAE_REGION_PARAM, TRAE_SETTINGS_NS, TRAE_SOLO_CHAT_PATH, TRAE_SOLO_FUNCTION, TRAE_SOLO_MODELS_PATH, TRAE_SOLO_REMOTE_BASE, TRAE_STATE_DB_FILENAME, TRAE_STREAM_IDLE_TIMEOUT_MS, TRAE_USAGE_PATH, TRAE_VERSION_CODE_FALLBACK, type TraeActivityRule, type TraeAdapter, type TraeCachedModelConfig, TraeCatalog, type TraeChatResult, type TraeCheckinClaim, type TraeCheckinStatus, type TraeContextBudget, type TraeCredential, TraeCredentialStore, TraeDelegatingUpstreamClient, type TraeDiscoveredModel, type TraeDiscoveredReasoning, type TraeEdition, type TraeFailure, TraeFallbackUpstreamClient, type TraeFallbackUpstreamOptions, type TraeFusionRawChatEnvelope, TraeGatedUpstreamClient, type TraeGatedUpstreamOptions, type TraeIdentity, type TraeInputModality, type TraeModelDetailRequest, type TraeModelInfo, type TraeModelProbeVerdict, type TraeModelsTestResponse, type TraeObservedModelConfig, type TraePanel, type TraeProbeResult, type TraeProbeVerdict, type TraeProviderRoute, TraeRawCapabilityController, type TraeRawCapabilityControllerOptions, type TraeRawCapabilitySnapshot, TraeRawCapabilityState, type TraeRawChatBehaviorConfig, type TraeRawChatCapability, type TraeRawChatClientOptions, type TraeRawChatConfig, type TraeRawChatFailureReason, type TraeRawChatRuntimeConfig, TraeRawChatUpstreamClient, type TraeRawDiagnostic, type TraeRawDiagnosticState, type TraeRawGateway, type TraeRawGatewayOptions, type TraeRawResolverResult, type TraeReasoningCapability, type TraeReasoningEffort, type TraeRefreshDevice, type TraeRegion, type TraeRegionGateways, TraeRegionState, type TraeShim, TraeSoloBridge, type TraeSoloClientOptions, TraeSoloRemoteCatalogClient, type TraeSoloRemoteCatalogOptions, TraeSoloUpstreamClient, type TraeStorageCandidate, type TraeStreamEvent, type TraeUpstreamClient, TraeUsageClient, type TraeUsageOptions, type TraeUsagePack, type TraeUsageRouteOptions, type TraeUsageSnapshot, type TraeUsageSummary, type TraeUsageView, type TraeWebAccountState, type TraeWebActivity, type TraeWebCheckin, type TraeWebCheckinClaim, type TraeWebCredits, type TraeWebUsage, type TraeWireModel, type TraeWireTarget, UnconfiguredTraeUpstreamClient, adaptLegacyPiAiContext, adaptModernPiAiContext, apply, applyContextBudgets, applyImageSelection, applyReasoningEffort, asVolatile, bridgeTraeSoloStream, buildTraeAgentTaskBody, buildTraeCnHeaders, buildTraeFusionRawChatEnvelope, buildTraeModelDetailRequest, buildTraeRawChatDraft, buildTraeRawChatRuntimeConfig, classifyProbeError, classifyProbeResult, classifyTraeRawChatFailure, configuredAccountsOf, createTraeAdapter, createTraeRawGateway, createTraeShim, creditPosition, decidePiAiGeneration, decodeRawChatChunk, decodeTraeEvent, decryptTraeStorageValue, deriveCatalog, describeIdShape, describeNameShape, describeTraeFailure, discoveredCatalog, displayNameOfTraeProvider, fallbackModelsFor, generationOf, hashTraeRawChatArg, identityHeaders, inject, isEnterpriseAccount, legacyTraeOwnAuthPath, maskUserPath, mergeTraeModelSources, name, nextRegionCreditPosition, nextRegionEnabled, nextRegionSlots, normalizeTraeCredential, normalizeTraeVersionCode, panelOfKey, panelOfProvider, parseObservedModelConfig, parseReasoningCapability, parseTraeAuthValue, parseTraeCachedModel, parseTraeModelExtraConfigLogLine, parseTraeRawChatBehaviorConfig, parseTraeRemoteModel, parseTraeStorageDocument, piAiRuntimeInfo, pickTraeStorageIdentity, prepareSoloBody, probeBody, probeModelsSequentially, probeOneModel, probeTraeRawChatCapability, providerOfPanel, rawCapabilityDiagnostic, rawCapabilityFingerprint, readTraeCachedModel, readTraeCliIdentity, readTraeIdentity, refreshTraeCredential, regionCreditPositionOf, regionEnabled, regionEnabledOf, regionOfCredential, regionOfEdition, regionOfHost, regionOfPanel, regionOfTraeProvider, regionOfTraeStatusUrl, regionOfUserRegion, regionStateOf, registerTraeUsageRoute, resolveTraeIdentity, resolveTraeRawRuntime, routeOfTraeProvider, sanitizeCatalog, settingsNamespaceOf, traeEndpoint, traeInputModalities, traeModelDisplayName, traeOwnAuthPath, traeRawChatExtraInfo, traeStateDatabaseCandidates, traeStorageCandidates, traeWebUsage, traeWindowsAppNames, unwrapVolatile, unwrapVolatileDeep, wireTargetsOf, withContextAdaptation, withTraeRegion };
|
package/lib/index.js
CHANGED
|
@@ -242,6 +242,7 @@ function mergeTraeModelSources(remote, wire) {
|
|
|
242
242
|
...model.maxContextWindow === void 0 ? {} : { maxContextWindow: model.maxContextWindow },
|
|
243
243
|
...creditMultiplier === void 0 ? {} : { creditMultiplier },
|
|
244
244
|
input: ["text"],
|
|
245
|
+
...wireModel?.maxTokens === void 0 ? {} : { maxTokens: wireModel.maxTokens },
|
|
245
246
|
...model.multimodal === void 0 ? {} : { multimodal: model.multimodal },
|
|
246
247
|
reasoningSupported: model.reasoningSupported,
|
|
247
248
|
...model.reasoning === void 0 ? {} : {
|
|
@@ -1161,20 +1162,6 @@ function configuredAccountsOf(configured) {
|
|
|
1161
1162
|
return typeof accounts === "object" && accounts !== null ? accounts : {};
|
|
1162
1163
|
}
|
|
1163
1164
|
/**
|
|
1164
|
-
* Whether the host-side "follow the Trae app's sign-in" switch is on (issue
|
|
1165
|
-
* #29). Absent reads as OFF, so an existing configuration keeps the strict
|
|
1166
|
-
* bind it shipped with and the switch is an opt-in — the same opt-out
|
|
1167
|
-
* semantics as {@link regionEnabledOf}, for the same reason: a config written
|
|
1168
|
-
* before this field existed cannot ask for behavior it never declared.
|
|
1169
|
-
*
|
|
1170
|
-
* Reads the whole settings section (or the bare field); deep-unwraps first
|
|
1171
|
-
* because on DSH 0.1.7 a volatile field arrives as a `{get(): T}` live
|
|
1172
|
-
* reference, whose `typeof === 'object'` would otherwise pass a naive check.
|
|
1173
|
-
*/
|
|
1174
|
-
function followAppLoginEnabled(configured) {
|
|
1175
|
-
return unwrapVolatileDeep(configured)?.followAppLogin === true;
|
|
1176
|
-
}
|
|
1177
|
-
/**
|
|
1178
1165
|
* Build the next `regions` settings value for the card's save. The write
|
|
1179
1166
|
* targets ONLY the signed-in account's region slot; every other region's slot
|
|
1180
1167
|
* is carried over untouched, so switching accounts never clobbers the other
|
|
@@ -2364,36 +2351,6 @@ var TraeCredentialStore = class {
|
|
|
2364
2351
|
return eligible.find((credential) => credential.source === "desktop") ?? eligible[0];
|
|
2365
2352
|
}
|
|
2366
2353
|
/**
|
|
2367
|
-
* The account the Trae app is signed in to right now, when that differs from
|
|
2368
|
-
* the account this store is bound to (issue #29).
|
|
2369
|
-
*
|
|
2370
|
-
* This is a READ, not a rebind: `current()` keeps resolving the bound
|
|
2371
|
-
* account verbatim so billing never moves without a decision — the store
|
|
2372
|
-
* only reports the mismatch, and the card (hint row) or the host (follow
|
|
2373
|
-
* switch) turns it into a settings write the user can see and undo. Absent
|
|
2374
|
-
* when nothing is live, when the live account IS the bound one, or when the
|
|
2375
|
-
* binding itself already fell through to the live account.
|
|
2376
|
-
*/
|
|
2377
|
-
async liveLogin() {
|
|
2378
|
-
if (this.accountId === void 0 || this.accountId === "") return void 0;
|
|
2379
|
-
const credentials = await this.readAll();
|
|
2380
|
-
const live = this.preferred(credentials);
|
|
2381
|
-
if (live === void 0) return void 0;
|
|
2382
|
-
const liveId = traeAccountId(live);
|
|
2383
|
-
if (liveId === this.accountId) return void 0;
|
|
2384
|
-
return {
|
|
2385
|
-
id: liveId,
|
|
2386
|
-
accountName: live.accountName ?? (live.userId || `${live.edition} account`),
|
|
2387
|
-
edition: live.edition,
|
|
2388
|
-
enterprise: isEnterpriseAccount(live),
|
|
2389
|
-
region: regionOfCredential(live),
|
|
2390
|
-
source: live.source,
|
|
2391
|
-
tokenExpiresAtMs: live.expiresAtMs,
|
|
2392
|
-
...live.refreshExpiresAtMs === void 0 ? {} : { refreshExpiresAtMs: live.refreshExpiresAtMs },
|
|
2393
|
-
selected: false
|
|
2394
|
-
};
|
|
2395
|
-
}
|
|
2396
|
-
/**
|
|
2397
2354
|
* The accounts this store is willing to OFFER.
|
|
2398
2355
|
*
|
|
2399
2356
|
* Scoped to who this store may bill:
|
|
@@ -6915,10 +6872,6 @@ async function traeWebUsage(deps, panel, options = {}) {
|
|
|
6915
6872
|
message: safeMessage(error)
|
|
6916
6873
|
};
|
|
6917
6874
|
}
|
|
6918
|
-
let appLogin;
|
|
6919
|
-
try {
|
|
6920
|
-
appLogin = await deps.liveLogin?.(panel);
|
|
6921
|
-
} catch {}
|
|
6922
6875
|
const account = {
|
|
6923
6876
|
accountId: accounts.find((item) => item.selected)?.id ?? "",
|
|
6924
6877
|
accountName: credential.accountName ?? credential.userId,
|
|
@@ -6927,7 +6880,6 @@ async function traeWebUsage(deps, panel, options = {}) {
|
|
|
6927
6880
|
region: regionOfPanel(panel),
|
|
6928
6881
|
enabled,
|
|
6929
6882
|
accounts,
|
|
6930
|
-
...appLogin === void 0 ? {} : { appLogin },
|
|
6931
6883
|
models: deps.displayModels(panel).map((model) => ({
|
|
6932
6884
|
...model,
|
|
6933
6885
|
...model.input === void 0 ? {} : { input: [...model.input] }
|
|
@@ -8575,7 +8527,6 @@ const Config = z.object({
|
|
|
8575
8527
|
]).default("auto").description("Trae edition hint")),
|
|
8576
8528
|
accountId: z.string().description("Deprecated: pre-split account selector, attributed to its own region"),
|
|
8577
8529
|
showPointsInMainUi: asVolatile(z.boolean().default(false).description("在输入框工具栏显示积分读数「Trae CN · <数值>」(仅当选中的模型属于本插件时出现,可点击查看账号与积分明细)")),
|
|
8578
|
-
followAppLogin: asVolatile(z.boolean().default(false).description("跟随 Trae 桌面端当前登录账号换绑(打开后每次配置生效时重绑到 App 现在登录的账号)")),
|
|
8579
8530
|
accounts: asVolatile(accountSelectionConfig.description("Per-panel account selections, keyed cn | enterprise | ai")),
|
|
8580
8531
|
regions: asVolatile(z.dict(regionStateConfig).default({}).description("Per-panel model directory and selection, keyed cn | enterprise | ai")),
|
|
8581
8532
|
lastCatalog: z.array(modelConfig).description("Deprecated: pre-region-split CN model directory"),
|
|
@@ -9437,50 +9388,6 @@ function apply(ctx, config) {
|
|
|
9437
9388
|
}
|
|
9438
9389
|
};
|
|
9439
9390
|
};
|
|
9440
|
-
/**
|
|
9441
|
-
* The app's current sign-in when it differs from the bound account (issue
|
|
9442
|
-
* #29). Pure read: the store resolves the bound account verbatim, so billing
|
|
9443
|
-
* never moves from here — the card's hint and the follow switch below are
|
|
9444
|
-
* the only writers.
|
|
9445
|
-
*/
|
|
9446
|
-
const liveLoginOf = async (panel) => {
|
|
9447
|
-
const region = regionOfPanel(panel);
|
|
9448
|
-
try {
|
|
9449
|
-
const live = await stacks[panel].store.liveLogin();
|
|
9450
|
-
if (live === void 0 || live.region !== region) return void 0;
|
|
9451
|
-
return {
|
|
9452
|
-
id: live.id,
|
|
9453
|
-
accountName: live.accountName,
|
|
9454
|
-
edition: live.edition,
|
|
9455
|
-
region: live.region
|
|
9456
|
-
};
|
|
9457
|
-
} catch {
|
|
9458
|
-
return;
|
|
9459
|
-
}
|
|
9460
|
-
};
|
|
9461
|
-
/**
|
|
9462
|
-
* Persist `accounts.<region>` = the app's live sign-in and rebind the store
|
|
9463
|
-
* (issue #29). The ONE Host-side path that moves the binding, driven by the
|
|
9464
|
-
* follow switch in {@link maybeFollowAppLogin}; the card's one-click hint
|
|
9465
|
-
* goes through its own settings write instead (one writer per path). Returns
|
|
9466
|
-
* the applied login so the caller can report what moved.
|
|
9467
|
-
*
|
|
9468
|
-
* The write goes through `settings.update` (the volatile write gate), not a
|
|
9469
|
-
* direct config mutation: `apply()` receives a snapshot, and the settings
|
|
9470
|
-
* event (`loader/volatile-update`) is what re-runs `applySelection` with the
|
|
9471
|
-
* updated document — the same channel every card write already uses.
|
|
9472
|
-
*/
|
|
9473
|
-
const followAppLogin = async (panel) => {
|
|
9474
|
-
const live = await liveLoginOf(panel);
|
|
9475
|
-
if (live === void 0 || writeSettings === void 0) return void 0;
|
|
9476
|
-
const configured = configuredAccountsOf(current());
|
|
9477
|
-
if (configured[panel] === live.id) return live;
|
|
9478
|
-
await writeSettings({ accounts: {
|
|
9479
|
-
...configured,
|
|
9480
|
-
[panel]: live.id
|
|
9481
|
-
} });
|
|
9482
|
-
return live;
|
|
9483
|
-
};
|
|
9484
9391
|
ctx.inject(["webServer"], (webCtx) => registerTraeUsageRoute(webCtx, {
|
|
9485
9392
|
store: (panel) => stacks[panel].store,
|
|
9486
9393
|
client: (panel) => stacks[panel].usageClient,
|
|
@@ -9501,7 +9408,6 @@ function apply(ctx, config) {
|
|
|
9501
9408
|
}),
|
|
9502
9409
|
accountStateOf: (panel, accountId) => stacks[panel].accountStateOf(accountId),
|
|
9503
9410
|
claimCheckinOf: (panel, accountId) => stacks[panel].claimCheckinOf(accountId),
|
|
9504
|
-
liveLogin: (panel) => liveLoginOf(panel),
|
|
9505
9411
|
pool: {
|
|
9506
9412
|
preferences: (panel) => poolPreferencesOf(panel),
|
|
9507
9413
|
members: (panel) => poolMembersOf(panel),
|
|
@@ -9627,59 +9533,13 @@ function apply(ctx, config) {
|
|
|
9627
9533
|
}
|
|
9628
9534
|
} catch {}
|
|
9629
9535
|
})();
|
|
9630
|
-
let writeSettings;
|
|
9631
9536
|
ctx.inject(["settings"], (settingsCtx) => {
|
|
9632
9537
|
const settings = settingsCtx.settings;
|
|
9633
9538
|
ctx.effect(() => settings.configure({ auto: true }, ctx.fiber));
|
|
9634
|
-
writeSettings = async (patch) => {
|
|
9635
|
-
const revision = () => settings.describe().find((entry) => entry.ns === settingsNs)?.revision;
|
|
9636
|
-
const conflict = (error) => typeof error === "object" && error !== null && error.code === "SETTINGS_CONFLICT";
|
|
9637
|
-
try {
|
|
9638
|
-
await settings.update(settingsNs, patch, revision());
|
|
9639
|
-
} catch (error) {
|
|
9640
|
-
if (!conflict(error)) throw error;
|
|
9641
|
-
await settings.update(settingsNs, patch, revision());
|
|
9642
|
-
}
|
|
9643
|
-
};
|
|
9644
|
-
ctx.effect(() => () => {
|
|
9645
|
-
writeSettings = void 0;
|
|
9646
|
-
});
|
|
9647
9539
|
});
|
|
9648
9540
|
ctx.on("loader/volatile-update", () => {
|
|
9649
9541
|
applySelection(current());
|
|
9650
|
-
maybeFollowAppLogin();
|
|
9651
9542
|
});
|
|
9652
|
-
/**
|
|
9653
|
-
* Follow the app's sign-in on every settings change when the switch is ON
|
|
9654
|
-
* (issue #29). Runs AFTER `applySelection` so this pass binds the previous
|
|
9655
|
-
* document, reads the app's live login against it, and — if they differ —
|
|
9656
|
-
* writes `accounts.<region>` once; that write emits `volatile-update` again,
|
|
9657
|
-
* which re-runs `applySelection` on the NEW document. The loop terminates on
|
|
9658
|
-
* its own the moment `liveLogin()` reports no mismatch (the second pass binds
|
|
9659
|
-
* the live account, so `preferred` and `current` agree). The guard below
|
|
9660
|
-
* additionally forbids two writes in flight, so a stuck mismatch can never
|
|
9661
|
-
* turn into a write storm: the next settings change retries from scratch.
|
|
9662
|
-
*
|
|
9663
|
-
* The switch reads FALSE for an existing config (see {@link Config}), so a
|
|
9664
|
-
* user who never opted in never gets a rebind — the card's one-click hint is
|
|
9665
|
-
* their path instead.
|
|
9666
|
-
*/
|
|
9667
|
-
let followInFlight = false;
|
|
9668
|
-
const maybeFollowAppLogin = async () => {
|
|
9669
|
-
if (followInFlight || !followAppLoginEnabled(current())) return;
|
|
9670
|
-
followInFlight = true;
|
|
9671
|
-
try {
|
|
9672
|
-
for (const panel of TRAE_PANELS) {
|
|
9673
|
-
if (!regionEnabled(current(), panel)) continue;
|
|
9674
|
-
await followAppLogin(panel);
|
|
9675
|
-
}
|
|
9676
|
-
} catch (error) {
|
|
9677
|
-
ctx.logger.warn("dsh-connect-trae: follow-app-login rebind skipped", error);
|
|
9678
|
-
} finally {
|
|
9679
|
-
followInFlight = false;
|
|
9680
|
-
}
|
|
9681
|
-
};
|
|
9682
|
-
maybeFollowAppLogin();
|
|
9683
9543
|
let stopped = false;
|
|
9684
9544
|
ctx.effect(() => () => {
|
|
9685
9545
|
stopped = true;
|
|
@@ -9764,4 +9624,4 @@ function apply(ctx, config) {
|
|
|
9764
9624
|
});
|
|
9765
9625
|
}
|
|
9766
9626
|
//#endregion
|
|
9767
|
-
export { Config, FALLBACK_TRAE_MODELS, FALLBACK_TRAE_MODELS_AI, MAX_PROBE_INPUT_TOKENS, REGION_GATEWAYS, SseDecoder, TRAE_ACCOUNT_STATUS_PATH, TRAE_AI_PROVIDER, TRAE_CHECKIN_PATH, TRAE_CN_AGENT_TASK_PATH, TRAE_CN_TITLE_PATH, TRAE_ENTERPRISE_PROVIDER, TRAE_MODELS_TEST_PATH, TRAE_MODEL_DETAIL_FUNCTIONS, TRAE_MODEL_DETAIL_PATH, TRAE_PANELS, TRAE_PAY_BASE, TRAE_PROBE_TIMEOUT_MS, TRAE_PROVIDER, TRAE_PROVIDERS, TRAE_PROVIDER_DISPLAY_NAMES, TRAE_PROVIDER_IDS, TRAE_PROVIDER_ID_DISPLAY_NAMES, TRAE_PROVIDER_ROUTES, TRAE_RAW_CHAT_V1_PATH, TRAE_RAW_CHAT_V2_PATH, TRAE_REASONING_EFFORTS, TRAE_REGIONS, TRAE_REGION_PARAM, TRAE_SETTINGS_NS, TRAE_SOLO_CHAT_PATH, TRAE_SOLO_FUNCTION, TRAE_SOLO_MODELS_PATH, TRAE_SOLO_REMOTE_BASE, TRAE_STATE_DB_FILENAME, TRAE_STREAM_IDLE_TIMEOUT_MS, TRAE_USAGE_PATH, TRAE_VERSION_CODE_FALLBACK, TraeCatalog, TraeCredentialStore, TraeDelegatingUpstreamClient, TraeFallbackUpstreamClient, TraeGatedUpstreamClient, TraeRawCapabilityController, TraeRawCapabilityState, TraeRawChatUpstreamClient, TraeSoloBridge, TraeSoloRemoteCatalogClient, TraeSoloUpstreamClient, TraeUsageClient, UnconfiguredTraeUpstreamClient, adaptLegacyPiAiContext, adaptModernPiAiContext, apply, applyContextBudgets, applyImageSelection, applyReasoningEffort, asVolatile, bridgeTraeSoloStream, buildTraeAgentTaskBody, buildTraeCnHeaders, buildTraeFusionRawChatEnvelope, buildTraeModelDetailRequest, buildTraeRawChatDraft, buildTraeRawChatRuntimeConfig, classifyProbeError, classifyProbeResult, classifyTraeRawChatFailure, configuredAccountsOf, createTraeAdapter, createTraeRawGateway, createTraeShim, creditPosition, decidePiAiGeneration, decodeRawChatChunk, decodeTraeEvent, decryptTraeStorageValue, deriveCatalog, describeIdShape, describeNameShape, describeTraeFailure, discoveredCatalog, displayNameOfTraeProvider, fallbackModelsFor,
|
|
9627
|
+
export { Config, FALLBACK_TRAE_MODELS, FALLBACK_TRAE_MODELS_AI, MAX_PROBE_INPUT_TOKENS, REGION_GATEWAYS, SseDecoder, TRAE_ACCOUNT_STATUS_PATH, TRAE_AI_PROVIDER, TRAE_CHECKIN_PATH, TRAE_CN_AGENT_TASK_PATH, TRAE_CN_TITLE_PATH, TRAE_ENTERPRISE_PROVIDER, TRAE_MODELS_TEST_PATH, TRAE_MODEL_DETAIL_FUNCTIONS, TRAE_MODEL_DETAIL_PATH, TRAE_PANELS, TRAE_PAY_BASE, TRAE_PROBE_TIMEOUT_MS, TRAE_PROVIDER, TRAE_PROVIDERS, TRAE_PROVIDER_DISPLAY_NAMES, TRAE_PROVIDER_IDS, TRAE_PROVIDER_ID_DISPLAY_NAMES, TRAE_PROVIDER_ROUTES, TRAE_RAW_CHAT_V1_PATH, TRAE_RAW_CHAT_V2_PATH, TRAE_REASONING_EFFORTS, TRAE_REGIONS, TRAE_REGION_PARAM, TRAE_SETTINGS_NS, TRAE_SOLO_CHAT_PATH, TRAE_SOLO_FUNCTION, TRAE_SOLO_MODELS_PATH, TRAE_SOLO_REMOTE_BASE, TRAE_STATE_DB_FILENAME, TRAE_STREAM_IDLE_TIMEOUT_MS, TRAE_USAGE_PATH, TRAE_VERSION_CODE_FALLBACK, TraeCatalog, TraeCredentialStore, TraeDelegatingUpstreamClient, TraeFallbackUpstreamClient, TraeGatedUpstreamClient, TraeRawCapabilityController, TraeRawCapabilityState, TraeRawChatUpstreamClient, TraeSoloBridge, TraeSoloRemoteCatalogClient, TraeSoloUpstreamClient, TraeUsageClient, UnconfiguredTraeUpstreamClient, adaptLegacyPiAiContext, adaptModernPiAiContext, apply, applyContextBudgets, applyImageSelection, applyReasoningEffort, asVolatile, bridgeTraeSoloStream, buildTraeAgentTaskBody, buildTraeCnHeaders, buildTraeFusionRawChatEnvelope, buildTraeModelDetailRequest, buildTraeRawChatDraft, buildTraeRawChatRuntimeConfig, classifyProbeError, classifyProbeResult, classifyTraeRawChatFailure, configuredAccountsOf, createTraeAdapter, createTraeRawGateway, createTraeShim, creditPosition, decidePiAiGeneration, decodeRawChatChunk, decodeTraeEvent, decryptTraeStorageValue, deriveCatalog, describeIdShape, describeNameShape, describeTraeFailure, discoveredCatalog, displayNameOfTraeProvider, fallbackModelsFor, generationOf, hashTraeRawChatArg, identityHeaders, inject, isEnterpriseAccount, legacyTraeOwnAuthPath, maskUserPath, mergeTraeModelSources, name, nextRegionCreditPosition, nextRegionEnabled, nextRegionSlots, normalizeTraeCredential, normalizeTraeVersionCode, panelOfKey, panelOfProvider, parseObservedModelConfig, parseReasoningCapability, parseTraeAuthValue, parseTraeCachedModel, parseTraeModelExtraConfigLogLine, parseTraeRawChatBehaviorConfig, parseTraeRemoteModel, parseTraeStorageDocument, piAiRuntimeInfo, pickTraeStorageIdentity, prepareSoloBody, probeBody, probeModelsSequentially, probeOneModel, probeTraeRawChatCapability, providerOfPanel, rawCapabilityDiagnostic, rawCapabilityFingerprint, readTraeCachedModel, readTraeCliIdentity, readTraeIdentity, refreshTraeCredential, regionCreditPositionOf, regionEnabled, regionEnabledOf, regionOfCredential, regionOfEdition, regionOfHost, regionOfPanel, regionOfTraeProvider, regionOfTraeStatusUrl, regionOfUserRegion, regionStateOf, registerTraeUsageRoute, resolveTraeIdentity, resolveTraeRawRuntime, routeOfTraeProvider, sanitizeCatalog, settingsNamespaceOf, traeEndpoint, traeInputModalities, traeModelDisplayName, traeOwnAuthPath, traeRawChatExtraInfo, traeStateDatabaseCandidates, traeStorageCandidates, traeWebUsage, traeWindowsAppNames, unwrapVolatile, unwrapVolatileDeep, wireTargetsOf, withContextAdaptation, withTraeRegion };
|
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": "
|
|
5
|
+
"version": "4.0.1",
|
|
6
6
|
"author": "dingminhua",
|
|
7
7
|
"copyright": "Copyright (c) 2026 LaoDing",
|
|
8
8
|
"license": "MIT",
|