@@ -519,46 +519,93 @@ export class FrontendPromptCustomizationServiceImpl implements PromptCustomizati
519519 }
520520
521521 async getCustomAgents ( ) : Promise < CustomAgentDescription [ ] > {
522- const customAgentYamlUri = ( await this . getTemplatesDirectoryURI ( ) ) . resolve ( 'customAgents.yml' ) ;
522+ const agentsById = new Map < string , CustomAgentDescription > ( ) ;
523+ // First, process additional (workspace) template directories to give them precedence
524+ for ( const dirPath of this . additionalTemplateDirs ) {
525+ const dirURI = URI . fromFilePath ( dirPath ) ;
526+ await this . loadCustomAgentsFromDirectory ( dirURI , agentsById ) ;
527+ }
528+ // Then process global template directory (only adding agents that don't conflict)
529+ const globalTemplateDir = await this . getTemplatesDirectoryURI ( ) ;
530+ await this . loadCustomAgentsFromDirectory ( globalTemplateDir , agentsById ) ;
531+ // Return the merged list of agents
532+ return Array . from ( agentsById . values ( ) ) ;
533+ }
534+
535+ /**
536+ * Load custom agents from a specific directory
537+ * @param directoryURI The URI of the directory to load from
538+ * @param agentsById Map to store the loaded agents by ID
539+ */
540+ protected async loadCustomAgentsFromDirectory (
541+ directoryURI : URI ,
542+ agentsById : Map < string , CustomAgentDescription >
543+ ) : Promise < void > {
544+ const customAgentYamlUri = directoryURI . resolve ( 'customAgents.yml' ) ;
523545 const yamlExists = await this . fileService . exists ( customAgentYamlUri ) ;
524546 if ( ! yamlExists ) {
525- return [ ] ;
547+ return ;
526548 }
527- const fileContent = await this . fileService . read ( customAgentYamlUri , { encoding : 'utf-8' } ) ;
549+
528550 try {
551+ const fileContent = await this . fileService . read ( customAgentYamlUri , { encoding : 'utf-8' } ) ;
529552 const doc = load ( fileContent . value ) ;
553+
530554 if ( ! Array . isArray ( doc ) || ! doc . every ( entry => CustomAgentDescription . is ( entry ) ) ) {
531- console . debug ( ' Invalid customAgents.yml file content' ) ;
532- return [ ] ;
555+ console . debug ( ` Invalid customAgents.yml file content in ${ directoryURI . toString ( ) } ` ) ;
556+ return ;
533557 }
558+
534559 const readAgents = doc as CustomAgentDescription [ ] ;
535- // make sure all agents are unique (id and name)
536- const uniqueAgentIds = new Set < string > ( ) ;
537- const uniqueAgents : CustomAgentDescription [ ] = [ ] ;
538- readAgents . forEach ( agent => {
539- if ( uniqueAgentIds . has ( agent . id ) ) {
540- return ;
560+
561+ // Add agents to the map if they don't already exist
562+ for ( const agent of readAgents ) {
563+ if ( ! agentsById . has ( agent . id ) ) {
564+ agentsById . set ( agent . id , agent ) ;
541565 }
542- uniqueAgentIds . add ( agent . id ) ;
543- uniqueAgents . push ( agent ) ;
544- } ) ;
545- return uniqueAgents ;
566+ }
546567 } catch ( e ) {
547- console . debug ( e . message , e ) ;
548- return [ ] ;
568+ console . debug ( `Error loading customAgents.yml from ${ directoryURI . toString ( ) } : ${ e . message } ` , e ) ;
549569 }
550570 }
551571
552- async openCustomAgentYaml ( ) : Promise < void > {
553- const customAgentYamlUri = ( await this . getTemplatesDirectoryURI ( ) ) . resolve ( 'customAgents.yml' ) ;
572+ /**
573+ * Returns all locations of existing customAgents.yml files and potential locations where
574+ * new customAgents.yml files could be created.
575+ *
576+ * @returns An array of objects containing the URI and whether the file exists
577+ */
578+ async getCustomAgentsLocations ( ) : Promise < { uri : URI , exists : boolean } [ ] > {
579+ const locations : { uri : URI , exists : boolean } [ ] = [ ] ;
580+ // Check global template directory
581+ const globalTemplateDir = await this . getTemplatesDirectoryURI ( ) ;
582+ const globalAgentsUri = globalTemplateDir . resolve ( 'customAgents.yml' ) ;
583+ const globalExists = await this . fileService . exists ( globalAgentsUri ) ;
584+ locations . push ( { uri : globalAgentsUri , exists : globalExists } ) ;
585+ // Check additional (workspace) template directories
586+ for ( const dirPath of this . additionalTemplateDirs ) {
587+ const dirURI = URI . fromFilePath ( dirPath ) ;
588+ const agentsUri = dirURI . resolve ( 'customAgents.yml' ) ;
589+ const exists = await this . fileService . exists ( agentsUri ) ;
590+ locations . push ( { uri : agentsUri , exists : exists } ) ;
591+ }
592+ return locations ;
593+ }
594+
595+ /**
596+ * Opens an existing customAgents.yml file at the given URI, or creates a new one if it doesn't exist.
597+ *
598+ * @param uri The URI of the customAgents.yml file to open or create
599+ */
600+ async openCustomAgentYaml ( uri : URI ) : Promise < void > {
554601 const content = dump ( [ templateEntry ] ) ;
555- if ( ! await this . fileService . exists ( customAgentYamlUri ) ) {
556- await this . fileService . createFile ( customAgentYamlUri , BinaryBuffer . fromString ( content ) ) ;
602+ if ( ! await this . fileService . exists ( uri ) ) {
603+ await this . fileService . createFile ( uri , BinaryBuffer . fromString ( content ) ) ;
557604 } else {
558- const fileContent = ( await this . fileService . readFile ( customAgentYamlUri ) ) . value ;
559- await this . fileService . writeFile ( customAgentYamlUri , BinaryBuffer . concat ( [ fileContent , BinaryBuffer . fromString ( content ) ] ) ) ;
605+ const fileContent = ( await this . fileService . readFile ( uri ) ) . value ;
606+ await this . fileService . writeFile ( uri , BinaryBuffer . concat ( [ fileContent , BinaryBuffer . fromString ( content ) ] ) ) ;
560607 }
561- const openHandler = await this . openerService . getOpener ( customAgentYamlUri ) ;
562- openHandler . open ( customAgentYamlUri ) ;
608+ const openHandler = await this . openerService . getOpener ( uri ) ;
609+ openHandler . open ( uri ) ;
563610 }
564611}
0 commit comments