1414 * limitations under the License.
1515 */
1616
17- import { join } from 'node:path' ;
18- import { mkdirSync , writeFileSync , readFileSync } from 'node:fs' ;
17+ import { join , resolve } from 'node:path' ;
18+ import { mkdirSync , writeFileSync , readFileSync , existsSync } from 'node:fs' ;
1919import { SfCommand , Flags } from '@salesforce/sf-plugins-core' ;
20- import { Messages , SfError } from '@salesforce/core' ;
20+ import { generateApiName , Messages , SfError } from '@salesforce/core' ;
2121import { Agent , AgentJobSpec } from '@salesforce/agents' ;
2222import YAML from 'yaml' ;
23- import { FlaggablePrompt , promptForFlag } from '../../../flags.js' ;
23+ import { input as inquirerInput } from '@inquirer/prompts' ;
24+ import { theme } from '../../../inquirer-theme.js' ;
25+ import { FlaggablePrompt , promptForFlag , promptForYamlFile } from '../../../flags.js' ;
2426
2527Messages . importMessagesDirectoryFromMetaUrl ( import . meta. url ) ;
2628const messages = Messages . loadMessages ( '@salesforce/plugin-agent' , 'agent.generate.authoring-bundle' ) ;
@@ -39,6 +41,9 @@ export default class AgentGenerateAuthoringBundle extends SfCommand<AgentGenerat
3941
4042 public static readonly flags = {
4143 'target-org' : Flags . requiredOrg ( ) ,
44+ 'api-name' : Flags . string ( {
45+ summary : messages . getMessage ( 'flags.api-name.summary' ) ,
46+ } ) ,
4247 'api-version' : Flags . orgApiVersion ( ) ,
4348 spec : Flags . file ( {
4449 summary : messages . getMessage ( 'flags.spec.summary' ) ,
@@ -58,13 +63,36 @@ export default class AgentGenerateAuthoringBundle extends SfCommand<AgentGenerat
5863 private static readonly FLAGGABLE_PROMPTS = {
5964 name : {
6065 message : messages . getMessage ( 'flags.name.summary' ) ,
61- promptMessage : messages . getMessage ( 'flags.name.prompt' ) ,
62- validate : ( d : string ) : boolean | string => d . length > 0 || 'Name cannot be empty' ,
66+ validate : ( d : string ) : boolean | string =>
67+ d . trim ( ) . length > 0 || 'Name cannot be empty or contain only whitespace ' ,
6368 required : true ,
6469 } ,
70+ 'api-name' : {
71+ message : messages . getMessage ( 'flags.api-name.summary' ) ,
72+ promptMessage : messages . getMessage ( 'flags.api-name.prompt' ) ,
73+ validate : ( d : string ) : boolean | string => {
74+ if ( d . length === 0 ) {
75+ return true ;
76+ }
77+ if ( d . length > 80 ) {
78+ return 'API name cannot be over 80 characters.' ;
79+ }
80+ const regex = / ^ [ A - Z a - z ] [ A - Z a - z 0 - 9 _ ] * [ A - Z a - z 0 - 9 ] + $ / ;
81+ if ( ! regex . test ( d ) ) {
82+ return 'Invalid API name.' ;
83+ }
84+ return true ;
85+ } ,
86+ } ,
6587 spec : {
6688 message : messages . getMessage ( 'flags.spec.summary' ) ,
67- validate : ( d : string ) : boolean | string => d . length > 0 || 'Spec file path cannot be empty' ,
89+ validate : ( d : string ) : boolean | string => {
90+ const specPath = resolve ( d ) ;
91+ if ( ! existsSync ( specPath ) ) {
92+ return 'Please enter an existing agent spec (yaml) file' ;
93+ }
94+ return true ;
95+ } ,
6896 required : true ,
6997 } ,
7098 } satisfies Record < string , FlaggablePrompt > ;
@@ -74,12 +102,25 @@ export default class AgentGenerateAuthoringBundle extends SfCommand<AgentGenerat
74102 const { 'output-dir' : outputDir , 'target-org' : targetOrg } = flags ;
75103
76104 // If we don't have a spec yet, prompt for it
77- const spec = flags [ ' spec' ] ?? ( await promptForFlag ( AgentGenerateAuthoringBundle . FLAGGABLE_PROMPTS [ 'spec' ] ) ) ;
105+ const spec = flags . spec ?? ( await promptForYamlFile ( AgentGenerateAuthoringBundle . FLAGGABLE_PROMPTS [ 'spec' ] ) ) ;
78106
79107 // If we don't have a name yet, prompt for it
80- const name = (
81- flags [ 'name' ] ?? ( await promptForFlag ( AgentGenerateAuthoringBundle . FLAGGABLE_PROMPTS [ 'name' ] ) )
82- ) . replaceAll ( ' ' , '_' ) ;
108+ const name = flags [ 'name' ] ?? ( await promptForFlag ( AgentGenerateAuthoringBundle . FLAGGABLE_PROMPTS [ 'name' ] ) ) ;
109+
110+ // If we don't have an api name yet, prompt for it
111+ let bundleApiName = flags [ 'api-name' ] ;
112+ if ( ! bundleApiName ) {
113+ bundleApiName = generateApiName ( name ) ;
114+ const promptedValue = await inquirerInput ( {
115+ message : messages . getMessage ( 'flags.api-name.prompt' ) ,
116+ validate : AgentGenerateAuthoringBundle . FLAGGABLE_PROMPTS [ 'api-name' ] . validate ,
117+ default : bundleApiName ,
118+ theme,
119+ } ) ;
120+ if ( promptedValue ?. length ) {
121+ bundleApiName = promptedValue ;
122+ }
123+ }
83124
84125 try {
85126 // Get default output directory if not specified
0 commit comments