Skip to content

Add inline chat search and Spotlight global search#1419

Merged
zerob13 merged 8 commits intodevfrom
copilot/add-chat-search-functionality
Apr 2, 2026
Merged

Add inline chat search and Spotlight global search#1419
zerob13 merged 8 commits intodevfrom
copilot/add-chat-search-functionality

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 1, 2026

close #1417

This PR expands the original lightweight search work into two complementary search flows: inline search inside the active conversation, plus an app-level Spotlight overlay for fast global navigation across sessions, messages, agents, settings, and safe actions.

  • Current chat inline search

    • Adds a compact floating search bar in ChatPage
    • Opens with Ctrl/Cmd+F
    • Highlights matches directly in rendered message content
    • Shows running match count (current / total)
    • Supports Enter / Shift+Enter for next/previous match
    • Closes with Esc
  • DOM-scoped message highlighting

    • Adds a focused chatSearch utility to:
      • scan only message content
      • inject/remove highlight marks safely
      • track and scroll the active match
    • Keeps search scoped to chat body text instead of top bar/input chrome
  • Sidebar history search

    • Adds inline title filtering to WindowSideBar
    • Filters both pinned and grouped sessions in place
    • Highlights matching substrings inside WindowSideBarSessionItem
    • Adds search-specific empty-state copy
  • Spotlight global search

    • Adds a top-level Spotlight overlay in the main chat window
    • Opens with configurable QuickSearch shortcut, defaulting to Cmd/Ctrl+P
    • Adds a persistent Spotlight entry in the left rail
    • Auto-focuses the input on open and supports Esc, ↑/↓, Home/End, Enter, hover, and click interactions
    • Shows recent sessions, agents, and actions for empty queries
    • Shows a unified mixed result list for sessions, messages, agents, settings, and actions for non-empty queries
  • History search integration

    • Adds INewAgentPresenter.searchHistory(query, options?)
    • Returns typed session/message hits for Spotlight
    • Searches persisted session titles and message content from the new-agent session store
    • Builds snippets for message hits and ranks title matches ahead of body matches
  • Settings and shortcut integration

    • Adds SHORTCUT_EVENTS.TOGGLE_SPOTLIGHT
    • Adds QuickSearch to shortcut settings and exposes it in the settings UI
    • Extracts shared settings navigation metadata so the settings window sidebar and Spotlight consume the same route registry
  • Cross-surface result execution

    • session hits activate the matched session
    • message hits activate the matched session, then scroll to and temporarily highlight the target message after load
    • agent hits reuse existing agent switching flow
    • setting hits open/focus the settings window and navigate to the matched page
    • action hits support non-destructive shortcuts such as New Chat, Open Settings, and direct entries for Providers, Agents, MCP, Remote, and Shortcuts
  • Localization and test coverage

    • Adds the new Spotlight and shortcut copy to chat/settings locale files
    • Extends main and renderer coverage for:
      • inline chat search behavior
      • sidebar filtering and title highlighting
      • history search result shaping
      • Spotlight entry points and message jump behavior
  • Example

    if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === 'f') {
      event.preventDefault()
      openChatSearch()
      return
    }
    
    if (event.key === 'Enter') {
      event.preventDefault()
      event.shiftKey ? goToPreviousChatSearchMatch() : goToNextChatSearchMatch()
    }
    
    window.electron.ipcRenderer.on(SHORTCUT_EVENTS.TOGGLE_SPOTLIGHT, () => {
      spotlightStore.toggleSpotlight()
    })
  • **

Original prompt

你在一个 Electron 桌面聊天应用中设计并实现一个搜索功能,目标是提升用户在聊天内容和历史聊天中的检索效率,且整体体验要符合现有设计风格,做到“丝滑、细腻、清爽”。

背景需求

参考 issue:#1417

用户希望:

  1. 在当前打开的聊天中可以快速搜索内容,最好支持类似 Ctrl+F 的原生体验。
  1. 在历史聊天列表中可以搜索聊天标题,必要时也可以扩展到摘要或消息内容。
  1. 交互要轻量、自然,不要做成重型搜索页。
  1. 视觉上要和现有产品风格一致:简洁、克制、现代、柔和、细腻。

设计目标

• 当前聊天搜索应优先支持:

• Ctrl+F 打开搜索框

• 实时高亮匹配结果

• Enter / Shift+Enter 跳转上下一个结果

• Esc 关闭搜索

• 显示命中数量,例如 3 / 12

Copilot AI and others added 2 commits April 1, 2026 00:56
Agent-Logs-Url: https://github.com/ThinkInAIXYZ/deepchat/sessions/03e6c597-17cc-43b2-b07e-9690c5828beb

Co-authored-by: zhangmo8 <43628500+zhangmo8@users.noreply.github.com>
Agent-Logs-Url: https://github.com/ThinkInAIXYZ/deepchat/sessions/03e6c597-17cc-43b2-b07e-9690c5828beb

Co-authored-by: zhangmo8 <43628500+zhangmo8@users.noreply.github.com>
Copilot AI changed the title [WIP] Add search functionality for chat messages and history Add lightweight inline search for current chat and chat history titles Apr 1, 2026
Copilot AI requested a review from zhangmo8 April 1, 2026 01:00
@zerob13
Copy link
Copy Markdown
Collaborator

zerob13 commented Apr 1, 2026

我补充一个 plan,可以参考做做,既然这次要做搜索,我们可以考虑做的完整一点

DeepChat 内置 Spotlight 全局搜索方案

Summary

  • 目标是做一个单实例、App 级、Raycast 风格的命令面板:Cmd/Ctrl+F 全局唤起,统一搜索会话标题、历史消息、Agent、设置页面和少量非破坏性动作。
  • 视觉语言沿用现有侧边栏/欢迎页的半透明卡片风格:rounded-2xl + border + bg-card/40 + backdrop-blur,不引入新视觉系统。
  • 首版设置搜索只覆盖“设置页面”,不下钻具体开关;动作只做非破坏性动作,避免误触。
  • 先在 docs/specs/app-spotlight-search/spec.mdplan.mdtasks.md,再进入代码实现。
主窗口
┌──────────── 左侧 rail ────────────┬──────────────────────────────┐
│ ○ All Agents                     │                              │
│ ◉ DeepChat                       │                              │
│ ◎ Claude Code                    │                              │
│                                   │                              │
│ 🔍 Spotlight                     │   Chat / New Thread / ...    │
│ ⇆ Collapse                       │                              │
│ … Settings                       │                              │
└───────────────────────────────────┴──────────────────────────────┘

Spotlight overlay
╭──────────────────────────────────────────────────────────────────╮
│ 🔎 Search chats, messages, agents, settings, actions…      ⌘F  │
│──────────────────────────────────────────────────────────────────│
│ › 💬 Release checklist                             Session      │
│   Claude Code · 2h ago · /deepchat                              │
│   ≡ "pnpm run build still fails on arm64..."     Message      │
│   in Release checklist · assistant · 2h ago                    │
│   🤖 Claude Code                                  Agent        │
│   ⚙ Shortcuts                                    Setting      │
│   ⌁ New Chat                                     Action       │
│──────────────────────────────────────────────────────────────────│
│ ↑↓ move   Enter open   Esc close   Click works   Hover follows │
╰──────────────────────────────────────────────────────────────────╯

UX & Interaction

  • Cmd/Ctrl+F 由主进程全局快捷键接管,并新增为可配置快捷键项 QuickSearch;鼠标入口放在左侧 rail,常驻可见。
  • 面板为 App 顶层 modal overlay,打开时自动聚焦输入框;Esc 关闭,↑/↓ 移动,Home/End 跳首尾,Enter 执行当前项,鼠标 hover 同步高亮,click 执行。
  • 空查询展示 Recent Sessions + Agents + Actions;有查询时展示一条统一结果列表,用 kind pill 标记 Session / Message / Agent / Setting / Action,不做多段重复分组,保证键盘移动稳定。
  • session 命中切到该会话;message 命中切到该会话,待消息加载完成后滚动到目标消息并高亮 2 秒。
  • agent 命中复用现有侧栏切换逻辑;setting 命中打开/聚焦设置窗口并导航到对应页面;action 只执行非破坏性动作,首版包含 New ChatOpen Settings 和到 Providers / Agents / MCP / Shortcuts 的快捷入口。
  • 搜索范围默认忽略当前 sidebar 的 agent 过滤,始终在“全量历史 + 全量导航项”里搜索。

Implementation Changes

  • 主进程新增可复用历史搜索服务,抽离当前 conversation search 的“消息正文提取 + snippet 生成”逻辑,给 MCP 和 UI 共用,避免两套规则漂移。
  • 历史搜索默认走 SQLite FTS5:新增 deepchat_search_documents 普通表存 entity_kind / entity_id / session_id / title / body / role / updated_at,再建 deepchat_search_documents_fts 虚表做全文索引。
  • 首次启动或 schema 变更时,从现有 new_sessions + deepchat_messages 全量回填;此后在“会话创建/重命名/删除、消息写入/编辑/删除、历史导入”路径增量同步。
  • FTS 查询失败或当前 query 无法被 tokenizer 正常处理时,自动降级到同一份 deepchat_search_documents 上的 LIKE 查询,保证“任意字符都能出结果”。
  • 历史索引只收录用户可见文本:用户消息取 text,助手消息取可见内容块和错误文本,不索引工具调用原始 JSON、图片元数据和未持久化的流式内容。
  • 渲染层新增 spotlight store 管理 open/query/results/activeIndex/loading/pendingMessageJump/requestSeq,输入 80ms debounce,请求按序号丢弃过期响应,结果最多渲染 12 条。
  • 设置页搜索不散落硬编码:把设置导航元数据抽成一份共享 registry,设置窗口路由和 Spotlight 同时消费;Spotlight 只读页面级条目。
  • 结果排序统一在 renderer 合并完成:标题前缀命中 > 名称前缀命中 > 正文命中,session 略高于 message,再叠加轻量 recency boost。
  • 消息跳转通过 pendingMessageJump 串起来:执行 message 结果后先记目标,Chat 页在 session 激活并加载消息完成后再消费,成功滚动后清空。

Public APIs / Types

  • 新增 INewAgentPresenter.searchHistory(query, options?),只返回聊天数据的 union results:session hit | message hit
  • 新增共享类型:HistorySearchHitHistorySearchSessionHitHistorySearchMessageHitHistorySearchOptions;renderer 本地再补 SpotlightItemagent | setting | action
  • 新增快捷键配置项 QuickSearch 和事件 SHORTCUT_EVENTS.TOGGLE_SPOTLIGHT,默认值为 CommandOrControl+F
  • 新增共享设置导航 registry,字段固定为 routeName / titleKey / icon / keywords[]

Test Plan

  • Main tests 覆盖:session title hit 与 message hit 的排序、会话重命名/消息编辑删除后的索引同步、legacy import 后的回填、FTS 失败时自动降级到 LIKE
  • Renderer tests 覆盖:Cmd/Ctrl+F 打开关闭、输入框自动聚焦、Esc/↑/↓/Enter 全链路、统一结果列表混排与去重、message 结果切会话后滚动高亮、agent/setting/action 执行行为、hover 与 click 不破坏键盘 active item。
  • 验收场景:空查询有 recent/agents/actions;sidebar 收起时仍可用;设置窗口获得焦点时按 Cmd/Ctrl+F,会聚焦主聊天窗口并打开同一个 Spotlight。

Assumptions

  • v1 只做一个 Spotlight 实例,挂在主聊天窗口,不在设置窗口内再做第二套 UI。
  • v1 不做 prefix scopes(如 >@#)、不做具体设置开关级搜索,也不提供 destructive actions。
  • v1 搜索“历史消息”仅覆盖已持久化内容,不覆盖正在 streaming 但尚未落库的临时内容。
  • 动效保持轻量,并统一尊重 prefers-reduced-motion

Copy link
Copy Markdown
Collaborator

@zhangmo8 zhangmo8 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

除了当前的task内搜索,还想实现一个全局索引快速跳转

Summary

目标是做一个单实例、App 级、Raycast 风格的命令面板:Cmd/Ctrl+P 全局唤起,希望可以设置该快捷键,基于之前快捷键设置的实现进行扩展

主要功能统一搜索会话标题、历史消息、Agent、设置页面和少量非破坏性动作。
视觉语言沿用现有侧边栏/欢迎页的半透明卡片风格:rounded-2xl + border + bg-card/40 + backdrop-blur,不引入新视觉系统。
首版设置搜索只覆盖“设置页面”,不下钻具体开关;动作只做非破坏性动作,避免误触。
先在 docs/specs/app-spotlight-search/ 补 spec.md、plan.md、tasks.md,再进入代码实现。
主窗口
┌──────────── 左侧 rail ────────────┬──────────────────────────────┐
│ ○ All Agents │ │
│ ◉ DeepChat │ │
│ ◎ Claude Code │ │
│ │ │
│ 🔍 Spotlight │ Chat / New Thread / ... │
│ ⇆ Collapse │ │
│ … Settings │ │
└───────────────────────────────────┴──────────────────────────────┘

Spotlight overlay
╭──────────────────────────────────────────────────────────────────╮
│ 🔎 Search chats, messages, agents, settings, actions… ⌘F │
│──────────────────────────────────────────────────────────────────│
│ › 💬 Release checklist Session │
│ Claude Code · 2h ago · /deepchat │
│ ≡ "pnpm run build still fails on arm64..." Message │
│ in Release checklist · assistant · 2h ago │
│ 🤖 Claude Code Agent │
│ ⚙ Shortcuts Setting │
│ ⌁ New Chat Action │
│──────────────────────────────────────────────────────────────────│
│ ↑↓ move Enter open Esc close Click works Hover follows │
╰──────────────────────────────────────────────────────────────────╯
UX & Interaction

Cmd/Ctrl+F 由主进程全局快捷键接管,并新增为可配置快捷键项 QuickSearch;鼠标入口放在左侧 rail,常驻可见。
面板为 App 顶层 modal overlay,打开时自动聚焦输入框;Esc 关闭,↑/↓ 移动,Home/End 跳首尾,Enter 执行当前项,鼠标 hover 同步高亮,click 执行。
空查询展示 Recent Sessions + Agents + Actions;有查询时展示一条统一结果列表,用 kind pill 标记 Session / Message / Agent / Setting / Action,不做多段重复分组,保证键盘移动稳定。
session 命中切到该会话;message 命中切到该会话,待消息加载完成后滚动到目标消息并高亮 2 秒。
agent 命中复用现有侧栏切换逻辑;setting 命中打开/聚焦设置窗口并导航到对应页面;action 只执行非破坏性动作,首版包含 New Chat、Open Settings 和到 Providers / Agents / MCP / Shortcuts 的快捷入口。
搜索范围默认忽略当前 sidebar 的 agent 过滤,始终在“全量历史 + 全量导航项”里搜索。
Implementation Changes

主进程新增可复用历史搜索服务,抽离当前 conversation search 的“消息正文提取 + snippet 生成”逻辑,给 MCP 和 UI 共用,避免两套规则漂移。
历史搜索默认走 SQLite FTS5:新增 deepchat_search_documents 普通表存 entity_kind / entity_id / session_id / title / body / role / updated_at,再建 deepchat_search_documents_fts 虚表做全文索引。
首次启动或 schema 变更时,从现有 new_sessions + deepchat_messages 全量回填;此后在“会话创建/重命名/删除、消息写入/编辑/删除、历史导入”路径增量同步。
FTS 查询失败或当前 query 无法被 tokenizer 正常处理时,自动降级到同一份 deepchat_search_documents 上的 LIKE 查询,保证“任意字符都能出结果”。
历史索引只收录用户可见文本:用户消息取 text,助手消息取可见内容块和错误文本,不索引工具调用原始 JSON、图片元数据和未持久化的流式内容。
渲染层新增 spotlight store 管理 open/query/results/activeIndex/loading/pendingMessageJump/requestSeq,输入 80ms debounce,请求按序号丢弃过期响应,结果最多渲染 12 条。
设置页搜索不散落硬编码:把设置导航元数据抽成一份共享 registry,设置窗口路由和 Spotlight 同时消费;Spotlight 只读页面级条目。
结果排序统一在 renderer 合并完成:标题前缀命中 > 名称前缀命中 > 正文命中,session 略高于 message,再叠加轻量 recency boost。
消息跳转通过 pendingMessageJump 串起来:执行 message 结果后先记目标,Chat 页在 session 激活并加载消息完成后再消费,成功滚动后清空。
Public APIs / Types

新增 INewAgentPresenter.searchHistory(query, options?),只返回聊天数据的 union results:session hit | message hit。
新增共享类型:HistorySearchHit、HistorySearchSessionHit、HistorySearchMessageHit、HistorySearchOptions;renderer 本地再补 SpotlightItem 的 agent | setting | action。
新增快捷键配置项 QuickSearch 和事件 SHORTCUT_EVENTS.TOGGLE_SPOTLIGHT,默认值为 CommandOrControl+F。
新增共享设置导航 registry,字段固定为 routeName / titleKey / icon / keywords[]。
Test Plan

Main tests 覆盖:session title hit 与 message hit 的排序、会话重命名/消息编辑删除后的索引同步、legacy import 后的回填、FTS 失败时自动降级到 LIKE。
Renderer tests 覆盖:Cmd/Ctrl+F 打开关闭、输入框自动聚焦、Esc/↑/↓/Enter 全链路、统一结果列表混排与去重、message 结果切会话后滚动高亮、agent/setting/action 执行行为、hover 与 click 不破坏键盘 active item。
验收场景:空查询有 recent/agents/actions;sidebar 收起时仍可用;设置窗口获得焦点时按 Cmd/Ctrl+F,会聚焦主聊天窗口并打开同一个 Spotlight。
Assumptions

v1 只做一个 Spotlight 实例,挂在主聊天窗口,不在设置窗口内再做第二套 UI。
v1 不做 prefix scopes(如 >、@、#)、不做具体设置开关级搜索,也不提供 destructive actions。
v1 搜索“历史消息”仅覆盖已持久化内容,不覆盖正在 streaming 但尚未落库的临时内容。
动效保持轻量,并统一尊重 prefers-reduced-motion。

Agent-Logs-Url: https://github.com/ThinkInAIXYZ/deepchat/sessions/c50314d6-15fd-4335-b969-aab75fd62c4b

Co-authored-by: zhangmo8 <43628500+zhangmo8@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 1, 2026

我补充一个 plan,可以参考做做,既然这次要做搜索,我们可以考虑做的完整一点

DeepChat 内置 Spotlight 全局搜索方案

...

已在 5e3ea2d 补上 docs/specs/app-spotlight-search/spec.mdplan.mdtasks.md,把 Spotlight 的范围、索引方案、事件流、跳转时序和测试拆分先落成了可审阅规格。为了避免和已实现的会话内搜索冲突,规格里先定为保留 Cmd/Ctrl+F 给 inline search,Spotlight 的 QuickSearch 默认改为 Cmd/Ctrl+P。UI 参考图:https://github.com/user-attachments/assets/c73269c3-beeb-40a7-ac78-fa4061cfb483

除了当前的task内搜索,还想实现一个全局索引快速跳转

Summary...

已在 5e3ea2d 先按 SDD 补齐 docs/specs/app-spotlight-search/ 下的 spec.mdplan.mdtasks.md,把全局索引快速跳转拆成快捷键、历史索引、共享类型、setting registry、Spotlight store、消息跳转和测试几个阶段。规格里也先收敛了快捷键冲突:保留当前会话内搜索的 Cmd/Ctrl+F,Spotlight 的 QuickSearch 默认设为 Cmd/Ctrl+P,后续再基于快捷键设置页开放自定义。UI 参考图:https://github.com/user-attachments/assets/c73269c3-beeb-40a7-ac78-fa4061cfb483

Copilot AI requested a review from zhangmo8 April 1, 2026 07:59
Copy link
Copy Markdown
Collaborator

@zhangmo8 zhangmo8 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

帮我按照文档完成spotlight search spec 的功能

Copilot AI and others added 2 commits April 1, 2026 09:22
Agent-Logs-Url: https://github.com/ThinkInAIXYZ/deepchat/sessions/d4d03af1-949d-45cf-aad8-257e96a2cf3f

Co-authored-by: zhangmo8 <43628500+zhangmo8@users.noreply.github.com>
Agent-Logs-Url: https://github.com/ThinkInAIXYZ/deepchat/sessions/d4d03af1-949d-45cf-aad8-257e96a2cf3f

Co-authored-by: zhangmo8 <43628500+zhangmo8@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 1, 2026

帮我按照文档完成spotlight search spec 的功能

已按 docs/specs/app-spotlight-search/ 把 Spotlight 主链路实现到这条分支里,并在 143e9c8 做了最后一轮收口:包含 QuickSearch 快捷键、主窗口 Spotlight overlay、历史会话/消息搜索、settings shared registry、sidebar 入口,以及 message hit 切会话后的滚动高亮。当前环境因为 cdn.sheetjs.com 不可达,没法在本地装齐依赖去跑完整 lint/typecheck/test,但代码 review 已做过一轮修正,CodeQL 也没有给出可修复告警。截图参考:https://github.com/user-attachments/assets/c73269c3-beeb-40a7-ac78-fa4061cfb483

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • cdn.sheetjs.com
    • Triggering command: /home/REDACTED/work/_temp/ghcca-node/node/bin/node node /home/REDACTED/work/_temp/ghcca-node/node/bin/corepack pnpm install (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI changed the title Add lightweight inline search for current chat and chat history titles Add inline chat search and Spotlight global search Apr 1, 2026
Copilot AI requested a review from zhangmo8 April 1, 2026 09:34
@zhangmo8 zhangmo8 marked this pull request as ready for review April 2, 2026 03:18
@zerob13 zerob13 merged commit 0ed5d8f into dev Apr 2, 2026
2 checks passed
@zhangmo8 zhangmo8 deleted the copilot/add-chat-search-functionality branch April 2, 2026 11:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] Search within a chat and among chats

3 participants