dsh-prompt-predict 0.2.0 → 0.2.2

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
@@ -4,11 +4,27 @@ All notable changes to this project are documented here. The format follows
4
4
  [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the version numbers follow
5
5
  [Semantic Versioning](https://semver.org/).
6
6
 
7
- [中文](CHANGELOG.zh.md)
7
+ [中文](CHANGELOG_zh.md)
8
8
 
9
- ## [0.2.0] — Unreleased
9
+ ### Fixed
10
+
11
+ - **The suggestion is now an in-dock row instead of a fixed overlay.** DSH `0.2.1-rc.2` stopped
12
+ exposing the composer draft through the slot's `useInput`, so the overlay kept showing while
13
+ typing; and because it was positioned from `getBoundingClientRect` it vanished whenever that
14
+ measurement failed. The row lives in `conversation.composer.dock` — space the host allocates —
15
+ and hides on the first printable keypress, which needs no draft state.
16
+ - Verified on DSH `0.2.1-rc.2`.
17
+
18
+ ## [0.2.1] — 2026-10-17
19
+
20
+ ### Fixed
21
+
22
+ - **The npm package page rendered the Chinese README.** npm picks the first `README.*` match in
23
+ glob order, and `README.zh.md` sorts before `README.md`, so the Chinese file won. The Chinese
24
+ README is now `README_zh.md`, which npm's `{README,README.*}` pattern does not match, so
25
+ `README.md` (English) is always the one published. Supersedes `0.2.0`; no code changes.
10
26
 
11
- > The code is on `main`; it is not published to npm yet (npm still serves `0.1.0`). The date will be added here once released.
27
+ ## [0.2.0] — 2026-10-17
12
28
 
13
29
  ### Added
14
30
 
@@ -35,10 +51,10 @@ All notable changes to this project are documented here. The format follows
35
51
 
36
52
  ### Docs
37
53
 
38
- - English README is now the primary `README.md` (Chinese moved to `README.zh.md`, 11 sections each, cross-linked)
54
+ - English README is now the primary `README.md` (Chinese moved to `README_zh.md`, 11 sections each, cross-linked)
39
55
  - README gained the in-DSH install route, npm install and badges, the four interactions, and the new settings
40
56
  - New demo assets: `docs/demo.gif`, `docs/screenshot.png`, `docs/social-preview.png`
41
- - This file (`CHANGELOG.md` / `CHANGELOG.zh.md`)
57
+ - This file (`CHANGELOG.md` / `CHANGELOG_zh.md`)
42
58
 
43
59
  ## [0.1.0] — 2026-10-17
44
60
 
@@ -5,9 +5,23 @@
5
5
 
6
6
  [English](CHANGELOG.md)
7
7
 
8
- ## [0.2.0] — 未发布
8
+ ### 修复
9
+
10
+ - **建议改为在 composer dock 内的一行,不再用 fixed 覆盖层。** DSH `0.2.1-rc.2` 不再通过 slot 的
11
+ `useInput` 暴露草稿,覆盖层会在打字时继续显示;而它靠 `getBoundingClientRect` 定位,一旦算不出
12
+ 坐标就整个消失。新实现放在 `conversation.composer.dock`(宿主分配好的空间),并在第一个可打印
13
+ 按键时隐藏——不依赖草稿状态。
14
+ - 已在 DSH `0.2.1-rc.2` 上验证。
15
+
16
+ ## [0.2.1] — 2026-10-17
17
+
18
+ ### 修复
19
+
20
+ - **npm 包页显示的是中文 README**。npm 按 glob 取第一个 `README.*` 匹配,而 `README.zh.md`
21
+ 排序在 `README.md` 之前,于是中文版被选中。中文版改名 `README_zh.md` 后不再匹配
22
+ `{README,README.*}`,npm 必然选到英文的 `README.md`。取代 `0.2.0`,无代码改动。
9
23
 
10
- > 代码已在 `main` 分支,尚未发布到 npm(npm 上仍是 `0.1.0`)。发布后本节会补上日期。
24
+ ## [0.2.0] — 2026-10-17
11
25
 
12
26
  ### 新增
13
27
 
@@ -34,10 +48,10 @@
34
48
 
35
49
  ### 文档
36
50
 
37
- - 英文版升为主 `README.md`(中文移到 `README.zh.md`,两侧 11 节逐节对应并互链)
51
+ - 英文版升为主 `README.md`(中文移到 `README_zh.md`,两侧 11 节逐节对应并互链)
38
52
  - README 补充「在 DSH 里安装」、npm 安装方式与徽章、四种交互说明、新设置项
39
53
  - 演示素材重录为含 `↻` / `Alt+→` 的新界面:`docs/demo.gif`、`docs/screenshot.png`、`docs/social-preview.png`
40
- - 本文件(`CHANGELOG.md` / `CHANGELOG.zh.md`)
54
+ - 本文件(`CHANGELOG.md` / `CHANGELOG_zh.md`)
41
55
 
42
56
  ## [0.1.0] — 2026-10-17
43
57
 
package/README.md CHANGED
@@ -6,14 +6,14 @@
6
6
  <a href="https://www.npmjs.com/package/dsh-prompt-predict"><img alt="npm version" src="https://img.shields.io/npm/v/dsh-prompt-predict" /></a>
7
7
  <a href="https://www.npmjs.com/package/dsh-prompt-predict"><img alt="npm downloads" src="https://img.shields.io/npm/dm/dsh-prompt-predict" /></a>
8
8
  <a href="https://github.com/ferrisching/dsh-prompt-predict/stargazers"><img alt="GitHub stars" src="https://img.shields.io/github/stars/ferrisching/dsh-prompt-predict" /></a>
9
- <img alt="Verified on DSH 0.2.0-rc.2" src="https://img.shields.io/badge/DSH-0.2.0--rc.2-4d6bfe" />
9
+ <img alt="Verified on DSH 0.2.1-rc.2" src="https://img.shields.io/badge/DSH-0.2.1--rc.2-4d6bfe" />
10
10
  <img alt="Zero runtime dependencies" src="https://img.shields.io/badge/dependencies-zero%20runtime-41ba41" />
11
11
  <img alt="Host + client plugin" src="https://img.shields.io/badge/shape-host%20%2B%20client-8250df" />
12
12
  <a href="./LICENSE"><img alt="License: MIT" src="https://img.shields.io/badge/License-MIT-yellow.svg" /></a>
13
13
  </div>
14
14
 
15
15
  <div align="center">
16
- 🌏 <a href="./README.zh.md">中文</a> · <b>English</b>
16
+ 🌏 <a href="./README_zh.md">中文</a> · <b>English</b>
17
17
  </div>
18
18
 
19
19
  <div align="center">
@@ -54,15 +54,35 @@ The plugin is published on npm. Options are ordered by convenience.
54
54
 
55
55
  **GUI**: open the plugins page → **Add plugin** → enter the package name `dsh-prompt-predict` → install.
56
56
 
57
- **Or the dsh CLI**:
57
+ **Or the dsh CLI** — pin any published version with pnpm's `@version` syntax:
58
58
 
59
59
  ```bash
60
- dsh plugin --profile desktop add dsh-prompt-predict
60
+ dsh plugin --profile desktop add dsh-prompt-predict@0.2.1
61
61
  ```
62
62
 
63
- Replace `--profile` with your own profile (usually `desktop` on the desktop app, `web` for the web build). Both routes pull from npm; **restart DSH afterwards**.
63
+ Replace `--profile` with your own profile (usually `desktop` on the desktop app, `web` for the web build), then **restart DSH**.
64
64
 
65
- > You'll find the switch and all parameters under **Settings → Prompt Suggestions**. If the plugin doesn't show up, re-run `scripts/install.sh` below to wire it up (idempotent).
65
+ > ⚠️ **The CLI only installs the package.** DSH loads a plugin only when it is also listed in
66
+ > `dsh.profile.bundles` inside `~/.dsh/profiles/<profile>/package.json`. Verified: with the package
67
+ > installed but not in that list, the plugin's routes answer `404` and nothing loads. The GUI route
68
+ > above handles it for you; with the CLI add `"dsh-prompt-predict"` to that array yourself, or just
69
+ > run `scripts/install.sh` below, which does both steps.
70
+
71
+ > You'll find the switch and all parameters under **Settings → Prompt Suggestions**.
72
+
73
+ ### Install from a release tarball
74
+
75
+ Every [release](https://github.com/ferrisching/dsh-prompt-predict/releases) carries the exact
76
+ tarball that is on npm (`shasum` matches the registry), which is handy for offline machines or for
77
+ pinning an artifact you can verify:
78
+
79
+ ```bash
80
+ gh release download v0.2.1 --repo ferrisching/dsh-prompt-predict --pattern '*.tgz'
81
+ dsh plugin --profile desktop add ./dsh-prompt-predict-0.2.1.tgz
82
+ ```
83
+
84
+ Same caveat as the CLI route above: add `"dsh-prompt-predict"` to `dsh.profile.bundles` yourself,
85
+ or run `scripts/install.sh` instead.
66
86
 
67
87
  ### Install from source
68
88
 
@@ -93,7 +113,7 @@ Then open that profile's `package.json` and add `"dsh-prompt-predict"` to the `d
93
113
 
94
114
  ### Requirements
95
115
 
96
- - Verified on **DSH `0.2.0-rc.2`** (desktop)
116
+ - Verified on **DSH `0.2.1-rc.2`** (web build; the desktop app runs the same host and client code)
97
117
  - `node` / `pnpm`: the install script prefers DSH's own runtime under `~/.dsh/dsh-runtimes/*/dependencies` and only falls back to `PATH`
98
118
  - macOS / Linux; Windows untested
99
119
 
@@ -203,7 +223,7 @@ The tests need no DSH runtime: a fake ctx plus a local HTTP server cover route r
203
223
 
204
224
  ## ⚠️ Known limitations
205
225
 
206
- - Verified only on DSH `0.2.0-rc.2`; other versions untested
226
+ - Verified only on DSH `0.2.1-rc.2`; other versions untested
207
227
  - Depends on the host's `conversation.composer.dock` and `settings.section` slot names — a major DSH update may require adapting
208
228
  - Predictions consume quota on the selected model; pinning a fast small model is cheaper than following a reasoning model
209
229
 
@@ -213,4 +233,4 @@ The tests need no DSH runtime: a fake ctx plus a local HTTP server cover route r
213
233
 
214
234
  Free to use, modify and distribute, including in closed-source commercial projects — just keep the copyright notice and license text.
215
235
 
216
- See [CHANGELOG.md](./CHANGELOG.md) for the change history ([中文](./CHANGELOG.zh.md)).
236
+ See [CHANGELOG.md](./CHANGELOG.md) for the change history ([中文](./CHANGELOG_zh.md)).
@@ -6,7 +6,7 @@
6
6
  <a href="https://www.npmjs.com/package/dsh-prompt-predict"><img alt="npm version" src="https://img.shields.io/npm/v/dsh-prompt-predict" /></a>
7
7
  <a href="https://www.npmjs.com/package/dsh-prompt-predict"><img alt="npm downloads" src="https://img.shields.io/npm/dm/dsh-prompt-predict" /></a>
8
8
  <a href="https://github.com/ferrisching/dsh-prompt-predict/stargazers"><img alt="GitHub stars" src="https://img.shields.io/github/stars/ferrisching/dsh-prompt-predict" /></a>
9
- <img alt="已验证 DSH 0.2.0-rc.2" src="https://img.shields.io/badge/DSH-0.2.0--rc.2-4d6bfe" />
9
+ <img alt="已验证 DSH 0.2.1-rc.2" src="https://img.shields.io/badge/DSH-0.2.1--rc.2-4d6bfe" />
10
10
  <img alt="零运行时依赖" src="https://img.shields.io/badge/%E4%BE%9D%E8%B5%96-%E9%9B%B6%E8%BF%90%E8%A1%8C%E6%97%B6%E4%BE%9D%E8%B5%96-41ba41" />
11
11
  <img alt="客户端 + Host 双端插件" src="https://img.shields.io/badge/%E5%BD%A2%E6%80%81-Host%20%2B%20%E5%AE%A2%E6%88%B7%E7%AB%AF%E6%8F%92%E4%BB%B6-8250df" />
12
12
  <a href="./LICENSE"><img alt="License: MIT" src="https://img.shields.io/badge/License-MIT-yellow.svg" /></a>
@@ -54,15 +54,33 @@
54
54
 
55
55
  **图形界面**:打开插件页 →「添加插件」→ 填入包名 `dsh-prompt-predict` → 安装。
56
56
 
57
- **或者用 dsh CLI**:
57
+ **或者用 dsh CLI**——想装某个已发布版本就用 pnpm 的 `@版本` 语法:
58
58
 
59
59
  ```bash
60
- dsh plugin --profile desktop add dsh-prompt-predict
60
+ dsh plugin --profile desktop add dsh-prompt-predict@0.2.1
61
61
  ```
62
62
 
63
- `--profile` 换成你自己的 profile(桌面端一般是 `desktop`,Web 端是 `web`)。两条路都是从 npm 拉取;**装完重启 DSH 生效**。
63
+ `--profile` 换成你自己的 profile(桌面端一般是 `desktop`,Web 端是 `web`),**装完重启 DSH 生效**。
64
64
 
65
- > 装完在 **设置 → 提示词联想** 里能看到开关与各项参数。若装完没生效,用下面的 `scripts/install.sh` 再跑一次补接线(幂等,可重复执行)。
65
+ > ⚠️ **CLI 只负责装包。** DSH 只有在 `~/.dsh/profiles/<profile>/package.json` 的
66
+ > `dsh.profile.bundles` 里也列出该插件时才会加载它。实测:包装了但不在该列表里,插件路由返回 `404`,
67
+ > 什么都不会加载。上面的图形界面路径会替你处理;用 CLI 的话请自己把 `"dsh-prompt-predict"` 加进该数组,
68
+ > 或直接跑下面的 `scripts/install.sh`——它两步都做。
69
+
70
+ > 装完在 **设置 → 提示词联想** 里能看到开关与各项参数。
71
+
72
+ ### 从 release 的 tarball 安装
73
+
74
+ 每个 [release](https://github.com/ferrisching/dsh-prompt-predict/releases) 都附了与 npm 上
75
+ **完全一致**的 tarball(`shasum` 与 registry 相同),适合离线机器或需要自行校验产物的场景:
76
+
77
+ ```bash
78
+ gh release download v0.2.1 --repo ferrisching/dsh-prompt-predict --pattern '*.tgz'
79
+ dsh plugin --profile desktop add ./dsh-prompt-predict-0.2.1.tgz
80
+ ```
81
+
82
+ 与上面 CLI 路径同样的注意点:请自己把 `"dsh-prompt-predict"` 加进 `dsh.profile.bundles`,
83
+ 或改用 `scripts/install.sh`。
66
84
 
67
85
  ### 从源码安装
68
86
 
@@ -93,7 +111,7 @@ pnpm add /path/to/dsh-prompt-predict
93
111
 
94
112
  ### 安装要求
95
113
 
96
- - 已在 **DSH `0.2.0-rc.2`** 上验证(桌面端)
114
+ - 已在 **DSH `0.2.1-rc.2`** 上验证(Web 构建;桌面端跑的是同一套 host 与 client 代码)
97
115
  - `node` / `pnpm`:安装脚本优先使用 `~/.dsh/dsh-runtimes/*/dependencies` 下 DSH 自带的运行时,找不到才回退 `PATH`
98
116
  - macOS / Linux;Windows 未验证
99
117
 
@@ -203,7 +221,7 @@ npm test # 66 项:51 项 Host 端 + 15 项客户端渲染冒烟
203
221
 
204
222
  ## ⚠️ 已知限制
205
223
 
206
- - 仅在 DSH `0.2.0-rc.2` 上验证过,其它版本未测
224
+ - 仅在 DSH `0.2.1-rc.2` 上验证过,其它版本未测
207
225
  - 依赖宿主的 `conversation.composer.dock` 与 `settings.section` 两个 slot 名称,DSH 大版本调整后可能需要适配
208
226
  - 联想会消耗所选模型的额度;固定到快速小模型比跟随推理模型更省
209
227
 
@@ -213,4 +231,4 @@ npm test # 66 项:51 项 Host 端 + 15 项客户端渲染冒烟
213
231
 
214
232
  可以自由使用、修改、分发,包括闭源商业项目;只需保留版权声明与许可证文本。
215
233
 
216
- 变更记录见 [CHANGELOG.zh.md](./CHANGELOG.zh.md)([English](./CHANGELOG.md))。
234
+ 变更记录见 [CHANGELOG_zh.md](./CHANGELOG_zh.md)([English](./CHANGELOG.md))。
package/client/client.js CHANGED
@@ -361,6 +361,10 @@ window.__ModuleLoader__.load({
361
361
  var abortRef = useRef(null);
362
362
  var sessionRef = useRef(sessionId);
363
363
  var dismissedByDraft = useRef(false);
364
+ // rc.2 不再把 draft 暴露给 slot,拿不到「输入框是否为空」。
365
+ // 用等价信号:建议可见时按下任何可打印键 = 用户开始输入 → 立即隐藏。
366
+ var _tk = useState(0), typedTick = _tk[0], setTypedTick = _tk[1];
367
+ var typedSince = useRef(false);
364
368
  // 逐段采纳的前缀,只有「输入框里确实还留着它」时才算数:
365
369
  // 用户把它删掉后必须重新完整展示整条建议,否则会出现从中间截断的鬼影。
366
370
  var prefixKept = accepted !== "" && suggestion.indexOf(accepted) === 0 && draft === accepted;
@@ -368,7 +372,7 @@ window.__ModuleLoader__.load({
368
372
  // 打字即隐藏,两种例外:
369
373
  // (a) 草稿又被删空 —— 用户回到了「需要建议」的状态,让它重新浮现(只有 Esc 才是永久忽略)
370
374
  // (b) 草稿正是我们逐段写进去、且没有改动的前缀 —— 不能把自己插的内容误判成用户打字
371
- dismissedByDraft.current = draft.trim() !== "" && !prefixKept;
375
+ dismissedByDraft.current = (draft.trim() !== "" || typedSince.current) && !prefixKept;
372
376
  var visibleSuggestion = dismissedByDraft.current ? "" : remaining;
373
377
 
374
378
  // 首次读取启用状态;设置页保存后通过事件让当前会话立即生效。
@@ -395,6 +399,7 @@ window.__ModuleLoader__.load({
395
399
  dismissedByDraft.current = false;
396
400
  setSuggestion("");
397
401
  setAccepted("");
402
+ typedSince.current = false;
398
403
  if (abortRef.current) abortRef.current.abort();
399
404
  }, [sessionId]);
400
405
 
@@ -405,6 +410,7 @@ window.__ModuleLoader__.load({
405
410
  dismissedByDraft.current = false;
406
411
  setSuggestion("");
407
412
  setAccepted("");
413
+ typedSince.current = false;
408
414
  if (abortRef.current) abortRef.current.abort();
409
415
  return;
410
416
  }
@@ -418,6 +424,7 @@ window.__ModuleLoader__.load({
418
424
  .then(function (result) {
419
425
  if (controller.signal.aborted || sessionRef.current !== sessionId) return;
420
426
  if (result && result.ok && typeof result.suggestion === "string") {
427
+ typedSince.current = false;
421
428
  setSuggestion(result.suggestion.trim());
422
429
  recordRun(result, null);
423
430
  } else {
@@ -483,6 +490,11 @@ window.__ModuleLoader__.load({
483
490
  var onKey = function (event) {
484
491
  if (event.isComposing) return;
485
492
  if (event.key === "Escape") { event.preventDefault(); setSuggestion(""); setAccepted(""); return; }
493
+ // 任何可打印字符 → 认定用户开始输入,隐藏建议(与「开始输入自动消失」一致)
494
+ if (!typedSince.current && typeof event.key === "string" && event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) {
495
+ typedSince.current = true;
496
+ setTypedTick(function (n) { return n + 1; });
497
+ }
486
498
  // Option/Alt + → :逐段采纳(对齐 Codex 的手感)
487
499
  if (event.key === "ArrowRight" && event.altKey) {
488
500
  if (!acceptChunk()) return;
@@ -501,7 +513,37 @@ window.__ModuleLoader__.load({
501
513
 
502
514
  // 建议直接以灰色 ghost text 覆盖在 Lexical 输入框首字符处。
503
515
  if (!enabled || dismissedByDraft.current || !visibleSuggestion) return null;
504
- return h(GhostOverlay, { suggestion: visibleSuggestion, sessionId: sessionId, onAccept: accept, onReroll: reroll, t: t });
516
+ // 在 composer dock 的流内渲染一行建议(不再用 fixed 覆盖层):
517
+ // dock 是宿主分配了空间的位置,不依赖 findElement 算坐标,也不会压在草稿文字上。
518
+ return h("div", {
519
+ "data-prompt-predict-row": "true",
520
+ role: "status",
521
+ "aria-live": "polite",
522
+ style: {
523
+ display: "flex", alignItems: "center", gap: 8, minWidth: 0,
524
+ padding: "2px 4px", fontSize: 12, lineHeight: "18px", color: "#9aa3b2",
525
+ },
526
+ },
527
+ h("span", {
528
+ style: { flex: 1, minWidth: 0, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" },
529
+ }, visibleSuggestion),
530
+ h("button", {
531
+ type: "button", onClick: accept, title: tt(t, "ghost.acceptHint"),
532
+ style: {
533
+ flex: "none", padding: "0 7px", height: 19, borderRadius: 5,
534
+ border: "1px solid var(--dsw-alias-border-l1, #d1d5db)", background: "var(--dsw-alias-bg-secondary, #f8fafc)",
535
+ color: "#9aa3b2", fontSize: 10, fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", cursor: "pointer",
536
+ },
537
+ }, "Tab"),
538
+ h("button", {
539
+ type: "button", onClick: reroll, title: tt(t, "ghost.reroll"),
540
+ style: {
541
+ flex: "none", width: 19, height: 19, padding: 0, borderRadius: 5,
542
+ border: "1px solid var(--dsw-alias-border-l1, #d1d5db)", background: "var(--dsw-alias-bg-secondary, #f8fafc)",
543
+ color: "#9aa3b2", fontSize: 11, lineHeight: 1, cursor: "pointer",
544
+ },
545
+ }, "↻"),
546
+ h("span", { style: { flex: "none", fontSize: 10, whiteSpace: "nowrap" } }, tt(t, "ghost.dismiss")));
505
547
  }
506
548
 
507
549
  // ================= 设置页 =================
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-prompt-predict",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "输入框提示词联想插件:助手回复结束后预测你的下一句话,以灰色 ghost text 浮在输入框里,Tab 采纳、Esc 忽略 | Codex-style composer prompt predictions for DeepSeek Harness: your next message ghosted into the composer, accepted with Tab.",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -16,9 +16,9 @@
16
16
  "client",
17
17
  "cordis.patch.yml",
18
18
  "README.md",
19
- "README.zh.md",
19
+ "README_zh.md",
20
20
  "CHANGELOG.md",
21
- "CHANGELOG.zh.md"
21
+ "CHANGELOG_zh.md"
22
22
  ],
23
23
  "scripts": {
24
24
  "test": "node test/predict.mjs && node test/client-render.mjs",