@@ -14,7 +14,7 @@ import { autorun } from '../../../../../base/common/observable.js';
1414import { basename , dirname , isEqual , isEqualOrParent } from '../../../../../base/common/resources.js' ;
1515import { ThemeIcon } from '../../../../../base/common/themables.js' ;
1616import { URI } from '../../../../../base/common/uri.js' ;
17- import { ResourceSet } from '../../../../../base/common/map.js' ;
17+ import { ResourceMap , ResourceSet } from '../../../../../base/common/map.js' ;
1818import { Codicon } from '../../../../../base/common/codicons.js' ;
1919import { localize } from '../../../../../nls.js' ;
2020import { IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js' ;
@@ -55,8 +55,6 @@ import { Schemas } from '../../../../../base/common/network.js';
5555import { OS } from '../../../../../base/common/platform.js' ;
5656import { ITelemetryService } from '../../../../../platform/telemetry/common/telemetry.js' ;
5757import { ICustomizationHarnessService , IExternalCustomizationItem , IExternalCustomizationItemProvider , matchesWorkspaceSubpath , matchesInstructionFileFilter , ICustomizationSyncProvider } from '../../common/customizationHarnessService.js' ;
58- import { evaluateApplyToPattern } from '../../common/promptSyntax/computeAutomaticInstructions.js' ;
59- import { isInClaudeRulesFolder , getCleanPromptName } from '../../common/promptSyntax/config/promptFileLocations.js' ;
6058import { ExtensionIdentifier } from '../../../../../platform/extensions/common/extensions.js' ;
6159import { ICommandService } from '../../../../../platform/commands/common/commands.js' ;
6260import { IProductService } from '../../../../../platform/product/common/productService.js' ;
@@ -1202,12 +1200,12 @@ export class AICustomizationListWidget extends Disposable {
12021200 * agent hooks) are left untouched — groupKey overrides are only applied to
12031201 * items whose current groupKey is `undefined`.
12041202 */
1205- private applyBuiltinGroupKeys ( items : IAICustomizationListItem [ ] , extensionInfoByUri : ReadonlyMap < string , { id : ExtensionIdentifier ; displayName ?: string } > ) : IAICustomizationListItem [ ] {
1203+ private applyBuiltinGroupKeys ( items : IAICustomizationListItem [ ] , extensionInfoByUri : ResourceMap < { id : ExtensionIdentifier ; displayName ?: string } > ) : IAICustomizationListItem [ ] {
12061204 return items . map ( item => {
12071205 if ( item . storage !== PromptsStorage . extension ) {
12081206 return item ;
12091207 }
1210- const extInfo = extensionInfoByUri . get ( item . uri . toString ( ) ) ;
1208+ const extInfo = extensionInfoByUri . get ( item . uri ) ;
12111209 if ( ! extInfo ) {
12121210 return item ;
12131211 }
@@ -1249,7 +1247,7 @@ export class AICustomizationListWidget extends Disposable {
12491247
12501248 const items : IAICustomizationListItem [ ] = [ ] ;
12511249 const disabledUris = this . promptsService . getDisabledPromptFiles ( promptType ) ;
1252- const extensionInfoByUri = new Map < string , { id : ExtensionIdentifier ; displayName ?: string } > ( ) ;
1250+ const extensionInfoByUri = new ResourceMap < { id : ExtensionIdentifier ; displayName ?: string } > ( ) ;
12531251
12541252
12551253 if ( promptType === PromptsType . agent ) {
@@ -1259,7 +1257,7 @@ export class AICustomizationListWidget extends Disposable {
12591257 const allAgentFiles = await this . promptsService . listPromptFiles ( PromptsType . agent , CancellationToken . None ) ;
12601258 for ( const file of allAgentFiles ) {
12611259 if ( file . extension ) {
1262- extensionInfoByUri . set ( file . uri . toString ( ) , { id : file . extension . identifier , displayName : file . extension . displayName } ) ;
1260+ extensionInfoByUri . set ( file . uri , { id : file . extension . identifier , displayName : file . extension . displayName } ) ;
12631261 }
12641262 }
12651263 for ( const agent of agents ) {
@@ -1276,8 +1274,8 @@ export class AICustomizationListWidget extends Disposable {
12761274 disabled : disabledUris . has ( agent . uri ) ,
12771275 } ) ;
12781276 // Track extension ID for built-in grouping (if not already set from file list)
1279- if ( agent . source . storage === PromptsStorage . extension && ! extensionInfoByUri . has ( agent . uri . toString ( ) ) ) {
1280- extensionInfoByUri . set ( agent . uri . toString ( ) , { id : agent . source . extensionId } ) ;
1277+ if ( agent . source . storage === PromptsStorage . extension && ! extensionInfoByUri . has ( agent . uri ) ) {
1278+ extensionInfoByUri . set ( agent . uri , { id : agent . source . extensionId } ) ;
12811279 }
12821280 }
12831281 } else if ( promptType === PromptsType . skill ) {
@@ -1287,7 +1285,7 @@ export class AICustomizationListWidget extends Disposable {
12871285 const allSkillFiles = await this . promptsService . listPromptFiles ( PromptsType . skill , CancellationToken . None ) ;
12881286 for ( const file of allSkillFiles ) {
12891287 if ( file . extension ) {
1290- extensionInfoByUri . set ( file . uri . toString ( ) , { id : file . extension . identifier , displayName : file . extension . displayName } ) ;
1288+ extensionInfoByUri . set ( file . uri , { id : file . extension . identifier , displayName : file . extension . displayName } ) ;
12911289 }
12921290 }
12931291 const uiIntegrations = this . workspaceService . getSkillUIIntegrations ( ) ;
@@ -1340,23 +1338,23 @@ export class AICustomizationListWidget extends Disposable {
13401338 // Filter out skills since they have their own section
13411339 const commands = await this . promptsService . getPromptSlashCommands ( CancellationToken . None ) ;
13421340 for ( const command of commands ) {
1343- if ( command . promptPath . type === PromptsType . skill ) {
1341+ if ( command . type === PromptsType . skill ) {
13441342 continue ;
13451343 }
1346- const filename = basename ( command . promptPath . uri ) ;
1344+ const filename = basename ( command . uri ) ;
13471345 items . push ( {
1348- id : command . promptPath . uri . toString ( ) ,
1349- uri : command . promptPath . uri ,
1346+ id : command . uri . toString ( ) ,
1347+ uri : command . uri ,
13501348 name : command . name ,
13511349 filename,
13521350 description : command . description ,
1353- storage : command . promptPath . storage ,
1351+ storage : command . storage ,
13541352 promptType,
1355- pluginUri : command . promptPath . storage === PromptsStorage . plugin ? command . promptPath . pluginUri : undefined ,
1356- disabled : disabledUris . has ( command . promptPath . uri ) ,
1353+ pluginUri : command . storage === PromptsStorage . plugin ? command . pluginUri : undefined ,
1354+ disabled : disabledUris . has ( command . uri ) ,
13571355 } ) ;
1358- if ( command . promptPath . extension ) {
1359- extensionInfoByUri . set ( command . promptPath . uri . toString ( ) , { id : command . promptPath . extension . identifier , displayName : command . promptPath . extension . displayName } ) ;
1356+ if ( command . extension ) {
1357+ extensionInfoByUri . set ( command . uri , { id : command . extension . identifier , displayName : command . extension . displayName } ) ;
13601358 }
13611359 }
13621360 } else if ( promptType === PromptsType . hook ) {
@@ -1463,10 +1461,10 @@ export class AICustomizationListWidget extends Disposable {
14631461 }
14641462 } else {
14651463 // For instructions, group by category: agent instructions, context instructions, on-demand instructions
1466- const promptFiles = await this . promptsService . listPromptFiles ( promptType , CancellationToken . None ) ;
1467- for ( const file of promptFiles ) {
1464+ const instructionFiles = await this . promptsService . getInstructionFiles ( CancellationToken . None ) ;
1465+ for ( const file of instructionFiles ) {
14681466 if ( file . extension ) {
1469- extensionInfoByUri . set ( file . uri . toString ( ) , { id : file . extension . identifier , displayName : file . extension . displayName } ) ;
1467+ extensionInfoByUri . set ( file . uri , { id : file . extension . identifier , displayName : file . extension . displayName } ) ;
14701468 }
14711469 }
14721470 const agentInstructionFiles = await this . promptsService . listAgentInstructions ( CancellationToken . None , undefined ) ;
@@ -1496,63 +1494,53 @@ export class AICustomizationListWidget extends Disposable {
14961494 }
14971495
14981496 // Parse prompt files to separate into context vs on-demand
1499- const promptFilesToParse = promptFiles . filter ( item => ! agentInstructionUris . has ( item . uri ) ) ;
1500- const parseResults = await Promise . all ( promptFilesToParse . map ( async item => {
1501- try {
1502- const parsed = await this . promptsService . parseNew ( item . uri , CancellationToken . None ) ;
1503- return { item, parsed } ;
1504- } catch {
1505- // Parse failed — treat as on-demand
1506- return { item, parsed : undefined } ;
1497+
1498+ for ( const { uri, pattern, name, description, storage, pluginUri } of instructionFiles ) {
1499+ if ( agentInstructionUris . has ( uri ) ) {
1500+ continue ; // already added as agent instruction
15071501 }
1508- } ) ) ;
15091502
1510- for ( const { item, parsed } of parseResults ) {
1511- const applyTo = evaluateApplyToPattern ( parsed ?. header , isInClaudeRulesFolder ( item . uri ) ) ;
1512- const name = parsed ?. header ?. name ;
1513- let description = parsed ?. header ?. description ;
1514- const friendlyName = this . getFriendlyName ( name || item . name || getCleanPromptName ( item . uri ) ) ;
1515- description = description || item . description ;
1503+ const friendlyName = this . getFriendlyName ( name ) ;
15161504
1517- if ( applyTo !== undefined ) {
1505+ if ( pattern !== undefined ) {
15181506 // Context instruction
1519- const badge = applyTo === '**'
1507+ const badge = pattern === '**'
15201508 ? localize ( 'alwaysAdded' , "always added" )
1521- : applyTo ;
1522- const badgeTooltip = applyTo === '**'
1509+ : pattern ;
1510+ const badgeTooltip = pattern === '**'
15231511 ? localize ( 'alwaysAddedTooltip' , "This instruction is automatically included in every interaction." )
1524- : localize ( 'onContextTooltip' , "This instruction is automatically included when files matching '{0}' are in context." , applyTo ) ;
1512+ : localize ( 'onContextTooltip' , "This instruction is automatically included when files matching '{0}' are in context." , pattern ) ;
15251513 items . push ( {
1526- id : item . uri . toString ( ) ,
1527- uri : item . uri ,
1514+ id : uri . toString ( ) ,
1515+ uri,
15281516 name : friendlyName ,
1529- filename : this . labelService . getUriLabel ( item . uri , { relative : true } ) ,
1517+ filename : this . labelService . getUriLabel ( uri , { relative : true } ) ,
15301518 displayName : friendlyName ,
15311519 badge,
15321520 badgeTooltip,
1533- description : description ,
1534- storage : item . storage ,
1521+ description,
1522+ storage,
15351523 promptType,
1536- typeIcon : storageToIcon ( item . storage ) ,
1524+ typeIcon : storageToIcon ( storage ) ,
15371525 groupKey : 'context-instructions' ,
1538- pluginUri : item . storage === PromptsStorage . plugin ? item . pluginUri : undefined ,
1539- disabled : disabledUris . has ( item . uri ) ,
1526+ pluginUri,
1527+ disabled : disabledUris . has ( uri ) ,
15401528 } ) ;
15411529 } else {
15421530 // On-demand instruction
15431531 items . push ( {
1544- id : item . uri . toString ( ) ,
1545- uri : item . uri ,
1532+ id : uri . toString ( ) ,
1533+ uri,
15461534 name : friendlyName ,
1547- filename : basename ( item . uri ) ,
1535+ filename : basename ( uri ) ,
15481536 displayName : friendlyName ,
1549- description : description ,
1550- storage : item . storage ,
1537+ description,
1538+ storage,
15511539 promptType,
1552- typeIcon : storageToIcon ( item . storage ) ,
1540+ typeIcon : storageToIcon ( storage ) ,
15531541 groupKey : 'on-demand-instructions' ,
1554- pluginUri : item . storage === PromptsStorage . plugin ? item . pluginUri : undefined ,
1555- disabled : disabledUris . has ( item . uri ) ,
1542+ pluginUri,
1543+ disabled : disabledUris . has ( uri ) ,
15561544 } ) ;
15571545 }
15581546 }
0 commit comments