@wenaixi/dsh-prompt-history 2.0.1 → 2.1.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 ADDED
@@ -0,0 +1,281 @@
1
+ # Changelog
2
+
3
+ 本仓库的版本历史。格式遵循 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/),版本号遵循 [语义化版本](https://semver.org/lang/zh-CN/)。
4
+
5
+ ## [Unreleased]
6
+
7
+ ## [2.1.0] - 2026-10-06
8
+
9
+ ### 变更
10
+
11
+ - **复刻 Claude Code 的上下键历史与双击 Esc 语义**:↑/↓ 从 bash 前缀搜索改为顺序浏览(↑ 从最新一条逐条回退、到底不环绕;↑ 回填光标签行首、↓/恢复草稿光标行尾;多行输入只在光标处于首/末行时才接管方向键,行号按 Lexical 的 `<br>` 结构计算)。双击 Esc 改为草稿非空时第一次提示、第二次存入历史后清空输入框(空草稿仍是打开历史列表)。
12
+ - **去掉设置保存按钮,改动自动保存**:配置卡不再使用官方 `SettingsForm` 外壳与 staged 草稿,开关、单选与「恢复默认」点击即写入宿主;失败时显示提示并回落到宿主真值。删除 `save/saving/conflict/draftHint` 文案键。
13
+ - **README 精简为双语文档**:主 README 改为英文,新增 `README.zh.md` 中文版;移除 `README.en.md` / `README.es.md` / `README.pt.md` 并同步 `package.json` 的 `files` 清单。
14
+
15
+ ### 修复
16
+
17
+ - **Lexical 多行输入的首/末行判定**:Lexical 的换行是 `<br>` 而非 `\n`,旧实现按换行符判断会把多行草稿误判成单行,导致光标停在第二行按 ↑ 也直接进历史。改为按「host 开头到光标锚点的 `<br>` 数」计算行号;空输入框的占位 `<br>` 不计为第二行。
18
+
19
+ ## [2.0.2] - 2026-10-06
20
+
21
+ ### 修复
22
+
23
+ - **设置界面迁移到官方 SettingsForm 体系**:`plugins.bundle.config` 配置卡改用官方 `SettingsForm` 外壳(不可用提示、只读横幅、保存失败提示、Save/Saving、离开即丢弃草稿),保存语义改为 staged 草稿 + 一次保存。新增 `SettingsCardController`(仿官方 `dsh-client-ui-settings-subagent` 控制器):用快照 `revision` 做冲突栅栏、保存后回读逐字段比对确认落盘、代际计数抑制卸载后的迟到回执。文案键对齐官方模板句式。
24
+ - **修复 2.0.1 客户端从未加载成功**:tsdown 产物注册 id 仍是旧名 `dsh-prompt-history`,与改名后的包名 `@wenaixi/dsh-prompt-history` 不一致,client-modules 报 `loaded without registering`,整条 client bundle 无法激活。产物 id 与 `plugins.bundle.config` 插槽 key 一并修正为包名(plugin-manager 按 `entry.options.key` 与 `pkg.name` 比对决定是否渲染配置区)。
25
+ - **设置写入文档对齐**:`cordis.patch.yml` 与 schema 默认值逐字段一致(config-editor 深比较判定)。
26
+
27
+ ### 新增
28
+
29
+ - `prefs-model.ts` 新增 `prefsEqual` / `draftDiffOps` 纯函数并补单测(23 项全绿)。
30
+
31
+ ## [2.0.1] - 2026-10-05
32
+
33
+ ### 修复
34
+
35
+ - scoped 包名在 YAML 里加引号:裸 `@` 开头导致 `dsh add` 解析失败。
36
+
37
+ ## [2.0.0] - 2026-10-05
38
+
39
+ ### 变更
40
+
41
+ - 包名改为 scoped:`@wenaixi/dsh-prompt-history`。
42
+ - 配置界面迁移到 DSH 官方插件配置组合(`plugins.bundle.config` + Host `Config` schema + volatile 字段),设置由 DSH 宿主持久化;旧版浏览器 localStorage 设置在首次打开时自动迁移。
43
+
44
+ ### 其他
45
+
46
+ - 配置 CI(`pnpm install --frozen-lockfile` + typecheck + 单测 + build)与发布流水线(tag 触发 npm publish + GitHub Release)。
47
+
48
+ ## [1.2.15] - 2026-10-04
49
+
50
+ ### 修复
51
+
52
+ - 依赖对齐当前 DSH 客户端 API 与兼容矩阵。
53
+
54
+ ## [1.2.14] - 2026-10-03
55
+
56
+ ### 修复
57
+
58
+ - 跨 DSH 代际规范化会话节点读取。
59
+
60
+ ## [1.2.13] - 2026-10-02
61
+
62
+ ### 修复
63
+
64
+ - rc.1 会话快照的 chat nodes 是 store 不是数组。
65
+
66
+ ## [1.2.12] - 2026-10-01
67
+
68
+ ### 修复
69
+
70
+ - 兼容 DSH 0.1.2(Lexical 编辑器 + chat-view nodes)。
71
+
72
+ ## [1.2.11] - 2026-09-30
73
+
74
+ ### 修复
75
+
76
+ - 全量历史拉宽真正执行;收紧行距;提示气泡点击即关。
77
+
78
+ ## [1.2.10] - 2026-09-29
79
+
80
+ ### 新增
81
+
82
+ - 会话目录(Chat TOC)显示全量历史。
83
+
84
+ ## [1.2.9] - 2026-09-28
85
+
86
+ ### 修复
87
+
88
+ - TOC 点击总是跳到正确的消息;收紧行距。
89
+
90
+ ## [1.2.8] - 2026-09-27
91
+
92
+ ### 新增
93
+
94
+ - TOC 行编号统一;悬停显示全文气泡。
95
+
96
+ ## [1.2.7] - 2026-09-26
97
+
98
+ ### 修复
99
+
100
+ - TOC 条目显示全文;移除坏掉的 line-clamp。
101
+
102
+ ## [1.2.6] - 2026-09-25
103
+
104
+ ### 新增
105
+
106
+ - TOC 面板右下角拖拽调整大小。
107
+
108
+ ## [1.2.5] - 2026-09-24
109
+
110
+ ### 修复
111
+
112
+ - TOC 条目不被压缩;头部固定、列表滚动。
113
+
114
+ ## [1.2.4] - 2026-09-23
115
+
116
+ ### 修复
117
+
118
+ - TOC 条目多行可读;面板加宽。
119
+
120
+ ## [1.2.3] - 2026-09-22
121
+
122
+ ### 修复
123
+
124
+ - 长列表下 TOC 可靠滚动。
125
+
126
+ ## [1.2.2] - 2026-09-21
127
+
128
+ ### 新增
129
+
130
+ - TOC 面板像上下文菜单一样吸附在 grip 上。
131
+
132
+ ## [1.2.1] - 2026-09-20
133
+
134
+ ### 修复
135
+
136
+ - TOC 面板跟随 grip 且始终在视口内。
137
+
138
+ ## [1.2.0] - 2026-09-19
139
+
140
+ ### 变更
141
+
142
+ - 移除「off」复制模式与代码工具栏按钮。
143
+
144
+ ## [1.1.0] - 2026-09-18
145
+
146
+ ### 新增
147
+
148
+ - 可开关的会话目录(Chat TOC);终端字形替换齿轮导航图标。
149
+
150
+ ## [1.0.0] - 2026-09-17
151
+
152
+ ### 新增
153
+
154
+ - 界面国际化(zh/en),终端式输入的设置标签。
155
+
156
+ ## [0.17.0] - 2026-09-16
157
+
158
+ ### 新增
159
+
160
+ - 复制为代码的工具栏动作;可选跨会话历史环(默认关)。
161
+
162
+ ## [0.16.0] - 2026-09-15
163
+
164
+ ### 新增
165
+
166
+ - TOC grip 可拖拽;位置存 localStorage。
167
+
168
+ ## [0.15.0] - 2026-09-13
169
+
170
+ ### 新增
171
+
172
+ - 会话目录(Chat TOC)grip 雏形:列出用户消息、点击跳转。
173
+
174
+ ## [0.14.0] - 2026-09-12
175
+
176
+ ### 新增
177
+
178
+ - bash 风格前缀历史搜索(带前缀按 ↑);Ctrl+R 增量反向搜索。
179
+
180
+ ## [0.13.0] - 2026-09-11
181
+
182
+ ### 变更
183
+
184
+ - 引用改为干净的 markdown 引用块(`>` 前缀)。
185
+
186
+ ## [0.12.0] - 2026-09-10
187
+
188
+ ### 新增
189
+
190
+ - 引用在输入框渲染为卡片式盒子,下一行继续输入。
191
+
192
+ ## [0.11.0] - 2026-09-09
193
+
194
+ ### 变更
195
+
196
+ - 引用把选中文本的完整内容以 `>` 引用块插入输入框。
197
+
198
+ ## [0.10.0] - 2026-09-08
199
+
200
+ ### 新增
201
+
202
+ - 输入框上方全文引用预览条;chip 气泡显示完整引用。
203
+
204
+ ## [0.9.0] - 2026-09-07
205
+
206
+ ### 新增
207
+
208
+ - 引用插入引用 chip(视觉可区分),发送时展开为 `>` 引用块,chip 后换行。
209
+
210
+ ## [0.8.0] - 2026-09-06
211
+
212
+ ### 新增
213
+
214
+ - 选区工具栏增加「引用」动作:把选中文本以 `>` 引用块插入输入框。
215
+
216
+ ## [0.7.0] - 2026-09-05
217
+
218
+ ### 变更
219
+
220
+ - 选区复制工具栏(显式点击复制)成为默认;选中即自动复制改为可选。
221
+
222
+ ## [0.6.1] - 2026-09-04
223
+
224
+ ### 变更
225
+
226
+ - 设置区块改名「终端式输入」便于查找。
227
+
228
+ ## [0.6.0] - 2026-09-03
229
+
230
+ ### 新增
231
+
232
+ - 设置区块:选中即复制与右键粘贴开关。
233
+
234
+ ## [0.5.1] - 2026-09-02
235
+
236
+ ### 新增
237
+
238
+ - 全页选中即复制,带可见的已复制气泡。
239
+
240
+ ## [0.5.0] - 2026-09-01
241
+
242
+ ### 新增
243
+
244
+ - 选中即复制(任意选中方式)。
245
+
246
+ [Unreleased]: https://github.com/Wenaixi/dsh-prompt-history/compare/v2.1.0...HEAD
247
+ [2.1.0]: https://github.com/Wenaixi/dsh-prompt-history/compare/v2.0.2...v2.1.0
248
+ [2.0.2]: https://github.com/Wenaixi/dsh-prompt-history/compare/v2.0.1...v2.0.2
249
+ [2.0.1]: https://github.com/Wenaixi/dsh-prompt-history/compare/v2.0.0...v2.0.1
250
+ [2.0.0]: https://github.com/Wenaixi/dsh-prompt-history/compare/v1.2.15...v2.0.0
251
+ [1.2.15]: https://github.com/Wenaixi/dsh-prompt-history/compare/v1.2.14...v1.2.15
252
+ [1.2.14]: https://github.com/Wenaixi/dsh-prompt-history/compare/v1.2.13...v1.2.14
253
+ [1.2.13]: https://github.com/Wenaixi/dsh-prompt-history/compare/v1.2.12...v1.2.13
254
+ [1.2.12]: https://github.com/Wenaixi/dsh-prompt-history/compare/v1.2.11...v1.2.12
255
+ [1.2.11]: https://github.com/Wenaixi/dsh-prompt-history/compare/v1.2.10...v1.2.11
256
+ [1.2.10]: https://github.com/Wenaixi/dsh-prompt-history/compare/v1.2.9...v1.2.10
257
+ [1.2.9]: https://github.com/Wenaixi/dsh-prompt-history/compare/v1.2.8...v1.2.9
258
+ [1.2.8]: https://github.com/Wenaixi/dsh-prompt-history/compare/v1.2.7...v1.2.8
259
+ [1.2.7]: https://github.com/Wenaixi/dsh-prompt-history/compare/v1.2.6...v1.2.7
260
+ [1.2.6]: https://github.com/Wenaixi/dsh-prompt-history/compare/v1.2.5...v1.2.6
261
+ [1.2.5]: https://github.com/Wenaixi/dsh-prompt-history/compare/v1.2.4...v1.2.5
262
+ [1.2.4]: https://github.com/Wenaixi/dsh-prompt-history/compare/v1.2.3...v1.2.4
263
+ [1.2.3]: https://github.com/Wenaixi/dsh-prompt-history/compare/v1.2.2...v1.2.3
264
+ [1.2.2]: https://github.com/Wenaixi/dsh-prompt-history/compare/v1.2.1...v1.2.2
265
+ [1.2.1]: https://github.com/Wenaixi/dsh-prompt-history/compare/v1.2.0...v1.2.1
266
+ [1.2.0]: https://github.com/Wenaixi/dsh-prompt-history/compare/v1.1.0...v1.2.0
267
+ [1.1.0]: https://github.com/Wenaixi/dsh-prompt-history/compare/v1.0.0...v1.1.0
268
+ [1.0.0]: https://github.com/Wenaixi/dsh-prompt-history/compare/v0.17.0...v1.0.0
269
+ [0.17.0]: https://github.com/Wenaixi/dsh-prompt-history/compare/v0.16.0...v0.17.0
270
+ [0.16.0]: https://github.com/Wenaixi/dsh-prompt-history/compare/v0.15.0...v0.16.0
271
+ [0.15.0]: https://github.com/Wenaixi/dsh-prompt-history/compare/v0.14.0...v0.15.0
272
+ [0.14.0]: https://github.com/Wenaixi/dsh-prompt-history/compare/v0.13.0...v0.14.0
273
+ [0.13.0]: https://github.com/Wenaixi/dsh-prompt-history/compare/v0.12.0...v0.13.0
274
+ [0.12.0]: https://github.com/Wenaixi/dsh-prompt-history/compare/v0.11.0...v0.12.0
275
+ [0.11.0]: https://github.com/Wenaixi/dsh-prompt-history/compare/v0.10.0...v0.11.0
276
+ [0.10.0]: https://github.com/Wenaixi/dsh-prompt-history/compare/v0.9.0...v0.10.0
277
+ [0.9.0]: https://github.com/Wenaixi/dsh-prompt-history/compare/v0.8.0...v0.9.0
278
+ [0.8.0]: https://github.com/Wenaixi/dsh-prompt-history/compare/v0.7.0...v0.8.0
279
+ [0.7.0]: https://github.com/Wenaixi/dsh-prompt-history/compare/v0.6.0...v0.7.0
280
+ [0.6.0]: https://github.com/Wenaixi/dsh-prompt-history/compare/v0.5.0...v0.6.0
281
+ [0.5.0]: https://github.com/Wenaixi/dsh-prompt-history/compare/v0.4.1...v0.5.0
package/README.md CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  # ⌨️ @wenaixi/dsh-prompt-history
4
4
 
5
- **DSH Web 输入框的「类 Linux shell」提示词历史 + 终端式复制粘贴插件。**
5
+ **Terminal-style input for the DeepSeek Harness Web GUI composer — Claude Code-style prompt history, copy & quote, and right-click paste.**
6
6
 
7
- *像在终端里一样按 ↑ —— 历史、引用、粘贴,一个插件搞定。*
7
+ *Press ↑ like it's a terminal — history, quoting and pasting in one plugin.*
8
8
 
9
9
  [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
10
10
  [![DSH plugin](https://img.shields.io/badge/dsh-plugin-✅-green)](https://github.com/topics/dsh-plugin)
@@ -12,90 +12,91 @@
12
12
  [![npm version](https://img.shields.io/npm/v/@wenaixi/dsh-prompt-history)](https://www.npmjs.com/package/@wenaixi/dsh-prompt-history)
13
13
  [![npm downloads](https://img.shields.io/npm/dm/@wenaixi/dsh-prompt-history)](https://www.npmjs.com/package/@wenaixi/dsh-prompt-history)
14
14
 
15
- [English](README.en.md) · **简体中文** · [Español](README.es.md) · [Português](README.pt.md)
15
+ **English** · [简体中文](README.zh.md)
16
16
 
17
17
  </div>
18
18
 
19
19
  ---
20
20
 
21
- ## 兼容性
21
+ ## Compatibility
22
22
 
23
- | 表面 | 状态 |
23
+ | Surface | Status |
24
24
  |---|---|
25
- | DSH 版本 | 目标为 **0.2.0-rc.2**;客户端配置卡片使用 `plugins.bundle.config` 与 Host `Config` schema |
26
- | 平台 | Web GUI(客户端插件;设置由 DSH Host 配置持久化;历史数据仍按功能需要使用浏览器本地存储) |
25
+ | DSH versions | Targets **0.2.0-rc.2**; the configuration card uses `plugins.bundle.config` with the Host `Config` schema and a self-drawn shell (write-on-change, no Save button) |
26
+ | Platform | Web GUI only (client plugin; settings are persisted by the DSH Host, cross-session history stays in browser local storage) |
27
27
  | Node | `>=20` |
28
- | 模型 | 任意(不发起模型请求 —— 纯 UI 行为) |
29
- | 界面语言 | 中文 / English(跟随 DSH 应用语言,设置页可切换) |
28
+ | Model | Any (no model requests — pure UI behavior) |
29
+ | UI language | 中文 / English (follows the DSH app locale) |
30
30
 
31
- ## 你能得到什么
31
+ ## What you get
32
32
 
33
- `@wenaixi/dsh-prompt-history` 把终端的输入历史搬进 DeepSeek Harness Web 输入框:
33
+ `@wenaixi/dsh-prompt-history` puts a terminal's input history into the DeepSeek Harness Web GUI composer:
34
34
 
35
- 1. **类 shell 的方向键召回** — 空输入时 **↑** 召回上一条发送过的消息(最新在前);**输入前缀后按 ↑** 跳到最近一条以该前缀开头的消息(bash 的 `history-search-backward` 行为),继续按 ↑ 往前翻匹配;**↓** 向后翻(含前缀匹配的前向),翻到底时**恢复你翻历史之前正在输入的那一行**(readline 的 pending-line 行为)。
36
- 2. **编辑即退出** — 浏览历史时一旦动手编辑,自动回到当前行,不再继续翻。
37
- 3. **Ctrl+R 历史列表** — 一键调出全部历史提问的浮层列表(最新在前,重复提问只保留最新一次)。焦点留在输入框:继续打字即按「包含」实时过滤并高亮命中词,**↑↓** 移动高亮且不改动草稿,Home/End 跳首尾,**Enter 或 Tab** 把高亮那条写进草稿,**Esc** 关闭并把草稿还原成打开前那一行。底部实时显示「命中数 / 总条数」。
38
- 4. **双击 Esc 打开同一个列表**(设置里可关)— 输入框为空时 800 毫秒内连按两次 Esc 即可打开;第一次 Esc 仍然照常关闭工具栏等浮层(不吞按键),任何其他按键会取消这次待定。设置项三选:**只用 Ctrl+R** / **只用双击 Esc** / **两者都要**(默认)。
39
- 5. **复制 + 引用(两种模式,设置里切换)** — 页面里任何非空选区——输入框、聊天消息、代码块等——按所选模式处理:
40
- - **工具栏**(默认):选区上方出现「复制」「引用」按钮——复制点击才写剪贴板(不刷屏 Win+V);**引用**把选中文本的**完整内容**以简约的 `>` 引用块插入输入框(标准 markdown 引用,发送时渲染为引用块)。
41
- - **选中即自动复制**:终端风格,选中直接写系统剪贴板。
42
- 6. **鼠标右键直接粘贴** — 在输入框上右键即粘贴剪贴板内容(和 Linux 终端一致,不弹菜单);粘贴走与 Ctrl+V 完全一致的管线(图片与引用 chip 行为一致),execCommand 路径被限制时自动回退到 Clipboard API 手动插入。
43
- 7. **跨会话历史记忆**(设置里可开关,默认关)— 开启后 ↑/↓ 历史在会话间保持,存于浏览器本地(上限 200 条),刷新/切换会话不丢失。
35
+ 1. **Claude Code-style arrow recall** — with the caret on the **first line** of the draft, **Up** walks back through prompts one by one from the most recent (caret parks at the start of each recalled line); at the oldest entry Up does nothing (no wrap-around). **Down** walks forward (recalled lines park the caret at the end) and, at the bottom edge, **restores the line you were typing before browsing began** (an empty draft restores an empty line). In multi-line drafts, Up/Down still move the caret normally unless it is on the first/last line.
36
+ 2. **Edit exits browsing** — editing the draft while browsing drops back to the live line.
37
+ 3. **Ctrl+R history list** — one key opens the full prompt-history overlay (newest first, duplicates keep only their latest occurrence). Focus stays in the input: typing filters by substring with live highlighting, **↑↓** move the highlight without touching the draft, Home/End jump to the edges, **Enter or Tab** fills the highlighted entry, **Esc** closes and restores the draft from before opening. The footer shows "matches / total" live.
38
+ 4. **Double Escape** (toggleable in Settings) — matches Claude Code semantics: with a **non-empty** draft the first Escape hints "Esc again to clear" and passes through, the second within 800 ms **saves the draft to history and clears the input** (the cleared text is then recallable with Up); with an **empty** draft a double Escape opens the history list. Three-way choice: **Ctrl+R only** / **Double Escape only** / **Both** (default).
39
+ 5. **Copy + quote (two modes, in Settings)** — any non-empty selection in the page — the composer input, chat messages, code blocks — is handled per the chosen mode:
40
+ - **Toolbar** (default): Copy / Quote buttons appear above the selection — copy writes the clipboard only on click (no Win+V flooding); **Quote** inserts the FULL selected text as a clean `>`-prefixed markdown blockquote into the composer (rendered as a blockquote when sent).
41
+ - **Auto** (terminal-style): copies the selection straight to the system clipboard on select.
42
+ 6. **Right-click pastes directly** — a right-click on the composer pastes the clipboard — no context menu, like a Linux terminal. Paste runs the same pipeline as Ctrl+V (images and reference chips behave identically), with a Clipboard API fallback when the execCommand path is blocked.
43
+ 7. **Cross-session history** (Settings toggle, default off) — keeps Up/Down history across sessions, stored in browser localStorage (cap 200), survives reloads and session switches.
44
44
 
45
- 纯 UI 行为:不产生会话事件、不改变 agent 循环、不发起模型请求。召回/引用的文本只会进入输入框草稿,只有**你**按 Enter 才会到达模型。
45
+ Pure UI behavior: no session events, no agent-loop changes, no model requests. Recalled or quoted text only enters the ordinary composer draft — it reaches the model only if *you* press Enter.
46
46
 
47
- ## 快速开始
47
+ ## Quick start
48
48
 
49
49
  ```sh
50
- # 1. 把插件装进你的 profile
50
+ # 1. install the bundle into your profile
51
51
  dsh plugin --profile web add @wenaixi/dsh-prompt-history
52
52
 
53
- # 2. 刷新页面即可使用(无需重启服务)
53
+ # 2. refresh the page — no service restart needed
54
54
  ```
55
55
 
56
- ## 安装与卸载
56
+ ## Install & uninstall
57
57
 
58
- - **npm 渠道**(已发布版本):`dsh plugin --profile web add @wenaixi/dsh-prompt-history`
59
- - **源码渠道**(本地开发,最新 `main`):`dsh plugin --profile web add "github:Wenaixi/dsh-prompt-history#main"`(源码检出需先 `pnpm run build` —— 未构建的 bundle 会拒绝启动)
60
- - **卸载**:`dsh plugin --profile web remove @wenaixi/dsh-prompt-history`
58
+ - **npm channel** (published releases): `dsh plugin --profile web add @wenaixi/dsh-prompt-history`
59
+ - **git channel** (local dev, latest `main`): `dsh plugin --profile web add "github:Wenaixi/dsh-prompt-history#main"` (a source checkout must be built first — `pnpm run build`; an unbuilt bundle refuses to boot)
60
+ - **uninstall**: `dsh plugin --profile web remove @wenaixi/dsh-prompt-history`
61
61
 
62
- ## 配置
62
+ ## Configuration
63
63
 
64
- 打开 **插件 → `@wenaixi/dsh-prompt-history` → 配置**(由 DSH 宿主配置持久化;旧版浏览器设置会在首次打开时自动迁移):
64
+ Open **Plugins → `@wenaixi/dsh-prompt-history` → configuration** (persisted by the DSH Host into `cordis.patch.yml`; legacy browser settings migrate on first open). Changes save immediately — there is no Save button: every toggle, option pick, or "Restore defaults" click writes the Host at once.
65
65
 
66
- | 选项 | 默认 | 说明 |
66
+ | Option | Default | Meaning |
67
67
  |---|---|---|
68
- | 复制方式(选中文字时) | `工具栏复制` | `工具栏`(推荐,点击才写剪贴板)/ `选中即自动复制`(终端风格) |
69
- | 跨会话历史记忆 | 关 | ↑/↓ 历史在会话间保持,历史数据存于浏览器本地,上限 200 条 |
70
- | 右键直接粘贴 | 开 | 关闭后右键恢复浏览器原生菜单 |
68
+ | After selecting text | `Show a toolbar` | `Nothing` / `Show a toolbar` (writes the clipboard only on click) / `Copy immediately` (terminal-style) |
69
+ | Open history list | `Both` | `Ctrl+R only` / `Double Escape only` / `Both` |
70
+ | Up/Down history | On | Off hands ↑/↓, Ctrl+R and double Escape back to the Host |
71
+ | Cross-session memory | Off | Up/Down history persists across sessions in browser local storage (cap 200) |
72
+ | Right-click paste | On | Off restores the browser's native context menu |
71
73
 
72
- ↑/↓ 历史始终开启,不随以上开关变化。
74
+ ## Features
73
75
 
74
- ## 特性
76
+ - **History comes from the session's own message log**: reads the conversation snapshot's user nodes (`user` / `steering`) and appends as they land — strictly consistent with the transcript, persisted with the session, survives page reloads, and needs no configuration or extra storage. With "Cross-session memory" on it seeds from browser localStorage (cap 200) and dedupes against the whole ring on every append.
77
+ - **Consecutive duplicates collapse**; browse state resets on session switch.
78
+ - Fully localized (中文 / English): settings, toolbar, feedback pills, history list all follow the DSH app locale.
79
+ - The client bundle is ~13 KB gzipped and depends only on the official `@deepseek-ai/*` peer packages.
75
80
 
76
- - **历史来自会话自身的消息记录**:直接读取会话快照中的用户消息节点(`user` / `steering`),随消息落地实时追加——与聊天记录严格一致,随会话持久化,刷新页面后依然可用,不需要任何配置或额外存储。
77
- - **连续重复自动合并**,浏览状态跟随会话切换自动重置。
78
- - **界面国际化**:全部文案(设置、工具栏、提示 pill、历史列表)跟随 DSH 应用语言(中文 / English)。
79
- - client bundle 压缩后约 12 KB;依赖全部走官方 `@deepseek-ai/*` peer 依赖。
81
+ ## Known limitations
80
82
 
81
- ## 已知限制
83
+ - **Ctrl+R**: while the composer is focused, Ctrl+R opens the history list — it no longer reloads the page (click outside the input first to reload).
84
+ - Plain text only: image-only or chip-bearing messages are not recalled; recalled drafts are plain text.
85
+ - Multi-line detection works on logical lines (Lexical line-breaks are `<br>`): pressing Up on a visually wrapped single line enters history instead of moving the caret up one visual row.
82
86
 
83
- - **Ctrl+R**:输入框聚焦时 Ctrl+R 打开历史列表,**不再触发浏览器刷新**(想刷新先点一下输入框外面)。
84
- - 纯文本召回:带图片/命令 chip 的消息不参与;召回内容为纯文本。
85
-
86
- ## 开发
87
+ ## Development
87
88
 
88
89
  ```sh
89
90
  pnpm install
90
91
  pnpm run typecheck # tsc --noEmit
91
- pnpm run build # tsc(lib/types)+ tsdown(lib/index.js / lib/invariant.js / lib/client.js)
92
+ pnpm run build # tsc (lib/types) + tsdown (lib/index.js / lib/invariant.js / lib/client.js)
92
93
  ```
93
94
 
94
- 浏览器半区(`src/client/`)注册在 `conversation.input.right` 槽位,构建产物为 DSH `__ModuleLoader__` 闭包格式,外部依赖仅 `react`(其余由浏览器模块表提供)。文案字典在 `src/client/locales.ts`(`zh` 为准、`en` 键位对齐),通过 `ctx.locale.register` 注册。
95
+ The browser half (`src/client/`) registers into the `conversation.input.right` slot and the plugin-detail configuration card (`plugins.bundle.config`); the build emits the DSH `__ModuleLoader__` closure format with `react` and the official `@deepseek-ai/*` peer packages as externals (everything else comes from the browser module table). The card draws its own shell and `SettingsCardController` writes on every change, falling back to the Host value on refusal. Copy dictionaries live in `src/client/locales.ts` (`zh` authoritative, `en` key-parity) and register via `ctx.locale.register`.
95
96
 
96
- ## 原理
97
+ ## How it works
97
98
 
98
- 插件是一个不可见的 composer 槽位条目:挂一个 document 捕获期 keydown 监听,仅在目标为 composer 输入框、无修饰键、非输入法组合、菜单未打开、会话非忙碌时接管 ↑/↓,通过 `inputActions.setDraft` 写入历史文本。历史列表由会话快照的 `user`/`steering` 节点按 seq 去重追加,浏览位置(index + 待恢复的当前行)保存在组件 ref 中。
99
+ The plugin is an invisible composer slot entry that mounts a capture-phase `keydown` listener on the document. It takes over Up only when the caret is on the first line (Down only on the last line), the target is the composer editor, no modifiers are held, no IME composition is active, no suggestion menu is open, and the session is not busy — then writes the recalled text through `inputActions.setDraft`. The browse position is an "entries seen" counter (`browseRef.step`) plus a copy of the line typed before browsing began, mirroring Claude Code's `upOrHistoryUp` / `downOrHistoryDown` ("move the caret first"). The history list is fed from the snapshot's `user`/`steering` nodes (deduped by seq). Multi-line row numbers are computed from Lexical's `<br>` structure.
99
100
 
100
101
  ## License
101
102
 
package/README.zh.md ADDED
@@ -0,0 +1,103 @@
1
+ <div align="center">
2
+
3
+ # ⌨️ @wenaixi/dsh-prompt-history
4
+
5
+ **DSH Web 输入框的「Claude Code 式」提示词历史 + 终端式复制粘贴插件。**
6
+
7
+ *像在终端里一样按 ↑ —— 历史、引用、粘贴,一个插件搞定。*
8
+
9
+ [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
10
+ [![DSH plugin](https://img.shields.io/badge/dsh-plugin-✅-green)](https://github.com/topics/dsh-plugin)
11
+ [![Node](https://img.shields.io/badge/node-%3E%3D20-brightgreen.svg)](#)
12
+ [![npm version](https://img.shields.io/npm/v/@wenaixi/dsh-prompt-history)](https://www.npmjs.com/package/@wenaixi/dsh-prompt-history)
13
+ [![npm downloads](https://img.shields.io/npm/dm/@wenaixi/dsh-prompt-history)](https://www.npmjs.com/package/@wenaixi/dsh-prompt-history)
14
+
15
+ [English](README.md) · **简体中文**
16
+
17
+ </div>
18
+
19
+ ---
20
+
21
+ ## 兼容性
22
+
23
+ | 表面 | 状态 |
24
+ |---|---|
25
+ | DSH 版本 | 目标为 **0.2.0-rc.2**;客户端配置卡片使用 `plugins.bundle.config` 与 Host `Config` schema,UI 自绘外壳(改动即写,无保存按钮) |
26
+ | 平台 | Web GUI(客户端插件;设置由 DSH Host 配置持久化;跨会话历史存浏览器本地) |
27
+ | Node | `>=20` |
28
+ | 模型 | 任意(不发起模型请求 —— 纯 UI 行为) |
29
+ | 界面语言 | 中文 / English(跟随 DSH 应用语言) |
30
+
31
+ ## 你能得到什么
32
+
33
+ `@wenaixi/dsh-prompt-history` 把终端的输入历史搬进 DeepSeek Harness Web 输入框:
34
+
35
+ 1. **Claude Code 式方向键召回** — 光标在输入框**第一行**时按 **↑** 从最新一条提问开始**逐条往回**(每条光标停在行首);一直翻到最旧再按 ↑ 不会环绕回最新。**↓** 往更新方向走(回填时光标停在行尾),翻到底**恢复你翻历史之前正在输入的那一行**(空输入则恢复空行)。多行草稿中,光标在第一行/最后一行之外的普通上下移行不受影响。
36
+ 2. **编辑即退出** — 浏览历史时一旦动手编辑,自动回到当前行,不再继续翻。
37
+ 3. **Ctrl+R 历史列表** — 一键调出全部历史提问的浮层列表(最新在前,重复提问只保留最新一次)。焦点留在输入框:继续打字即按「包含」实时过滤并高亮命中词,**↑↓** 移动高亮且不改动草稿,Home/End 跳首尾,**Enter 或 Tab** 把高亮那条写进草稿,**Esc** 关闭并把草稿还原成打开前那一行。底部实时显示「命中数 / 总条数」。
38
+ 4. **双击 Esc**(设置里可关)— 语义与 Claude Code 一致:草稿**非空**时第一次 Esc 提示「再按一次 Esc 清空输入」并照常透传,800 毫秒内第二次把草稿**存入历史后清空输入框**(清掉的内容随后可用 ↑ 召回);草稿**为空**时连按两次 Esc 打开历史列表。设置项三选:**只用 Ctrl+R** / **只用双击 Esc** / **两者都要**(默认)。
39
+ 5. **复制 + 引用(两种模式,设置里切换)** — 页面里任何非空选区——输入框、聊天消息、代码块等——按所选模式处理:
40
+ - **工具栏**(默认):选区上方出现「复制」「引用」按钮——复制点击才写剪贴板(不刷屏 Win+V);**引用**把选中文本的**完整内容**以简约的 `>` 引用块插入输入框(标准 markdown 引用,发送时渲染为引用块)。
41
+ - **选中即自动复制**:终端风格,选中直接写系统剪贴板。
42
+ 6. **鼠标右键直接粘贴** — 在输入框上右键即粘贴剪贴板内容(和 Linux 终端一致,不弹菜单);粘贴走与 Ctrl+V 完全一致的管线(图片与引用 chip 行为一致),execCommand 路径被限制时自动回退到 Clipboard API 手动插入。
43
+ 7. **跨会话历史记忆**(设置里可开关,默认关)— 开启后 ↑/↓ 历史在会话间保持,存于浏览器本地(上限 200 条),刷新/切换会话不丢失。
44
+
45
+ 纯 UI 行为:不产生会话事件、不改变 agent 循环、不发起模型请求。召回/引用的文本只会进入输入框草稿,只有**你**按 Enter 才会到达模型。
46
+
47
+ ## 快速开始
48
+
49
+ ```sh
50
+ # 1. 把插件装进你的 profile
51
+ dsh plugin --profile web add @wenaixi/dsh-prompt-history
52
+
53
+ # 2. 刷新页面即可使用(无需重启服务)
54
+ ```
55
+
56
+ ## 安装与卸载
57
+
58
+ - **npm 渠道**(已发布版本):`dsh plugin --profile web add @wenaixi/dsh-prompt-history`
59
+ - **源码渠道**(本地开发,最新 `main`):`dsh plugin --profile web add "github:Wenaixi/dsh-prompt-history#main"`(源码检出需先 `pnpm run build` —— 未构建的 bundle 会拒绝启动)
60
+ - **卸载**:`dsh plugin --profile web remove @wenaixi/dsh-prompt-history`
61
+
62
+ ## 配置
63
+
64
+ 打开 **插件 → `@wenaixi/dsh-prompt-history` → 配置**(由 DSH 宿主配置持久化到 `cordis.patch.yml`;旧版浏览器设置会在首次打开时自动迁移)。改动即时保存,不需要保存按钮——每次开关、切换单选或点「恢复默认」都立即写入宿主:
65
+
66
+ | 选项 | 默认 | 说明 |
67
+ |---|---|---|
68
+ | 选中文本后 | `弹出工具栏` | `什么都不做` / `弹出工具栏`(点击才写剪贴板)/ `选中即复制`(终端风格) |
69
+ | 打开历史列表 | `两者都要` | `只用 Ctrl+R` / `只用双击 Esc` / `两者都要` |
70
+ | 上下键历史 | 开 | 关闭后 ↑/↓、Ctrl+R 与双击 Esc 全部交还宿主 |
71
+ | 跨会话记忆 | 关 | ↑/↓ 历史在会话间保持,存浏览器本地,上限 200 条 |
72
+ | 右键直接粘贴 | 开 | 关闭后右键恢复浏览器原生菜单 |
73
+
74
+ ## 特性
75
+
76
+ - **历史来自会话自身的消息记录**:直接读取会话快照中的用户消息节点(`user` / `steering`),随消息落地实时追加——与聊天记录严格一致,随会话持久化,刷新页面后依然可用,不需要任何配置或额外存储。开启「跨会话记忆」后改从浏览器 localStorage(上限 200 条)播种并在每次追加时全环去重。
77
+ - **连续重复自动合并**,浏览状态跟随会话切换自动重置。
78
+ - **界面国际化**:全部文案(设置、工具栏、提示 pill、历史列表)跟随 DSH 应用语言(中文 / English)。
79
+ - client bundle 压缩后约 13 KB;依赖全部走官方 `@deepseek-ai/*` peer 依赖。
80
+
81
+ ## 已知限制
82
+
83
+ - **Ctrl+R**:输入框聚焦时 Ctrl+R 打开历史列表,**不再触发浏览器刷新**(想刷新先点一下输入框外面)。
84
+ - 纯文本召回:带图片/命令 chip 的消息不参与;召回内容为纯文本。
85
+ - 多行判定按逻辑行(Lexical 以 `<br>` 换行):超长单行**视觉折行**后按 ↑ 会直接进入历史而非上移一行。
86
+
87
+ ## 开发
88
+
89
+ ```sh
90
+ pnpm install
91
+ pnpm run typecheck # tsc --noEmit
92
+ pnpm run build # tsc(lib/types)+ tsdown(lib/index.js / lib/invariant.js / lib/client.js)
93
+ ```
94
+
95
+ 浏览器半区(`src/client/`)注册在 `conversation.input.right` 槽位与插件详情页配置卡(`plugins.bundle.config`),构建产物为 DSH `__ModuleLoader__` 闭包格式,外部依赖仅 `react` 与官方 `@deepseek-ai/*` peer 包(其余由浏览器模块表提供)。配置卡自绘外壳,`SettingsCardController` 做「操作即写」:每次改动直接写宿主,失败回落宿主真值。文案字典在 `src/client/locales.ts`(`zh` 为准、`en` 键位对齐),通过 `ctx.locale.register` 注册。
96
+
97
+ ## 原理
98
+
99
+ 插件是一个不可见的 composer 槽位条目:挂一个 document 捕获期 keydown 监听,仅在目标为 composer 输入框、无修饰键、非输入法组合、菜单未打开、会话非忙碌时接管 ↑/↓,通过 `inputActions.setDraft` 写入历史文本。浏览位置用「已浏览条数」(`browseRef.step`)表示,配合「开始浏览前那一行」的草稿副本;↑ 只在光标位于第一行时接管,↓ 只在最后一行时接管(对齐 Claude Code `upOrHistoryUp` / `downOrHistoryDown` 的「先移光标」)。历史列表由会话快照的 `user`/`steering` 节点按 seq 去重追加。多行行号按 Lexical 的 `<br>` 结构计算。
100
+
101
+ ## License
102
+
103
+ [MIT](LICENSE)