Skip to content

Conversation

@roomote
Copy link
Contributor

@roomote roomote bot commented Jan 4, 2026

Implements $ autocomplete for Agent Skills in the chat textarea, similar to how / works for commands.

Features

UI/UX

  • $ trigger works anywhere in message after whitespace/newline (not just at start)
  • Fuzzy search filtering of skills by name
  • Skills are mode-filtered (only shows skills available in current mode)
  • Visual highlighting of valid $skill-name tokens in textarea
  • Keyboard navigation (↑↓ arrows, Enter/Tab to select)

Backend

  • requestSkills handler provides mode-filtered skill list to webview
  • Send-time resolution: $skill-name tokens are detected and SKILL.md content is included in the prompt
  • Structured metadata attached to skill selections for extension processing
  • Supports both hyphenated and non-hyphenated skill names (e.g., $pdf-processing and $pdfprocessing)

Implementation Details

Frontend Changes

  • Added Skill type to ContextMenuOptionType enum
  • Extended shouldShowContextMenu() to detect $ trigger
  • Added insertSkill() function for $skill-name insertion with trailing space
  • Updated getContextMenuOptions() to handle $ queries with fuzzy matching
  • Updated ChatTextArea to request and receive skills from extension
  • Updated ContextMenu to render skill suggestions with descriptions
  • Added skillRegexGlobal pattern for highlighting

Backend Changes

  • Added Skill interface to ExtensionMessage and WebviewMessage types
  • Added requestSkills message handler in webviewMessageHandler.ts
  • Updated parseMentions() to detect and resolve $skill-name tokens
  • Skills are loaded from SkillsManager and included as <skill> XML blocks
  • Full SKILL.md content is injected into the prompt at send time

Tests

  • Comprehensive tests for shouldShowContextMenu with $ trigger
  • Tests for skill filtering and fuzzy matching
  • Tests for insertSkill behavior
  • Tests for skill resolution in parseMentions

Related

Implements the Slack discussion for skill autocomplete with:

  • Insert $skill-name + trailing space
  • Attach structured metadata for extension-side resolution
  • Mode-filtered suggestions from SkillsManager

View task on Roo Code Cloud

- Add Skill type to ContextMenuOptionType enum
- Implement $ trigger detection anywhere after whitespace
- Add insertSkill function for $skill-name insertion with metadata
- Add skill-related message types (ExtensionMessage and WebviewMessage)
- Update ChatTextArea to handle skill autocomplete (request/receive/display)
- Update handleMentionSelect to use insertSkill for skill selection
- Update ContextMenu component to render skill suggestions
- Add requestSkills handler in ClineProvider to provide mode-filtered skills
- Add send-time skill resolution to include SKILL.md content in prompts
- Update highlight layer to visually highlight valid $skill-name tokens
- Add comprehensive tests for skill autocomplete functionality
- Skills are filtered by current mode and resolved at message send time
- Skill content is attached as structured metadata for extension processing
@roomote
Copy link
Contributor Author

roomote bot commented Jan 4, 2026

Rooviewer Clock   See task on Roo Cloud

Reviewed the $skill-name autocomplete implementation. Found 1 issue related to redundant file I/O and potential test mismatch.

Issues

Mention @roomote in a comment to request specific changes to this pull request or fix all unresolved issues.

Comment on lines +301 to +307
try {
// Read the full SKILL.md content
const skillContent = await fs.readFile(skillInfo.path, "utf-8")
parsedText += `\n\n<skill name="${skillName}">\n${skillContent}\n</skill>`
} catch (error) {
parsedText += `\n\n<skill name="${skillName}">\nError loading skill '${skillName}': ${error.message}\n</skill>`
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This reads the skill content from the filesystem, but getSkillContent() already reads and parses the file (returning content in its instructions field). This creates two issues:

  1. Redundant file I/O: The skill file is read twice - once in the validation loop via getSkillContent() and again here.

  2. Test mismatch: The tests mock getSkillContent to return skill metadata with instructions, but this code ignores that and reads from the path directly. Since mocked paths like /path/to/skill/SKILL.md don't exist, fs.readFile throws and the tests would fail unless fs is globally mocked.

Consider storing the skill content during validation and reusing it here, or using the instructions field from SkillContent.

Suggested change
try {
// Read the full SKILL.md content
const skillContent = await fs.readFile(skillInfo.path, "utf-8")
parsedText += `\n\n<skill name="${skillName}">\n${skillContent}\n</skill>`
} catch (error) {
parsedText += `\n\n<skill name="${skillName}">\nError loading skill '${skillName}': ${error.message}\n</skill>`
}
// Use the skill content that was already fetched during validation
const skillFullContent = await skillsManager.getSkillContent(skillName, currentMode)
if (skillFullContent) {
parsedText += `\n\n<skill name="${skillName}">\n${skillFullContent.instructions}\n</skill>`
}

Fix it with Roo Code or mention @roomote and request a fix.

@hannesrudolph hannesrudolph added the Issue/PR - Triage New issue. Needs quick review to confirm validity and assign labels. label Jan 4, 2026
@github-project-automation github-project-automation bot moved this from Triage to Done in Roo Code Roadmap Jan 8, 2026
@github-project-automation github-project-automation bot moved this from New to Done in Roo Code Roadmap Jan 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Issue/PR - Triage New issue. Needs quick review to confirm validity and assign labels.

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants