dsh-prompt-predict 0.1.0 → 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/CHANGELOG.md +55 -0
- package/CHANGELOG.zh.md +54 -0
- package/README.md +140 -94
- package/README.zh.md +216 -0
- package/client/client.js +364 -51
- package/lib/host-route.mjs +113 -33
- package/lib/messages.mjs +96 -0
- package/lib/predict.mjs +28 -8
- package/package.json +7 -4
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the version numbers follow
|
|
5
|
+
[Semantic Versioning](https://semver.org/).
|
|
6
|
+
|
|
7
|
+
[中文](CHANGELOG.zh.md)
|
|
8
|
+
|
|
9
|
+
## [0.2.0] — Unreleased
|
|
10
|
+
|
|
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.
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- **`↻` reroll** — a button next to the suggestion that asks the model for a different one
|
|
16
|
+
- **`Alt+→` accept piece by piece** — a couple of characters at a time in CJK, one word in Latin; the rest keeps floating and you can stop whenever you like
|
|
17
|
+
- **Two new advanced settings** — context budget (`maxChars`, 1000–20000 characters) and output cap (`maxTokens`, 16–512 tokens)
|
|
18
|
+
- **A "last prediction" line** at the bottom of the settings page: time, model, latency, whether the reasoning level was auto-downgraded or a reroll happened, and the reason when it failed
|
|
19
|
+
- **Chinese / English UI** that follows DSH's *Settings → Language* and switches **immediately** with no reload. Covers every client string (settings page, ghost hints) **and the validation errors / prediction failures returned by the host**
|
|
20
|
+
- `GET /status` accepts `?sessionId=` and reports the model that session actually uses
|
|
21
|
+
- An optional **`x-dsh-locale`** request header (`zh` / `en`) deciding which language errors come back in
|
|
22
|
+
- A client render smoke test (`test/client-render.mjs`, 18 cases) that expands the component tree through a tiny React stand-in
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
|
|
26
|
+
- The reasoning-effort dropdown is now generated from the **session's actual model** (previously the global default model, so the two could disagree and offer an unsupported level)
|
|
27
|
+
- Helper calls per turn: still **1** by default, with one extra attempt only when the reasoning level needs downgrading or a suggestion needs rerolling — **three calls is the hard ceiling**, sharing a single timeout budget
|
|
28
|
+
- Hiding the suggestion by typing is no longer permanent for the turn: **clearing the draft brings it back**
|
|
29
|
+
|
|
30
|
+
### Fixed
|
|
31
|
+
|
|
32
|
+
- **Silent failure when the reasoning level doesn't suit the real model** — the symptom was "settings look fine but no suggestion ever appears". It now drops the level and retries once
|
|
33
|
+
- **Repeated suggestions**: when two consecutive turns produced the same one, the model is asked for a different one (once only, falling back to the original)
|
|
34
|
+
- **A partially accepted prefix that the user then deleted** produced a suggestion truncated mid-sentence (Tab inserted half of it). The full suggestion is now shown again
|
|
35
|
+
|
|
36
|
+
### Docs
|
|
37
|
+
|
|
38
|
+
- English README is now the primary `README.md` (Chinese moved to `README.zh.md`, 11 sections each, cross-linked)
|
|
39
|
+
- README gained the in-DSH install route, npm install and badges, the four interactions, and the new settings
|
|
40
|
+
- New demo assets: `docs/demo.gif`, `docs/screenshot.png`, `docs/social-preview.png`
|
|
41
|
+
- This file (`CHANGELOG.md` / `CHANGELOG.zh.md`)
|
|
42
|
+
|
|
43
|
+
## [0.1.0] — 2026-10-17
|
|
44
|
+
|
|
45
|
+
First public release.
|
|
46
|
+
|
|
47
|
+
### Added
|
|
48
|
+
|
|
49
|
+
- **A suggestion the moment a reply ends** — gray ghost text at the composer's first character, matching the editor's caret position, font size and line height
|
|
50
|
+
- **Three interactions** — `Tab` to accept, `Esc` to dismiss, start typing and it vanishes; the suggestion is not part of the conversation until accepted
|
|
51
|
+
- **Follows the current session model by default** — nothing is hard-coded to a provider
|
|
52
|
+
- **Lightweight context** — only the most recent user/assistant *text*; tool results, attachments and system prompts never leave your machine
|
|
53
|
+
- **A settings page** — on/off, provider / model, response timeout, context size, reasoning effort; changes apply immediately, no DSH restart
|
|
54
|
+
- Same-origin HTTP API: `/status`, `/catalog`, `/efforts`, `/settings`, `/suggest`
|
|
55
|
+
- MIT licensed; zero third-party runtime dependencies on both the host and client side
|
package/CHANGELOG.zh.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# 变更记录
|
|
2
|
+
|
|
3
|
+
本项目的所有值得注意的变更都记在这里。格式参考 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/),
|
|
4
|
+
版本号遵循 [语义化版本](https://semver.org/lang/zh-CN/)。
|
|
5
|
+
|
|
6
|
+
[English](CHANGELOG.md)
|
|
7
|
+
|
|
8
|
+
## [0.2.0] — 未发布
|
|
9
|
+
|
|
10
|
+
> 代码已在 `main` 分支,尚未发布到 npm(npm 上仍是 `0.1.0`)。发布后本节会补上日期。
|
|
11
|
+
|
|
12
|
+
### 新增
|
|
13
|
+
|
|
14
|
+
- **`↻` 换一条**:输入框建议右侧新增按钮,点一下让模型给出不同的建议
|
|
15
|
+
- **`Alt+→` 逐段采纳**:一次填一小段(中文 2 字 / 英文 1 词),剩下的继续浮动,随时可停
|
|
16
|
+
- **设置页「高级」新增两项**:上下文预算(`maxChars`,1000–20000 字符)与输出上限(`maxTokens`,16–512 token)
|
|
17
|
+
- **设置页新增「上次预测」状态行**:时间、所用模型、耗时,以及是否自动降级了思考档位 / 换过一条,失败时直接显示原因
|
|
18
|
+
- **界面中英双语**:跟随 DSH 的「设置 → 语言」**即时切换**,无需刷新。覆盖客户端全部文案(设置页、ghost 上的提示)与 **Host 端返回的校验错误 / 预测失败原因**
|
|
19
|
+
- `GET /status` 支持 `?sessionId=`,回传该会话实际使用的模型
|
|
20
|
+
- 接口新增可选请求头 **`x-dsh-locale`**(`zh` / `en`),决定错误原因用哪种语言返回
|
|
21
|
+
- 客户端渲染冒烟测试(`test/client-render.mjs`,18 项):用极简 React 替身把组件树展开后断言
|
|
22
|
+
|
|
23
|
+
### 变更
|
|
24
|
+
|
|
25
|
+
- 设置页「思考深度」下拉改为按**会话实际使用的模型**生成(此前按全局默认模型,两者不同时用户可能选到不被支持的档位)
|
|
26
|
+
- 每轮辅助调用次数:默认仍为 **1 次**,仅在「档位需降级」或「建议撞车需换一条」时多试一次,**极端情况上限 3 次**且共享同一超时预算
|
|
27
|
+
- 打字隐藏建议后,**把草稿删空会重新显示**(此前一旦开始打字就隐藏到本轮结束)
|
|
28
|
+
|
|
29
|
+
### 修复
|
|
30
|
+
|
|
31
|
+
- **思考档位与真实模型不兼容时静默失败**——表现为「设置都对,但永远没有建议」。现在会自动去掉档位重试一次
|
|
32
|
+
- **建议复读**:连续两轮给出同一条时,要求模型换一条(一次为限,失败则保留原建议)
|
|
33
|
+
- **逐段采纳后删掉已采纳的那段**,建议会显示从中间截断的残句(按 `Tab` 只插入半句)。改为完整重新展示
|
|
34
|
+
|
|
35
|
+
### 文档
|
|
36
|
+
|
|
37
|
+
- 英文版升为主 `README.md`(中文移到 `README.zh.md`,两侧 11 节逐节对应并互链)
|
|
38
|
+
- README 补充「在 DSH 里安装」、npm 安装方式与徽章、四种交互说明、新设置项
|
|
39
|
+
- 演示素材重录为含 `↻` / `Alt+→` 的新界面:`docs/demo.gif`、`docs/screenshot.png`、`docs/social-preview.png`
|
|
40
|
+
- 本文件(`CHANGELOG.md` / `CHANGELOG.zh.md`)
|
|
41
|
+
|
|
42
|
+
## [0.1.0] — 2026-10-17
|
|
43
|
+
|
|
44
|
+
首个公开版本。
|
|
45
|
+
|
|
46
|
+
### 新增
|
|
47
|
+
|
|
48
|
+
- **回复结束即出建议**:在输入框首字符处浮出灰色 ghost text,光标位置、字号、行高对齐当前编辑器
|
|
49
|
+
- **三种交互**:`Tab` 采纳 · `Esc` 忽略 · 开始输入自动消失;采纳前建议不属于会话内容
|
|
50
|
+
- **默认跟随当前会话模型**:不向辅助调用写死任何提供商
|
|
51
|
+
- **轻量上下文**:只取最近若干条 user/assistant 的纯文本,工具结果、附件、系统提示一律不进入辅助调用
|
|
52
|
+
- **设置页**:开关、提供商 / 模型、响应超时、上下文规模、思考深度;保存后立即生效,无需重启 DSH
|
|
53
|
+
- 同源 HTTP 接口:`/status`、`/catalog`、`/efforts`、`/settings`、`/suggest`
|
|
54
|
+
- MIT 许可;Host 端与客户端均无第三方运行时依赖
|
package/README.md
CHANGED
|
@@ -1,43 +1,70 @@
|
|
|
1
1
|
# dsh-prompt-predict
|
|
2
2
|
|
|
3
3
|
<div align="center">
|
|
4
|
-
<b>Codex
|
|
5
|
-
|
|
4
|
+
<b>Codex-style composer predictions for DeepSeek Harness</b><br />
|
|
5
|
+
After each reply, your next prompt is ghosted right into the composer — <b>Tab to accept</b>, <b>Esc to dismiss</b>, start typing and it's gone<br /><br />
|
|
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
|
+
<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>
|
|
6
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>
|
|
7
|
-
<img alt="
|
|
8
|
-
<img alt="
|
|
9
|
-
<img alt="
|
|
10
|
-
<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" />
|
|
9
|
+
<img alt="Verified on DSH 0.2.0-rc.2" src="https://img.shields.io/badge/DSH-0.2.0--rc.2-4d6bfe" />
|
|
10
|
+
<img alt="Zero runtime dependencies" src="https://img.shields.io/badge/dependencies-zero%20runtime-41ba41" />
|
|
11
|
+
<img alt="Host + client plugin" src="https://img.shields.io/badge/shape-host%20%2B%20client-8250df" />
|
|
11
12
|
<a href="./LICENSE"><img alt="License: MIT" src="https://img.shields.io/badge/License-MIT-yellow.svg" /></a>
|
|
12
13
|
</div>
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
<div align="center">
|
|
16
|
+
🌏 <a href="./README.zh.md">中文</a> · <b>English</b>
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
<div align="center">
|
|
20
|
+
<img alt="Preview: after each reply a gray suggestion appears; ↻ for another one, Alt+→ to accept piece by piece, Tab to accept" src="https://raw.githubusercontent.com/ferrisching/dsh-prompt-predict/main/docs/demo.gif" width="760" />
|
|
21
|
+
</div>
|
|
15
22
|
|
|
16
|
-
|
|
23
|
+
`dsh-prompt-predict` is a [DeepSeek Harness](https://www.deepseek.com/) plugin: after every assistant turn it predicts **the message you are most likely to type next** and floats it into the composer as gray ghost text. The suggestion never enters the editor — only pressing `Tab` inserts it, and even then it stays undoable — so a wrong prediction costs you nothing.
|
|
17
24
|
|
|
18
|
-
|
|
19
|
-
- [🚀 安装](#-安装)
|
|
20
|
-
- [⌨️ 使用](#-使用)
|
|
21
|
-
- [⚙️ 设置](#-设置)
|
|
22
|
-
- [🔌 HTTP 接口](#-http-接口)
|
|
23
|
-
- [🧩 工作原理](#-工作原理)
|
|
24
|
-
- [🛠️ 开发](#-开发)
|
|
25
|
-
- [🔐 安全与成本](#-安全与成本)
|
|
26
|
-
- [⚠️ 已知限制](#-已知限制)
|
|
27
|
-
- [📄 许可](#-许可)
|
|
25
|
+
## 📑 Table of Contents
|
|
28
26
|
|
|
29
|
-
|
|
27
|
+
- [✨ Features](#-features)
|
|
28
|
+
- [🚀 Installation](#-installation)
|
|
29
|
+
- [⌨️ Usage](#-usage)
|
|
30
|
+
- [⚙️ Settings](#-settings)
|
|
31
|
+
- [🔌 HTTP API](#-http-api)
|
|
32
|
+
- [🧩 How it works](#-how-it-works)
|
|
33
|
+
- [🛠️ Development](#-development)
|
|
34
|
+
- [🔐 Security and cost](#-security-and-cost)
|
|
35
|
+
- [⚠️ Known limitations](#-known-limitations)
|
|
36
|
+
- [📄 License](#-license)
|
|
30
37
|
|
|
31
|
-
|
|
32
|
-
- **三种交互**:`Tab` 采纳 · `Esc` 忽略 · 开始输入自动消失;采纳前建议不属于会话内容
|
|
33
|
-
- **轻量上下文**:只取最近若干条 user/assistant 的纯文本,工具结果、附件、系统提示一律不进辅助调用
|
|
34
|
-
- **默认跟随当前会话模型**:不写死任何提供商,联想调用沿用会话自身选用的模型;也可以在设置页固定到某个更便宜的模型
|
|
35
|
-
- **全部可调**:开关、提供商 / 模型、响应超时、上下文规模、思考深度,保存后立即生效,无需重启 DSH
|
|
36
|
-
- **零运行时依赖**:纯 ESM,Host 端与客户端都不引入第三方包
|
|
38
|
+
## ✨ Features
|
|
37
39
|
|
|
38
|
-
|
|
40
|
+
- **A suggestion the moment a reply ends** — gray ghost text rendered at the composer's first character, matching the editor's caret position, font size and line height
|
|
41
|
+
- **Four interactions** — `Tab` to accept, `Alt+→` to accept piece by piece, `↻` for a different suggestion, `Esc` to dismiss; typing hides it, and clearing the draft brings it back
|
|
42
|
+
- **Lightweight context** — only the most recent user/assistant *text*; tool results, attachments and system prompts never leave your machine
|
|
43
|
+
- **Follows the current session model by default** — nothing is hard-coded to a provider, the prediction call reuses whatever model the session itself uses; you can also pin a cheaper model
|
|
44
|
+
- **No repeats, no dead ends** — a repeat of the previous suggestion triggers an automatic "give me a different one"; a reasoning level the real model doesn't support falls back automatically, so you never hit "settings look fine but no suggestion ever appears"
|
|
45
|
+
- **Everything is adjustable** — on/off, provider / model, response timeout, context size and budget, output cap, reasoning effort; changes apply immediately, no DSH restart
|
|
46
|
+
- **The UI follows your language** — switch Settings → Language to 中文 and the whole plugin UI changes at once, including the ghost hint above the composer **and the validation errors inside Settings** (those are produced by the host, which answers in the language the client sends); no reload needed, and it falls back to Chinese when no locale service is present
|
|
47
|
+
- **Zero runtime dependencies** — plain ESM on both the host and client side
|
|
39
48
|
|
|
40
|
-
|
|
49
|
+
## 🚀 Installation
|
|
50
|
+
|
|
51
|
+
The plugin is published on npm. Options are ordered by convenience.
|
|
52
|
+
|
|
53
|
+
### Install inside DSH (recommended)
|
|
54
|
+
|
|
55
|
+
**GUI**: open the plugins page → **Add plugin** → enter the package name `dsh-prompt-predict` → install.
|
|
56
|
+
|
|
57
|
+
**Or the dsh CLI**:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
dsh plugin --profile desktop add dsh-prompt-predict
|
|
61
|
+
```
|
|
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**.
|
|
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).
|
|
66
|
+
|
|
67
|
+
### Install from source
|
|
41
68
|
|
|
42
69
|
```bash
|
|
43
70
|
git clone https://github.com/ferrisching/dsh-prompt-predict.git
|
|
@@ -45,126 +72,145 @@ cd dsh-prompt-predict
|
|
|
45
72
|
bash scripts/install.sh
|
|
46
73
|
```
|
|
47
74
|
|
|
48
|
-
|
|
75
|
+
The script packs this repo on the fly, installs it into the profile's `node_modules`, and adds `dsh-prompt-predict` to `dsh.profile.bundles`. The default target is `~/.dsh/profiles/desktop`; for another profile:
|
|
49
76
|
|
|
50
77
|
```bash
|
|
51
78
|
bash scripts/install.sh ~/.dsh/profiles/web
|
|
52
79
|
```
|
|
53
80
|
|
|
54
|
-
|
|
81
|
+
**Restart DSH afterwards**, then look under **Settings → Prompt Suggestions**.
|
|
55
82
|
|
|
56
|
-
###
|
|
83
|
+
### Manual install
|
|
57
84
|
|
|
58
85
|
```bash
|
|
59
86
|
cd ~/.dsh/profiles/desktop
|
|
87
|
+
pnpm add dsh-prompt-predict # from npm
|
|
88
|
+
# or link local source (symlink — handy while developing):
|
|
60
89
|
pnpm add /path/to/dsh-prompt-predict
|
|
61
90
|
```
|
|
62
91
|
|
|
63
|
-
|
|
92
|
+
Then open that profile's `package.json` and add `"dsh-prompt-predict"` to the `dsh.profile.bundles` array, and restart DSH.
|
|
64
93
|
|
|
65
|
-
|
|
94
|
+
### Requirements
|
|
66
95
|
|
|
67
|
-
|
|
96
|
+
- Verified on **DSH `0.2.0-rc.2`** (desktop)
|
|
97
|
+
- `node` / `pnpm`: the install script prefers DSH's own runtime under `~/.dsh/dsh-runtimes/*/dependencies` and only falls back to `PATH`
|
|
98
|
+
- macOS / Linux; Windows untested
|
|
68
99
|
|
|
69
|
-
|
|
70
|
-
- `node` / `pnpm`:安装脚本优先使用 `~/.dsh/dsh-runtimes/*/dependencies` 下 DSH 自带的运行时,找不到才回退 `PATH`
|
|
71
|
-
- macOS / Linux;Windows 未验证
|
|
100
|
+
## ⌨️ Usage
|
|
72
101
|
|
|
73
|
-
|
|
102
|
+
1. Chat normally, wait for the assistant to finish its turn, and leave the **composer empty**
|
|
103
|
+
2. About 350 ms later a gray suggestion appears, with `Tab` / `↻` / `Esc` on its right
|
|
104
|
+
3. Pick what you need:
|
|
74
105
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
106
|
+
| Action | Effect |
|
|
107
|
+
|---|---|
|
|
108
|
+
| `Tab` | Accept the whole thing (only now is it inserted, and it stays undoable) |
|
|
109
|
+
| `Alt+→` | **Accept piece by piece** — a couple of characters at a time in CJK, one word in Latin; the rest keeps floating, stop whenever you like |
|
|
110
|
+
| `↻` (button on the right) | **Reroll** — ask the model for a different suggestion |
|
|
111
|
+
| `Esc` | Dismiss this one |
|
|
112
|
+
| Just start typing | It disappears; **clearing the draft brings it back** (only `Esc` is a permanent dismissal) |
|
|
78
113
|
|
|
79
|
-
|
|
114
|
+
Suggestions only appear when the composer is empty and the session isn't running. Switching sessions or interrupting a reply clears any pending suggestion.
|
|
80
115
|
|
|
81
|
-
## ⚙️
|
|
116
|
+
## ⚙️ Settings
|
|
82
117
|
|
|
83
|
-
|
|
118
|
+
**Settings → Prompt Suggestions**:
|
|
84
119
|
|
|
85
|
-
|
|
|
120
|
+
| Setting | Description | Default |
|
|
86
121
|
|---|---|---|
|
|
87
|
-
|
|
|
88
|
-
|
|
|
89
|
-
|
|
|
90
|
-
|
|
|
91
|
-
|
|
|
122
|
+
| Enable predictions | Master switch | On |
|
|
123
|
+
| Provider / model | Model used for the prediction call; pick "Follow current session model" to reuse the session's own model | Follow current session model |
|
|
124
|
+
| Response timeout (advanced) | 1–60 seconds | 12 seconds |
|
|
125
|
+
| Context size (advanced) | Small 3 / Standard 8 / Large 12 messages | Standard 8 |
|
|
126
|
+
| Context budget (advanced) | Character cap sent to the helper call, 1000–20000 | 6000 |
|
|
127
|
+
| Output cap (advanced) | Token cap per suggestion, 16–512 | 64 |
|
|
128
|
+
| Reasoning effort (advanced) | Options are **generated from the model actually in use** (the session's model when following it); unsupported levels never appear | Off (fastest, cheapest) |
|
|
92
129
|
|
|
93
|
-
-
|
|
94
|
-
- 设置落盘在 `~/.dsh/dsh-prompt-predict/config.json`(权限 600)
|
|
95
|
-
- 优先级:**用户保存的设置 > cordis patch 部署默认 > 内置默认**
|
|
130
|
+
The bottom of the settings page shows a **last prediction** line: time, model, latency, whether the reasoning level was auto-downgraded or a reroll happened, and the reason when it failed — no more guessing why nothing appeared.
|
|
96
131
|
|
|
97
|
-
|
|
132
|
+
- Changes take effect **immediately** — no DSH restart
|
|
133
|
+
- Settings are stored at `~/.dsh/dsh-prompt-predict/config.json` (mode 600)
|
|
134
|
+
- Precedence: **user-saved settings > cordis patch deploy defaults > built-in defaults**
|
|
98
135
|
|
|
99
|
-
|
|
136
|
+
## 🔌 HTTP API
|
|
100
137
|
|
|
101
|
-
|
|
138
|
+
The plugin registers a same-origin prefix route `/dsh-prompt-predict` on DSH's web server; both the settings page and the composer suggestion go through it. Every endpoint is authenticated with DSH's browser cookie (`connection.requestRejection`) — off-machine callers get 401/403.
|
|
139
|
+
|
|
140
|
+
| Method | Path | Description |
|
|
102
141
|
|---|---|---|
|
|
103
|
-
| GET | `/dsh-prompt-predict/status` |
|
|
104
|
-
| GET | `/dsh-prompt-predict/catalog` |
|
|
105
|
-
| GET | `/dsh-prompt-predict/efforts?provider=&model=` |
|
|
106
|
-
| POST | `/dsh-prompt-predict/settings` |
|
|
107
|
-
| POST | `/dsh-prompt-predict/suggest` | `{ sessionId }` →
|
|
142
|
+
| GET | `/dsh-prompt-predict/status` | Current session model, effective settings, saved overrides, deploy defaults |
|
|
143
|
+
| GET | `/dsh-prompt-predict/catalog` | All providers and models (for the dropdowns) |
|
|
144
|
+
| GET | `/dsh-prompt-predict/efforts?provider=&model=` | The reasoning levels that model actually supports |
|
|
145
|
+
| POST | `/dsh-prompt-predict/settings` | Save settings; `{ "reset": true }` restores defaults |
|
|
146
|
+
| POST | `/dsh-prompt-predict/suggest` | `{ sessionId }` → one suggestion |
|
|
147
|
+
|
|
148
|
+
Every endpoint accepts an optional **`x-dsh-locale`** header (`zh` / `en`, default Chinese) deciding which language validation errors and prediction failures come back in. The client sends the active UI language automatically.
|
|
108
149
|
|
|
109
|
-
## 🧩
|
|
150
|
+
## 🧩 How it works
|
|
110
151
|
|
|
111
|
-
**Host
|
|
152
|
+
**Host side** (`lib/`)
|
|
112
153
|
|
|
113
|
-
1. `lib/index.js`
|
|
114
|
-
2.
|
|
115
|
-
3.
|
|
116
|
-
4.
|
|
154
|
+
1. `lib/index.js` is the plugin entry point and registers the same-origin HTTP route
|
|
155
|
+
2. On `suggest`, `lib/predict.mjs` trims the session down to the most recent user/assistant plain text — walking backwards under both a message-count limit and a character budget
|
|
156
|
+
3. That trimmed history is **framed as a single request-only user input** before it reaches the helper model: DSH assistant messages must carry a full `stream` / `replayState`, so a trimmed fragment cannot masquerade as one (same approach session-title uses)
|
|
157
|
+
4. The streamed reply is normalized (code fences, `Suggestion:` prefixes and wrapping quotes stripped, newlines collapsed) and returned to the client
|
|
117
158
|
|
|
118
|
-
|
|
159
|
+
For model selection, `provider` / `model` set to `auto` means "follow the session": no route is hard-coded onto the helper call, and `predictNextPrompt` inherits whatever the session itself selected.
|
|
119
160
|
|
|
120
|
-
|
|
161
|
+
**Client side** (`client/`)
|
|
121
162
|
|
|
122
|
-
-
|
|
123
|
-
- ghost text
|
|
163
|
+
- Injects into the `conversation.composer.dock` (lifecycle mount point next to the composer) and `settings.section` slots
|
|
164
|
+
- The ghost text is an **overlay** — it is never written into the Lexical editor; only accepting goes through `inputActions.insertText`
|
|
124
165
|
|
|
125
|
-
## 🛠️
|
|
166
|
+
## 🛠️ Development
|
|
126
167
|
|
|
127
168
|
```bash
|
|
128
169
|
git clone https://github.com/ferrisching/dsh-prompt-predict.git
|
|
129
170
|
cd dsh-prompt-predict
|
|
130
|
-
|
|
171
|
+
npm test # 66 cases: 51 host-side + 15 client render smoke tests
|
|
131
172
|
```
|
|
132
173
|
|
|
133
174
|
```
|
|
134
175
|
.
|
|
135
|
-
├── lib/ Host
|
|
136
|
-
│ ├── index.js
|
|
137
|
-
│ ├── host-route.mjs
|
|
138
|
-
│ ├── predict.mjs
|
|
139
|
-
│
|
|
176
|
+
├── lib/ Host side (plain ESM, no build step)
|
|
177
|
+
│ ├── index.js Plugin entry point, registers the HTTP route
|
|
178
|
+
│ ├── host-route.mjs Same-origin API: status / catalog / efforts / settings / suggest
|
|
179
|
+
│ ├── predict.mjs Session trimming, helper-model call, suggestion normalization
|
|
180
|
+
│ ├── messages.mjs User-facing host copy (Chinese + English)
|
|
181
|
+
│ └── config.mjs User settings persistence
|
|
140
182
|
├── client/
|
|
141
|
-
│ └── client.js
|
|
183
|
+
│ └── client.js Client: composer ghost-text overlay + settings page
|
|
142
184
|
├── test/
|
|
143
|
-
│
|
|
185
|
+
│ ├── predict.mjs 51 cases: trimming, cleanup, route inheritance, settings validation, degrade-retry, dedup, bilingual errors, HTTP end-to-end
|
|
186
|
+
│ └── client-render.mjs 15 cases: renders the ghost overlay and settings page through a tiny React stand-in, incl. both locales and dictionary self-checks
|
|
144
187
|
├── scripts/
|
|
145
|
-
│ └── install.sh
|
|
146
|
-
├── cordis.patch.yml
|
|
188
|
+
│ └── install.sh One-shot install / upgrade
|
|
189
|
+
├── cordis.patch.yml Plugin mount patch
|
|
147
190
|
└── package.json
|
|
148
191
|
```
|
|
149
192
|
|
|
150
|
-
|
|
193
|
+
> `test/client-render.mjs` is the only automated safety net for the client side: no browser needed — a tiny React stand-in expands the components into a plain object tree so the test can assert that the ghost shows up and that `Tab` / `↻` / `Esc` are all there. It exists because of a real incident: the overlay referenced a variable it never read from props, the render threw, React's error boundary swallowed it, and the symptom was "the API returns a suggestion but nothing ever appears" — while every host-side test was green.
|
|
151
194
|
|
|
152
|
-
|
|
195
|
+
The tests need no DSH runtime: a fake ctx plus a local HTTP server cover route registration, settings validation, route inheritance and end-to-end calls.
|
|
153
196
|
|
|
154
|
-
|
|
155
|
-
- 建议**不写入会话日志**;只有按 `Tab` 采纳并发送后才成为正式消息
|
|
156
|
-
- 只发送裁剪后的 user/assistant 纯文本,工具结果、附件、系统提示都不出本机
|
|
157
|
-
- 设置页与联想接口均走 DSH 自身的浏览器 Cookie 认证
|
|
197
|
+
## 🔐 Security and cost
|
|
158
198
|
|
|
159
|
-
|
|
199
|
+
- **One** small helper call per assistant turn by default (`maxTokens: 64`); an extra attempt only happens when the reasoning level needs downgrading or a suggestion needs rerolling — **three calls is the hard ceiling**, and they share a single timeout budget
|
|
200
|
+
- Suggestions are **not written to the session log**; only after you accept with `Tab` and send does the text become a real message
|
|
201
|
+
- Only trimmed user/assistant plain text is sent — tool results, attachments and system prompts never leave the machine
|
|
202
|
+
- Both the settings page and the suggestion endpoint sit behind DSH's own browser-cookie authentication
|
|
160
203
|
|
|
161
|
-
|
|
162
|
-
- 依赖宿主的 `conversation.composer.dock` 与 `settings.section` 两个 slot 名称,DSH 大版本调整后可能需要适配
|
|
163
|
-
- **尚未发布到 npm 官方源**,因此暂时无法通过 DSH 的「添加插件」向导安装,只能用上面的源码安装方式
|
|
164
|
-
- 联想会消耗所选模型的额度;固定到快速小模型比跟随推理模型更省
|
|
204
|
+
## ⚠️ Known limitations
|
|
165
205
|
|
|
166
|
-
|
|
206
|
+
- Verified only on DSH `0.2.0-rc.2`; other versions untested
|
|
207
|
+
- Depends on the host's `conversation.composer.dock` and `settings.section` slot names — a major DSH update may require adapting
|
|
208
|
+
- Predictions consume quota on the selected model; pinning a fast small model is cheaper than following a reasoning model
|
|
209
|
+
|
|
210
|
+
## 📄 License
|
|
167
211
|
|
|
168
212
|
[MIT](LICENSE) © ferrisching
|
|
169
213
|
|
|
170
|
-
|
|
214
|
+
Free to use, modify and distribute, including in closed-source commercial projects — just keep the copyright notice and license text.
|
|
215
|
+
|
|
216
|
+
See [CHANGELOG.md](./CHANGELOG.md) for the change history ([中文](./CHANGELOG.zh.md)).
|