From cb5a3e0e70c853eb2ab83be253e8b6fbb3a0613d Mon Sep 17 00:00:00 2001 From: trangevi Date: Thu, 5 Feb 2026 09:43:59 -0800 Subject: [PATCH 1/8] Improving handling around model selection Signed-off-by: trangevi --- .../azure.ai.agents/internal/cmd/init.go | 253 +++++++++++++++++- .../internal/pkg/azure/ai/model_catalog.go | 191 +++++++------ 2 files changed, 351 insertions(+), 93 deletions(-) diff --git a/cli/azd/extensions/azure.ai.agents/internal/cmd/init.go b/cli/azd/extensions/azure.ai.agents/internal/cmd/init.go index 8a322daa452..36a6e4a384c 100644 --- a/cli/azd/extensions/azure.ai.agents/internal/cmd/init.go +++ b/cli/azd/extensions/azure.ai.agents/internal/cmd/init.go @@ -1917,7 +1917,8 @@ func (a *InitAction) loadAiCatalog(ctx context.Context) error { return fmt.Errorf("failed to start spinner: %w", err) } - aiModelCatalog, err := a.modelCatalogService.ListAllModels(ctx, a.azureContext.Scope.SubscriptionId, a.azureContext.Scope.Location) + // aiModelCatalog, err := a.modelCatalogService.ListAllModels(ctx, a.azureContext.Scope.SubscriptionId, a.azureContext.Scope.Location) + aiModelCatalog, err := a.modelCatalogService.ListAllModels(ctx, a.azureContext.Scope.SubscriptionId, "") if err != nil { return fmt.Errorf("failed to load the model catalog: %w", err) } @@ -2108,13 +2109,13 @@ func (a *InitAction) getModelDeploymentDetails(ctx context.Context, model agent_ return nil, fmt.Errorf("failed to get model details: %w", err) } - message := fmt.Sprintf("Enter model deployment name for model '%s' (defaults to model name)", model.Id) + message := fmt.Sprintf("Enter model deployment name for model '%s' (defaults to model name)", modelDetails.Name) modelDeploymentInput, err := a.azdClient.Prompt().Prompt(ctx, &azdext.PromptRequest{ Options: &azdext.PromptOptions{ Message: message, IgnoreHintKeys: true, - DefaultValue: model.Id, + DefaultValue: modelDetails.Name, }, }) if err != nil { @@ -2126,7 +2127,7 @@ func (a *InitAction) getModelDeploymentDetails(ctx context.Context, model agent_ return &project.Deployment{ Name: modelDeployment, Model: project.DeploymentModel{ - Name: model.Id, + Name: modelDetails.Name, Format: modelDetails.Format, Version: modelDetails.Version, }, @@ -2149,10 +2150,35 @@ func (a *InitAction) getModelDetails(ctx context.Context, modelName string) (*ai var model *ai.AiModel model, exists := a.modelCatalog[modelName] if !exists { - return nil, fmt.Errorf("The model '%s' could not be found in the model catalog", modelName) + // Model not found - prompt user for alternative + selectedModel, err := a.promptForAlternativeModel(ctx, modelName) + if err != nil { + return nil, err + } + if selectedModel == nil { + return nil, fmt.Errorf("no model selected, exiting") + } + model = selectedModel + modelName = model.Name + } + + // Check if the model is available in the current location + currentLocation := a.azureContext.Scope.Location + if _, hasLocation := model.ModelDetailsByLocation[currentLocation]; !hasLocation { + // Model not available in current location - prompt user for action + resolvedModel, resolvedLocation, err := a.promptForModelLocationMismatch(ctx, model, currentLocation) + if err != nil { + return nil, err + } + if resolvedModel == nil { + return nil, fmt.Errorf("model unavailable in current location and no alternative selected, exiting") + } + model = resolvedModel + modelName = model.Name + currentLocation = resolvedLocation } - availableVersions, defaultVersion, err := a.modelCatalogService.ListModelVersions(ctx, model) + availableVersions, defaultVersion, err := a.modelCatalogService.ListModelVersions(ctx, model, currentLocation) if err != nil { return nil, fmt.Errorf("listing versions for model '%s': %w", modelName, err) } @@ -2162,7 +2188,7 @@ func (a *InitAction) getModelDetails(ctx context.Context, modelName string) (*ai return nil, err } - availableSkus, err := a.modelCatalogService.ListModelSkus(ctx, model, modelVersion) + availableSkus, err := a.modelCatalogService.ListModelSkus(ctx, model, currentLocation, modelVersion) if err != nil { return nil, fmt.Errorf("listing SKUs for model '%s': %w", modelName, err) } @@ -2214,6 +2240,219 @@ func (a *InitAction) getModelDetails(ctx context.Context, modelName string) (*ai return modelDeployment, nil } +func (a *InitAction) promptForAlternativeModel(ctx context.Context, originalModelName string) (*ai.AiModel, error) { + fmt.Println(output.WithErrorFormat("The model '%s' could not be found in the model catalog for your subscription in any region.\n", originalModelName)) + + // Ask if they want to select a different model or exit + choices := []*azdext.SelectChoice{ + {Label: "Select a different model", Value: "select"}, + {Label: "Exit", Value: "exit"}, + } + + defaultIndex := int32(1) + selectResp, err := a.azdClient.Prompt().Select(ctx, &azdext.SelectRequest{ + Options: &azdext.SelectOptions{ + Message: "Would you like to select a different model or exit?", + Choices: choices, + SelectedIndex: &defaultIndex, + }, + }) + if err != nil { + return nil, fmt.Errorf("failed to prompt for model selection choice: %w", err) + } + + if choices[*selectResp.Value].Value == "exit" { + return nil, nil + } + + // Ask if they want all models or region-specific models + regionChoices := []*azdext.SelectChoice{ + {Label: fmt.Sprintf("Models available in my current region (%s)", a.azureContext.Scope.Location), Value: "region"}, + {Label: "All available models", Value: "all"}, + } + + regionResp, err := a.azdClient.Prompt().Select(ctx, &azdext.SelectRequest{ + Options: &azdext.SelectOptions{ + Message: "Which models would you like to explore?", + Choices: regionChoices, + }, + }) + if err != nil { + return nil, fmt.Errorf("failed to prompt for region choice: %w", err) + } + + // Get the list of model names based on the choice + var modelNames []string + if regionChoices[*regionResp.Value].Value == "region" { + // Filter models that have the current region + for name, model := range a.modelCatalog { + if _, hasLocation := model.ModelDetailsByLocation[a.azureContext.Scope.Location]; hasLocation { + modelNames = append(modelNames, name) + } + } + } else { + // All models + for name := range a.modelCatalog { + modelNames = append(modelNames, name) + } + } + + if len(modelNames) == 0 { + return nil, fmt.Errorf("no models available for selection") + } + + // Sort the model names + slices.Sort(modelNames) + + // Create choices for the model selection + modelChoices := make([]*azdext.SelectChoice, len(modelNames)) + for i, name := range modelNames { + modelChoices[i] = &azdext.SelectChoice{ + Label: name, + Value: name, + } + } + + modelResp, err := a.azdClient.Prompt().Select(ctx, &azdext.SelectRequest{ + Options: &azdext.SelectOptions{ + Message: "Select a model", + Choices: modelChoices, + }, + }) + if err != nil { + return nil, fmt.Errorf("failed to prompt for model selection: %w", err) + } + + selectedModelName := modelNames[*modelResp.Value] + return a.modelCatalog[selectedModelName], nil +} + +func (a *InitAction) promptForModelLocationMismatch(ctx context.Context, model *ai.AiModel, currentLocation string) (*ai.AiModel, string, error) { + fmt.Println(output.WithErrorFormat("The model '%s' is not available in your current location '%s'.", model.Name, currentLocation)) + fmt.Println("Would you like you use a different model, or select a different location?") + fmt.Println(output.WithWarningFormat( + "WARNING: If you choose to select a different location, this will change your currently configured " + + "region in your AZD environment. If you have already created a Foundry Project in your currently " + + "configured region, this will cause failures, and you should either choose a different model or " + + "create a new project in a different region where your desired model is available.")) + + // Ask what they want to do + choices := []*azdext.SelectChoice{ + {Label: "Select a different model available in this location", Value: "model"}, + {Label: "Select a different location for this model", Value: "location"}, + {Label: "Exit", Value: "exit"}, + } + + defaultIndex := int32(2) + selectResp, err := a.azdClient.Prompt().Select(ctx, &azdext.SelectRequest{ + Options: &azdext.SelectOptions{ + Message: "What would you like to do?", + Choices: choices, + SelectedIndex: &defaultIndex, + }, + }) + if err != nil { + return nil, "", fmt.Errorf("failed to prompt for action choice: %w", err) + } + + selectedChoice := choices[*selectResp.Value].Value + + if selectedChoice == "exit" { + return nil, "", nil + } + + if selectedChoice == "location" { + // Get available locations for this model + var locationNames []string + for locationName := range model.ModelDetailsByLocation { + locationNames = append(locationNames, locationName) + } + + if len(locationNames) == 0 { + return nil, "", fmt.Errorf("no locations available for model '%s'", model.Name) + } + + slices.Sort(locationNames) + + // Create choices for location selection + locationChoices := make([]*azdext.SelectChoice, len(locationNames)) + for i, name := range locationNames { + locationChoices[i] = &azdext.SelectChoice{ + Label: name, + Value: name, + } + } + + locationResp, err := a.azdClient.Prompt().Select(ctx, &azdext.SelectRequest{ + Options: &azdext.SelectOptions{ + Message: fmt.Sprintf("Select a location for model '%s'", model.Name), + Choices: locationChoices, + }, + }) + if err != nil { + return nil, "", fmt.Errorf("failed to prompt for location selection: %w", err) + } + + selectedLocation := locationNames[*locationResp.Value] + + // Update the azd environment with the new location + workflow := &azdext.Workflow{ + Name: "env set", + Steps: []*azdext.WorkflowStep{ + {Command: &azdext.WorkflowCommand{Args: []string{"env", "set", "AZURE_LOCATION", selectedLocation}}}, + }, + } + + _, err = a.azdClient.Workflow().Run(ctx, &azdext.RunWorkflowRequest{ + Workflow: workflow, + }) + if err != nil { + return nil, "", fmt.Errorf("failed to update AZURE_LOCATION in azd environment: %w", err) + } + + fmt.Printf("Updated AZURE_LOCATION to '%s' in your azd environment.\n", selectedLocation) + + return model, selectedLocation, nil + } + + // selectedChoice == "model" + // Get models available in the current location + var modelNames []string + for name, m := range a.modelCatalog { + if _, hasLocation := m.ModelDetailsByLocation[currentLocation]; hasLocation { + modelNames = append(modelNames, name) + } + } + + if len(modelNames) == 0 { + return nil, "", fmt.Errorf("no models available in location '%s'", currentLocation) + } + + slices.Sort(modelNames) + + // Create choices for model selection + modelChoices := make([]*azdext.SelectChoice, len(modelNames)) + for i, name := range modelNames { + modelChoices[i] = &azdext.SelectChoice{ + Label: name, + Value: name, + } + } + + modelResp, err := a.azdClient.Prompt().Select(ctx, &azdext.SelectRequest{ + Options: &azdext.SelectOptions{ + Message: fmt.Sprintf("Select a model available in '%s'", currentLocation), + Choices: modelChoices, + }, + }) + if err != nil { + return nil, "", fmt.Errorf("failed to prompt for model selection: %w", err) + } + + selectedModelName := modelNames[*modelResp.Value] + return a.modelCatalog[selectedModelName], currentLocation, nil +} + func (a *InitAction) ProcessModels(ctx context.Context, manifest *agent_yaml.AgentManifest) (*agent_yaml.AgentManifest, []project.Deployment, error) { // Convert the template to bytes templateBytes, err := yaml.Marshal(manifest.Template) diff --git a/cli/azd/extensions/azure.ai.agents/internal/pkg/azure/ai/model_catalog.go b/cli/azd/extensions/azure.ai.agents/internal/pkg/azure/ai/model_catalog.go index 6009d108bbd..f8b9e1fadcf 100644 --- a/cli/azd/extensions/azure.ai.agents/internal/pkg/azure/ai/model_catalog.go +++ b/cli/azd/extensions/azure.ai.agents/internal/pkg/azure/ai/model_catalog.go @@ -6,6 +6,7 @@ package ai import ( "context" "errors" + "fmt" "slices" "strings" "sync" @@ -18,13 +19,8 @@ import ( ) type AiModel struct { - Name string - Locations []*AiModelLocation -} - -type AiModelLocation struct { - Model *armcognitiveservices.Model - Location *armsubscriptions.Location + Name string + ModelDetailsByLocation map[string][]*armcognitiveservices.Model } type ModelCatalogService struct { @@ -68,13 +64,19 @@ func (c *ModelCatalogService) ListAllKinds(ctx context.Context, allModels map[st }) } -func (c *ModelCatalogService) ListModelVersions(ctx context.Context, model *AiModel) ([]string, string, error) { +func (c *ModelCatalogService) ListModelVersions(ctx context.Context, model *AiModel, location string) ([]string, string, error) { versions := make(map[string]struct{}) defaultVersion := "" - for _, location := range model.Locations { - versions[*location.Model.Model.Version] = struct{}{} - if location.Model.Model.IsDefaultVersion != nil && *location.Model.Model.IsDefaultVersion { - defaultVersion = *location.Model.Model.Version + + models, exists := model.ModelDetailsByLocation[location] + if !exists { + return nil, "", fmt.Errorf("no model details found for location '%s'", location) + } + + for _, m := range models { + versions[*m.Model.Version] = struct{}{} + if m.Model.IsDefaultVersion != nil && *m.Model.IsDefaultVersion { + defaultVersion = *m.Model.Version } } @@ -88,12 +90,17 @@ func (c *ModelCatalogService) ListModelVersions(ctx context.Context, model *AiMo return versionList, defaultVersion, nil } -func (c *ModelCatalogService) ListModelSkus(ctx context.Context, model *AiModel, modelVersion string) ([]string, error) { +func (c *ModelCatalogService) ListModelSkus(ctx context.Context, model *AiModel, location string, modelVersion string) ([]string, error) { skus := make(map[string]struct{}) - for _, location := range model.Locations { - if *location.Model.Model.Version == modelVersion { - for _, sku := range location.Model.Model.SKUs { + models, exists := model.ModelDetailsByLocation[location] + if !exists { + return nil, fmt.Errorf("no model details found for location '%s'", location) + } + + for _, m := range models { + if *m.Model.Version == modelVersion { + for _, sku := range m.Model.SKUs { skus[*sku.Name] = struct{}{} } } @@ -136,34 +143,36 @@ func (c *ModelCatalogService) ListFilteredModels( isFormatMatch := len(options.Formats) == 0 isKindMatch := len(options.Kinds) == 0 - for _, location := range model.Locations { - if !isCapabilityMatch && len(options.Capabilities) > 0 { - for modelCapability := range location.Model.Model.Capabilities { - if slices.Contains(options.Capabilities, modelCapability) { - isCapabilityMatch = true - break + for locationName, models := range model.ModelDetailsByLocation { + for _, m := range models { + if !isCapabilityMatch && len(options.Capabilities) > 0 { + for modelCapability := range m.Model.Capabilities { + if slices.Contains(options.Capabilities, modelCapability) { + isCapabilityMatch = true + break + } } } - } - if !isLocationMatch && len(options.Locations) > 0 && - slices.Contains(options.Locations, *location.Location.Name) { - isLocationMatch = true - } + if !isLocationMatch && len(options.Locations) > 0 && + slices.Contains(options.Locations, locationName) { + isLocationMatch = true + } - if !isStatusMatch && len(options.Statuses) > 0 && - slices.Contains(options.Statuses, string(*location.Model.Model.LifecycleStatus)) { - isStatusMatch = true - } + if !isStatusMatch && len(options.Statuses) > 0 && + slices.Contains(options.Statuses, string(*m.Model.LifecycleStatus)) { + isStatusMatch = true + } - if !isFormatMatch && len(options.Formats) > 0 && - slices.Contains(options.Formats, *location.Model.Model.Format) { - isFormatMatch = true - } + if !isFormatMatch && len(options.Formats) > 0 && + slices.Contains(options.Formats, *m.Model.Format) { + isFormatMatch = true + } - if !isKindMatch && len(options.Kinds) > 0 && - slices.Contains(options.Kinds, *location.Model.Kind) { - isKindMatch = true + if !isKindMatch && len(options.Kinds) > 0 && + slices.Contains(options.Kinds, *m.Kind) { + isKindMatch = true + } } } @@ -217,6 +226,7 @@ func (c *ModelCatalogService) ListAllModels(ctx context.Context, subscriptionId for pager.More() { page, err := pager.NextPage(ctx) + page.MarshalJSON() if err != nil { return } @@ -237,19 +247,18 @@ func (c *ModelCatalogService) ListAllModels(ctx context.Context, subscriptionId modelsList := value.([]*armcognitiveservices.Model) for _, model := range modelsList { + modelName := *model.Model.Name existingModel, exists := modelMap[modelName] if !exists { existingModel = &AiModel{ - Name: modelName, - Locations: []*AiModelLocation{}, + Name: modelName, + ModelDetailsByLocation: make(map[string][]*armcognitiveservices.Model), } } - existingModel.Locations = append(existingModel.Locations, &AiModelLocation{ - Model: model, - Location: location, - }) + locationName := *location.Name + existingModel.ModelDetailsByLocation[locationName] = append(existingModel.ModelDetailsByLocation[locationName], model) modelMap[modelName] = existingModel } @@ -306,57 +315,63 @@ func (c *ModelCatalogService) GetModelDeployment( var modelDeployment *AiModelDeployment hasDefaultVersion := c.hasDefaultVersion(model) - for _, location := range model.Locations { + for locationName, models := range model.ModelDetailsByLocation { if modelDeployment != nil { break } // Check for location match if specified - if len(options.Locations) > 0 && !slices.Contains(options.Locations, *location.Location.Name) { + if len(options.Locations) > 0 && !slices.Contains(options.Locations, locationName) { continue } - // Check for version match if specified - if len(options.Versions) > 0 && !slices.Contains(options.Versions, *location.Model.Model.Version) { - continue - } + for _, m := range models { + if modelDeployment != nil { + break + } - // Check for default version if no version is specified - if len(options.Versions) > 0 { - if !slices.Contains(options.Versions, *location.Model.Model.Version) { + // Check for version match if specified + if len(options.Versions) > 0 && !slices.Contains(options.Versions, *m.Model.Version) { continue } - } else if hasDefaultVersion { - // Not all models have a default version - if location.Model.Model.IsDefaultVersion != nil && !*location.Model.Model.IsDefaultVersion { - continue + + // Check for default version if no version is specified + if len(options.Versions) > 0 { + if !slices.Contains(options.Versions, *m.Model.Version) { + continue + } + } else if hasDefaultVersion { + // Not all models have a default version + if m.Model.IsDefaultVersion != nil && !*m.Model.IsDefaultVersion { + continue + } } - } - // Check for SKU match if specified - for _, sku := range location.Model.Model.SKUs { + // Check for SKU match if specified + for _, sku := range m.Model.SKUs { - if !slices.Contains(options.Skus, *sku.Name) { - continue - } + if !slices.Contains(options.Skus, *sku.Name) { + continue + } - modelDeployment = &AiModelDeployment{ - Name: *location.Model.Model.Name, - Format: *location.Model.Model.Format, - Version: *location.Model.Model.Version, - Sku: AiModelDeploymentSku{ - Name: *sku.Name, - UsageName: *sku.UsageName, - }, - } + modelDeployment = &AiModelDeployment{ + Name: *m.Model.Name, + Format: *m.Model.Format, + Version: *m.Model.Version, + Sku: AiModelDeploymentSku{ + Name: *sku.Name, + UsageName: *sku.UsageName, + }, + } - if sku.Capacity.Default != nil { - modelDeployment.Sku.Capacity = *sku.Capacity.Default - } else { - modelDeployment.Sku.Capacity = -1 - } + if sku.Capacity.Default != nil { + modelDeployment.Sku.Capacity = *sku.Capacity.Default + } else { + modelDeployment.Sku.Capacity = -1 + } - break + break + } } } @@ -368,9 +383,11 @@ func (c *ModelCatalogService) GetModelDeployment( } func (c *ModelCatalogService) hasDefaultVersion(model *AiModel) bool { - for _, location := range model.Locations { - if location.Model.Model.IsDefaultVersion != nil && *location.Model.Model.IsDefaultVersion { - return true + for _, models := range model.ModelDetailsByLocation { + for _, m := range models { + if m.Model.IsDefaultVersion != nil && *m.Model.IsDefaultVersion { + return true + } } } return false @@ -382,11 +399,13 @@ func filterDistinctModelData( ) []string { filtered := make(map[string]struct{}) for _, model := range models { - for _, location := range model.Locations { - value := filterFunc(location.Model) - for _, v := range value { - if v != "" { - filtered[v] = struct{}{} + for _, locationModels := range model.ModelDetailsByLocation { + for _, m := range locationModels { + value := filterFunc(m) + for _, v := range value { + if v != "" { + filtered[v] = struct{}{} + } } } } From cd3b89c7227e694f356774d1d02d455caa8f4e03 Mon Sep 17 00:00:00 2001 From: trangevi Date: Thu, 5 Feb 2026 11:43:22 -0800 Subject: [PATCH 2/8] Remove commented out code Signed-off-by: trangevi --- cli/azd/extensions/azure.ai.agents/internal/cmd/init.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/azd/extensions/azure.ai.agents/internal/cmd/init.go b/cli/azd/extensions/azure.ai.agents/internal/cmd/init.go index 36a6e4a384c..6e2814365c9 100644 --- a/cli/azd/extensions/azure.ai.agents/internal/cmd/init.go +++ b/cli/azd/extensions/azure.ai.agents/internal/cmd/init.go @@ -1917,8 +1917,8 @@ func (a *InitAction) loadAiCatalog(ctx context.Context) error { return fmt.Errorf("failed to start spinner: %w", err) } - // aiModelCatalog, err := a.modelCatalogService.ListAllModels(ctx, a.azureContext.Scope.SubscriptionId, a.azureContext.Scope.Location) aiModelCatalog, err := a.modelCatalogService.ListAllModels(ctx, a.azureContext.Scope.SubscriptionId, "") + if err != nil { return fmt.Errorf("failed to load the model catalog: %w", err) } From c576bd7c0370334a2ce5a5c06e68dc9b9fe7f001 Mon Sep 17 00:00:00 2001 From: Travis Angevine Date: Thu, 5 Feb 2026 11:46:13 -0800 Subject: [PATCH 3/8] Update cli/azd/extensions/azure.ai.agents/internal/cmd/init.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- cli/azd/extensions/azure.ai.agents/internal/cmd/init.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/azd/extensions/azure.ai.agents/internal/cmd/init.go b/cli/azd/extensions/azure.ai.agents/internal/cmd/init.go index 6e2814365c9..062c2f7a150 100644 --- a/cli/azd/extensions/azure.ai.agents/internal/cmd/init.go +++ b/cli/azd/extensions/azure.ai.agents/internal/cmd/init.go @@ -2329,7 +2329,7 @@ func (a *InitAction) promptForAlternativeModel(ctx context.Context, originalMode func (a *InitAction) promptForModelLocationMismatch(ctx context.Context, model *ai.AiModel, currentLocation string) (*ai.AiModel, string, error) { fmt.Println(output.WithErrorFormat("The model '%s' is not available in your current location '%s'.", model.Name, currentLocation)) - fmt.Println("Would you like you use a different model, or select a different location?") + fmt.Println("Would you like to use a different model, or select a different location?") fmt.Println(output.WithWarningFormat( "WARNING: If you choose to select a different location, this will change your currently configured " + "region in your AZD environment. If you have already created a Foundry Project in your currently " + From 992a19caa3bb639b99077d857292c76a52cdcbbe Mon Sep 17 00:00:00 2001 From: Travis Angevine Date: Thu, 5 Feb 2026 11:48:06 -0800 Subject: [PATCH 4/8] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../azure.ai.agents/internal/pkg/azure/ai/model_catalog.go | 1 - 1 file changed, 1 deletion(-) diff --git a/cli/azd/extensions/azure.ai.agents/internal/pkg/azure/ai/model_catalog.go b/cli/azd/extensions/azure.ai.agents/internal/pkg/azure/ai/model_catalog.go index f8b9e1fadcf..d0e97e47015 100644 --- a/cli/azd/extensions/azure.ai.agents/internal/pkg/azure/ai/model_catalog.go +++ b/cli/azd/extensions/azure.ai.agents/internal/pkg/azure/ai/model_catalog.go @@ -226,7 +226,6 @@ func (c *ModelCatalogService) ListAllModels(ctx context.Context, subscriptionId for pager.More() { page, err := pager.NextPage(ctx) - page.MarshalJSON() if err != nil { return } From d6fd16f7c3800ad49c158081dc0ef05ff3cf6238 Mon Sep 17 00:00:00 2001 From: trangevi Date: Thu, 5 Feb 2026 11:55:36 -0800 Subject: [PATCH 5/8] redundant check Signed-off-by: trangevi --- .../azure.ai.agents/internal/pkg/azure/ai/model_catalog.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/cli/azd/extensions/azure.ai.agents/internal/pkg/azure/ai/model_catalog.go b/cli/azd/extensions/azure.ai.agents/internal/pkg/azure/ai/model_catalog.go index d0e97e47015..9c593e4f1d6 100644 --- a/cli/azd/extensions/azure.ai.agents/internal/pkg/azure/ai/model_catalog.go +++ b/cli/azd/extensions/azure.ai.agents/internal/pkg/azure/ai/model_catalog.go @@ -329,11 +329,6 @@ func (c *ModelCatalogService) GetModelDeployment( break } - // Check for version match if specified - if len(options.Versions) > 0 && !slices.Contains(options.Versions, *m.Model.Version) { - continue - } - // Check for default version if no version is specified if len(options.Versions) > 0 { if !slices.Contains(options.Versions, *m.Model.Version) { From f4a7c6274a5be5b66cafe03be1c2d0a7001bac9b Mon Sep 17 00:00:00 2001 From: trangevi Date: Thu, 5 Feb 2026 13:41:06 -0800 Subject: [PATCH 6/8] Update warning message format Signed-off-by: trangevi --- .../extensions/azure.ai.agents/internal/cmd/init.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/cli/azd/extensions/azure.ai.agents/internal/cmd/init.go b/cli/azd/extensions/azure.ai.agents/internal/cmd/init.go index 062c2f7a150..d18bf0d144c 100644 --- a/cli/azd/extensions/azure.ai.agents/internal/cmd/init.go +++ b/cli/azd/extensions/azure.ai.agents/internal/cmd/init.go @@ -2331,10 +2331,12 @@ func (a *InitAction) promptForModelLocationMismatch(ctx context.Context, model * fmt.Println(output.WithErrorFormat("The model '%s' is not available in your current location '%s'.", model.Name, currentLocation)) fmt.Println("Would you like to use a different model, or select a different location?") fmt.Println(output.WithWarningFormat( - "WARNING: If you choose to select a different location, this will change your currently configured " + - "region in your AZD environment. If you have already created a Foundry Project in your currently " + - "configured region, this will cause failures, and you should either choose a different model or " + - "create a new project in a different region where your desired model is available.")) + "WARNING: If you switch locations:\n" + + "• Your AZD environment will use a new default region.\n" + + "• Any existing Azure AI Foundry project created in your current region may fail.\n\n" + + "Recommended options:\n" + + "1) Select a different model in this region (safe), or\n" + + "2) Create a new Foundry project after changing regions.")) // Ask what they want to do choices := []*azdext.SelectChoice{ From 0b209f0d5e09afc5ff855e46f749c1ec30ab00db Mon Sep 17 00:00:00 2001 From: trangevi Date: Thu, 5 Feb 2026 13:53:43 -0800 Subject: [PATCH 7/8] better method Signed-off-by: trangevi --- .../azure.ai.agents/internal/cmd/init.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cli/azd/extensions/azure.ai.agents/internal/cmd/init.go b/cli/azd/extensions/azure.ai.agents/internal/cmd/init.go index d18bf0d144c..fe6574ced86 100644 --- a/cli/azd/extensions/azure.ai.agents/internal/cmd/init.go +++ b/cli/azd/extensions/azure.ai.agents/internal/cmd/init.go @@ -2398,15 +2398,15 @@ func (a *InitAction) promptForModelLocationMismatch(ctx context.Context, model * selectedLocation := locationNames[*locationResp.Value] // Update the azd environment with the new location - workflow := &azdext.Workflow{ - Name: "env set", - Steps: []*azdext.WorkflowStep{ - {Command: &azdext.WorkflowCommand{Args: []string{"env", "set", "AZURE_LOCATION", selectedLocation}}}, - }, + envResponse, err := a.azdClient.Environment().GetCurrent(ctx, &azdext.EmptyRequest{}) + if err != nil { + return nil, "", fmt.Errorf("failed to get current azd environment: %w", err) } - _, err = a.azdClient.Workflow().Run(ctx, &azdext.RunWorkflowRequest{ - Workflow: workflow, + _, err = a.azdClient.Environment().SetValue(ctx, &azdext.SetEnvRequest{ + EnvName: envResponse.Environment.Name, + Key: "AZURE_LOCATION", + Value: selectedLocation, }) if err != nil { return nil, "", fmt.Errorf("failed to update AZURE_LOCATION in azd environment: %w", err) From c8e8dbab2c0e5abb4b92fdccb671f55173b451b6 Mon Sep 17 00:00:00 2001 From: trangevi Date: Thu, 5 Feb 2026 13:56:04 -0800 Subject: [PATCH 8/8] Make sure we properly set the env change everywhere Signed-off-by: trangevi --- cli/azd/extensions/azure.ai.agents/internal/cmd/init.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cli/azd/extensions/azure.ai.agents/internal/cmd/init.go b/cli/azd/extensions/azure.ai.agents/internal/cmd/init.go index fe6574ced86..f041e4bc944 100644 --- a/cli/azd/extensions/azure.ai.agents/internal/cmd/init.go +++ b/cli/azd/extensions/azure.ai.agents/internal/cmd/init.go @@ -2403,10 +2403,11 @@ func (a *InitAction) promptForModelLocationMismatch(ctx context.Context, model * return nil, "", fmt.Errorf("failed to get current azd environment: %w", err) } + a.azureContext.Scope.Location = selectedLocation _, err = a.azdClient.Environment().SetValue(ctx, &azdext.SetEnvRequest{ EnvName: envResponse.Environment.Name, Key: "AZURE_LOCATION", - Value: selectedLocation, + Value: a.azureContext.Scope.Location, }) if err != nil { return nil, "", fmt.Errorf("failed to update AZURE_LOCATION in azd environment: %w", err)