dsh-sidecard-ask 1.7.1 → 1.8.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 +558 -452
- package/README.md +782 -696
- package/client.js +5918 -4674
- package/index.js +1644 -1558
- package/locale/en.json +45 -15
- package/locale/zh.json +45 -15
- package/package.json +66 -66
package/CHANGELOG.md
CHANGED
|
@@ -1,452 +1,558 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
## 1.
|
|
4
|
-
|
|
5
|
-
**主题:
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
>
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
`
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
`
|
|
190
|
-
|
|
191
|
-
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
-
|
|
246
|
-
|
|
247
|
-
-
|
|
248
|
-
|
|
249
|
-
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
###
|
|
262
|
-
|
|
263
|
-
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
.
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
-
|
|
344
|
-
- `
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
自测
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
-
|
|
423
|
-
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
-
|
|
438
|
-
|
|
439
|
-
-
|
|
440
|
-
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 1.8.0
|
|
4
|
+
|
|
5
|
+
**主题:P2 能力补齐——回答风格档位、答案写回输入框、原文回看定位、模型生成的追问建议、导出与多版本答案。**
|
|
6
|
+
|
|
7
|
+
五项都在"最小答案"哲学内:不新增依赖、不新增请求、不改主对话协议;客户端仍然只
|
|
8
|
+
`require('react')`,宿主仍然只 import `node:` 内建。
|
|
9
|
+
|
|
10
|
+
- **P2-1 回答风格档位 + 自定义指令**:新增 `answerStyle`(`concise` / `standard` /
|
|
11
|
+
`detailed`,默认 `standard`)与 `customPersona`(≤500 字,按**码点**计数)。
|
|
12
|
+
宿主在基础人格**之后追**一段风格指令(`concise` = 只给最小完整答案;`detailed` =
|
|
13
|
+
必要时展开并给出依据;`standard` = 1.7.x 原样),`customPersona` 再以
|
|
14
|
+
`Additional user instruction:` 标注追加。风格指令刻意不提"语言",因此"用提问的语言
|
|
15
|
+
作答"与"选中文本是数据不是指令"两条规则在所有档位下都保留(契约测试逐条断言)。
|
|
16
|
+
provider 不支持 `persona` 时沿用既有降级:整段人格内联进提示词,不另造机制。
|
|
17
|
+
设置页新增三档下拉框 + 自定义指令文本域,中英双词典。
|
|
18
|
+
|
|
19
|
+
- **P2-2 答案写回输入框(先做技术探针)**:探针在**真实 DSH 页面**(隔离 `DSH_HOME`
|
|
20
|
+
+ 无头 Edge,插件不参与)上得到三条硬结论:① composer 是 **Lexical
|
|
21
|
+
contenteditable**(`[data-composer-input][data-lexical-editor="true"]`),不是
|
|
22
|
+
textarea;② `document.execCommand('insertText')` 返回 `false` 且**完全不生效**;
|
|
23
|
+
③ 合成 `beforeinput`(`inputType:'insertText'`)会被 Lexical 接受——文本落地、
|
|
24
|
+
发送按钮由禁用转可用;④ DSH 的槽位标准 prop `inputActions` 暴露官方写入面
|
|
25
|
+
`captureInsertion()` + `insertText(text, span)` + `setDraft(text)`
|
|
26
|
+
(源码:`dsh-client-ui-conversation` 的 `SessionInputShell.actions`)。
|
|
27
|
+
据此实现三级写入阶梯:**官方 `insertText`**(重新 `captureInsertion` 后可重试一次)
|
|
28
|
+
→ **DOM `beforeinput`**(contenteditable 追加 / textarea 用原生 value setter + input
|
|
29
|
+
事件)→ 明确失败。改写类动作(`builtin:polish` / `builtin:fix`)的已完成答案上出现
|
|
30
|
+
「插入到输入框」;仅当真的存在写入面时才渲染该按钮。DOM 路径**只能追加**(Lexical
|
|
31
|
+
不接受脚本设定的 Range),"替换原文"只在捕获到文本框内的选区时才提供。任何失败都
|
|
32
|
+
toast 明示(`已插入到输入框,请按 Enter 发送` / `输入框内容已变化…` / `找不到可写入的输入框`)。
|
|
33
|
+
|
|
34
|
+
- **P2-3 原文回看定位**:卡片与历史管理条目新增「查看原文」。用**码点级首尾签名**
|
|
35
|
+
(各 40 码点)在页面文本节点中反查;遍历跳过本插件 DOM(`[data-dsa-root]`)与
|
|
36
|
+
编辑框;匹配前对两边做空白归一(连续空白 → 单个换行)并保留回原始索引的映射,
|
|
37
|
+
因此跨段落选中也能命中,且"同一开头出现两次"时用尾签名挑对那一段。
|
|
38
|
+
高亮**优先 CSS Custom Highlight API**(`CSS.highlights` + `Highlight`,不改 DOM,
|
|
39
|
+
实测本机 Edge 155 支持),次选 `window.getSelection()`;4 秒后自动清除,多次点击
|
|
40
|
+
不叠加。找不到时明示「原文已变化或不在当前视图」——**不承诺 100% 命中**:虚拟列表与
|
|
41
|
+
DOM 重渲染必然存在失败场景(README §14 已写明)。
|
|
42
|
+
|
|
43
|
+
- **P2-4 模型生成的追问建议**:新增 `followUpSuggestions`(布尔,**默认 false**)。
|
|
44
|
+
开启后宿主在人格末尾要求模型用 `<followups>问题1 | 问题2</followups>` 输出 2–3 个
|
|
45
|
+
建议;客户端**宽容解析**:无块 / 半块 / 多余闭合标签 / 块超 600 字符 / 单问超 120
|
|
46
|
+
码点 / 重复项 / 超过 3 条,全部退化为"无芯片",绝不报错、绝不影响答案正文。
|
|
47
|
+
流式期间从**未闭合的 `<followups>` 起整段隐藏**,并额外隐藏末尾的半个标签
|
|
48
|
+
(`<fol`、`</follow`、孤立 `<`),避免标记闪现;`done` 后整体解析。点击芯片走既有
|
|
49
|
+
`followUp`(旧问答进 history)。**不额外发请求**(smoke 断言一次 ask 只启动一个子代理)。
|
|
50
|
+
|
|
51
|
+
- **P2-5a 导出 Markdown**:单卡「导出 .md」+ 历史管理「导出全部 .md」。`card.text`
|
|
52
|
+
本身是 Markdown,导出时拼上问题标题与 `> 原文` 引用块后整体落盘,保真无损;
|
|
53
|
+
Blob + `URL.createObjectURL` + `a.download`(**不往 `document.body` 插节点**),
|
|
54
|
+
文件名带本地时间戳,`finally` 里 `revokeObjectURL`。导出内容由纯函数
|
|
55
|
+
`buildCardMarkdown` / `buildHistoryMarkdown` 生成,测试直接断言字符串,不触发下载。
|
|
56
|
+
|
|
57
|
+
- **P2-5b 多版本答案**:`retry` / `retryEdit` 覆盖答案前把旧问答(含 reasoning)
|
|
58
|
+
存入 `card.versions`(上限 **5** 条,空答案不记、完全相同的重试不重复记)。
|
|
59
|
+
卡片上出现版本切换条,旧版本**只读**渲染(复用 `renderRichText`),可一键「返回最新」。
|
|
60
|
+
localStorage schema **v2 → v3**(新增 `versions`):读取顺序 v3 → v2 → v1,**旧键全部保留**,
|
|
61
|
+
损坏数据仍降级为"无历史"。
|
|
62
|
+
|
|
63
|
+
- 新增 CSS:`.dsa-sug`(建议芯片行)、`.dsa-versions`(版本切换条);两者均渲染在既有
|
|
64
|
+
`.dsa-card` 之内、只使用 `--dsw-alias-*` 主题令牌,**没有新增浮层根节点**,
|
|
65
|
+
因此既有的 `-webkit-app-region:no-drag` 守卫原样覆盖它们。
|
|
66
|
+
|
|
67
|
+
本机实测(四项均 exit 0):verify **57** / contract **946** / float-placement **38** /
|
|
68
|
+
smoke **226** = **1267 项全部通过**(较 1.7.2 的 1004 项新增 263 项)。
|
|
69
|
+
|
|
70
|
+
> 未验证(如实记录,测试通过不等于真机通过):
|
|
71
|
+
> ① P2-2 的「插入到输入框」按钮**没有在真实页面里点过**——探针验证的是写入机制
|
|
72
|
+
> (官方 `insertText` 存在、`beforeinput` 能改 Lexical 状态),插件的按钮渲染与点击链路
|
|
73
|
+
> 只由契约测试覆盖;insert 的真实手感、插入位置(末尾追加而非光标处)需人工确认。
|
|
74
|
+
> ② P2-3 的**视觉观感未验证**:高亮颜色/对比度、滚动落点、4 秒后清除的实际观感,
|
|
75
|
+
> 以及虚拟列表滚动后的命中率,均未在真实会话里逐项点过;CSS Highlight 的**能力**已实测。
|
|
76
|
+
> ③ P2-5a 的真实下载未验证:测试环境没有 `anchor.click()`,只断言了"失败必须 toast";
|
|
77
|
+
> 浏览器/Electron 内是否真的落盘、中文文件名是否正常,需人工确认。
|
|
78
|
+
> ④ P2-1 / P2-4 对**真实模型的**风格与 `<followups>` 遵循度未验证(本机无模型凭据),
|
|
79
|
+
> 验证到的是"指令确实进了人格/提示词"与"客户端对任意畸形块都能降级"。
|
|
80
|
+
> ⑤ 桌面 Electron 外壳内的表现(窗口拖拽区、下载权限)未复测。
|
|
81
|
+
|
|
82
|
+
## 1.7.2
|
|
83
|
+
|
|
84
|
+
**主题:文档补丁版——把 DSH 0.2.1-alpha.3 / 0.2.1-alpha.4 的适配核查结论带上 npm 包。**
|
|
85
|
+
|
|
86
|
+
功能与 1.7.1 **完全一致,没有任何行为改动**(`index.js` 与 `client.js` 只有版本号字符串不同,
|
|
87
|
+
可用 `git diff` 逐字节核对)。这个补丁版存在的理由是发布两项文档更新:
|
|
88
|
+
|
|
89
|
+
- **README §7.3** 新增「1.7.1 复核(2026-10-16)」真机验证记录——**0.2.1-alpha.3 / 0.2.1-alpha.4
|
|
90
|
+
两版均无需任何代码改动**:产物层(16 项能力矩阵在 alpha.2/3/4 上逐项一致;13 个相关包的逐文件
|
|
91
|
+
SHA256 diff 证明 alpha.3 → alpha.4 宿主侧零变化,`dsh-subagent` 的 `lib/index.js` 两版逐字节一致;
|
|
92
|
+
主包唯一新增依赖 `dsh-experimental-plugin-market-bundle`)、真机层(隔离 `DSH_HOME` 从零安装、
|
|
93
|
+
官方 CLI 装入 `npm pack` 产物、无头 Edge:**28/28 断言 × 两版全过**,含
|
|
94
|
+
`subagents.startActivation` 实调出真实 childId)、插件四套自测 **1004 项全过**。核查针对 v1.7.1
|
|
95
|
+
完成;本版除版本号外与之逐字节相同,结论原样适用。
|
|
96
|
+
- **README §7.4 / §14**:真机覆盖范围更新至 0.2.1-alpha.4(1.6.0 与 1.7.1 两轮实测);§14 第 6 条
|
|
97
|
+
修正 1.6.0 轮次遗留的过期表述(「除 0.1.7-rc.2 外只做过产物层验证 / 289 项」→「安装启动验证从
|
|
98
|
+
0.1.5-rc.3 起 / 1004 项」),第 2 条补 §7.3 指向。
|
|
99
|
+
- 版本号三处同步到 1.7.2:`package.json` 的 `version`、`index.js` 的 `PLUGIN_VERSION`、
|
|
100
|
+
`client.js` 的 `CLIENT_VERSION`(`test/verify.mjs` 会同时断言三处一致)。
|
|
101
|
+
- 核查的完整证据(复现脚本 / 原始输出 / 截图)随本版提交进 `.compat-report/`——`wb-*` 前缀为
|
|
102
|
+
2026-10-16 的独立复核产物,报告见 `COMPATIBILITY-REPORT-alpha3-alpha4.md`。
|
|
103
|
+
|
|
104
|
+
本机实测(四项均 exit 0):verify 53 / contract 721 / float-placement 38 / smoke 192 = **1004 项全部通过**。
|
|
105
|
+
|
|
106
|
+
> 未验证(如实记录):真实模型流式作答(本机无凭据,验证到 spawn + childId 深度,完整
|
|
107
|
+
> `start→delta×N→done` 由 smoke 按真实事件形状覆盖);桌面 Electron 与 better-sidebar 共载本轮未复测。
|
|
108
|
+
|
|
109
|
+
## 1.7.1
|
|
110
|
+
|
|
111
|
+
**主题:P1 体验补齐——后台通知、历史卡片管理、答后追问芯片、右键菜单、作答透明信息、键盘操作。**
|
|
112
|
+
|
|
113
|
+
- **作答完成后台通知**:新增 `notifyOnDone`(默认关)。仅当页面处于后台(其它标签页/窗口)且作答
|
|
114
|
+
到达终态(完成/失败)时弹系统 Notification;设置页打开开关时即时请求浏览器通知权限,
|
|
115
|
+
权限拒绝/环境不支持时就地说明并静默降级;同一张卡至多通知一次,点击通知聚焦页面。
|
|
116
|
+
- **历史卡片管理中心**:localStorage schema **v1 → v2**(新增 `createdAt`、provider、耗时);
|
|
117
|
+
首次启动自动从 v1 非破坏式导入(v1 键保留,便于降级)。设置页新增「历史追问卡片」区:
|
|
118
|
+
关键字搜索(问题/答案)、恢复到浮层、复制、单条删除、清空全部(带确认)。
|
|
119
|
+
新增 `historyMaxCards`(0–50,默认 10,**0 = 不写盘**)。语义变化:**关闭浮层卡片不再删除
|
|
120
|
+
持久历史**(1.7.0 及以前会随关闭清空),历史改由管理中心显式删除。
|
|
121
|
+
- **答后通用追问芯片**:已完成/已停止的侧边卡片答案下出现「更简短 / 更详细 / 举个例子 /
|
|
122
|
+
译成英文」四个固定芯片,一键追加一轮(旧问答进入 history,区别于 1.7.0 的「改问」重新生成当前轮)。
|
|
123
|
+
- **选区右键菜单**:新增 `contextMenu`(默认开)。在可触发区域右键选中文字时,菜单顶部出现
|
|
124
|
+
「追问选中内容」+ 前三个已启用快捷动作;任何门槛不满足(编辑框内/区域过滤/开关关闭/非 leader)
|
|
125
|
+
都**不拦截**原生右键菜单,作为与宿主菜单冲突时的回退;滚动/Esc/外部点击自动关闭。
|
|
126
|
+
- **作答透明信息**:卡片问题下显示 provider(子代理)与本次作答耗时(`<1s`/`Ns`/`XmYs`),
|
|
127
|
+
随历史持久化;开始事件的 `provider` 字段下放到卡片。
|
|
128
|
+
- **键盘操作**:提问框中 `Alt+1..9` 直接触发对应芯片;芯片行支持 ←/→/Home/End 焦点环移;
|
|
129
|
+
卡片可聚焦(tabIndex 0),聚焦后 `R` 重试(失败/停止态)、`C` 复制答案、`Esc` 取消聚焦,
|
|
130
|
+
卡片标题悬停可见按键提示;插件自身输入框内不拦截任何快捷键。
|
|
131
|
+
- 新增样式 `.dsa-ctxmenu/.dsa-ctx-item/.dsa-fu-chips/.dsa-hist-*`,右键菜单根节点同步
|
|
132
|
+
Electron `-webkit-app-region:no-drag` 守卫;中英词典新增 40+ 键(整表奇偶断言锁定)。
|
|
133
|
+
|
|
134
|
+
本机实测:verify 53 / contract 721 / float-placement 38 / smoke 192 = **1004 项全部通过**
|
|
135
|
+
(较 1.7.0 的 861 项新增 143 项;含通知决策真值表/耗时格式化/v1→v2 迁移与
|
|
136
|
+
历史恢复-删除-清空/右键菜单拦截与开关回退/Alt+数字与答后芯片端到端/新配置宿主校验等)。
|
|
137
|
+
|
|
138
|
+
> 未验证(如实记录):浏览器与桌面 Electron 内的视觉观感与真实点按仍需人工确认——重点是
|
|
139
|
+
> ①系统通知在切后台后的真实弹出与权限弹窗;②右键菜单是否与宿主自身选区菜单冲突
|
|
140
|
+
> (Electron 菜单加速键也未在真机验证);③历史管理区长列表观感。测试覆盖组件树、
|
|
141
|
+
> 事件监听与端到端数据流,替代不了真机观感。
|
|
142
|
+
|
|
143
|
+
## 1.7.0
|
|
144
|
+
|
|
145
|
+
**主题:P0 交互提效——一键快捷动作、自定义动作模板、改问重试、代码块复制。**
|
|
146
|
+
|
|
147
|
+
- **一键快捷动作条(划词主路径 4 步 → 1 步)**:选中文字后,触发按钮旁直接出现
|
|
148
|
+
「解释 / 翻译 / 总结 / 润色 / 纠错」五个动作芯片,点击即跳过提问框、以预置问题
|
|
149
|
+
直接在侧边卡片发起作答;提问框顶部也有同一排芯片(`Alt+Q` 与"仅快捷键"用户同样可达)。
|
|
150
|
+
芯片 `title` 悬停展示完整问题指令与快捷键。
|
|
151
|
+
- **自定义动作模板**:新增配置项 `quickActions`(三层合并、随用户层持久化)。
|
|
152
|
+
设置页「快捷动作」区可启用/停用内置动作、为每个动作配独立快捷键、新增/删除自定义动作
|
|
153
|
+
(名称 + 问题指令 + 快捷键),问题指令支持 `{selection}` 占位符(内嵌选中正文;
|
|
154
|
+
不写占位符时原文按既有方式随问题附上)。内置 5 个动作的文案在客户端按界面语言解析,
|
|
155
|
+
配置与线协议保持语言中立。
|
|
156
|
+
- 宿主端新增**有界结构校验** `sanitizeQuickActions`:≤12 条、id 唯一且 ≤40 字符、
|
|
157
|
+
自定义动作名称 1–20 字 / 问题 1–500 字、快捷键 ≤40 字符;任何一条非法即**整表拒绝**
|
|
158
|
+
(`/config` 返回 `invalid-config`),不做半表保存。客户端保存前同样预检,
|
|
159
|
+
并检查动作快捷键之间、动作与主快捷键之间的冲突(大小写不敏感)。
|
|
160
|
+
- 每个动作的快捷键在页面 keydown 捕获阶段分发:主快捷键优先;在插件自己的输入框/编辑器中
|
|
161
|
+
不拦截任何快捷键;无选区时回退到最近一次触发候选(与主快捷键同语义)。
|
|
162
|
+
- **编辑问题后重新提问(改问重试)**:终态侧边卡片(已完成 / 失败 / 已停止)新增「改问」按钮,
|
|
163
|
+
就地编辑原问题后**重新生成当前这一轮**(不把旧问答压入 history,区别于"继续追问"的追加一轮);
|
|
164
|
+
原「重试」保留(原样重发,仅失败/停止态显示);空问题不触发。
|
|
165
|
+
- **代码块单独复制**:答案中的围栏代码块右上角新增复制按钮,复用既有剪贴板 API →
|
|
166
|
+
选区降级链与 toast 提示;`pre` 改为 `pre-wrap` 容器承载,代码文本与样式不变。
|
|
167
|
+
- 浮层/弹层样式新增 `.dsa-quickbar` / `.dsa-chip` / `.dsa-pre-wrap` / `.dsa-code-copy` /
|
|
168
|
+
`.dsa-qa-*`,并同步加入 Electron 窗口拖拽守卫(`-webkit-app-region:no-drag`)。
|
|
169
|
+
|
|
170
|
+
本机实测:verify 53 / contract 589 / float-placement 38 / smoke 181 = **861 项全部通过**
|
|
171
|
+
(较 1.6.0 的 577 项新增 284 项;含动作解析/占位符截断/快捷键冲突/宿主整表校验/
|
|
172
|
+
芯片与触发条渲染/quickAsk 与 retryEdit 端到端/代码块复制按钮/中英词典整表奇偶等用例)。
|
|
173
|
+
|
|
174
|
+
> 未验证(如实记录):浏览器与桌面 Electron 内的视觉观感与真实点按——本工作区无 GUI 自动化
|
|
175
|
+
> 接入运行实例,动作条换行/定位、芯片点击、代码块复制按钮、设置页编辑器需在真实页面按
|
|
176
|
+
> README 第九节路径人工确认;单测覆盖组件树与端到端数据流,替代不了观感验证。
|
|
177
|
+
|
|
178
|
+
## 1.6.0
|
|
179
|
+
|
|
180
|
+
**主题:最新版 DSH(0.2.1-alpha.2)适配 + 新旧包名共载时的单例护栏。**
|
|
181
|
+
|
|
182
|
+
十版本真机矩阵(隔离 DSH_HOME、真实安装启动、HTTP/探针双证据)发现并修复:
|
|
183
|
+
|
|
184
|
+
- **0.2.1-alpha.2 侧边作答引擎失效(真问题)**:该版本把 `subagents.start(provider, request)`
|
|
185
|
+
重构为受管激活 API `subagents.startActivation({provider, label, request, signal, delivery})`
|
|
186
|
+
(返回值由 `{id, localAgent, result, dispose}` 变为 `{childId, result, dispose}`)。
|
|
187
|
+
旧代码的能力门只认 `start()`,导致 provider 明明注册成功(spawn/fork)却自检显示
|
|
188
|
+
「侧边作答引擎:不可用」,侧答走降级。现按运行时方法面自动选择两代 API:新 API 用
|
|
189
|
+
`delivery: 'caller'` 保持"答案不进主对话"的旧语义,流式帧改由子会话 id 归因(新运行时不再
|
|
190
|
+
提供 live Agent 句柄)。0.1.5-rc.3~0.2.1-alpha.1 的调用路径保持不变。
|
|
191
|
+
- **新旧包名同时启用时双重触发(真问题)**:`dsh-selection-followup`(≤1.0.1 旧名)与
|
|
192
|
+
`dsh-sidecard-ask` 被同时装入一个 profile 时,选区旁叠出两个悬浮按钮,一次 Alt+Q 弹两个
|
|
193
|
+
提问框。现新增**页面内家族注册表**(`window.__dshSidecardFamily`):协作的副本按版本号选举
|
|
194
|
+
唯一领导者(同版本先加载者胜),落选副本保留设置页(显示停用说明横幅)但不挂载任何交互面、
|
|
195
|
+
不响应快捷键;无法协作的 1.0.x 旧版通过结构特征识别(无 owner 标记的 `dsa-layer`),
|
|
196
|
+
领导者注入一条样式规则隐藏其整个交互层,并提示卸载旧包。
|
|
197
|
+
- **data-slot 锚点自检结果不稳定(真问题)**:旧逻辑用"当前选区是否落在锚点链内"反推
|
|
198
|
+
"本版本是否支持锚点",选区落在直接挂 body 的节点(引导弹窗、第三方裸 DOM 面板)时会把
|
|
199
|
+
全局判定翻成"缺失",导致同一次自检两次结果不一致。改为构建级探测(全文档是否存在
|
|
200
|
+
`[data-slot]`),单个无锚点选区不再影响全局判定。
|
|
201
|
+
|
|
202
|
+
客户端自检上报新增 `family` 字段(leader/legacy/peers),宿主侧白名单做同样的长度裁剪。
|
|
203
|
+
|
|
204
|
+
本机实测:verify 53 / contract 323 / float-placement 38 / smoke 163 = **577 项全部通过**;
|
|
205
|
+
另在 0.2.0-rc.2 与 0.2.1-alpha.2 真机(headless)复核:两版引擎均可用、共载单实例、
|
|
206
|
+
锚点判定稳定、better-sidebar 0.25.0 承载面识别正常。
|
|
207
|
+
|
|
208
|
+
## 1.5.1
|
|
209
|
+
|
|
210
|
+
**主题:1.5.0 的发布收尾——把发布闸门补全,并把校验记录进版本号。**
|
|
211
|
+
|
|
212
|
+
功能与 1.5.0 **完全一致,没有任何行为改动**(`client.js` 与 `index.js` 只有版本号字符串不同,
|
|
213
|
+
可用 sha256 逐字节核对)。这个补丁版存在的理由是发布流程本身:
|
|
214
|
+
|
|
215
|
+
- `README` 第十三节的发布闸门原先只列了 `verify` / `contract-test` / `smoke-test` 三个脚本,
|
|
216
|
+
**漏掉了 1.5.0 新增的 `float-placement`**——照那一节执行会漏跑浮层几何用例(1.5.0 发布时就漏跑了,
|
|
217
|
+
事后才补上,38 项通过)。现已把 `node test/float-placement.mjs` 加进闸门,并把 `git tag v1.5.0`
|
|
218
|
+
改成 `git tag v<package.json 的 version>`,避免照抄上一版的标签号。**1.5.0 的 npm 包内 README 是补全前的版本,这一版起才是补全后的。**
|
|
219
|
+
- 版本号三处同步到 1.5.1:`package.json` 的 `version`、`index.js` 的 `PLUGIN_VERSION`、`client.js` 的 `CLIENT_VERSION`
|
|
220
|
+
(`test/verify.mjs` 会同时断言这三处一致)。这样 npm 上的 `latest` 带上了完整的闸门说明,
|
|
221
|
+
下一次发布不会再照着缺一行的清单执行。
|
|
222
|
+
- 1.5.0 的发布过程有个值得记的坑:`npm publish` 返回的是 **HTTP 202 "being processed"**,
|
|
223
|
+
之后约 2 分钟 registry 文档仍显示 `latest: 1.4.0`、`...-1.5.0.tgz` 还是 404。
|
|
224
|
+
这**不是失败**,不要立即重发(重发会撞版本已存在);等 2–5 分钟再查 `npm view dsh-sidecard-ask dist-tags` 即可。
|
|
225
|
+
|
|
226
|
+
本机实测(四项均 exit 0):verify 53 / contract 296 / float-placement 38 / smoke 138 = **525 项全部通过**。
|
|
227
|
+
|
|
228
|
+
## 1.5.0
|
|
229
|
+
|
|
230
|
+
**主题:浮层不再压住主对话——「A 胶囊 + C 右栏」定案,一个算宽度的纯函数 + 一个默认收起的形态。**
|
|
231
|
+
|
|
232
|
+
用户实测反馈(截图:原文被卡片尾部盖住):右下角卡片从 `right:16px` 往左固定铺 400px,
|
|
233
|
+
截图上(1400px 宽的窗口)对话区右边界 x≈971,而**卡片左边界 x≈858,压进对话区约 113px**。
|
|
234
|
+
如实记录一点:这个位置关系随帧宽变化——1400px 下理论值是 `1400−16−400=984`,本身并不越界;
|
|
235
|
+
问题是宽度写死 400px,窗口一窄就必然压住正文(这正是截图里的情形)。
|
|
236
|
+
同时定案 A(悬浮胶囊,可随时收起/隐藏)+ C(停靠原生右侧栏)。
|
|
237
|
+
|
|
238
|
+
### 位置:宽度由预算决定,不再固定 400px
|
|
239
|
+
|
|
240
|
+
- A1 新增纯函数 `floatPlacement({frameWidth, laneRight, railLeft, maxWidth})` →
|
|
241
|
+
`{width, avail, capped, bleeds}`:`avail = 帧宽 − 8 − 对话区右边界`,有右栏时再取
|
|
242
|
+
`min(avail, 帧宽 − 右栏左边界 − 10)`;`width = min(上限, max(240, avail))`。
|
|
243
|
+
语义是**浮层只使用对话区右侧那条预留带,不越过对话区右边界**;只有带宽跌破 240px(胶囊再窄就不可用)
|
|
244
|
+
才允许压入,并把这种情况如实报成 `bleeds`。
|
|
245
|
+
- A2 浮层 `right` 锚定帧右边缘,宽度写进 CSS 变量 `--dsa-float-w`(不再有 `width:min(400px,92vw)`);
|
|
246
|
+
挂载、窗口 resize、右栏开合(`ResizeObserver`)时重算,流式刷新只重渲染不清算几何。
|
|
247
|
+
- A3 新增配置 `floatMaxWidth`(240–560,默认 **340**):实际宽度是 `min(上限, 可用带宽)`。
|
|
248
|
+
旧的 400px 在多数窗口下本就超预算,故默认下调到 340。
|
|
249
|
+
- A4 浮层节点带 `data-layer-width` 与 `data-dsa-float-mode`:出问题时截图即可定位几何与形态。
|
|
250
|
+
|
|
251
|
+
### 形态:默认胶囊,随时收起或隐藏
|
|
252
|
+
|
|
253
|
+
- A5 新增配置 `floatMode`(`capsule` | `full` | `off`,默认 **`capsule`**):作答期只有一行,
|
|
254
|
+
完成后显示问题首句;`full` 展开为完整卡片栈;`off` 只留一个带计数的圆点启动器。
|
|
255
|
+
- A6 运行时可即时切换且**不写回配置**:卡片标题栏右侧新增两个**图标按钮**「⇥ 收起为胶囊 / × 隐藏浮层」
|
|
256
|
+
(完整文案放在 `title` 与 `aria-label`——中文全称 12 个字以上,写成文字会把标题栏挤成两行),
|
|
257
|
+
它们只改会话内状态(`state.floatMode`),刷新后回到设置页的默认形态——按一下隐藏不会变成永久设置。
|
|
258
|
+
这两个按钮只有浮层里的卡片才有;被原生右侧栏 tab 承载的同一张卡不传该回调,因此不出现(宿主 tab 不会遮挡对话区)。
|
|
259
|
+
- A7 设置页新增「浮层默认形态」「浮层宽度上限」两项控件。
|
|
260
|
+
|
|
261
|
+
### 视觉
|
|
262
|
+
|
|
263
|
+
- A8 卡片阴影 `0 10px 30px rgba(0,0,0,.22)` → `0 4px 16px rgba(0,0,0,.10)`
|
|
264
|
+
(DSH 主题**没有**阴影令牌,只能硬编码 rgba;数值参照其 14 个 `--dsw-alias-*` 令牌的对比度下调)。
|
|
265
|
+
|
|
266
|
+
### 测试
|
|
267
|
+
|
|
268
|
+
- 新增 `test/float-placement.mjs`:把几何写成断言——旧实现固定 400px,在**帧宽收窄**时左边界必然越到
|
|
269
|
+
对话区右边界左侧(用例 fixture:帧 1380 / 边界 980 / 右栏左界 1010 → 旧左边界 964 < 980,新实现同组不越界);
|
|
270
|
+
并如实保留一条「上报帧宽 1400 时旧实现 984 其实并未越界」,防止把一个随窗口变化的位置关系说成永远成立。
|
|
271
|
+
另含 8 种帧宽 × 4 种右栏宽的不变量(有空间就绝不越界);带宽条带与极端值(390px 带宽得 390 且 `capped`
|
|
272
|
+
为 false、`avail` 取夹取前的原始预算、NaN 退化到 240 而非 NaN、上限 9999 夹到 560、上限 10 夹到 240);
|
|
273
|
+
纯函数性(不改输入、同入同出);默认形态必须是 `capsule`;以及源码里旧固定 400px 规则确实已消失
|
|
274
|
+
(防止只改测试不改实现)。
|
|
275
|
+
- `test/contract-test.mjs` 的两面默认值等价断言(`pure.CLIENT_DEFAULTS` 对 `host.DEFAULT_CONFIG`)覆盖新键。
|
|
276
|
+
- **既有契约用例改为显式要求 `floatMode: 'full'`**:`test/contract-test.mjs` 里读卡片正文的三处
|
|
277
|
+
(思考过程、刷新后重放、渲染证明回退)本来依赖「浮层就是卡片栈」,而新的默认形态是胶囊——
|
|
278
|
+
这些用例断言的是**卡片内容**,所以它们显式要 `full`;胶囊这个默认值本身由 `float-placement` 断言。
|
|
279
|
+
不改它们的话,默认值一改就会三处变红,而那不是回归。
|
|
280
|
+
- 版本三处同步到 1.5.0:`package.json` 的 `version`、`index.js` 的 `PLUGIN_VERSION`、`client.js` 的
|
|
281
|
+
`CLIENT_VERSION`(`test/verify.mjs` 会同时断言这三处)。
|
|
282
|
+
|
|
283
|
+
### 本机实测结果(权威)
|
|
284
|
+
|
|
285
|
+
- `node --check` 对 `index.js`、`client.js` 与全部 `test/*.mjs`、`tools/compat-probe.mjs` 通过(exit 0)。
|
|
286
|
+
- `node test/verify.mjs` → **53 passed, 0 failed**(含 zh/en 两本词典的 `t()` 键覆盖断言)。
|
|
287
|
+
- `node test/contract-test.mjs` → **296 passed, 0 failed**。
|
|
288
|
+
- `node test/float-placement.mjs` → **38 passed, 0 failed**。
|
|
289
|
+
- `node test/smoke-test.mjs` → **138 passed, 0 failed**。
|
|
290
|
+
- 诚实记录:`float-placement` 第一轮报 **7 条红**,逐条查完**全部是我把测试写错**,实现未因此改动:
|
|
291
|
+
① 旧实现越界的 fixture 手算错(1420/991 那组其实不越界);② 一条断言把左右关系写成了负值恒假;
|
|
292
|
+
③④ 退化右栏用例期望 340/false,实测 240/true;⑤ 硬上限用例的 `avail` 只有 400,压根碰不到 560;
|
|
293
|
+
⑥ 新增的 `capped` 断言把语义写反(`capped` 指"被可用带宽限制",命中硬上限时为 false);
|
|
294
|
+
⑦ `avail` 断言误用了带右栏的用例(390 而非 421);⑧ 源码钩子去找根本不存在的
|
|
295
|
+
`setFloatMode('capsule')` 调用——控制项实际走 `floatControl('capsule','floatCollapse','⇥')` 的
|
|
296
|
+
`onFloatMode` 回调,正则已改。
|
|
297
|
+
- 本版一度新增 `tools/balance-check.mjs` 与 `tools/i18n-check.mjs` 两个「替代检查」,**现已删除**:
|
|
298
|
+
它们本身是错的——前者用「正则字面量 vs 除号」的启发式,把 8 个源文件全部误报为残损;
|
|
299
|
+
后者定位词典块的缩进假设写错,解析出 0 个键并误报上百条缺失。会撒谎的检查器比没有检查器更糟。
|
|
300
|
+
|
|
301
|
+
> 仍未验证:**浏览器内的视觉观感**(浮层实际宽度是否等于预算、是否真的不越过对话区右边界)。
|
|
302
|
+
> 请按 README 第九节 **A 路径第 8 条**在真实页面确认(读 `data-dsa-float-mode` 与 `data-layer-width`),
|
|
303
|
+
> 单测替代不了这一步。1.5.0 前半段本工作区 shell 工具整体不可用
|
|
304
|
+
> (`SetNamedSecurityInfoW failed (Win32 5)`),当时的改动确实没跑过任何命令;故障解除后才补跑上述四项。
|
|
305
|
+
|
|
306
|
+
## 1.4.0
|
|
307
|
+
|
|
308
|
+
**主题:一次系统性的代码走查——19 项改进,功能缺口、正确性边界、i18n、代码卫生一次补齐。**
|
|
309
|
+
|
|
310
|
+
### 功能缺口(A)
|
|
311
|
+
|
|
312
|
+
- **A1 设置页补齐控件**:`sideTimeoutMs`(5000–3600000,即宿主侧接受的范围)与 `sideProvider`
|
|
313
|
+
(下拉,选项来自 `/state` 实际报告的 provider 列表,默认 `auto`)此前宿主接受但设置页没有控件,
|
|
314
|
+
只能手改 `config.json`——现在设置页直接可改。
|
|
315
|
+
- **A2 思考过程可见**:子代理的 `reasoning` 帧此前被丢弃;现在卡片上以**可折叠的「思考过程」区**展示,
|
|
316
|
+
流式期间与答案同窗口合并提交,复制答案不含思考文本。
|
|
317
|
+
- **A3 原生右侧栏 tab 可关闭**:此前的「关闭」只撤掉渲染证明、tab 留成空壳;现在真正关闭 tab
|
|
318
|
+
并携带空态文案,关闭失败的兜底路径(回退关 tab)一并处理。
|
|
319
|
+
- **A4 卡片持久化**:已完成(含已停止且非空)的侧边卡片镜像进 `localStorage`(schema `v1`,
|
|
320
|
+
最多 10 张、单卡文本上限 64K),页面刷新后重放进浮层卡片栈(原生/better 的 tab 无法跨刷新存活);
|
|
321
|
+
隐私模式、配额满、数据被篡改一律降级为「无历史」,不阻断启动。
|
|
322
|
+
- **A5 流式自动滚动**:侧边卡片答案流式增长时自动滚动到底部(仅当用户已在底部附近,不打断上翻)。
|
|
323
|
+
- **A6 markdown-lite 扩展**:行内新增斜体与链接(链接协议白名单 http/https、`noopener` 打开,
|
|
324
|
+
模型输出不可能造出 `javascript:` URL);块级新增引用块与表格(此前行内只有代码/粗体,
|
|
325
|
+
块级只有代码块/列表/标题)。
|
|
326
|
+
|
|
327
|
+
### 正确性与边界(B)
|
|
328
|
+
|
|
329
|
+
- **B7 渲染证明竞态**:同一卡片在两个承载面(原生右侧栏与 better-sidebar)同时出现过的窗口期,
|
|
330
|
+
第二面的渲染证明会顶掉第一面;现在挂载即撤销旧证明,回退路径改为关闭 tab 而非仅撤证明。
|
|
331
|
+
- **B8 码点计数**:截断、徽标、`minChars` 全部从 UTF-16 单元计数改为 **Unicode 码点**计数
|
|
332
|
+
(两端 `truncateSelection` 同步,契约测试断言等价):emoji 或扩展区汉字不再被数成两个字符、
|
|
333
|
+
截断不再切半个代理对。
|
|
334
|
+
- **B9 流式增量节流合并**:每个流式 delta 曾触发一次全卡重渲染(整卡 re-render + 全文重解析,
|
|
335
|
+
长答案下是二次方开销);现在 50ms 窗口内合并为一次提交,终止事件(done/error/cancel/close)
|
|
336
|
+
先冲刷缓冲再落终态,**不丢任何流式文本**;关闭卡片会丢弃未冲刷的缓冲(冲刷 tick 不复活已关卡片)。
|
|
337
|
+
|
|
338
|
+
### i18n 与一致性(C)
|
|
339
|
+
|
|
340
|
+
- **C10 宿主错误消息本地化**:含义完全已知的错误码(`too-large`/`busy`/`aborted` 等)在英文界面
|
|
341
|
+
显示英文文案,不再显示宿主拼接的中文消息;携带实时诊断的错误码(`engine-error`/`blocked-step` 等)
|
|
342
|
+
**保留宿主原文**(那是原因唯一所在,替换即丢失)。
|
|
343
|
+
- **C11 子代理提示词统一英文**:`buildSidePrompt` 生成的指令段落统一英文,与 persona 语言一致。
|
|
344
|
+
- **C12 语言解析集中化**:`resolveLanguage()` 集中解析,优先 `navigator.languages` 逐项回退,
|
|
345
|
+
不再散落多处手写判断。
|
|
346
|
+
|
|
347
|
+
### 代码卫生(D)
|
|
348
|
+
|
|
349
|
+
- **D13 停止/关闭真正终止子代理**:此前只中断浏览器端流;现在同时 `POST /cancel`,宿主侧运行
|
|
350
|
+
登记表真正清空(子代理不再跑到超时)。
|
|
351
|
+
- **D14 移除载荷死字段 `cross`**:ask 载荷里宿主从不读取的字段,连同客户端构造一并删除
|
|
352
|
+
(`zoneLabel` 的 `candidate.cross` 显示逻辑保留——那是客户端自用)。
|
|
353
|
+
- **D15/D17 dispose 对称清理**:所有 `ctx.inject` 的返回反注册都保存并在 dispose 时调用,
|
|
354
|
+
不再只清理部分订阅;补齐一处缩进格式问题。
|
|
355
|
+
- **D16 历史轮数常量化**:卡片继续追问携带的历史轮数从两处裸 `6` 提为导出常量 `HISTORY_TURNS`
|
|
356
|
+
(客户端与宿主各自导出,契约测试断言两值相等,且宿主提示词只保留最近 N 轮)。
|
|
357
|
+
- **D18 触发按钮宽度自适应**:视口钳制宽度从按中文估的硬编码 132px 改为按**当前语言文案**估算
|
|
358
|
+
(CJK 全宽、其余 ~0.55em + 固定 chrome 余量):英文按钮("Ask about selection")比中文宽约 50px,
|
|
359
|
+
此前选区靠右时会溢出视口右缘;样式加 `white-space:nowrap` 杜绝挤压折行。
|
|
360
|
+
|
|
361
|
+
### 可选加固(E)
|
|
362
|
+
|
|
363
|
+
- **E19 信任围栏端口比较**:`isTrustedRequest` 的 Origin 与 Host 比较改为**完整 authority(host:port)**——
|
|
364
|
+
同主机名不同端口的 Origin 是不同源,此前只比主机名会放行;`trustedHosts` 条目带端口时只信任该端口,
|
|
365
|
+
不带端口则信任该主机全部端口(管理员语义)。
|
|
366
|
+
|
|
367
|
+
### 其他
|
|
368
|
+
|
|
369
|
+
- 修复契约测试中 B9 用例的定时器竞态(Windows 定时器粒度 ~15.6ms 下,80ms 的 done 门与 65ms 的
|
|
370
|
+
检查点余量不足;门移至 130ms 并放宽后续等待)。
|
|
371
|
+
|
|
372
|
+
自测 336 → **487 项**(verify 53 / contract 296 / smoke 138),契约测试连跑 5 次全绿。
|
|
373
|
+
|
|
374
|
+
## 1.3.2
|
|
375
|
+
|
|
376
|
+
**主题:核对并适配 DSH 桌面版(Electron,0.2.0-rc.2)。**
|
|
377
|
+
|
|
378
|
+
核对结论(实测,详见 README §5.3):
|
|
379
|
+
|
|
380
|
+
- 桌面版是**独立运行形态**:Electron-as-Node 跑 `app.asar\dsh\...\dsh-desktop-host`,框架包全在 `app.asar` 内,
|
|
381
|
+
自带 node 24.18.1 + pnpm 11.7.0;`DSH_PROFILE=desktop`,与 web 版的 `profiles\web` **各自独立**;
|
|
382
|
+
- 本插件在桌面 profile 中已登记(`link:D:/Users/34332/AI/dsh-sidecard-ask` + `dsh.profile.bundles`),
|
|
383
|
+
**无需改动即加载**:宿主半 `v1.3.1` 正常,客户端自检上报显示三个槽位落点正常、两个适配器均可用,
|
|
384
|
+
真机 `start→reasoning×106→delta×46→status→done`(1.89 s)通过;
|
|
385
|
+
- 桌面版用的 dsh-better-sidebar 是 **0.24.1**:与 0.22.1 的消费端契约差异**纯增量**
|
|
386
|
+
(`target` 增加 `'side'`、新增可选 `preferNewPane`),本插件不传这两项 → 不受影响。
|
|
387
|
+
|
|
388
|
+
**桌面特有修改:窗口拖拽区防御。** 桌面外壳把顶层元素标记为窗口拖拽区(`-webkit-app-region: drag`),
|
|
389
|
+
落在其中的点击会变成拖动窗口;同生态的 dsh-better-sidebar 为此专门带了一条防御,而本插件的浮层此前没有。
|
|
390
|
+
现在样式表为每个自有根节点声明 `-webkit-app-region:no-drag`(`.dsa-layer/.dsa-trigger/.dsa-pop/.dsa-stack/
|
|
391
|
+
.dsa-card/.dsa-toast/.dsa-settings`),并有回归测试锁定该规则(含"该规则是真实规则而非只出现在注释里"的断言)。
|
|
392
|
+
该属性在浏览器中无效,web 版不受影响。
|
|
393
|
+
|
|
394
|
+
**确认无需改动的部分**:`styles.insert` / `host.call` 只属于**动态**客户端半(本插件是静态形态,官方等价做法
|
|
395
|
+
就是手工插 `<style>`,宿主通信走自有 HTTP 路由);名为 `shortcuts` 与 `conversation` 的客户端服务在运行实例中
|
|
396
|
+
**都不存在**(inspection 报 `no catalogued Service`),因此快捷键与 composer 草稿保持既有实现与占位降级。
|
|
397
|
+
|
|
398
|
+
自测 327 → **336 项**(verify 53 / contract 149 / smoke 134)。
|
|
399
|
+
|
|
400
|
+
## 1.3.1
|
|
401
|
+
|
|
402
|
+
**主题:让"两半代际不一致"成为一个被处理的状态,而不是噪声。**
|
|
403
|
+
|
|
404
|
+
这个插件的宿主半只在**重启 DSH** 时更新,客户端半在**页面加载**时更新,所以"新客户端 + 旧宿主"是结构性常态
|
|
405
|
+
(当前本机就是这个状态:页面已跑到 1.3.x,宿主仍是重启前的 1.2.0)。
|
|
406
|
+
|
|
407
|
+
- 客户端在自检上报被宿主以 `not-found`(该路由还不存在,旧宿主)、`bad-response`(SPA 兜底返回 HTML)
|
|
408
|
+
或 `unreachable` 拒绝时,**记住"此宿主不支持自检"并停止重试**,只打一条 info 说明"重启 DSH 后生效";
|
|
409
|
+
其它错误(例如配置类真实错误)仍按 warning 记录,不会错误地关闭通道。
|
|
410
|
+
- 新增纯函数 `isDiagnosticsUnsupported(error)` 并纳入契约测试(5 条断言覆盖各错误码)。
|
|
411
|
+
|
|
412
|
+
自测 322 → **327 项**(verify 53 / contract 140 / smoke 134)。
|
|
413
|
+
|
|
414
|
+
## 1.3.0
|
|
415
|
+
|
|
416
|
+
**主题:把"客户端半的状态"变成宿主可读——补上导致前两次缺陷排查困难的观测盲点。**
|
|
417
|
+
|
|
418
|
+
- 新增 **`POST /sidecard-ask/api/diagnose`**:客户端半在启动、槽位落点变化、承载面回退时把一份受限摘要
|
|
419
|
+
(客户端版本、当前承载面、区域锚点是否可用、三个槽位的真实落点、两个适配器的可用性与失败原因、
|
|
420
|
+
侧边卡片插件的版本与能力列表)上报给宿主;`GET /state` 的 **`value.client`** 即可读到。
|
|
421
|
+
宿主对上报做**白名单 + 截断**(未知键丢弃、字符串 ≤200 字符、能力列表 ≤40 项、槽位 ≤8 项)。
|
|
422
|
+
- 客户端版本改为单一常量 `CLIENT_VERSION`:自检上报与 `api.version` 同源,报告不会声称一个页面其实没在跑的版本。
|
|
423
|
+
- 此前两次客户端静默失效(原生 tab 类型因 kind 冲突从未注册;客户端产物是上一代)都只能靠人工翻阅
|
|
424
|
+
槽位清单才发现,这条通道把它们变成一条命令就能查到的事实。
|
|
425
|
+
|
|
426
|
+
**同时复核 1.2.1 的修复在运行实例上生效**:`sidebar.right.pane.tab` 的占用者现在**同时**包含
|
|
427
|
+
`sidecard-ask:card`(本插件原生右侧栏)与 `dsh-better-sidebar:sidecard-ask:card:workbench`(better-sidebar 镜像),
|
|
428
|
+
两者均 active——kind 冲突已消除。
|
|
429
|
+
|
|
430
|
+
自测 295 → **322 项**(verify 53 / contract 135 / smoke 134),新增用例覆盖上报的接收、白名单裁剪、
|
|
431
|
+
截断、非法体拒绝,以及客户端上报体的构造。
|
|
432
|
+
|
|
433
|
+
## 1.2.1
|
|
434
|
+
|
|
435
|
+
**主题:核对 DSH 0.2.0-rc.1 的适配性,并修掉由此暴露的一个真实缺陷。**
|
|
436
|
+
|
|
437
|
+
核对(本机运行中的就是 0.2.0-rc.1,`@deepseek-ai/dsh` 的 `next` 通道):
|
|
438
|
+
|
|
439
|
+
- 包内容层面:`node tools/compat-probe.mjs 0.1.7-rc.2 0.2.0-rc.1` → 16 项能力**逐项一致**,没有任何依赖被移除或改名;
|
|
440
|
+
- 运行实例上:宿主半 `v1.2.0` 正常(`sideEngine`、provider `spawn,fork`、`capabilities.parent` 均可用);
|
|
441
|
+
客户端半在 `shell.overlay` / `conversation.input.right` 都已注册;`standardProps` 仍含 `sessionId` 与 `inputActions`;
|
|
442
|
+
真机端到端作答 `start→delta×31→status→done`(1.36 s)通过。新增的 `sessions.fork`/`uiWorkspace.forkSession`
|
|
443
|
+
可选参数 `onCreated` 是纯增量,不影响既有调用。
|
|
444
|
+
|
|
445
|
+
**修掉的缺陷**:`sidebar.right.pane.tab` 的运行清单里只有 `dsh-better-sidebar:sidecard-ask:card`,
|
|
446
|
+
没有本插件原生右侧栏的 `sidecard-ask:card`——两个适配器用了同一个 tab kind,而 better-sidebar 会把每个 tab 描述符
|
|
447
|
+
镜像注册进**同一个**原生注册表(band `extension`),该注册表对同 band 同 kind 的二次注册抛错,后注册的一方静默失败。
|
|
448
|
+
|
|
449
|
+
- better-sidebar 承载面改用独立类型 `sidecard-ask:card:workbench`(`CARD_KIND_BETTER`),两端不再重叠;
|
|
450
|
+
- `contract-test` 新增"surface kinds must not collide"一节:**在测试里模拟该注册表的重复 kind 抛错规则**
|
|
451
|
+
与 better-sidebar 的镜像注册行为,若两者再共用 kind,测试立即失败;
|
|
452
|
+
- 设置页自检行改为同时报告**两个适配器**(原先原生适配器的错误在界面上不可见,只能靠翻槽位清单发现)。
|
|
453
|
+
|
|
454
|
+
自测 289 → **295 项**(verify 53 / contract 124 / smoke 118)。
|
|
455
|
+
|
|
456
|
+
## 1.2.0
|
|
457
|
+
|
|
458
|
+
**主题:核对并加固与 dsh-better-sidebar 0.22.1 的适配。**
|
|
459
|
+
|
|
460
|
+
核对方式(可复现):把 0.22.0 与 0.22.1 的发布产物都拉下来解包,逐文件 SHA256 比对。结论:
|
|
461
|
+
|
|
462
|
+
- 消费端契约 `lib/types/client/service.d.ts` **除 `SIDEBAR_SERVICE_VERSION` 常量外逐字节相同**;
|
|
463
|
+
`SIDEBAR_FEATURES`、`dsh.client.inject`、peer 依赖均未变;
|
|
464
|
+
- 0.22.1 唯一的大体量改动是它**自己** `src/client/native/index.ts` 的健壮性修复(`disposeSafely` +
|
|
465
|
+
槽位注册失败时回滚已注册的 tab 类型),不涉及本插件调用的任何字段;
|
|
466
|
+
- 本插件用到的 `registerTab / openTab(seed, scope) / closeTab / features / version` 全部仍在。
|
|
467
|
+
|
|
468
|
+
即 **0.22.1 下无需改动即兼容**。据此做了三处加固:
|
|
469
|
+
|
|
470
|
+
1. **按能力而非版本判断**:适配器仅在 `features` 含 `tabMeta` 时可用(该能力自 better-sidebar 0.12 起提供,
|
|
471
|
+
更早的版本会打开一个读不到 `meta.cardId` 的空 tab);不满足时 `auto` 跳到原生右侧栏/内置浮层,
|
|
472
|
+
并在自检里给出 `no-tab-meta`。
|
|
473
|
+
2. **原生承载面注册回滚**:先注册 tab 类型再注册槽位,槽位注册抛错时释放已占用的类型 id
|
|
474
|
+
(正是 0.22.1 在自己原生胶水里修的同类问题,否则该 kind 会永久占用、渲染宿主"无实现"的空面)。
|
|
475
|
+
3. **运行时可见**:设置页「运行自检」新增一行,显示侧边卡片插件**自己报告的 `version` 与能力项数**,
|
|
476
|
+
以及本插件对它的判定(可用 / 版本过旧 / 未检测到)。
|
|
477
|
+
|
|
478
|
+
自测 276 → **289 项**(verify 53 / contract 118 / smoke 118),新增用例覆盖:0.22.1 形状的服务被接受、
|
|
479
|
+
`openTab(seed, scope)` 的字段与作用域、缺 `tabMeta` 时被拒绝并落到浮层、缺 `registerTab` 时被拒绝、
|
|
480
|
+
槽位注册失败时类型被释放且适配器转为不可用。
|
|
481
|
+
|
|
482
|
+
## 1.1.0
|
|
483
|
+
|
|
484
|
+
**改名:`dsh-selection-followup` → `dsh-sidecard-ask`**(显示名「划词追问」→「侧边卡片追问」)。
|
|
485
|
+
|
|
486
|
+
原因(可复核):
|
|
487
|
+
|
|
488
|
+
- `dsh-selection-followup` 在 **DSH 插件生态里已被他人使用**——GitHub 仓库
|
|
489
|
+
`zzx-dear/dsh-selection-followup` 与官方收录索引 `data/plugins/zzx-dear__dsh-selection-followup.yml`
|
|
490
|
+
(category: ui),早于本插件约 20 天。1.0.0 发布时只核对了 npm 名字是否可用(当时为空),
|
|
491
|
+
**没有核对 GitHub 仓库名与收录索引**,这是本项目的疏漏。
|
|
492
|
+
- 新名 `dsh-sidecard-ask` 的 npm 包名与 GitHub 仓库名都已核对为空,并且与既有的
|
|
493
|
+
`dsh-selection-ask` / `dsh-selection-explain` / `dsh-selection-toolbar` / `dsh-quote-selection` /
|
|
494
|
+
`dsh-ui-quote-selection` / `dsh-quote-annotate` / `dsh-selection-memory` / `dsh-plugin-followup`
|
|
495
|
+
在名字与定位上都区分开:本插件由**独立子代理在侧边卡片里流式作答**,不是把选中内容塞进输入框。
|
|
496
|
+
|
|
497
|
+
随之变更的标识(旧 → 新):
|
|
498
|
+
|
|
499
|
+
| 项 | 旧 | 新 |
|
|
500
|
+
|---|---|---|
|
|
501
|
+
| npm 包名 / bundle 名 | `dsh-selection-followup` | `dsh-sidecard-ask` |
|
|
502
|
+
| 宿主行 id | `selection-followup` | `sidecard-ask` |
|
|
503
|
+
| 插件自有路由 | `/selection-followup/api` | `/sidecard-ask/api` |
|
|
504
|
+
| 客户端模块 id / 槽位条目 id | `dsh-selection-followup` / `selection-followup` | `dsh-sidecard-ask` / `sidecard-ask` |
|
|
505
|
+
| 侧边卡片类型 | `selection-followup:card` | `sidecard-ask:card` |
|
|
506
|
+
| 用户配置目录 | `<DSH_HOME>/selection-followup/` | `<DSH_HOME>/sidecard-ask/` |
|
|
507
|
+
| 显示名(Plugins 页 / 设置页) | 划词追问 | 侧边卡片追问 |
|
|
508
|
+
|
|
509
|
+
其它:`package.json` 增加中英文关键词(划词 / 选中追问 / 侧边卡片);自测同步改名,仍是 **276 项全通过**;
|
|
510
|
+
旧 npm 包名已 `deprecate` 指向新名字。功能与 API 与 1.0.1 完全一致,**升级只需卸旧装新**(见 README §三)。
|
|
511
|
+
|
|
512
|
+
## 1.0.1
|
|
513
|
+
|
|
514
|
+
**主题:把"版本适配"从字段笔记变成可验证的适配。**
|
|
515
|
+
|
|
516
|
+
- 新增 `tools/compat-probe.mjs`:从 npm 拉取 **13 个 DSH 版本**(0.1.2-rc.1 → 0.1.7-rc.2)
|
|
517
|
+
× **12 个相关包**的已发布产物,解包后按标记字符串判定能力,输出矩阵(结果写进 README §7)。
|
|
518
|
+
据此确认的缺口与适配:
|
|
519
|
+
- **原生右侧栏**(0.1.2 / 0.1.3 缺)→ 承载面探测链已有降级;
|
|
520
|
+
- **主对话提交**(≤0.1.6-alpha.1 既无 `using` 也无 `retain`)→ 新增四级提交阶梯
|
|
521
|
+
`using → retain+release → 槽位标准 prop inputActions(setDraft+submit) → 仅写草稿`,逐级探测并回报实际生效的一级;
|
|
522
|
+
- **归档会话门**(仅 0.1.7-alpha.1+ 存在)→ 修正上一版引入的误伤:不再对归档父会话一刀切拒绝,
|
|
523
|
+
改为优先挑未归档代理、只剩归档候选时照常尝试并在 `start` 事件标注 `parentArchived`;
|
|
524
|
+
- **流式帧**(0.1.2-rc.1 无 `agent/assistant-stream`)→ 新增第二条流式源,桥接该版本持久化的
|
|
525
|
+
`assistant/chunk` 会话事件,与帧源互斥(先到者生效,绝不重复累计文本),并在 `done` 里给出 `streamSource`。
|
|
526
|
+
- **新增槽位阶梯**:浮层 / 设置页 / 会话采集各自在多个等价 `list` 槽位间回退(先到者胜,更好的槽位后到会顶掉兜底),
|
|
527
|
+
诊断里记录真实落点;`single` 槽位一律不碰(避免替换宿主 UI)。
|
|
528
|
+
- **区域锚点缺失时不再静默失效**:检测不到 `data-slot` 时停用区域过滤并在自检里说明(原先 `captureZones:chat` 会永远不触发)。
|
|
529
|
+
- **provider 能力门控**:只发送 provider 声明支持的启动字段(`capabilities.persona/toolFilter`),
|
|
530
|
+
`persona` 不支持时内联进提示词,`toolFilter` 不支持时在卡片上明说"本次继承了会话工具"。
|
|
531
|
+
- **路由注册降级**:`prefix` 路由被拒时退化为逐方法精确路由。
|
|
532
|
+
- 自测从 236 项扩到 **276 项**(verify 53 / contract 105 / smoke 118),新增用例覆盖上面每一条降级路径。
|
|
533
|
+
|
|
534
|
+
## 1.0.0
|
|
535
|
+
|
|
536
|
+
首个版本(发布名 `dsh-sidecard-ask`:npm 上的 `dsh-selection-ask` 已被他人占用)。
|
|
537
|
+
|
|
538
|
+
- **划词追问**:在聊天区 / 任务区选中文本,选区末端就地浮出「追问选中内容」按钮,点击弹出提问框。
|
|
539
|
+
- **两种作答承载**:主对话(引用块进入当前会话,答案原生流式)与独立侧边卡片(子代理在自己的会话里作答,零父上下文),可在提问框临时切换并配置默认值。
|
|
540
|
+
- **侧边承载面适配**:DSH 原生右侧栏 → `dsh-better-sidebar` → 内置浮层卡片,三层能力探测自动降级;未安装侧边卡片插件时功能完整。
|
|
541
|
+
适配器"接受打开但没渲染"时由**渲染证明**在 600ms 后把卡片移到内置浮层,不会留下空 tab。
|
|
542
|
+
- **流式渲染**:宿主半把 `agent/assistant-stream` 帧桥接到 SSE;卡片支持关闭、复制、继续追问、停止作答、重试。
|
|
543
|
+
- **边界处理**:空选/过短、编辑框内选择、跨区选择、超长截断(两端算法一致)、接口失败逐层降级、重复触发抑制、并发上限、请求超时、卸载清理。
|
|
544
|
+
- **配置三层**:内置默认 ← bundle 补丁 ← 用户层(`<DSH_HOME>/sidecard-ask/config.json`,原子写入),设置页可视化编辑 + 运行自检。
|
|
545
|
+
- **零运行时依赖**:宿主半只用 `node:` 内建;客户端半只 `require('react')`。
|
|
546
|
+
- 附带三套可运行自测(236 项):`test/verify.mjs`、`test/contract-test.mjs`、`test/smoke-test.mjs`。
|
|
547
|
+
|
|
548
|
+
### 真实宿主联调中发现并修掉的问题(DSH 0.1.7-rc.2)
|
|
549
|
+
|
|
550
|
+
1. **`tools.restrict()` 会拒绝未知工具名**:硬编码的只读工具白名单里有若干本组合不存在的名字,导致子代理启动即失败。
|
|
551
|
+
现在白名单在调用时与 `tools.schemas()` 求交,交集为空则完全不传 `toolFilter`。
|
|
552
|
+
2. **`req.on('close')` 不是"浏览器断开"**:Node 的 `IncomingMessage` 在请求体读完时就触发 `close`,用它作断线信号会在请求体结束的瞬间取消作答。
|
|
553
|
+
改为只监听 `res.on('close')`,并要求 `res.writableEnded !== true`。
|
|
554
|
+
3. **父会话可能已被归档**:宿主的归档门会拒绝整条子代理血统的每一步(空 turn → 子代理接缝记为 `refusal`),
|
|
555
|
+
而 `agents.roots()[0]` 可能正好落在归档会话上。现在按"提问会话 → 首个未归档活动代理"选择父代理,
|
|
556
|
+
候选全部归档时直接返回 `parent-archived`;其它 `refusal` 也被翻译成可读的 `blocked-step`。
|
|
557
|
+
4. **终止事件必须最后**:末尾多余的 `status{settled}` 会让"最后一个事件是终局"的读法失效,已移除。
|
|
558
|
+
5. **`/config` 之后的 `provenance.persisted` 是启动时的快照**:保存后仍显示未持久化,改为按当前用户层实时计算。
|