Skip to content

feat(web): Discord-style search operators in the command palette - #5

Open
devin-ai-integration[bot] wants to merge 10 commits into
mainfrom
devin/1789608792-discord-search-operators
Open

devin-ai-integration[bot] wants to merge 10 commits into
mainfrom
devin/1789608792-discord-search-operators

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Sep 17, 2026 •

Copy link
Copy Markdown

What Changed

Adds Discord-style search operators to the root command palette (web). Only apps/web is touched; the inline sidebar search and project-scope combobox on main are left as-is.

  • in:<project> (quoted names supported, in: autocompletes projects under Filter by project; Enter commits in:Name (quoted only if the name has spaces) and keeps the palette open)
  • provider:<provider> (provider: autocompletes providers under Filter by provider, with provider icons)
  • Typing a bare word that prefixes an operator (a, be) appends a Search filters group after the results listing the matching operators with a one-line description; picking one rewrites the word to keyword:. It trails the results so Enter still selects the first real result.
  • before: / after: / on: with ISO days, 7d/2w, today, yesterday. Unparseable dates fall back to plain text.
  • Operator tokens are stripped before the query is sent to useThreadSearch, so only residual text hits the server content search.
  • Archived threads are included in root-search results (loaded via useArchivedThreadSnapshots only while a non-empty root query is active; live shells win over archived duplicates). Selecting one restores it, waits for the restored shell to land in the store (waitForThreadShell, modelled on waitForProject), then opens it.
  • Committed operators (token followed by a space) become real chips rendered inline between the search icon and the input, like a tokenized input (Discord, Gmail). CommandInput gains a leading slot for this; when it is set, the icon moves into a fixed-width zone with the same left edge so it does not shift. The palette keeps one canonical query string (tokenizeThreadSearchQuery / composeThreadSearchQuery), so parsing, filtering and the in: autocomplete are unchanged. Chips have an x button; Backspace with the caret at position 0 removes the last chip. Chips read keyword: [icon] value: in: shows the project favicon on an exact name match, provider: shows the provider icon. Chips/autocomplete are suppressed in > actions-only mode and in submenus.

Files: threadSearchQuery.logic.ts (+tests, pure parser and tokenizer), CommandPalette.tsx, CommandPalette.logic.ts (+test update), ui/command.tsx, state/entities.ts.

Why

Users with many projects and providers can only filter palette results by free text today; there is no way to scope by project, provider or date, and archived threads are unreachable from the palette. This ports the palette half of an older map-sidebar-project-search branch onto current main without reintroducing the stale sidebar rewrite.

Reproduction (before)

Setup: vp run dev --home-dir .t3/search-test on origin/main (7a368fe7c), two projects (Atlas, Beacon), fixture threads across Codex/Claude and dates, one archived Atlas thread.

Steps: Ctrl+K, type in:Atlas; then after:7d.
Expected: threads scoped to Atlas / updated in the last 7 days.
Actual: "No results" and the text is treated as a literal title search; archived thread never appears.

UI Changes

Before (main): in:Atlas Before (main): after:7d
before in:Atlas before after:7d

Note: screenshots and recordings below predate the agent: → provider: rename (ecedf1782); only the operator keyword/label changed.

After: combined in:Atlas agent:Codex after:7d (light) After: same query (dark)
combined light combined dark
Chip close-up (light) in: completion close-up
chips light in completion
agent: autocomplete Operator hints for a bare a
filter by agent search filters

Autocomplete flow (in: pick, agent:co pick, a hints, click after:):

autocomplete flow

Chip interaction (pick in: suggestion, commit agent:/after: by typing a space, Backspace pops a chip, x removes one):

chip flow

After: in: autocomplete After: on:today After: invalid date stays literal
in autocomplete on today invalid date
> actions mode: no chip Long in: value truncates Archived hit, first click opens the real thread
actions only long value archived opened

Archived-hit interaction (re-archive, search yesterday, click, thread opens on first selection):

archived flow

Verification

  • vp test run apps/web/src/components/threadSearchQuery.logic.test.ts apps/web/src/components/CommandPalette.logic.test.ts: 69 passed
  • vp run --filter @t3tools/web typecheck: clean
  • vp lint on changed files: only 3 pre-existing react(set-state-in-effect) warnings in untouched open-intent effects
  • vp run knip:check: clean
  • Browser pass (Chrome, isolated .t3/search-test state) covering every operator, autocomplete, actions-only, submenus, and the archived first-selection flow on 45915804c. The inline chips were re-verified on the latest commit in light and dark: chip creation from the suggestion and from a typed space, Backspace and x removal keep focus, before:banana and in: stay text, > in:Atlas stays in actions mode, and the search icon does not move between the no-chip and chip layouts (0px at 1600px viewport). The provider: autocomplete, operator hints, and the keyword: icon value chip order were verified on 41bf3b1e0 along with the same regressions.

Verification blockers: none for the palette. Provider execution was not exercised (no Codex/Claude CLI auth on the test box); the feature is provider-independent.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Work done by Devin (Claude) via the Devin harness.

Link to Devin session: https://app.devin.ai/sessions/ab01d132f2654ca88f7deab636a173e0
Open in Devin Desktop: https://app.devin.ai/desktop/session/ab01d132f2654ca88f7deab636a173e0?variant=devin
Requested by: @SunkenInTime

Ports the command-palette search work from the stale map-sidebar-project-search branch onto current main:

- in:<project> scopes results by project name/path, with an inline 'Filter by project' autocomplete group — Enter commits the filter into the query and keeps the palette open
- agent:<provider> matches the session provider name / model instance id
- before:/after:/on: bound updatedAt with ISO days, relative values (7d, 2w), today, and yesterday; unparseable dates degrade to plain text
- residual text keeps ranking against titles, project names, and server content-search snippets; operator tokens are stripped from the content-search query
- archived threads join the search corpus (snapshot fetched only while a root query is active) with an Archived badge replacing the live status decorations
- recognized operator tokens wear send-button-colored pills via a metric-identical backdrop behind the palette input

The operator engine lives in threadSearchQuery.logic.ts, pure and unit tested. The sidebar's inline thread search is unchanged.

Devin

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@devin-ai-integration

Copy link
Copy Markdown
Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XL labels Sep 17, 2026
SunkenInTime and others added 2 commits September 17, 2026 01:54
…n mode

Three fixes from browser testing of the operator search work:

- Selecting an archived thread hit fell through to a new-thread draft
  because archived threads aren't in the live shell store. runThread now
  unarchives first (useThreadActions.unarchiveThread, which also refreshes
  the archived snapshots) and only navigates on success; failures surface
  a toast via the existing squashAtomCommandFailure pattern.
- Operator pills rendered in actions-only mode (> queries). showOperatorPills
  now requires the live query to not start with '>'.
- Scrolling an overflowing query let the pill backdrop text translate into
  the start padding and paint over the search icon. Clipping now happens in
  an inner min-w-0 flex-1 overflow-hidden wrapper that starts exactly where
  the input text starts.

Devin

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Unarchive succeeded but navigate fired before the unarchived shell reached the live store, so the thread route saw a "missing" render state and redirected to /.

Adds waitForThreadShell(ref) to apps/web/src/state/entities.ts, modelled on waitForProject but subscribing to environmentThreadShells.threadShellAtom; the predicate requires shell.archivedAt === null because an archived thread can already have a stale shell in the live store. The palette's archived-hit path awaits it after a successful unarchive and toasts + returns on timeout instead of navigating.

Devin

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@devin-ai-integration
devin-ai-integration Bot marked this pull request as draft September 17, 2026 02:05
SunkenInTime and others added 5 commits September 17, 2026 04:58
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Filled foreground/8 chip with muted keyword and foreground value, replacing the primary-colored highlight.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Replaces the metric-identical backdrop behind a transparent input with real DOM chips rendered before the input via a new CommandInput leading prop — a tokenized input like Discord/Gmail. The canonical query string still prefixes committed operator tokens, so parsing, filtering, and the in: autocomplete are untouched.

- CommandInput gains a leading slot; when present, the search icon moves into a fixed-width zone with the same left edge (shell inset + 2px) so it does not shift when chips appear, and the input's start padding collapses to zero
- Committed operators render as removable muted chips (favicon for in: hits); Backspace at caret 0 pops the last chip, and the × button keeps input focus
- Backdrop, scroll-sync refs/effect, and the text-transparent trick are deleted; CommandPaletteContent drops inputBackdrop

Devin

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…hips

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@SunkenInTime
SunkenInTime marked this pull request as ready for review September 19, 2026 23:11
Extends the palette's operator UX:

- Chips render as keyword:[icon]value — ProjectFavicon for in: hits, the provider's icon for agent: hits resolved from the deduped provider list
- agent: gets a 'Filter by agent' autocomplete group mirroring the project one (prefix-then-substring ranking over display name and instance id, keepOpen, Enter commits into the query)
- A bare trailing word offers the operator keyword catalog ('Search filters' group appended after results, so Enter still targets real results)
- getTrailingProjectOperatorToken/applyProjectSuggestionToQuery generalize to getTrailingOperatorToken(query, keyword)/applyOperatorSuggestionToQuery, which now quotes values only when they contain whitespace; getTrailingKeywordPrefix detects bare trailing words

Devin

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@github-actions github-actions Bot added size:XXL and removed size:XL labels Sep 21, 2026
Maintainer feedback: the filter targets providers, not agents. Renames the
operator keyword, parsed field (providerQueries), trailing-token helper
keyword union, suggestion group, chip icon lookup, and tests. No alias.

Devin

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

This branch has not been deployed

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

Labels

size:XXL vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant