@yfwu2020/dsh-selection-explain 0.1.1 → 0.1.3
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/README.md +60 -12
- 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/lib/client.js +10 -4
- package/lib/index.js +3 -136
- package/lib/index.js.map +1 -1
- package/lib/prompts.js +135 -0
- package/lib/prompts.js.map +1 -0
- package/lib/types/prompts.d.ts +26 -0
- package/package.json +5 -3
- package/scripts/build-demo-pages.mjs +296 -0
- package/scripts/crop-png.mjs +142 -0
- package/scripts/test-client.mjs +11 -0
- package/scripts/test-prompt.mjs +178 -0
- package/src/client/index.js +10 -4
- package/src/index.ts +9 -142
- package/src/prompts.ts +139 -0
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 淘汰,**升格过的条目不会被淘汰**。
|
|
@@ -77,6 +106,15 @@
|
|
|
77
106
|
|
|
78
107
|
面板自带 Markdown 渲染器(段落、多级列表、小标题、表格、引用、代码块)和**语法高亮 tokenizer**(自研,零依赖):注释 / 字符串 / 数字 / 关键字 / 函数名 / 类型 / 标签 / 属性 / 变量 / 运算符分色,按围栏语言标记选规则。配色跟随**面板实际底色**判定,不是看系统偏好——所以 App 深色 + 系统浅色也不会出现深底配深字。文字对比度实测全部 ≥ WCAG AA 4.5。
|
|
79
108
|
|
|
109
|
+
<!--
|
|
110
|
+
上面几张演示图的来源(要换图看这里):
|
|
111
|
+
· 图由 scripts/build-demo-pages.mjs 生成演示页 —— 样式直接从 lib/client.js 抽取真实 CSS,
|
|
112
|
+
DOM 结构与文案照 src/client/index.js 的渲染器写,所以和真实面板一致(非手绘示意图)。
|
|
113
|
+
· 截图:Chrome 无头(--headless --screenshot --force-device-scale-factor=2)
|
|
114
|
+
· 裁边:node scripts/crop-png.mjs <in.png> assets/<name>.png 24
|
|
115
|
+
· 想换成真实环境截图,直接用同名文件覆盖 assets/ 下的图片即可。
|
|
116
|
+
-->
|
|
117
|
+
|
|
80
118
|
---
|
|
81
119
|
|
|
82
120
|
## 安装
|
|
@@ -93,21 +131,26 @@ dsh plugin --profile web add @yfwu2020/dsh-selection-explain
|
|
|
93
131
|
|
|
94
132
|
### 方式二:从 Release 安装
|
|
95
133
|
|
|
96
|
-
每个 Release 都附了**构建好的 `.tgz`**(含 `lib/` 产物,装完即可用,无需 clone
|
|
134
|
+
每个 Release 都附了**构建好的 `.tgz`**(含 `lib/` 产物,装完即可用,无需 clone 源码)。
|
|
135
|
+
用 `latest` 路径可以不写版本号、永远取最新:
|
|
97
136
|
|
|
98
137
|
```bash
|
|
99
|
-
# 下载最新 release
|
|
100
|
-
curl -
|
|
138
|
+
# 下载最新 release 的安装包(无需知道版本号)
|
|
139
|
+
VER=$(curl -sI https://github.com/yfwu2020/dsh-selection-explain/releases/latest | grep -i '^location:' | sed 's|.*/tag/v||' | tr -d '\r\n')
|
|
140
|
+
curl -LO "https://github.com/yfwu2020/dsh-selection-explain/releases/download/v$VER/yfwu2020-dsh-selection-explain-$VER.tgz"
|
|
101
141
|
|
|
102
142
|
# 解包到插件目录
|
|
103
143
|
mkdir -p ~/.dsh/plugins/dsh-selection-explain
|
|
104
|
-
tar -xzf yfwu2020-dsh-selection-explain
|
|
144
|
+
tar -xzf "yfwu2020-dsh-selection-explain-$VER.tgz" \
|
|
105
145
|
-C ~/.dsh/plugins/dsh-selection-explain --strip-components=1
|
|
106
146
|
|
|
107
147
|
# 装配到 profile(重启后由官方接管)
|
|
108
148
|
dsh plugin --profile web add ~/.dsh/plugins/dsh-selection-explain
|
|
109
149
|
```
|
|
110
150
|
|
|
151
|
+
> 也可以直接下某个固定版本,把上面的 `$VER` 换成版本号即可,例如
|
|
152
|
+
> `.../releases/download/v0.1.2/yfwu2020-dsh-selection-explain-0.1.2.tgz`。
|
|
153
|
+
|
|
111
154
|
### 方式三:从源码安装
|
|
112
155
|
|
|
113
156
|
```bash
|
|
@@ -277,13 +320,14 @@ curl -s http://127.0.0.1:3080/selection-explain/api/ping
|
|
|
277
320
|
|
|
278
321
|
```bash
|
|
279
322
|
npm run build # 构建(= bash scripts/build.sh)
|
|
280
|
-
npm test #
|
|
323
|
+
npm test # 489 条断言(filters / prompt / client / transcript / guard)
|
|
281
324
|
npm run typecheck # tsc --noEmit
|
|
282
325
|
```
|
|
283
326
|
|
|
284
327
|
| 脚本 | 用途 |
|
|
285
328
|
| --- | --- |
|
|
286
|
-
| `scripts/test-client.mjs` | 无浏览器集成测试:真实 host 路由 + 最小 DOM 桩,覆盖槽注册 → 划词浮标 → 点击 → SSE 流式渲染 → 两节内容 →
|
|
329
|
+
| `scripts/test-client.mjs` | 无浏览器集成测试:真实 host 路由 + 最小 DOM 桩,覆盖槽注册 → 划词浮标 → 点击 → SSE 流式渲染 → 两节内容 → 清理(host 不在跑时自动跳过在线断言) |
|
|
330
|
+
| `scripts/test-prompt.mjs` | **提示词契约测试**:把两节结构标题、结论条格式、音标规则、详解来源判断、追问网页模式要求等关键约束固化成断言,误删即 CI 红 |
|
|
287
331
|
| `scripts/test-filters.mjs` | host 侧流式过滤器单测(思考泄漏、工具调用残渣等) |
|
|
288
332
|
| `scripts/test-transcript.mjs` | 会话背景窗口的离线测试(锚点 / 条数 / 不截断 / 噪音剔除 / 退化路径) |
|
|
289
333
|
| `scripts/test-guard.mjs` | 文件工具读取边界的路径校验 |
|
|
@@ -305,7 +349,7 @@ node scripts/dump-prompt.mjs --no-session "<选中文字>" # 不带会话背
|
|
|
305
349
|
git tag v0.2.0 && git push origin v0.2.0
|
|
306
350
|
```
|
|
307
351
|
|
|
308
|
-
`.github/workflows/publish.yml` 会自动:校验 tag 与 `version` 一致 → `npm install` → 构建 → 跑
|
|
352
|
+
`.github/workflows/publish.yml` 会自动:校验 tag 与 `version` 一致 → `npm install` → 构建 → 跑 489 条测试 → 类型检查 → `npm publish --provenance`(附 provenance 签名)。
|
|
309
353
|
|
|
310
354
|
npm 侧只需配一次:包设置 → **Trusted Publisher** → GitHub Actions,填 `yfwu2020` / `dsh-selection-explain` / `publish.yml`,并勾选允许 **`npm publish`**(默认只允许 `npm stage publish`)。
|
|
311
355
|
|
|
@@ -316,16 +360,20 @@ npm 侧只需配一次:包设置 → **Trusted Publisher** → GitHub Actions
|
|
|
316
360
|
## 目录
|
|
317
361
|
|
|
318
362
|
```
|
|
319
|
-
src/index.ts host 半:SSE 路由 / 模型调用 /
|
|
363
|
+
src/index.ts host 半:SSE 路由 / 模型调用 / 会话背景 / 历史落盘 / 过滤器
|
|
364
|
+
src/prompts.ts 提示词与写作规则(纯字符串常量,无逻辑)
|
|
320
365
|
src/client/index.js client 半:划词浮标 + 面板 + 渲染器(手写 ModuleLoader bundle,无打包器)
|
|
321
|
-
scripts/ build.sh +
|
|
366
|
+
scripts/ build.sh + 5 个测试 + dump-prompt + 演示图生成
|
|
322
367
|
skills/web-design/ 网页模式注入的设计规范(运行时读取)
|
|
323
|
-
|
|
324
|
-
docs/*.html UI 试验页(浮标动效 / 模型选择器 / 配色方案等)
|
|
368
|
+
assets/ README 的演示图(由 scripts/build-demo-pages.mjs 生成)
|
|
325
369
|
cordis.patch.yml 官方装配用的 bundle patch
|
|
326
370
|
lib/ 构建产物(已 gitignore,克隆后需 npm run build)
|
|
327
371
|
```
|
|
328
372
|
|
|
373
|
+
> **`docs/` 不在本仓库中**:开发期的资料(UI 比选实验台——浮标动效 / 模型选择器 / 折叠实验台 /
|
|
374
|
+
> 配色方案等,以及含本机路径与逐轮实测记录的内部开发文档)**仅保留在开发者本地**,已在 `.gitignore`
|
|
375
|
+
> 中整体排除,也从未进入 npm 包。它们记录的是"当初为什么这么设计",与插件运行无关。
|
|
376
|
+
|
|
329
377
|
## 已知限制
|
|
330
378
|
|
|
331
379
|
- 只覆盖**同源页面内**的选中文字;跨域 iframe(如内置浏览器标签页里的外部站点)内部的选择不触发。
|
package/assets/code.png
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/assets/web.png
ADDED
|
Binary file
|
package/lib/client.js
CHANGED
|
@@ -2953,11 +2953,15 @@ window.__ModuleLoader__.load({
|
|
|
2953
2953
|
}
|
|
2954
2954
|
|
|
2955
2955
|
/**
|
|
2956
|
-
* 取一条历史回放。anchor
|
|
2957
|
-
*
|
|
2958
|
-
*
|
|
2956
|
+
* 取一条历史回放。anchor 省略时:
|
|
2957
|
+
* · 从「最近」列表里点一条 → **面板不挪位置**:列表本来就贴着面板摆,
|
|
2958
|
+
* 把面板重新锚到胶囊上会让人眼看着面板"跳到右下角胶囊上方"(实测反馈的 bug)。
|
|
2959
|
+
* · 就绪状态点胶囊回放 → 锚到胶囊上方;否则面板从没被摆过位置,会跑到屏幕左上角。
|
|
2960
|
+
*
|
|
2961
|
+
* 注意:`applyHistoryEntry` 内部会收起列表,所以"是否从列表进入"必须在调用**之前**判断。
|
|
2959
2962
|
*/
|
|
2960
2963
|
function loadHistoryEntry(key, anchor) {
|
|
2964
|
+
var fromList = historyList.style.display === 'flex'
|
|
2961
2965
|
fetch(HISTORY + '?key=' + encodeURIComponent(key))
|
|
2962
2966
|
.then(function (response) {
|
|
2963
2967
|
return response.json()
|
|
@@ -2968,7 +2972,9 @@ window.__ModuleLoader__.load({
|
|
|
2968
2972
|
panel.style.display = 'flex'
|
|
2969
2973
|
applyHistoryEntry(data.entry, 'history')
|
|
2970
2974
|
// 先画内容再摆位置:showPanel 要量面板高度才能决定放上面还是下面
|
|
2971
|
-
showPanel(anchor || rectOfPill())
|
|
2975
|
+
if (!fromList) showPanel(anchor || rectOfPill())
|
|
2976
|
+
// 内容换了、面板高度可能变 → 列表跟着重摆(列表此时已被 applyHistoryEntry 收起,按需再开)
|
|
2977
|
+
if (historyList.style.display === 'flex') placeHistoryList()
|
|
2972
2978
|
})
|
|
2973
2979
|
.catch(function () {
|
|
2974
2980
|
/* noop */
|
package/lib/index.js
CHANGED
|
@@ -18,6 +18,9 @@ import { join, resolve, sep } from 'node:path';
|
|
|
18
18
|
import { fileURLToPath } from 'node:url';
|
|
19
19
|
import { BlockAssembler, createAssistantMessage, createSystemMessage, createToolResultMessage, createUserMessage, ReasoningEffortId } from '@deepseek-ai/dsh-llm';
|
|
20
20
|
import z from '@deepseek-ai/schemastery';
|
|
21
|
+
// 提示词与写作规则(纯文本常量)单独成模块:本文件是 2400+ 行的 host 全量逻辑,
|
|
22
|
+
// 提示词放这里既难找也容易误改。组装逻辑仍在下方(按 stage / kind 选一套)。
|
|
23
|
+
import { CHAT_SYSTEM_PROMPT, CODE_PROMPT, DETAIL_PROMPT, TRANSLATION_PROMPT, } from './prompts.js';
|
|
21
24
|
/** 插件名(= package.json name,客户端 bundle 的模块 id 也是它)。 */
|
|
22
25
|
export const name = '@yfwu2020/dsh-selection-explain';
|
|
23
26
|
/** 路由注册与模型调用所需的服务。 */
|
|
@@ -103,134 +106,6 @@ function resolveToolNames(preferred, fallback, visible) {
|
|
|
103
106
|
}
|
|
104
107
|
return out;
|
|
105
108
|
}
|
|
106
|
-
/** 系统提示词:固定文本,两节结构,前端按标题切分。 */
|
|
107
|
-
/** 公共前言与尾部规则(两套提示词共用,避免重复维护)。 */
|
|
108
|
-
const PROMPT_HEAD = [
|
|
109
|
-
'你是一位跨领域的资深解读专家,覆盖中英双语语言学、软件工程与系统架构、数据与算法、产品与交互设计。',
|
|
110
|
-
'先判断【选中文字】实际属于哪个领域,再按该领域资深从业者的标准解读:',
|
|
111
|
-
'术语取该领域的准确定义(必要时补一句通用含义做对照),关注点也对齐该领域的关注点——',
|
|
112
|
-
'代码看行为、边界与副作用,架构看约束与取舍,设计看目标与权衡,语言看语域、搭配与言外之意。',
|
|
113
|
-
'领域判断是内部动作:**不要把判断过程写出来**,也不要写「这属于工程领域」这类交代,直接给解读。',
|
|
114
|
-
'',
|
|
115
|
-
'用户消息可能是:先给一段【会话背景】(可选,最前面),最后给出要解读的【选中文字】及其上下文。',
|
|
116
|
-
].join('\n');
|
|
117
|
-
/**
|
|
118
|
-
* 「总结 / 详解」的表达要求:既要专业,也要说人话。
|
|
119
|
-
*
|
|
120
|
-
* 只讲术语等于没解释(换个说法还是不懂),只打比方又拿不去用(不知道确切边界)——
|
|
121
|
-
* 所以**内容上两层都要在**。但**形式上不设模板**:不要求小标题、不要求固定句式、
|
|
122
|
-
* 不要求先后顺序,由内容自己决定怎么说最自然;否则每段都长成同一个模子,读起来很僵。
|
|
123
|
-
*/
|
|
124
|
-
const TWO_LAYER_RULE = [
|
|
125
|
-
'**写法:内容有要求,形式随内容走。**',
|
|
126
|
-
'- 要让人看懂:出现术语、缩写、行话,就用日常话把它说清楚——',
|
|
127
|
-
' 顺在句子里讲明白就行,不必另起一句、也不必加小标题分栏。',
|
|
128
|
-
'- 反过来,只给了比方或感觉,就把准确的说法和边界补上(叫什么、在什么前提下成立、到什么程度)。',
|
|
129
|
-
'- 专业体现在**说得准**,不是用词生僻:术语用对、该给英文原词或全称就给、',
|
|
130
|
-
' 该有的限定不能省;也不要同义反复(「是指……的一种……」)或用术语解释术语。',
|
|
131
|
-
'- **别写成同一个模子**:不必每段都按同一个顺序铺陈,也不必凑够三条要点;',
|
|
132
|
-
' 一句能说清就一句,需要展开再展开;不要为整齐而分点,不要用「第一/第二」这类序号。',
|
|
133
|
-
].join('\n');
|
|
134
|
-
/** 只输出「翻译」一节时用。 */
|
|
135
|
-
const TRANSLATION_PROMPT = [
|
|
136
|
-
PROMPT_HEAD,
|
|
137
|
-
'',
|
|
138
|
-
'**本轮只输出一个章节**(标题见下),不要输出其它章节,不要前言与结语。',
|
|
139
|
-
'先看【选中文字】里**有没有需要翻译的英文**,据此决定标题与内容(判断过程不要写出来):',
|
|
140
|
-
'',
|
|
141
|
-
'### 情形一:选中文字里有英文(含中英混排)→ 标题写 `## 翻译`',
|
|
142
|
-
'- **以中文为主的句子**(可能夹着英文词):中文部分**一律不翻译**、也不要复述原句;',
|
|
143
|
-
' 只把【选中文字】**自己**含着的**英文**片段(由拉丁字母组成的单词、词组或整句)挑出来逐条译成',
|
|
144
|
-
' 中文,一个片段一条,且**层级分明**:',
|
|
145
|
-
' · 是**单词** → 父项写「词头 + 音标」(IPA,斜杠包起来),词性与义项**缩进两个空格**作为子项,',
|
|
146
|
-
' 每行以 `**n.**`、`**v.**` 这样的词性标记开头(**词性必须标**,一词多义就多行):',
|
|
147
|
-
' 形如 `- **migration** /maɪˈɡreɪʃn/`,下一行缩进写 `- **n.** 迁移;移居`;',
|
|
148
|
-
' · 是**词组或整句** → 一行 `- **原英文**:中文意思` 即可(不标音标、不拆词性)。',
|
|
149
|
-
' 音标拿不准就不写(缩写、专有名词尤其常见);宁可不标也不要编。',
|
|
150
|
-
' 中文词句即使有对应的英文说法(如「缓存层」「灰度」)也**不要列**,不要到上下文或标题里去找英文;',
|
|
151
|
-
' 写完自查:列出的每一条都必须①由英文字母构成、②能在【选中文字】里逐字找到,否则删掉。',
|
|
152
|
-
'- **以英文为主**(整句、词组或单词都算):',
|
|
153
|
-
' · 句子或词组 → 译文**单独成段**,段落以译文的第一个字开头(长句可拆成 2~3 行;',
|
|
154
|
-
' 句中的中文词原样保留,关键术语用括号注明原词);',
|
|
155
|
-
' · 单词 → **两级结构,层级要看得出来**:',
|
|
156
|
-
' 第一行是**词头 + 音标**(IPA,斜杠包起来),它是父项:`- **migrate** /maɪˈɡreɪt/`;',
|
|
157
|
-
' 英式与美式读音不同就都写(`/英 …/ `/美 …/` 并列,标上「英」「美」),相同只写一个;拿不准就不写,不要编。',
|
|
158
|
-
' 下面**每个词性义项各占一行、缩进两个空格**作为子项,行首是 `**v.**` 这样的词性标记,',
|
|
159
|
-
' 后面跟中文义项,常用义项在前;词头行本身**不要再写义项**。',
|
|
160
|
-
' 形如:父项 `- **long** /英 lɒŋ/ /美 lɔːŋ/`,子项缩进两格 `- **adj.** 长的;远的`、`- **v.** 渴望,极想`。',
|
|
161
|
-
'- **以中英之外的语言为主**(日、韩、法、德等):译成中文。',
|
|
162
|
-
'',
|
|
163
|
-
'### 情形二:选中文字**全是中文**(纯汉字的词、短语或句子)→ 标题写 `## 解读`',
|
|
164
|
-
'- **不要翻译**:不译成英文,不给英文说法,也不列义项、不做词典式解释;',
|
|
165
|
-
'- 只是把这段中文**在当前上下文里是什么意思**讲清楚,一两句就够,直接说结论。',
|
|
166
|
-
'',
|
|
167
|
-
'两种情形的**最后一行都固定**写成引用行,作为本节的总结(**这一行是本节的重点**):',
|
|
168
|
-
'> 在本句中:<它在这段上下文里到底是什么意思>',
|
|
169
|
-
'- 一行说清:用日常话讲明白,专业上的准确说法和必要限定顺在里面带出来即可,',
|
|
170
|
-
' 不用套固定句式、也不用刻意分两截;',
|
|
171
|
-
'- **不要照抄原句**,不要写「可能」「取决于」:给确定答案;',
|
|
172
|
-
'- 说清楚为止:该长就长、该短就短,不卡字数;也不要为凑字数把一行写成一段。',
|
|
173
|
-
'',
|
|
174
|
-
'规则:',
|
|
175
|
-
'- 只处理选中文字,不要整段翻译「上下文」,也不要复述指令。',
|
|
176
|
-
'- 正文里不要出现「翻译:」「中文句子:」这类分类标签,直接给内容。',
|
|
177
|
-
'- 用简洁 Markdown:要点可以用「- 」,但别把什么都做成列表;强调用 **加粗**,别整段加粗;',
|
|
178
|
-
' 整段输出不要用代码块包裹。',
|
|
179
|
-
'- 不要出现「以下是」「希望对你有所帮助」之类的客套话。',
|
|
180
|
-
'- **不要叙述查资料的过程**("让我先搜一下""我再确认一下"这类一律不写);查到什么直接给结论,',
|
|
181
|
-
' 有链接就自然带在结论里。',
|
|
182
|
-
].join('\n');
|
|
183
|
-
/** 选中文字是代码时用:代码块原样呈现 + 逐句注释 + 小结(首轮,只要快)。 */
|
|
184
|
-
const CODE_PROMPT = [
|
|
185
|
-
PROMPT_HEAD,
|
|
186
|
-
'',
|
|
187
|
-
'**本轮只输出「## 注释」这一节**,不要输出「## 详解」或其它章节,不要前言与结语:',
|
|
188
|
-
'',
|
|
189
|
-
'## 注释',
|
|
190
|
-
'**整节只有一个代码块**(用 ``` 围起来,尽可能标上语言),**注释就写在代码块里面**,',
|
|
191
|
-
'贴着它解释的那条语句,看起来像一份"带批注的代码清单":',
|
|
192
|
-
'',
|
|
193
|
-
'```',
|
|
194
|
-
'// 这条语句在做什么(用该语言的注释符号)',
|
|
195
|
-
'<原代码这一句>',
|
|
196
|
-
'// 下一条语句在做什么',
|
|
197
|
-
'<原代码下一句>',
|
|
198
|
-
'```',
|
|
199
|
-
'',
|
|
200
|
-
'块内规则:',
|
|
201
|
-
'- 原代码**逐字不变**:缩进、空行、注释、变量名全部保留;不要补全、不要精简、不要加行号、不要改写成伪代码。',
|
|
202
|
-
'- 在**每一条语句/逻辑块之前**加一行注释,用**该语言的注释符号**(`//`、`#`、`--`、`<!-- -->`、`<!--` 等),',
|
|
203
|
-
' 注释紧贴代码、中间不插空行;注释的缩进跟着它解释的那行代码走。',
|
|
204
|
-
'- **每一句都要覆盖**,不要跳句;讲「这行为什么这么写、和整体什么关系、有什么副作用或坑」,',
|
|
205
|
-
' 不要复述语言基础语法("这是一个 if 语句"这种不要写)。',
|
|
206
|
-
'- 太长的语句可以在其后补一行注释,但不要撕裂代码本身。',
|
|
207
|
-
'- 每条注释尽量一两句说完;说不完就换行再起一行注释(小窗很窄,一条注释太长会被折成好几行),不要写成一大段。',
|
|
208
|
-
'',
|
|
209
|
-
'代码块**外面**只留最后一行,固定写成引用行作为总结:',
|
|
210
|
-
'> 小结:<这段代码整体在干什么、值得点出的地方>',
|
|
211
|
-
'- 一行说清,话要顺:用日常话讲它在做什么,顺带点出关键路径、复杂度、副作用或坑;',
|
|
212
|
-
' 没什么可点就只说在做什么,别硬凑,也别把这一行拆成好几段;',
|
|
213
|
-
'- 用自己的话讲,不要照抄代码,也不要复述块内的逐句注释;',
|
|
214
|
-
'- 说清楚为止:该长就长、该短就短,不卡字数;也不要为整齐而拉长。',
|
|
215
|
-
'',
|
|
216
|
-
'规则:',
|
|
217
|
-
'- 只处理【选中文字】这段代码;上下文只用来理解它,不要注释上下文里的其它代码。',
|
|
218
|
-
'- 除了最后那一行小结,**不要在代码块外再写逐句注释**(注释已经在块内了)。',
|
|
219
|
-
'- 用中文讲解;术语、API 名保留原文。',
|
|
220
|
-
'- 不要出现「以下是」「希望对你有所帮助」之类的客套话。',
|
|
221
|
-
].join('\n');
|
|
222
|
-
/** 只输出「详解」一节时用(第二阶段,带完整会话背景)。 */
|
|
223
|
-
const DETAIL_PROMPT = [
|
|
224
|
-
PROMPT_HEAD,
|
|
225
|
-
'',
|
|
226
|
-
'**本轮只输出「## 详解」这一节**,不要输出「## 翻译」或其它章节,不要前言与结语:',
|
|
227
|
-
'',
|
|
228
|
-
'## 详解',
|
|
229
|
-
'选中的这段文字是什么意思?把意思讲透——既专业,也让人看得懂;该长就长、该短就短。',
|
|
230
|
-
'(先看一眼它是怎么来的:真实对话/正文,还是示例、测试用例、演示输出、引用别人的话;',
|
|
231
|
-
'是后者就先说一句,再按它实际的意思解释。)',
|
|
232
|
-
'选中文字是单个英文单词时,带上音标(IPA;英式美式不同就都写,拿不准就不写)。',
|
|
233
|
-
].join('\n');
|
|
234
109
|
/** 写一条 SSE 事件。 */
|
|
235
110
|
function sse(res, payload) {
|
|
236
111
|
if (res.writableEnded)
|
|
@@ -551,14 +426,6 @@ async function loadDesignSkill() {
|
|
|
551
426
|
return DESIGN_SKILL_FALLBACK;
|
|
552
427
|
}
|
|
553
428
|
}
|
|
554
|
-
/** 追问模式(对话小窗)的系统提示词:不再要求两节结构,就是围绕这段文字聊天。 */
|
|
555
|
-
const CHAT_SYSTEM_PROMPT = [
|
|
556
|
-
'你是 DeepSeek Harness 中「划词解读」小窗里的助手,正在辅助用户对一段【选中文字】及其上下文进行理解。',
|
|
557
|
-
'用户问什么就答什么:可以问这段文字本身,也可以顺着它问到别的,不必把话题拉回选中文字。',
|
|
558
|
-
'回答简洁、准确、具体;前情里已经给过的翻译/详解不用重复,引用时一句话带过即可。',
|
|
559
|
-
'要画图、做可视化或写页面时,直接给**完整的单文件 HTML**(放进 ```html 代码块,样式和脚本都内联),',
|
|
560
|
-
'小窗会把它当场渲染成可交互的网页;不要只给片段,也不要说"你可以把它保存成 .html 再打开"。',
|
|
561
|
-
].join('\n');
|
|
562
429
|
/**
|
|
563
430
|
* 粗略判断"是不是公网地址",口径与 dsh-web-fetch-http 的 SSRF 防护一致(非 unicast 一律拒绝)。
|
|
564
431
|
*
|