diff --git a/cli/azd/cmd/copilot.go b/cli/azd/cmd/copilot.go index 3c739e498c0..203eea70042 100644 --- a/cli/azd/cmd/copilot.go +++ b/cli/azd/cmd/copilot.go @@ -12,6 +12,7 @@ import ( "github.com/azure/azure-dev/cli/azd/cmd/actions" "github.com/azure/azure-dev/cli/azd/internal" "github.com/azure/azure-dev/cli/azd/internal/agent/consent" + agentcopilot "github.com/azure/azure-dev/cli/azd/internal/agent/copilot" "github.com/azure/azure-dev/cli/azd/pkg/config" "github.com/azure/azure-dev/cli/azd/pkg/input" "github.com/azure/azure-dev/cli/azd/pkg/output" @@ -24,8 +25,10 @@ import ( func copilotActions(root *actions.ActionDescriptor) *actions.ActionDescriptor { group := root.Add("copilot", &actions.ActionDescriptorOptions{ Command: &cobra.Command{ - Use: "copilot", - Short: fmt.Sprintf("Manage Copilot agent settings. %s", output.WithWarningFormat("(Alpha)")), + Use: "copilot", + Short: fmt.Sprintf( + "Manage %s agent settings. %s", + agentcopilot.DisplayTitle, output.WithWarningFormat("(Preview)")), }, GroupingOptions: actions.CommandGroupOptions{ RootLevelHelp: actions.CmdGroupAlpha, diff --git a/cli/azd/cmd/init.go b/cli/azd/cmd/init.go index de21e5df07d..dbab9dae387 100644 --- a/cli/azd/cmd/init.go +++ b/cli/azd/cmd/init.go @@ -283,7 +283,7 @@ func (i *initAction) Run(ctx context.Context) (*actions.ActionResult, error) { if i.featuresManager.IsEnabled(agentcopilot.FeatureCopilot) { followUp += fmt.Sprintf("\n\n%s Run %s to deploy project to the cloud.", - color.HiMagentaString("Next steps:"), + output.WithHintFormat("(→) NEXT STEPS:"), output.WithHighLightFormat("azd up")) } @@ -409,7 +409,11 @@ func (i *initAction) initAppWithAgent(ctx context.Context, azdCtx *azdcontext.Az if dirty { defaultNo := false confirm := uxlib.NewConfirm(&uxlib.ConfirmOptions{ - Message: "Your working directory has uncommitted changes. Continue initializing?", + Message: "Your working directory has uncommitted changes. Continue initializing?", + HelpMessage: fmt.Sprintf( + "%s may create or modify files in your working directory. "+ + "Consider committing or stashing your changes first to avoid losing work.", + agentcopilot.DisplayTitle), DefaultValue: &defaultNo, }) result, promptErr := confirm.Ask(ctx) @@ -422,12 +426,14 @@ func (i *initAction) initAppWithAgent(ctx context.Context, azdCtx *azdcontext.Az } } - // Show alpha warning + // Show preview notice i.console.MessageUxItem(ctx, &ux.MessageTitle{ - Title: fmt.Sprintf("Agentic mode init is in preview. The agent will scan your repository and "+ - "attempt to make an azd-ready template to init.\nYou can always change permissions later "+ - "by running %s. Mistakes may occur in agent mode.\n\n"+ - "To learn more, go to %s", + Title: fmt.Sprintf( + "%s will scan your repository and help generate an azd compatible project to get you started. "+ + "This experience is currently in preview.\n\n"+ + "You can always change permissions later by running %s.\n\n"+ + "To learn more, go to %s", + agentcopilot.DisplayTitle, output.WithHighLightFormat("azd copilot consent"), output.WithLinkFormat("https://aka.ms/azd-feature-stages")), }) @@ -486,7 +492,9 @@ func (i *initAction) initAppWithAgent(ctx context.Context, azdCtx *azdcontext.Az timeDisplay := agent.FormatSessionTime(session.StartedAt) defaultYes := true confirm := uxlib.NewConfirm(&uxlib.ConfirmOptions{ - Message: fmt.Sprintf("Resume previous session from %s?", timeDisplay), + Message: fmt.Sprintf("Resume previous session from %s?", timeDisplay), + HelpMessage: "Resuming continues where you left off. " + + "Choosing no starts a fresh session.", DefaultValue: &defaultYes, }) if result, err := confirm.Ask(ctx); err == nil && result != nil && *result { @@ -561,7 +569,7 @@ func promptInitType( options := []string{ "Scan current directory", // This now covers minimal project creation too "Select a template", - fmt.Sprintf("Use agent mode %s", color.YellowString("(Alpha)")), + fmt.Sprintf("Set up with %s %s", agentcopilot.DisplayTitle, color.YellowString("(Preview)")), } selection, err := console.Select(ctx, input.ConsoleOptions{ @@ -594,8 +602,8 @@ func promptInitType( return initUnknown, fmt.Errorf("failed to save config: %w", err) } - console.Message(ctx, "\nThe azd agent feature has been enabled to support this new experience."+ - " To turn off in the future run `azd config unset alpha.llm`.") + console.Message(ctx, fmt.Sprintf("\n%s has been enabled to support this new experience."+ + " To turn off in the future run `azd config unset alpha.llm`.", agentcopilot.DisplayTitle)) err = azdConfig.Set(agentcopilot.ConfigKeyModelType, "copilot") if err != nil { @@ -607,8 +615,10 @@ func promptInitType( return initUnknown, fmt.Errorf("failed to save config: %w", err) } - console.Message(ctx, fmt.Sprintf("\nGitHub Copilot has been enabled to support this new experience."+ - " To turn off in the future run `azd config unset %s`.", agentcopilot.ConfigKeyModelType)) + console.Message(ctx, fmt.Sprintf( + "\n%s has been enabled to support this new experience."+ + " To turn off in the future run `azd config unset %s`.", + agentcopilot.DisplayTitle, agentcopilot.ConfigKeyModelType)) } return initWithAgent, nil diff --git a/cli/azd/cmd/middleware/error.go b/cli/azd/cmd/middleware/error.go index 60b1c67d6c1..9d3b74fe210 100644 --- a/cli/azd/cmd/middleware/error.go +++ b/cli/azd/cmd/middleware/error.go @@ -39,7 +39,6 @@ import ( "github.com/azure/azure-dev/cli/azd/pkg/tools/maven" "github.com/azure/azure-dev/cli/azd/pkg/tools/pack" uxlib "github.com/azure/azure-dev/cli/azd/pkg/ux" - "github.com/fatih/color" "go.opentelemetry.io/otel/codes" ) @@ -262,7 +261,8 @@ func (e *ErrorMiddleware) Run(ctx context.Context, next NextFn) (*actions.Action troubleshootPrompt := e.buildTroubleshootingPrompt(originalError) previousError = originalError - e.console.Message(ctx, color.MagentaString("Preparing Copilot to troubleshoot error...")) + e.console.Message(ctx, output.WithHintFormat( + "Preparing %s to troubleshoot error...", agentcopilot.DisplayTitle)) agentResult, err := azdAgent.SendMessage(ctx, troubleshootPrompt) if err != nil { @@ -337,7 +337,8 @@ func (e *ErrorMiddleware) promptTroubleshootConsent(ctx context.Context) (bool, // Check for saved "always allow" preference if val, ok := userConfig.GetString(agentcopilot.ConfigKeyErrorHandlingFix); ok && val == "allow" { e.console.Message(ctx, output.WithWarningFormat( - "Agent troubleshooting is set to always allow. To change, run %s.\n", + "%s troubleshooting is set to always allow. To change, run %s.\n", + agentcopilot.DisplayTitle, output.WithHighLightFormat( fmt.Sprintf("azd config unset %s", agentcopilot.ConfigKeyErrorHandlingFix)), )) @@ -347,7 +348,8 @@ func (e *ErrorMiddleware) promptTroubleshootConsent(ctx context.Context) (bool, // Check for saved "always skip" preference if val, ok := userConfig.GetString(agentcopilot.ConfigKeyErrorHandlingTroubleshootSkip); ok && val == "allow" { e.console.Message(ctx, output.WithWarningFormat( - "Agent troubleshooting is set to always skip. To change, run %s.\n", + "%s troubleshooting is set to always skip. To change, run %s.\n", + agentcopilot.DisplayTitle, output.WithHighLightFormat( fmt.Sprintf("azd config unset %s", agentcopilot.ConfigKeyErrorHandlingTroubleshootSkip)), )) @@ -362,10 +364,11 @@ func (e *ErrorMiddleware) promptTroubleshootConsent(ctx context.Context) (bool, } selector := uxlib.NewSelect(&uxlib.SelectOptions{ - Message: "Would you like the agent to troubleshoot this error?", + Message: fmt.Sprintf("Would you like %s to troubleshoot this error?", agentcopilot.DisplayTitle), HelpMessage: fmt.Sprintf( - "The agent will explain the error and offer to fix it. "+ + "%s will explain the error and offer to fix it. "+ "Edit permissions anytime by running %s.", + agentcopilot.DisplayTitle, output.WithHighLightFormat("azd copilot consent")), Choices: choices, EnableFiltering: new(false), diff --git a/cli/azd/cmd/testdata/TestFigSpec.ts b/cli/azd/cmd/testdata/TestFigSpec.ts index 759f6c9477e..6f37fe88e27 100644 --- a/cli/azd/cmd/testdata/TestFigSpec.ts +++ b/cli/azd/cmd/testdata/TestFigSpec.ts @@ -1568,7 +1568,7 @@ const completionSpec: Fig.Spec = { }, { name: ['copilot'], - description: 'Manage Copilot agent settings. (Alpha)', + description: 'Manage GitHub Copilot agent settings. (Preview)', subcommands: [ { name: ['consent'], @@ -3409,7 +3409,7 @@ const completionSpec: Fig.Spec = { }, { name: ['copilot'], - description: 'Manage Copilot agent settings. (Alpha)', + description: 'Manage GitHub Copilot agent settings. (Preview)', subcommands: [ { name: ['consent'], diff --git a/cli/azd/cmd/testdata/TestUsage-azd-copilot.snap b/cli/azd/cmd/testdata/TestUsage-azd-copilot.snap index e566a34d84e..ed69deb7e2b 100644 --- a/cli/azd/cmd/testdata/TestUsage-azd-copilot.snap +++ b/cli/azd/cmd/testdata/TestUsage-azd-copilot.snap @@ -1,5 +1,5 @@ -Manage Copilot agent settings. (Alpha) +Manage GitHub Copilot agent settings. (Preview) Usage azd copilot [command] diff --git a/cli/azd/cmd/testdata/TestUsage-azd.snap b/cli/azd/cmd/testdata/TestUsage-azd.snap index 1fc3ce6c267..dc3cef009f4 100644 --- a/cli/azd/cmd/testdata/TestUsage-azd.snap +++ b/cli/azd/cmd/testdata/TestUsage-azd.snap @@ -35,7 +35,7 @@ Commands template : Find and view template details. Enabled alpha commands - copilot : Manage Copilot agent settings. (Alpha) + copilot : Manage GitHub Copilot agent settings. (Preview) mcp : Manage Model Context Protocol (MCP) server. (Alpha) Enabled extensions commands diff --git a/cli/azd/internal/agent/copilot/cli.go b/cli/azd/internal/agent/copilot/cli.go index 53bbf784b12..9d20211ee70 100644 --- a/cli/azd/internal/agent/copilot/cli.go +++ b/cli/azd/internal/agent/copilot/cli.go @@ -156,13 +156,13 @@ func (c *CopilotCLI) ensureInstalled(ctx context.Context) error { return fmt.Errorf("creating copilot CLI directory: %w", err) } - c.console.ShowSpinner(ctx, "Downloading Copilot CLI", input.Step) + c.console.ShowSpinner(ctx, "Downloading GitHub Copilot CLI", input.Step) err := downloadCopilotCLI(ctx, c.transporter, cliVersion, cliPath) if err != nil { - c.console.StopSpinner(ctx, "Downloading Copilot CLI", input.StepFailed) + c.console.StopSpinner(ctx, "Downloading GitHub Copilot CLI", input.StepFailed) return fmt.Errorf("downloading copilot CLI: %w", err) } - c.console.StopSpinner(ctx, "Downloading Copilot CLI", input.StepDone) + c.console.StopSpinner(ctx, "Downloading GitHub Copilot CLI", input.StepDone) c.console.Message(ctx, "") } diff --git a/cli/azd/internal/agent/copilot/config_keys.go b/cli/azd/internal/agent/copilot/config_keys.go index fc3ec54ed8d..ede4dc461a1 100644 --- a/cli/azd/internal/agent/copilot/config_keys.go +++ b/cli/azd/internal/agent/copilot/config_keys.go @@ -6,6 +6,10 @@ package copilot // Config key constants for the copilot.* namespace in azd user configuration. // All keys are built from shared prefix constants so renaming any level requires a single change. const ( + // DisplayTitle is the user-facing brand name for the agent experience. + // Change this single constant to rebrand across all UI text. + DisplayTitle = "GitHub Copilot" + // ConfigRoot is the root namespace for all Copilot agent configuration keys. ConfigRoot = "copilot" diff --git a/cli/azd/internal/agent/copilot/copilot_client.go b/cli/azd/internal/agent/copilot/copilot_client.go index 42318c2a051..c2febbea213 100644 --- a/cli/azd/internal/agent/copilot/copilot_client.go +++ b/cli/azd/internal/agent/copilot/copilot_client.go @@ -70,8 +70,8 @@ func (m *CopilotClientManager) Start(ctx context.Context) error { if err := m.client.Start(ctx); err != nil { log.Printf("[copilot-client] Start failed: %v", err) return fmt.Errorf( - "failed to start Copilot agent runtime: %w", - err, + "failed to start %s agent runtime: %w", + DisplayTitle, err, ) } log.Printf("[copilot-client] Started successfully (state=%s)", m.client.State()) @@ -95,7 +95,7 @@ func (m *CopilotClientManager) Client() *copilot.Client { func (m *CopilotClientManager) GetAuthStatus(ctx context.Context) (*copilot.GetAuthStatusResponse, error) { status, err := m.client.GetAuthStatus(ctx) if err != nil { - return nil, fmt.Errorf("failed to check Copilot auth status: %w", err) + return nil, fmt.Errorf("failed to check %s auth status: %w", DisplayTitle, err) } return status, nil } @@ -104,7 +104,7 @@ func (m *CopilotClientManager) GetAuthStatus(ctx context.Context) (*copilot.GetA func (m *CopilotClientManager) ListModels(ctx context.Context) ([]copilot.ModelInfo, error) { models, err := m.client.ListModels(ctx) if err != nil { - return nil, fmt.Errorf("failed to list Copilot models: %w", err) + return nil, fmt.Errorf("failed to list %s models: %w", DisplayTitle, err) } return models, nil } diff --git a/cli/azd/internal/agent/copilot/feature.go b/cli/azd/internal/agent/copilot/feature.go index c97cbe386a0..96d10a11f1d 100644 --- a/cli/azd/internal/agent/copilot/feature.go +++ b/cli/azd/internal/agent/copilot/feature.go @@ -20,8 +20,9 @@ func IsFeatureEnabled(alphaManager *alpha.FeatureManager) error { panic("alphaManager cannot be nil") } if !alphaManager.IsEnabled(FeatureCopilot) { - return fmt.Errorf("the Copilot agent feature is not enabled. Please enable it using the command: \"%s\"", - alpha.GetEnableCommand(FeatureCopilot)) + return fmt.Errorf( + "the %s feature is not enabled. Please enable it using the command: \"%s\"", + DisplayTitle, alpha.GetEnableCommand(FeatureCopilot)) } return nil } diff --git a/cli/azd/internal/agent/copilot/session_config.go b/cli/azd/internal/agent/copilot/session_config.go index d301337f09e..2841131ae76 100644 --- a/cli/azd/internal/agent/copilot/session_config.go +++ b/cli/azd/internal/agent/copilot/session_config.go @@ -67,7 +67,18 @@ func (b *SessionConfigBuilder) Build( Do not respond to requests unrelated to application development, Azure services, or deployment. For unrelated requests, briefly explain that you are focused on Azure application development - and suggest the user use a general-purpose assistant for other topics.` + and suggest the user use a general-purpose assistant for other topics. + + When prompting the user to choose Azure subscriptions, regions, or resources, follow these guidelines: + - Use short, focused prompts (e.g., "Which subscription would you like to use?") paired with + well-formatted choices via the ask_user tool with the choices field. + - Do NOT embed long inline lists of options inside a text message with an open-ended question. + - Keep prompt messages concise — move details into choices, not the question text. + - Format Azure subscriptions as: () + Example: "My Dev Subscription (a1b2c3d4-e5f6-7890-abcd-ef1234567890)" + - Format Azure regions as: () + Example: "East US 2 (eastus2)" + - Always use actual entity names and identifiers from Azure APIs, never placeholders.` if msg, ok := userConfig.GetString(ConfigKeySystemMessage); ok && msg != "" { systemContent += "\n\n" + msg diff --git a/cli/azd/internal/agent/copilot_agent.go b/cli/azd/internal/agent/copilot_agent.go index d2095e68f15..d27fea96cac 100644 --- a/cli/azd/internal/agent/copilot_agent.go +++ b/cli/azd/internal/agent/copilot_agent.go @@ -767,7 +767,10 @@ func (a *CopilotAgent) createUserInputHandler(ctx context.Context) copilot.UserI selected := choices[*idx].Value if selected == freeformValue { - prompt := uxlib.NewPrompt(&uxlib.PromptOptions{Message: question}) + prompt := uxlib.NewPrompt(&uxlib.PromptOptions{ + Message: question, + IgnoreHintKeys: true, + }) answer, err := prompt.Ask(ctx) fmt.Println() if err != nil { @@ -779,7 +782,12 @@ func (a *CopilotAgent) createUserInputHandler(ctx context.Context) copilot.UserI return copilot.UserInputResponse{Answer: selected}, nil } - prompt := uxlib.NewPrompt(&uxlib.PromptOptions{Message: question}) + // TODO: IgnoreHintKeys should not be needed — Prompt should auto-suppress + // hint key handling when no HelpMessage is provided. + prompt := uxlib.NewPrompt(&uxlib.PromptOptions{ + Message: question, + IgnoreHintKeys: true, + }) answer, err := prompt.Ask(ctx) fmt.Println() if err != nil { @@ -850,11 +858,14 @@ func (a *CopilotAgent) ensureAuthenticated(ctx context.Context) error { // Not authenticated — prompt to sign in a.console.Message(ctx, "") - a.console.Message(ctx, output.WithWarningFormat("Not authenticated with GitHub Copilot")) + a.console.Message(ctx, output.WithWarningFormat("Not authenticated with %s", agentcopilot.DisplayTitle)) a.console.Message(ctx, "") confirm := uxlib.NewConfirm(&uxlib.ConfirmOptions{ - Message: "Sign in to GitHub Copilot? (opens browser)", + Message: fmt.Sprintf("Sign in to %s? (opens browser)", agentcopilot.DisplayTitle), + HelpMessage: fmt.Sprintf( + "%s requires GitHub authentication to access AI models and agent capabilities.", + agentcopilot.DisplayTitle), DefaultValue: uxlib.Ptr(true), }) @@ -864,18 +875,18 @@ func (a *CopilotAgent) ensureAuthenticated(ctx context.Context) error { } if shouldLogin == nil || !*shouldLogin { - return fmt.Errorf("GitHub Copilot authentication is required to continue") + return fmt.Errorf("%s authentication is required to continue", agentcopilot.DisplayTitle) } a.console.Message(ctx, "") if err := a.cli.Login(ctx); err != nil { - return fmt.Errorf("GitHub Copilot sign-in failed: %w", err) + return fmt.Errorf("%s sign-in failed: %w", agentcopilot.DisplayTitle, err) } // Verify auth succeeded authStatus, err = a.clientManager.GetAuthStatus(ctx) if err != nil || !authStatus.IsAuthenticated { - return fmt.Errorf("GitHub Copilot authentication was not completed") + return fmt.Errorf("%s authentication was not completed", agentcopilot.DisplayTitle) } a.console.Message(ctx, "") @@ -889,7 +900,7 @@ func (a *CopilotAgent) ensurePlugins(ctx context.Context) { if _, err := exec.LookPath("copilot"); err != nil { log.Printf("[copilot] 'copilot' CLI not found in PATH — skipping plugin management") a.console.Message(ctx, output.WithWarningFormat( - "The Copilot CLI is not installed. Some features may be limited.\n"+ + "The GitHub Copilot CLI is not installed. Some features may be limited.\n"+ "Install it with: npm install -g @github/copilot")) return } @@ -933,12 +944,13 @@ func (a *CopilotAgent) promptPluginInstall(ctx context.Context, plugin pluginSpe a.console.Message(ctx, "") confirm := uxlib.NewConfirm(&uxlib.ConfirmOptions{ - Message: fmt.Sprintf("The %s plugin is not installed. Would you like to install it?", plugin.Name), - HelpMessage: fmt.Sprintf( - "The %s plugin provides Azure-specific skills for infrastructure generation, "+ - "project validation, and deployment guidance. Without it, the agent will have "+ - "limited Azure capabilities. The plugin is installed globally at ~/.copilot/installed-plugins/.", - plugin.Name), + Message: fmt.Sprintf( + "%s works better with the %s plugin. Would you like to install it?", + agentcopilot.DisplayTitle, plugin.Name), + HelpMessage: "The Azure plugin provides:\n" + + "• Azure MCP server that contains additional tools for Azure\n" + + "• Skills that streamline and provide better results for creating, " + + "validating, and deploying applications to Azure", DefaultValue: &defaultYes, }) diff --git a/cli/azd/pkg/output/colors.go b/cli/azd/pkg/output/colors.go index f9463affcb3..a5466b559b7 100644 --- a/cli/azd/pkg/output/colors.go +++ b/cli/azd/pkg/output/colors.go @@ -60,14 +60,6 @@ func WithBackticks(s string) string { return fmt.Sprintf("`%s`", s) } -func AzdLabel() string { - return "[azd]" -} - -func AzdAgentLabel() string { - return color.HiMagentaString(fmt.Sprintf("🤖 %s Agent", AzdLabel())) -} - // WithMarkdown converts markdown to terminal-friendly colorized output using glamour. // This provides rich markdown rendering including bold, italic, code blocks, headers, etc. func WithMarkdown(markdownText string) string { diff --git a/cli/azd/pkg/ux/confirm.go b/cli/azd/pkg/ux/confirm.go index f68e8100887..6fdf419446a 100644 --- a/cli/azd/pkg/ux/confirm.go +++ b/cli/azd/pkg/ux/confirm.go @@ -191,6 +191,11 @@ func (p *Confirm) Render(printer Printer) error { // Message printer.Fprintf("%s", BoldString("%s: ", p.options.Message)) + // Hint indicator + if !p.cancelled && !p.complete && p.options.HelpMessage != "" { + printer.Fprintf("%s ", output.WithGrayFormat("[type ? for hint]")) + } + // Hint if !p.cancelled && !p.complete && p.options.Hint != "" { printer.Fprintf("%s ", output.WithHighLightFormat(p.options.Hint)) diff --git a/cli/azd/pkg/ux/multi_select.go b/cli/azd/pkg/ux/multi_select.go index 1da97b1d632..271ccb0de3f 100644 --- a/cli/azd/pkg/ux/multi_select.go +++ b/cli/azd/pkg/ux/multi_select.go @@ -483,5 +483,9 @@ func (p *MultiSelect) renderFooter(printer Printer) { printer.Fprintln(output.WithGrayFormat("───────────────────────────────────────")) printer.Fprintln(output.WithGrayFormat("Use arrows to move, use space to select")) printer.Fprintln(output.WithGrayFormat("Use left/right to select none/all")) - printer.Fprintln(output.WithGrayFormat("Use enter to submit, type ? for help")) + if p.options.HelpMessage != "" { + printer.Fprintln(output.WithGrayFormat("Use enter to submit, type ? for help")) + } else { + printer.Fprintln(output.WithGrayFormat("Use enter to submit")) + } } diff --git a/cli/azd/pkg/ux/prompt.go b/cli/azd/pkg/ux/prompt.go index a0854cc5cb1..0a055d1dedd 100644 --- a/cli/azd/pkg/ux/prompt.go +++ b/cli/azd/pkg/ux/prompt.go @@ -27,7 +27,8 @@ type PromptOptions struct { Message string // The optional message to display when the user types ? (default: "") HelpMessage string - // The optional hint text that display after the message (default: "[Type ? for hint]") + // The optional hint text displayed after the message. + // When empty (default), auto-generated as "[Type ? for hint]" only if HelpMessage is set. Hint string // The optional placeholder text to display when the value is empty (default: "") PlaceHolder string @@ -53,7 +54,7 @@ var DefaultPromptOptions PromptOptions = PromptOptions{ Required: false, ValidationMessage: "Invalid input", RequiredMessage: "This field is required", - Hint: "[Type ? for hint]", + Hint: "", ClearOnCompletion: false, IgnoreHintKeys: false, ValidationFn: func(input string) (bool, string) { @@ -88,6 +89,11 @@ func NewPrompt(options *PromptOptions) *Prompt { panic(err) } + // Auto-generate hint text only when a help message is available + if mergedOptions.Hint == "" && mergedOptions.HelpMessage != "" { + mergedOptions.Hint = "[Type ? for hint]" + } + return &Prompt{ input: internal.NewInput(), options: &mergedOptions, diff --git a/cli/azd/pkg/ux/select.go b/cli/azd/pkg/ux/select.go index 7478cfac5c6..7e5a8de904e 100644 --- a/cli/azd/pkg/ux/select.go +++ b/cli/azd/pkg/ux/select.go @@ -405,5 +405,9 @@ func (p *Select) renderFooter(printer Printer) { printer.Fprintln() printer.Fprintln(output.WithGrayFormat("───────────────────────────────────")) - printer.Fprintln(output.WithGrayFormat("Use arrows to move, type ? for hint")) + if p.options.HelpMessage != "" { + printer.Fprintln(output.WithGrayFormat("Use arrows to move, type ? for hint")) + } else { + printer.Fprintln(output.WithGrayFormat("Use arrows to move")) + } }