fix(vscode): keep @ mention search open across spaces - #13592
Conversation
The mention trigger stopped at the first space, so files whose names contain spaces could not be found. Allow spaces in the in-progress query, bounded by newlines and by a later ' @' so a second mention starts its own query, and close the dropdown once a spaced query resolves to no matches so ordinary prose after a mention neither reopens it nor steals Enter.
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Files Reviewed (1 file)
Previous Review Summaries (9 snapshots, latest commit fccc74a)Current summary above is authoritative. Previous snapshots are kept for context only. Previous review (commit fccc74a)Status: No Issues Found | Recommendation: Merge Files Reviewed (6 files)
Previous review (commit f9cc1ae)Status: No Issues Found | Recommendation: Merge Files Reviewed (5 files)
Previous review (commit 673b5e9)Status: No Issues Found | Recommendation: Merge Files Reviewed (2 files)
Previous review (commit 456676b)Status: 1 Issue Found | Recommendation: Address before merge Overview
Issue Details (click to expand)WARNING
Files Reviewed (6 files)
Fix these issues in Kilo Cloud Previous review (commit 881d756)Status: No Issues Found | Recommendation: Merge Files Reviewed (4 files)
Previous review (commit 916b94f)Status: 1 Issue Found | Recommendation: Address before merge Overview
Issue Details (click to expand)WARNING
Files Reviewed (6 files)
Fix these issues in Kilo Cloud Previous review (commit e4d321f)Status: 1 Issue Found | Recommendation: Address before merge Overview
Issue Details (click to expand)WARNING
Files Reviewed (4 files)
Fix these issues in Kilo Cloud Previous review (commit e4a3905)Status: No Issues Found | Recommendation: Merge Files Reviewed (4 files)
Previous review (commit 6a224d2)Status: No Issues Found | Recommendation: Merge Files Reviewed (5 files)
Reviewed by grok-4.6 · Input: 154.8K · Output: 16.8K · Cached: 595.5K Review guidance: REVIEW.md from base branch |
|
Hi @sylwester-liljegren did you test this manually? |
|
Hi @marius-kilocode ! Yes, I have tested this myself and it works. The space key does not close the list of files anymore. The only way to close this is by clicking on Esc key AFAIK, but maybe we should add a cross somewhere in the mentions menu if it isn't obvious to the end-user. What is your opinion on this? |
|
@marius-kilocode , my goodness, it is worse than previously. Not sure if it is related to suggestions introduced by kilo-code-bot. But yeah, I'll definitely look into this. Thanks for catching up! |
Allowing spaces in the query meant text typed after an inserted mention still matched the trigger, so the dropdown reopened and kept offering the already-selected file. Close it as soon as the query covers a complete mention token followed by whitespace, which is immediate and independent of what the pending file search returns. A query that is only a prefix of (or exactly) a known token still counts as editing that mention and stays open.
|
Follow-up after testing: allowing spaces meant text typed after an already-inserted mention still matched the trigger, so the dropdown reopened and kept offering the file that had just been selected. The dropdown now closes as soon as the query covers a complete mention token followed by whitespace (mentionSettled). That check is immediate and independent of what the pending file search returns, which is what the previous result-based heuristic got wrong. A query that is only a prefix of, or exactly equal to, a known token still counts as editing that mention and keeps the dropdown open, so deleting back into a mention behaves as before. |
| for (const token of [...tokens, TERMINAL_MENTION, GIT_CHANGES_MENTION]) { | ||
| if (query.length <= token.length) continue | ||
| if (!query.startsWith(token)) continue | ||
| if (/\s/.test(query[token.length] ?? "")) return true |
There was a problem hiding this comment.
WARNING: mentionSettled treats any shorter known token followed by a space as complete, which can close @ search for spaced filenames.
query.startsWith(token) plus a following whitespace character returns true on the first match. Unlike syncMentionedPaths / findMentionRange in this file, the loop is not longest-first, and it never checks whether query is still a prefix of a longer known token — the behavior the comment above describes.
That is reachable in this PR's own feature: knownPaths is sticky, so after mentioning a folder named my, typing @my report makes syncMentionedPaths re-add my (the space after my is a valid boundary). mentionSettled("my report", {"my"}) then closes the dropdown and never searches for my report.txt. The same happens for builtins (terminal, git-changes) on every @terminal … query, even with an empty token set.
Suggestion: return false first when any token is equal to the query or has the query as a prefix; only then treat token + whitespace as settled. Also consider setting the existing dead query on select (token + trailing space) instead of inferring settlement from every shorter path still in mentionedPaths.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
There was a problem hiding this comment.
Good catch — this was a real bug in the feature's own path, fixed in 881d756.
The rule no longer consults every known token. useFileMention now records the mention actually inserted at each @ offset (in selectMention and insertFilePickerResult), and mentionSettled(query, token, tokens) only settles when the query continues past that token. Since knownPaths is sticky, a folder named my mentioned earlier no longer closes the search for a new @my report.txt, and a typed @terminal notes.txt no longer settles just because terminal is a builtin — a builtin has to have been inserted at that @ too.
I also took the prefix half of your suggestion: settlement returns false while any known token is longer than the query and still has it as a prefix, so a query growing toward a longer known path keeps searching.
On setting dead at select time instead: keying to the insertion offset does the same work but stays reversible — deleting back into the mention makes the query a prefix again and reopens the dropdown, which a sticky dead query would not.
New coverage in use-file-mention.test.ts (spaced path starting like an earlier mention keeps searching; typing after a genuinely selected file/builtin mention stays closed) and rewritten mentionSettled cases in file-mention-utils.test.ts.
The test bundles the fixture's whole webview graph with esbuild and runs it in a spawned process, which does not reliably fit in bun test's 5s default budget and has started timing out in CI. The work itself passes; only the budget was too tight.
mentionSettled tested every known token, and knownPaths is sticky for the whole session, so a short earlier mention such as a folder named 'my' closed the search for a genuinely new '@my report.txt'. Builtins had the same problem for any typed '@Terminal ...' query. Settlement now keys off the mention actually inserted at that '@' offset, and stays open while the query is still growing toward a longer known path.
|
@marius-kilocode I have fixed the issue now. I tested it more thoroughly and I couldn't find anything. But feel free to test again before merging this PR into main. |
|
Retested @sylwester-liljegren, can we also make inline Validation: 225 focused tests passed, and the extension build, lint, and type checks passed. |
|
Hi, @marius-kilocode ! Thanks for your feedback! I'll look into this more closely after my work. It should be possible to make it work, but just to confirm my understanding of your request: You'd like to remove the "Past chats" option and instead make past chats searchable the same way as files in the current repo? Is there anything about file search index architecture that needs to be considered when implementing these requested changes? |
|
No my argument is if we allow to search for a search string with space like 'past chats' it should not only include files in that search but also include all other searchable elements in our context menu. |
|
I see your point now, @marius-kilocode . In that case, I'll fix it today after my work :) |
Spaced queries only reached files, so '@past chats' or '@git changes' matched nothing and chat titles were reachable only after opening the Past chats picker. Mention labels and queries are now compared with hyphens and whitespace normalised, so every special entry answers the way its label reads, and a typed query also ranks directory-scoped past chats inline ahead of the file results. The session list is fetched once per scope on the first typed character, so a bare '@' still costs nothing extra.
|
@marius-kilocode implemented in Every menu entry answers to its label, not just files. Mention labels and the query are now compared with hyphens and whitespace normalised to one separator, so Past chats rank inline. A typed One detail worth flagging: inline results are built from a shared candidate list, so Tests: new coverage for spaced label matching ( |
…paces # Conflicts: # packages/kilo-vscode/tests/unit/session-provider-activity.test.ts
Inline chat results arrive from an async fetch, but the prose heuristic closed the menu as soon as the file search came back empty, which is exactly what happens while typing a chat title. The close is now held while that scope's fetch is in flight and applied only once the list is known and still matches nothing, bounded by a grace timer so a lost reply cannot disable it.
The Browse files entry ends every list as a fallback, so a spaced query kept it out of the way: Enter sent the message and the prose heuristic closed the menu. A query that spells the entry out is a choice rather than prose, so both checks now make an exception for it and Enter opens the picker, whose result replaces the typed query including its spaces.
Files, past chats and the menu entries were emitted as fixed groups, so a chat title the query merely scattered across outranked a literal filename match, and the entries could only ever appear in their reserved slot. Everything is now scored against the query on one scale and sorted by fit, with a relevance floor that keeps a loose subsequence from dragging entries and chats into every short query. Browse files is never dropped, since reaching a file outside the workspace must not depend on what the query matches; it simply sinks to the bottom when ignored. The selection starts on the best answer, and a bare @ keeps the curated menu order. Matching now has a single definition: the prose heuristic and the synchronous filter ask the ranking rather than testing label prefixes of their own, which is what made a fully typed 'browse files...' match the list and miss the prose check.
|
@marius-kilocode , I have fixed so that "@git changes", "@past chats", and "@browse files" are matched by the inline search. For "@past chats", it opens up a separate search through previous chats as per your suggestion. Similarily, for "@git changes", it correctly inserts "@git-changes", and for "@browse files", it opens up the filepicker to choose a file outside of the workspace. I also have made some changes regarding scoring and ordering of all entries appearing in the mentions dropdown, and it seems to me that it works so much faster. I hope that there is no catch to that, so feel free to try it for yourself and let me hear your feedback on this. Maybe some introduced features should be contained in a separate pull request, but I'll await your opinion on the current state of this PR. |
|
Thanks @sylwester-liljegren, this works well now. Merged. |
|
Perfect, thanks @marius-kilocode ! I'll go through the other PR concerning mentions in a multi-root workspace setting then :) |



Issue
No existing issue found for this behavior (searched open issues for
mention/mention space filename). Reported directly by a user of the VS Code extension.Context
Typing
@in the chat input opens the mention list, but the first space closed it. The trigger pattern only matched a query of non-whitespace characters, so any file or folder whose name contains a space was unreachable through@search — the user had to fall back to "Browse files...". Everything downstream of selection already supports spaced paths (syncMentionedPaths,buildFileAttachments,seedFromParts, mention span highlighting); only the trigger stopped early.Implementation
AT_PATTERNnow allows spaces in the in-progress query. Two boundaries keep that from being greedy in the wrong direction:@, so a second mention starts its own query instead of swallowing the first. An@that is not preceded by whitespace stays inside the query, so scoped paths like@node_modules/@types/nodestill resolve.Allowing spaces means ordinary prose typed after a completed mention (
@README.md and then ...) also matches the trigger, which would leave the dropdown open and let it consume Enter via the always-present "Browse files..." fallback. Two guards inuseFileMentionprevent that:@offset, so continuing the sentence does not reopen it on every keystroke. Editing back to a query that can still match clears the flag, and switching session scope resets it.The dead-query heuristic is deliberately driven by search results rather than a synchronous local filter: the locally cached list is only the top slice for a shorter prefix, so closing on a local miss would break exactly the large-repo case this fix targets.
Screenshots / Video
N/A — no visual/layout change. The mention dropdown is the existing component; only when it stays open changed.
How to Test
Manual/local verification
Executed by the agent:
bun test tests/unit/file-mention-utils.test.ts tests/unit/use-file-mention.test.ts tests/unit/agent-manager-worktree-reference.test.ts tests/unit/prompt-input-utils.test.tsfrompackages/kilo-vscode/— 209 pass, 0 fail. Covers the new cases: spaced query captured, second mention not swallowed, scoped@typespath preserved, no newline spanning, dropdown stays open and renders a spaced-path result, dropdown closes and stays closed while prose is typed after a mention, Enter not consumed for a spaced query offering only the file picker.bun run typecheckandbun run lintfrompackages/kilo-vscode/— clean.bun run formatfrompackages/kilo-vscode/— no changes.Reviewer test steps
docs/my report.txt.@my rep— the dropdown stays open anddocs/my report.txtis offered; press Enter to insert it.@docs/my report.txt please summarize this) — the dropdown closes once the search resolves and does not flicker back on later keystrokes; Enter sends the message.@node_modules/@types— scoped paths still resolve.@src/a.ts and @b— the second@starts a fresh query and selecting a result does not overwrite the first mention.Blocked checks and substitute verification
bun run test:unitsuite frompackages/kilo-vscode/could not be used as a clean signal on this Windows machine: 91 tests fail onmain-unrelated environment issues (POSIX path expectations such as/repovsC:\repo,EPERMonsymlink, missingecho/pwd, and esbuild-child timeouts). None of the failures are in mention code. Substitute verification was the targeted test files listed above plus package typecheck and lint.Checklist
Get in Touch
N/A