dsh-prompt-enhance 0.2.4 → 0.2.6
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 +4 -3
- package/README.zh-CN.md +4 -3
- package/docs/code-review-2026-09.md +49 -0
- package/docs/release-0.2.3.md +47 -0
- package/docs/release-0.2.4.md +20 -0
- package/docs/release-0.2.6.md +33 -0
- package/package.json +2 -3
package/README.md
CHANGED
|
@@ -52,14 +52,15 @@ The plugin is one npm package with two halves, following the dsh plugin conventi
|
|
|
52
52
|
|
|
53
53
|
## Requirements
|
|
54
54
|
|
|
55
|
-
- `dsh >= 0.1.1-rc.2`
|
|
56
|
-
- Boot-verified on `0.1.1-rc.2`, `0.1.2-alpha.3`,
|
|
55
|
+
- `dsh >= 0.1.1-rc.2 < 0.3.0` — the range states what has actually been exercised, not an open-ended promise.
|
|
56
|
+
- Boot-verified on `0.1.1-rc.2`, `0.1.2-alpha.3`, `0.1.7-rc.2`, and `0.2.0-rc.2` (layer mounts, enhance route answers, client bundle builds; on alpha the plugin takes the newer `ctx.settings.installSection` registration path, and on `0.2.0-rc.2` it also passes the runtime's plugin-compatibility gate). The `0.2.0-rc.2` checks include the **dsh desktop application** — the environment this plugin is normally used in. On a `0.2.x` runtime expect some *other* plugins to disappear from the UI: the gate skips any bundle whose `peerDependencies` pin an older `@deepseek-ai/dsh-*` range (observed: `dshmarket`, `dsh-find-plugin`, `dsh-better-sidebar`). The harness has broken two APIs the plugin touches: `@deepseek-ai/dsh-settings` changed its registration entry between the two early lines, and from `0.1.5-rc.3` the settings service became `SettingsForms` (no synchronous `get`) while `dsh-agent-default-model` moved the harness default model behind its own `ctx.agentDefaultModel.currentSelection()` service. The plugin probes all three shapes at runtime and adapts, no configuration needed.
|
|
57
|
+
- The ceiling covers the whole `0.2.x` line (including its prereleases); a `0.3.x` is untested and therefore outside the range. `dsh.engines` is advisory metadata read by the loader and plugin manager — it states support, it does not enforce it.
|
|
57
58
|
- Node `^22.19.0 || >=24.0.0` (for building from source)
|
|
58
59
|
- Browser peers `react` / `react-dom` (`^18.2.0`) come from the web shell's module registry. The host-half module `@deepseek-ai/dsh-llm` is a **runtime module supplied by the dsh host and is not installed from npm** (the `lib/` bundles keep every package import external), so it is declared as an *optional* peer: an install that does not provide it produces no warning, and the plugin reports a normal error at enhance time rather than failing to load.
|
|
59
60
|
|
|
60
61
|
| | |
|
|
61
62
|
|---|---|
|
|
62
|
-
| dsh | `>= 0.1.1-rc.2` |
|
|
63
|
+
| dsh | `>= 0.1.1-rc.2 < 0.3.0` |
|
|
63
64
|
| Node | `^22.19.0 \|\| >=24.0.0` |
|
|
64
65
|
| Plugin | `0.2.x` |
|
|
65
66
|
|
package/README.zh-CN.md
CHANGED
|
@@ -52,14 +52,15 @@ flowchart LR
|
|
|
52
52
|
|
|
53
53
|
## 环境要求
|
|
54
54
|
|
|
55
|
-
- `dsh >= 0.1.1-rc.2`
|
|
56
|
-
- 实测环境:`0.1.1-rc.2`、`0.1.2-alpha.3`、`0.1.7-rc.2` 均已 boot 验证(插件层挂载、增强路由应答、客户端 bundle 构建通过;alpha 上走新版 `ctx.settings.installSection`
|
|
55
|
+
- `dsh >= 0.1.1-rc.2 < 0.3.0` —— 这个区间表示**实际验证过的范围**,而不是无限期的承诺。
|
|
56
|
+
- 实测环境:`0.1.1-rc.2`、`0.1.2-alpha.3`、`0.1.7-rc.2`、`0.2.0-rc.2` 均已 boot 验证(插件层挂载、增强路由应答、客户端 bundle 构建通过;alpha 上走新版 `ctx.settings.installSection` 注册路径,`0.2.0-rc.2` 上还通过了运行时的插件兼容性闸门)。其中 `0.2.0-rc.2` 的验证包含 **dsh 桌面应用**——也就是本插件日常实际运行的环境。在 `0.2.x` 运行时上,可能会发现**别的**插件从界面消失:凡 `peerDependencies` 把 `@deepseek-ai/dsh-*` 锁在旧区间的 bundle 都会被闸门跳过(实测被跳过的是 `dshmarket`、`dsh-find-plugin`、`dsh-better-sidebar`)。宿主在插件用到的两处 API 上做过破坏性变更:`@deepseek-ai/dsh-settings` 的注册入口在两条早期版本线之间变了;`0.1.5-rc.3` 起 settings 服务改为 `SettingsForms`(不再有同步 `get`),同时 `dsh-agent-default-model` 把全局默认模型收进了自己的 `ctx.agentDefaultModel.currentSelection()` 服务。插件对三种形态均做运行时探测并自动适配,无需配置。
|
|
57
|
+
- 上界覆盖整条 `0.2.x` 线(含其预发布版本);`0.3.x` 尚未验证,因此不在区间内。`dsh.engines` 是加载器与插件管理器读取的**声明性元数据**——它表达支持范围,并不强制拦截。
|
|
57
58
|
- Node `^22.19.0 || >=24.0.0`(仅从源码构建时需要)
|
|
58
59
|
- 浏览器侧 peer `react` / `react-dom`(`^18.2.0`)由 Web 壳的模块注册表提供。宿主半区用到的 `@deepseek-ai/dsh-llm` 是**由 dsh 宿主提供的运行时模块,不从 npm 安装**(`lib/` 产物把包引用全部保持为外部),因此声明为**可选** peer:未提供它的环境不会出现安装警告,增强时按正常错误路径报错,而不是加载失败。
|
|
59
60
|
|
|
60
61
|
| | |
|
|
61
62
|
|---|---|
|
|
62
|
-
| dsh | `>= 0.1.1-rc.2` |
|
|
63
|
+
| dsh | `>= 0.1.1-rc.2 < 0.3.0` |
|
|
63
64
|
| Node | `^22.19.0 \|\| >=24.0.0` |
|
|
64
65
|
| 插件 | `0.2.x` |
|
|
65
66
|
|
|
@@ -160,3 +160,52 @@ src/
|
|
|
160
160
|
## 六、安装形态提醒
|
|
161
161
|
|
|
162
162
|
当前 profile 通过 `link:` 指向本仓库,**宿主半改动必须重启 `dsh web`**;且 profile 的 `package.json` 里若残留 `^0.2.x` 语义版本声明,任何一次 `npm install` 都可能把 `link:` 覆盖回 npm 上的版本,从而静默丢掉本地修复。
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## 七、发布记录(本次交付闭环)
|
|
167
|
+
|
|
168
|
+
审阅修复经多轮提交交付,并已发布到 npm 与 GitHub。
|
|
169
|
+
|
|
170
|
+
### 版本演进
|
|
171
|
+
|
|
172
|
+
| 版本 | 内容 | 状态 |
|
|
173
|
+
|---|---|---|
|
|
174
|
+
| `0.2.1` / `0.2.2` | 审阅前已发布(**不含本次任何修复**) | 已被 0.2.4 取代 |
|
|
175
|
+
| `0.2.3` | 四个缺陷修复(locale 映射、SSE 未结束、启动崩溃、渲染崩溃)+ 打包面补全 | 已发布,GitHub **Latest** |
|
|
176
|
+
| `0.2.4` | 仅打包修正:`@deepseek-ai/dsh-llm` 改为可满足范围的 optional peer | 已发布,npm **latest** / GitHub **Pre-release** |
|
|
177
|
+
|
|
178
|
+
### commit 批次
|
|
179
|
+
|
|
180
|
+
| 顺序 | 主题 |
|
|
181
|
+
|---|---|
|
|
182
|
+
| 1 | `fix: locale reason mapping, package peer surface, SSE backpressure` |
|
|
183
|
+
| 2 | `fix: end the SSE response so the streamed route terminates` |
|
|
184
|
+
| 3 | `fix(client): never hard-require optional services so boot cannot fail` |
|
|
185
|
+
| 4 | `fix(client): tolerate host input states without imageIds/occurrences` |
|
|
186
|
+
| 5 | `docs: finalize code review report` |
|
|
187
|
+
| 6 | `docs: add 0.2.3 changelog entry`,随后 `npm version patch` 产出 0.2.3 的版本提交与 `v0.2.3` 标签 |
|
|
188
|
+
| 7 | `fix: make the dsh-llm peer optional and satisfiable`,随后 `npm version patch` 产出 0.2.4 的版本提交与 `v0.2.4` 标签 |
|
|
189
|
+
| 8 | `docs: add release notes for 0.2.3 and 0.2.4` |
|
|
190
|
+
|
|
191
|
+
精确 hash 以 `git log --oneline` 为准;此处刻意不写 hash,避免记录随 rebase/amend 失真。
|
|
192
|
+
|
|
193
|
+
### 发布验证
|
|
194
|
+
|
|
195
|
+
| 检查 | 结果 |
|
|
196
|
+
|---|---|
|
|
197
|
+
| `npm view dsh-prompt-enhance dist-tags --json` | `latest` = **`0.2.4`** |
|
|
198
|
+
| `gh release list` | `v0.2.3` = **Latest**;`v0.2.4` = **Pre-release** |
|
|
199
|
+
| GitHub 远端 | `main` 已推送(以 `git log origin/main -1` 为准) |
|
|
200
|
+
| `npm pack` | 37 个文件(0.2.3/0.2.4 发布时),含 `lib/`、`cordis.patch.yml`、两份 README、`docs/`、`src/` |
|
|
201
|
+
| `prepublishOnly` 闸门 | `npm run build && npm test` 各执行一次,207 用例通过后才上传 |
|
|
202
|
+
|
|
203
|
+
### 过程中的两个教训
|
|
204
|
+
|
|
205
|
+
1. **npm 版本号不可覆盖。** 首次 `npm publish` 因「已发布 0.2.2」被拒——这不是权限问题(`npm whoami` 全程为 `rongxingda`),而是 npm 的版本号一次性语义。正确反应是升版本号(`npm version patch`),而非排查权限。任何"改完直接重发同号"的期望都不成立。
|
|
206
|
+
2. **`npm view` 的即时读数是旧快照。** 发布成功后立刻查 `dist-tags` 仍返回 0.2.2,属于 registry 复制延迟;判断发布是否成功应以 `npm publish` 自身的 `+ <pkg>@<version>` 输出为准,稍后再查 dist-tags 复核。
|
|
207
|
+
|
|
208
|
+
### 已知遗留(未处理,供后续决策)
|
|
209
|
+
|
|
210
|
+
- `v0.2.0`–`v0.2.2` **有标签但无 GitHub Release 页**;CHANGELOG 的口径已相应限定为「自 0.2.3 起」,因此文档与实际一致,无需补建。
|
|
211
|
+
- `files` 含 `"docs"`,因此 Release 正文等文档会随后续版本进入 npm 包(每个约几 KB,不影响功能)。
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
## Two boot/render failures, two silent bugs
|
|
2
|
+
|
|
3
|
+
This release fixes two defects that made the plugin unusable rather than merely imperfect, plus two long-standing bugs that only showed up once it ran against a real `dsh web` host.
|
|
4
|
+
|
|
5
|
+
### If the web GUI went blank
|
|
6
|
+
|
|
7
|
+
The browser half declared `settingsScope` in the plugin's exported `inject`. Cordis loads a plugin **only while every service named there is available**, and that service belongs to the optional settings surface (`@deepseek-ai/dsh-client-ui-settings`) — which a minimal profile need not bundle. The entry therefore sat `pending` forever and the shell reported:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
web boot: 1 entry did not activate
|
|
11
|
+
dsh-prompt-enhance: pending (waiting for service: settingsScope)
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
The browser half now hard-requires **nothing**: `slots`, `locale`, and `settingsScope` all ride optional `ctx.inject`, and `apply()` itself touches no service. Degradation is graceful — a profile with no settings surface keeps the bundled default mirror (shortcut `ctrl+alt+e`, 12000-character cap, streaming on), and one with no locale service renders dictionary keys.
|
|
15
|
+
|
|
16
|
+
### If the composer lost the enhance button
|
|
17
|
+
|
|
18
|
+
`EnhanceButton` read `state.imageIds.length` and `state.occurrences.length` directly. Those fields are part of the input snapshot in the dsh lines the plugin was written against, but a slot host is not obliged to expose them, and reading `.length` off a missing field throws **during render** — which React answers by unmounting the whole slot entry behind its error boundary:
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
slot entry crashed in 'conversation.input.right': TypeError: Cannot read properties of undefined (reading 'length')
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Both counts, plus `draft` / `phase`, are now read defensively. An absent field only disables the corresponding *advisory* guard (images-only, reference chips); the enhancement itself always runs.
|
|
25
|
+
|
|
26
|
+
### Specific upstream fix hints never appeared
|
|
27
|
+
|
|
28
|
+
The host sends `reason` in kebab-case (`invalid-credential`, `rate-limit`, `context-window`, `tool-call`, `max-tokens`) while the dictionaries key those hints in camelCase (`error.upstream.invalidCredential`, …). Building the key as `` `error.upstream.${reason}` `` matched only the three single-word reasons (`auth`, `quota`, `empty`) and silently fell back to the generic line for the other five — the specific copy was shipped but unreachable. `UPSTREAM_ERROR_KEYS` is now an explicit, literal-typed table, covered by a key-set test and a per-reason render test on the real panel.
|
|
29
|
+
|
|
30
|
+
### The streamed route never ended its response
|
|
31
|
+
|
|
32
|
+
`/prompt-enhance/enhance-stream` wrote its `done` frame but never called `res.end()`, so the chunked body lacked its `0\r\n\r\n` terminator and the connection stayed half-open. A browser client survived only because it returns on the `done` frame and cancels its reader — but any whole-body consumer (`response.text()`, curl, a reverse proxy, a logging middleware) waited **forever**, and keep-alive could never reuse the socket. The route now ends the response after the final frame, guarded against a client that vanished mid-stream.
|
|
33
|
+
|
|
34
|
+
### Also in this release
|
|
35
|
+
|
|
36
|
+
- New SSE frame writer with real socket backpressure (`src/sse.ts`): a slow reader parks frames instead of letting the socket buffer grow without bound.
|
|
37
|
+
- The conversation-context budget uses the same Unicode code-point gauge as the input cap, and truncates without splitting surrogate pairs.
|
|
38
|
+
- `resolveConfig` normalizes a blank `provider` / `model` pair to `undefined` instead of a surviving `''` that downstream read as "an override exists".
|
|
39
|
+
- The cross-session busy state uses `aria-disabled` with a readable reason, so the cause is reachable by keyboard and screen-reader users instead of a silently disabled button.
|
|
40
|
+
- `ResultPanel`'s focus restore no longer hands focus straight back out under React StrictMode (which had neutered the Tab trap and the Escape handler).
|
|
41
|
+
- `peerDependencies` now includes `react-dom`; `files` includes the `docs/` screenshot the READMEs reference; CI runs the Node floor (`22.19`).
|
|
42
|
+
|
|
43
|
+
### Verification
|
|
44
|
+
|
|
45
|
+
- `npm run typecheck`, `npm run build` clean.
|
|
46
|
+
- **207 tests across 20 files** — new coverage for locale key-set integrity, per-reason error copy, 10 SSE writer units, SSE route end-to-end (reads the body to completion, which is what catches the missing terminator), boot under a service-less host, and render under a host input state without `imageIds` / `occurrences`.
|
|
47
|
+
- Exercised against a live `dsh web` profile: the layer mounts, the composer button renders, and the enhance flow (stream → preview → fill back → undo) works.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
## Packaging-only follow-up to 0.2.3
|
|
2
|
+
|
|
3
|
+
No runtime behavior changes. **0.2.3 is the functional release** — see its notes for the four defect fixes; use 0.2.4 if you want the clean install.
|
|
4
|
+
|
|
5
|
+
### What changed
|
|
6
|
+
|
|
7
|
+
`0.2.3` declared `@deepseek-ai/dsh-llm` as a peer with the range `^0.1.1-rc.2`. No published version can satisfy that — the registry serves `0.0.1-rc.1`, one minor below the range — so every install produced a peer warning that could not be resolved, and npm could offer to pull a version whose API does not match this plugin.
|
|
8
|
+
|
|
9
|
+
That module is in fact a **runtime module supplied by the dsh host**: both `lib/` bundles keep every package import external, and the plugin loader satisfies it in-process. It is not installable from npm by design.
|
|
10
|
+
|
|
11
|
+
- The range is now the honest floor: **`>=0.1.1-rc.2`**, matching the `dsh.engines.dsh` floor.
|
|
12
|
+
- The entry is marked **`optional`** in `peerDependenciesMeta`, so a host that does not provide it produces no warning; the plugin reports a normal error at enhance time rather than failing to load.
|
|
13
|
+
- The `react` / `react-dom` peers stay **required** — the web shell's module registry provides them and they really are needed.
|
|
14
|
+
- Both READMEs' *Requirements* sections now state where the module comes from.
|
|
15
|
+
|
|
16
|
+
### Verification
|
|
17
|
+
|
|
18
|
+
- `npm run typecheck`, `npm run build` clean.
|
|
19
|
+
- **207 tests across 20 files** pass.
|
|
20
|
+
- `npm pack` contents unchanged apart from `package.json`.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
## Verified on the latest dsh line
|
|
2
|
+
|
|
3
|
+
No runtime behavior changes — this release widens the declared compatibility ceiling, because the versions that were previously outside it have now been checked on real hosts.
|
|
4
|
+
|
|
5
|
+
### What was verified
|
|
6
|
+
|
|
7
|
+
The `0.2.0-rc.2` runtime (the current npm line) had never been exercised when `0.2.5` capped the range at `<0.2.0`. It has now been, on two hosts:
|
|
8
|
+
|
|
9
|
+
| Host | Runtime | Result |
|
|
10
|
+
|---|---|---|
|
|
11
|
+
| dsh **desktop application** (`DeepSeek Harness.exe`, FileVersion `0.2.0-rc.2`) | `0.2.0-rc.2` | loads and enhances |
|
|
12
|
+
| global CLI (`dsh web`) | `0.2.0-rc.2` | loads and enhances |
|
|
13
|
+
|
|
14
|
+
Three independent signals, not just "the UI looked fine":
|
|
15
|
+
|
|
16
|
+
1. **The runtime's plugin-compatibility gate accepts this plugin.** `0.2.0-rc.2` refuses to load bundles whose `peerDependencies` pin an older `@deepseek-ai/dsh-*` range. This plugin is **not** among the refused: the optional `@deepseek-ai/dsh-llm` peer introduced in `0.2.4` (range `>=0.1.1-rc.2`, marked `optional`) satisfies the gate. For comparison, the gate skipped `dshmarket@1.45.0`, `dsh-find-plugin@0.4.0`, and `dsh-better-sidebar@0.15.2` on the same host.
|
|
17
|
+
2. **No `pending (waiting for service: …)` and no `1 entry did not activate`.** The "hard-require nothing" fix from `0.2.3` — every optional service reached through `ctx.inject` — holds on the new runtime as well.
|
|
18
|
+
3. **A real enhancement completed end to end** against the live model: `[prompt-enhance] … in=2 out=64 ctx=0 1928ms ok`.
|
|
19
|
+
|
|
20
|
+
### What changed
|
|
21
|
+
|
|
22
|
+
`dsh.engines.dsh` is now **`>=0.1.1-rc.2 <0.3.0`** (was `>=0.1.1-rc.2 <0.2.0`). The new ceiling covers the whole `0.2.x` line including its prereleases, while still refusing a `0.3.x` that has never been seen.
|
|
23
|
+
|
|
24
|
+
Two notes on reading this field:
|
|
25
|
+
|
|
26
|
+
- `dsh.engines` is **advisory metadata** consumed by the loader and the plugin manager. It states the supported range; it does not enforce anything.
|
|
27
|
+
- If you run a `0.2.x` runtime, expect *other* plugins to disappear from the UI. That is the compatibility gate doing its job, not a fault in this plugin — check your dsh startup output for `skipping profile bundle` lines.
|
|
28
|
+
|
|
29
|
+
### Verification
|
|
30
|
+
|
|
31
|
+
- `npm run typecheck`, `npm run build` clean.
|
|
32
|
+
- **207 tests across 20 files** pass.
|
|
33
|
+
- Boot-verified on `0.1.1-rc.2`, `0.1.2-alpha.3`, `0.1.7-rc.2`, and `0.2.0-rc.2`.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-prompt-enhance",
|
|
3
3
|
"description": "Prompt enhancement for the dsh web GUI: rewrite the composer draft into a well-structured prompt through the harness LLM service, preview the before/after, then fill back, copy, or undo. Original draft is always preserved.",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.6",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
7
7
|
"node": "^22.19.0 || >=24.0.0"
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
},
|
|
21
21
|
"dsh": {
|
|
22
22
|
"engines": {
|
|
23
|
-
"dsh": ">=0.1.1-rc.2"
|
|
23
|
+
"dsh": ">=0.1.1-rc.2 <0.3.0"
|
|
24
24
|
},
|
|
25
25
|
"bundle": {
|
|
26
26
|
"patch": "./cordis.patch.yml"
|
|
@@ -29,7 +29,6 @@
|
|
|
29
29
|
"inject": [
|
|
30
30
|
"@deepseek-ai/dsh-client-locale",
|
|
31
31
|
"@deepseek-ai/dsh-client-ui-conversation",
|
|
32
|
-
"@deepseek-ai/dsh-client-ui-settings",
|
|
33
32
|
"@deepseek-ai/dsh-client-ui-slots",
|
|
34
33
|
"react-dom"
|
|
35
34
|
],
|