Fix skills duplication when Agent Skills Location overlaps with Plugin Locations#307693
Fix skills duplication when Agent Skills Location overlaps with Plugin Locations#307693
Conversation
When 'Agent Skills Location' overlaps with 'Plugin Locations', the same skill URI can appear in both discoveredSkills and pluginSkills sources. Add URI-based deduplication (seenUris Set) before processing each skill to prevent the same file from being included multiple times. Also add a test verifying that skills are not duplicated when the same URI appears via both SKILLS_LOCATION_KEY and plugin sources. Agent-Logs-Url: https://github.com/microsoft/vscode/sessions/93df8c49-237a-434e-938e-5ba4e004cfd9 Co-authored-by: connor4312 <2230985+connor4312@users.noreply.github.com>
| const uri = skill.uri; | ||
| const promptPath = skill; | ||
|
|
||
| const uriKey = uri.toString(); |
Agent-Logs-Url: https://github.com/microsoft/vscode/sessions/790cd72e-c8ea-4c81-80c1-e203e1a29ab8 Co-authored-by: connor4312 <2230985+connor4312@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR aims to prevent the same SKILL.md from being surfaced multiple times when skill discovery sources overlap (notably when SKILLS_LOCATION_KEY points into a plugin’s skills area), which previously led to duplicate entries in user-facing lists.
Changes:
- Add URI-based de-duplication to
computeSkillDiscoveryInfousing aResourceSet, so the sameURIis only parsed once across sources. - Add a unit test for the overlap scenario to ensure a single skill result is returned.
Show a summary per file
| File | Description |
|---|---|
| src/vs/workbench/contrib/chat/common/promptSyntax/service/promptsServiceImpl.ts | Adds URI-based de-duplication in skill discovery. |
| src/vs/workbench/contrib/chat/test/common/promptSyntax/service/promptsService.test.ts | Adds a test intended to cover overlap de-duplication. |
Copilot's findings
- Files reviewed: 2/2 changed files
- Comments generated: 2
| private async computeSkillDiscoveryInfo(token: CancellationToken): Promise<IPromptFileDiscoveryResult[]> { | ||
| const files: IPromptFileDiscoveryResult[] = []; | ||
| const seenNames = new Set<string>(); | ||
| const seenUris = new ResourceSet(); | ||
| const nameToUri = new Map<string, URI>(); |
There was a problem hiding this comment.
This URI de-duplication is added in computeSkillDiscoveryInfo, which is used by findAgentSkills()/cachedSkills. However, the slash command list is built via getPromptSlashCommands() → computeSlashCommandDiscoveryInfo() → listPromptFiles(PromptsType.skill), and that path still merges file-locator + plugin skills without URI de-duplication. If the user-facing duplication was in slash commands (per PR description), this change likely won’t address it; consider adding URI de-duplication in computeListPromptFiles (for PromptsType.skill) or in computeSlashCommandDiscoveryInfo, and update tests accordingly.
There was a problem hiding this comment.
Done in 88f9527. Added URI deduplication (ResourceSet) to computeListPromptFiles — the function that feeds both computeSlashCommandDiscoveryInfo and all other listPromptFiles callers. Also fixed the test: the previous version used an absolute path for SKILLS_LOCATION_KEY which is rejected by isValidPromptFolderPath, so the file locator never actually found the skill. The updated test uses a workspace-relative path, causing the file locator to discover the same URI the plugin registers — and both findAgentSkills and getPromptSlashCommands now assert exactly 1 result.
src/vs/workbench/contrib/chat/test/common/promptSyntax/service/promptsService.test.ts
Show resolved
Hide resolved
Agent-Logs-Url: https://github.com/microsoft/vscode/sessions/71dad59b-e7d7-4655-8141-a34b5072d905 Co-authored-by: connor4312 <2230985+connor4312@users.noreply.github.com>
Skills appeared multiple times in the slash command list when
SKILLS_LOCATION_KEYwas configured to a workspace-relative path that overlapped with a plugin location — the sameSKILL.mdURI would surface via both the file locator and_pluginPromptFilesByType. This affected both thefindAgentSkills()path and, critically, the user-facing slash command list built viagetPromptSlashCommands()→computeSlashCommandDiscoveryInfo()→listPromptFiles(PromptsType.skill).Changes
promptsServiceImpl.ts—computeListPromptFiles: Add URI-based deduplication using aResourceSetso that when the file locator and plugin registration both return the same URI, only the first occurrence is kept. This fixes the slash-command path (getPromptSlashCommands).promptsServiceImpl.ts—computeSkillDiscoveryInfo: URI-based deduplication using aResourceSet(instead ofSet<string>) checked beforeparseNew(), so the same file path from any number of sources is only processed once. The existing name-based dedup (seenNames) is preserved for catching distinct files that resolve to the same skill name.promptsService.test.ts: Test covering the overlap scenario uses a workspace-relativeSKILLS_LOCATION_KEYpath (absolute paths are rejected byisValidPromptFolderPathand would not be found by the file locator). BothfindAgentSkills()andgetPromptSlashCommands()are asserted to return exactly one result, covering both affected code paths.