dsh-plugin-term-dictionary 1.0.0 → 1.1.1

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
@@ -2,7 +2,122 @@
2
2
 
3
3
  本文件记录**发布出去**的版本。每一项都是可验证的行为,不写计划。
4
4
 
5
- ## 未发布
5
+ ## 1.1.1 — 2026-10-11
6
+
7
+ ### 组可以改名、移动、删除
8
+
9
+ - **重命名与移动是同一件事**,因为组就是一条路径:`backend → 服务端` 是改名,把 `net` 从 `backend` 挪到
10
+ `infra` 是移动。组行第二行有 `[✎]`(改名/移动)与 `[🗑]`(删除)。
11
+ - 每个词条都走**单条移动那条带时间戳的决定**(`groupAt`)——批量移动不是"决定"这条规则的例外,所以它
12
+ 同样经得起与宿主的合并。
13
+ - **站在被改名的组里会跟着它走**(留在同一层、路径变了),而不是被扔回顶层。
14
+ - 改到已存在的组名 = **合并两个组**。三种情况明确拒绝:空名、名字没变、把组移到自己里面。
15
+ - **删除是软删除**:组里的词条进「已删除」并留下墓碑(可逐条撤回,也挡住路过的包把它们又放回来)。
16
+ 确认框里**带条数**——"删除这个分组?"与"删除 12 条词条?"是两个不同的提议。
17
+ - 改名表单是**内联**的,不是 `prompt()`:Electron 不实现 `prompt`。
18
+
19
+ ### 组卡片有一行正文
20
+
21
+ - 组行现在是 `[📁] 名字 N 条 ›` 加一行**里面最新的几个词条名**(超过三条接「等 N 条」)。空盒子变成了
22
+ 可读的预览,等高也就有了内容可撑。
23
+
24
+ ### 悬停/点击:段落左侧空白不再误触发
25
+
26
+ - 报告:术语在**行首**时,鼠标在它**正左侧**任意位置(直到聊天区边缘)都会弹出悬浮窗、点击也会进词条。
27
+ - 原因:`caretRangeFromPoint` **横向夹取**——左空白里的点被解析成该行起点(offset 0),而当术语正好在
28
+ 行首时,offset 0 就是它。
29
+ - 修法:量**光标自己**的位置(折叠 Range 的 `getBoundingClientRect`),只有光标真的在该点时才接受
30
+ (容差 8px ≈ 词前空格宽度)。量不到光标时选择信任,而不是拒掉所有悬浮。
31
+
32
+ ### 打包闸门不再崩在退出上(开发侧)
33
+
34
+ - `pnpm publish` 曾报 `ERR_PNPM_EXECUTOR_LIFECYCLE_SCRIPT_FAILED` / `0xc0000409`:闸门**通过了**,却在
35
+ `process.exit()` 时撞上 libuv 的 `UV_HANDLE_CLOSING` 断言(fetch 的 keep-alive socket)。现在先关
36
+ dispatcher、再用 `process.exitCode` 让事件循环自然排空;绿路径退 0、红路径退 1,两条都验过。
37
+
38
+ ## 1.1.0 — 2026-10-10
39
+
40
+ ### 词条组(目录)
41
+
42
+ - **组是列表里的一行**,和词条同一块地方、同一层滚动、同一行尺寸——因为组和词条是同一类东西:**点开它**。
43
+ 行里给出组名、里面有多少条(含所有下级)、以及一个 `›`。
44
+ - **一次只看一层**:顶层显示"就在顶层"的词条与下级组;进去之后显示该层的词条与它自己的下级组,上层的
45
+ 词条不再出现(组是目录,里面的东西是进去之后看到的)。
46
+ - **面包屑是回去的路**:`全部 › backend › net`,每段都能点,当前层不可点(它不是动作)。只能进不能出的
47
+ 目录是陷阱。
48
+ - **站在哪一层,新建的词条就落在哪一层**(编辑器里的「分组」字段也可手改,用 `/` 分层)。
49
+ - 分组是**决定**而不是内容:按 `groupAt` 时间戳合并(第三次用 `pinnedAt` 那套),所以移动、移回顶层、
50
+ 同毫秒再移动都有确定结果,不会因合并顺序被翻案。
51
+ - 「导入文件夹」按文件夹路径建组(选中的文件夹名就是第一级),可用开关关掉。
52
+
53
+ ### 恢复删除是一个有名字的动作
54
+
55
+ - `restoreEntry`:记录 `restoredAt` 作为合并真正去读的证据,并**重新封存文档**——墓碑与它的 key 直接消失,
56
+ 而不是"在一次比较里被否决"。导入时**新词条走写入、被删词条走恢复**(`planImport` 用 `revived` 单独列出
57
+ 被恢复的那些)。
58
+ - 这是被报上来的形状问题:**"被投票否决"不等于"撤回"**,此后任何一次读到墓碑的合并都能把删除放回去。
59
+
60
+ ### 词条行:钉选在前、操作在第二行,而且操作不再让列表跳动
61
+
62
+ - **列表不再重排**:以前排序是"钉选优先 → 待补充优先 → 最近见过优先",于是钉选会把词条顶到首位、补上解释会让它掉下去、正文里再提一次都会打乱顺序——**操作移动了正在看的那一行**。现在只按**创建时间倒序**:这是唯一不会被任何操作改变的东西。钉选状态就在行首显示,「已钉选」标签负责汇集它们,顺序不必再承担这件事。
63
+ - **钉选移到标题前面**:它是词条的**状态**而不是对它的操作,所以和标题同一行、且在标题之前。
64
+ - **操作统一到第二行**:复制 / 反馈 / 编辑 / 删除,每一行都在同样的位置。以前它们跟在标题行末尾,位置随术语长度、徽标数量、有没有分类而变——控件在行与行之间游走。
65
+ - **单行输入框统一宽度**(22em;地址类字段显式放宽到 30em)。上一版按内容给了 18/12/14/20em 不等,结果是一列长短不齐的框,读起来像失误而不是决定。多行字段(Area)仍占满宽度。
66
+
67
+ ### 导入:文件夹,以及"导入之后看得见"
68
+
69
+ - **导入文件夹**:用系统自己的目录选择器(`webkitdirectory`)选一个文件夹,把里面的 `*.json` 全部读一遍
70
+ ——导出的词典、下载的包文件都认。不是 JSON 的文件直接忽略,读不了的**点名列出**(一个二十文件的文件夹
71
+ 里有个坏文件,只说"失败"等于没说);可选「用文件夹名作为分类」,只补**没有分类**的词条。用
72
+ `webkitdirectory` 而不是宿主服务,是因为那需要一个可能缺席的服务依赖,而缺席会把整个插件挂起。
73
+ - **导入之后看得见**:以前写入后仍停在原来的标签与搜索里——在「已删除」下导入,界面看起来就是"什么都没
74
+ 发生"(这正是它被报上来的样子)。现在导入页请面板切到「全部」并清空搜索,且报告里明说何时动过视图。
75
+ - **数据那条路本来就是好的**:新增的宿主往返用例证明"导入撤回的词条"在宿主那边活着、带着文件里的文本、
76
+ 且墓碑消失——报告里的"看不到"发生在显示层,不是写入层。
77
+
78
+ ### 三处界面
79
+
80
+ - **词条列表可以多列排版**:新偏好「词条排列」= 自动 / 1 / 2 / 3 列。自动按面板宽度铺,窄了回到一列;
81
+ 一列排下去是"很长一条",多列才看得动。列表容器带 `data-term-columns`,排版规则是一个可断言的纯函数。
82
+ 已删除 / 已标记视图与批量选择模式**不**参与分列(那是"决定的列表"和"带勾选框的行")。
83
+ - **导入要确认**:选文件不再立刻写入——先给一份**预演**(将导入几条 / 已有几条 / 你删过几条会被跳过 /
84
+ 重复或无效几条),按「确认导入」才真的写。勾选「导入我删除过的词条」会**重新预演**,因为要确认的
85
+ 数字必须是这个勾选产生的数字。预演用的是同一个纯函数 `planImport`,写入那一刻再算一次——所以预演
86
+ 即使过期(另一个窗口删了东西),写进去的也不是过期的答案。读文件时上一份报告同时清掉:它描述的是
87
+ 已经发生的事,留在新的确认框下面会读成在描述这一次。
88
+ - **输入框不再一律撑满**:`Field` 多了一个 `width`(上限)——包名 18em、署名 / 许可 12em、源地址 26em、
89
+ 编辑器里的术语 20em / 中文名 12em / 分类 14em。一个两字字段不该横跨整个面板。
90
+
91
+ ### 自带一个源
92
+
93
+ - **新装即有源**:`settings.packSources` 的默认值是本仓库自己的 `packs/index.json`
94
+ (`@main`,所以仓库里新增的包不必发新版就能被看到)。它不是硬编码的特例:在「源」列表里显示
95
+ **内置**、一键可移除,取回只在你打开词条包页或按刷新时发生。
96
+ - **打开页面就取一次**:没有这一步,新装用户看到的是一个源加一片空白,而「刷新」是一个没人猜得出
97
+ 目的的按钮。取的是**你自己配置的那些源**,宿主负责取并缓存一小时。
98
+ - **"从没设过"与"我全删了"是两件事**:设置里缺这个键 → 用内置默认;存着空数组 → 就是空
99
+ (不把默认塞回来)。少了这个区分,清空源列表的人每次都会被内置源"复活"一次。
100
+
101
+ ## 1.0.0 — 2026-10-10
102
+
103
+ 首个正式版(已发布到 npm)。功能面:自动收录、标注、悬停解释、点击进词条、面板五个视图与三个二级页、
104
+ 设置页、导入 / 导出、反馈、词条包与分享码。
105
+
106
+ ### 反馈
107
+
108
+ - **词条上可以留言**:编辑器里的「反馈」块记录问题类型(解释不对 / 术语不对 / 不该收录 / 其他)
109
+ 与一句自己的说明;面板多了一个「已标记」视图,每行一个「撤回标记」。
110
+ - **「解释不可信」是一条会给机器看的判断**:标上之后,自动解释**不会再覆盖**这条词条
111
+ (规则在数据层 `recordSighting`,所以页面的队列、将来的后台刷新、宿主自己的 `record` 动作都受它约束),
112
+ 列表与已标记视图里都带徽标。
113
+ - **重新生成会告诉模型上一次被否掉了**:页面发 `retry: true`,宿主在提示词末尾追加一句固定的话。
114
+ 用户自己的备注永远不会发给模型——那是把备注变成指令。
115
+ - **反馈报告**:导入 / 导出页可以把标记导出成一个文件(下载或复制)。报告里**永远没有会话原文**
116
+ (构造上就没有这个字段),当前解释要另外勾选才附上。
117
+ - **也可以记进宿主自己的反馈日志**:宿主半边用 `ctx.inject(["sessionFeedback"], …)` 接这条可选服务
118
+ (和 `llm` 同一个模式),页面 POST 到自己的 `/feedback` 路由。**没有**把它写成客户端的
119
+ `remote.sessionFeedback`:实测这个桌面端没有 `remote` 服务,写进客户端 `inject` 会让整个包
120
+ 永远等待、插件整体不加载。没有这条通道的组合会如实回答 `unavailable`,报告照样能导出。
6
121
 
7
122
  ### 词条包与分享码
8
123
 
@@ -27,7 +142,6 @@
27
142
  勾选、"精心构造的复活"因此只有一份实现);分类勾选行提成共享组件 `CategoryChecklist`
28
143
  ——**变异 harness 先发现它有两份**。
29
144
  - 源地址规则三处共用(设置存储 / 页面添加源 / 宿主发起请求前),页面不可能接受传输层会拒绝的地址。
30
- - `settings.packSources`:源的列表(去空白、同一条规则过滤、去重、上限 12)。
31
145
  - 用例的 vm 沙箱补上 `URL`(真实页面有):缺它时页面把每个地址都判成 `bad-url`,
32
146
  "拒绝 http" 的检查因此看到的是错的理由。
33
147
  - 打包修复:`files` 白名单漏了 `lib/pack-code.js`(装出来的包 import 会失败)——
@@ -41,27 +155,7 @@
41
155
  以前面板里双击词条中的词会打开编辑器、正文里拖选句子(选区结束在标记词上)会切进词典,
42
156
  现在两条路都不动,规则统一在 `lib/core/selection.js`。
43
157
 
44
- ## 未发布
45
-
46
- ### 反馈
47
-
48
- - **词条上可以留言**:编辑器里的「反馈」块记录问题类型(解释不对 / 术语不对 / 不该收录 / 其他)
49
- 与一句自己的说明;面板多了一个「已标记」视图,每行一个「撤回标记」。
50
- - **「解释不可信」是一条会给机器看的判断**:标上之后,自动解释**不会再覆盖**这条词条
51
- (规则在数据层 `recordSighting`,所以页面的队列、将来的后台刷新、宿主自己的 `record` 动作都受它约束),
52
- 列表与已标记视图里都带徽标。
53
- - **重新生成会告诉模型上一次被否掉了**:页面发 `retry: true`,宿主在提示词末尾追加一句固定的话。
54
- 用户自己的备注永远不会发给模型——那是把备注变成指令。
55
- - **反馈报告**:导入 / 导出页可以把标记导出成一个文件(下载或复制)。报告里**永远没有会话原文**
56
- (构造上就没有这个字段),当前解释要另外勾选才附上。
57
- - **也可以记进宿主自己的反馈日志**:宿主半边用 `ctx.inject(["sessionFeedback"], …)` 接这条可选服务
58
- (和 `llm` 同一个模式),页面 POST 到自己的 `/feedback` 路由。**没有**把它写成客户端的
59
- `remote.sessionFeedback`:实测这个桌面端没有 `remote` 服务,写进客户端 `inject` 会让整个包
60
- 永远等待、插件整体不加载。没有这条通道的组合会如实回答 `unavailable`,报告照样能导出。
61
-
62
- ## 1.0.0 — 2026-10-10
63
-
64
- 首个正式版。功能面:自动收录、标注、悬停解释、点击进词条、面板四个视图与两个二级页、
158
+ 首个正式版的功能面:自动收录、标注、悬停解释、点击进词条、面板视图与二级页、
65
159
  设置页、导入 / 导出。
66
160
 
67
161
  ### 收录与标注
package/README.md CHANGED
@@ -314,16 +314,16 @@ POST /dsh-term-dictionary/feedback { sessionId, text, category }
314
314
  ```
315
315
  页面对这几种结果分别给不同的话,不合并成一句"失败了":`unavailable` 是"这个版本做不到",`session-not-found` 是"那个会话没了",`no-session` 是"还没看到过会话,先回对话里点一下"。
316
316
 
317
- ## 面板的五个视图与两个二级页
317
+ ## 面板的五个视图与三个二级页
318
318
 
319
- 标题栏右侧依次是「设置」「导入 / 导出」、新建词条、批量选择;下面是搜索框与四个视图标签。
319
+ 标题栏右侧依次是「设置」「导入 / 导出」「词条包」、新建词条、批量选择;下面是搜索框与五个视图标签。
320
320
 
321
321
  | 视图 / 页面 | 内容 |
322
322
  |---|---|
323
323
  | **全部 / 待补充 / 已钉选** | 同一份词条列表的三种看法:全部、还没有解释的、你钉选的。 |
324
324
  | **已标记** | 你标过的词条:写了什么问题、有没有判为不可信,一行一个「撤回标记」。见「反馈」一节。 |
325
325
  | **已删除** | 删掉的词条(墓碑),可以撤回。见下一节。 |
326
- | **设置**(二级页) | 11 项偏好,每项一行:名字(不随状态变化)+ 它做什么 + 控件。 |
326
+ | **设置**(二级页) | 12 项偏好,每项一行:名字(不随状态变化)+ 它做什么 + 控件。 |
327
327
  | **导入 / 导出**(二级页) | 按全部或按分类导出成文件;从文件导入;导出反馈报告。见「导入 / 导出」一节。 |
328
328
 
329
329
  二级页开在面板内部而不是弹窗里:面板占着主区域,弹窗会盖住它正在处理的东西。
@@ -393,6 +393,10 @@ Quorum(多数派确认)
393
393
 
394
394
  推荐用 jsDelivr 托管(`https://cdn.jsdelivr.net/gh/<owner>/<repo>@<tag>/index.json`):它是静态、可缓存、对国内网络也通的那条路。
395
395
 
396
+ **新装自带一个源**:本仓库的 `packs/index.json`(`@main`,在「源」列表里标着**内置**,一键可移除)。打开词条包页时会自动取一次——没有这一步,新装用户看到的是一个源加一片空白,而「刷新」是个没人猜得出目的的按钮。取的是**你自己配置的那些源**,宿主负责取并缓存一小时。
397
+
398
+ 设置层面有一处必须分清:**缺这个键**(从没设过)用内置默认,**存着空数组**(我全删了)就是空——少了这个区分,清空源列表的人每次打开都会被内置源"复活"一次。
399
+
396
400
  ### 自己发一个源(四步)
397
401
 
398
402
  ```
@@ -733,7 +737,7 @@ host 的 client 图**里,而不是「磁盘上有文件」。实测它复现
733
737
  - **词典分享市场**:尚未开始。
734
738
 
735
739
  已经可用的:搜索、四个视图(含**已删除**与**撤回**)、钉选、编辑、单条与批量删除、
736
- 设置页的 11 项偏好、导入 / 导出(含「按分类导出」与「导入我删除过的词条」)、
740
+ 设置页的 12 项偏好、导入 / 导出(含「按分类导出」与「导入我删除过的词条」)、
737
741
  面板底部的「清空词典」(跳过钉选的)与「复制 JSON」、`用模型生成解释`。
738
742
 
739
743
  ## 已知限制