본문으로 건너뛰기
P

dsh-chat-search

p-ppj/dsh-chat-search

Find text inside the open conversation with Ctrl+F: matches are highlighted in the message text, previous/next step through them, clicking the count lists the matches and jumps to any of them, and the count grows while the scan runs. No collapsed block is opened and the reading position does not move.

설치

dsh plugin --profile web add github:p-ppj/dsh-chat-search

README

DeepSeek Harness 的对话内搜索插件。 按 Ctrl+F 就能在当前对话里查找关键词:正文高亮、上一个/下一个、命中位置列表,计数边搜边涨——而且不展开任何折叠块,不改变你正在看的位置。

English | 简体中文

搜索面板

命中位置列表

图为插件面板的界面预览(用插件自己的样式表渲染),不含任何真实对话内容。

为什么还要一个

Harness 本身没有对话内查找,Ctrl+F 交给浏览器后什么也不会发生;插件市场里的同类插件装上却用不了,因为它定位聊天内容靠的是 data-chat-anchor-key、data-chat-node-key、data-chat-turn 这类属性——这些属性在 0.2.x 的会话视图里已经不存在了(现在只有 data-conversation-region、data-conversation-scroll、data-conversation-session)。锚点找不到,跳转就永远是空的。

这个插件按现在的 DOM 契约重写,顺手把「搜索时的打扰感」也一起去掉了:

浏览器原生查找老插件本插件
只在对话里搜(不含输入框/侧栏)❌✅✅
正文高亮❌只闪整条消息✅ 按字符高亮
上一个 / 下一个❌✅✅
不展开折叠块、不移动阅读位置—❌ 会展开全部✅
计数随扫描实时增长—❌ 一次性阻塞✅
首个命中就在你附近—❌ 从对话最顶上开始✅
中文输入法合成时不误搜—❌✅
点击面板外不关闭—❌ 点就关✅

功能

  • Ctrl+F 随时唤起——包括光标停在输入框里的时候(不再弹浏览器原生查找栏);已经打开时再按一次 = 聚焦并全选。
  • 边搜边涨的计数:扫描分片进行(每帧约 900 个节点 / 8ms),长对话也不会把界面卡住,数字一路往上走。
  • 正文高亮:用 CSS Custom Highlight API 画 Range,不往 React 的 DOM 里插 <mark>,所以不会触发重排、不会和宿主抢节点。
  • 上一个 / 下一个:Enter / Shift+Enter,到尽头自动回绕。
  • 首个命中 = 离你最近的那处:以当前视口顶部为锚,从近到远找第一个匹配,只有不可见时才滚动,且只滚到"刚好看得见"。
  • 命中位置列表:点击计数展开全部命中(最多 300 条),每条带片段,命中词标蓝,点哪条跳哪条。
  • 回到搜索前的位置:跳走之后点 ⟲,一键回到开始搜索时的阅读位置(锚的是元素而不是滚动像素,所以中途加载历史也不会偏)。
  • 不打扰:不展开折叠块、不改动对话内容;点面板空白处、点聊天区都不会关;Esc 才关,并且把焦点还给打开前的元素。
  • 顺手补历史:开头会按需加载更早的消息(最多 80 页 / 12 秒),加载不完会在面板里说明"只搜索了已加载的部分"。
  • 跟随主题:只用 --dsw-alias-* 主题 token,明暗主题自动适配。

快捷键

按键作用
Ctrl+F / Cmd+F打开搜索;已打开则聚焦并全选
Enter / ↓ 按钮下一个命中
Shift+Enter / ↑ 按钮上一个命中
Esc退出搜索,焦点还回原处
点击 3/58展开 / 收起命中位置列表

安装

需要 DeepSeek Harness 桌面版(0.2.x)。装完刷新页面即可生效,不用重启应用。

方式 A:插件安装器(推荐 .tgz 直链或本地文件——不需要 Git)

对话框里的「安装源:中国大陆镜像源」只改写 npm 包名的请求。填 GitHub 地址或 .tgz 直链时它不参与,必须本机自己连得上。

不需要 Git 的三种填法,挑一条通得过的即可:

https://github.com/P-PPJ/dsh-chat-search/releases/download/v1.0.1/dsh-chat-search-1.0.1.tgz
https://cdn.jsdelivr.net/gh/P-PPJ/dsh-chat-search@main/dist/dsh-chat-search-1.0.1.tgz
D:\某个目录\dsh-chat-search-1.0.1.tgz        ← 本地文件,连网络都不用

填仓库地址(https://github.com/owner/repo)则需要本机装过 Git。 安装器会把这种地址当 git 依赖,用 git ls-remote 去解析;Windows 不自带 Git,没装就必然报这一条:

[ERR_PNPM_GIT_RESOLVE_FAILED] Failed to resolve git dependency "https://github.com/...":
git ls-remote failed: 'git' 不是内部或外部命令,也不是可运行的程序或批处理文件。

看到这句,要么把地址换成上面的 .tgz,要么先装 Git for Windows(winget install Git.Git)再重试。这条报错和网络无关,和仓库里放了什么也无关。

安装报错对照

报错真正原因怎么办
'git' 不是内部或外部命令 / ERR_PNPM_GIT_RESOLVE_FAILED填了仓库地址,但本机没有 Git改用 .tgz 直链或本地文件;或装 Git
无法连接 github.com / ETIMEDOUT / ECONNRESET本机到 GitHub 的线路不通或不稳见下方「中国大陆网络下载不动 .tgz」:套加速前缀,或交给本地文件
卡在 allowBuilds 提示某个依赖带安装脚本,被 pnpm 拦下本插件零依赖、零安装脚本,不会出现

⚠️ 中国大陆无代理实测:GitHub Release 直链 20 秒后连接被重置(会重定向到 objects.githubusercontent.com);cdn.jsdelivr.net 时通时断——同一条链接有时 1 秒下载完,也可能 25 秒超时。安装器对 GitHub 地址和 .tgz 直链不走任何镜像源,所以这两条在国内并不算稳,报错文案是「无法连接 github.com……需要本机能直接访问它或配置代理」。

四种装法(Release tarball、git+ 地址、github: 简写、CDN tarball)都用 Harness 自带的 pnpm 11 实测过:能连上时 exit=0、装出来版本 1.0.1 —— 包本身没有问题:失败要么是本机没有 Git,要么是线路不通,两者都在本机一侧。

中国大陆网络下载不动 .tgz 怎么办

Release 直链会 302 到 objects.githubusercontent.com,国内常见 ECONNRESET。可以给地址套一个加速前缀——规则就是「镜像前缀 + 完整 GitHub 地址」,装的是同一份字节(sha256 51af9c1c…):

https://ghfast.top/https://github.com/P-PPJ/dsh-chat-search/releases/download/v1.0.1/dsh-chat-search-1.0.1.tgz
https://gh-proxy.com/https://github.com/P-PPJ/dsh-chat-search/releases/download/v1.0.1/dsh-chat-search-1.0.1.tgz
https://ghproxy.net/https://github.com/P-PPJ/dsh-chat-search/releases/download/v1.0.1/dsh-chat-search-1.0.1.tgz

实测(无代理):ghfast.top 4.0 秒、gh-proxy.com 4.2 秒、ghproxy.net 9.6 秒;用第一条地址跑 pnpm add 4.6 秒装出 1.0.1,文件校验和与官方一致。

这些是第三方公共镜像,可用性不由本项目保证;嫌麻烦就把 .tgz 下载下来,改用本地路径装(完全不联网)。

方式 B:放进 profile(本地开发也走这条)

git clone https://github.com/P-PPJ/dsh-chat-search.git

然后在 profile 的 package.json(%USERPROFILE%\.dsh\profiles\<profile>\package.json)里加一条依赖和一条 bundle:

{
  "dependencies": {
    "dsh-chat-search": "file:D:/path/to/dsh-chat-search"
  },
  "dsh": {
    "profile": {
      "bundles": ["...", "dsh-chat-search"]
    }
  }
}

再让 Harness 装一次依赖(下次启动会自动装;也可以在该目录执行 pnpm install),刷新页面。

方式 C:Release 预构建包(插件市场装的就是这个)

https://github.com/P-PPJ/dsh-chat-search/releases/download/v1.0.1/dsh-chat-search-1.0.1.tgz

把它交给插件安装器即可,不经过源码构建、不需要 allowBuilds 授权。

已收录进社区目录:插件 → 市场 里搜 dsh-chat-search 就能找到(条目是 awesome-dsh-plugin 的 PR #10155,账号改名为 P-PPJ 后由 PR #11623 更新地址)。目录只收精选条目,所以本仓库按它的要求整理过:package.json 里有 dsh.bundle、根目录有 screenshots.json、assets/ 下是位图图标、Release 上有预构建 tarball。

⚠️ 与同名旧插件冲突:社区里另一个也叫 dsh-chat-search 的包(helo060228/dsh-chat-search)用的是同一个包名。装本插件前请先把旧的那条依赖和 bundle 删掉,否则 npm 会直接覆盖,且两个 bundle 会在同一个 overlay 槽里抢 Ctrl+F。

它怎么工作

  1. 找到对话:[data-conversation-region="chat"] 就是聊天区,滚动容器是 [data-conversation-scroll];[data-conversation-region="composer"](输入框那一块在 chat region 里面)整个剪掉,所以搜不到自己正在写的字。
  2. 把文本拼成块:手写一个走树的 walker,把文本节点按"最近的非行内祖先"分组拼成字符串——所以短语即使跨了 <code>、<span>、加粗,也能整句命中;script/style/svg/hidden 一律跳过。
  3. 分片扫描:walker 每帧只走约 900 个节点或 8ms,匹配结果攒够一批再交给界面,计数因此是"涨"出来的而不是等出来的。
  4. 高亮:每个命中造一个 Range,丢进 CSS.highlights(全部命中一个集合、当前命中另一个集合,优先级更高),配色写在组件内的 <style> 里。
  5. 定位:用 elementFromPoint 取视口顶部那块节点当锚,compareDocumentPosition 找到第一个"在锚之后"的命中;滚动时由外到内逐个滚动容器校正,只做最小位移。
  6. 输入法:compositionstart/end + isComposing + keyCode 229 三重判断,合成期间不搜索、不响应 Enter/Esc,落字之后才搜一次。

限制(都是有意为之)

  • 折叠块里的文字搜不到:Tool 调用、思考过程、被折叠的长输出都是条件渲染,内容根本不在 DOM 里。想要搜到它们只能先点开——而这正好会改变你的阅读位置,与"无痕"冲突,所以不做。需要的话可以后续加一个默认关闭的「包含折叠内容」开关。
  • 命中上限 3000、染色上限 1200、位置列表 300 条(再多也没有意义,读不过来)。
  • 更早的历史最多补 80 页 / 12 秒,超出会显示"只搜索了已加载的部分"。
  • 需要 CSS Custom Highlight API(Chromium 105+,Harness 桌面版满足);不支持时仍能定位跳转,只是不染色。
  • 绑定宿主 DOM 契约:依赖 data-conversation-* 这几个属性。Harness 大版本改了结构就需要更新插件(这也是老插件坏掉的原因)。

想发布自己的 DSH 插件?

仓库根目录还有一份技能 publishing-dsh-plugin/——把这个插件从「本地能跑」推到「别人贴个地址就能装」的完整过程:打包、推 GitHub、写 README、进社区目录,以及对方装不上时怎么一条条查下去。

放进 ~/.dsh/skills/(Windows 是 C:\Users\<你>\.dsh\skills\),新开一个会话就能用:

git clone https://github.com/P-PPJ/dsh-chat-search.git
Copy-Item .\dsh-chat-search\publishing-dsh-plugin "$env:USERPROFILE\.dsh\skills\" -Recurse
文件内容
SKILL.md六道关卡:注册 → 打包 → GitHub → README → 目录 → 安装链路,附交付前检查清单
references/readme-template.md可直接套用的 README 骨架
references/registry-entry.md目录条目字段、分类枚举、纯 API 提 PR、改名后的迁移
references/install-troubleshooting.md报错原文 → 真因 → 解法(含实测数字)

文件结构

client.js         # 全部功能:扫描、高亮、面板(React 组件 + CSS)
index.js          # Host 半,空实现(本插件纯前端)
cordis.patch.yml  # 把 bundle 插进 profile
locale/zh.json    # 插件信息(名称/简介)
locale/en.json
icon.svg
screenshots/      # README 里的界面预览
publishing-dsh-plugin/  # 发布技能(不属于插件本体,不会打进 npm 包)

没有构建步骤、没有第三方依赖:client.js 是一个 window.__ModuleLoader__.load({...}) 的工厂函数,React 从宿主模块表里 require('react') 拿。

开发

  • 改 client.js 后刷新页面就生效(插件以 file: 链接进 profile 时不需要重装)。
  • node --check client.js 做语法检查。
  • 插件通过 ctx.slots.register({ name: 'shell.overlay', id: 'dsh-chat-search', order: 60 }, FindOverlay) 挂到全屏浮层槽位,浮层本身 click-through,只有面板自己接收鼠标事件。

许可证

MIT © P-PPJ

관련 플러그인