feat(web): Discord-style search operators in the command palette - #5
Open
devin-ai-integration[bot] wants to merge 10 commits into
Open
devin-ai-integration[bot] wants to merge 10 commits into
devin-ai-integration[bot] wants to merge 10 commits into
Conversation
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>
Author
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
…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>
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
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>
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What Changed
Adds Discord-style search operators to the root command palette (web). Only
apps/webis touched; the inline sidebar search and project-scope combobox onmainare left as-is.in:<project>(quoted names supported,in:autocompletes projects under Filter by project; Enter commitsin: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)a,be) appends a Search filters group after the results listing the matching operators with a one-line description; picking one rewrites the word tokeyword:. 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.useThreadSearch, so only residual text hits the server content search.useArchivedThreadSnapshotsonly 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 onwaitForProject), then opens it.CommandInputgains aleadingslot 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 canonicalquerystring (tokenizeThreadSearchQuery/composeThreadSearchQuery), so parsing, filtering and thein:autocomplete are unchanged. Chips have an x button; Backspace with the caret at position 0 removes the last chip. Chips readkeyword: [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-searchbranch onto currentmainwithout reintroducing the stale sidebar rewrite.Reproduction (before)
Setup:
vp run dev --home-dir .t3/search-testonorigin/main(7a368fe7c), two projects (Atlas, Beacon), fixture threads across Codex/Claude and dates, one archived Atlas thread.Steps: Ctrl+K, type
in:Atlas; thenafter: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
main):in:Atlasmain):after:7din:Atlas agent:Codex after:7d(light)in:completion close-upagent:autocompleteaAutocomplete flow (
in:pick,agent:copick,ahints, clickafter:):Chip interaction (pick
in:suggestion, commitagent:/after:by typing a space, Backspace pops a chip, x removes one):in:autocompleteon:today>actions mode: no chipin:value truncatesArchived-hit interaction (re-archive, search
yesterday, click, thread opens on first selection):Verification
vp test run apps/web/src/components/threadSearchQuery.logic.test.ts apps/web/src/components/CommandPalette.logic.test.ts: 69 passedvp run --filter @t3tools/web typecheck: cleanvp linton changed files: only 3 pre-existingreact(set-state-in-effect)warnings in untouched open-intent effectsvp run knip:check: clean.t3/search-teststate) covering every operator, autocomplete, actions-only, submenus, and the archived first-selection flow on45915804c. 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:bananaandin:stay text,> in:Atlasstays in actions mode, and the search icon does not move between the no-chip and chip layouts (0px at 1600px viewport). Theprovider:autocomplete, operator hints, and thekeyword: icon valuechip order were verified on41bf3b1e0along 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
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