@yfwu2020/dsh-selection-explain 0.1.2 → 0.2.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/LICENSE +21 -0
- package/README.md +103 -13
- package/assets/code.png +0 -0
- package/assets/stage1.png +0 -0
- package/assets/stage2.png +0 -0
- package/assets/web.png +0 -0
- package/cordis.patch.yml +4 -0
- package/lib/client.js +727 -1
- package/lib/index.js +8 -0
- package/lib/index.js.map +1 -1
- package/lib/types/index.d.ts +20 -0
- package/package.json +5 -2
- package/scripts/build-demo-pages.mjs +296 -0
- package/scripts/crop-png.mjs +142 -0
- package/scripts/smoke-bridge.mjs +365 -0
- package/scripts/test-bridge.mjs +408 -0
- package/scripts/test-client.mjs +221 -1
- package/src/client/index.js +727 -1
- package/src/index.ts +18 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 yfwu2020
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
> 在 [DSH](https://github.com/deepseek-ai) Web 界面里**选中任意文字**,就地得到**专业翻译** + **这段文字在当前上下文里到底是什么意思**,还能接着追问、或一键升格成正式会话。
|
|
4
4
|
|
|
5
|
-
[](https://github.com/yfwu2020/dsh-selection-explain/releases)
|
|
6
|
+
[](https://www.npmjs.com/package/@yfwu2020/dsh-selection-explain)
|
|
6
7
|
[](./package.json)
|
|
7
8
|
[](https://github.com/yfwu2020/dsh-selection-explain)
|
|
8
9
|
|
|
@@ -24,6 +25,8 @@
|
|
|
24
25
|
|
|
25
26
|
点开面板**先只出翻译**(上下文窗口收窄到 8 条消息,首字最快);翻译出来后才出现 **`↓ 展开详解`**,点了才用完整会话背景(24 条消息)做深度解读。想要快就停在第一段,想要透就展开——**不强迫你为深度等首字**。
|
|
26
27
|
|
|
28
|
+
<img src="assets/stage1.png" alt="首轮:只有翻译一节 + 展开详解按钮" width="540">
|
|
29
|
+
|
|
27
30
|
### 翻译:按选中内容的语言和形态自适应
|
|
28
31
|
|
|
29
32
|
不是无脑翻译,而是先判断这段文字是什么,只给对应的那一种:
|
|
@@ -49,6 +52,8 @@
|
|
|
49
52
|
|
|
50
53
|
如果选中的是代码(在 `<pre>/<code>` 里,或文本特征像代码),首轮标题变成「**注释**」:整个回答是一个代码块,里面是**注释 + 原代码交替**的批注清单——每条语句**前面**一行该语言的注释符号(`//`、`#`、`--`、`<!--`…),原代码逐字不变。注释行弱化显示,一眼分得清哪行是代码、哪行是批注。缩进按原行起始列对齐,折行也不会跑到注释左边。
|
|
51
54
|
|
|
55
|
+
<img src="assets/code.png" alt="选中代码:注释与原代码交替的批注清单" width="540">
|
|
56
|
+
|
|
52
57
|
### 临时对话小窗
|
|
53
58
|
|
|
54
59
|
翻译一出来就能直接追问,不必先展开详解:
|
|
@@ -59,6 +64,30 @@
|
|
|
59
64
|
- 生成中可以点**停止**打断;没有可用结果时给「重新生成」。
|
|
60
65
|
- 关掉面板**不会丢**:点右下角胶囊原样回来,不重新请求。
|
|
61
66
|
|
|
67
|
+
<img src="assets/stage2.png" alt="展开详解后:翻译与详解两节卡片,下方可继续追问" width="540">
|
|
68
|
+
|
|
69
|
+
### 输出偏好:Markdown ↔ 网页
|
|
70
|
+
|
|
71
|
+
输入区左下角那个两格开关(`M↓` = Markdown / `▭` = 网页)决定**追问的回答用什么形式**。默认是 **Markdown**,选择记在浏览器本地,下次打开还是它。
|
|
72
|
+
|
|
73
|
+
| 档位 | 行为 |
|
|
74
|
+
| --- | --- |
|
|
75
|
+
| **Markdown**(默认) | 普通文字 / Markdown 回答——标题、列表、表格、代码块都可以。**并不禁止 HTML**:如果某个问题用一页网页明显讲得更清楚,照样会给网页;只是不会为了"好看"把简单问题做成页面 |
|
|
76
|
+
| **网页** | **网页优先**(不是"一律网页"):需要对比、流程、层级、图表,或文字答案会长到不好读 → 直接给**完整的单文件 HTML**,页面本身就是答案;一两段话能说清的简单问题**仍然用文字回答** |
|
|
77
|
+
|
|
78
|
+
<img src="assets/web.png" alt="网页模式:回答里嵌一张可交互的页面,带「预览 / 源码」切换" width="540">
|
|
79
|
+
|
|
80
|
+
**网页输出的优点**(也是它值得单独一档的原因):
|
|
81
|
+
|
|
82
|
+
- **复杂信息能"看"而不是"读"**:三种方案的取舍做成对照表 + 条形图,一眼看出差别;文字版要读三段才建立同样的印象。
|
|
83
|
+
- **页面就是答案,不是附件**:生成的是**完整单文件 HTML**(样式与脚本全内联),小窗当场渲染成可交互页面——能悬停、能点、能滚,不用保存成文件再打开。
|
|
84
|
+
- **两个视图随时切**:回答上方有 `预览 / 源码` 两个页签,切到源码就能把 HTML 拿走。
|
|
85
|
+
- **默认就整页展示**:预览高度**由页面内容决定**(内部不滚动),所以一页对比表能完整看下来;想收起来点右侧 **`⤡ 还原`**,回到固定高度(320px、内部滚动)。
|
|
86
|
+
- **有设计规范兜底**:开网页模式时,插件会把自己带的 `skills/web-design/SKILL.md` 注入提示词——按小窗**约 500px 宽的窄容器**写的单列布局规范,避免生成那种"三栏卡片 + 渐变大标题"的通用 AI 模板感。(该文件读不到时有一份内置兜底,不会因此失败。)
|
|
87
|
+
- **回答仍然可追问**:网页结果会作为前情带回下一轮,可以继续说"把第二列改成时间线"。
|
|
88
|
+
|
|
89
|
+
**什么时候别用网页**:只想要一段解释、或要的是可以直接复制的文本时,Markdown 更快也更省 token——网页要生成一整份 HTML,等待时间和输出长度都更大。
|
|
90
|
+
|
|
62
91
|
### 「最近聊过的」历史
|
|
63
92
|
|
|
64
93
|
面板头部 `🕘 最近` 打开独立浮层列表(贴面板侧边,空间不够自动翻到另一侧)。重划同一个词**直接回放上次的对话,一次模型都不调**。默认保留最近 20 个划词条目(每个条目含它自己的全部追问),LRU 淘汰,**升格过的条目不会被淘汰**。
|
|
@@ -73,10 +102,54 @@
|
|
|
73
102
|
|
|
74
103
|
右下角一枚胶囊显示"最近一次划词现在什么状态"(进行中报阶段和秒数、其余报结果),点一下回到那个小窗。它会自动贴到费用胶囊上方。
|
|
75
104
|
|
|
105
|
+
### 侧边栏网页里也能划词
|
|
106
|
+
|
|
107
|
+
侧边栏里显示的**网页**里选中文字,同样会浮出 `✦ 解读` 按钮:解释用**那个网页自己的上下文**(选区前后各 1500 字,`【】`标出选中部分),追问、历史、升格都照常。覆盖两类:
|
|
108
|
+
|
|
109
|
+
| 谁渲染的网页 | 例子 |
|
|
110
|
+
| --- | --- |
|
|
111
|
+
| 内置「文档预览」的 HTML 文件预览 | 在侧边栏点开一个 `.html` 文件(预览模式) |
|
|
112
|
+
| 其它插件在侧边栏渲染的生成网页 | **「图解」**(`dsh-reply-visual`:模型产出的单文件 HTML 在侧边栏渲染)等 |
|
|
113
|
+
|
|
114
|
+
为什么需要专门做一层:这些网页都渲染在不透明源沙箱 iframe 里(`sandbox="allow-scripts"`,刻意**没有** `allow-same-origin`),父页面拿不到它的文档,顶层 `window.getSelection()` 永远是空的——划词在那里天然是瞎的。所以插件往被渲染的文档里注入一段**桥脚本**:它在帧内读选区、就地采上下文,再 `postMessage` 报出来;父页面把「帧内坐标 + iframe 的位置」换算成视口坐标,复用同一套浮标与面板。
|
|
115
|
+
|
|
116
|
+
| 网页形态 | 桥怎么进去 |
|
|
117
|
+
| --- | --- |
|
|
118
|
+
| **基础预览**(默认,`srcdoc` + `sandbox=""`,宿主已用 DOMPurify 清洗过:无脚本、无外链) | 重写 `srcdoc`:插入桥脚本,把 CSP 的 `script-src 'none'` 放宽成 `'unsafe-inline'`(`default-src 'none'` / `connect-src 'none'` 等其余限制一条不动),沙箱补 `allow-scripts` |
|
|
119
|
+
| **交互式预览**(开发者工具打开后:外层是 `blob:` bootstrap + `document.write`) | 取回那份 blob → 插入桥脚本 → 换成一个新的 blob 装上去;桥的监听挂在 `window` 上并用轮询兜底,`document.write` 冲不掉它 |
|
|
120
|
+
| **其它插件的生成网页**(如「图解」的 `blob:` 帧) | 同上(取回 blob → 注入 → 换新 blob),但**只桥本来就允许脚本的帧**——不给别人的沙箱加权限 |
|
|
121
|
+
|
|
122
|
+
**浮现与消失的时机都与主会话一致**:
|
|
123
|
+
|
|
124
|
+
| 动作 | 结果 |
|
|
125
|
+
| --- | --- |
|
|
126
|
+
| 拖拽划词(按住鼠标) | **期间不弹**;松手后才浮出,位置是**最终**选区末端 |
|
|
127
|
+
| 键盘扩选(`Shift`+方向键) | 松键即弹 |
|
|
128
|
+
| 在网页里点一下(取消选区 / 点别处) | **按下就收**(不等松手),选区真没了再补一条清空 |
|
|
129
|
+
| 点另一个网页 | 也收(跨帧点击同样算"点了别处") |
|
|
130
|
+
| 点主界面别处 / 滚主界面 / 改窗口大小 | 收(与主会话同一套规则) |
|
|
131
|
+
| 页面重绘、动画、字体回流导致的**瞬时**读不到选区 | **不**收(连续 6 拍 ≈1.5s 都读不到才算真没了) |
|
|
132
|
+
| 选区滚出网页可视区 | 收(滚回来会重新浮出) |
|
|
133
|
+
|
|
134
|
+
**安全边界没有退让**:帧始终是不透明源,**不会**加 `allow-same-origin`——网页读不到 GUI 的 DOM / Cookie / localStorage,也不能导航顶层窗口。桥只往外报「选中了什么 + 周围那点文本」。给宿主预览补 `allow-scripts` 是因为那份 HTML 已被清洗成"无脚本",放宽 `script-src` 之后真正会跑的只有桥自己;别人插件的沙箱一概不碰(只桥它们自己已经开了脚本的帧)。
|
|
135
|
+
|
|
136
|
+
不想要这个行为就关掉:`bridgeSidebarPreview: false`(见下面的配置表)。
|
|
137
|
+
|
|
138
|
+
> 不在覆盖范围内:**内置浏览器标签页里的外部站点**(那是远端 URL 的 iframe,插件没有任何注入手段)、以及宿主的**源码视图**(没有 iframe,切回「预览」即可)。用**路由 URL**(而非 `srcdoc`/`blob`)的第三方预览器(如 better-sidebar 自己的 HTML 预览)也不动它——那些的资源配置归它们自己管。
|
|
139
|
+
|
|
76
140
|
### 零依赖渲染
|
|
77
141
|
|
|
78
142
|
面板自带 Markdown 渲染器(段落、多级列表、小标题、表格、引用、代码块)和**语法高亮 tokenizer**(自研,零依赖):注释 / 字符串 / 数字 / 关键字 / 函数名 / 类型 / 标签 / 属性 / 变量 / 运算符分色,按围栏语言标记选规则。配色跟随**面板实际底色**判定,不是看系统偏好——所以 App 深色 + 系统浅色也不会出现深底配深字。文字对比度实测全部 ≥ WCAG AA 4.5。
|
|
79
143
|
|
|
144
|
+
<!--
|
|
145
|
+
上面几张演示图的来源(要换图看这里):
|
|
146
|
+
· 图由 scripts/build-demo-pages.mjs 生成演示页 —— 样式直接从 lib/client.js 抽取真实 CSS,
|
|
147
|
+
DOM 结构与文案照 src/client/index.js 的渲染器写,所以和真实面板一致(非手绘示意图)。
|
|
148
|
+
· 截图:Chrome 无头(--headless --screenshot --force-device-scale-factor=2)
|
|
149
|
+
· 裁边:node scripts/crop-png.mjs <in.png> assets/<name>.png 24
|
|
150
|
+
· 想换成真实环境截图,直接用同名文件覆盖 assets/ 下的图片即可。
|
|
151
|
+
-->
|
|
152
|
+
|
|
80
153
|
---
|
|
81
154
|
|
|
82
155
|
## 安装
|
|
@@ -93,21 +166,26 @@ dsh plugin --profile web add @yfwu2020/dsh-selection-explain
|
|
|
93
166
|
|
|
94
167
|
### 方式二:从 Release 安装
|
|
95
168
|
|
|
96
|
-
每个 Release 都附了**构建好的 `.tgz`**(含 `lib/` 产物,装完即可用,无需 clone
|
|
169
|
+
每个 Release 都附了**构建好的 `.tgz`**(含 `lib/` 产物,装完即可用,无需 clone 源码)。
|
|
170
|
+
用 `latest` 路径可以不写版本号、永远取最新:
|
|
97
171
|
|
|
98
172
|
```bash
|
|
99
|
-
# 下载最新 release
|
|
100
|
-
curl -
|
|
173
|
+
# 下载最新 release 的安装包(无需知道版本号)
|
|
174
|
+
VER=$(curl -sI https://github.com/yfwu2020/dsh-selection-explain/releases/latest | grep -i '^location:' | sed 's|.*/tag/v||' | tr -d '\r\n')
|
|
175
|
+
curl -LO "https://github.com/yfwu2020/dsh-selection-explain/releases/download/v$VER/yfwu2020-dsh-selection-explain-$VER.tgz"
|
|
101
176
|
|
|
102
177
|
# 解包到插件目录
|
|
103
178
|
mkdir -p ~/.dsh/plugins/dsh-selection-explain
|
|
104
|
-
tar -xzf yfwu2020-dsh-selection-explain
|
|
179
|
+
tar -xzf "yfwu2020-dsh-selection-explain-$VER.tgz" \
|
|
105
180
|
-C ~/.dsh/plugins/dsh-selection-explain --strip-components=1
|
|
106
181
|
|
|
107
182
|
# 装配到 profile(重启后由官方接管)
|
|
108
183
|
dsh plugin --profile web add ~/.dsh/plugins/dsh-selection-explain
|
|
109
184
|
```
|
|
110
185
|
|
|
186
|
+
> 也可以直接下某个固定版本,把上面的 `$VER` 换成版本号即可,例如
|
|
187
|
+
> `.../releases/download/v0.1.2/yfwu2020-dsh-selection-explain-0.1.2.tgz`。
|
|
188
|
+
|
|
111
189
|
### 方式三:从源码安装
|
|
112
190
|
|
|
113
191
|
```bash
|
|
@@ -142,7 +220,7 @@ dsh plugin --profile web remove @yfwu2020/dsh-selection-explain
|
|
|
142
220
|
|
|
143
221
|
| 动作 | 结果 |
|
|
144
222
|
| --- | --- |
|
|
145
|
-
| **鼠标划选** / `Shift` + 方向键 | 选区末端浮出 `✦ 解读` 药丸按钮(✦
|
|
223
|
+
| **鼠标划选** / `Shift` + 方向键 | 选区末端浮出 `✦ 解读` 药丸按钮(✦ 是图标,按钮文字是「解读」;输入框内的选择不触发,避免干扰打字)。侧边栏的 HTML 文件预览里同样生效 |
|
|
146
224
|
| 点击按钮 | 弹出面板:顶部是选中文字,正文是「翻译」卡片 |
|
|
147
225
|
| 点 `↓ 展开详解` | 加载完整会话背景,追加「详解」卡片 |
|
|
148
226
|
| 面板底部输入框 | 就这段文字继续追问(`Enter` 发送 / `Shift+Enter` 换行) |
|
|
@@ -167,6 +245,8 @@ dsh plugin --profile web remove @yfwu2020/dsh-selection-explain
|
|
|
167
245
|
window.__dshSelectionExplain.open('the migration ran long', 'Dev: the migration ran long, so we ship Wednesday.')
|
|
168
246
|
window.__dshSelectionExplain.state() // { phase, chars, model, sections }
|
|
169
247
|
window.__dshSelectionExplain.ping() // 当前模型路由与限制
|
|
248
|
+
window.__dshSelectionExplain.bridge() // 侧边栏网页划词桥:{ on, frames:[{connected,own,srcdoc,sandbox}], active, selection }
|
|
249
|
+
window.__dshSelectionExplain.selection() // 当前选区:{ text, source:'document'|'iframe', label, context }
|
|
170
250
|
```
|
|
171
251
|
|
|
172
252
|
### HTTP 接口
|
|
@@ -232,6 +312,7 @@ curl -s http://127.0.0.1:3080/selection-explain/api/ping
|
|
|
232
312
|
| `resultCacheTtlMs` | `600000` | 共享结果缓存 TTL(毫秒);`0` = 关闭 |
|
|
233
313
|
| `historyMaxEntries` | `20` | 小窗对话历史保留多少个划词条目;`0` = 关闭历史 |
|
|
234
314
|
| `maxRequestsPerMinute` | `40` | 本地限流,防误触发刷爆额度 |
|
|
315
|
+
| `bridgeSidebarPreview` | `true` | 侧边栏 HTML 预览里的划词桥。关掉 = 预览网页里选中文字不再弹按钮(预览帧不再补 `allow-scripts`,也不注入桥脚本) |
|
|
235
316
|
|
|
236
317
|
### 工具(联网 / 文件)
|
|
237
318
|
|
|
@@ -270,6 +351,7 @@ curl -s http://127.0.0.1:3080/selection-explain/api/ping
|
|
|
270
351
|
- **不建会话**:小窗对话落在插件自己的 `history.json` 里。会话是重型对象,高频功能那样做只会堆死会话列表。
|
|
271
352
|
- **缓存 key 不含选中文字之后的内容**:否则主会话后面追加新消息时,同一个词的 key 就变了,表现为"找不着上次的小窗、又生成一个"。
|
|
272
353
|
- **上下文窗口锚定选中文字所在的那条消息**,向上取——不是简单取最近 N 条,这样"这个词在这段对话里什么意思"才有前提。
|
|
354
|
+
- **侧边栏预览里的选区由帧内桥上报**:那段上下文是在**帧内**用同一套算法(容器 ≥120 字、前后各 1500 字、`【】`标记、key 只取选中前 300 字)算出来的,所以侧边栏网页里的解释质量与主会话里一致,而不是退化成"只有选中文字、没有上下文"。
|
|
273
355
|
|
|
274
356
|
---
|
|
275
357
|
|
|
@@ -277,13 +359,17 @@ curl -s http://127.0.0.1:3080/selection-explain/api/ping
|
|
|
277
359
|
|
|
278
360
|
```bash
|
|
279
361
|
npm run build # 构建(= bash scripts/build.sh)
|
|
280
|
-
npm test #
|
|
362
|
+
npm test # 576 条断言(filters / prompt / bridge / smoke / client / transcript / guard)
|
|
363
|
+
npm run test:smoke # 只跑真浏览器冒烟(本机 Chrome;找不到自动 SKIP)
|
|
281
364
|
npm run typecheck # tsc --noEmit
|
|
282
365
|
```
|
|
283
366
|
|
|
284
367
|
| 脚本 | 用途 |
|
|
285
368
|
| --- | --- |
|
|
286
|
-
| `scripts/test-client.mjs` | 无浏览器集成测试:真实 host 路由 + 最小 DOM 桩,覆盖槽注册 → 划词浮标 → 点击 → SSE 流式渲染 → 两节内容 →
|
|
369
|
+
| `scripts/test-client.mjs` | 无浏览器集成测试:真实 host 路由 + 最小 DOM 桩,覆盖槽注册 → 划词浮标 → 点击 → SSE 流式渲染 → 两节内容 → 侧边栏网页划词桥(注入 / 来源校验 / 坐标换算 / 帧内清空)→ 清理(host 不在跑时自动跳过在线断言) |
|
|
370
|
+
| `scripts/test-bridge.mjs` | **划词桥单测**(无需宿主):从 bundle 里抠出桥脚本与注入函数单独跑 —— 插在哪、CSP 只放宽哪一条、沙箱补哪个 token、帧内报出来的文字 / `【】`上下文 / `keyContext` / 坐标对不对 |
|
|
371
|
+
| `scripts/smoke-bridge.mjs` | **划词桥真浏览器冒烟**(本机 Chrome,找不到就 SKIP):起临时 http 服务,用两种预览形态(`srcdoc` / `blob` bootstrap)验沙箱 + CSP + 跨不透明源 postMessage + `document.write` 冲不掉监听 |
|
|
372
|
+
| `scripts/test-prompt.mjs` | **提示词契约测试**:把两节结构标题、结论条格式、音标规则、详解来源判断、追问网页模式要求等关键约束固化成断言,误删即 CI 红 |
|
|
287
373
|
| `scripts/test-filters.mjs` | host 侧流式过滤器单测(思考泄漏、工具调用残渣等) |
|
|
288
374
|
| `scripts/test-transcript.mjs` | 会话背景窗口的离线测试(锚点 / 条数 / 不截断 / 噪音剔除 / 退化路径) |
|
|
289
375
|
| `scripts/test-guard.mjs` | 文件工具读取边界的路径校验 |
|
|
@@ -305,7 +391,7 @@ node scripts/dump-prompt.mjs --no-session "<选中文字>" # 不带会话背
|
|
|
305
391
|
git tag v0.2.0 && git push origin v0.2.0
|
|
306
392
|
```
|
|
307
393
|
|
|
308
|
-
`.github/workflows/publish.yml` 会自动:校验 tag 与 `version` 一致 → `npm install` → 构建 →
|
|
394
|
+
`.github/workflows/publish.yml` 会自动:校验 tag 与 `version` 一致 → `npm install` → 构建 → 跑全量测试(`npm test`,含真浏览器冒烟,CI 里自动 SKIP)→ 类型检查 → `npm publish --provenance`(附 provenance 签名)。
|
|
309
395
|
|
|
310
396
|
npm 侧只需配一次:包设置 → **Trusted Publisher** → GitHub Actions,填 `yfwu2020` / `dsh-selection-explain` / `publish.yml`,并勾选允许 **`npm publish`**(默认只允许 `npm stage publish`)。
|
|
311
397
|
|
|
@@ -316,10 +402,12 @@ npm 侧只需配一次:包设置 → **Trusted Publisher** → GitHub Actions
|
|
|
316
402
|
## 目录
|
|
317
403
|
|
|
318
404
|
```
|
|
319
|
-
src/index.ts host 半:SSE 路由 / 模型调用 /
|
|
405
|
+
src/index.ts host 半:SSE 路由 / 模型调用 / 会话背景 / 历史落盘 / 过滤器
|
|
406
|
+
src/prompts.ts 提示词与写作规则(纯字符串常量,无逻辑)
|
|
320
407
|
src/client/index.js client 半:划词浮标 + 面板 + 渲染器(手写 ModuleLoader bundle,无打包器)
|
|
321
|
-
scripts/ build.sh +
|
|
408
|
+
scripts/ build.sh + 5 个测试 + dump-prompt + 演示图生成
|
|
322
409
|
skills/web-design/ 网页模式注入的设计规范(运行时读取)
|
|
410
|
+
assets/ README 的演示图(由 scripts/build-demo-pages.mjs 生成)
|
|
323
411
|
cordis.patch.yml 官方装配用的 bundle patch
|
|
324
412
|
lib/ 构建产物(已 gitignore,克隆后需 npm run build)
|
|
325
413
|
```
|
|
@@ -330,8 +418,10 @@ lib/ 构建产物(已 gitignore,克隆后需 npm run buil
|
|
|
330
418
|
|
|
331
419
|
## 已知限制
|
|
332
420
|
|
|
333
|
-
-
|
|
334
|
-
-
|
|
421
|
+
- 主会话(以及 DSH 界面本身)里只覆盖**同源页面内**的选中文字。
|
|
422
|
+
- 侧边栏 **HTML 文件预览**已覆盖(靠帧内桥,见上);但**内置浏览器标签页里的外部站点**(远端 URL 的 iframe,插件没有任何注入手段)与**源码视图**(没有 iframe)不触发。
|
|
423
|
+
- 预览帧被换成路由 URL 而非 `srcdoc`/`blob` 的第三方预览器不接管(不动别人的资源改写与生命周期)。
|
|
424
|
+
- 面板**不跟随页面滚动**(滚动即收起浮标 / 面板),符合「划完即看」的一次性使用预期;侧边栏网页内部滚动会重新上报位置,浮标跟着走。
|
|
335
425
|
- 结论来自当前模型,专业领域术语请以人工判断为准。
|
|
336
426
|
- 依赖 DSH 的 `webServer` 与 `llm` 服务;宿主版本过旧可能不兼容(peerDependencies 见 `package.json`)。
|
|
337
427
|
|
package/assets/code.png
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/assets/web.png
ADDED
|
Binary file
|
package/cordis.patch.yml
CHANGED
|
@@ -21,6 +21,10 @@
|
|
|
21
21
|
# toolReadRoot 文件类工具(read/grep/glob)的读取边界:'' = 会话工作目录(默认),
|
|
22
22
|
# '*' = 不限制,其他 = 写死的某个目录。越界在**执行前**被拒
|
|
23
23
|
# tools 总开关(false = 完全不给工具)
|
|
24
|
+
# bridgeSidebarPreview 侧边栏 HTML 预览里的划词桥(默认 true):预览帧会被补上
|
|
25
|
+
# allow-scripts 并注入一段桥脚本(**不会**加 allow-same-origin,
|
|
26
|
+
# 预览页仍读不到 GUI 数据),这样在预览网页里划词也能解读。
|
|
27
|
+
# false = 侧边栏网页里不弹「解读」按钮
|
|
24
28
|
- insert:
|
|
25
29
|
- id: selection-explain
|
|
26
30
|
name: '@yfwu2020/dsh-selection-explain'
|