dsh-codex-composer
Codex-style composer history and next-prompt suggestions for the DeepSeek Harness Web GUI.
给 DSH Web GUI 的输入框补上 Codex 风格的键盘手感:
| 键 | 行为 |
|---|---|
↑ |
光标在首行(或草稿为空)时,召回上一条 prompt |
↓ |
在召回历史中前进;走到底恢复召回前的草稿 |
Tab |
草稿为空:按上下文生成下一步 prompt;有文字且有历史匹配:补全;有文字但无匹配:原生 Tab(焦点跳转) |
Esc |
取消召回 / 取消正在生成的建议,恢复召回前的草稿 |
/、@ 补全菜单打开时,方向键和 Tab 仍归菜单使用;插件不会抢。普通多行编辑、中文输入法、Shift+Enter 换行都不受影响。
上下文建议(Tab)
只在草稿为空时,按 Tab 会调用宿主的 POST /codex-composer/suggest:
- 输入框获得焦点时,客户端会后台调用
GET /codex-composer/history拉取当前 Session 的完整 user prompt 列表(纯读、不调用模型),补足浏览器事件窗口看不到的老 prompt;首次按 Tab 也会兜底拉一次; - 草稿为空时,宿主读取当前 Session 最近的 user/assistant 消息(最多 14 条、总量约 20k 字符),用当前会话实际使用的模型路由生成一条“下一步用户 prompt”;
- 生成期间底部出现
正在生成下一步建议…,结果直接写入输入框(不会自动发送); - 只请求一次,重复按 Tab 不会并发;输入、切换会话、按
Esc或关闭插件都会取消; - 这是一次辅助模型调用:不 spawn agent、不写入会话事件、不进入对话历史,但会消耗对应 provider 的 token。
兼容性
- 目标:DeepSeek Harness
>= 0.2.1-rc.3,Web profile; - 依赖宿主已有的
conversation/sessions/llm/webServer服务; - 不改
app.asar,不注册全局快捷键,不发送后台请求(除了用户按 Tab/聚焦输入框时的两个本地路由)。
安全与隐私
- 历史 prompt 只存在浏览器
localStorage,key 带 Session id;不会上传到第三方。 - 上下文建议会把当前 Session 最近的消息发送给会话正在使用的模型 provider(与正常对话同一路由);不发送凭据、环境变量或工作区文件内容。
- 两个宿主路由都经过 DSH 的 origin fence 和 Web 登录态;不会接受任意 URL 或任意 prompt。
- 辅助模型调用不 spawn agent、不写入会话事件;仍会按 provider 计费。
行为细节
- 按 Session 隔离:以
data-conversation-session为准,每个会话一份历史。 - 自动播种:首次使用时从会话事件流的
user/message里读出历史 prompt,所以老会话也能直接按↑。 - 持续记录:Enter 发送和点击发送按钮后会追加到历史;最多保留 100 条。
- 持久化:写入
localStorage,key 为dsh-codex-composer.history.v1:<sessionId>。清空这个 key 即可重置该会话历史。 - 只写草稿,不碰 Lexical DOM:通过
conversation.input.for(scope).setDraft()写入,保留宿主自己的 undo/输入法/触发菜单逻辑。 - 建议不落会话:
ctx.llm.stream走辅助请求通道,不产生user/message或assistant/message;生成内容只存在于输入框。
已知边界
- 历史只覆盖纯文本 prompt。带
@引用 chip 的草稿被召回时,会以 chip 的文本投影出现(setDraft本身会压平 chip)。 - 发送失败后宿主恢复草稿的场景,历史里可能已经记下这条,属于可接受的重复。
- 只处理主 composer(
data-composer-input);队列编辑框、侧栏编辑器不接管。 - 上下文建议会真实调用模型(使用会话当前路由,低 reasoning effort),每次 Tab 最多一次;不想用时停用插件即可。
Shift+Tab不被接管,仍可做焦点遍历;只有不带修饰键的 Tab 会触发补全/建议。- 有文字时 Tab 只在历史命中时接管,否则原样交给浏览器;空草稿时 Tab 用于生成建议,想移出输入框可用
Shift+Tab或点击。 - 这是 Web 客户端插件,不改
app.asar,也不改变会话历史。
安装
标准 bundle 安装(推荐,需要能运行 dsh plugin add 的环境):
dsh plugin --profile desktop add /absolute/path/to/dsh-codex-composer
或手工装进 profile:
- 在
~/.dsh/profiles/desktop/package.json的dependencies里加"dsh-codex-composer": "file:/absolute/path/to/dsh-codex-composer"; - 把
"dsh-codex-composer"追加到dsh.profile.bundles; - 在 profile 目录执行
pnpm install; - 重启 DSH(Host 需要重新扫描 client bundle)。
安装后可在 Settings → Plugins 里看到 codex-composer 条目;停用它即可完全移除键盘接管。
从 dsh.pub 安装(发布后):
npx dshpub add sakura-hly/dsh-codex-composer --ref <commit>
也可以直接在 Settings → Plugins → Discover 里搜索 dsh-codex-composer。
卸载
从 profile 的 dsh.profile.bundles 和 dependencies 里移除 dsh-codex-composer,在 profile 目录重新 pnpm install,再重启 DSH。若只想临时关掉,直接在 Settings → Plugins 停用即可,无需改文件。
开发
lib/client.js 是手写的 client bundle,格式与 window.__ModuleLoader__.load({ id, factory }) 一致;lib/index.js 是 host half,注册 /codex-composer/suggest 辅助路由(ctx.llm.stream),并让 Loader 有这个条目。
npm run check # node --check lib/client.js && node --check lib/index.js
npm test # core + keyboard unit tests
No comments yet. Be the first to write one.