dsh-connect-trae 3.10.2 → 4.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 CHANGED
@@ -1,5 +1,42 @@
1
1
  # Changelog
2
2
 
3
+ ## 4.0.0 (2026-10-19)
4
+
5
+ > 移除 issue #29 的「跟随 Trae 桌面端当前登录」整套机制,连同它派生的两处 UI。
6
+ >
7
+ > **原因:账号池功能无法兼容原需求。** #29 要的是「插件始终跟着 App 当前的登录走」,而账号池要的是
8
+ > 「每个账号都能被长期保留、随时选中、按可用性换号」——池里选中的账号往往正是那个已经不在 App 里
9
+ > 登录的账号,它必须照常可用。「跟随当前登录」与「账号池」是互斥的两条规则,只能是后者。
10
+ >
11
+ > 这是**大版本**:一个配置字段与两处界面被移除。
12
+
13
+ ### 移除
14
+
15
+ - **设置卡片里的「跟随 Trae 当前登录的账号」开关**。连带删除 `Config.followAppLogin` 字段、每次设置
16
+ 生效时的自动重绑、以及启动时的那次跟随。插件不再有「不点也会自己换绑计费账号」的路径。
17
+ 该开关默认关闭,所以从未打开过它的用户没有任何行为变化;存过 `true` 的旧配置里的这个键会被忽略。
18
+ - **账号区上方的「Trae 已登录 X,但本插件绑定的是 Y。改用 Y」提示条**。连带删除 Host 侧
19
+ `TraeCredentialStore.liveLogin()`、usage 文档的 `appLogin` 字段及其读取路径、`TraeWebAppLogin` 类型。
20
+ usage 文档不再携带这个字段。
21
+ - **账号池设置里的「每登录一个账号,就刷新一次」黄色警告框**。账号副本是每次读取就补齐一次的,
22
+ 这句「没刷新就换号,上一个账号不会被保存」与实现不符。
23
+ - 顺带清掉只服务于跟随开关的 Host 侧 `writeSettings` 写入通道(`settings.update` + revision 冲突重试),
24
+ 它的唯一消费者就是那个开关。
25
+
26
+ ### 不变
27
+
28
+ - **没有显式选择账号时,仍然默认使用 App 当前登录的账号**(`preferred()` 对 `source === 'desktop'`
29
+ 的凭据优先)。这是本次移除后仍然保留的「跟随」行为,且不需要任何开关。
30
+ - **账号副本机制不变**:本机每个 Trae 登录都会被复制成自己的一份(`~/.dsh/.trae-auth.<region>.json`),
31
+ 换号不会顶掉任何账号,之前的账号仍可被重新选回来。
32
+
33
+ ### 测试
34
+
35
+ - 删掉随功能退役的用例:`auth.spec.ts` 的 `liveLogin()` 三态、`web-status.spec.ts` 整个
36
+ `app sign-in follow hint (issue #29)` describe、`card-accounts-table` 的提示条两条、`card-pool` 的
37
+ 警告框一条。`card-styles` 的遮罩用例改用 `showPointsInMainUi` 开关驱动。
38
+ - 全仓 **895** 例通过,0 skipped;`tsc` 两个工程干净;`build` 通过。
39
+
3
40
  ## 3.10.2 (2026-10-19)
4
41
 
5
42
  > 设置页的账号列表**先出、积分后补**。打开卡片原本要等**一整份**用量文档组装完才画第一笔:那份文档的
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 小时 → 已过期**),写明金额、套餐数和最早到期时间,避免只盯总额时悄悄丢掉最先到期的额度。国内版在用量页与输入框积分面板两处都显示(国际版是订阅制,没有逐包到期数据)。
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
- ("跟随 Trae 当前登录的账号 在 Trae 桌面端切换登录后…"), which is what made
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}
@@ -915,9 +901,6 @@ window.__ModuleLoader__.load({
915
901
  /* "Every member is unusable" is the one case that IS the pool's fault, so it
916
902
  keeps the warn tone the base class sets. */
917
903
  .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
904
  .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
905
  .dsm-trae-pool-save-buttons{display:flex;align-items:center;justify-content:flex-end;gap:8px}
923
906
  .dsm-trae-pool-save-row .dsm-btn{padding:5px 14px;font-size:13px;line-height:1.5}
@@ -1938,17 +1921,6 @@ window.__ModuleLoader__.load({
1938
1921
  className: "dsm-trae-pool-tools dsm-trae-pool-tools-dashed",
1939
1922
  children: tools
1940
1923
  }),
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
1924
  pool.copies === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1953
1925
  className: "dsm-trae-pool-note dsm-trae-pool-copyfile",
1954
1926
  role: "note",
@@ -3179,10 +3151,7 @@ window.__ModuleLoader__.load({
3179
3151
  * local state: a write made elsewhere (the DSH settings form, another window)
3180
3152
  * then shows up here instead of being shadowed by a stale copy.
3181
3153
  */
3182
- const committedSettings = {
3183
- followAppLogin: followAppLoginEnabled(settingsScope?.getSnapshot().value),
3184
- showPointsInMainUi: unwrapVolatileDeep(settingsScope?.getSnapshot().value)?.showPointsInMainUi === true
3185
- };
3154
+ const committedSettings = { showPointsInMainUi: unwrapVolatileDeep(settingsScope?.getSnapshot().value)?.showPointsInMainUi === true };
3186
3155
  /**
3187
3156
  * Ids for the block's label/hint wiring. `useId`, not constants: DSH can mount
3188
3157
  * this card twice at once (the settings ROW and the expanded PAGE), and two
@@ -3194,13 +3163,8 @@ window.__ModuleLoader__.load({
3194
3163
  * over it. Reading BOTH sources here is what lets the write above stay simple —
3195
3164
  * it never has to write into component state that a Host refresh would fight.
3196
3165
  */
3197
- const settingsEdits = {
3198
- followAppLogin: optimisticSettings.current.followAppLogin ?? committedSettings.followAppLogin,
3199
- showPointsInMainUi: optimisticSettings.current.showPointsInMainUi ?? committedSettings.showPointsInMainUi
3200
- };
3166
+ const settingsEdits = { showPointsInMainUi: optimisticSettings.current.showPointsInMainUi ?? committedSettings.showPointsInMainUi };
3201
3167
  const settingsIds = (0, react.useId)();
3202
- const followLabelId = `${settingsIds}-follow`;
3203
- const followHintId = `${settingsIds}-follow-hint`;
3204
3168
  const creditsLabelId = `${settingsIds}-credits`;
3205
3169
  const creditsHintId = `${settingsIds}-credits-hint`;
3206
3170
  /**
@@ -3226,7 +3190,7 @@ window.__ModuleLoader__.load({
3226
3190
  };
3227
3191
  setSettingsRevision((revision) => revision + 1);
3228
3192
  try {
3229
- await writeSettingsField(settingsScope, field, value, (readBack) => field === "followAppLogin" ? followAppLoginEnabled(readBack) === value : unwrapVolatileDeep(readBack)?.showPointsInMainUi === value);
3193
+ await writeSettingsField(settingsScope, field, value, (readBack) => unwrapVolatileDeep(readBack)?.showPointsInMainUi === value);
3230
3194
  } catch (error) {
3231
3195
  if (mounted.current) setWriteError(error instanceof Error ? error.message : t("row.requestFailed"));
3232
3196
  } finally {
@@ -3509,21 +3473,6 @@ window.__ModuleLoader__.load({
3509
3473
  }
3510
3474
  };
3511
3475
  /**
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
3476
  * Load one account row's per-account state (check-in / balances /
3528
3477
  * subscription) and cache it for the row. Called when the table renders and
3529
3478
  * again after a claim so the reward/refusal lands on the row that owns it.
@@ -4185,90 +4134,62 @@ window.__ModuleLoader__.load({
4185
4134
  }),
4186
4135
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4187
4136
  className: "dsm-trae-prefs",
4188
- children: [
4189
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
4190
- className: "dsm-trae-pref",
4191
- title: t("row.followAppLoginHint"),
4192
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
4193
- type: "checkbox",
4194
- className: "dsm-trae-pref-check",
4195
- checked: settingsEdits.followAppLogin,
4196
- disabled: settingsScope?.getSnapshot().writable !== true || savingSettings,
4197
- "aria-describedby": followHintId,
4198
- onChange: (event) => {
4199
- writePreference("followAppLogin", event.currentTarget.checked);
4200
- }
4201
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4202
- className: "dsm-trae-pref-copy",
4203
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4204
- className: "dsm-trae-pref-label",
4205
- id: followLabelId,
4206
- children: t("row.followAppLogin")
4207
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4208
- className: "dsm-trae-pref-hint",
4209
- id: followHintId,
4210
- children: t("row.followAppLoginHint")
4211
- })]
4137
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
4138
+ className: "dsm-trae-pref",
4139
+ title: t(isCnPool ? "row.showPointsInMainUiHint" : "row.showPointsInMainUiHintAi"),
4140
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
4141
+ type: "checkbox",
4142
+ className: "dsm-trae-pref-check",
4143
+ checked: settingsEdits.showPointsInMainUi,
4144
+ disabled: settingsScope?.getSnapshot().writable !== true || savingSettings,
4145
+ "aria-describedby": creditsHintId,
4146
+ onChange: (event) => {
4147
+ writePreference("showPointsInMainUi", event.currentTarget.checked);
4148
+ }
4149
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4150
+ className: "dsm-trae-pref-copy",
4151
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4152
+ className: "dsm-trae-pref-label",
4153
+ id: creditsLabelId,
4154
+ children: t("row.showPointsInMainUi")
4155
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4156
+ className: "dsm-trae-pref-hint",
4157
+ id: creditsHintId,
4158
+ children: t(isCnPool ? "row.showPointsInMainUiHint" : "row.showPointsInMainUiHintAi")
4212
4159
  })]
4213
- }),
4214
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
4215
- className: "dsm-trae-pref",
4216
- title: t(isCnPool ? "row.showPointsInMainUiHint" : "row.showPointsInMainUiHintAi"),
4217
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
4218
- type: "checkbox",
4219
- className: "dsm-trae-pref-check",
4220
- checked: settingsEdits.showPointsInMainUi,
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",
4160
+ })]
4161
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
4162
+ className: "dsm-trae-pref dsm-trae-credit-position-pref",
4163
+ title: t("row.creditPositionHint"),
4164
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4165
+ className: "dsm-trae-pref-copy",
4166
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4167
+ className: "dsm-trae-pref-lead",
4228
4168
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4229
4169
  className: "dsm-trae-pref-label",
4230
- id: creditsLabelId,
4231
- children: t("row.showPointsInMainUi")
4232
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4233
- className: "dsm-trae-pref-hint",
4234
- id: creditsHintId,
4235
- children: t(isCnPool ? "row.showPointsInMainUiHint" : "row.showPointsInMainUiHintAi")
4236
- })]
4237
- })]
4238
- }),
4239
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
4240
- className: "dsm-trae-pref dsm-trae-credit-position-pref",
4241
- title: t("row.creditPositionHint"),
4242
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4243
- className: "dsm-trae-pref-copy",
4244
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
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
- })]
4170
+ children: t("row.creditPositionLabel")
4171
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
4172
+ className: "dsm-trae-credit-position",
4173
+ value: activeRegionOn ? creditPositionOn(activeRegion) : "composer",
4174
+ disabled: !activeRegionOn || settingsScope?.getSnapshot().writable !== true || savingSettings,
4175
+ "aria-label": t("row.creditPositionAria", { region: activeRegion === "cn" ? t("row.tabCn") : activeRegion === "enterprise" ? t("row.tabEnterprise") : t("row.tabAi") }),
4176
+ onChange: (event) => {
4177
+ changeCreditPosition(activeRegion, event.currentTarget.value === "stats" ? "stats" : "composer");
4178
+ },
4179
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
4180
+ value: "composer",
4181
+ children: t("row.creditPositionComposer")
4182
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
4183
+ value: "stats",
4184
+ children: t("row.creditPositionStats")
4264
4185
  })]
4265
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4266
- className: "dsm-trae-pref-hint",
4267
- children: t("row.creditPositionHint")
4268
4186
  })]
4269
- })
4187
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4188
+ className: "dsm-trae-pref-hint",
4189
+ children: t("row.creditPositionHint")
4190
+ })]
4270
4191
  })
4271
- ]
4192
+ })]
4272
4193
  }),
4273
4194
  status.status === "signed-in" && status.pool !== void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
4274
4195
  className: "dsm-trae-accounts",
@@ -4443,25 +4364,6 @@ window.__ModuleLoader__.load({
4443
4364
  formatNumber,
4444
4365
  formatDateTime
4445
4366
  }) : 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
4367
  rescanNote === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
4466
4368
  className: "dsm-trae-usage-note",
4467
4369
  role: "status",
@@ -5603,10 +5505,6 @@ window.__ModuleLoader__.load({
5603
5505
  "row.expiryWarningWeek": "{total} credit lapses within 7 days ({packs} packs)",
5604
5506
  "row.expiryWarningLapsed": "{total} credit has already lapsed but is still counted in the balance ({packs} packs)",
5605
5507
  "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
5508
  "row.settingsDirty": "Unsaved changes",
5611
5509
  "row.modelsTestEmpty": "Enable at least one model first.",
5612
5510
  "row.modelsTestError": "Test failed: {message}",
@@ -5654,8 +5552,6 @@ window.__ModuleLoader__.load({
5654
5552
  "row.poolCreditExpiry": "expires {when}",
5655
5553
  "row.poolProbeMeasured": "measured {when}",
5656
5554
  "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
5555
  "row.poolSettingsNote": "Preferences below take effect when you save; test results are written by the plugin and are not affected by that button.",
5660
5556
  "row.poolSelectedCount": "Selected {count} / {total}",
5661
5557
  "row.poolNoCopyTag": "no copy here",
@@ -5925,10 +5821,6 @@ window.__ModuleLoader__.load({
5925
5821
  "row.expiryWarningWeek": "有 {total} 积分将在 7 天内过期({packs} 个套餐)",
5926
5822
  "row.expiryWarningLapsed": "有 {total} 积分已过期但仍计入余额({packs} 个套餐)",
5927
5823
  "row.expiryEarliest": "最早到期:{time}",
5928
- "row.appLoginMismatch": "Trae 已登录 {account},但本插件绑定的是 {bound}。",
5929
- "row.appLoginFollow": "改用 {account}",
5930
- "row.followAppLogin": "跟随 Trae 当前登录的账号",
5931
- "row.followAppLoginHint": "在 Trae 桌面端切换登录后自动换绑到新账号。默认关闭,已有绑定保持不变。",
5932
5824
  "row.settingsDirty": "有未保存的修改",
5933
5825
  "row.modelsTestEmpty": "请先启用至少一个模型。",
5934
5826
  "row.modelsTestError": "测试失败:{message}",
@@ -5976,8 +5868,6 @@ window.__ModuleLoader__.load({
5976
5868
  "row.poolCreditExpiry": "{when} 过期",
5977
5869
  "row.poolProbeMeasured": "测得 {when}",
5978
5870
  "row.poolProbeAt": "测试于 {when}",
5979
- "row.poolMirrorWorkflowTitle": "每登录一个账号,就刷新一次",
5980
- "row.poolMirrorWorkflowHint": "Trae 应用只有一个登录位:每登录一个账号,就回到这里刷新一次(打开卡片或点「重新检测账号」),插件会把这次登录保存成一份自己的副本。没刷新就换号,上一个账号不会被保存——它会被 Trae 里的新登录覆盖。",
5981
5871
  "row.poolSettingsNote": "下面是偏好设置:点保存才生效;测试结果由插件自动写入,不受这个保存按钮影响。",
5982
5872
  "row.poolSelectedCount": "已选 {count} / {total}",
5983
5873
  "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 TraeWebAppLogin, 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, followAppLoginEnabled, 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 };
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
@@ -1161,20 +1161,6 @@ function configuredAccountsOf(configured) {
1161
1161
  return typeof accounts === "object" && accounts !== null ? accounts : {};
1162
1162
  }
1163
1163
  /**
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
1164
  * Build the next `regions` settings value for the card's save. The write
1179
1165
  * targets ONLY the signed-in account's region slot; every other region's slot
1180
1166
  * is carried over untouched, so switching accounts never clobbers the other
@@ -2364,36 +2350,6 @@ var TraeCredentialStore = class {
2364
2350
  return eligible.find((credential) => credential.source === "desktop") ?? eligible[0];
2365
2351
  }
2366
2352
  /**
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
2353
  * The accounts this store is willing to OFFER.
2398
2354
  *
2399
2355
  * Scoped to who this store may bill:
@@ -6915,10 +6871,6 @@ async function traeWebUsage(deps, panel, options = {}) {
6915
6871
  message: safeMessage(error)
6916
6872
  };
6917
6873
  }
6918
- let appLogin;
6919
- try {
6920
- appLogin = await deps.liveLogin?.(panel);
6921
- } catch {}
6922
6874
  const account = {
6923
6875
  accountId: accounts.find((item) => item.selected)?.id ?? "",
6924
6876
  accountName: credential.accountName ?? credential.userId,
@@ -6927,7 +6879,6 @@ async function traeWebUsage(deps, panel, options = {}) {
6927
6879
  region: regionOfPanel(panel),
6928
6880
  enabled,
6929
6881
  accounts,
6930
- ...appLogin === void 0 ? {} : { appLogin },
6931
6882
  models: deps.displayModels(panel).map((model) => ({
6932
6883
  ...model,
6933
6884
  ...model.input === void 0 ? {} : { input: [...model.input] }
@@ -8575,7 +8526,6 @@ const Config = z.object({
8575
8526
  ]).default("auto").description("Trae edition hint")),
8576
8527
  accountId: z.string().description("Deprecated: pre-split account selector, attributed to its own region"),
8577
8528
  showPointsInMainUi: asVolatile(z.boolean().default(false).description("在输入框工具栏显示积分读数「Trae CN · <数值>」(仅当选中的模型属于本插件时出现,可点击查看账号与积分明细)")),
8578
- followAppLogin: asVolatile(z.boolean().default(false).description("跟随 Trae 桌面端当前登录账号换绑(打开后每次配置生效时重绑到 App 现在登录的账号)")),
8579
8529
  accounts: asVolatile(accountSelectionConfig.description("Per-panel account selections, keyed cn | enterprise | ai")),
8580
8530
  regions: asVolatile(z.dict(regionStateConfig).default({}).description("Per-panel model directory and selection, keyed cn | enterprise | ai")),
8581
8531
  lastCatalog: z.array(modelConfig).description("Deprecated: pre-region-split CN model directory"),
@@ -9437,50 +9387,6 @@ function apply(ctx, config) {
9437
9387
  }
9438
9388
  };
9439
9389
  };
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
9390
  ctx.inject(["webServer"], (webCtx) => registerTraeUsageRoute(webCtx, {
9485
9391
  store: (panel) => stacks[panel].store,
9486
9392
  client: (panel) => stacks[panel].usageClient,
@@ -9501,7 +9407,6 @@ function apply(ctx, config) {
9501
9407
  }),
9502
9408
  accountStateOf: (panel, accountId) => stacks[panel].accountStateOf(accountId),
9503
9409
  claimCheckinOf: (panel, accountId) => stacks[panel].claimCheckinOf(accountId),
9504
- liveLogin: (panel) => liveLoginOf(panel),
9505
9410
  pool: {
9506
9411
  preferences: (panel) => poolPreferencesOf(panel),
9507
9412
  members: (panel) => poolMembersOf(panel),
@@ -9627,59 +9532,13 @@ function apply(ctx, config) {
9627
9532
  }
9628
9533
  } catch {}
9629
9534
  })();
9630
- let writeSettings;
9631
9535
  ctx.inject(["settings"], (settingsCtx) => {
9632
9536
  const settings = settingsCtx.settings;
9633
9537
  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
9538
  });
9648
9539
  ctx.on("loader/volatile-update", () => {
9649
9540
  applySelection(current());
9650
- maybeFollowAppLogin();
9651
9541
  });
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
9542
  let stopped = false;
9684
9543
  ctx.effect(() => () => {
9685
9544
  stopped = true;
@@ -9764,4 +9623,4 @@ function apply(ctx, config) {
9764
9623
  });
9765
9624
  }
9766
9625
  //#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, followAppLoginEnabled, 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 };
9626
+ 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": "3.10.2",
5
+ "version": "4.0.0",
6
6
  "author": "dingminhua",
7
7
  "copyright": "Copyright (c) 2026 LaoDing",
8
8
  "license": "MIT",