Skip to content

sidebar: Improved search — content, archived, closed-ACP, scope alignment, ranking, collapse during search - #58219

Closed
KevinLaveto wants to merge 8 commits into
zed-industries:mainfrom
KevinLaveto:pr/improved-search
Closed

sidebar: Improved search — content, archived, closed-ACP, scope alignment, ranking, collapse during search#58219
KevinLaveto wants to merge 8 commits into
zed-industries:mainfrom
KevinLaveto:pr/improved-search

Conversation

@KevinLaveto

Copy link
Copy Markdown
Contributor

Summary:

A bundle of improvements to the agent thread sidebar's "Search threads…"
filter. Previously it only matched titles. With this PR a query matches
the actual conversation content too, archived threads are reachable from
the same search box, and the result ordering and collapse behaviour
match what you'd expect coming from any cross-document search.

Builds on @dandv's in-thread search bar work in #57231 conceptually:
that PR added search inside a single open thread; this PR adds search
across threads, designed to match the same visible scope so a sidebar
match is always findable in dandv's bar once #57231 lands. See "Credit"
below.

What's in the PR:

  1. Content search — typing in the sidebar filter now also matches
    thread message content, not just titles. Loaded threads are searched
    in memory; unloaded native threads are read from the local thread DB
    on demand. Debounced + cached + cancelable.

  2. Archived in content search — archived threads (normally hidden
    from the sidebar) surface in results when their content matches the
    query, rendered demoted via ThreadItem::archived. New helper
    ThreadMetadataStore::archived_entries_for_main_worktree_path and
    per-group injection in rebuild_contents.

  3. "Search more (closed agent threads)" footer — closed
    external/ACP threads can't be searched from local storage (their
    history lives in the agent). An explicit "Search more" button runs
    a progressive pass: load each one through its agent, search its
    content, and surface matches as they're found, with a live N/M
    progress and a Stop control. Per-agent connections are reused, so
    one connection per agent (not per thread). New
    AgentPanel::load_session_content_for_search performs the headless
    load.

  4. Scope alignment + ranking — the sidebar matched the thread's
    full markdown (including thinking blocks and tool output), but the
    in-thread search bar (agent_ui: Add in-thread search bar #57231) deliberately scans only the visible
    text. A sidebar match in hidden content would open to "0/0" in the
    bar. Now both paths use the same scope via new
    AcpThread::searchable_text and agent::Message::searchable_markdown
    helpers, so cross-thread results are always navigable in-thread.
    Results are also ranked: title/worktree matches first, then content
    matches by hit count, then recency.

  5. "Search more" includes archived — archived external/ACP threads
    are also covered by the on-demand pass, and matches surface through
    the archived injection.

  6. Respect collapse during search — typing a query no longer force-
    loads every group's threads. Clicking the project chevron during a
    search actually folds/unfolds results. Groups whose threads match by
    title or content still show their header so the user can expand to
    reveal the hits.

Credit:

This work builds directly on @dandv's open PR #57231 ("agent_ui: Add
in-thread search bar"):

  • Scope alignment: @dandv's PR defines which thread content is
    "visible / searchable" for the in-thread Find bar (user messages,
    assistant message chunks, tool-call labels; excluding thinking blocks
    and tool output). This PR's AcpThread::searchable_text and
    agent::Message::searchable_markdown mirror that exact scope, so a
    sidebar match is guaranteed to be reachable in his bar once agent_ui: Add in-thread search bar #57231
    lands.
  • Click-through (held back): Clicking a sidebar result and having
    it open his Find bar pre-filled with the same query is a tiny
    follow-up we built but are holding back until agent_ui: Add in-thread search bar #57231 merges (it
    modifies thread_search_bar.rs / thread_view.rs directly). Will
    open it as a small standalone PR after his lands.

Related PRs in this bundle:

Tests:

  • 142 sidebar tests pass (incl. new tests for content search, archived surfacing, project-name match, and collapse-during-search).

Self-Review Checklist:

  • I've reviewed my own diff for quality, security, and reliability
  • Unsafe blocks (if any) have justifying comments — N/A
  • The content is consistent with the UI/UX checklist
  • Tests cover the new/changed behavior
  • Performance impact has been considered and is acceptable — content search is debounced, cached, and run off the main thread; "Search more" is gated behind explicit user action and reuses one connection per agent.

Release Notes:

  • Improved agent thread sidebar search: now matches thread message content (not just titles), surfaces archived threads, ranks results by relevance, makes project folding work during search, and adds a "Search more" footer button that loads closed external/ACP threads on demand for content search.

Extends the sidebar thread filter so a thread surfaces when the query
appears in its conversation, not only in its title. The search scatters
the query across every thread in the list: threads loaded in an agent
panel are searched in-memory via AcpThread::to_markdown (covering
external/ACP threads and unsaved, in-flight content), and unloaded
native threads are loaded from the thread DB on demand. Work runs off
the main thread, is debounced, cached by updated_at, and cancelled when
a newer query supersedes it.

Clicking a content match opens the thread with its in-thread search bar
pre-seeded with the same query (ThreadView::open_search_with_query +
ThreadSearchBar::set_query), so matches are highlighted immediately.

Known gap: closed external/ACP threads are not searched (their history
isn't stored locally); covering them requires loading on demand.
Archived threads are excluded from the normal sidebar list, but when a
content search matches one it now appears inline rendered demoted (via
ThreadItem::archived). Adds ThreadMetadataStore::
archived_entries_for_main_worktree_path so the rebuild can gather
archived threads for a group, and injects content-matched archived
threads into the filtered list.

Closed external/ACP threads are still not covered (no local content
store) — that's the next step.
The cheap content search can't read closed external/ACP threads (their
history lives in the agent, not a local DB). This adds an on-demand
"Search more" pass: a footer button loads each closed ACP thread in an
open project from its agent (reusing the per-agent connection), searches
its content, and surfaces matches progressively, with a live N/M count
and a Stop control. Results merge into the filtered list; a query change
clears them.

Adds AgentPanel::load_session_content_for_search, which loads a session
headlessly (no active-view takeover) for search.
Two fixes to cross-thread content search:

1. Scope: the sidebar matched a thread's full markdown (including
   thinking blocks and tool output), while the in-thread search bar
   only scans visible user/assistant text + tool-call labels. A sidebar
   match in hidden content opened to "0/0" in-thread. Now both the
   loaded-thread and native-DB paths use the same visible scope
   (AcpThread::searchable_text / Message::searchable_markdown), so every
   sidebar match is navigable in-thread and incidental matches disappear.

2. Ranking: filtered results are now ordered title/worktree matches
   first, then content matches by hit count (most relevant first), then
   recency — instead of purely by recency.
Archived external/ACP threads had no path to content search: the cheap
search can't read them (not in the native DB, not loaded), and the
"Search more" pass excluded them. They render through the archived
injection in `rebuild_contents`, which only consulted the cheap
content_matches set. Now:

- `start_closed_acp_search` includes archived threads as candidates
- `has_searchable_closed_acp_threads` doesn't exclude archived ones,
  so the footer button surfaces when only archived ACPs remain
- The archived injection also consults `closed_search_matches`, so a
  match from "Search more" surfaces (demoted) under its group

Also adds a regression test that typing a project name surfaces that
project's threads via workspace-label match.
Typing a query forced every group to load its threads regardless of the
user's collapsed state, so clicking the chevron during search did
nothing. The chevron now actually folds/unfolds results during search.
A header for a collapsed group is still surfaced when one of its threads
matched by content (or by the "Search more" pass), so the group doesn't
silently disappear from search — the user can expand it to see the hits.
@cla-bot cla-bot Bot added the cla-signed The user has signed the Contributor License Agreement label Jun 1, 2026
@zed-community-bot zed-community-bot Bot added the first contribution the author's first pull request to Zed. NOTE: the label application is automated via github actions label Jun 1, 2026

@dinocosta dinocosta left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hey @KevinLaveto ! 🙂

Thank you for working to improve the search experience for the threads sidebar. Since this pull request is fairly large and tackles six concerns at once, as you outlined in its description, I’d consider breaking it into multiple, more focused pull requests.

For a change of this scope, we’d also usually expect an issue or discussion where the Zed team has already confirmed we’re interested in shipping the idea.

I’ve compiled the changes, but I haven’t been able to get the new behavior working locally. Given the breadth and impact of these changes, it’s important to attach screenshots or a short screen recording showing the feature in action, as a recording would at least demonstrate that it’s functioning before we commit time to a full review

Given all of the above, I’m going to close this PR for now. That said, you’re very welcome to open a discussion about improving the search experience for the threads sidebar so we can first agree on the desired behavior and scope, and then iterate on it together.

Finally, our contributing guide outlines what we look for in contributions and offers tips for first‑time contributors. I’d recommend taking a look. Thanks!

@dinocosta dinocosta closed this Jun 2, 2026
@dandv

dandv commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

In the meantime, I've created a skill to search across Zed threads. It autodetects the Zed profile and supports regular expressions and auto-expanding compressed blobs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla-signed The user has signed the Contributor License Agreement first contribution the author's first pull request to Zed. NOTE: the label application is automated via github actions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants