diff --git a/src/azure-cli/azure/cli/command_modules/cognitiveservices/_client_factory.py b/src/azure-cli/azure/cli/command_modules/cognitiveservices/_client_factory.py index 0b64cb82a5d..0cafbb7aaa5 100644 --- a/src/azure-cli/azure/cli/command_modules/cognitiveservices/_client_factory.py +++ b/src/azure-cli/azure/cli/command_modules/cognitiveservices/_client_factory.py @@ -7,6 +7,7 @@ def get_cognitiveservices_management_client(cli_ctx, *_): from azure.cli.core.commands.client_factory import get_mgmt_service_client from azure.mgmt.cognitiveservices import CognitiveServicesManagementClient + return get_mgmt_service_client(cli_ctx, CognitiveServicesManagementClient) @@ -42,6 +43,48 @@ def cf_usages(cli_ctx, *_): return get_cognitiveservices_management_client(cli_ctx).usages +def cf_ai_projects(cli_ctx, command_args): + """ + Create AI Projects client for data plane operations. + Similar to keyvault's data plane client factory pattern. + """ + from azure.ai.projects import AIProjectClient + from azure.cli.core.commands.client_factory import prepare_client_kwargs_track2 + from azure.cli.core._profile import Profile + + # Get credentials using Azure CLI login + profile = Profile(cli_ctx=cli_ctx) + credential, _, _ = profile.get_login_credentials( + subscription_id=cli_ctx.data.get("subscription_id") + ) + + # Get endpoint from command arguments (similar to keyvault's vault_url) + account_name = command_args.get("account_name", None) + endpoint = command_args.get("endpoint", None) + project = command_args.get("project_name", None) + + # If no explicit endpoint provided, construct from account name + if not endpoint and account_name: + # Construct endpoint URL from account name + # Format: https://{account_name}.cognitiveservices.azure.com + endpoint = ( + f"https://{account_name}.services.ai.azure.com/api/projects/{project}" + ) + + if not endpoint: + from azure.cli.core.azclierror import RequiredArgumentMissingError + + raise RequiredArgumentMissingError( + "Please specify --account-name or --endpoint" + ) + + # Prepare client kwargs with proper logging and telemetry + client_kwargs = prepare_client_kwargs_track2(cli_ctx) + + # Create and return the AI Projects client + return AIProjectClient(endpoint=endpoint, credential=credential, **client_kwargs) + + def cf_projects(cli_ctx, *_): return get_cognitiveservices_management_client(cli_ctx).projects diff --git a/src/azure-cli/azure/cli/command_modules/cognitiveservices/_help.py b/src/azure-cli/azure/cli/command_modules/cognitiveservices/_help.py index df6e07faae0..c19737ff184 100644 --- a/src/azure-cli/azure/cli/command_modules/cognitiveservices/_help.py +++ b/src/azure-cli/azure/cli/command_modules/cognitiveservices/_help.py @@ -5,21 +5,28 @@ # -------------------------------------------------------------------------------------------- from knack.help_files import helps # pylint: disable=unused-import + # pylint: disable=line-too-long, too-many-lines -helps['cognitiveservices'] = """ +helps[ + "cognitiveservices" +] = """ type: group short-summary: Manage Azure Cognitive Services accounts. long-summary: This article lists the Azure CLI commands for Azure Cognitive Services account and subscription management only. Refer to the documentation at https://learn.microsoft.com/azure/cognitive-services/ for individual services to learn how to use the APIs and supported SDKs. """ -helps['cognitiveservices account'] = """ +helps[ + "cognitiveservices account" +] = """ type: group short-summary: Manage Azure Cognitive Services accounts. long-summary: This article lists the Azure CLI commands for Azure Cognitive Services account and subscription management only. Refer to the documentation at https://learn.microsoft.com/azure/cognitive-services/ for individual services to learn how to use the APIs and supported SDKs. """ -helps['cognitiveservices account create'] = """ +helps[ + "cognitiveservices account create" +] = """ type: command short-summary: Manage Azure Cognitive Services accounts. long-summary: This article lists the Azure CLI commands for Azure Cognitive Services account and subscription management only. Refer to the documentation at https://learn.microsoft.com/azure/cognitive-services/ for individual services to learn how to use the APIs and supported SDKs. @@ -57,7 +64,9 @@ }' """ -helps['cognitiveservices account delete'] = """ +helps[ + "cognitiveservices account delete" +] = """ type: command short-summary: Manage Azure Cognitive Services accounts. long-summary: This article lists the Azure CLI commands for Azure Cognitive Services account and subscription management only. Refer to the documentation at https://learn.microsoft.com/azure/cognitive-services/ for individual services to learn how to use the APIs and supported SDKs. @@ -66,13 +75,17 @@ text: az cognitiveservices account delete --name myresource-luis -g cognitive-services-resource-group """ -helps['cognitiveservices account keys'] = """ +helps[ + "cognitiveservices account keys" +] = """ type: group short-summary: Manage Azure Cognitive Services accounts. long-summary: This article lists the Azure CLI commands for Azure Cognitive Services account and subscription management only. Refer to the documentation at https://learn.microsoft.com/azure/cognitive-services/ for individual services to learn how to use the APIs and supported SDKs. """ -helps['cognitiveservices account keys list'] = """ +helps[ + "cognitiveservices account keys list" +] = """ type: command short-summary: Manage Azure Cognitive Services accounts. long-summary: This article lists the Azure CLI commands for Azure Cognitive Services account and subscription management only. Refer to the documentation at https://learn.microsoft.com/azure/cognitive-services/ for individual services to learn how to use the APIs and supported SDKs. @@ -84,7 +97,9 @@ crafted: true """ -helps['cognitiveservices account keys regenerate'] = """ +helps[ + "cognitiveservices account keys regenerate" +] = """ type: command short-summary: Manage Azure Cognitive Services accounts. long-summary: This article lists the Azure CLI commands for Azure Cognitive Services account and subscription management only. Refer to the documentation at https://learn.microsoft.com/azure/cognitive-services/ for individual services to learn how to use the APIs and supported SDKs. @@ -93,7 +108,9 @@ text: az cognitiveservices account keys regenerate --name myresource -g cognitive-services-resource-group --key-name key1 """ -helps['cognitiveservices account list'] = """ +helps[ + "cognitiveservices account list" +] = """ type: command short-summary: Manage Azure Cognitive Services accounts. long-summary: This article lists the Azure CLI commands for Azure Cognitive Services account and subscription management only. Refer to the documentation at https://learn.microsoft.com/azure/cognitive-services/ for individual services to learn how to use the APIs and supported SDKs. @@ -102,7 +119,9 @@ text: az cognitiveservices account list -g MyResourceGroup """ -helps['cognitiveservices account list-skus'] = """ +helps[ + "cognitiveservices account list-skus" +] = """ type: command short-summary: Manage Azure Cognitive Services accounts. long-summary: This article lists the Azure CLI commands for Azure Cognitive Services account and subscription management only. Refer to the documentation at https://learn.microsoft.com/azure/cognitive-services/ for individual services to learn how to use the APIs and supported SDKs. @@ -122,7 +141,9 @@ text: az cognitiveservices account list-skus --kind Face --location westus """ -helps['cognitiveservices account list-models'] = """ +helps[ + "cognitiveservices account list-models" +] = """ type: command short-summary: Manage Azure Cognitive Services accounts. long-summary: This article lists the Azure CLI commands for Azure Cognitive Services account and subscription management only. Refer to the documentation at https://learn.microsoft.com/azure/cognitive-services/ for individual services to learn how to use the APIs and supported SDKs. @@ -131,12 +152,16 @@ text: az cognitiveservices account list-models -n myresource -g cognitive-services-resource-group """ -helps['cognitiveservices account network-rule'] = """ +helps[ + "cognitiveservices account network-rule" +] = """ type: group short-summary: Manage network rules. """ -helps['cognitiveservices account network-rule add'] = """ +helps[ + "cognitiveservices account network-rule add" +] = """ type: command short-summary: Add a network rule. long-summary: > @@ -148,7 +173,9 @@ text: az cognitiveservices account network-rule add -g myRg --name MyAccount --vnet myvnet --subnet mysubnet """ -helps['cognitiveservices account network-rule list'] = """ +helps[ + "cognitiveservices account network-rule list" +] = """ type: command short-summary: List network rules. examples: @@ -157,7 +184,9 @@ crafted: true """ -helps['cognitiveservices account network-rule remove'] = """ +helps[ + "cognitiveservices account network-rule remove" +] = """ type: command short-summary: Remove a network rule. examples: @@ -169,7 +198,9 @@ crafted: true """ -helps['cognitiveservices account show'] = """ +helps[ + "cognitiveservices account show" +] = """ type: command short-summary: Manage Azure Cognitive Services accounts. long-summary: This article lists the Azure CLI commands for Azure Cognitive Services account and subscription management only. Refer to the documentation at https://learn.microsoft.com/azure/cognitive-services/ for individual services to learn how to use the APIs and supported SDKs. @@ -178,7 +209,9 @@ text: az cognitiveservices account show --name myresource --resource-group cognitive-services-resource-group """ -helps['cognitiveservices account update'] = """ +helps[ + "cognitiveservices account update" +] = """ type: command short-summary: Manage Azure Cognitive Services accounts. long-summary: This article lists the Azure CLI commands for Azure Cognitive Services account and subscription management only. Refer to the documentation at https://learn.microsoft.com/azure/cognitive-services/ for individual services to learn how to use the APIs and supported SDKs. @@ -191,7 +224,9 @@ text: az cognitiveservices account update --name myresource -g cognitive-services-resource-group --sku S0 --tags external-app=chatbot-HR azure-web-app-bot=HR-external azure-app-service=HR-external-app-service """ -helps['cognitiveservices list'] = """ +helps[ + "cognitiveservices list" +] = """ type: command short-summary: Manage Azure Cognitive Services accounts. long-summary: This article lists the Azure CLI commands for Azure Cognitive Services account and subscription management only. Refer to the documentation at https://learn.microsoft.com/azure/cognitive-services/ for individual services to learn how to use the APIs and supported SDKs. @@ -200,12 +235,16 @@ text: az cognitiveservices list -g MyResourceGroup """ -helps['cognitiveservices account identity'] = """ +helps[ + "cognitiveservices account identity" +] = """ type: group short-summary: Manage identity of Cognitive Services accounts. """ -helps['cognitiveservices account identity assign'] = """ +helps[ + "cognitiveservices account identity assign" +] = """ type: command short-summary: Assign an identity of a Cognitive Services account. long-summary: Assign an identity object of a Cognitive Services account. An system assigned identity will be generate and assigned to the account. @@ -214,7 +253,9 @@ text: az cognitiveservices account identity assign --name myresource --resource-group cognitive-services-resource-group """ -helps['cognitiveservices account identity show'] = """ +helps[ + "cognitiveservices account identity show" +] = """ type: command short-summary: Show the identity of a Cognitive Services account. long-summary: Show the identity object of a Cognitive Services account, empty object might be returned if the account has no assigned identity. @@ -223,7 +264,9 @@ text: az cognitiveservices account identity show --name myresource --resource-group cognitive-services-resource-group """ -helps['cognitiveservices account identity remove'] = """ +helps[ + "cognitiveservices account identity remove" +] = """ type: command short-summary: Remove the identity from a Cognitive Services account. long-summary: Remove the identity (if exists) from a Cognitive Services account. @@ -232,7 +275,9 @@ text: az cognitiveservices account identity remove --name myresource --resource-group cognitive-services-resource-group """ -helps['cognitiveservices account list-deleted'] = """ +helps[ + "cognitiveservices account list-deleted" +] = """ type: command short-summary: List soft-deleted Azure Cognitive Services accounts. long-summary: This article lists the Azure CLI commands for Azure Cognitive Services account and subscription management only. Refer to the documentation at https://learn.microsoft.com/azure/cognitive-services/ for individual services to learn how to use the APIs and supported SDKs. @@ -242,7 +287,9 @@ """ -helps['cognitiveservices account show-deleted'] = """ +helps[ + "cognitiveservices account show-deleted" +] = """ type: command short-summary: Show a soft-deleted Azure Cognitive Services account. long-summary: This article lists the Azure CLI commands for Azure Cognitive Services account and subscription management only. Refer to the documentation at https://learn.microsoft.com/azure/cognitive-services/ for individual services to learn how to use the APIs and supported SDKs. @@ -251,7 +298,9 @@ text: az cognitiveservices account show-deleted --location eastus --resource-group cognitive-services-resource-group --name cognitive-services-account-name """ -helps['cognitiveservices account recover'] = """ +helps[ + "cognitiveservices account recover" +] = """ type: command short-summary: Recover a soft-deleted Azure Cognitive Services account. long-summary: This article lists the Azure CLI commands for Azure Cognitive Services account and subscription management only. Refer to the documentation at https://learn.microsoft.com/azure/cognitive-services/ for individual services to learn how to use the APIs and supported SDKs. @@ -260,7 +309,9 @@ text: az cognitiveservices account recover --location eastus --resource-group cognitive-services-resource-group --name cognitive-services-account-name """ -helps['cognitiveservices account purge'] = """ +helps[ + "cognitiveservices account purge" +] = """ type: command short-summary: Purge a soft-deleted Azure Cognitive Services account. long-summary: This article lists the Azure CLI commands for Azure Cognitive Services account and subscription management only. Refer to the documentation at https://learn.microsoft.com/azure/cognitive-services/ for individual services to learn how to use the APIs and supported SDKs. @@ -269,12 +320,16 @@ text: az cognitiveservices account purge --location eastus --resource-group cognitive-services-resource-group --name cognitive-services-account-name """ -helps['cognitiveservices account deployment'] = """ +helps[ + "cognitiveservices account deployment" +] = """ type: group short-summary: Manage deployments for Azure Cognitive Services accounts. """ -helps['cognitiveservices account deployment create'] = """ +helps[ + "cognitiveservices account deployment create" +] = """ type: command short-summary: Create a deployment for Azure Cognitive Services account. long-summary: This article lists the Azure CLI commands for Azure Cognitive Services account and subscription management only. Refer to the documentation at https://learn.microsoft.com/azure/cognitive-services/ for individual services to learn how to use the APIs and supported SDKs. @@ -283,7 +338,9 @@ text: az cognitiveservices account deployment create -g yuanyang-test-sdk -n yytest-oai --deployment-name dpy --model-name ada --model-version "1" --model-format OpenAI --sku-capacity 1 --sku-name "Standard" """ -helps['cognitiveservices account deployment delete'] = """ +helps[ + "cognitiveservices account deployment delete" +] = """ type: command short-summary: Delete a deployment from Azure Cognitive Services account. long-summary: This article lists the Azure CLI commands for Azure Cognitive Services account and subscription management only. Refer to the documentation at https://learn.microsoft.com/azure/cognitive-services/ for individual services to learn how to use the APIs and supported SDKs. @@ -292,7 +349,9 @@ text: az cognitiveservices account deployment delete -g yuanyang-test-sdk -n yytest-oai --deployment-name dpy """ -helps['cognitiveservices account deployment show'] = """ +helps[ + "cognitiveservices account deployment show" +] = """ type: command short-summary: Show a deployment for Azure Cognitive Services account. long-summary: This article lists the Azure CLI commands for Azure Cognitive Services account and subscription management only. Refer to the documentation at https://learn.microsoft.com/azure/cognitive-services/ for individual services to learn how to use the APIs and supported SDKs. @@ -301,7 +360,9 @@ text: az cognitiveservices account deployment show -g yuanyang-test-sdk -n yytest-oai --deployment-name dpy """ -helps['cognitiveservices account deployment list'] = """ +helps[ + "cognitiveservices account deployment list" +] = """ type: command short-summary: Show all deployments for Azure Cognitive Services account. long-summary: This article lists the Azure CLI commands for Azure Cognitive Services account and subscription management only. Refer to the documentation at https://learn.microsoft.com/azure/cognitive-services/ for individual services to learn how to use the APIs and supported SDKs. @@ -310,12 +371,16 @@ text: az cognitiveservices account deployment list -g yuanyang-test-sdk -n yytest-oai """ -helps['cognitiveservices commitment-tier'] = """ +helps[ + "cognitiveservices commitment-tier" +] = """ type: group short-summary: Manage commitment tiers for Azure Cognitive Services. """ -helps['cognitiveservices commitment-tier list'] = """ +helps[ + "cognitiveservices commitment-tier list" +] = """ type: command short-summary: Show all commitment tiers for Azure Cognitive Services. long-summary: This article lists the Azure CLI commands for Azure Cognitive Services account and subscription management only. Refer to the documentation at https://learn.microsoft.com/azure/cognitive-services/ for individual services to learn how to use the APIs and supported SDKs. @@ -324,12 +389,16 @@ text: az cognitiveservices commitment-tier list -l centraluseuap """ -helps['cognitiveservices account commitment-plan'] = """ +helps[ + "cognitiveservices account commitment-plan" +] = """ type: group short-summary: Manage commitment plans for Azure Cognitive Services accounts. """ -helps['cognitiveservices account commitment-plan create'] = """ +helps[ + "cognitiveservices account commitment-plan create" +] = """ type: command short-summary: Create a commitment plan for Azure Cognitive Services account. long-summary: This article lists the Azure CLI commands for Azure Cognitive Services account and subscription management only. Refer to the documentation at https://learn.microsoft.com/azure/cognitive-services/ for individual services to learn how to use the APIs and supported SDKs. @@ -338,7 +407,9 @@ text: az cognitiveservices account commitment-plan create -g yuanyang-test-sdk -n yytest-ta --commitment-plan-name "plan" --hosting-model "Web" --plan-type "TA" --auto-renew false --current-tier "T1" --next-tier "T2" """ -helps['cognitiveservices account commitment-plan delete'] = """ +helps[ + "cognitiveservices account commitment-plan delete" +] = """ type: command short-summary: Delete a commitment plan from Azure Cognitive Services account. long-summary: This article lists the Azure CLI commands for Azure Cognitive Services account and subscription management only. Refer to the documentation at https://learn.microsoft.com/azure/cognitive-services/ for individual services to learn how to use the APIs and supported SDKs. @@ -347,7 +418,9 @@ text: az cognitiveservices account commitment-plan delete -g yuanyang-test-sdk -n yytest-ta --commitment-plan-name "plan" """ -helps['cognitiveservices account commitment-plan show'] = """ +helps[ + "cognitiveservices account commitment-plan show" +] = """ type: command short-summary: Show a commitment plan from Azure Cognitive Services account. long-summary: This article lists the Azure CLI commands for Azure Cognitive Services account and subscription management only. Refer to the documentation at https://learn.microsoft.com/azure/cognitive-services/ for individual services to learn how to use the APIs and supported SDKs. @@ -356,7 +429,9 @@ text: az cognitiveservices account commitment-plan show -g yuanyang-test-sdk -n yytest-ta --commitment-plan-name "plan" """ -helps['cognitiveservices account commitment-plan list'] = """ +helps[ + "cognitiveservices account commitment-plan list" +] = """ type: command short-summary: Show all commitment plans from Azure Cognitive Services account. long-summary: This article lists the Azure CLI commands for Azure Cognitive Services account and subscription management only. Refer to the documentation at https://learn.microsoft.com/azure/cognitive-services/ for individual services to learn how to use the APIs and supported SDKs. @@ -365,12 +440,16 @@ text: az cognitiveservices account commitment-plan list -g yuanyang-test-sdk -n yytest-ta """ -helps['cognitiveservices model'] = """ +helps[ + "cognitiveservices model" +] = """ type: group short-summary: Manage model for Azure Cognitive Services. """ -helps['cognitiveservices model list'] = """ +helps[ + "cognitiveservices model list" +] = """ type: command short-summary: Show all models for Azure Cognitive Services. long-summary: This article lists the Azure CLI commands for Azure Cognitive Services account and subscription management only. Refer to the documentation at https://learn.microsoft.com/azure/cognitive-services/ for individual services to learn how to use the APIs and supported SDKs. @@ -379,12 +458,16 @@ text: az cognitiveservices model list -l centraluseuap """ -helps['cognitiveservices usage'] = """ +helps[ + "cognitiveservices usage" +] = """ type: group short-summary: Manage usage for Azure Cognitive Services. """ -helps['cognitiveservices usage list'] = """ +helps[ + "cognitiveservices usage list" +] = """ type: command short-summary: Show all usages for Azure Cognitive Services. long-summary: This article lists the Azure CLI commands for Azure Cognitive Services account and subscription management only. Refer to the documentation at https://learn.microsoft.com/azure/cognitive-services/ for individual services to learn how to use the APIs and supported SDKs. @@ -393,6 +476,43 @@ text: az cognitiveservices usage list -l centraluseuap """ +helps[ + "cognitiveservices agent" +] = """ +type: group +short-summary: Control foundry agents. +""" + +helps[ + "cognitiveservices agent start" +] = """ +type: command +short-summary: Start a hosted agent deployment. +examples: + - name: Start hosted agent deployment. + text: az cognitiveservices agent start --account-name myAccount --project-name myProject --name myAgent --agent-version 1 +""" + +helps[ + "cognitiveservices agent stop" +] = """ +type: command +short-summary: Stop a hosted agent deployment. +examples: + - name: Start hosted agent deployment. + text: az cognitiveservices agent stop --account-name myAccount --project-name myProject --name myAgent --agent-version 1 +""" + +helps[ + "cognitiveservices agent update" +] = """ +type: command +short-summary: Update a hosted agent deployment. +examples: + - name: Start hosted agent deployment. + text: az cognitiveservices agent update --account-name myAccount --project-name myProject --name myAgent --agent-version 1 --min-replicas 1 --max-replicas 2 +""" + helps['cognitiveservices account connection'] = """ type: group short-summary: Manage Azure Cognitive Services connection and its more specific derivatives. diff --git a/src/azure-cli/azure/cli/command_modules/cognitiveservices/_params.py b/src/azure-cli/azure/cli/command_modules/cognitiveservices/_params.py index ab70ab36fe2..024c7cecc7a 100644 --- a/src/azure-cli/azure/cli/command_modules/cognitiveservices/_params.py +++ b/src/azure-cli/azure/cli/command_modules/cognitiveservices/_params.py @@ -13,18 +13,23 @@ get_three_state_flag, resource_group_name_type, get_resource_name_completion_list, - get_location_type) -from azure.cli.core.util import (shell_safe_json_parse, CLIError) + get_location_type, +) +from azure.cli.core.util import shell_safe_json_parse, CLIError from azure.cli.core.commands.validators import validate_tag from azure.cli.core.decorators import Completer from azure.cli.command_modules.cognitiveservices._client_factory import cf_resource_skus -from azure.mgmt.cognitiveservices.models import KeyName, DeploymentScaleType, HostingModel +from azure.mgmt.cognitiveservices.models import ( + KeyName, + DeploymentScaleType, + HostingModel, +) logger = get_logger(__name__) -name_arg_type = CLIArgumentType(options_list=['--name', '-n'], metavar='NAME') +name_arg_type = CLIArgumentType(options_list=["--name", "-n"], metavar="NAME") def extract_key_values_pairs(api_properties): @@ -35,7 +40,7 @@ def extract_key_values_pairs(api_properties): def validate_api_properties(ns): - """ Extracts JSON format or 'a=b c=d' format as api properties """ + """Extracts JSON format or 'a=b c=d' format as api properties""" api_properties = ns.api_properties if api_properties is None: @@ -51,17 +56,20 @@ def validate_api_properties(ns): except CLIError: result = extract_key_values_pairs([string]) if _is_suspected_json(string): - logger.warning('Api properties looks like a JSON format but not valid, interpreted as key=value pairs:' - ' %s', str(result)) + logger.warning( + "Api properties looks like a JSON format but not valid, interpreted as key=value pairs:" + " %s", + str(result), + ) ns.api_properties = result return def _is_suspected_json(string): - """ If the string looks like a JSON """ - if string.startswith('{') or string.startswith('\'{') or string.startswith('\"{'): + """If the string looks like a JSON""" + if string.startswith("{") or string.startswith("'{") or string.startswith('"{'): return True - if string.startswith('[') or string.startswith('\'[') or string.startswith('\"['): + if string.startswith("[") or string.startswith("'[") or string.startswith('"['): return True if re.match(r"^['\"\s]*{.+}|\[.+\]['\"\s]*$", string): return True @@ -72,8 +80,8 @@ def _is_suspected_json(string): api_properties_type = CLIArgumentType( validator=validate_api_properties, help="Api properties in JSON format or a=b c=d format. Some cognitive services (i.e. QnA Maker) " - "require extra api properties to create the account.", - nargs='*' + "require extra api properties to create the account.", + nargs="*", ) @@ -81,9 +89,9 @@ def _sku_filter(cmd, namespace): """ Get a list of ResourceSku and filter by existing conditions: 'kind', 'location' and 'sku_name' """ - kind = getattr(namespace, 'kind', None) - location = getattr(namespace, 'location', None) - sku_name = getattr(namespace, 'sku_name', None) + kind = getattr(namespace, "kind", None) + location = getattr(namespace, "location", None) + sku_name = getattr(namespace, "sku_name", None) def _filter_sku(_sku): if sku_name is not None: @@ -114,11 +122,12 @@ def _validate_subnet(cmd, namespace): namespace.subnet = resource_id( subscription=get_subscription_id(cmd.cli_ctx), resource_group=namespace.resource_group_name, - namespace='Microsoft.Network', - type='virtualNetworks', + namespace="Microsoft.Network", + type="virtualNetworks", name=vnet, - child_type_1='subnets', - child_name_1=subnet) + child_type_1="subnets", + child_name_1=subnet, + ) def _validate_user_assigned_identity(cmd, namespace): @@ -136,7 +145,9 @@ def _validate_user_assigned_identity(cmd, namespace): @Completer -def sku_name_completer(cmd, prefix, namespace, **kwargs): # pylint: disable=unused-argument +def sku_name_completer( + cmd, prefix, namespace, **kwargs +): # pylint: disable=unused-argument names = {x.name for x in _sku_filter(cmd, namespace)} # TODO: For deployment return sorted(list(names)) @@ -149,12 +160,215 @@ def kind_completer(cmd, prefix, namespace, **kwargs): # pylint: disable=unused- @Completer -def location_completer(cmd, prefix, namespace, **kwargs): # pylint: disable=unused-argument +def location_completer( + cmd, prefix, namespace, **kwargs +): # pylint: disable=unused-argument names = {location for x in _sku_filter(cmd, namespace) for location in x.locations} return [x.lower() for x in sorted(list(names))] def load_arguments(self, _): + with self.argument_context("cognitiveservices") as c: + c.argument( + "account_name", + arg_type=name_arg_type, + help="cognitive service account name", + completer=get_resource_name_completion_list( + "Microsoft.CognitiveServices/accounts" + ), + ) + c.argument( + "location", + arg_type=get_location_type(self.cli_ctx), + completer=location_completer, + ) + c.argument("resource_group_name", arg_type=resource_group_name_type) + c.argument( + "sku_name", + options_list=["--sku", "--sku-name"], + help="Name of the Sku of Cognitive Services account/deployment", + completer=sku_name_completer, + ) + c.argument( + "sku_capacity", + options_list=["--capacity", "--sku-capacity"], + help="Capacity value of the Sku of Cognitive Services account/deployment.", + ) + c.argument( + "kind", + help="the API name of cognitive services account", + completer=kind_completer, + ) + c.argument("tags", tags_type) + c.argument( + "key_name", + required=True, + help="Key name to generate", + arg_type=get_enum_type(KeyName), + ) + c.argument("api_properties", api_properties_type) + c.argument( + "custom_domain", + help="User domain assigned to the account. Name is the CNAME source.", + ) + c.argument( + "storage", + help="The storage accounts for this resource, in JSON array format.", + ) + c.argument( + "encryption", + help="The encryption properties for this resource, in JSON format.", + ) + + with self.argument_context( + "cognitiveservices account", arg_group="AI Services" + ) as c: + c.argument( + "allow_project_management", + options_list=["--manage-projects", "--allow-project-management"], + arg_type=get_three_state_flag(), + help="AIServices kind only. Enables project management. Default true.", + ) + + with self.argument_context("cognitiveservices account create") as c: + c.argument( + "assign_identity", + help="Generate and assign an Azure Active Directory Identity for this account.", + ) + c.argument( + "yes", action="store_true", help="Do not prompt for terms confirmation" + ) + + with self.argument_context( + "cognitiveservices account update", arg_group="AI Services" + ) as c: + c.argument( + "kind", + arg_type=get_enum_type(data=["AIServices", "OpenAI"]), + help="The target API name to transform the existing account into.", + ) + + with self.argument_context("cognitiveservices account network-rule") as c: + c.argument("ip_address", help="IPv4 address or CIDR range.") + c.argument( + "subnet", + help="Name or ID of subnet. If name is supplied, `--vnet-name` must be supplied.", + ) + c.argument( + "vnet_name", help="Name of a virtual network.", validator=_validate_subnet + ) + + with self.argument_context("cognitiveservices account deployment") as c: + c.argument("deployment_name", help="Cognitive Services account deployment name") + + with self.argument_context( + "cognitiveservices account deployment", arg_group="DeploymentModel" + ) as c: + c.argument( + "model_name", help="Cognitive Services account deployment model name." + ) + c.argument( + "model_format", help="Cognitive Services account deployment model format." + ) + c.argument( + "model_version", help="Cognitive Services account deployment model version." + ) + c.argument( + "model_source", help="Cognitive Services account deployment model source." + ) + + with self.argument_context( + "cognitiveservices account deployment", arg_group="DeploymentScaleSettings" + ) as c: + c.argument( + "scale_settings_scale_type", + get_enum_type(DeploymentScaleType), + options_list=["--scale-type", "--scale-settings-scale-type"], + help="Cognitive Services account deployment scale settings scale type.", + ) + c.argument( + "scale_settings_capacity", + options_list=["--scale-capacity", "--scale-settings-capacity"], + help="Cognitive Services account deployment scale settings capacity.", + ) + + with self.argument_context("cognitiveservices account commitment-plan") as c: + c.argument( + "commitment_plan_name", + help="Cognitive Services account commitment plan name", + ) + c.argument("plan_type", help="Cognitive Services account commitment plan type") + c.argument( + "hosting_model", + get_enum_type(HostingModel), + help="Cognitive Services account hosting model", + ) + c.argument( + "auto_renew", + arg_type=get_three_state_flag(), + help="A boolean indicating whether to apply auto renew.", + ) + + with self.argument_context( + "cognitiveservices account commitment-plan", + arg_group="Current CommitmentPeriod", + ) as c: + c.argument( + "current_count", + help="Cognitive Services account commitment plan current commitment period count.", + ) + c.argument( + "current_tier", + help="Cognitive Services account commitment plan current commitment period tier.", + ) + + with self.argument_context( + "cognitiveservices account commitment-plan", arg_group="Next CommitmentPeriod" + ) as c: + c.argument( + "next_count", + help="Cognitive Services account commitment plan next commitment period count.", + ) + c.argument( + "next_tier", + help="Cognitive Services account commitment plan next commitment period tier.", + ) + + with self.argument_context("cognitiveservices agent") as c: + c.argument( + "account_name", + options_list=["--account-name", "-a"], + help="cognitive service account name." + ) + c.argument("project_name", help="AI Project name") + c.argument( + "agent_name", + options_list=["--name", "-n"], + help="Cognitive Services hosted agent name", + ) + c.argument("agent_version", help="Cognitive Services hosted agent version") + + with self.argument_context("cognitiveservices agent update") as c: + c.argument( + "min_replicas", + type=int, + options_list=["--min-replicas"], + help="Minimum number of replicas for horizontal scaling", + ) + c.argument( + "max_replicas", + type=int, + options_list=["--max-replicas"], + help="Maximum number of replicas for horizontal scaling", + ) + c.argument("description", help="Description of the agent") + + with self.argument_context("cognitiveservices agent delete") as c: + c.argument( + "agent_version", + help="Cognitive Services hosted agent version. If not provided, deletes all versions.", + required=False, + ) with self.argument_context('cognitiveservices') as c: c.argument('account_name', arg_type=name_arg_type, help='cognitive service account name', completer=get_resource_name_completion_list('Microsoft.CognitiveServices/accounts')) diff --git a/src/azure-cli/azure/cli/command_modules/cognitiveservices/commands.py b/src/azure-cli/azure/cli/command_modules/cognitiveservices/commands.py index f65f314a731..4558985aebb 100644 --- a/src/azure-cli/azure/cli/command_modules/cognitiveservices/commands.py +++ b/src/azure-cli/azure/cli/command_modules/cognitiveservices/commands.py @@ -6,7 +6,7 @@ from azure.cli.core.commands import CliCommandType from azure.cli.command_modules.cognitiveservices._client_factory import cf_accounts, cf_resource_skus, \ cf_deleted_accounts, cf_deployments, cf_commitment_plans, cf_commitment_tiers, cf_models, cf_usages, \ - cf_account_connections, cf_projects, cf_project_connections + cf_ai_projects, cf_account_connections, cf_projects, cf_project_connections def load_command_table(self, _): @@ -119,6 +119,15 @@ def load_command_table(self, _): with self.command_group('cognitiveservices usage', usages_type) as g: g.command('list', 'list') + with self.command_group('cognitiveservices agent', client_factory=cf_ai_projects, is_preview=True) as g: + g.custom_command('update', 'agent_update') + g.custom_command('stop', 'agent_stop') + g.custom_command('start', 'agent_start') + g.custom_command('delete-deployment', 'agent_delete_deployment') + g.custom_command('delete', 'agent_delete') + g.custom_command('list', 'agent_list') + g.custom_command('list-versions', 'agent_versions_list') + g.custom_show_command('show', 'agent_show') with self.command_group( 'cognitiveservices account project', projects_type, client_factory=cf_projects) as g: diff --git a/src/azure-cli/azure/cli/command_modules/cognitiveservices/custom.py b/src/azure-cli/azure/cli/command_modules/cognitiveservices/custom.py index f6c1c940b0e..0feb3a76be1 100644 --- a/src/azure-cli/azure/cli/command_modules/cognitiveservices/custom.py +++ b/src/azure-cli/azure/cli/command_modules/cognitiveservices/custom.py @@ -4,10 +4,13 @@ # -------------------------------------------------------------------------------------------- import json +import urllib.parse from knack.util import CLIError from knack.log import get_logger +import azure.core.rest + from azure.mgmt.cognitiveservices.models import Account as CognitiveServicesAccount, Sku, \ VirtualNetworkRule, IpRule, NetworkRuleSet, NetworkRuleAction, \ AccountProperties as CognitiveServicesAccountProperties, ApiProperties as CognitiveServicesAccountApiProperties, \ @@ -64,16 +67,19 @@ def list_kinds(client): return sorted(list(kinds)) -def list_skus(cmd, kind=None, location=None, resource_group_name=None, account_name=None): +def list_skus( + cmd, kind=None, location=None, resource_group_name=None, account_name=None +): """ List skus for Azure Cognitive Services account. """ if resource_group_name is not None or account_name is not None: logger.warning( - 'list-skus with an existing account has been deprecated and will be removed in a future release.') + "list-skus with an existing account has been deprecated and will be removed in a future release." + ) if resource_group_name is None: # account_name must not be None - raise CLIError('--resource-group is required when --name is specified.') + raise CLIError("--resource-group is required when --name is specified.") # keep the original behavior to avoid breaking changes return cf_accounts(cmd.cli_ctx).list_skus(resource_group_name, account_name) @@ -91,22 +97,30 @@ def _filter_sku(_sku): def _is_valid_kind_change(current_kind, target_kind): - valid_upgrades = { - 'AIServices': ['OpenAI'], - 'OpenAI': ['AIServices'] - } + valid_upgrades = {"AIServices": ["OpenAI"], "OpenAI": ["AIServices"]} return target_kind in valid_upgrades.get(current_kind, []) def _kind_uses_project_management(kind): - return kind in ['AIServices'] + return kind in ["AIServices"] def create( - client, resource_group_name, account_name, sku_name, kind, location, custom_domain=None, - tags=None, api_properties=None, assign_identity=False, storage=None, encryption=None, - allow_project_management=None, - yes=None): # pylint: disable=unused-argument + client, + resource_group_name, + account_name, + sku_name, + kind, + location, + custom_domain=None, + tags=None, + api_properties=None, + assign_identity=False, + storage=None, + encryption=None, + allow_project_management=None, + yes=None, +): # pylint: disable=unused-argument """ Create an Azure Cognitive Services account. """ @@ -118,7 +132,9 @@ def create( properties = CognitiveServicesAccountProperties() if api_properties is not None: - api_properties = CognitiveServicesAccountApiProperties.deserialize(api_properties) + api_properties = CognitiveServicesAccountApiProperties.deserialize( + api_properties + ) properties.api_properties = api_properties if custom_domain: properties.custom_sub_domain_name = custom_domain @@ -138,9 +154,19 @@ def create( return client.begin_create(resource_group_name, account_name, params) -def update(client, resource_group_name, account_name, sku_name=None, custom_domain=None, - tags=None, api_properties=None, storage=None, encryption=None, - allow_project_management=None, kind=None): +def update( + client, + resource_group_name, + account_name, + sku_name=None, + custom_domain=None, + tags=None, + api_properties=None, + storage=None, + encryption=None, + allow_project_management=None, + kind=None, +): """ Update an Azure Cognitive Services account. """ @@ -153,7 +179,9 @@ def update(client, resource_group_name, account_name, sku_name=None, custom_doma properties = CognitiveServicesAccountProperties() if api_properties is not None: - api_properties = CognitiveServicesAccountApiProperties.deserialize(api_properties) + api_properties = CognitiveServicesAccountApiProperties.deserialize( + api_properties + ) properties.api_properties = api_properties if custom_domain: properties.custom_sub_domain_name = custom_domain @@ -196,8 +224,14 @@ def list_network_rules(client, resource_group_name, account_name): return rules -def add_network_rule(client, resource_group_name, account_name, subnet=None, - vnet_name=None, ip_address=None): # pylint: disable=unused-argument +def add_network_rule( + client, + resource_group_name, + account_name, + subnet=None, + vnet_name=None, + ip_address=None, +): # pylint: disable=unused-argument """ Add a network rule for Azure Cognitive Services account. """ @@ -208,12 +242,17 @@ def add_network_rule(client, resource_group_name, account_name, subnet=None, if subnet: from azure.mgmt.core.tools import is_valid_resource_id + if not is_valid_resource_id(subnet): - raise CLIError("Expected fully qualified resource ID: got '{}'".format(subnet)) + raise CLIError( + "Expected fully qualified resource ID: got '{}'".format(subnet) + ) if not rules.virtual_network_rules: rules.virtual_network_rules = [] - rules.virtual_network_rules.append(VirtualNetworkRule(id=subnet, ignore_missing_vnet_service_endpoint=True)) + rules.virtual_network_rules.append( + VirtualNetworkRule(id=subnet, ignore_missing_vnet_service_endpoint=True) + ) if ip_address: if not rules.ip_rules: rules.ip_rules = [] @@ -226,8 +265,14 @@ def add_network_rule(client, resource_group_name, account_name, subnet=None, return client.begin_update(resource_group_name, account_name, params) -def remove_network_rule(client, resource_group_name, account_name, ip_address=None, subnet=None, - vnet_name=None): # pylint: disable=unused-argument +def remove_network_rule( + client, + resource_group_name, + account_name, + ip_address=None, + subnet=None, + vnet_name=None, +): # pylint: disable=unused-argument """ Remove a network rule for Azure Cognitive Services account. """ @@ -238,8 +283,9 @@ def remove_network_rule(client, resource_group_name, account_name, ip_address=No return client.update(resource_group_name, account_name) if subnet: - rules.virtual_network_rules = [x for x in rules.virtual_network_rules - if not x.id.endswith(subnet)] + rules.virtual_network_rules = [ + x for x in rules.virtual_network_rules if not x.id.endswith(subnet) + ] if ip_address: rules.ip_rules = [x for x in rules.ip_rules if x.value != ip_address] @@ -307,10 +353,18 @@ def deployment_begin_create_or_update( def commitment_plan_create_or_update( - client, resource_group_name, account_name, commitment_plan_name, - hosting_model, plan_type, auto_renew, - current_tier=None, current_count=None, - next_tier=None, next_count=None): + client, + resource_group_name, + account_name, + commitment_plan_name, + hosting_model, + plan_type, + auto_renew, + current_tier=None, + current_count=None, + next_tier=None, + next_count=None, +): """ Create a commitment plan for Azure Cognitive Services account. """ @@ -318,16 +372,207 @@ def commitment_plan_create_or_update( plan.properties = CommitmentPlanProperties() plan.properties.hosting_model = hosting_model plan.properties.plan_type = plan_type - if (current_tier is not None or current_count is not None): + if current_tier is not None or current_count is not None: plan.properties.current = CommitmentPeriod() plan.properties.current.tier = current_tier plan.properties.current.count = current_count - if (next_tier is not None or next_count is not None): + if next_tier is not None or next_count is not None: plan.properties.next = CommitmentPeriod() plan.properties.next.tier = next_tier plan.properties.next.count = next_count plan.properties.auto_renew = auto_renew - return client.create_or_update(resource_group_name, account_name, commitment_plan_name, plan) + return client.create_or_update( + resource_group_name, account_name, commitment_plan_name, plan + ) + + +AGENT_API_VERSION_PARAMS = {"api-version": "2025-11-15-preview"} + + +def _create_agent_request( + method: str, + agent_name: str, + agent_version: str = None, + *, + container: bool = False, + action: str = None, + body: dict = None, +): + if container and not agent_version: + raise ValueError("container=True requires agent_version to be specified") + + if agent_version: + url = f"/agents/{urllib.parse.quote(agent_name)}/versions/{urllib.parse.quote(agent_version)}" + if container: + url += "/containers/default" + else: + url = f"/agents/{urllib.parse.quote(agent_name)}" + + if action: + url += f":{action}" + return azure.core.rest.HttpRequest( + method, url, json=body, params=AGENT_API_VERSION_PARAMS + ) + + +def _invoke_agent_container_operation( + client, + agent_name, + agent_version, + *, + action: str, + min_replicas=None, + max_replicas=None, +): + request_body = {} + if min_replicas is not None: + request_body["min_replicas"] = min_replicas + if max_replicas is not None: + request_body["max_replicas"] = max_replicas + request = _create_agent_request( + "POST", + agent_name, + agent_version, + action=action, + container=True, + body=request_body, + ) + response = client.send_request(request) + response.raise_for_status() + return response.json() + + +def agent_update( + client, + account_name, + project_name, + agent_name, + agent_version, + min_replicas=None, + max_replicas=None, + description=None, + tags=None, +): # pylint: disable=unused-argument + """ + Update hosted agent deployment configuration. + Updates horizontal scale configuration (min and max replica), agent meta-data such as description and tags. + New version is not created for this update. + """ + return _invoke_agent_container_operation( + client, + agent_name, + agent_version, + action="update", + min_replicas=min_replicas, + max_replicas=max_replicas, + ) + + +def agent_stop( + client, account_name, project_name, agent_name, agent_version +): # pylint: disable=unused-argument + """ + Stop hosted agent deployment. + """ + return _invoke_agent_container_operation( + client, agent_name, agent_version, action="stop" + ) + + +def agent_start( + client, account_name, project_name, agent_name, agent_version +): # pylint: disable=unused-argument + """ + Start hosted agent deployment. + """ + return _invoke_agent_container_operation( + client, agent_name, agent_version, action="start" + ) + + +def agent_delete_deployment( + client, account_name, project_name, agent_name, agent_version +): # pylint: disable=unused-argument + """ + Delete hosted agent deployment. + Deletes the agent deployment only, agent version associated with the deployment remains. + """ + request = _create_agent_request( + "POST", agent_name, agent_version, action="delete", container=True + ) + response = client.send_request(request) + response.raise_for_status() + return response.json() + + +def agent_delete( + client, account_name, project_name, agent_name, agent_version=None +): # pylint: disable=unused-argument + """ + Delete hosted agent version or all versions. + If agent_version is provided, deletes the agent instance and agent definition associated with that version. + If agent_version is not provided, deletes all agent instances and agent definitions associated with the agent name. + """ + request = _create_agent_request("DELETE", agent_name, agent_version) + response = client.send_request(request) + response.raise_for_status() + return response.json() + + +def agent_list(client, account_name, project_name): # pylint: disable=unused-argument + """ + List agents. + """ + agents = [] + params = AGENT_API_VERSION_PARAMS.copy() + while True: + request = azure.core.rest.HttpRequest("GET", "/agents", params=params) + response = client.send_request(request) + response.raise_for_status() + body = response.json() + agents.extend(body.get("data", [])) + if body.get("has_more"): + params["after"] = body.get("last_id") + else: + return agents + + +def agent_versions_list( + client, account_name, project_name, agent_name +): # pylint: disable=unused-argument + """ + List all versions of a hosted agent. + """ + versions = [] + params = AGENT_API_VERSION_PARAMS.copy() + while True: + request = azure.core.rest.HttpRequest( + "GET", f"/agents/{urllib.parse.quote(agent_name)}/versions", params=params + ) + response = client.send_request(request) + response.raise_for_status() + body = response.json() + versions.extend(body.get("data", [])) + if body.get("has_more"): + params["after"] = body.get("last_id") + else: + return versions + + +def agent_show( + client, account_name, project_name, agent_name +): # pylint: disable=unused-argument + """ + Show details of a hosted agent. + """ + request = azure.core.rest.HttpRequest( + "GET", + f"/agents/{urllib.parse.quote(agent_name)}", + params=AGENT_API_VERSION_PARAMS, + ) + response = client.send_request(request) + response.raise_for_status() + return response.json() def project_create( diff --git a/src/azure-cli/setup.py b/src/azure-cli/setup.py index efc2ba3d613..f8cd3013341 100644 --- a/src/azure-cli/setup.py +++ b/src/azure-cli/setup.py @@ -53,6 +53,7 @@ DEPENDENCIES = [ "antlr4-python3-runtime~=4.13.1", 'azure-appconfiguration~=1.7.1', + 'azure-ai-projects~=1.0.0', 'azure-batch==15.0.0b1', 'azure-cli-core=={}'.format(VERSION), 'azure-cosmos~=3.0,>=3.0.2',