Skip to content

feat(vscode): @ file mention with dropdown and file chips#397

Open
iscekic wants to merge 20 commits intodevfrom
feature/vscode-at-file-mention
Open

feat(vscode): @ file mention with dropdown and file chips#397
iscekic wants to merge 20 commits intodevfrom
feature/vscode-at-file-mention

Conversation

@iscekic
Copy link
Contributor

@iscekic iscekic commented Feb 17, 2026

Summary

Closes #289@ file tagging with dropdown menu for the VS Code extension.

What's new

  • Type @ in the chat input to trigger a fuzzy file search dropdown
  • Keyboard navigation: ↑↓ to move, Enter/Tab to select, Escape to dismiss
  • Selected files appear as removable chips below the textarea (click × to remove)
  • Chips are sent as FileAttachment[] with the message on submit
  • Dropdown and chips use FileIcon from @kilocode/kilo-ui/file-icon for VS Code–themed file type icons

Implementation

  • http-client.ts: findFiles(query, dir)GET /find/file?query=...&dirs=false&limit=10
  • messages.ts: RequestFileSearchMessage (webview→ext) and FileSearchResultMessage (ext→webview)
  • KiloProvider.ts: handles requestFileSearch, calls findFiles, posts result back
  • PromptInput.tsx: @ detection, debounced search, dropdown with keyboard nav, file chips
  • esbuild.js: custom svgSpritePlugin injects the file-icon SVG sprite into document.body to avoid VS Code webview cross-origin <use href="data:..."> errors
  • chat.css: dropdown item layout [icon] filename parent/dir and chip layout [icon] filename ×

Add findFiles() to HttpClient, add RequestFileSearchMessage/FileSearchResultMessage
message types, and handle requestFileSearch in KiloProvider.
- Detect @<query> pattern in textarea and show fuzzy file search dropdown
- Keyboard navigation (arrows, Enter/Tab to select, Escape to close)
- Selected files appear as removable chips below the textarea
- Chips are sent as FileAttachment[] with the message on submit
…chips

- Add .svg dataurl loader to esbuild for webview and agent-manager builds
- Replace hardcoded SVG with FileIcon from @kilocode/kilo-ui/file-icon
- Dropdown shows: [icon] filename  parent/path (name bold, dir muted right-aligned)
- Chips show: [icon] filename
Use a custom esbuild plugin to inject sprite.svg into document.body as a
hidden element instead of using the dataurl loader. This avoids VS Code
webview's cross-origin block on <use href="data:..."> references.
@kiloconnect
Copy link
Contributor

kiloconnect bot commented Feb 17, 2026

Code Review Summary

Status: 1 Issue Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 0
Issue Details (click to expand)

WARNING

File Line Issue
packages/kilo-vscode/webview-ui/src/hooks/useFileMention.ts 122 Enter/Tab key is swallowed when mention dropdown is open but results are empty, preventing message submission
Files Reviewed (6 files)
  • packages/kilo-vscode/esbuild.js - 0 issues
  • packages/kilo-vscode/src/KiloProvider.ts - 0 issues
  • packages/kilo-vscode/src/services/cli-backend/http-client.ts - 0 issues
  • packages/kilo-vscode/webview-ui/src/components/chat/PromptInput.tsx - 0 issues
  • packages/kilo-vscode/webview-ui/src/hooks/useFileMention.ts - 1 issue
  • packages/kilo-vscode/webview-ui/src/styles/chat.css - 0 issues
  • packages/kilo-vscode/webview-ui/src/types/messages.ts - 0 issues

Fix these issues in Kilo Cloud

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR implements @ file mention functionality for the VS Code extension's chat interface, allowing users to tag and attach files to their messages through a fuzzy search dropdown.

Changes:

  • Added file search API endpoint integration (/find/file) with debounced search
  • Implemented keyboard-navigable dropdown with fuzzy file search triggered by @ symbol
  • Added removable file chips to display attached files before sending
  • Extended message handling to include FileAttachment[] in chat messages

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
packages/kilo-vscode/webview-ui/src/types/messages.ts Added RequestFileSearchMessage and FileSearchResultMessage types for file search communication
packages/kilo-vscode/webview-ui/src/styles/chat.css Added CSS for file mention dropdown and attached file chips with VS Code theme integration
packages/kilo-vscode/webview-ui/src/components/chat/PromptInput.tsx Implemented @ detection, file search, dropdown with keyboard navigation, and file chip UI
packages/kilo-vscode/src/services/cli-backend/http-client.ts Added findFiles method to query backend /find/file endpoint
packages/kilo-vscode/src/KiloProvider.ts Added message handler for requestFileSearch to call backend and return results
packages/kilo-vscode/esbuild.js Added svgSpritePlugin to inject FileIcon SVG sprite into webview DOM to avoid CSP issues

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Add .catch() to findFiles promise, posting paths:[] on failure so the
  webview doesn't hang (KiloProvider.ts)
- Fix AT_PATTERN to require word boundary before @ to avoid false triggers
  on email addresses and mid-word @ symbols
- Increment fileSearchCounter before setTimeout to prevent duplicate
  requestIds when multiple keystrokes fire before the debounce fires
- Replace inline SVG send/stop icons with Icon name="arrow-up"/"stop"
- Replace hand-rolled chip remove button with IconButton icon="close-small"
- Remove .file-chip-remove CSS ruleset (no longer needed)
Move all @ mention logic into a dedicated hook:
- Signals: attachedFiles, mentionQuery, mentionResults, mentionIndex
- onInput(val, cursor): boolean — AT_PATTERN detection, returns true if consumed
- onKeyDown(e, textarea): boolean — dropdown navigation, returns true if consumed
- selectFile, removeFile, closeMention, buildFileAttachments, clearAttachedFiles

PromptInput retains only text/ghostText state, autocomplete, and JSX.
- Add multiline support: regex now matches @ after newlines (m flag)
- Show dropdown on bare @: trigger search with empty query to show all/recent files
- Add empty state: display 'No files found' when search returns 0 results
@iscekic iscekic force-pushed the feature/vscode-at-file-mention branch from adfd2c1 to 7f869a4 Compare February 17, 2026 21:26
… createEffect

The createEffect approach didn't work because dropdownRef is inside a
<Show> block — the ref is undefined when the effect is first created and
is not reactive, so the effect never runs. Move scroll logic to
handleKeyDown where dropdownRef is guaranteed to exist when the dropdown
is visible, using queueMicrotask to defer until after Solid updates DOM.
import type { FileAttachment, WebviewMessage, ExtensionMessage } from "../types/messages"

const FILE_SEARCH_DEBOUNCE_MS = 150
const AT_PATTERN = /(?:^|\s)@(\S*)$/m
Copy link
Contributor

Choose a reason for hiding this comment

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

[WARNING]: The m (multiline) flag on AT_PATTERN causes $ to match end-of-line, not just end-of-string

In a multiline textarea, if the user types:

hello @foo
some other text|

(cursor at |), before will be "hello @foo\nsome other text". With the m flag, $ matches the end of the first line, so the regex matches @foo on line 1 — even though the cursor is on line 2. This would incorrectly trigger the mention dropdown for a stale @ on a previous line.

Remove the m flag so $ only matches end-of-string (i.e. the cursor position):

Suggested change
const AT_PATTERN = /(?:^|\s)@(\S*)$/m
const AT_PATTERN = /(?:^|\s)@(\S*)$/

this.postMessage({ type: "fileSearchResult", paths: [], requestId: message.requestId })
})
}
break
Copy link
Contributor

Choose a reason for hiding this comment

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

[WARNING]: No response sent when httpClient is null

If this.httpClient is falsy, the requestFileSearch message is silently dropped — no fileSearchResult is ever posted back. The webview's mention dropdown will remain open indefinitely, waiting for a response that never arrives.

Consider sending back an empty result when the client isn't available:

case "requestFileSearch": {
  const client = this.httpClient
  if (client) {
    // ... existing code ...
  } else {
    this.postMessage({ type: "fileSearchResult", paths: [], requestId: message.requestId })
  }
  break
}

e.preventDefault()
const path = mentionResults()[mentionIndex()]
if (path && textarea) selectMentionFile(path, textarea, setText)
return true
Copy link
Contributor

Choose a reason for hiding this comment

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

[WARNING]: Enter key is swallowed when mention dropdown is open but results are empty

When showMention() is true (user typed @) but mentionResults() is empty (no files matched), pressing Enter calls e.preventDefault() and returns true — but selectMentionFile is never called because path is undefined. This silently swallows the Enter key, preventing the user from sending their message.

Consider also checking that there are results before intercepting Enter/Tab:

Suggested change
return true
if ((e.key === "Enter" || e.key === "Tab") && mentionResults().length > 0) {

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Vcode][FEATURE] tagging files with @, including dropdown menu

1 participant