dsh-tui-find

September 19, 2026 · View on GitHub

dsh-tui-find 封面

dsh-TUI 的跨会话全文搜索插件 —— 对本机全部 dsh 会话(zstd 帧链 + 明文 JSONL)做即时增量搜索:命中可读、可复制、可恢复会话。

English · MIT · 零第三方运行时依赖

这是什么

dsh-TUI 有 resume 浏览器、会话内 / 搜索与 Ctrl+R 输入历史,但没有跨会话内容检索——对话滚出当前窗口就成了不可搜索的档案。本插件补上这一块:

  • 即时:fzf 式纯内存过滤,结果流式渐进出现;多词 AND、JS 正则、拼音(全拼/首字母)、标题限定、时间窗口。
  • 可读可复制:split 分栏(左列表 · 右内容,/resume 同款风格)或全屏预览,锚定命中消息、命中词高亮,一键复制原文或日志路径。
  • 可恢复 恢复会话,二次确认;右键上下文菜单(仅 0.10+ 宿主)。

安装

dsh plugin --profile dsh-tui add -w dsh-tui-find@latest

--profile 换成实际 profile 名($DSH_HOME/profiles/ 下的目录名,未设 DSH_HOME 时为 ~/.dsh)。CLI 把包收录进 profile 的 bundle 列表并自动应用包内 cordis.patch.yml,无需手动改配置;安装 / 升级 / 卸载后需重启 dsh-TUI(或 /restart)生效——宿主 /reload 不重载插件代码。

本地开发安装:npm install && npm pack(prepack 自动构建并跑全量测试),然后 dsh plugin --profile dsh-tui add -w ./dsh-tui-find-<版本号>.tgz;不要直接安装源码目录。

升级与卸载

升级:重跑安装命令(幂等);版本未变先 npm cache clean --force,重启后用 /plugins 验证。

卸载:dsh plugin --profile dsh-tui remove -w dsh-tui-find,重启生效。若 profile package.json → dsh.profile.bundles 仍残留条目(CLI 版本差异),手动删除即可;/settings 保存过的设置留在 settings.yaml、重装后继续生效,想归零删除 dsh-tui-find 命名空间键。卸载只影响本插件:会话数据全程只读、不受影响。

使用

操作说明
/find <关键词>带参直接出结果(空格分隔多词)
/find空参进全屏搜索场景
Alt+F全局入口快捷键(shortcut 配置可改键或 off 关闭)

场景内按键:

动作
任意字符即时过滤;空查询列出最近会话
Tab / Alt+T切换范围(本仓库 ⇄ 全部)/ 时间窗口(全部 ⇄ 近 7 天 ⇄ 近 30 天)
Alt+R / Alt+N切换正则匹配 / 仅搜索标题
↑↓ / PgUp PgDn条目间移动 / 翻页
/ split 布局:右移聚焦右栏阅读窗,左移回到列表(阅读窗始终在屏上,无需打开/关闭)
Alt+Pclassic 布局:打开全屏预览(锚定命中消息、命中词高亮);阅读窗内 ↑↓ 逐行滚动、PgUp/PgDn 翻页、n/N 命中跳转(循环回绕)、滚轮按档滚动
Alt+C / Alt+E复制命中原文(预览内为当前命中:n/N 停驻的那条,或自由滚动后视口上方最近的一条;该会话没有命中时回退为视口顶部那条消息)/ 折叠、展开当前会话命中(与行尾 ▸ (+N) 徽标同一动作)
Alt+H键位帮助面板
/ Esc恢复会话(二次确认)/ 清空查询、返回、退出场景

鼠标:左键选中、悬停高亮、滚轮按宿主同样的档距移动选择(一档 ≈ 3 行;在阅读窗内则按档滚动阅读窗);命中超过 3 条的会话在最后一条命中行右端显示 ▸ (+N) 徽标,点它即展开该会话全部命中(展开后同一位置变 ▴ 收起,箭头转向表示"折回去",悬停时徽标带背景高亮——这是唯一一个不跟随整行点击的控件,整行点击仍是"选中并进入恢复确认");右键开上下文菜单(仅 0.10+ 宿主):复制消息文本 / 复制会话日志路径 / 恢复该会话。

场景布局由 layout 配置选择:split(默认)在终端 ≥ 100 列时同屏显示"左侧列表 + 右侧会话内容阅读窗"(与 /resume 浏览器同风格)——选中项自动锚定右栏、右栏可独立滚动/复制/右键, 聚焦右栏、 回到列表(Alt+P 在 split 下不再使用),窄终端自动回退单栏;classic 维持"单栏列表 + Alt+P 全屏预览"。

阅读窗是只读视图,没有光标↑↓ 直接逐行滚动、PgUp/PgDn 与滚轮按档滚动,n/N 跳到视口之外的上一个/下一个命中(循环回绕)——选中在只读预览里没有意义,所以窗口本身就是位置。因此同一屏永远只有一处选中高亮:左栏持焦点时右栏不带任何强调, 聚焦右栏后边框点亮、左栏仍保留自己的高亮。两种形态下阅读窗都保证命中词在视口内:命中落在消息深处(视口装不下)时直接在命中行开窗,而不是停在看不到关键词的消息头。提示行也按宽度取词:先丢低优先键(滚动与返回键永远保留),极端窄终端再截断兜底,任何宽度都严格占一行,不会换行挤掉内容行。

结果按会话分组、每会话默认展示前 3 条命中((+N) 提示),最近优先;场景打开即开始扫描,结果随会话解析流式出现,头部实时显示进度。

启动约 10 秒后插件在后台预建一次索引(warmup 配置可关),此后首次 /find 即刻出列表;0.10+ 宿主在提示符上方显示"后台索引 n/m"进度行,点按即取消。预热只把冷解码挪到空闲期,不减少总解码量。

默认快捷键是 Alt+F 而非 Ctrl+Shift+F:主流终端把后者留给自身的"查找"功能并截获按键。冲突时用 shortcut 配置改成任意含 CtrlAlt 的组合键。

检索范围

  • 索引:用户消息、助手文本、会话标题;indexTools 开启后含工具调用摘要,indexThinking 开启后含 thinking 文本。
  • 匹配:默认大小写不敏感子串(CJK 天然正确,无分词依赖);多词 AND(双引号短语保留内部空格、至多 16 词);正则模式下整个查询是一个模式、不拆词。
  • 拼音(默认开,pinyin 可关):纯字母词同时按拼音匹配汉字——全拼(zhangsan → 张三)、默认读音链(zhongqing → 重庆)、首字母(zs → 张三、bjdx → 北京大学,一个字母对一个字、可跨词连续);全拼从音节起点匹配(不会把上一音节的尾字母接到下一字首字母),首字母则按你打字的样子连续拼接;多音字按全部读音参与、ü 按键盘习惯写作 v;内置 3500 常用字读音表,表外字按自身折叠;正则模式不扩展拼音。
  • 标题限定Alt+N 即时切换):只匹配会话标题、消息正文不参与——适合"找那个会话";无标题会话不命中。
  • 默认范围:本仓库(按会话 cwd 匹配当前工作目录,与 resume 浏览器同语义,含子目录会话)。

配置

cordis.patch.yml 的插件行上覆盖(全部可选):

- insert:
    - id: dsh-tui-find
      name: 'dsh-tui-find'
      defaultScope: 'all'        # 初始范围:repo(默认) | all
      defaultTime: 'all'         # 初始时间窗口:all(默认) | 7d | 30d
      layout: 'split'            # 界面布局:split(默认,左列表+右阅读窗,需≥100列) | classic(单栏+全屏预览)
      caseSensitive: false       # 大小写敏感匹配(默认关)
      regex: false               # 默认启用正则匹配(默认关;场景内 Alt+R 即时切换)
      pinyin: true               # 拼音搜索(默认开;纯字母词同时按全拼/首字母匹配汉字)
      titleOnly: false           # 仅搜索标题(默认关;场景内 Alt+N 即时切换)
      indexTools: false          # 索引工具调用摘要(默认关)
      indexThinking: false       # 索引 thinking 文本(默认关)
      sessionRoot: ''            # 手动指定会话根目录(默认自动探测)
      maxMessageChars: 4000      # 单条消息索引字符上限
      warmup: true               # 后台预热索引(默认开;关闭后 /find 打开时才扫描)
      lang: 'auto'               # zh | en | auto(跟随宿主语言)
      shortcut: 'alt+f'          # 全局入口组合键(必须含 ctrl 或 alt;'off' 关闭全局入口)

lang 外的选项都可以在 TUI 内直接改:/settingsdsh-tui-find(会话搜索) 卡片。布尔/选择项一改即存,文本项回车确认,写入宿主设置服务的用户层并按层级覆盖插件行默认值;卡片文案跟随 TUI 语言。

lang: auto 跟随 dsh-TUI 语言链:DSH_TUI_LANG~/.dsh-tui/lang.json → 系统 locale → 中文,/lang 切换即时生效。

会话根目录按序探测(首个命中即用):sessionRoot 配置(排他覆盖)→ DSH_TUI_SESSION_ROOT 环境变量 → $DSH_HOME || ~/.dsh + /sessions~/.dsh-tui/sessions

隐私与安全

  • 全程只读:只读打开会话日志,不触碰 history lock,不改写历史。
  • 世代命名:dsh 的会话日志按格式世代命名(session.jsonlsession.vN.jsonl,各有 .zstd 压缩变体)。同一会话目录取编号最高的世代、同世代内压缩版优先——迁移窗口里并存的旧世代日志不会被索引。
  • 落盘最小化:对话内容只存内存、绝不落盘。唯一例外是水位日志 ~/.dsh-tui/dsh-tui-find/watermark.json——仅记录路径与字节/修改时间/偏移等元数据、绝无对话文本(0700/0600 + tmp+rename 原子写,DSH_TUI_FIND_WATERMARK=off 可关)。
  • 增量解码与容错:追加只解新增帧、同尺寸触碰零解码,缩水/改写/编码翻转自动回退全量;不完整尾帧按 RFC 8878 结构校验跳过,不崩溃、不残留。
  • 恢复需确认:恢复是丢弃当前上下文的破坏性切换, 二次确认,当前会话工作中给醒目警告。

开发

npm install          # 开发依赖
npm run build        # tsc → dist/
npm test             # pretest 自动构建并生成 fixture,vitest 全量
npm run verify:hosts # 双宿主矩阵:隔离副本换宿主包,0.9.3 与 0.10.1 各跑一次 build+test

测试覆盖(353 项):帧链解析、扫描器(mtime 缓存复用、水位增量解码、世代命名枚举)、搜索(多词 AND / 正则 / 拼音含跨词首字母 / 标题限定 / 时间窗 / 范围过滤)、折叠构建与冻结旧实现的逐字段等价对照、折叠的内存表示(缓存的是扁平串而不是逐码点拼接出来的 ConsString 绳,按保留堆断言)、预览阅读器(含命中落点开窗、输入即重定位、无光标逐行滚动、窗口基准的 n/N、Alt+C 的当前命中选取与提示行按宽度取词且严格一行)、键位帮助(按布局取词、鼠标折叠徽标)、场景接线(真实宿主渲染器 + SGR 鼠标注入与右键派发,含 split 分栏布局、←/→ 焦点移交、选择锚定、宽度回退、滚轮步幅、徽标折叠不触发恢复与折叠后悬停不落到邻卡)、宿主代际分派、事件清洗、显示宽度、准入与真实 fiber 挂载、启动竞态防护、后台预热索引(预算/中止/缓存键形状/表下界)与 tuiStatus 进度视图。

环境要求

  • dsh-TUI v0.9+(v0.15 community-draft 插件体系)。0.9.x 与 0.10.x 双版本验证(npm run verify:hosts);0.10-only 能力一律软探测 + 优雅降级,不强制升级宿主
  • Node ^22.19 || >=24;Windows / macOS / Linux

许可

MIT