dsh-prompt-enhance 0.3.0 → 0.3.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/README.md +2 -2
- package/README.zh-CN.md +2 -2
- package/docs/release-0.3.1.md +50 -0
- package/lib/client.js +40 -20
- package/lib/index.js +73 -52
- package/lib/index.js.map +2 -2
- package/package.json +2 -2
- package/src/client/ResultPanel.tsx +10 -2
- package/src/client/enhance-client.ts +30 -5
- package/src/client/index.tsx +36 -7
- package/src/client/settings-source.ts +14 -7
- package/src/client/ui-state.ts +9 -0
- package/src/config.ts +35 -24
- package/src/enhance-command.ts +13 -8
- package/src/enhance-routes.ts +76 -40
- package/src/http.ts +22 -0
- package/src/index.ts +14 -4
package/README.md
CHANGED
|
@@ -47,14 +47,14 @@ flowchart LR
|
|
|
47
47
|
|
|
48
48
|
The plugin is one npm package with two halves, following the dsh plugin conventions:
|
|
49
49
|
|
|
50
|
-
- **Host half** (`exports "."`, Node): declares the `prompt-enhance` settings schema (schemastery — the
|
|
50
|
+
- **Host half** (`exports "."`, Node): declares the `prompt-enhance` settings schema (schemastery, every field marked `.volatile()` — the host's `describe()` **drops any entry with no volatile field**, so that mark is both what makes the config page appear and the contract for "edits apply to the next request"; the plugin **re-reads it on every request** instead of caching the boot snapshot), registers the `POST /prompt-enhance/enhance` route on the shared webserver (loopback-fenced, body-capped), and the `/enhance` slash command. The model call goes through `ctx.llm.stream` with a normalized output pass — the same auxiliary-call discipline the harness applies to session titles: deadline + caller cancellation rechecked during and after the stream, terminal-finish validation, tool-call rejection.
|
|
51
51
|
- **Browser half** (`exports "./client"`): registers the enhance button into the `conversation.input.right` slot and the undo bar into `conversation.input.dock`, binds a live mirror of the settings namespace, and installs the global shortcut. All copy is localized (zh/en) through the harness locale system.
|
|
52
52
|
|
|
53
53
|
## Requirements
|
|
54
54
|
|
|
55
55
|
- `dsh >= 0.1.1-rc.2 < 0.3.0` — the range states what has actually been exercised, not an open-ended promise.
|
|
56
56
|
- Boot-verified on `0.1.1-rc.2`, `0.1.2-alpha.3`, `0.1.7-rc.2`, `0.2.0-rc.2`, and **`0.2.1-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.1-rc.2` check is a **real-host end-to-end smoke**: with the local build installed into a temporary profile, the enhance route returned a real model result; setting that profile's `maxInputChars` to `300` made a 400-character draft fail with `422 {count: 400, max: 300}`, and after editing the same profile to `20000` — **without restarting** — the identical draft went through, so a settings edit reaches the *next* request instead of staying at the boot-time snapshot. 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 several of the APIs this plugin touches: `@deepseek-ai/dsh-settings` changed its registration entry between the two early lines, from `0.1.5-rc.3` the settings service became `SettingsForms` (no synchronous `get`), and `0.2.x` **deleted the `installSettingsSection` / `settingsNamespace` exports outright**; `dsh-agent-default-model` moved the harness default model behind its own `ctx.agentDefaultModel.currentSelection()` service; and the browser-side settings mirror moved from `ctx.settingsScope` to `ctx.configForms`. The plugin probes every generation 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
|
|
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 enforced**: the host's boot preflight marks a mismatched entry `disabled = true`, and only an explicit `--accept-risk` gets past the throw (`Incompatible plugins may cause crashes or data loss`). A wrong range means the plugin does not load — not that it loads with a warning.
|
|
58
58
|
- Node `^22.19.0 || >=24.0.0` (for building from source)
|
|
59
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.
|
|
60
60
|
|
package/README.zh-CN.md
CHANGED
|
@@ -47,14 +47,14 @@ flowchart LR
|
|
|
47
47
|
|
|
48
48
|
插件是单个 npm 包、双半区结构,完全遵循 dsh 插件规范:
|
|
49
49
|
|
|
50
|
-
- **宿主半区**(`exports "."`,Node):声明 `prompt-enhance` 设置 schema(schemastery
|
|
50
|
+
- **宿主半区**(`exports "."`,Node):声明 `prompt-enhance` 设置 schema(schemastery,每个字段带 `.volatile()`——宿主的 `describe()` 会**跳过没有任何 volatile 字段的条目**,这个标记既是"设置页会出现"的前提,也是"改完下次请求就生效"的契约;插件在**每次请求时**重新读取,而不是缓存启动快照),注册共享 webserver 上的 `POST /prompt-enhance/enhance` 路由(仅回环、限长),以及 `/enhance` 斜杠命令。模型调用走 `ctx.llm.stream` 并做规范化处理——与 harness 对会话标题相同的辅助调用纪律:超时与调用方取消在流过程中和结束后复查、终结 finish 校验、拒绝工具调用。
|
|
51
51
|
- **浏览器半区**(`exports "./client"`):把增强按钮注册进 `conversation.input.right` 插槽、撤销条注册进 `conversation.input.dock` 插槽,绑定设置命名空间的实时镜像,并安装全局快捷键。全部文案经 harness locale 系统提供中英双语。
|
|
52
52
|
|
|
53
53
|
## 环境要求
|
|
54
54
|
|
|
55
55
|
- `dsh >= 0.1.1-rc.2 < 0.3.0` —— 这个区间表示**实际验证过的范围**,而不是无限期的承诺。
|
|
56
56
|
- 实测环境:`0.1.1-rc.2`、`0.1.2-alpha.3`、`0.1.7-rc.2`、`0.2.0-rc.2`、**`0.2.1-rc.2`** 均已 boot 验证(插件层挂载、增强路由应答、客户端 bundle 构建通过;alpha 上走新版 `ctx.settings.installSection` 注册路径,`0.2.0-rc.2` 上还通过了运行时的插件兼容性闸门)。`0.2.1-rc.2` 的验证是**真实宿主的端到端冒烟**:在临时 profile 里装入本地构建后,增强路由对着在线模型返回了真实结果;把该 profile 的 `maxInputChars` 设为 `300` 后,400 字草稿被 `422 {count:400,max:300}` 拒绝,随后**不重启**把它改成 `20000`,同一份草稿立即通过——设置改动确实作用到下一次请求,而不是停在启动时的快照。其中 `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`),而 `0.2.x` 干脆**删掉了 `installSettingsSection` / `settingsNamespace` 导出**;`dsh-agent-default-model` 把全局默认模型收进了自己的 `ctx.agentDefaultModel.currentSelection()` 服务;浏览器侧的设置镜像则从 `ctx.settingsScope` 迁到了 `ctx.configForms`。插件对每一代形态均做运行时探测并自动适配,无需配置。
|
|
57
|
-
- 上界覆盖整条 `0.2.x` 线(含其预发布版本);`0.3.x` 尚未验证,因此不在区间内。`dsh.engines`
|
|
57
|
+
- 上界覆盖整条 `0.2.x` 线(含其预发布版本);`0.3.x` 尚未验证,因此不在区间内。`dsh.engines` **是强制的**:宿主启动预检会把不匹配的条目直接 `disabled = true`,要放行必须显式 `--accept-risk`,否则抛 `Incompatible plugins may cause crashes or data loss`。所以这个区间写错的结果是**插件不加载**,而不是"只提示一下"。
|
|
58
58
|
- Node `^22.19.0 || >=24.0.0`(仅从源码构建时需要)
|
|
59
59
|
- 浏览器侧 peer `react` / `react-dom`(`^18.2.0`)由 Web 壳的模块注册表提供。宿主半区用到的 `@deepseek-ai/dsh-llm` 是**由 dsh 宿主提供的运行时模块,不从 npm 安装**(`lib/` 产物把包引用全部保持为外部),因此声明为**可选** peer:未提供它的环境不会出现安装警告,增强时按正常错误路径报错,而不是加载失败。
|
|
60
60
|
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# 0.3.1 — 设置页真的会出现,失败流真的会关
|
|
2
|
+
|
|
3
|
+
0.3.0 把插件搬到了 `0.2.1-rc.2` 的契约上,但有两条最关键的路径**在真实宿主上从未生效**:设置页不存在,失败流不结束。两条都属于"看着在、其实不在",所以这次每条都配了一个**在旧代码上必然失败**的测试。
|
|
4
|
+
|
|
5
|
+
## 两个致命项
|
|
6
|
+
|
|
7
|
+
| 面 | 0.2.x 的真实行为 | 用户看到什么 | 修法 |
|
|
8
|
+
|---|---|---|---|
|
|
9
|
+
| **设置** | `SettingsForms.describe()` 用内部 `volatileForm()` 过滤每个条目:**没有任何字段带 `meta.volatile` 时整条被丢弃** | 设置页里没有本插件;即使写入也会抛 `Plugin entry "prompt-enhance" has no volatile fields` | 16 个字段全部加 `.volatile()`;schema 库从裸 `schemastery` 换成 `@deepseek-ai/schemastery`(只有它带 `.volatile()` 与配套的位置校验) |
|
|
10
|
+
| **流式失败** | 错误分支写了 `event: error` 帧,**没有 `res.end()`** | 浏览器因为收到帧而正常显示错误;`curl` / `response.text()` / 代理**永久挂起** | 成功与失败共用 `endResponse()` 收尾 |
|
|
11
|
+
|
|
12
|
+
复现与验证(不是推断):
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
宿主 volatileForm(Config) → 修复前: undefined(条目被跳过)
|
|
16
|
+
→ 修复后: present, 16 个字段
|
|
17
|
+
真宿主 dsh web @0.2.1-rc.2 → 插件激活、POST /prompt-enhance/enhance
|
|
18
|
+
返回 deepseek-official / deepseek-flash 的真实结果
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
失败流那条的证伪:把 `endResponse(res)` 注释掉,新用例在 2.07 秒被 abort 判失败——正是"永久挂起"。
|
|
22
|
+
|
|
23
|
+
## 生命周期与失败路径
|
|
24
|
+
|
|
25
|
+
- **路由不随卸载回收**:`webServer.register` 只返回"从表里删项"的函数,disposer 却存在模块级 map 里、无人调用 ⇒ 卸载后路由仍用旧配置与旧限流窗答卷,重载撞 `duplicate prefix route`。改为 `ctx.inject(['webServer'])` + `ctx.effect`,服务按身份跟随、随光纤回收。
|
|
26
|
+
- **`/enhance` 在无 webServer 的组合里整体消失**:`inject` 里硬写了 `['llm','webServer']`。`webServer` 移出硬依赖、改按需注入后,斜杠命令在纯 CLI 组合里依然可用。
|
|
27
|
+
- **`/enhance` 遇配置异常直接抛**:`readConfig()` 在 `try` 之外,provider/model 半填时抛出的是未捕获异常,而不是路由侧那句中英双语提示。已移入 `try`。
|
|
28
|
+
- **流式端点把"服务端拒绝"当成"宿主不支持流式"**:`response.ok === false` 时丢弃整个错误信封并**原样重发一次**——429 反而打两次、结构化原因(`limit`/`retryAfterSeconds`)全丢。现在先按 `ok` 分流:拒绝即报拒绝,只有"200 但不是流"才回退一次性。
|
|
29
|
+
- **面板打开时快捷键打到别的会话**:结果面板 `createPortal` 挂在 `body` 上并接管焦点,上溯循环走到 `body` 时 `body.contains(每个 composer)` 恒真 ⇒ 返回注册表里的第一个会话。现在遇 `body`/`documentElement` 即停,退回"最近挂载的会话"。证伪:去掉这行判断,用例立刻变成"点了另一个会话"。
|
|
30
|
+
- **设置镜像可能永久停在默认值**:`boundId` 在 `forms.get()` **之前**落值,取不到时后续每次 describe tick 都因 `entryId === boundId` 直接返回 ⇒ 永不重试。改为取到 form 之后才认领 id。
|
|
31
|
+
|
|
32
|
+
## 可诊断性与小项
|
|
33
|
+
|
|
34
|
+
- 客户端三处空 `catch` 改为 `console.warn`(模块注释早就承诺 "caught and logged",代码里一行都没有)——"按钮不出现"这类报告唯一的线索来源。
|
|
35
|
+
- 对话框 Tab 焦点陷阱的**反向**漏:面板根节点是刻意 `tabIndex={-1}`,既不是 first 也不是 last,`Shift+Tab` 能直接逃出。已把根节点视为"first 之前"。
|
|
36
|
+
- 关闭插件后不再抢键:此前仍 `preventDefault` 后跑一个空动作,等于静默吃掉用户绑给同一组合的宿主快捷键。
|
|
37
|
+
- `scripts/build.mjs` 列在 `tsconfig.include` 里但 `allowJs` 没开 ⇒ 从未被检查。现在开 `checkJs`,并给 esbuild 选项补 JSDoc(否则 `packages: 'external'` 会退化成 `string`)。
|
|
38
|
+
- README 不再称 `dsh.engines` 为"声明性、不强制":宿主启动预检会直接 `disabled = true`,放行必须显式 `--accept-risk`。
|
|
39
|
+
|
|
40
|
+
## 验证
|
|
41
|
+
|
|
42
|
+
- `npm run typecheck` 干净(`build.mjs` 现在确实在检查范围内,`tsc --listFilesOnly` 命中 1)
|
|
43
|
+
- `npm test` **24 文件 / 242 用例全绿**(0.3.0 为 22 / 231,新增 `client-enhance-client`、`client-shortcut-target` 及配置/路由/镜像若干条)
|
|
44
|
+
- 真实宿主冒烟:临时 profile 装本地包 → 插件激活、无 `pending` / `did not activate` → 增强路由返回真实模型结果 → 临时 profile 与临时目录已删除
|
|
45
|
+
|
|
46
|
+
## 未做(有意)
|
|
47
|
+
|
|
48
|
+
- **快捷键没有迁移到宿主的 `shortcuts` 服务**(`dsh-client-shortcuts` 支持用户改键与冲突消解)。迁移需要先确认该服务的注册契约与冲突语义,属于独立改动,不在这次"失败路径闭包"的范围内。
|
|
49
|
+
- **`Origin` 只比对 hostname、不比对端口**:任意 `localhost:任意端口` 的页面都被信任。收紧需要把服务实际监听的端口传进栅栏,同样属独立改动。
|
|
50
|
+
- 跨代探测的兼容死分支(`installSection`、旧 settings 模块、`webUiSettings`、`settingsScope`)保留:它们在旧版本线上仍是唯一的路径。
|
package/lib/client.js
CHANGED
|
@@ -124,6 +124,16 @@ async function readEnvelope(response) {
|
|
|
124
124
|
}
|
|
125
125
|
throw new EnhanceClientError({ code: "internal", message: `\u5BBF\u4E3B\u670D\u52A1\u8FD4\u56DE\u5F02\u5E38\uFF08HTTP ${response.status}\uFF09\u3002` });
|
|
126
126
|
}
|
|
127
|
+
async function rejectionOf(response) {
|
|
128
|
+
try {
|
|
129
|
+
const parsed = await response.json();
|
|
130
|
+
if (parsed !== null && typeof parsed === "object" && parsed.error !== void 0) {
|
|
131
|
+
return new EnhanceClientError(parseError(parsed.error));
|
|
132
|
+
}
|
|
133
|
+
} catch {
|
|
134
|
+
}
|
|
135
|
+
return new EnhanceClientError({ code: "internal", message: `\u5BBF\u4E3B\u670D\u52A1\u62D2\u7EDD\u4E86\u8BF7\u6C42\uFF08HTTP ${response.status}\uFF09\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002` });
|
|
136
|
+
}
|
|
127
137
|
function takeFrames(buffer) {
|
|
128
138
|
const frames = [];
|
|
129
139
|
let rest = buffer;
|
|
@@ -170,9 +180,9 @@ async function requestEnhanceStream(body, options) {
|
|
|
170
180
|
throw new EnhanceClientError({ code: "internal", message: "\u65E0\u6CD5\u8FDE\u63A5\u5BBF\u4E3B\u670D\u52A1\uFF0C\u8BF7\u786E\u8BA4 dsh web \u6B63\u5728\u8FD0\u884C\u540E\u91CD\u8BD5\u3002" });
|
|
171
181
|
}
|
|
172
182
|
const contentType = String(response.headers.get("content-type") ?? "").toLowerCase();
|
|
183
|
+
if (!response.ok) throw await rejectionOf(response);
|
|
173
184
|
const stream = response.body;
|
|
174
|
-
|
|
175
|
-
if (stream === null || stream === void 0 || !streamable) {
|
|
185
|
+
if (stream === null || stream === void 0 || !contentType.includes("event-stream")) {
|
|
176
186
|
void Promise.resolve().then(() => stream?.cancel()).catch(() => {
|
|
177
187
|
});
|
|
178
188
|
return requestEnhance(body, options.signal);
|
|
@@ -295,10 +305,12 @@ function ResultPanel(props) {
|
|
|
295
305
|
const first = focusables[0];
|
|
296
306
|
const last = focusables[focusables.length - 1];
|
|
297
307
|
if (first === void 0 || last === void 0) return;
|
|
298
|
-
|
|
308
|
+
const active = document.activeElement;
|
|
309
|
+
const atRoot = active === panel;
|
|
310
|
+
if (event.shiftKey && (active === first || atRoot)) {
|
|
299
311
|
event.preventDefault();
|
|
300
312
|
last.focus();
|
|
301
|
-
} else if (!event.shiftKey &&
|
|
313
|
+
} else if (!event.shiftKey && active === last) {
|
|
302
314
|
event.preventDefault();
|
|
303
315
|
first.focus();
|
|
304
316
|
}
|
|
@@ -562,6 +574,7 @@ function shortcutTarget() {
|
|
|
562
574
|
if (active !== null && active instanceof Element) {
|
|
563
575
|
let node = active;
|
|
564
576
|
for (let depth = 0; depth < 8 && node !== null; depth++) {
|
|
577
|
+
if (node === document.body || node === document.documentElement) break;
|
|
565
578
|
for (const entry of sessions.values()) {
|
|
566
579
|
if (entry.root !== null && (node === entry.root || node.contains(entry.root))) {
|
|
567
580
|
const found = entry;
|
|
@@ -1168,12 +1181,6 @@ function installClientSettingsSource(ctx, options) {
|
|
|
1168
1181
|
const bind = () => {
|
|
1169
1182
|
const entryId = resolveEntryId();
|
|
1170
1183
|
if (entryId === void 0 || entryId === boundId) return;
|
|
1171
|
-
try {
|
|
1172
|
-
unsubscribeForm?.();
|
|
1173
|
-
} catch {
|
|
1174
|
-
}
|
|
1175
|
-
unsubscribeForm = void 0;
|
|
1176
|
-
boundId = entryId;
|
|
1177
1184
|
let form;
|
|
1178
1185
|
try {
|
|
1179
1186
|
form = forms.get?.(entryId);
|
|
@@ -1181,6 +1188,12 @@ function installClientSettingsSource(ctx, options) {
|
|
|
1181
1188
|
return;
|
|
1182
1189
|
}
|
|
1183
1190
|
if (form === void 0) return;
|
|
1191
|
+
try {
|
|
1192
|
+
unsubscribeForm?.();
|
|
1193
|
+
} catch {
|
|
1194
|
+
}
|
|
1195
|
+
unsubscribeForm = void 0;
|
|
1196
|
+
boundId = entryId;
|
|
1184
1197
|
adoptSnapshot(RANK.configForms, form);
|
|
1185
1198
|
try {
|
|
1186
1199
|
unsubscribeForm = form.subscribe?.(() => adoptSnapshot(RANK.configForms, form));
|
|
@@ -1263,15 +1276,22 @@ function installClientSettingsSource(ctx, options) {
|
|
|
1263
1276
|
|
|
1264
1277
|
// src/client/index.tsx
|
|
1265
1278
|
var inject = [];
|
|
1279
|
+
function report(step, error) {
|
|
1280
|
+
try {
|
|
1281
|
+
console.warn(`[prompt-enhance] ${step} failed; that feature stays off.`, error);
|
|
1282
|
+
} catch {
|
|
1283
|
+
}
|
|
1284
|
+
return () => {
|
|
1285
|
+
};
|
|
1286
|
+
}
|
|
1266
1287
|
function apply(ctx) {
|
|
1267
1288
|
ensureStyles();
|
|
1268
1289
|
ctx.inject(["locale"], (localeCtx) => {
|
|
1269
1290
|
ctx.effect(() => {
|
|
1270
1291
|
try {
|
|
1271
1292
|
return localeCtx.locale.register(NS, dictionaries);
|
|
1272
|
-
} catch {
|
|
1273
|
-
return (
|
|
1274
|
-
};
|
|
1293
|
+
} catch (error) {
|
|
1294
|
+
return report("dictionary registration", error);
|
|
1275
1295
|
}
|
|
1276
1296
|
}, "dsh-prompt-enhance: dictionaries");
|
|
1277
1297
|
});
|
|
@@ -1289,9 +1309,8 @@ function apply(ctx) {
|
|
|
1289
1309
|
{ name: "conversation.input.right", id: "prompt-enhance", order: 60, locale: NS },
|
|
1290
1310
|
EnhanceButton
|
|
1291
1311
|
);
|
|
1292
|
-
} catch {
|
|
1293
|
-
return (
|
|
1294
|
-
};
|
|
1312
|
+
} catch (error) {
|
|
1313
|
+
return report("composer enhance button slot", error);
|
|
1295
1314
|
}
|
|
1296
1315
|
});
|
|
1297
1316
|
});
|
|
@@ -1304,16 +1323,17 @@ function apply(ctx) {
|
|
|
1304
1323
|
{ name: "conversation.input.dock", id: "prompt-enhance-undo", order: 90, locale: NS },
|
|
1305
1324
|
UndoBar
|
|
1306
1325
|
);
|
|
1307
|
-
} catch {
|
|
1308
|
-
return (
|
|
1309
|
-
};
|
|
1326
|
+
} catch (error) {
|
|
1327
|
+
return report("undo bar slot", error);
|
|
1310
1328
|
}
|
|
1311
1329
|
});
|
|
1312
1330
|
});
|
|
1313
1331
|
ctx.effect(() => {
|
|
1314
1332
|
const onKeyDown = (event) => {
|
|
1315
1333
|
if (event.defaultPrevented || event.isComposing) return;
|
|
1316
|
-
const
|
|
1334
|
+
const settings = getClientSettings();
|
|
1335
|
+
if (!settings.enabled) return;
|
|
1336
|
+
const combo = parseShortcut(settings.shortcut);
|
|
1317
1337
|
if (!matchesShortcut(event, combo)) return;
|
|
1318
1338
|
const target = shortcutTarget();
|
|
1319
1339
|
if (target === void 0) return;
|
package/lib/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/config.ts
|
|
2
|
-
import z from "schemastery";
|
|
2
|
+
import z from "@deepseek-ai/schemastery";
|
|
3
3
|
var PROMPT_ENHANCE_NAMESPACE = "prompt-enhance";
|
|
4
4
|
var DEFAULT_CONFIG = {
|
|
5
5
|
enabled: true,
|
|
@@ -18,22 +18,22 @@ var DEFAULT_CONFIG = {
|
|
|
18
18
|
contextMaxChars: 4e3
|
|
19
19
|
};
|
|
20
20
|
var Config = z.object({
|
|
21
|
-
enabled: z.boolean().default(DEFAULT_CONFIG.enabled).description("\u603B\u5F00\u5173\uFF1A\u5173\u95ED\u540E\u9690\u85CF\u8F93\u5165\u6846\u589E\u5F3A\u6309\u94AE\u5E76\u505C\u7528\u6240\u6709\u89E6\u53D1\u65B9\u5F0F"),
|
|
22
|
-
provider: z.string().description("\u8986\u76D6\u6A21\u578B\u8DEF\u7531\u7684 provider\uFF08\u4E0E\u300C\u6A21\u578B\u300D\u5FC5\u987B\u6210\u5BF9\u586B\u5199\uFF1B\u7559\u7A7A\u8DDF\u968F\u5F53\u524D\u4F1A\u8BDD\u6A21\u578B\uFF09"),
|
|
23
|
-
model: z.string().description("\u8986\u76D6\u6A21\u578B\u8DEF\u7531\u7684 model\uFF08\u4E0E\u300Cprovider\u300D\u5FC5\u987B\u6210\u5BF9\u586B\u5199\uFF1B\u7559\u7A7A\u8DDF\u968F\u5F53\u524D\u4F1A\u8BDD\u6A21\u578B\uFF09"),
|
|
24
|
-
temperature: z.number().min(0).max(1).step(0.05).default(DEFAULT_CONFIG.temperature).description("\u91C7\u6837\u6E29\u5EA6\uFF1B\u4F4E\u6E29\u6539\u5199\u66F4\u5FE0\u5B9E\u4E8E\u539F\u610F"),
|
|
25
|
-
maxOutputTokens: z.number().step(1).min(256).max(32768).default(DEFAULT_CONFIG.maxOutputTokens).description("\u5355\u6B21\u589E\u5F3A\u7684\u8F93\u51FA token \u4E0A\u9650"),
|
|
26
|
-
maxInputChars: z.number().step(1).min(200).max(2e5).default(DEFAULT_CONFIG.maxInputChars).description("\u8F93\u5165\u5B57\u6570\u4E0A\u9650\uFF1B\u8D85\u9650\u62D2\u7EDD\u800C\u4E0D\u622A\u65AD\uFF0C\u907F\u514D\u6539\u53D8\u539F\u610F"),
|
|
27
|
-
timeoutMs: z.number().step(1).min(5e3).max(6e5).default(DEFAULT_CONFIG.timeoutMs).description("\u5355\u6B21\u589E\u5F3A\u7684\u8D85\u65F6\uFF08\u6BEB\u79D2\uFF09"),
|
|
28
|
-
systemPrompt: z.string().role("textarea").default(DEFAULT_CONFIG.systemPrompt).description("\u7CFB\u7EDF\u63D0\u793A\u8BCD\uFF1B\u7559\u7A7A\u4F7F\u7528\u5185\u7F6E\u589E\u5F3A\u7B56\u7565"),
|
|
29
|
-
strategyMode: z.union(["replace-default", "extend-default"]).default(DEFAULT_CONFIG.strategyMode).description("\u81EA\u5B9A\u4E49\u7CFB\u7EDF\u63D0\u793A\u8BCD\u7684\u7EC4\u5408\u65B9\u5F0F\uFF1A\u6574\u4F53\u66FF\u6362\u5185\u7F6E\u7B56\u7565\uFF08\u9ED8\u8BA4\uFF1B\u5185\u7F6E\u7B56\u7565\u7684\u4E0D\u7F16\u9020\u3001\u53EA\u8F93\u51FA\u6B63\u6587\u7B49\u786C\u6027\u7EA6\u675F\u4E0D\u4F1A\u81EA\u52A8\u4FDD\u7559\uFF09\uFF0C\u6216\u628A\u81EA\u5B9A\u4E49\u6587\u672C\u8FFD\u52A0\u5728\u5185\u7F6E\u7B56\u7565\u4E4B\u540E\uFF08\u786C\u6027\u7EA6\u675F\u7EE7\u7EED\u751F\u6548\uFF09"),
|
|
30
|
-
shortcut: z.string().default(DEFAULT_CONFIG.shortcut).description("\u89E6\u53D1\u5FEB\u6377\u952E\uFF08\u5982 ctrl+alt+e\uFF1B\u987B\u5305\u542B ctrl/alt/meta \u4E2D\u81F3\u5C11\u4E00\u4E2A\u4FEE\u9970\u952E\uFF0Cshift \u4EC5\u53EF\u4F5C\u9644\u52A0\uFF0C\u7EAF\u5B57\u6BCD/\u6570\u5B57\u6216 shift+\u5B57\u6BCD\u4F1A\u88AB\u5FFD\u7565\uFF1B\u7559\u7A7A\u7981\u7528\uFF09"),
|
|
31
|
-
maxConcurrent: z.number().step(1).min(1).max(16).default(DEFAULT_CONFIG.maxConcurrent).description("\u5BBF\u4E3B\u4FA7\u5E76\u53D1\u4E0A\u9650\uFF1A\u540C\u65F6\u8FDB\u884C\u7684\u589E\u5F3A\u8C03\u7528\u6570\uFF0C\u8D85\u51FA\u7684\u8BF7\u6C42\u8FD4\u56DE 429"),
|
|
32
|
-
rateLimitPerMinute: z.number().step(1).min(1).max(600).default(DEFAULT_CONFIG.rateLimitPerMinute).description("\u6BCF\u5206\u949F\u589E\u5F3A\u6B21\u6570\u4E0A\u9650\uFF08\u6ED1\u52A8\u7A97\u53E3\uFF09\uFF0C\u8D85\u51FA\u8FD4\u56DE 429"),
|
|
33
|
-
streaming: z.boolean().default(DEFAULT_CONFIG.streaming).description("\u589E\u91CF\u5C55\u793A\uFF1A\u6A21\u578B\u8FB9\u5199\u8FB9\u5728\u9762\u677F\u663E\u793A\uFF08\u4EC5\u5F71\u54CD\u663E\u793A\u8282\u594F\uFF0C\u6700\u7EC8\u7ED3\u679C\u4E0D\u53D8\uFF1B\u5BBF\u4E3B\u6216\u7F51\u7EDC\u4E0D\u652F\u6301\u65F6\u81EA\u52A8\u56DE\u9000\u4E3A\u4E00\u6B21\u6027\u8FD4\u56DE\uFF09"),
|
|
34
|
-
contextAware: z.boolean().default(DEFAULT_CONFIG.contextAware).description("\u4E0A\u4E0B\u6587\u611F\u77E5\uFF1A\u8BFB\u53D6\u5F53\u524D\u4F1A\u8BDD\u8FD1\u671F\u5BF9\u8BDD\uFF0C\u7528\u4E8E\u6D88\u89E3\u6307\u4EE3\u3001\u8865\u5168\u7701\u7565\u4E0E\u672F\u8BED\u7EA6\u675F\uFF1B\u65E0\u5386\u53F2\u6216\u5386\u53F2\u4E0D\u8DB3\u65F6\u81EA\u52A8\u56DE\u9000\u4E3A\u5355\u6761\u589E\u5F3A\uFF0C\u4E0D\u81C6\u9020\u4FE1\u606F"),
|
|
35
|
-
contextMaxMessages: z.number().step(1).min(0).max(50).default(DEFAULT_CONFIG.contextMaxMessages).description("\u4E0A\u4E0B\u6587\u7A97\u53E3\uFF08\u6761\u6570\uFF09\uFF1A\u6700\u591A\u53C2\u8003\u6700\u8FD1\u591A\u5C11\u6761 user/assistant \u8F6E\u6B21\uFF1B0 \u8868\u793A\u4E0D\u53C2\u8003"),
|
|
36
|
-
contextMaxChars: z.number().step(1).min(0).max(1e5).default(DEFAULT_CONFIG.contextMaxChars).description("\u4E0A\u4E0B\u6587\u7A97\u53E3\uFF08\u5B57\u6570\uFF09\uFF1A\u5386\u53F2\u7247\u6BB5\u7684\u5B57\u7B26\u9884\u7B97\uFF0C\u4ECE\u6700\u65B0\u4E00\u6761\u5411\u524D\u88C5\u914D\uFF1B0 \u8868\u793A\u4E0D\u53C2\u8003")
|
|
21
|
+
enabled: z.boolean().default(DEFAULT_CONFIG.enabled).description("\u603B\u5F00\u5173\uFF1A\u5173\u95ED\u540E\u9690\u85CF\u8F93\u5165\u6846\u589E\u5F3A\u6309\u94AE\u5E76\u505C\u7528\u6240\u6709\u89E6\u53D1\u65B9\u5F0F").volatile(),
|
|
22
|
+
provider: z.string().description("\u8986\u76D6\u6A21\u578B\u8DEF\u7531\u7684 provider\uFF08\u4E0E\u300C\u6A21\u578B\u300D\u5FC5\u987B\u6210\u5BF9\u586B\u5199\uFF1B\u7559\u7A7A\u8DDF\u968F\u5F53\u524D\u4F1A\u8BDD\u6A21\u578B\uFF09").volatile(),
|
|
23
|
+
model: z.string().description("\u8986\u76D6\u6A21\u578B\u8DEF\u7531\u7684 model\uFF08\u4E0E\u300Cprovider\u300D\u5FC5\u987B\u6210\u5BF9\u586B\u5199\uFF1B\u7559\u7A7A\u8DDF\u968F\u5F53\u524D\u4F1A\u8BDD\u6A21\u578B\uFF09").volatile(),
|
|
24
|
+
temperature: z.number().min(0).max(1).step(0.05).default(DEFAULT_CONFIG.temperature).description("\u91C7\u6837\u6E29\u5EA6\uFF1B\u4F4E\u6E29\u6539\u5199\u66F4\u5FE0\u5B9E\u4E8E\u539F\u610F").volatile(),
|
|
25
|
+
maxOutputTokens: z.number().step(1).min(256).max(32768).default(DEFAULT_CONFIG.maxOutputTokens).description("\u5355\u6B21\u589E\u5F3A\u7684\u8F93\u51FA token \u4E0A\u9650").volatile(),
|
|
26
|
+
maxInputChars: z.number().step(1).min(200).max(2e5).default(DEFAULT_CONFIG.maxInputChars).description("\u8F93\u5165\u5B57\u6570\u4E0A\u9650\uFF1B\u8D85\u9650\u62D2\u7EDD\u800C\u4E0D\u622A\u65AD\uFF0C\u907F\u514D\u6539\u53D8\u539F\u610F").volatile(),
|
|
27
|
+
timeoutMs: z.number().step(1).min(5e3).max(6e5).default(DEFAULT_CONFIG.timeoutMs).description("\u5355\u6B21\u589E\u5F3A\u7684\u8D85\u65F6\uFF08\u6BEB\u79D2\uFF09").volatile(),
|
|
28
|
+
systemPrompt: z.string().role("textarea").default(DEFAULT_CONFIG.systemPrompt).description("\u7CFB\u7EDF\u63D0\u793A\u8BCD\uFF1B\u7559\u7A7A\u4F7F\u7528\u5185\u7F6E\u589E\u5F3A\u7B56\u7565").volatile(),
|
|
29
|
+
strategyMode: z.union(["replace-default", "extend-default"]).default(DEFAULT_CONFIG.strategyMode).description("\u81EA\u5B9A\u4E49\u7CFB\u7EDF\u63D0\u793A\u8BCD\u7684\u7EC4\u5408\u65B9\u5F0F\uFF1A\u6574\u4F53\u66FF\u6362\u5185\u7F6E\u7B56\u7565\uFF08\u9ED8\u8BA4\uFF1B\u5185\u7F6E\u7B56\u7565\u7684\u4E0D\u7F16\u9020\u3001\u53EA\u8F93\u51FA\u6B63\u6587\u7B49\u786C\u6027\u7EA6\u675F\u4E0D\u4F1A\u81EA\u52A8\u4FDD\u7559\uFF09\uFF0C\u6216\u628A\u81EA\u5B9A\u4E49\u6587\u672C\u8FFD\u52A0\u5728\u5185\u7F6E\u7B56\u7565\u4E4B\u540E\uFF08\u786C\u6027\u7EA6\u675F\u7EE7\u7EED\u751F\u6548\uFF09").volatile(),
|
|
30
|
+
shortcut: z.string().default(DEFAULT_CONFIG.shortcut).description("\u89E6\u53D1\u5FEB\u6377\u952E\uFF08\u5982 ctrl+alt+e\uFF1B\u987B\u5305\u542B ctrl/alt/meta \u4E2D\u81F3\u5C11\u4E00\u4E2A\u4FEE\u9970\u952E\uFF0Cshift \u4EC5\u53EF\u4F5C\u9644\u52A0\uFF0C\u7EAF\u5B57\u6BCD/\u6570\u5B57\u6216 shift+\u5B57\u6BCD\u4F1A\u88AB\u5FFD\u7565\uFF1B\u7559\u7A7A\u7981\u7528\uFF09").volatile(),
|
|
31
|
+
maxConcurrent: z.number().step(1).min(1).max(16).default(DEFAULT_CONFIG.maxConcurrent).description("\u5BBF\u4E3B\u4FA7\u5E76\u53D1\u4E0A\u9650\uFF1A\u540C\u65F6\u8FDB\u884C\u7684\u589E\u5F3A\u8C03\u7528\u6570\uFF0C\u8D85\u51FA\u7684\u8BF7\u6C42\u8FD4\u56DE 429").volatile(),
|
|
32
|
+
rateLimitPerMinute: z.number().step(1).min(1).max(600).default(DEFAULT_CONFIG.rateLimitPerMinute).description("\u6BCF\u5206\u949F\u589E\u5F3A\u6B21\u6570\u4E0A\u9650\uFF08\u6ED1\u52A8\u7A97\u53E3\uFF09\uFF0C\u8D85\u51FA\u8FD4\u56DE 429").volatile(),
|
|
33
|
+
streaming: z.boolean().default(DEFAULT_CONFIG.streaming).description("\u589E\u91CF\u5C55\u793A\uFF1A\u6A21\u578B\u8FB9\u5199\u8FB9\u5728\u9762\u677F\u663E\u793A\uFF08\u4EC5\u5F71\u54CD\u663E\u793A\u8282\u594F\uFF0C\u6700\u7EC8\u7ED3\u679C\u4E0D\u53D8\uFF1B\u5BBF\u4E3B\u6216\u7F51\u7EDC\u4E0D\u652F\u6301\u65F6\u81EA\u52A8\u56DE\u9000\u4E3A\u4E00\u6B21\u6027\u8FD4\u56DE\uFF09").volatile(),
|
|
34
|
+
contextAware: z.boolean().default(DEFAULT_CONFIG.contextAware).description("\u4E0A\u4E0B\u6587\u611F\u77E5\uFF1A\u8BFB\u53D6\u5F53\u524D\u4F1A\u8BDD\u8FD1\u671F\u5BF9\u8BDD\uFF0C\u7528\u4E8E\u6D88\u89E3\u6307\u4EE3\u3001\u8865\u5168\u7701\u7565\u4E0E\u672F\u8BED\u7EA6\u675F\uFF1B\u65E0\u5386\u53F2\u6216\u5386\u53F2\u4E0D\u8DB3\u65F6\u81EA\u52A8\u56DE\u9000\u4E3A\u5355\u6761\u589E\u5F3A\uFF0C\u4E0D\u81C6\u9020\u4FE1\u606F").volatile(),
|
|
35
|
+
contextMaxMessages: z.number().step(1).min(0).max(50).default(DEFAULT_CONFIG.contextMaxMessages).description("\u4E0A\u4E0B\u6587\u7A97\u53E3\uFF08\u6761\u6570\uFF09\uFF1A\u6700\u591A\u53C2\u8003\u6700\u8FD1\u591A\u5C11\u6761 user/assistant \u8F6E\u6B21\uFF1B0 \u8868\u793A\u4E0D\u53C2\u8003").volatile(),
|
|
36
|
+
contextMaxChars: z.number().step(1).min(0).max(1e5).default(DEFAULT_CONFIG.contextMaxChars).description("\u4E0A\u4E0B\u6587\u7A97\u53E3\uFF08\u5B57\u6570\uFF09\uFF1A\u5386\u53F2\u7247\u6BB5\u7684\u5B57\u7B26\u9884\u7B97\uFF0C\u4ECE\u6700\u65B0\u4E00\u6761\u5411\u524D\u88C5\u914D\uFF1B0 \u8868\u793A\u4E0D\u53C2\u8003").volatile()
|
|
37
37
|
});
|
|
38
38
|
function resolveConfig(config) {
|
|
39
39
|
if (config === null || typeof config !== "object") throw new Error("prompt-enhance: configuration is required");
|
|
@@ -867,6 +867,13 @@ function writeJson(res, status, body) {
|
|
|
867
867
|
});
|
|
868
868
|
res.end(JSON.stringify(body));
|
|
869
869
|
}
|
|
870
|
+
function endResponse(res) {
|
|
871
|
+
if (res.writableEnded || res.destroyed) return;
|
|
872
|
+
try {
|
|
873
|
+
res.end();
|
|
874
|
+
} catch {
|
|
875
|
+
}
|
|
876
|
+
}
|
|
870
877
|
|
|
871
878
|
// src/enhance-routes.ts
|
|
872
879
|
var bodyCapOf = (maxInputChars) => maxInputChars * 6 + 4096;
|
|
@@ -1005,12 +1012,7 @@ data: ${JSON.stringify({ type: "delta", text: tail })}
|
|
|
1005
1012
|
data: ${JSON.stringify({ type: "done", value })}
|
|
1006
1013
|
|
|
1007
1014
|
`);
|
|
1008
|
-
|
|
1009
|
-
try {
|
|
1010
|
-
res.end();
|
|
1011
|
-
} catch {
|
|
1012
|
-
}
|
|
1013
|
-
}
|
|
1015
|
+
endResponse(res);
|
|
1014
1016
|
} finally {
|
|
1015
1017
|
sse.dispose();
|
|
1016
1018
|
}
|
|
@@ -1030,10 +1032,16 @@ data: ${JSON.stringify({ type: "done", value })}
|
|
|
1030
1032
|
}
|
|
1031
1033
|
const wire = toEnhanceError(error);
|
|
1032
1034
|
if (stream && res.headersSent) {
|
|
1033
|
-
if (!res.writableEnded)
|
|
1035
|
+
if (!res.writableEnded) {
|
|
1036
|
+
try {
|
|
1037
|
+
res.write(`event: error
|
|
1034
1038
|
data: ${JSON.stringify({ type: "error", error: wire })}
|
|
1035
1039
|
|
|
1036
1040
|
`);
|
|
1041
|
+
} catch {
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
endResponse(res);
|
|
1037
1045
|
} else {
|
|
1038
1046
|
writeJson(res, wire.code === "timeout" ? 504 : wire.code === "unconfigured" ? 409 : 502, { ok: false, error: wire });
|
|
1039
1047
|
}
|
|
@@ -1044,27 +1052,40 @@ data: ${JSON.stringify({ type: "error", error: wire })}
|
|
|
1044
1052
|
}
|
|
1045
1053
|
var mounts = /* @__PURE__ */ new WeakMap();
|
|
1046
1054
|
function registerEnhanceRoute(ctx, readConfig) {
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
const dispose = webserver.register({
|
|
1059
|
-
kind: "prefix",
|
|
1060
|
-
path: ENHANCE_PREFIX,
|
|
1061
|
-
handler: (req, res) => {
|
|
1062
|
-
const pathname = new URL(req.url ?? "/", "http://x").pathname;
|
|
1063
|
-
return serveEnhance(ctx, readConfig, gate, pathname, req, res, pathname === ENHANCE_STREAM_ENDPOINT);
|
|
1055
|
+
ctx.inject(["webServer"], (routeCtx) => {
|
|
1056
|
+
const webserver = routeCtx.get("webServer");
|
|
1057
|
+
if (webserver === void 0) return;
|
|
1058
|
+
const existing = mounts.get(ctx);
|
|
1059
|
+
if (existing !== void 0 && existing.webserver === webserver) return;
|
|
1060
|
+
if (existing !== void 0) {
|
|
1061
|
+
try {
|
|
1062
|
+
existing.dispose();
|
|
1063
|
+
} catch {
|
|
1064
|
+
}
|
|
1065
|
+
mounts.delete(ctx);
|
|
1064
1066
|
}
|
|
1067
|
+
const gate = { stamps: [], active: 0, failures: 0, cooldownUntil: 0 };
|
|
1068
|
+
routeCtx.effect(() => {
|
|
1069
|
+
const dispose = webserver.register({
|
|
1070
|
+
kind: "prefix",
|
|
1071
|
+
path: ENHANCE_PREFIX,
|
|
1072
|
+
handler: (req, res) => {
|
|
1073
|
+
const pathname = new URL(req.url ?? "/", "http://x").pathname;
|
|
1074
|
+
return serveEnhance(ctx, readConfig, gate, pathname, req, res, pathname === ENHANCE_STREAM_ENDPOINT);
|
|
1075
|
+
}
|
|
1076
|
+
});
|
|
1077
|
+
const disposed = typeof dispose === "function" ? dispose : () => {
|
|
1078
|
+
};
|
|
1079
|
+
mounts.set(ctx, { webserver, dispose: disposed });
|
|
1080
|
+
return () => {
|
|
1081
|
+
if (mounts.get(ctx)?.dispose === disposed) mounts.delete(ctx);
|
|
1082
|
+
try {
|
|
1083
|
+
disposed();
|
|
1084
|
+
} catch {
|
|
1085
|
+
}
|
|
1086
|
+
};
|
|
1087
|
+
}, "prompt-enhance: enhance route");
|
|
1065
1088
|
});
|
|
1066
|
-
mounts.set(ctx, { webserver, dispose: typeof dispose === "function" ? dispose : () => {
|
|
1067
|
-
} });
|
|
1068
1089
|
}
|
|
1069
1090
|
|
|
1070
1091
|
// src/enhance-command.ts
|
|
@@ -1081,15 +1102,15 @@ function registerEnhanceCommand(ctx, readConfig) {
|
|
|
1081
1102
|
if (raw === "") {
|
|
1082
1103
|
return { kind: "error", text: "\u7528\u6CD5\uFF1A/enhance <\u6587\u672C>\u3002\u8981\u589E\u5F3A\u8F93\u5165\u6846\u91CC\u7684\u8349\u7A3F\uFF0C\u8BF7\u7528\u8F93\u5165\u6846\u53F3\u4FA7\u7684\u300C\u589E\u5F3A\u300D\u6309\u94AE\u6216\u5FEB\u6377\u952E\u3002" };
|
|
1083
1104
|
}
|
|
1084
|
-
const config = readConfig();
|
|
1085
|
-
if (!config.enabled) {
|
|
1086
|
-
return { kind: "error", text: "\u63D0\u793A\u8BCD\u589E\u5F3A\u5DF2\u5728\u63D2\u4EF6\u8BBE\u7F6E\u4E2D\u5173\u95ED\u3002" };
|
|
1087
|
-
}
|
|
1088
|
-
const check = checkInputText(raw, config.maxInputChars);
|
|
1089
|
-
if (!check.ok) {
|
|
1090
|
-
return { kind: "error", text: formatInputCheckZh(check) };
|
|
1091
|
-
}
|
|
1092
1105
|
try {
|
|
1106
|
+
const config = readConfig();
|
|
1107
|
+
if (!config.enabled) {
|
|
1108
|
+
return { kind: "error", text: "\u63D0\u793A\u8BCD\u589E\u5F3A\u5DF2\u5728\u63D2\u4EF6\u8BBE\u7F6E\u4E2D\u5173\u95ED\u3002" };
|
|
1109
|
+
}
|
|
1110
|
+
const check = checkInputText(raw, config.maxInputChars);
|
|
1111
|
+
if (!check.ok) {
|
|
1112
|
+
return { kind: "error", text: formatInputCheckZh(check) };
|
|
1113
|
+
}
|
|
1093
1114
|
const value = await runEnhance(ctx, config, {
|
|
1094
1115
|
text: raw,
|
|
1095
1116
|
sessionRoute: sessionRouteOf(ctx, invocation.agent.session.id),
|
|
@@ -1107,7 +1128,7 @@ function registerEnhanceCommand(ctx, readConfig) {
|
|
|
1107
1128
|
|
|
1108
1129
|
// src/index.ts
|
|
1109
1130
|
var name = "prompt-enhance";
|
|
1110
|
-
var inject = ["llm"
|
|
1131
|
+
var inject = ["llm"];
|
|
1111
1132
|
function apply(ctx, config = { ...DEFAULT_CONFIG }) {
|
|
1112
1133
|
const source = installSettingsSource(ctx, {
|
|
1113
1134
|
namespace: PROMPT_ENHANCE_NAMESPACE,
|