From 51c6d3c9aa03837eecb28e193208540660b3bc87 Mon Sep 17 00:00:00 2001 From: Darren Cohen <39422044+dargilco@users.noreply.github.com> Date: Wed, 6 May 2026 12:27:06 -0700 Subject: [PATCH] Emit SDK from TypeSpec and apply post-emitter fixes Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- sdk/ai/azure-ai-projects/CHANGELOG.md | 3 + .../azure-ai-projects/apiview-properties.json | 15 +- .../azure/ai/projects/_utils/utils.py | 1 + .../ai/projects/aio/operations/_operations.py | 562 +++++++++++- .../ai/projects/aio/operations/_patch.py | 2 +- .../azure/ai/projects/models/__init__.py | 10 +- .../azure/ai/projects/models/_enums.py | 15 +- .../azure/ai/projects/models/_models.py | 194 ++++- .../ai/projects/operations/_operations.py | 811 ++++++++++++++++-- sdk/ai/azure-ai-projects/tsp-location.yaml | 2 +- 10 files changed, 1496 insertions(+), 119 deletions(-) diff --git a/sdk/ai/azure-ai-projects/CHANGELOG.md b/sdk/ai/azure-ai-projects/CHANGELOG.md index 3864773b2f2a..2da23ef74411 100644 --- a/sdk/ai/azure-ai-projects/CHANGELOG.md +++ b/sdk/ai/azure-ai-projects/CHANGELOG.md @@ -10,6 +10,8 @@ * New `.beta.datasets` sub-client with data generation job operations: `create_generation_job`, `get_generation_job`, `list_generation_jobs`, `cancel_generation_job`, `delete_generation_job`. * New read-only property `content_hash` on `CodeConfiguration`, returning the SHA-256 hex digest of the uploaded code zip. * New evaluator generation job operations on `.beta.evaluators`: `create_generation_job`, `get_generation_job`, `list_generation_jobs`, `cancel_generation_job`, `delete_generation_job`. +* New code-based agent operations on `.agents` sub-client: `create_agent_from_code`, `update_agent_from_code`, `create_agent_version_from_code`, `download_agent_version_code`, `download_agent_code`. +* New enum `CodeDependencyResolution` for specifying how package dependencies are resolved at deployment time for code-based hosted agents. ### Breaking Changes @@ -18,6 +20,7 @@ Breaking changes in beta operations: * Required property `isolation_key_source` removed from class `EntraAuthorizationScheme`. * Required keyword argument `isolation_key` removed from `.beta.agents.create_session()` and `.beta.agents.delete_session()` methods. * Argument `body` in methods `.beta.evaluation_taxonomies.create()` and `.beta.evaluation_taxonomies.update()` renamed to `taxonomy`. +* Removed model `TaskDataGenerationJobOptions` and enum value `DataGenerationJobType.TASK`. ### Bugs Fixed diff --git a/sdk/ai/azure-ai-projects/apiview-properties.json b/sdk/ai/azure-ai-projects/apiview-properties.json index c9c61ccf5141..9d3a92377546 100644 --- a/sdk/ai/azure-ai-projects/apiview-properties.json +++ b/sdk/ai/azure-ai-projects/apiview-properties.json @@ -85,6 +85,9 @@ "azure.ai.projects.models.EvaluationRuleAction": "Azure.AI.Projects.EvaluationRuleAction", "azure.ai.projects.models.ContinuousEvaluationRuleAction": "Azure.AI.Projects.ContinuousEvaluationRuleAction", "azure.ai.projects.models.CosmosDBIndex": "Azure.AI.Projects.CosmosDBIndex", + "azure.ai.projects.models.CreateAgentFromCodeContent": "Azure.AI.Projects.CreateAgentFromCodeContent", + "azure.ai.projects.models.CreateAgentVersionFromCodeContent": "Azure.AI.Projects.CreateAgentVersionFromCodeContent", + "azure.ai.projects.models.CreateAgentVersionFromCodeRequest": "Azure.AI.Projects.CreateAgentVersionFromCodeRequest", "azure.ai.projects.models.Trigger": "Azure.AI.Projects.Trigger", "azure.ai.projects.models.CronTrigger": "Azure.AI.Projects.CronTrigger", "azure.ai.projects.models.CustomCredential": "Azure.AI.Projects.CustomCredential", @@ -239,7 +242,6 @@ "azure.ai.projects.models.SpecificFunctionShellParam": "OpenAI.SpecificFunctionShellParam", "azure.ai.projects.models.StructuredInputDefinition": "Azure.AI.Projects.StructuredInputDefinition", "azure.ai.projects.models.StructuredOutputDefinition": "Azure.AI.Projects.StructuredOutputDefinition", - "azure.ai.projects.models.TaskDataGenerationJobOptions": "Azure.AI.Projects.TaskDataGenerationJobOptions", "azure.ai.projects.models.TaxonomyCategory": "Azure.AI.Projects.TaxonomyCategory", "azure.ai.projects.models.TaxonomySubCategory": "Azure.AI.Projects.TaxonomySubCategory", "azure.ai.projects.models.TelemetryConfig": "Azure.AI.Projects.TelemetryConfig", @@ -298,6 +300,7 @@ "azure.ai.projects.models.ContainerSkillType": "OpenAI.ContainerSkillType", "azure.ai.projects.models.SearchContextSize": "OpenAI.SearchContextSize", "azure.ai.projects.models.AgentProtocol": "Azure.AI.Projects.AgentProtocol", + "azure.ai.projects.models.CodeDependencyResolution": "Azure.AI.Projects.CodeDependencyResolution", "azure.ai.projects.models.TelemetryEndpointKind": "Azure.AI.Projects.TelemetryEndpointKind", "azure.ai.projects.models.TelemetryDataKind": "Azure.AI.Projects.TelemetryDataKind", "azure.ai.projects.models.TelemetryEndpointAuthType": "Azure.AI.Projects.TelemetryEndpointAuthType", @@ -352,6 +355,10 @@ "azure.ai.projects.models.MemoryStoreUpdateStatus": "Azure.AI.Projects.MemoryStoreUpdateStatus", "azure.ai.projects.operations.AgentsOperations.get": "Azure.AI.Projects.Agents.getAgent", "azure.ai.projects.aio.operations.AgentsOperations.get": "Azure.AI.Projects.Agents.getAgent", + "azure.ai.projects.operations.AgentsOperations.create_agent_from_code": "Azure.AI.Projects.Agents.createAgentFromCode", + "azure.ai.projects.aio.operations.AgentsOperations.create_agent_from_code": "Azure.AI.Projects.Agents.createAgentFromCode", + "azure.ai.projects.operations.AgentsOperations.update_agent_from_code": "Azure.AI.Projects.Agents.updateAgentFromCode", + "azure.ai.projects.aio.operations.AgentsOperations.update_agent_from_code": "Azure.AI.Projects.Agents.updateAgentFromCode", "azure.ai.projects.operations.AgentsOperations.delete": "Azure.AI.Projects.Agents.deleteAgent", "azure.ai.projects.aio.operations.AgentsOperations.delete": "Azure.AI.Projects.Agents.deleteAgent", "azure.ai.projects.operations.AgentsOperations.list": "Azure.AI.Projects.Agents.listAgents", @@ -366,6 +373,12 @@ "azure.ai.projects.aio.operations.AgentsOperations.delete_version": "Azure.AI.Projects.Agents.deleteAgentVersion", "azure.ai.projects.operations.AgentsOperations.list_versions": "Azure.AI.Projects.Agents.listAgentVersions", "azure.ai.projects.aio.operations.AgentsOperations.list_versions": "Azure.AI.Projects.Agents.listAgentVersions", + "azure.ai.projects.operations.AgentsOperations.create_agent_version_from_code": "Azure.AI.Projects.Agents.createAgentVersionFromCode", + "azure.ai.projects.aio.operations.AgentsOperations.create_agent_version_from_code": "Azure.AI.Projects.Agents.createAgentVersionFromCode", + "azure.ai.projects.operations.AgentsOperations.download_agent_version_code": "Azure.AI.Projects.Agents.downloadAgentVersionCode", + "azure.ai.projects.aio.operations.AgentsOperations.download_agent_version_code": "Azure.AI.Projects.Agents.downloadAgentVersionCode", + "azure.ai.projects.operations.AgentsOperations.download_agent_code": "Azure.AI.Projects.Agents.downloadAgentCode", + "azure.ai.projects.aio.operations.AgentsOperations.download_agent_code": "Azure.AI.Projects.Agents.downloadAgentCode", "azure.ai.projects.operations.EvaluationRulesOperations.get": "Azure.AI.Projects.EvaluationRules.get", "azure.ai.projects.aio.operations.EvaluationRulesOperations.get": "Azure.AI.Projects.EvaluationRules.get", "azure.ai.projects.operations.EvaluationRulesOperations.delete": "Azure.AI.Projects.EvaluationRules.delete", diff --git a/sdk/ai/azure-ai-projects/azure/ai/projects/_utils/utils.py b/sdk/ai/azure-ai-projects/azure/ai/projects/_utils/utils.py index 707b7d8fac75..bd821750f4c6 100644 --- a/sdk/ai/azure-ai-projects/azure/ai/projects/_utils/utils.py +++ b/sdk/ai/azure-ai-projects/azure/ai/projects/_utils/utils.py @@ -10,6 +10,7 @@ from .._utils.model_base import Model, SdkJSONEncoder + # file-like tuple could be `(filename, IO (or bytes))` or `(filename, IO (or bytes), content_type)` FileContent = Union[str, bytes, IO[str], IO[bytes]] diff --git a/sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/_operations.py b/sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/_operations.py index 92542b738815..359d3e0adafd 100644 --- a/sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/_operations.py +++ b/sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/_operations.py @@ -33,17 +33,23 @@ from azure.core.utils import case_insensitive_dict from ... import models as _models -from ..._utils.model_base import SdkJSONEncoder, _deserialize, _failsafe_deserialize +from ..._utils.model_base import Model as _Model, SdkJSONEncoder, _deserialize, _failsafe_deserialize from ..._utils.serialization import Deserializer, Serializer +from ..._utils.utils import prepare_multipart_form_data from ...operations._operations import ( + build_agents_create_agent_from_code_request, + build_agents_create_agent_version_from_code_request, build_agents_create_version_from_manifest_request, build_agents_create_version_request, build_agents_delete_request, build_agents_delete_version_request, + build_agents_download_agent_code_request, + build_agents_download_agent_version_code_request, build_agents_get_request, build_agents_get_version_request, build_agents_list_request, build_agents_list_versions_request, + build_agents_update_agent_from_code_request, build_beta_agents_create_session_request, build_beta_agents_delete_session_file_request, build_beta_agents_delete_session_request, @@ -254,6 +260,285 @@ async def get(self, agent_name: str, **kwargs: Any) -> _models.AgentDetails: return deserialized # type: ignore + @overload + async def create_agent_from_code( + self, body: _models.CreateAgentFromCodeContent, *, agent_name: str, code_zip_sha256: str, **kwargs: Any + ) -> _models.AgentDetails: + """Creates a new code-based agent. Uploads the code zip and creates the agent in a single call. + The agent name is provided in the ``x-ms-agent-name`` header since POST /agents has no name in + the URL path. The SHA-256 hex digest of the zip is provided in the ``x-ms-code-zip-sha256`` + header for integrity and dedup. The request body is multipart/form-data with a JSON metadata + part and a binary code part (part order is irrelevant). Maximum upload size is 250 MB. + + :param body: Required. + :type body: ~azure.ai.projects.models.CreateAgentFromCodeContent + :keyword agent_name: The unique name that identifies the agent. Max 63 chars, must start and + end with alphanumeric, hyphens allowed in the middle. Required. + :paramtype agent_name: str + :keyword code_zip_sha256: SHA-256 hex digest of the uploaded code zip. Used for change + detection (dedup) and integrity verification. Required. + :paramtype code_zip_sha256: str + :return: AgentDetails. The AgentDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentDetails + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + async def create_agent_from_code( + self, body: JSON, *, agent_name: str, code_zip_sha256: str, **kwargs: Any + ) -> _models.AgentDetails: + """Creates a new code-based agent. Uploads the code zip and creates the agent in a single call. + The agent name is provided in the ``x-ms-agent-name`` header since POST /agents has no name in + the URL path. The SHA-256 hex digest of the zip is provided in the ``x-ms-code-zip-sha256`` + header for integrity and dedup. The request body is multipart/form-data with a JSON metadata + part and a binary code part (part order is irrelevant). Maximum upload size is 250 MB. + + :param body: Required. + :type body: JSON + :keyword agent_name: The unique name that identifies the agent. Max 63 chars, must start and + end with alphanumeric, hyphens allowed in the middle. Required. + :paramtype agent_name: str + :keyword code_zip_sha256: SHA-256 hex digest of the uploaded code zip. Used for change + detection (dedup) and integrity verification. Required. + :paramtype code_zip_sha256: str + :return: AgentDetails. The AgentDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentDetails + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @distributed_trace_async + async def create_agent_from_code( + self, + body: Union[_models.CreateAgentFromCodeContent, JSON], + *, + agent_name: str, + code_zip_sha256: str, + **kwargs: Any + ) -> _models.AgentDetails: + """Creates a new code-based agent. Uploads the code zip and creates the agent in a single call. + The agent name is provided in the ``x-ms-agent-name`` header since POST /agents has no name in + the URL path. The SHA-256 hex digest of the zip is provided in the ``x-ms-code-zip-sha256`` + header for integrity and dedup. The request body is multipart/form-data with a JSON metadata + part and a binary code part (part order is irrelevant). Maximum upload size is 250 MB. + + :param body: Is either a CreateAgentFromCodeContent type or a JSON type. Required. + :type body: ~azure.ai.projects.models.CreateAgentFromCodeContent or JSON + :keyword agent_name: The unique name that identifies the agent. Max 63 chars, must start and + end with alphanumeric, hyphens allowed in the middle. Required. + :paramtype agent_name: str + :keyword code_zip_sha256: SHA-256 hex digest of the uploaded code zip. Used for change + detection (dedup) and integrity verification. Required. + :paramtype code_zip_sha256: str + :return: AgentDetails. The AgentDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentDetails + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[_models.AgentDetails] = kwargs.pop("cls", None) + + _body = body.as_dict() if isinstance(body, _Model) else body + _file_fields: list[str] = ["code"] + _data_fields: list[str] = ["metadata"] + _files = prepare_multipart_form_data(_body, _file_fields, _data_fields) + + _request = build_agents_create_agent_from_code_request( + agent_name=agent_name, + code_zip_sha256=code_zip_sha256, + api_version=self._config.api_version, + files=_files, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _decompress = kwargs.pop("decompress", True) + _stream = kwargs.pop("stream", False) + pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [200]: + if _stream: + try: + await response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) + + if _stream: + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + else: + deserialized = _deserialize(_models.AgentDetails, response.json()) + + if cls: + return cls(pipeline_response, deserialized, {}) # type: ignore + + return deserialized # type: ignore + + @overload + async def update_agent_from_code( + self, agent_name: str, body: _models.CreateAgentVersionFromCodeContent, *, code_zip_sha256: str, **kwargs: Any + ) -> _models.AgentDetails: + """Updates a code-based agent by uploading new code and creating a new version. If the code and + definition are unchanged (matched by x-ms-code-zip-sha256 header), returns the existing + version. The request body is multipart/form-data with a JSON metadata part and a binary code + part (part order is irrelevant). Maximum upload size is 250 MB. + + :param agent_name: The unique name that identifies the agent. Name can be used to + retrieve/update/delete the agent. + + * Must start and end with alphanumeric characters, + * Can contain hyphens in the middle + * Must not exceed 63 characters. Required. + :type agent_name: str + :param body: Required. + :type body: ~azure.ai.projects.models.CreateAgentVersionFromCodeContent + :keyword code_zip_sha256: SHA-256 hex digest of the uploaded code zip. Used for change + detection (dedup) and integrity verification. Required. + :paramtype code_zip_sha256: str + :return: AgentDetails. The AgentDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentDetails + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + async def update_agent_from_code( + self, agent_name: str, body: JSON, *, code_zip_sha256: str, **kwargs: Any + ) -> _models.AgentDetails: + """Updates a code-based agent by uploading new code and creating a new version. If the code and + definition are unchanged (matched by x-ms-code-zip-sha256 header), returns the existing + version. The request body is multipart/form-data with a JSON metadata part and a binary code + part (part order is irrelevant). Maximum upload size is 250 MB. + + :param agent_name: The unique name that identifies the agent. Name can be used to + retrieve/update/delete the agent. + + * Must start and end with alphanumeric characters, + * Can contain hyphens in the middle + * Must not exceed 63 characters. Required. + :type agent_name: str + :param body: Required. + :type body: JSON + :keyword code_zip_sha256: SHA-256 hex digest of the uploaded code zip. Used for change + detection (dedup) and integrity verification. Required. + :paramtype code_zip_sha256: str + :return: AgentDetails. The AgentDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentDetails + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @distributed_trace_async + async def update_agent_from_code( + self, + agent_name: str, + body: Union[_models.CreateAgentVersionFromCodeContent, JSON], + *, + code_zip_sha256: str, + **kwargs: Any + ) -> _models.AgentDetails: + """Updates a code-based agent by uploading new code and creating a new version. If the code and + definition are unchanged (matched by x-ms-code-zip-sha256 header), returns the existing + version. The request body is multipart/form-data with a JSON metadata part and a binary code + part (part order is irrelevant). Maximum upload size is 250 MB. + + :param agent_name: The unique name that identifies the agent. Name can be used to + retrieve/update/delete the agent. + + * Must start and end with alphanumeric characters, + * Can contain hyphens in the middle + * Must not exceed 63 characters. Required. + :type agent_name: str + :param body: Is either a CreateAgentVersionFromCodeContent type or a JSON type. Required. + :type body: ~azure.ai.projects.models.CreateAgentVersionFromCodeContent or JSON + :keyword code_zip_sha256: SHA-256 hex digest of the uploaded code zip. Used for change + detection (dedup) and integrity verification. Required. + :paramtype code_zip_sha256: str + :return: AgentDetails. The AgentDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentDetails + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[_models.AgentDetails] = kwargs.pop("cls", None) + + _body = body.as_dict() if isinstance(body, _Model) else body + _file_fields: list[str] = ["code"] + _data_fields: list[str] = ["metadata"] + _files = prepare_multipart_form_data(_body, _file_fields, _data_fields) + + _request = build_agents_update_agent_from_code_request( + agent_name=agent_name, + code_zip_sha256=code_zip_sha256, + api_version=self._config.api_version, + files=_files, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _decompress = kwargs.pop("decompress", True) + _stream = kwargs.pop("stream", False) + pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [200]: + if _stream: + try: + await response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) + + if _stream: + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + else: + deserialized = _deserialize(_models.AgentDetails, response.json()) + + if cls: + return cls(pipeline_response, deserialized, {}) # type: ignore + + return deserialized # type: ignore + @distributed_trace_async async def delete(self, agent_name: str, **kwargs: Any) -> _models.DeleteAgentResponse: """Deletes an agent. @@ -1059,6 +1344,281 @@ async def get_next(_continuation_token=None): return AsyncItemPaged(get_next, extract_data) + @overload + async def create_agent_version_from_code( + self, agent_name: str, body: _models.CreateAgentVersionFromCodeContent, *, code_zip_sha256: str, **kwargs: Any + ) -> _models.AgentVersionDetails: + """create_agent_version_from_code. + + :param agent_name: The unique name that identifies the agent. Name can be used to + retrieve/update/delete the agent. + + * Must start and end with alphanumeric characters, + * Can contain hyphens in the middle + * Must not exceed 63 characters. Required. + :type agent_name: str + :param body: Required. + :type body: ~azure.ai.projects.models.CreateAgentVersionFromCodeContent + :keyword code_zip_sha256: SHA-256 hex digest of the uploaded code zip. Used for change + detection (dedup) and integrity verification. Required. + :paramtype code_zip_sha256: str + :return: AgentVersionDetails. The AgentVersionDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentVersionDetails + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + async def create_agent_version_from_code( + self, agent_name: str, body: JSON, *, code_zip_sha256: str, **kwargs: Any + ) -> _models.AgentVersionDetails: + """create_agent_version_from_code. + + :param agent_name: The unique name that identifies the agent. Name can be used to + retrieve/update/delete the agent. + + * Must start and end with alphanumeric characters, + * Can contain hyphens in the middle + * Must not exceed 63 characters. Required. + :type agent_name: str + :param body: Required. + :type body: JSON + :keyword code_zip_sha256: SHA-256 hex digest of the uploaded code zip. Used for change + detection (dedup) and integrity verification. Required. + :paramtype code_zip_sha256: str + :return: AgentVersionDetails. The AgentVersionDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentVersionDetails + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @distributed_trace_async + async def create_agent_version_from_code( + self, + agent_name: str, + body: Union[_models.CreateAgentVersionFromCodeContent, JSON], + *, + code_zip_sha256: str, + **kwargs: Any + ) -> _models.AgentVersionDetails: + """create_agent_version_from_code. + + :param agent_name: The unique name that identifies the agent. Name can be used to + retrieve/update/delete the agent. + + * Must start and end with alphanumeric characters, + * Can contain hyphens in the middle + * Must not exceed 63 characters. Required. + :type agent_name: str + :param body: Is either a CreateAgentVersionFromCodeContent type or a JSON type. Required. + :type body: ~azure.ai.projects.models.CreateAgentVersionFromCodeContent or JSON + :keyword code_zip_sha256: SHA-256 hex digest of the uploaded code zip. Used for change + detection (dedup) and integrity verification. Required. + :paramtype code_zip_sha256: str + :return: AgentVersionDetails. The AgentVersionDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentVersionDetails + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[_models.AgentVersionDetails] = kwargs.pop("cls", None) + + _body = body.as_dict() if isinstance(body, _Model) else body + _file_fields: list[str] = ["code"] + _data_fields: list[str] = ["metadata"] + _files = prepare_multipart_form_data(_body, _file_fields, _data_fields) + + _request = build_agents_create_agent_version_from_code_request( + agent_name=agent_name, + code_zip_sha256=code_zip_sha256, + api_version=self._config.api_version, + files=_files, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _decompress = kwargs.pop("decompress", True) + _stream = kwargs.pop("stream", False) + pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [200]: + if _stream: + try: + await response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) + + if _stream: + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + else: + deserialized = _deserialize(_models.AgentVersionDetails, response.json()) + + if cls: + return cls(pipeline_response, deserialized, {}) # type: ignore + + return deserialized # type: ignore + + @distributed_trace_async + async def download_agent_version_code( + self, agent_name: str, agent_version: str, **kwargs: Any + ) -> AsyncIterator[bytes]: + """Download the code zip for a specific version of a code-based hosted agent. Returns the + previously-uploaded zip (``application/zip``). The SHA-256 digest of the returned bytes matches + the ``content_hash`` on the agent version's ``code_configuration``. + + :param agent_name: The name of the agent. Required. + :type agent_name: str + :param agent_version: The version of the agent whose code zip should be downloaded. Required. + :type agent_version: str + :return: AsyncIterator[bytes] + :rtype: AsyncIterator[bytes] + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[AsyncIterator[bytes]] = kwargs.pop("cls", None) + + _request = build_agents_download_agent_version_code_request( + agent_name=agent_name, + agent_version=agent_version, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _decompress = kwargs.pop("decompress", True) + _stream = kwargs.pop("stream", True) + pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [200]: + if _stream: + try: + await response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) + + response_headers = {} + response_headers["Content-Type"] = self._deserialize("str", response.headers.get("Content-Type")) + + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + + if cls: + return cls(pipeline_response, deserialized, response_headers) # type: ignore + + return deserialized # type: ignore + + @distributed_trace_async + async def download_agent_code(self, agent_name: str, **kwargs: Any) -> AsyncIterator[bytes]: + """Download the code zip for the latest version of a code-based hosted agent. Returns the + previously-uploaded zip (``application/zip``). The SHA-256 digest of the returned bytes matches + the ``content_hash`` on the latest version's ``code_configuration``. + + :param agent_name: The name of the agent whose latest-version code zip should be downloaded. + Required. + :type agent_name: str + :return: AsyncIterator[bytes] + :rtype: AsyncIterator[bytes] + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[AsyncIterator[bytes]] = kwargs.pop("cls", None) + + _request = build_agents_download_agent_code_request( + agent_name=agent_name, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _decompress = kwargs.pop("decompress", True) + _stream = kwargs.pop("stream", True) + pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [200]: + if _stream: + try: + await response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) + + response_headers = {} + response_headers["Content-Type"] = self._deserialize("str", response.headers.get("Content-Type")) + + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + + if cls: + return cls(pipeline_response, deserialized, response_headers) # type: ignore + + return deserialized # type: ignore + class EvaluationRulesOperations: """ diff --git a/sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/_patch.py b/sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/_patch.py index 48459efd771e..3c3e527771b4 100644 --- a/sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/_patch.py +++ b/sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/_patch.py @@ -59,7 +59,7 @@ class BetaOperations(GeneratedBetaOperations): skills: BetaSkillsOperations """:class:`~azure.ai.projects.aio.operations.BetaSkillsOperations` operations""" datasets: BetaDatasetsOperations - """:class:`~azure.ai.projects.aio.operations.BetaDatasetsOperations` operations""" + """:class:`~azure.ai.projects.aio.operations.BetaDatasetsOperations` operations""" def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) diff --git a/sdk/ai/azure-ai-projects/azure/ai/projects/models/__init__.py b/sdk/ai/azure-ai-projects/azure/ai/projects/models/__init__.py index b4e40ca68195..adcde6bef936 100644 --- a/sdk/ai/azure-ai-projects/azure/ai/projects/models/__init__.py +++ b/sdk/ai/azure-ai-projects/azure/ai/projects/models/__init__.py @@ -85,6 +85,9 @@ ContainerSkill, ContinuousEvaluationRuleAction, CosmosDBIndex, + CreateAgentFromCodeContent, + CreateAgentVersionFromCodeContent, + CreateAgentVersionFromCodeRequest, CronTrigger, CustomCredential, CustomGrammarFormatParam, @@ -246,7 +249,6 @@ StructuredOutputDefinition, Target, TargetConfig, - TaskDataGenerationJobOptions, TaxonomyCategory, TaxonomySubCategory, TelemetryConfig, @@ -307,6 +309,7 @@ AgentVersionStatus, AttackStrategy, AzureAISearchQueryType, + CodeDependencyResolution, ComputerEnvironment, ConnectionType, ContainerMemoryLimit, @@ -443,6 +446,9 @@ "ContainerSkill", "ContinuousEvaluationRuleAction", "CosmosDBIndex", + "CreateAgentFromCodeContent", + "CreateAgentVersionFromCodeContent", + "CreateAgentVersionFromCodeRequest", "CronTrigger", "CustomCredential", "CustomGrammarFormatParam", @@ -604,7 +610,6 @@ "StructuredOutputDefinition", "Target", "TargetConfig", - "TaskDataGenerationJobOptions", "TaxonomyCategory", "TaxonomySubCategory", "TelemetryConfig", @@ -662,6 +667,7 @@ "AgentVersionStatus", "AttackStrategy", "AzureAISearchQueryType", + "CodeDependencyResolution", "ComputerEnvironment", "ConnectionType", "ContainerMemoryLimit", diff --git a/sdk/ai/azure-ai-projects/azure/ai/projects/models/_enums.py b/sdk/ai/azure-ai-projects/azure/ai/projects/models/_enums.py index a709458309bf..40648951bbda 100644 --- a/sdk/ai/azure-ai-projects/azure/ai/projects/models/_enums.py +++ b/sdk/ai/azure-ai-projects/azure/ai/projects/models/_enums.py @@ -21,6 +21,8 @@ class _AgentDefinitionOptInKeys(str, Enum, metaclass=CaseInsensitiveEnumMeta): """CONTAINER_AGENTS_V1_PREVIEW.""" AGENT_ENDPOINT_V1_PREVIEW = "AgentEndpoints=V1Preview" """AGENT_ENDPOINT_V1_PREVIEW.""" + CODE_AGENTS_V1_PREVIEW = "CodeAgents=V1Preview" + """CODE_AGENTS_V1_PREVIEW.""" class _FoundryFeaturesOptInKeys(str, Enum, metaclass=CaseInsensitiveEnumMeta): @@ -234,6 +236,16 @@ class AzureAISearchQueryType(str, Enum, metaclass=CaseInsensitiveEnumMeta): """Query type ``vector_semantic_hybrid``.""" +class CodeDependencyResolution(str, Enum, metaclass=CaseInsensitiveEnumMeta): + """How package dependencies are resolved at deployment time for a code-based hosted agent.""" + + BUNDLED = "bundled" + """The caller has bundled all dependencies into the uploaded zip; the service performs no remote + build.""" + REMOTE_BUILD = "remote_build" + """The service builds dependencies remotely from the manifest included in the uploaded zip.""" + + class ComputerEnvironment(str, Enum, metaclass=CaseInsensitiveEnumMeta): """Type of ComputerEnvironment.""" @@ -375,9 +387,6 @@ class DataGenerationJobType(str, Enum, metaclass=CaseInsensitiveEnumMeta): """Single turn query and response from agent traces.""" TOOL_USE = "tool_use" """Tool calling conversation between user and agent.""" - TASK = "task" - """Task helps in providing a scenario description for generating multi turn conversation between - user and agent.""" class DatasetType(str, Enum, metaclass=CaseInsensitiveEnumMeta): diff --git a/sdk/ai/azure-ai-projects/azure/ai/projects/models/_models.py b/sdk/ai/azure-ai-projects/azure/ai/projects/models/_models.py index f0544466410e..8d1443124b21 100644 --- a/sdk/ai/azure-ai-projects/azure/ai/projects/models/_models.py +++ b/sdk/ai/azure-ai-projects/azure/ai/projects/models/_models.py @@ -12,6 +12,7 @@ from typing import Any, Literal, Mapping, Optional, TYPE_CHECKING, Union, overload from .._utils.model_base import Model as _Model, rest_discriminator, rest_field +from .._utils.utils import FileType from ._enums import ( AgentBlueprintReferenceType, AgentEndpointAuthorizationSchemeType, @@ -2926,6 +2927,12 @@ class CodeConfiguration(_Model): :vartype runtime: str :ivar entry_point: The entry point command and arguments for the code execution. Required. :vartype entry_point: list[str] + :ivar dependency_resolution: How package dependencies are resolved at deployment time. Defaults + to ``bundled``, where the caller bundles all dependencies into the uploaded zip and the service + performs no remote build. ``remote_build`` instructs the service to build dependencies remotely + from the manifest included in the uploaded zip. Required. Known values are: "bundled" and + "remote_build". + :vartype dependency_resolution: str or ~azure.ai.projects.models.CodeDependencyResolution :ivar content_hash: The SHA-256 hex digest of the uploaded code zip. Set by the service from the ``x-ms-code-zip-sha256`` request header; read-only in responses and never accepted in request payloads. @@ -2937,6 +2944,13 @@ class CodeConfiguration(_Model): Required.""" entry_point: list[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The entry point command and arguments for the code execution. Required.""" + dependency_resolution: Union[str, "_models.CodeDependencyResolution"] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) + """How package dependencies are resolved at deployment time. Defaults to ``bundled``, where the + caller bundles all dependencies into the uploaded zip and the service performs no remote build. + ``remote_build`` instructs the service to build dependencies remotely from the manifest + included in the uploaded zip. Required. Known values are: \"bundled\" and \"remote_build\".""" content_hash: Optional[str] = rest_field(visibility=["read"]) """The SHA-256 hex digest of the uploaded code zip. Set by the service from the ``x-ms-code-zip-sha256`` request header; read-only in responses and never accepted in request @@ -2948,6 +2962,7 @@ def __init__( *, runtime: str, entry_point: list[str], + dependency_resolution: Union[str, "_models.CodeDependencyResolution"], ) -> None: ... @overload @@ -3633,6 +3648,135 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: self.type = IndexType.COSMOS_DB # type: ignore +class CreateAgentFromCodeContent(_Model): + """Multipart request body for creating a new code-based agent (POST /agents). Inherits from + CreateAgentVersionFromCodeContent for future extensibility. + + :ivar metadata: JSON metadata including description and hosted definition. Required. + :vartype metadata: ~azure.ai.projects.models.CreateAgentVersionFromCodeRequest + :ivar code: The code zip file (max 250 MB). Required. + :vartype code: ~azure.ai.projects._utils.utils.FileType + """ + + metadata: "_models.CreateAgentVersionFromCodeRequest" = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) + """JSON metadata including description and hosted definition. Required.""" + code: FileType = rest_field( + visibility=["read", "create", "update", "delete", "query"], is_multipart_file_input=True + ) + """The code zip file (max 250 MB). Required.""" + + @overload + def __init__( + self, + *, + metadata: "_models.CreateAgentVersionFromCodeRequest", + code: FileType, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + + +class CreateAgentVersionFromCodeContent(_Model): + """Multipart request body for updating or versioning a code-based agent (POST /agents/{name} and + POST /agents/{name}/versions). + + :ivar metadata: JSON metadata including description and hosted definition. Required. + :vartype metadata: ~azure.ai.projects.models.CreateAgentVersionFromCodeRequest + :ivar code: The code zip file (max 250 MB). Required. + :vartype code: ~azure.ai.projects._utils.utils.FileType + """ + + metadata: "_models.CreateAgentVersionFromCodeRequest" = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) + """JSON metadata including description and hosted definition. Required.""" + code: FileType = rest_field( + visibility=["read", "create", "update", "delete", "query"], is_multipart_file_input=True + ) + """The code zip file (max 250 MB). Required.""" + + @overload + def __init__( + self, + *, + metadata: "_models.CreateAgentVersionFromCodeRequest", + code: FileType, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + + +class CreateAgentVersionFromCodeRequest(_Model): + """JSON metadata for code-based agent operations (create, update, create version). The agent name + comes from the URL path parameter or the ``x-ms-agent-name`` header, so it is not included in + this model. The content hash (SHA-256 of the zip) is carried in the ``x-ms-code-zip-sha256`` + header. + + :ivar description: A human-readable description of the agent. + :vartype description: str + :ivar metadata: Set of 16 key-value pairs that can be attached to an object. This can be + useful for storing additional information about the object in a structured + format, and querying for objects via API or the dashboard. + + Keys are strings with a maximum length of 64 characters. Values are strings + with a maximum length of 512 characters. + :vartype metadata: dict[str, str] + :ivar definition: The hosted agent definition including code_configuration (runtime, + entry_point), cpu, memory, and protocol_versions. Required. + :vartype definition: ~azure.ai.projects.models.HostedAgentDefinition + """ + + description: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """A human-readable description of the agent.""" + metadata: Optional[dict[str, str]] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """Set of 16 key-value pairs that can be attached to an object. This can be + useful for storing additional information about the object in a structured + format, and querying for objects via API or the dashboard. + + Keys are strings with a maximum length of 64 characters. Values are strings + with a maximum length of 512 characters.""" + definition: "_models.HostedAgentDefinition" = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """The hosted agent definition including code_configuration (runtime, entry_point), cpu, memory, + and protocol_versions. Required.""" + + @overload + def __init__( + self, + *, + definition: "_models.HostedAgentDefinition", + description: Optional[str] = None, + metadata: Optional[dict[str, str]] = None, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + + class Trigger(_Model): """Base model for Trigger of the schedule. @@ -4073,11 +4217,11 @@ class DataGenerationJobOptions(_Model): """Options for managing data generation jobs. You probably want to use the sub-classes and not this class directly. Known sub-classes are: - SimpleQnADataGenerationJobOptions, TaskDataGenerationJobOptions, - ToolUseFineTuningDataGenerationJobOptions, TracesDataGenerationJobOptions + SimpleQnADataGenerationJobOptions, ToolUseFineTuningDataGenerationJobOptions, + TracesDataGenerationJobOptions :ivar type: The data generation job type. Required. Known values are: "simple_qna", "traces", - "tool_use", and "task". + and "tool_use". :vartype type: str or ~azure.ai.projects.models.DataGenerationJobType :ivar max_samples: Maximum number of samples to generate. Required. :vartype max_samples: int @@ -4090,8 +4234,8 @@ class DataGenerationJobOptions(_Model): __mapping__: dict[str, _Model] = {} type: str = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) - """The data generation job type. Required. Known values are: \"simple_qna\", \"traces\", - \"tool_use\", and \"task\".""" + """The data generation job type. Required. Known values are: \"simple_qna\", \"traces\", and + \"tool_use\".""" max_samples: int = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Maximum number of samples to generate. Required.""" train_split: Optional[float] = rest_field(visibility=["read", "create", "update", "delete", "query"]) @@ -10571,46 +10715,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) -class TaskDataGenerationJobOptions(DataGenerationJobOptions, discriminator="task"): - """The options for a data generation job with Task type. - - :ivar max_samples: Maximum number of samples to generate. Required. - :vartype max_samples: int - :ivar train_split: The proportion of the generated data to be used for training when the data - is used for fine-tuning. The rest will be used for validation. Value should be between 0 and 1. - :vartype train_split: float - :ivar model_options: The LLM model options. - :vartype model_options: ~azure.ai.projects.models.DataGenerationModelOptions - :ivar type: The data generation job type, which is Task for this model. Required. Task helps in - providing a scenario description for generating multi turn conversation between user and agent. - :vartype type: str or ~azure.ai.projects.models.TASK - """ - - type: Literal[DataGenerationJobType.TASK] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore - """The data generation job type, which is Task for this model. Required. Task helps in providing a - scenario description for generating multi turn conversation between user and agent.""" - - @overload - def __init__( - self, - *, - max_samples: int, - train_split: Optional[float] = None, - model_options: Optional["_models.DataGenerationModelOptions"] = None, - ) -> None: ... - - @overload - def __init__(self, mapping: Mapping[str, Any]) -> None: - """ - :param mapping: raw JSON to initialize the model. - :type mapping: Mapping[str, Any] - """ - - def __init__(self, *args: Any, **kwargs: Any) -> None: - super().__init__(*args, **kwargs) - self.type = DataGenerationJobType.TASK # type: ignore - - class TaxonomyCategory(_Model): """Taxonomy category definition. diff --git a/sdk/ai/azure-ai-projects/azure/ai/projects/operations/_operations.py b/sdk/ai/azure-ai-projects/azure/ai/projects/operations/_operations.py index edcfcf622ab1..2635e82a9ae0 100644 --- a/sdk/ai/azure-ai-projects/azure/ai/projects/operations/_operations.py +++ b/sdk/ai/azure-ai-projects/azure/ai/projects/operations/_operations.py @@ -35,8 +35,9 @@ from .. import models as _models from .._configuration import AIProjectClientConfiguration -from .._utils.model_base import SdkJSONEncoder, _deserialize, _failsafe_deserialize +from .._utils.model_base import Model as _Model, SdkJSONEncoder, _deserialize, _failsafe_deserialize from .._utils.serialization import Deserializer, Serializer +from .._utils.utils import prepare_multipart_form_data JSON = MutableMapping[str, Any] _Unset: Any = object() @@ -72,6 +73,56 @@ def build_agents_get_request(agent_name: str, **kwargs: Any) -> HttpRequest: return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) +def build_agents_create_agent_from_code_request( # pylint: disable=name-too-long + *, agent_name: str, code_zip_sha256: str, **kwargs: Any +) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) + + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) + accept = _headers.pop("Accept", "application/json") + + # Construct URL + _url = "/agents" + + # Construct parameters + _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") + + # Construct headers + _headers["x-ms-agent-name"] = _SERIALIZER.header("agent_name", agent_name, "str") + _headers["x-ms-code-zip-sha256"] = _SERIALIZER.header("code_zip_sha256", code_zip_sha256, "str") + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") + + return HttpRequest(method="POST", url=_url, params=_params, headers=_headers, **kwargs) + + +def build_agents_update_agent_from_code_request( # pylint: disable=name-too-long + agent_name: str, *, code_zip_sha256: str, **kwargs: Any +) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) + + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) + accept = _headers.pop("Accept", "application/json") + + # Construct URL + _url = "/agents/{agent_name}" + path_format_arguments = { + "agent_name": _SERIALIZER.url("agent_name", agent_name, "str"), + } + + _url: str = _url.format(**path_format_arguments) # type: ignore + + # Construct parameters + _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") + + # Construct headers + _headers["x-ms-code-zip-sha256"] = _SERIALIZER.header("code_zip_sha256", code_zip_sha256, "str") + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") + + return HttpRequest(method="POST", url=_url, params=_params, headers=_headers, **kwargs) + + def build_agents_delete_request(agent_name: str, **kwargs: Any) -> HttpRequest: _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) @@ -279,6 +330,84 @@ def build_agents_list_versions_request( return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) +def build_agents_create_agent_version_from_code_request( # pylint: disable=name-too-long + agent_name: str, *, code_zip_sha256: str, **kwargs: Any +) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) + + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) + accept = _headers.pop("Accept", "application/json") + + # Construct URL + _url = "/agents/{agent_name}/versions" + path_format_arguments = { + "agent_name": _SERIALIZER.url("agent_name", agent_name, "str"), + } + + _url: str = _url.format(**path_format_arguments) # type: ignore + + # Construct parameters + _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") + + # Construct headers + _headers["x-ms-code-zip-sha256"] = _SERIALIZER.header("code_zip_sha256", code_zip_sha256, "str") + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") + + return HttpRequest(method="POST", url=_url, params=_params, headers=_headers, **kwargs) + + +def build_agents_download_agent_version_code_request( # pylint: disable=name-too-long + agent_name: str, agent_version: str, **kwargs: Any +) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) + + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) + accept = _headers.pop("Accept", "application/zip") + + # Construct URL + _url = "/agents/{agent_name}/versions/{agent_version}/code:download" + path_format_arguments = { + "agent_name": _SERIALIZER.url("agent_name", agent_name, "str"), + "agent_version": _SERIALIZER.url("agent_version", agent_version, "str"), + } + + _url: str = _url.format(**path_format_arguments) # type: ignore + + # Construct parameters + _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") + + # Construct headers + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") + + return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) + + +def build_agents_download_agent_code_request(agent_name: str, **kwargs: Any) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) + + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) + accept = _headers.pop("Accept", "application/zip") + + # Construct URL + _url = "/agents/{agent_name}/code:download" + path_format_arguments = { + "agent_name": _SERIALIZER.url("agent_name", agent_name, "str"), + } + + _url: str = _url.format(**path_format_arguments) # type: ignore + + # Construct parameters + _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") + + # Construct headers + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") + + return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) + + def build_evaluation_rules_get_request(id: str, **kwargs: Any) -> HttpRequest: _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) @@ -2684,14 +2813,77 @@ def get(self, agent_name: str, **kwargs: Any) -> _models.AgentDetails: return deserialized # type: ignore - @distributed_trace - def delete(self, agent_name: str, **kwargs: Any) -> _models.DeleteAgentResponse: - """Deletes an agent. + @overload + def create_agent_from_code( + self, body: _models.CreateAgentFromCodeContent, *, agent_name: str, code_zip_sha256: str, **kwargs: Any + ) -> _models.AgentDetails: + """Creates a new code-based agent. Uploads the code zip and creates the agent in a single call. + The agent name is provided in the ``x-ms-agent-name`` header since POST /agents has no name in + the URL path. The SHA-256 hex digest of the zip is provided in the ``x-ms-code-zip-sha256`` + header for integrity and dedup. The request body is multipart/form-data with a JSON metadata + part and a binary code part (part order is irrelevant). Maximum upload size is 250 MB. - :param agent_name: The name of the agent to delete. Required. - :type agent_name: str - :return: DeleteAgentResponse. The DeleteAgentResponse is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.DeleteAgentResponse + :param body: Required. + :type body: ~azure.ai.projects.models.CreateAgentFromCodeContent + :keyword agent_name: The unique name that identifies the agent. Max 63 chars, must start and + end with alphanumeric, hyphens allowed in the middle. Required. + :paramtype agent_name: str + :keyword code_zip_sha256: SHA-256 hex digest of the uploaded code zip. Used for change + detection (dedup) and integrity verification. Required. + :paramtype code_zip_sha256: str + :return: AgentDetails. The AgentDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentDetails + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + def create_agent_from_code( + self, body: JSON, *, agent_name: str, code_zip_sha256: str, **kwargs: Any + ) -> _models.AgentDetails: + """Creates a new code-based agent. Uploads the code zip and creates the agent in a single call. + The agent name is provided in the ``x-ms-agent-name`` header since POST /agents has no name in + the URL path. The SHA-256 hex digest of the zip is provided in the ``x-ms-code-zip-sha256`` + header for integrity and dedup. The request body is multipart/form-data with a JSON metadata + part and a binary code part (part order is irrelevant). Maximum upload size is 250 MB. + + :param body: Required. + :type body: JSON + :keyword agent_name: The unique name that identifies the agent. Max 63 chars, must start and + end with alphanumeric, hyphens allowed in the middle. Required. + :paramtype agent_name: str + :keyword code_zip_sha256: SHA-256 hex digest of the uploaded code zip. Used for change + detection (dedup) and integrity verification. Required. + :paramtype code_zip_sha256: str + :return: AgentDetails. The AgentDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentDetails + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @distributed_trace + def create_agent_from_code( + self, + body: Union[_models.CreateAgentFromCodeContent, JSON], + *, + agent_name: str, + code_zip_sha256: str, + **kwargs: Any + ) -> _models.AgentDetails: + """Creates a new code-based agent. Uploads the code zip and creates the agent in a single call. + The agent name is provided in the ``x-ms-agent-name`` header since POST /agents has no name in + the URL path. The SHA-256 hex digest of the zip is provided in the ``x-ms-code-zip-sha256`` + header for integrity and dedup. The request body is multipart/form-data with a JSON metadata + part and a binary code part (part order is irrelevant). Maximum upload size is 250 MB. + + :param body: Is either a CreateAgentFromCodeContent type or a JSON type. Required. + :type body: ~azure.ai.projects.models.CreateAgentFromCodeContent or JSON + :keyword agent_name: The unique name that identifies the agent. Max 63 chars, must start and + end with alphanumeric, hyphens allowed in the middle. Required. + :paramtype agent_name: str + :keyword code_zip_sha256: SHA-256 hex digest of the uploaded code zip. Used for change + detection (dedup) and integrity verification. Required. + :paramtype code_zip_sha256: str + :return: AgentDetails. The AgentDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentDetails :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -2705,11 +2897,18 @@ def delete(self, agent_name: str, **kwargs: Any) -> _models.DeleteAgentResponse: _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.DeleteAgentResponse] = kwargs.pop("cls", None) + cls: ClsType[_models.AgentDetails] = kwargs.pop("cls", None) - _request = build_agents_delete_request( + _body = body.as_dict() if isinstance(body, _Model) else body + _file_fields: list[str] = ["code"] + _data_fields: list[str] = ["metadata"] + _files = prepare_multipart_form_data(_body, _file_fields, _data_fields) + + _request = build_agents_create_agent_from_code_request( agent_name=agent_name, + code_zip_sha256=code_zip_sha256, api_version=self._config.api_version, + files=_files, headers=_headers, params=_params, ) @@ -2742,51 +2941,95 @@ def delete(self, agent_name: str, **kwargs: Any) -> _models.DeleteAgentResponse: if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.DeleteAgentResponse, response.json()) + deserialized = _deserialize(_models.AgentDetails, response.json()) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore return deserialized # type: ignore + @overload + def update_agent_from_code( + self, agent_name: str, body: _models.CreateAgentVersionFromCodeContent, *, code_zip_sha256: str, **kwargs: Any + ) -> _models.AgentDetails: + """Updates a code-based agent by uploading new code and creating a new version. If the code and + definition are unchanged (matched by x-ms-code-zip-sha256 header), returns the existing + version. The request body is multipart/form-data with a JSON metadata part and a binary code + part (part order is irrelevant). Maximum upload size is 250 MB. + + :param agent_name: The unique name that identifies the agent. Name can be used to + retrieve/update/delete the agent. + + * Must start and end with alphanumeric characters, + * Can contain hyphens in the middle + * Must not exceed 63 characters. Required. + :type agent_name: str + :param body: Required. + :type body: ~azure.ai.projects.models.CreateAgentVersionFromCodeContent + :keyword code_zip_sha256: SHA-256 hex digest of the uploaded code zip. Used for change + detection (dedup) and integrity verification. Required. + :paramtype code_zip_sha256: str + :return: AgentDetails. The AgentDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentDetails + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + def update_agent_from_code( + self, agent_name: str, body: JSON, *, code_zip_sha256: str, **kwargs: Any + ) -> _models.AgentDetails: + """Updates a code-based agent by uploading new code and creating a new version. If the code and + definition are unchanged (matched by x-ms-code-zip-sha256 header), returns the existing + version. The request body is multipart/form-data with a JSON metadata part and a binary code + part (part order is irrelevant). Maximum upload size is 250 MB. + + :param agent_name: The unique name that identifies the agent. Name can be used to + retrieve/update/delete the agent. + + * Must start and end with alphanumeric characters, + * Can contain hyphens in the middle + * Must not exceed 63 characters. Required. + :type agent_name: str + :param body: Required. + :type body: JSON + :keyword code_zip_sha256: SHA-256 hex digest of the uploaded code zip. Used for change + detection (dedup) and integrity verification. Required. + :paramtype code_zip_sha256: str + :return: AgentDetails. The AgentDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentDetails + :raises ~azure.core.exceptions.HttpResponseError: + """ + @distributed_trace - def list( + def update_agent_from_code( self, + agent_name: str, + body: Union[_models.CreateAgentVersionFromCodeContent, JSON], *, - kind: Optional[Union[str, _models.AgentKind]] = None, - limit: Optional[int] = None, - order: Optional[Union[str, _models.PageOrder]] = None, - before: Optional[str] = None, + code_zip_sha256: str, **kwargs: Any - ) -> ItemPaged["_models.AgentDetails"]: - """Returns the list of all agents. + ) -> _models.AgentDetails: + """Updates a code-based agent by uploading new code and creating a new version. If the code and + definition are unchanged (matched by x-ms-code-zip-sha256 header), returns the existing + version. The request body is multipart/form-data with a JSON metadata part and a binary code + part (part order is irrelevant). Maximum upload size is 250 MB. - :keyword kind: Filter agents by kind. If not provided, all agents are returned. Known values - are: "prompt", "hosted", and "workflow". Default value is None. - :paramtype kind: str or ~azure.ai.projects.models.AgentKind - :keyword limit: A limit on the number of objects to be returned. Limit can range between 1 and - 100, and the - default is 20. Default value is None. - :paramtype limit: int - :keyword order: Sort order by the ``created_at`` timestamp of the objects. ``asc`` for - ascending order and``desc`` - for descending order. Known values are: "asc" and "desc". Default value is None. - :paramtype order: str or ~azure.ai.projects.models.PageOrder - :keyword before: A cursor for use in pagination. ``before`` is an object ID that defines your - place in the list. - For instance, if you make a list request and receive 100 objects, ending with obj_foo, your - subsequent call can include before=obj_foo in order to fetch the previous page of the list. - Default value is None. - :paramtype before: str - :return: An iterator like instance of AgentDetails - :rtype: ~azure.core.paging.ItemPaged[~azure.ai.projects.models.AgentDetails] + :param agent_name: The unique name that identifies the agent. Name can be used to + retrieve/update/delete the agent. + + * Must start and end with alphanumeric characters, + * Can contain hyphens in the middle + * Must not exceed 63 characters. Required. + :type agent_name: str + :param body: Is either a CreateAgentVersionFromCodeContent type or a JSON type. Required. + :type body: ~azure.ai.projects.models.CreateAgentVersionFromCodeContent or JSON + :keyword code_zip_sha256: SHA-256 hex digest of the uploaded code zip. Used for change + detection (dedup) and integrity verification. Required. + :paramtype code_zip_sha256: str + :return: AgentDetails. The AgentDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentDetails :raises ~azure.core.exceptions.HttpResponseError: """ - _headers = kwargs.pop("headers", {}) or {} - _params = kwargs.pop("params", {}) or {} - - cls: ClsType[List[_models.AgentDetails]] = kwargs.pop("cls", None) - error_map: MutableMapping = { 401: ClientAuthenticationError, 404: ResourceNotFoundError, @@ -2795,31 +3038,196 @@ def list( } error_map.update(kwargs.pop("error_map", {}) or {}) - def prepare_request(_continuation_token=None): + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} - _request = build_agents_list_request( - kind=kind, - limit=limit, - order=order, - after=_continuation_token, - before=before, - api_version=self._config.api_version, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) - return _request + cls: ClsType[_models.AgentDetails] = kwargs.pop("cls", None) - def extract_data(pipeline_response): - deserialized = pipeline_response.http_response.json() - list_of_elem = _deserialize( - List[_models.AgentDetails], - deserialized.get("data", []), - ) - if cls: + _body = body.as_dict() if isinstance(body, _Model) else body + _file_fields: list[str] = ["code"] + _data_fields: list[str] = ["metadata"] + _files = prepare_multipart_form_data(_body, _file_fields, _data_fields) + + _request = build_agents_update_agent_from_code_request( + agent_name=agent_name, + code_zip_sha256=code_zip_sha256, + api_version=self._config.api_version, + files=_files, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _decompress = kwargs.pop("decompress", True) + _stream = kwargs.pop("stream", False) + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [200]: + if _stream: + try: + response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) + + if _stream: + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + else: + deserialized = _deserialize(_models.AgentDetails, response.json()) + + if cls: + return cls(pipeline_response, deserialized, {}) # type: ignore + + return deserialized # type: ignore + + @distributed_trace + def delete(self, agent_name: str, **kwargs: Any) -> _models.DeleteAgentResponse: + """Deletes an agent. + + :param agent_name: The name of the agent to delete. Required. + :type agent_name: str + :return: DeleteAgentResponse. The DeleteAgentResponse is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.DeleteAgentResponse + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[_models.DeleteAgentResponse] = kwargs.pop("cls", None) + + _request = build_agents_delete_request( + agent_name=agent_name, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _decompress = kwargs.pop("decompress", True) + _stream = kwargs.pop("stream", False) + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [200]: + if _stream: + try: + response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) + + if _stream: + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + else: + deserialized = _deserialize(_models.DeleteAgentResponse, response.json()) + + if cls: + return cls(pipeline_response, deserialized, {}) # type: ignore + + return deserialized # type: ignore + + @distributed_trace + def list( + self, + *, + kind: Optional[Union[str, _models.AgentKind]] = None, + limit: Optional[int] = None, + order: Optional[Union[str, _models.PageOrder]] = None, + before: Optional[str] = None, + **kwargs: Any + ) -> ItemPaged["_models.AgentDetails"]: + """Returns the list of all agents. + + :keyword kind: Filter agents by kind. If not provided, all agents are returned. Known values + are: "prompt", "hosted", and "workflow". Default value is None. + :paramtype kind: str or ~azure.ai.projects.models.AgentKind + :keyword limit: A limit on the number of objects to be returned. Limit can range between 1 and + 100, and the + default is 20. Default value is None. + :paramtype limit: int + :keyword order: Sort order by the ``created_at`` timestamp of the objects. ``asc`` for + ascending order and``desc`` + for descending order. Known values are: "asc" and "desc". Default value is None. + :paramtype order: str or ~azure.ai.projects.models.PageOrder + :keyword before: A cursor for use in pagination. ``before`` is an object ID that defines your + place in the list. + For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + subsequent call can include before=obj_foo in order to fetch the previous page of the list. + Default value is None. + :paramtype before: str + :return: An iterator like instance of AgentDetails + :rtype: ~azure.core.paging.ItemPaged[~azure.ai.projects.models.AgentDetails] + :raises ~azure.core.exceptions.HttpResponseError: + """ + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[List[_models.AgentDetails]] = kwargs.pop("cls", None) + + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + def prepare_request(_continuation_token=None): + + _request = build_agents_list_request( + kind=kind, + limit=limit, + order=order, + after=_continuation_token, + before=before, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + return _request + + def extract_data(pipeline_response): + deserialized = pipeline_response.http_response.json() + list_of_elem = _deserialize( + List[_models.AgentDetails], + deserialized.get("data", []), + ) + if cls: list_of_elem = cls(list_of_elem) # type: ignore return deserialized.get("last_id") or None, iter(list_of_elem) @@ -3487,6 +3895,279 @@ def get_next(_continuation_token=None): return ItemPaged(get_next, extract_data) + @overload + def create_agent_version_from_code( + self, agent_name: str, body: _models.CreateAgentVersionFromCodeContent, *, code_zip_sha256: str, **kwargs: Any + ) -> _models.AgentVersionDetails: + """create_agent_version_from_code. + + :param agent_name: The unique name that identifies the agent. Name can be used to + retrieve/update/delete the agent. + + * Must start and end with alphanumeric characters, + * Can contain hyphens in the middle + * Must not exceed 63 characters. Required. + :type agent_name: str + :param body: Required. + :type body: ~azure.ai.projects.models.CreateAgentVersionFromCodeContent + :keyword code_zip_sha256: SHA-256 hex digest of the uploaded code zip. Used for change + detection (dedup) and integrity verification. Required. + :paramtype code_zip_sha256: str + :return: AgentVersionDetails. The AgentVersionDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentVersionDetails + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + def create_agent_version_from_code( + self, agent_name: str, body: JSON, *, code_zip_sha256: str, **kwargs: Any + ) -> _models.AgentVersionDetails: + """create_agent_version_from_code. + + :param agent_name: The unique name that identifies the agent. Name can be used to + retrieve/update/delete the agent. + + * Must start and end with alphanumeric characters, + * Can contain hyphens in the middle + * Must not exceed 63 characters. Required. + :type agent_name: str + :param body: Required. + :type body: JSON + :keyword code_zip_sha256: SHA-256 hex digest of the uploaded code zip. Used for change + detection (dedup) and integrity verification. Required. + :paramtype code_zip_sha256: str + :return: AgentVersionDetails. The AgentVersionDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentVersionDetails + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @distributed_trace + def create_agent_version_from_code( + self, + agent_name: str, + body: Union[_models.CreateAgentVersionFromCodeContent, JSON], + *, + code_zip_sha256: str, + **kwargs: Any + ) -> _models.AgentVersionDetails: + """create_agent_version_from_code. + + :param agent_name: The unique name that identifies the agent. Name can be used to + retrieve/update/delete the agent. + + * Must start and end with alphanumeric characters, + * Can contain hyphens in the middle + * Must not exceed 63 characters. Required. + :type agent_name: str + :param body: Is either a CreateAgentVersionFromCodeContent type or a JSON type. Required. + :type body: ~azure.ai.projects.models.CreateAgentVersionFromCodeContent or JSON + :keyword code_zip_sha256: SHA-256 hex digest of the uploaded code zip. Used for change + detection (dedup) and integrity verification. Required. + :paramtype code_zip_sha256: str + :return: AgentVersionDetails. The AgentVersionDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentVersionDetails + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[_models.AgentVersionDetails] = kwargs.pop("cls", None) + + _body = body.as_dict() if isinstance(body, _Model) else body + _file_fields: list[str] = ["code"] + _data_fields: list[str] = ["metadata"] + _files = prepare_multipart_form_data(_body, _file_fields, _data_fields) + + _request = build_agents_create_agent_version_from_code_request( + agent_name=agent_name, + code_zip_sha256=code_zip_sha256, + api_version=self._config.api_version, + files=_files, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _decompress = kwargs.pop("decompress", True) + _stream = kwargs.pop("stream", False) + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [200]: + if _stream: + try: + response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) + + if _stream: + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + else: + deserialized = _deserialize(_models.AgentVersionDetails, response.json()) + + if cls: + return cls(pipeline_response, deserialized, {}) # type: ignore + + return deserialized # type: ignore + + @distributed_trace + def download_agent_version_code(self, agent_name: str, agent_version: str, **kwargs: Any) -> Iterator[bytes]: + """Download the code zip for a specific version of a code-based hosted agent. Returns the + previously-uploaded zip (``application/zip``). The SHA-256 digest of the returned bytes matches + the ``content_hash`` on the agent version's ``code_configuration``. + + :param agent_name: The name of the agent. Required. + :type agent_name: str + :param agent_version: The version of the agent whose code zip should be downloaded. Required. + :type agent_version: str + :return: Iterator[bytes] + :rtype: Iterator[bytes] + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[Iterator[bytes]] = kwargs.pop("cls", None) + + _request = build_agents_download_agent_version_code_request( + agent_name=agent_name, + agent_version=agent_version, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _decompress = kwargs.pop("decompress", True) + _stream = kwargs.pop("stream", True) + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [200]: + if _stream: + try: + response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) + + response_headers = {} + response_headers["Content-Type"] = self._deserialize("str", response.headers.get("Content-Type")) + + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + + if cls: + return cls(pipeline_response, deserialized, response_headers) # type: ignore + + return deserialized # type: ignore + + @distributed_trace + def download_agent_code(self, agent_name: str, **kwargs: Any) -> Iterator[bytes]: + """Download the code zip for the latest version of a code-based hosted agent. Returns the + previously-uploaded zip (``application/zip``). The SHA-256 digest of the returned bytes matches + the ``content_hash`` on the latest version's ``code_configuration``. + + :param agent_name: The name of the agent whose latest-version code zip should be downloaded. + Required. + :type agent_name: str + :return: Iterator[bytes] + :rtype: Iterator[bytes] + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[Iterator[bytes]] = kwargs.pop("cls", None) + + _request = build_agents_download_agent_code_request( + agent_name=agent_name, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _decompress = kwargs.pop("decompress", True) + _stream = kwargs.pop("stream", True) + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [200]: + if _stream: + try: + response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) + + response_headers = {} + response_headers["Content-Type"] = self._deserialize("str", response.headers.get("Content-Type")) + + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + + if cls: + return cls(pipeline_response, deserialized, response_headers) # type: ignore + + return deserialized # type: ignore + class EvaluationRulesOperations: """ diff --git a/sdk/ai/azure-ai-projects/tsp-location.yaml b/sdk/ai/azure-ai-projects/tsp-location.yaml index 9fe8f05d118a..c5eb35615866 100644 --- a/sdk/ai/azure-ai-projects/tsp-location.yaml +++ b/sdk/ai/azure-ai-projects/tsp-location.yaml @@ -1,4 +1,4 @@ directory: specification/ai-foundry/data-plane/Foundry -commit: 146c19ec2408517a8216df2b6403446a82813056 +commit: 43872da9bb5ec4a781f461f12fff51ab1f104d14 repo: Azure/azure-rest-api-specs additionalDirectories: