# dsh-client-ui-quickfill

给 DSH Web 输入框加上**终端式历史与快速补全**：像 shell 的 scrollback 一样翻阅历史 prompt、即时搜索、一键填充。

- **翻阅**：`Alt+↑` / `Alt+↓` 循环历史（多行草稿也能用）；单行草稿时裸 `↑`/`↓` 同样循环。第一次按 `↑` 应用 zsh `up-line-or-search`：若草稿是某条历史的**前缀**，直接跳转最新匹配并只在该前缀内翻页。
- **搜索**：`Ctrl+R`（macOS 为 `Cmd+R`）打开历史搜索面板——输入即**模糊匹配**（子序列），`↑`/`↓` 选择，再按 `Ctrl+R` 跳到下一条（reverse-i-search），`Enter` 回填，`Esc` 关闭。
- **补全**：输入时最新一条**以草稿开头**的历史以**灰色幽灵**实时显示在光标后（fish 式 autosuggestion）；`Tab` 或行尾 `→` 接受为一次普通（可撤销）草稿写入。
- **保护**：翻回最新（或按 `Esc`）时**原样恢复**正在输入的内容与光标位置；相邻重复 prompt 只留一条、空白 prompt 不记录；IME 组词（拼音）期间按键全部放行。
- **可选跨会话池**：opt-in 的全局历史（localStorage）让搜索、前缀定位与补全命中所有会话的 prompt（zsh `SHARE_HISTORY` 语义）；默认关闭（隐私）。

## 安装（社区用户）

需要 pnpm（`npm install -g pnpm`）：

```sh
dsh plugin --profile web add dsh-client-ui-quickfill
```

然后把插件加进 profile 的组合包列表（`~/.dsh/profiles/web/package.json`）：

```json
"dependencies": {
  "dsh-client-ui-quickfill": "^0.1.0"
}
```

**重启 `dsh web` 服务**——节点端启动时扫描 bundle、应用其 `cordis.patch.yml` 并编入 `window.__DSH_BOOT__` 引导图，只有重启会让新 bundle 生效。

> 插件是**自注册 bundle**：patch 层会自动插入 `ui-quickfill` 浏览器名册行，无需手写 `cordis.patch.yml`。

## 构建与测试（贡献者）

```sh
npm install   # 链接 peer 依赖
npm test      # 冒烟测试：历史派生 / 匹配 / 前缀步进 / 幽灵补全 / 全局池
npm pack      # 检查发布文件集
```

本地开发：在 web-test profile 的依赖里写 `"dsh-client-ui-quickfill": "file:../../dsh-client-ui-quickfill"`，或把目录符号链接进 `~/.dsh/profiles/node_modules` 后重启。

## 数据存储（全部浏览器本地，无服务端）

| localStorage 键 | 内容 |
| --- | --- |
| `dsh-quickfill.global-history` | 跨会话 prompt 池（全局唯一、上限 500 条，最新在后） |
| `dsh-quickfill.settings` | 开关（`global`） |

- 全局历史**默认关闭**（隐私——prompt 可能含敏感内容）。数据只存本机浏览器、不离开设备；会话数据本就在 `~/.dsh` 磁盘上，属于同信任域本地缓存。
- 开启后当前会话全部历史一次性并入池中，此后新发送的 prompt 自动追加；会话内条目始终排在前。
- 清除：DevTools → Application → Local Storage → 删除对应键。

## 已知限制

- macOS 上 `Cmd+R` 同时是浏览器刷新快捷键，拦截并不总是可靠；Windows/Linux 无此问题。
- 历史来自当前已加载的会话快照，超长会话靠 `loadOlder` 拉取。
- 斜杠命令已认领（claimed）或发送中时 `Ctrl+R` 会被吞掉（防刷新丢草稿）——先 Esc 再搜索。
- 幽灵层复制 composer 的字体度量，主题重度覆盖字体/字距时可能偏差 1–2px；多行与空草稿故意不启用补全。
- 分屏多 composer：textarea 定位按座位作用域（`[data-conversation-scroll]`）锁定，理论上互不干扰——尚未在分屏形态实测。

## 许可证

MIT —— 见 [LICENSE](./LICENSE)。

## English

See [README.md](./README.md).
