From 647b1f88f596e7647f8e2b8311748b673152987a Mon Sep 17 00:00:00 2001 From: A Vertex SDK engineer Date: Fri, 8 May 2026 13:48:11 -0700 Subject: [PATCH] feat: Add GetSkillRevision & ListSkillRevision methos in Vertex AI Skill Registry SDK PiperOrigin-RevId: 912678510 --- .../replays/test_skills_revisions_get.py | 70 ++++ .../replays/test_skills_revisions_list.py | 64 +++ .../unit/vertexai/genai/test_genai_skills.py | 122 +++++- vertexai/_genai/skill_revisions.py | 377 ++++++++++++++++++ vertexai/_genai/skills.py | 27 ++ vertexai/_genai/types/__init__.py | 28 ++ vertexai/_genai/types/common.py | 155 +++++++ 7 files changed, 841 insertions(+), 2 deletions(-) create mode 100644 tests/unit/vertexai/genai/replays/test_skills_revisions_get.py create mode 100644 tests/unit/vertexai/genai/replays/test_skills_revisions_list.py create mode 100644 vertexai/_genai/skill_revisions.py diff --git a/tests/unit/vertexai/genai/replays/test_skills_revisions_get.py b/tests/unit/vertexai/genai/replays/test_skills_revisions_get.py new file mode 100644 index 0000000000..a7a57fd1cb --- /dev/null +++ b/tests/unit/vertexai/genai/replays/test_skills_revisions_get.py @@ -0,0 +1,70 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +"""Tests the skills.revisions methods against the autopush endpoint.""" + +from tests.unit.vertexai.genai.replays import pytest_helper +from vertexai._genai import types + + +def test_get_skill_revision(client, tmp_path): + # Target the autopush sandbox endpoint for the Skill Registry API + client._api_client._http_options.base_url = ( + "https://us-central1-autopush-aiplatform.sandbox.googleapis.com" + ) + + # 1. Create a fresh unique skill + with open(tmp_path / "SKILL.md", "w") as f: + f.write("# Replay Revision Test Skill\nThis is a test skill.") + + created_skill = client.skills.create( + display_name="Replay Revision Test Skill", + description="A temporary skill to test revisions E2E", + config=types.CreateSkillConfig( + local_path=str(tmp_path), wait_for_completion=True + ), + ) + + try: + assert created_skill.name is not None + + # 2. List revisions to dynamically discover the revision ID + revisions_response = client.skills.revisions.list(name=created_skill.name) + revisions_list = revisions_response.skill_revisions + + assert len(revisions_list) > 0 + first_revision = revisions_list[0] + assert isinstance(first_revision, types.SkillRevision) + assert first_revision.name is not None + + # 3. Explicitly GET the revision by its resource name + revision = client.skills.revisions.get(name=first_revision.name) + + assert isinstance(revision, types.SkillRevision) + assert revision.name == first_revision.name + assert revision.state == types.SkillState.ACTIVE + + finally: + # 4. Clean up the temporary skill + client.skills.delete( + name=created_skill.name, + config=types.DeleteSkillConfig(wait_for_completion=True), + ) + + +pytestmark = pytest_helper.setup( + file=__file__, + globals_for_file=globals(), + test_method="skills.revisions.get", +) diff --git a/tests/unit/vertexai/genai/replays/test_skills_revisions_list.py b/tests/unit/vertexai/genai/replays/test_skills_revisions_list.py new file mode 100644 index 0000000000..76ab1d306e --- /dev/null +++ b/tests/unit/vertexai/genai/replays/test_skills_revisions_list.py @@ -0,0 +1,64 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +"""Tests the skills.revisions.list() method against the autopush endpoint.""" + +from tests.unit.vertexai.genai.replays import pytest_helper +from vertexai._genai import types + + +def test_list_skill_revisions(client, tmp_path): + # Target the autopush sandbox endpoint for the Skill Registry API + client._api_client._http_options.base_url = ( + "https://us-central1-autopush-aiplatform.sandbox.googleapis.com" + ) + + # 1. Create a fresh unique skill + with open(tmp_path / "SKILL.md", "w") as f: + f.write("# Replay List Revisions Test Skill\nThis is a test skill.") + + created_skill = client.skills.create( + display_name="Replay List Revisions Test Skill", + description="A temporary skill to test list revisions E2E", + config=types.CreateSkillConfig( + local_path=str(tmp_path), wait_for_completion=True + ), + ) + + try: + assert created_skill.name is not None + + # 2. List revisions + revisions_response = client.skills.revisions.list(name=created_skill.name) + revisions_list = revisions_response.skill_revisions + + assert len(revisions_list) > 0 + first_revision = revisions_list[0] + assert isinstance(first_revision, types.SkillRevision) + assert first_revision.name is not None + assert first_revision.state == types.SkillState.ACTIVE + + finally: + # 3. Clean up the temporary skill + client.skills.delete( + name=created_skill.name, + config=types.DeleteSkillConfig(wait_for_completion=True), + ) + + +pytestmark = pytest_helper.setup( + file=__file__, + globals_for_file=globals(), + test_method="skills.revisions.list", +) diff --git a/tests/unit/vertexai/genai/test_genai_skills.py b/tests/unit/vertexai/genai/test_genai_skills.py index 51bbefa60d..1c5e6a29a8 100644 --- a/tests/unit/vertexai/genai/test_genai_skills.py +++ b/tests/unit/vertexai/genai/test_genai_skills.py @@ -47,7 +47,6 @@ def async_skills_client(): class TestGenaiSkills: - """Tests the Genai Skills client.""" mock_get_skill_response = { "name": "projects/test-project/locations/test-location/skills/test-skill", @@ -219,7 +218,8 @@ def test_create_skill(self, skills_client): config={"local_path": tmpdir, "wait_for_completion": True}, ) - # Verify requests using robust assert_has_calls matching mock.ANY for base64 zipped Filesystem + # Verify requests using robust assert_has_calls matching + # mock.ANY for base64 zipped Filesystem request_mock.assert_has_calls( [ mock.call( @@ -896,3 +896,121 @@ async def test_delete_skill_async(self, async_skills_client): ), ] ) + + def test_get_skill_revision(self, skills_client): + revision_name = "projects/test-project/locations/test-location/skills/test-skill/revisions/rev-1" + mock_response = { + "name": revision_name, + "state": "ACTIVE", + } + + with mock.patch.object( + skills_client._api_client, "request", autospec=True + ) as request_mock: + request_mock.return_value = genai_types.HttpResponse( + body=json.dumps(mock_response) + ) + + revision = skills_client.revisions.get(name=revision_name) + + assert isinstance(revision, genai.types.SkillRevision) + assert revision.name == revision_name + assert revision.state == "ACTIVE" + + request_mock.assert_called_once_with( + "get", + revision_name, + {"_url": {"name": revision_name}}, + None, + ) + + @pytest.mark.asyncio + async def test_get_skill_revision_async(self, async_skills_client): + revision_name = "projects/test-project/locations/test-location/skills/test-skill/revisions/rev-1" + mock_response = { + "name": revision_name, + "state": "ACTIVE", + } + + with mock.patch.object( + async_skills_client._api_client, "async_request", autospec=True + ) as request_mock: + request_mock.return_value = genai_types.HttpResponse( + body=json.dumps(mock_response) + ) + + revision = await async_skills_client.revisions.get(name=revision_name) + + assert isinstance(revision, genai.types.SkillRevision) + assert revision.name == revision_name + assert revision.state == "ACTIVE" + + request_mock.assert_called_once_with( + "get", + revision_name, + {"_url": {"name": revision_name}}, + None, + ) + + def test_list_skill_revisions(self, skills_client): + skill_name = "projects/test-project/locations/test-location/skills/test-skill" + mock_response = { + "skillRevisions": [ + { + "name": f"{skill_name}/revisions/rev-1", + "state": "ACTIVE", + } + ] + } + + with mock.patch.object( + skills_client._api_client, "request", autospec=True + ) as request_mock: + request_mock.return_value = genai_types.HttpResponse( + body=json.dumps(mock_response) + ) + + response = skills_client.revisions.list(name=skill_name) + + assert isinstance(response, genai.types.ListSkillRevisionsResponse) + assert len(response.skill_revisions) == 1 + assert response.skill_revisions[0].name == f"{skill_name}/revisions/rev-1" + + request_mock.assert_called_once_with( + "get", + f"{skill_name}/revisions", + {"_url": {"name": skill_name}}, + None, + ) + + @pytest.mark.asyncio + async def test_list_skill_revisions_async(self, async_skills_client): + skill_name = "projects/test-project/locations/test-location/skills/test-skill" + mock_response = { + "skillRevisions": [ + { + "name": f"{skill_name}/revisions/rev-1", + "state": "ACTIVE", + } + ] + } + + with mock.patch.object( + async_skills_client._api_client, "async_request", autospec=True + ) as request_mock: + request_mock.return_value = genai_types.HttpResponse( + body=json.dumps(mock_response) + ) + + response = await async_skills_client.revisions.list(name=skill_name) + + assert isinstance(response, genai.types.ListSkillRevisionsResponse) + assert len(response.skill_revisions) == 1 + assert response.skill_revisions[0].name == f"{skill_name}/revisions/rev-1" + + request_mock.assert_called_once_with( + "get", + f"{skill_name}/revisions", + {"_url": {"name": skill_name}}, + None, + ) diff --git a/vertexai/_genai/skill_revisions.py b/vertexai/_genai/skill_revisions.py new file mode 100644 index 0000000000..f51cd9179c --- /dev/null +++ b/vertexai/_genai/skill_revisions.py @@ -0,0 +1,377 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Code generated by the Google Gen AI SDK generator DO NOT EDIT. + +import json +import logging +from typing import Any, Optional, Union +from urllib.parse import urlencode + +from google.genai import _api_module +from google.genai import _common +from google.genai._common import get_value_by_path as getv +from google.genai._common import set_value_by_path as setv + +from . import types + +logger = logging.getLogger("vertexai_genai.skillrevisions") + + +def _GetSkillRevisionRequestParameters_to_vertex( + from_object: Union[dict[str, Any], object], + parent_object: Optional[dict[str, Any]] = None, +) -> dict[str, Any]: + to_object: dict[str, Any] = {} + if getv(from_object, ["name"]) is not None: + setv(to_object, ["_url", "name"], getv(from_object, ["name"])) + + if getv(from_object, ["config"]) is not None: + setv(to_object, ["config"], getv(from_object, ["config"])) + + return to_object + + +def _ListSkillRevisionsConfig_to_vertex( + from_object: Union[dict[str, Any], object], + parent_object: Optional[dict[str, Any]] = None, +) -> dict[str, Any]: + to_object: dict[str, Any] = {} + + if getv(from_object, ["page_size"]) is not None: + setv(parent_object, ["_query", "pageSize"], getv(from_object, ["page_size"])) + + if getv(from_object, ["page_token"]) is not None: + setv(parent_object, ["_query", "pageToken"], getv(from_object, ["page_token"])) + + return to_object + + +def _ListSkillRevisionsRequestParameters_to_vertex( + from_object: Union[dict[str, Any], object], + parent_object: Optional[dict[str, Any]] = None, +) -> dict[str, Any]: + to_object: dict[str, Any] = {} + if getv(from_object, ["name"]) is not None: + setv(to_object, ["_url", "name"], getv(from_object, ["name"])) + + if getv(from_object, ["config"]) is not None: + setv( + to_object, + ["config"], + _ListSkillRevisionsConfig_to_vertex( + getv(from_object, ["config"]), to_object + ), + ) + + return to_object + + +class SkillRevisions(_api_module.BaseModule): + """Class for managing Skill Revisions in the Skill Registry.""" + + def get( + self, *, name: str, config: Optional[types.GetSkillRevisionConfigOrDict] = None + ) -> types.SkillRevision: + """ + Gets a Skill Revision. + """ + + parameter_model = types._GetSkillRevisionRequestParameters( + name=name, + config=config, + ) + + request_url_dict: Optional[dict[str, str]] + if not self._api_client.vertexai: + raise ValueError( + "This method is only supported in the Gemini Enterprise Agent Platform (previously known as Vertex AI) client." + ) + else: + request_dict = _GetSkillRevisionRequestParameters_to_vertex(parameter_model) + request_url_dict = request_dict.get("_url") + if request_url_dict: + path = "{name}".format_map(request_url_dict) + else: + path = "{name}" + + query_params = request_dict.get("_query") + if query_params: + path = f"{path}?{urlencode(query_params)}" + # TODO: remove the hack that pops config. + request_dict.pop("config", None) + + http_options: Optional[types.HttpOptions] = None + if ( + parameter_model.config is not None + and parameter_model.config.http_options is not None + ): + http_options = parameter_model.config.http_options + + request_dict = _common.convert_to_dict(request_dict) + request_dict = _common.encode_unserializable_types(request_dict) + + response = self._api_client.request("get", path, request_dict, http_options) + + response_dict = {} if not response.body else json.loads(response.body) + + return_value = types.SkillRevision._from_response( + response=response_dict, + kwargs=( + { + "config": { + "response_schema": getattr( + parameter_model.config, "response_schema", None + ), + "response_json_schema": getattr( + parameter_model.config, "response_json_schema", None + ), + "include_all_fields": getattr( + parameter_model.config, "include_all_fields", None + ), + } + } + if getattr(parameter_model, "config", None) + else {} + ), + ) + + self._api_client._verify_response(return_value) + return return_value + + def list( + self, + *, + name: str, + config: Optional[types.ListSkillRevisionsConfigOrDict] = None, + ) -> types.ListSkillRevisionsResponse: + """ + Lists Skill Revisions. + """ + + parameter_model = types._ListSkillRevisionsRequestParameters( + name=name, + config=config, + ) + + request_url_dict: Optional[dict[str, str]] + if not self._api_client.vertexai: + raise ValueError( + "This method is only supported in the Gemini Enterprise Agent Platform (previously known as Vertex AI) client." + ) + else: + request_dict = _ListSkillRevisionsRequestParameters_to_vertex( + parameter_model + ) + request_url_dict = request_dict.get("_url") + if request_url_dict: + path = "{name}/revisions".format_map(request_url_dict) + else: + path = "{name}/revisions" + + query_params = request_dict.get("_query") + if query_params: + path = f"{path}?{urlencode(query_params)}" + # TODO: remove the hack that pops config. + request_dict.pop("config", None) + + http_options: Optional[types.HttpOptions] = None + if ( + parameter_model.config is not None + and parameter_model.config.http_options is not None + ): + http_options = parameter_model.config.http_options + + request_dict = _common.convert_to_dict(request_dict) + request_dict = _common.encode_unserializable_types(request_dict) + + response = self._api_client.request("get", path, request_dict, http_options) + + response_dict = {} if not response.body else json.loads(response.body) + + return_value = types.ListSkillRevisionsResponse._from_response( + response=response_dict, + kwargs=( + { + "config": { + "response_schema": getattr( + parameter_model.config, "response_schema", None + ), + "response_json_schema": getattr( + parameter_model.config, "response_json_schema", None + ), + "include_all_fields": getattr( + parameter_model.config, "include_all_fields", None + ), + } + } + if getattr(parameter_model, "config", None) + else {} + ), + ) + + self._api_client._verify_response(return_value) + return return_value + + +class AsyncSkillRevisions(_api_module.BaseModule): + """Class for managing Skill Revisions in the Skill Registry.""" + + async def get( + self, *, name: str, config: Optional[types.GetSkillRevisionConfigOrDict] = None + ) -> types.SkillRevision: + """ + Gets a Skill Revision. + """ + + parameter_model = types._GetSkillRevisionRequestParameters( + name=name, + config=config, + ) + + request_url_dict: Optional[dict[str, str]] + if not self._api_client.vertexai: + raise ValueError( + "This method is only supported in the Gemini Enterprise Agent Platform (previously known as Vertex AI) client." + ) + else: + request_dict = _GetSkillRevisionRequestParameters_to_vertex(parameter_model) + request_url_dict = request_dict.get("_url") + if request_url_dict: + path = "{name}".format_map(request_url_dict) + else: + path = "{name}" + + query_params = request_dict.get("_query") + if query_params: + path = f"{path}?{urlencode(query_params)}" + # TODO: remove the hack that pops config. + request_dict.pop("config", None) + + http_options: Optional[types.HttpOptions] = None + if ( + parameter_model.config is not None + and parameter_model.config.http_options is not None + ): + http_options = parameter_model.config.http_options + + request_dict = _common.convert_to_dict(request_dict) + request_dict = _common.encode_unserializable_types(request_dict) + + response = await self._api_client.async_request( + "get", path, request_dict, http_options + ) + + response_dict = {} if not response.body else json.loads(response.body) + + return_value = types.SkillRevision._from_response( + response=response_dict, + kwargs=( + { + "config": { + "response_schema": getattr( + parameter_model.config, "response_schema", None + ), + "response_json_schema": getattr( + parameter_model.config, "response_json_schema", None + ), + "include_all_fields": getattr( + parameter_model.config, "include_all_fields", None + ), + } + } + if getattr(parameter_model, "config", None) + else {} + ), + ) + + self._api_client._verify_response(return_value) + return return_value + + async def list( + self, + *, + name: str, + config: Optional[types.ListSkillRevisionsConfigOrDict] = None, + ) -> types.ListSkillRevisionsResponse: + """ + Lists Skill Revisions. + """ + + parameter_model = types._ListSkillRevisionsRequestParameters( + name=name, + config=config, + ) + + request_url_dict: Optional[dict[str, str]] + if not self._api_client.vertexai: + raise ValueError( + "This method is only supported in the Gemini Enterprise Agent Platform (previously known as Vertex AI) client." + ) + else: + request_dict = _ListSkillRevisionsRequestParameters_to_vertex( + parameter_model + ) + request_url_dict = request_dict.get("_url") + if request_url_dict: + path = "{name}/revisions".format_map(request_url_dict) + else: + path = "{name}/revisions" + + query_params = request_dict.get("_query") + if query_params: + path = f"{path}?{urlencode(query_params)}" + # TODO: remove the hack that pops config. + request_dict.pop("config", None) + + http_options: Optional[types.HttpOptions] = None + if ( + parameter_model.config is not None + and parameter_model.config.http_options is not None + ): + http_options = parameter_model.config.http_options + + request_dict = _common.convert_to_dict(request_dict) + request_dict = _common.encode_unserializable_types(request_dict) + + response = await self._api_client.async_request( + "get", path, request_dict, http_options + ) + + response_dict = {} if not response.body else json.loads(response.body) + + return_value = types.ListSkillRevisionsResponse._from_response( + response=response_dict, + kwargs=( + { + "config": { + "response_schema": getattr( + parameter_model.config, "response_schema", None + ), + "response_json_schema": getattr( + parameter_model.config, "response_json_schema", None + ), + "include_all_fields": getattr( + parameter_model.config, "include_all_fields", None + ), + } + } + if getattr(parameter_model, "config", None) + else {} + ), + ) + + self._api_client._verify_response(return_value) + return return_value diff --git a/vertexai/_genai/skills.py b/vertexai/_genai/skills.py index ce15046456..7c6c818180 100644 --- a/vertexai/_genai/skills.py +++ b/vertexai/_genai/skills.py @@ -17,8 +17,10 @@ import asyncio import base64 +import importlib import json import logging +import typing from typing import Any, Iterator, Optional, Union from urllib.parse import urlencode @@ -31,6 +33,12 @@ from . import _skills_utils from . import types +if typing.TYPE_CHECKING: + from . import skill_revisions as skill_revisions_module + + _ = skill_revisions_module + + logger = logging.getLogger("vertexai_genai.skills") @@ -940,6 +948,16 @@ def delete( return operation + _revisions = None + + @property + def revisions(self) -> "skill_revisions_module.SkillRevisions": + """Returns the revisions sub-module.""" + if self._revisions is None: + # Lazy load to avoid circular imports + self._revisions = importlib.import_module(".skill_revisions", __package__) + return self._revisions.SkillRevisions(self._api_client) # type: ignore[no-any-return] + class AsyncSkills(_api_module.BaseModule): """Class for managing Skills in the Skill Registry.""" @@ -1684,3 +1702,12 @@ async def delete( return None return operation + + _revisions = None + + @property + def revisions(self) -> "skill_revisions_module.AsyncSkillRevisions": + """Returns the revisions sub-module asynchronously.""" + if self._revisions is None: + self._revisions = importlib.import_module(".skill_revisions", __package__) + return self._revisions.AsyncSkillRevisions(self._api_client) # type: ignore[no-any-return] diff --git a/vertexai/_genai/types/__init__.py b/vertexai/_genai/types/__init__.py index b063a10dc8..c749fbd16c 100644 --- a/vertexai/_genai/types/__init__.py +++ b/vertexai/_genai/types/__init__.py @@ -94,6 +94,7 @@ from .common import _GetSandboxEnvironmentTemplateRequestParameters from .common import _GetSkillOperationParameters from .common import _GetSkillRequestParameters +from .common import _GetSkillRevisionRequestParameters from .common import _IngestEventsRequestParameters from .common import _ListAgentEngineMemoryRequestParameters from .common import _ListAgentEngineMemoryRevisionsRequestParameters @@ -110,6 +111,7 @@ from .common import _ListMultimodalDatasetsRequestParameters from .common import _ListSandboxEnvironmentSnapshotsRequestParameters from .common import _ListSandboxEnvironmentTemplatesRequestParameters +from .common import _ListSkillRevisionsRequestParameters from .common import _ListSkillsRequestParameters from .common import _OptimizeRequestParameters from .common import _OptimizeRequestParameters @@ -630,6 +632,9 @@ from .common import GetSkillOperationConfig from .common import GetSkillOperationConfigDict from .common import GetSkillOperationConfigOrDict +from .common import GetSkillRevisionConfig +from .common import GetSkillRevisionConfigDict +from .common import GetSkillRevisionConfigOrDict from .common import IdentityType from .common import Importance from .common import IngestEventsConfig @@ -739,6 +744,12 @@ from .common import ListSandboxEnvironmentTemplatesResponse from .common import ListSandboxEnvironmentTemplatesResponseDict from .common import ListSandboxEnvironmentTemplatesResponseOrDict +from .common import ListSkillRevisionsConfig +from .common import ListSkillRevisionsConfigDict +from .common import ListSkillRevisionsConfigOrDict +from .common import ListSkillRevisionsResponse +from .common import ListSkillRevisionsResponseDict +from .common import ListSkillRevisionsResponseOrDict from .common import ListSkillsConfig from .common import ListSkillsConfigDict from .common import ListSkillsConfigOrDict @@ -1287,6 +1298,9 @@ from .common import SkillOperationDict from .common import SkillOperationOrDict from .common import SkillOrDict +from .common import SkillRevision +from .common import SkillRevisionDict +from .common import SkillRevisionOrDict from .common import SkillState from .common import State from .common import Strategy @@ -2565,6 +2579,18 @@ "GetSkillOperationConfig", "GetSkillOperationConfigDict", "GetSkillOperationConfigOrDict", + "GetSkillRevisionConfig", + "GetSkillRevisionConfigDict", + "GetSkillRevisionConfigOrDict", + "SkillRevision", + "SkillRevisionDict", + "SkillRevisionOrDict", + "ListSkillRevisionsConfig", + "ListSkillRevisionsConfigDict", + "ListSkillRevisionsConfigOrDict", + "ListSkillRevisionsResponse", + "ListSkillRevisionsResponseDict", + "ListSkillRevisionsResponseOrDict", "PromptOptimizerConfig", "PromptOptimizerConfigDict", "PromptOptimizerConfigOrDict", @@ -2810,6 +2836,8 @@ "_ListSkillsRequestParameters", "_DeleteSkillRequestParameters", "_GetSkillOperationParameters", + "_GetSkillRevisionRequestParameters", + "_ListSkillRevisionsRequestParameters", "evals", "agent_engines", "prompts", diff --git a/vertexai/_genai/types/common.py b/vertexai/_genai/types/common.py index e33f01470d..4eb672e852 100644 --- a/vertexai/_genai/types/common.py +++ b/vertexai/_genai/types/common.py @@ -18507,6 +18507,161 @@ class _GetSkillOperationParametersDict(TypedDict, total=False): ] +class GetSkillRevisionConfig(_common.BaseModel): + + http_options: Optional[genai_types.HttpOptions] = Field( + default=None, description="""Used to override HTTP request options.""" + ) + + +class GetSkillRevisionConfigDict(TypedDict, total=False): + + http_options: Optional[genai_types.HttpOptionsDict] + """Used to override HTTP request options.""" + + +GetSkillRevisionConfigOrDict = Union[GetSkillRevisionConfig, GetSkillRevisionConfigDict] + + +class _GetSkillRevisionRequestParameters(_common.BaseModel): + + name: Optional[str] = Field( + default=None, + description="""The resource name of the Skill Revision to retrieve. Format: projects/{project}/locations/{location}/skills/{skill}/revisions/{revision}""", + ) + config: Optional[GetSkillRevisionConfig] = Field(default=None, description="""""") + + +class _GetSkillRevisionRequestParametersDict(TypedDict, total=False): + + name: Optional[str] + """The resource name of the Skill Revision to retrieve. Format: projects/{project}/locations/{location}/skills/{skill}/revisions/{revision}""" + + config: Optional[GetSkillRevisionConfigDict] + """""" + + +_GetSkillRevisionRequestParametersOrDict = Union[ + _GetSkillRevisionRequestParameters, _GetSkillRevisionRequestParametersDict +] + + +class SkillRevision(_common.BaseModel): + + name: Optional[str] = Field( + default=None, + description="""Identifier. The resource name of the Skill Revision. Format: `projects/{project}/locations/{location}/skills/{skill}/revisions/{revision}`""", + ) + create_time: Optional[datetime.datetime] = Field( + default=None, + description="""Output only. Timestamp when this Skill Revision was created.""", + ) + skill: Optional[Skill] = Field( + default=None, + description="""Output only. The state of the Skill at this revision. TODO(b/503772996) Use a different proto for skill data included in skill revision""", + ) + state: Optional[SkillState] = Field( + default=None, description="""Output only. The state of the Skill Revision.""" + ) + + +class SkillRevisionDict(TypedDict, total=False): + + name: Optional[str] + """Identifier. The resource name of the Skill Revision. Format: `projects/{project}/locations/{location}/skills/{skill}/revisions/{revision}`""" + + create_time: Optional[datetime.datetime] + """Output only. Timestamp when this Skill Revision was created.""" + + skill: Optional[SkillDict] + """Output only. The state of the Skill at this revision. TODO(b/503772996) Use a different proto for skill data included in skill revision""" + + state: Optional[SkillState] + """Output only. The state of the Skill Revision.""" + + +SkillRevisionOrDict = Union[SkillRevision, SkillRevisionDict] + + +class ListSkillRevisionsConfig(_common.BaseModel): + + http_options: Optional[genai_types.HttpOptions] = Field( + default=None, description="""Used to override HTTP request options.""" + ) + page_size: Optional[int] = Field(default=None, description="""""") + page_token: Optional[str] = Field(default=None, description="""""") + + +class ListSkillRevisionsConfigDict(TypedDict, total=False): + + http_options: Optional[genai_types.HttpOptionsDict] + """Used to override HTTP request options.""" + + page_size: Optional[int] + """""" + + page_token: Optional[str] + """""" + + +ListSkillRevisionsConfigOrDict = Union[ + ListSkillRevisionsConfig, ListSkillRevisionsConfigDict +] + + +class _ListSkillRevisionsRequestParameters(_common.BaseModel): + """Parameters for ListSkillRevisionsRequest.""" + + name: Optional[str] = Field( + default=None, + description="""Required. The name of the Skill to list revisions for.""", + ) + config: Optional[ListSkillRevisionsConfig] = Field(default=None, description="""""") + + +class _ListSkillRevisionsRequestParametersDict(TypedDict, total=False): + """Parameters for ListSkillRevisionsRequest.""" + + name: Optional[str] + """Required. The name of the Skill to list revisions for.""" + + config: Optional[ListSkillRevisionsConfigDict] + """""" + + +_ListSkillRevisionsRequestParametersOrDict = Union[ + _ListSkillRevisionsRequestParameters, _ListSkillRevisionsRequestParametersDict +] + + +class ListSkillRevisionsResponse(_common.BaseModel): + + sdk_http_response: Optional[genai_types.HttpResponse] = Field( + default=None, description="""Used to retain the full HTTP response.""" + ) + next_page_token: Optional[str] = Field(default=None, description="""""") + skill_revisions: Optional[list[SkillRevision]] = Field( + default=None, description="""List of Skill Revisions.""" + ) + + +class ListSkillRevisionsResponseDict(TypedDict, total=False): + + sdk_http_response: Optional[genai_types.HttpResponseDict] + """Used to retain the full HTTP response.""" + + next_page_token: Optional[str] + """""" + + skill_revisions: Optional[list[SkillRevisionDict]] + """List of Skill Revisions.""" + + +ListSkillRevisionsResponseOrDict = Union[ + ListSkillRevisionsResponse, ListSkillRevisionsResponseDict +] + + class PromptOptimizerConfig(_common.BaseModel): """VAPO Prompt Optimizer Config."""