dsh-connect-trae 3.4.2 → 3.5.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,126 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.5.0 (2026-10-14)
4
+
5
+ > **积分读数不再只有一个固定位置。** 本版向同族 `dsh-connect-workbuddy` 学来它的 issue #62
6
+ > 修法:把「读数显示在哪里」做成每个区域一个选项,默认值与升级前完全一致。
7
+
8
+ ### 新增
9
+
10
+ - **输入框读数的显示位置可选:输入框工具栏 / 输入框下方**(学自 `dsh-connect-workbuddy` issue #62):
11
+ - **为什么需要**:那个位置本身是脆的。`conversation.input.left`(输入框工具栏)是一个**共享的 list 插槽**,
12
+ 外壳自己的控件和**任何其他 bundle** 都注册在那里,而 list 插槽**无法保证每个占用者都可见** ——
13
+ 同族的报告者装了第三方插件(`dsh-auto-continue`)之后,积分读数就**整个消失了**。
14
+ 本插件其实已经因为这个原因丢过一次这行读数:它早年放在**侧边栏底部**,那是一个共享的**根级行**,
15
+ 与 `dsh-connect-workbuddy` 的两行并排时被挤成只剩一个「Tr」的残片(2.12.0 才迁到输入框工具栏)。
16
+ **同一个坑踩了两次,这次把位置交给用户。**
17
+ - **两个席位**:
18
+ - `composer`(**默认**)—— 输入框工具栏 `conversation.input.left`,与模型选择同一行,即现在的样子;
19
+ - `stats` —— 输入框下方 `conversation.composer.dock`,外壳自己渲染「轮次 / 步数 · tok/s · token ·
20
+ 缓存命中」那一行;`order: 10` 排在 shell 统计**之后**,所以官方那几颗统计仍在最左,读数是**追加**而不是顶替。
21
+ - **判定顺序:归属 → 区域开关 → 显示开关 → 席位。** 席位排在**最后**,所以一个被关掉的区域在
22
+ **两个席位都不渲染**,而不是先在非当前席位画一帧再被拒。
23
+
24
+ ### 修复
25
+
26
+ - **区域被关闭后,它的积分读数仍在输入框工具栏里渲染**(本次移植时由新守卫发现):
27
+ - 把某个区域的供应商关掉时,Host 会把该区域的 adapter 路由与可配置供应商条目**一并撤下**,
28
+ 模型选择器里也不再有它 —— 但 gate 只检查了「显示积分」那个开关,**从未检查区域开关**。
29
+ 于是一个已被关闭的区域只要模型投影还指着它的 provider,读数就会继续画在那里,
30
+ 并且它的取数请求注定失败。
31
+ - 现按 Host 的同一套 opt-out 规则(`regionEnabledOf`:只有显式 `false` 才算关闭)在 gate 里补上这一判。
32
+ 这与卡片上那个区域开关**用的是同一个 reader**,所以卡片和 gate 不可能对「这个区域开没开」产生分歧。
33
+ - 同族的 gate 一直有这一判,是本插件漏了。
34
+
35
+ ### 设计取舍(两条,都写下来免得后人改回去)
36
+
37
+ - **两个席位都无条件注册,决定权在 gate 里一处**(席位不符就 `return null`)。
38
+ 若改成「按设置只注册当前席位」,则每次改设置都要**重新注册插槽** —— 而本仓库的文件头已经写明
39
+ 这种绑定是脆的(rc.6→rc.7 的 `id`/`order` → `key`/`priority` 改名就是同类问题),
40
+ 且用户是「一边看着结果一边改」的。现在改设置只是一次 settings 写入。
41
+ - **卡片控件读的是设置文档,不是 Host 的 usage 应答**(这里**故意与同族不同**)。
42
+ 同族那样做是因为它的 0.1.7 部署上浏览器设置镜像**实测是过期的那份**;本仓库没有复现到这种过期,
43
+ 而读镜像才能让控件**首帧就是对的** —— 只靠 usage 文档喂值的控件会先停在默认值上等一次网络往返,
44
+ 这正是「看起来没生效」的观感。这一点有守卫钉住(见下)。
45
+
46
+ ### 测试
47
+
48
+ - **+19**(全仓 **598 → 617**):
49
+ - `tests/credit-position.spec.tsx`(新增 13 例):默认 `composer`(含设置存在之前的 profile、
50
+ 手改的未知值 `'sidebar'`);**按区域**而非全局读取;整段设置与裸 `regions` 映射两种入参都接受
51
+ (传错形状在本卡片上真的出过货);写入只改该区域该字段(模型列表 / 预算 / enabled / 兄弟区域都不动);
52
+ 席位与两个开关相互独立;gate 在**指定席位渲染 / 另一席位渲染 0 个 / 两个席位都不渲染(隐藏或区域关闭)/
53
+ 别的 provider 两个席位都不渲染 / 按会话所指区域取席位(CN 与 AI 各在各自席位)**;
54
+ 以及 Host 侧 `creditPosition()` 与浏览器侧 `regionCreditPositionOf()` **两边答案一致**(含 schema 默认值)。
55
+ - `tests/card-composer-credits-switch.spec.tsx`(新增 6 例):控件默认值、**跟随标签页切换**
56
+ (按区域而非一个全局值)、写入是**整槽合并**(不丢模型选择、不动另一个区域)、
57
+ 区域关闭时**禁用而不是隐藏**(控件消失会读成功能没了)、与显示开关相互独立(隐藏后仍保留所选席位)、
58
+ 只读 scope 拒绝写入。
59
+ - `tests/client-activation.spec.tsx`(更新 2 处 + 新增 1 条断言):插槽清单由 3 个变 4 个,
60
+ 并**钉住两个席位的 slot id 互不相同** —— 两个注册共用一个 id 会让后一个静默替换前一个,
61
+ 于是设置能选到一个已不在册的席位、读数反而彻底消失(正是本特性要修的那个缺陷)。
62
+ 测试替身原先只认 `key` 字段,现在同时认 `id`/`key`(真实的 0.1.7 注册表两者都用),
63
+ 否则一条关于 slot 身份的新断言会静默读到 `undefined` 而假绿。
64
+ - **变异验证**(各自变红后恢复):删掉 gate 的席位判定 → 4 例红;把读取的默认值去掉(升级前的 profile
65
+ 读成 `undefined`)→ 4 例红;只注册一个席位 → 2 例红;控件不读所存席位 → 2 例红。
66
+ - 构建产物核对:`lib/client.js` 内两个插槽名与两个 slot id 均在。
67
+
68
+ ## 3.4.3 (2026-10-13)
69
+
70
+ > **保存模型列表时终于有了「正在进行」的反馈。** 本版对齐同族 `dsh-connect-workbuddy` 4.4.2
71
+ > 对忙碌遮罩做的修正(该处修的是同族共有的缺陷),并把当初核实过的依据一并带过来。
72
+
73
+ ### 新增
74
+
75
+ - **保存 / 写设置时有一层忙碌遮罩**(新增 `src/client/BusyOverlay.tsx`,共用组件):
76
+ - **此前完全没有。** 保存状态只表现为控件变灰加按钮文案从「保存」变「保存中…」——
77
+ 用户盯着某个具体行等它落地时,屏幕上没有任何「正在进行」的迹象。
78
+ - 遮罩由卡片的**两条**写路径共同驱动:`saveModels` 的 `saving`(保存模型列表)与
79
+ `writePreference` 的 `savingSettings`(跟随登录 / 输入框读数两个开关)。
80
+ - 遮罩在该写路径的 `finally` 里随忙碌标记一起落下,也就是 **Host 重读落地的时刻**——
81
+ 延迟从「看不见」变成「看着它发生」。
82
+
83
+ ### 修复
84
+
85
+ - **遮罩的配色与动效改用宿主自己的令牌与节奏**(对齐同族 workbuddy 4.4.2):
86
+ - **遮罩卡片底色**若沿用同族的旧值 `--dsw-alias-bg-primary`,那个变量**在宿主令牌集里根本不存在**
87
+ (实测宿主 bundle 零命中;宿主只有 `bg-base` / `bg-layer-1..3` / `bg-module-platform` / `bg-overlay` 等),
88
+ 于是一路回退到写死的近黑 —— 卡片变成一块黑板子,上面的字看不清。现改用宿主给弹层用的
89
+ `--dsw-alias-bg-layer-2`,亮暗两套主题各自成立;阴影也从手写的 drop shadow 换成宿主的
90
+ `--dsw-elevation-prominent`。
91
+ - **遮罩底色**原写死 `rgba(0,0,0,.38)`,既不跟随主题、也没有宿主的模糊。改用宿主自己遮罩用的
92
+ `--dsw-alias-bg-mask-1`(亮 `.24` / 暗 `.5`)+ `--dsw-mask-blur`,与外壳里其他遮罩一致。
93
+ - **提示行**用 `label-secondary` —— 原先的 `label-tertiary` 是宿主最暗的一档
94
+ (亮 `neutral-bluish-600`、暗 `neutral-bluish-400`),给元数据用的,不该承载一句要等的人必须读的话。
95
+ - **spinner 换成宿主同款弧线**。此前那种 18px 的 CSS border 环、`.7s` 匀速转,比宿主自己的状态
96
+ 转圈(`_dsh-state-dot-spin`:SVG 弧线 + dash 呼吸、`1.5s`)快了近一倍 —— 比起形状本身,
97
+ **这个速度差才是它看着廉价的主因**。现按宿主 bundle 实测到的几何逐条对齐:
98
+ `viewBox 0 0 20 20`、`r=8`、`stroke-width 2`、track `opacity .25`、弧线 `stroke-dasharray 12 150`
99
+ 与 dash 呼吸、`1.5s`、`currentColor` 继承所在层级;reduced-motion 降级为**静态弧线**
100
+ (与宿主降级方式一致),并补 `aria-hidden`,免得 `role="status"` 之外多报一次。
101
+
102
+ ### 测试
103
+
104
+ - **+4**(`tests/card-styles.spec.tsx` 5 → 9,全仓 **594 → 598**):
105
+ - 遮罩选择器守卫:逐条钉住五个遮罩规则,且要求整条 `{` 结尾匹配,避免改名前缀后被子串误判为存在。
106
+ - 弧线节奏守卫:钉住 `dsm-trae-veil-dash` 关键帧与 reduced-motion 降级,防止退回到自绘 border 环。
107
+ - **渲染守卫(唯一能证明「遮罩真的出现」的断言)**:jsdom 不做层叠,前几条都只证明样式表里有这些
108
+ 名字。这条在 `scope.set` 挂起的条件下点「跟随 Trae 当前登录的账号」,断言遮罩确实进 DOM
109
+ (`role=status` / `aria-busy=true` / `aria-live=polite`)、文案为 `row.veilSaving`、弧线与卡片都在,
110
+ 写盘落地后卸载。
111
+ - 令牌白名单补三条(`--dsw-alias-bg-mask-1` / `--dsw-mask-blur` / `--dsw-elevation-prominent`),
112
+ 三者均经宿主 bundle 实测存在。白名单断言「大小必须等于实际用到的令牌数」,遮罩引入新令牌后必须同步补齐。
113
+ - 变异验证(各自变红后恢复):把 `.dsm-trae-veil{` 改成 `.dsm-trae-veilz{` → 仅选择器守卫变红;
114
+ 把 `visible={saving || savingSettings}` 改成 `visible={false}` → 仅渲染守卫变红。
115
+ - **一处诚实记录,不夸大守卫能力**:本仓库的 `vite/oxc` 与 `tsdown` 比 workbuddy 严格,模板字符串被
116
+ 反引号截断后会**直接报解析错误**(构建同样失败),所以「顶层语句数」那条截断守卫在本仓库
117
+ 不会比它们更早报警。真正拦不住截断的是 `tsc`(实测被截断的文件 `tsc` 仍 `exit 0`)——
118
+ 这正是同族当初能静默中招的原因。那条守卫作为「解析器不再拦时的兜底」保留。
119
+
120
+ ### 文档
121
+
122
+ - 无。本版只含上述新增、修复与配套测试。
123
+
3
124
  ## 3.4.2 (2026-10-13)
4
125
 
5
126
  > **插件现在与它自己解析到的那份 `@earendil-works/pi-ai` 代数对齐了**——这是 [issue #27](https://github.com/dingminhua/dsh-connect-trae/issues/27)
package/README.en.md CHANGED
@@ -51,6 +51,8 @@ A [DeepSeek Harness (DSH)](https://github.com/deepseek-ai/deepseek-harness) bund
51
51
 
52
52
  <img src="docs/assets/dsh-connect-trae-composer-credits.png" width="536" alt="Trae credits panel: a table of accounts with their general balance, and the composer readout below" />
53
53
 
54
+ **Where that readout sits is a choice** (learned from the sibling `dsh-connect-workbuddy` issue #62). The default is the **composer toolbar** (the position described above); if another plugin occupies it and the readout does not appear, move it **below the input box** — the row carrying the round / step / token statistics, where the readout is APPENDED after the shipped figures rather than replacing them. The seat is set **per region** (CN and international are stored separately), in the card's settings block next to the "show credits in the composer row" checkbox. Why a second seat exists at all: the composer toolbar is a **shared list slot** that the shell's own controls and every other plugin register into, and a shared slot **cannot promise that every occupant is visible** — the report behind that issue is a readout that vanished entirely once a third-party plugin was installed (this plugin has been squeezed out of a shared row once before too, down to a clipped "Tr" at the sidebar foot).
55
+
54
56
  - **Secure loopback shim** — one random port + in-process random secret per region; the real Trae token is never handed to pi-ai.
55
57
 
56
58
  ## How it works
package/README.md CHANGED
@@ -52,6 +52,8 @@
52
52
 
53
53
  <img src="docs/assets/dsh-connect-trae-composer-credits.png" width="536" alt="Trae credits panel: a table of accounts with their general balance, and the composer readout below" />
54
54
 
55
+ **读数显示在哪里可以选**(学自同族 `dsh-connect-workbuddy` issue #62)。默认在**输入框工具栏**(即上面说的位置);如果那里被别的插件占了、读数不显示,改成**输入框下方**——那是「轮次 / 步数 / token」统计所在的那一行,读数是**追加**在官方统计之后,不会顶掉它们。位置**按区域分别设置**(国内版与国际版各存各的),在卡片「设置」区紧挨「在输入框工具栏显示积分读数」那个勾选框。之所以要有第二个位置:输入框工具栏是**共享的 list 插槽**,外壳自己的控件和其他插件都注册在那里,而共享插槽**无法保证每个占用者都可见**——同族的报告者装了第三方插件后读数就整个消失了(本插件早年放在侧边栏底部时也被挤成过一个「Tr」的残片)。
56
+
55
57
  - **安全 loopback shim** —— 每区域一个随机端口 + 进程内随机 secret,真实 Trae token 不交给 pi-ai。
56
58
 
57
59
  ## 工作原理