Skip to content

Commit bc4be37

Browse files
vertex-sdk-botcopybara-github
authored andcommitted
feat: Make skill_id a required parameter in skills.create
The `skill_id` parameter is now a required keyword argument in the `skills.create()` method. It was previously an optional field within the `config` object. PiperOrigin-RevId: 917387423
1 parent df50ac0 commit bc4be37

8 files changed

Lines changed: 1156 additions & 1106 deletions

File tree

agentplatform/_genai/skills.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,6 @@ def _CreateSkillConfig_to_vertex(
5555
getv(from_object, ["zipped_filesystem"]),
5656
)
5757

58-
if getv(from_object, ["skill_id"]) is not None:
59-
setv(parent_object, ["_query", "skillId"], getv(from_object, ["skill_id"]))
60-
6158
return to_object
6259

6360

@@ -75,6 +72,9 @@ def _CreateSkillRequestParameters_to_vertex(
7572
if getv(from_object, ["config"]) is not None:
7673
_CreateSkillConfig_to_vertex(getv(from_object, ["config"]), to_object)
7774

75+
if getv(from_object, ["skill_id"]) is not None:
76+
setv(to_object, ["_query", "skillId"], getv(from_object, ["skill_id"]))
77+
7878
return to_object
7979

8080

@@ -367,6 +367,7 @@ def _create(
367367
display_name: str,
368368
description: str,
369369
config: Optional[types.CreateSkillConfigOrDict] = None,
370+
skill_id: str,
370371
) -> types.SkillOperation:
371372
"""
372373
Creates a new Skill.
@@ -376,6 +377,7 @@ def _create(
376377
display_name=display_name,
377378
description=description,
378379
config=config,
380+
skill_id=skill_id,
379381
)
380382

381383
request_url_dict: Optional[dict[str, str]]
@@ -712,13 +714,17 @@ def _get_skill_operation(
712714
def create(
713715
self,
714716
*,
717+
skill_id: str,
715718
display_name: str,
716719
description: str,
717720
config: Optional[types.CreateSkillConfigOrDict] = None,
718721
) -> Union[types.Skill, types.SkillOperation]:
719722
"""Creates a new Skill.
720723
721724
Args:
725+
skill_id (str):
726+
Required. The ID to use for the Skill, which will become the final
727+
component of the Skill's resource name.
722728
display_name (str):
723729
Required. The display name of the Skill.
724730
description (str):
@@ -775,6 +781,7 @@ def create(
775781
config.zipped_filesystem = zipped_filesystem_payload
776782

777783
operation = self._create(
784+
skill_id=skill_id,
778785
display_name=display_name,
779786
description=description,
780787
config=config,
@@ -1110,6 +1117,7 @@ async def _create(
11101117
display_name: str,
11111118
description: str,
11121119
config: Optional[types.CreateSkillConfigOrDict] = None,
1120+
skill_id: str,
11131121
) -> types.SkillOperation:
11141122
"""
11151123
Creates a new Skill.
@@ -1119,6 +1127,7 @@ async def _create(
11191127
display_name=display_name,
11201128
description=description,
11211129
config=config,
1130+
skill_id=skill_id,
11221131
)
11231132

11241133
request_url_dict: Optional[dict[str, str]]
@@ -1465,13 +1474,17 @@ async def _get_skill_operation(
14651474
async def create(
14661475
self,
14671476
*,
1477+
skill_id: str,
14681478
display_name: str,
14691479
description: str,
14701480
config: Optional[types.CreateSkillConfigOrDict] = None,
14711481
) -> Union[types.Skill, types.SkillOperation]:
14721482
"""Creates a new Skill asynchronously.
14731483
14741484
Args:
1485+
skill_id (str):
1486+
Required. The ID to use for the Skill, which will become the final
1487+
component of the Skill's resource name.
14751488
display_name (str):
14761489
Required. The display name of the Skill.
14771490
description (str):
@@ -1529,6 +1542,7 @@ async def create(
15291542
config.zipped_filesystem = zipped_filesystem_payload
15301543

15311544
operation = await self._create(
1545+
skill_id=skill_id,
15321546
display_name=display_name,
15331547
description=description,
15341548
config=config,

agentplatform/_genai/types/common.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18262,12 +18262,6 @@ class CreateSkillConfig(_common.BaseModel):
1826218262
zipped_filesystem: Optional[Any] = Field(
1826318263
default=None, description="""Optional. The zipped filesystem of the Skill."""
1826418264
)
18265-
skill_id: Optional[str] = Field(
18266-
default=None,
18267-
description="""Optional. The ID to use for the Skill, which will become the final
18268-
component of the Skill's resource name.
18269-
""",
18270-
)
1827118265

1827218266

1827318267
class CreateSkillConfigDict(TypedDict, total=False):
@@ -18287,11 +18281,6 @@ class CreateSkillConfigDict(TypedDict, total=False):
1828718281
zipped_filesystem: Optional[Any]
1828818282
"""Optional. The zipped filesystem of the Skill."""
1828918283

18290-
skill_id: Optional[str]
18291-
"""Optional. The ID to use for the Skill, which will become the final
18292-
component of the Skill's resource name.
18293-
"""
18294-
1829518284

1829618285
CreateSkillConfigOrDict = Union[CreateSkillConfig, CreateSkillConfigDict]
1829718286

@@ -18306,6 +18295,12 @@ class _CreateSkillRequestParameters(_common.BaseModel):
1830618295
default=None, description="""Required. The description of the Skill."""
1830718296
)
1830818297
config: Optional[CreateSkillConfig] = Field(default=None, description="""""")
18298+
skill_id: Optional[str] = Field(
18299+
default=None,
18300+
description="""Required. The ID to use for the Skill, which will become the final
18301+
component of the Skill's resource name.
18302+
""",
18303+
)
1830918304

1831018305

1831118306
class _CreateSkillRequestParametersDict(TypedDict, total=False):
@@ -18320,6 +18315,11 @@ class _CreateSkillRequestParametersDict(TypedDict, total=False):
1832018315
config: Optional[CreateSkillConfigDict]
1832118316
""""""
1832218317

18318+
skill_id: Optional[str]
18319+
"""Required. The ID to use for the Skill, which will become the final
18320+
component of the Skill's resource name.
18321+
"""
18322+
1832318323

1832418324
_CreateSkillRequestParametersOrDict = Union[
1832518325
_CreateSkillRequestParameters, _CreateSkillRequestParametersDict

tests/unit/agentplatform/genai/replays/test_skills_create.py

Lines changed: 37 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -28,47 +28,49 @@
2828

2929

3030
def test_create_skill(client, tmp_path):
31-
client._api_client._http_options.base_url = (
32-
"https://us-central1-aiplatform.googleapis.com"
33-
)
31+
client._api_client._http_options.base_url = (
32+
"https://us-central1-aiplatform.googleapis.com"
33+
)
3434

35-
# Create a dummy skill structure (SKILL.md is required by the spec)
36-
with open(tmp_path / "SKILL.md", "w") as f:
37-
f.write("# My Replay Skill\nThis is a test skill for replay tests.")
35+
# Create a dummy skill structure (SKILL.md is required by the spec)
36+
with open(tmp_path / "SKILL.md", "w") as f:
37+
f.write("# My Replay Skill\nThis is a test skill for replay tests.")
3838

39-
skill = client.skills.create(
40-
display_name="My Replay Skill",
41-
description="My Replay Skill Description",
42-
config=types.CreateSkillConfig(
43-
local_path=str(tmp_path), wait_for_completion=True
44-
),
45-
)
39+
skill = client.skills.create(
40+
skill_id="my-replay-skill-v2",
41+
display_name="My Replay Skill",
42+
description="My Replay Skill Description",
43+
config=types.CreateSkillConfig(
44+
local_path=str(tmp_path), wait_for_completion=True
45+
),
46+
)
4647

47-
assert skill.name is not None
48-
assert skill.display_name == "My Replay Skill"
49-
assert skill.description == "My Replay Skill Description"
48+
assert skill.name is not None
49+
assert skill.display_name == "My Replay Skill"
50+
assert skill.description == "My Replay Skill Description"
5051

5152

5253
def test_create_skill_with_prezipped_bytes(client):
53-
"""Tests the creation of a skill with pre-zipped bytes."""
54-
client._api_client._http_options.base_url = (
55-
"https://us-central1-aiplatform.googleapis.com"
56-
)
54+
"""Tests the creation of a skill with pre-zipped bytes."""
55+
client._api_client._http_options.base_url = (
56+
"https://us-central1-aiplatform.googleapis.com"
57+
)
5758

58-
zip_buffer = io.BytesIO()
59-
zinfo = zipfile.ZipInfo("SKILL.md", date_time=(1980, 1, 1, 0, 0, 0))
60-
with zipfile.ZipFile(zip_buffer, "w") as zip_file:
61-
zip_file.writestr(zinfo, "# My Zipped Replay Skill\nThis is a test.")
62-
zipped_bytes = zip_buffer.getvalue()
59+
zip_buffer = io.BytesIO()
60+
zinfo = zipfile.ZipInfo("SKILL.md", date_time=(1980, 1, 1, 0, 0, 0))
61+
with zipfile.ZipFile(zip_buffer, "w") as zip_file:
62+
zip_file.writestr(zinfo, "# My Zipped Replay Skill\nThis is a test.")
63+
zipped_bytes = zip_buffer.getvalue()
6364

64-
skill = client.skills.create(
65-
display_name="My Zipped Replay Skill",
66-
description="My Zipped Replay Skill Description",
67-
config=types.CreateSkillConfig(
68-
zipped_filesystem=zipped_bytes, wait_for_completion=True
69-
),
70-
)
65+
skill = client.skills.create(
66+
skill_id="my-zipped-replay-skill-v2",
67+
display_name="My Zipped Replay Skill",
68+
description="My Zipped Replay Skill Description",
69+
config=types.CreateSkillConfig(
70+
zipped_filesystem=zipped_bytes, wait_for_completion=True
71+
),
72+
)
7173

72-
assert skill.name is not None
73-
assert skill.display_name == "My Zipped Replay Skill"
74-
assert skill.description == "My Zipped Replay Skill Description"
74+
assert skill.name is not None
75+
assert skill.display_name == "My Zipped Replay Skill"
76+
assert skill.description == "My Zipped Replay Skill Description"

tests/unit/agentplatform/genai/replays/test_skills_delete.py

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,28 +13,29 @@
1313

1414
def test_delete_skill(client, tmp_path):
1515

16-
# 1. Create a fresh unique skill first
17-
with open(tmp_path / "SKILL.md", "w") as f:
18-
f.write("# Test Skill\nTo be deleted.")
19-
20-
created_skill = client.skills.create(
21-
display_name="To Be Deleted Skill",
22-
description="Skill to be deleted",
23-
config=types.CreateSkillConfig(
24-
local_path=str(tmp_path), wait_for_completion=True
25-
),
26-
)
27-
28-
assert created_skill.name is not None
29-
30-
# 2. Delete the skill and wait for LRO completion
31-
client.skills.delete(
16+
# 1. Create a fresh unique skill first
17+
with open(tmp_path / "SKILL.md", "w") as f:
18+
f.write("# Test Skill\nTo be deleted.")
19+
20+
created_skill = client.skills.create(
21+
skill_id="my-skill-to-delete",
22+
display_name="To Be Deleted Skill",
23+
description="Skill to be deleted",
24+
config=types.CreateSkillConfig(
25+
local_path=str(tmp_path), wait_for_completion=True
26+
),
27+
)
28+
29+
assert created_skill.name is not None
30+
31+
# 2. Delete the skill and wait for LRO completion
32+
client.skills.delete(
3233
name=created_skill.name,
3334
config=types.DeleteSkillConfig(wait_for_completion=True),
3435
)
3536

36-
# 3. Verify the skill is successfully deleted (Getting it should raise NotFound)
37-
with pytest.raises(errors.ClientError) as exc_info:
38-
client.skills.get(name=created_skill.name)
37+
# 3. Verify the skill is successfully deleted (Getting it should raise NotFound)
38+
with pytest.raises(errors.ClientError) as exc_info:
39+
client.skills.get(name=created_skill.name)
3940

40-
assert exc_info.value.code == 404
41+
assert exc_info.value.code == 404

tests/unit/agentplatform/genai/replays/test_skills_revisions_get.py

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -19,45 +19,46 @@
1919

2020

2121
def test_get_skill_revision(client, tmp_path):
22-
# Target the autopush sandbox endpoint for the Skill Registry API
23-
client._api_client._http_options.base_url = (
22+
# Target the autopush sandbox endpoint for the Skill Registry API
23+
client._api_client._http_options.base_url = (
2424
"https://us-central1-autopush-aiplatform.sandbox.googleapis.com"
2525
)
2626

27-
# 1. Create a fresh unique skill
28-
with open(tmp_path / "SKILL.md", "w") as f:
29-
f.write("# Replay Revision Test Skill\nThis is a test skill.")
27+
# 1. Create a fresh unique skill
28+
with open(tmp_path / "SKILL.md", "w") as f:
29+
f.write("# Replay Revision Test Skill\nThis is a test skill.")
3030

31-
created_skill = client.skills.create(
32-
display_name="Replay Revision Test Skill",
33-
description="A temporary skill to test revisions E2E",
34-
config=types.CreateSkillConfig(
35-
local_path=str(tmp_path), wait_for_completion=True
36-
),
37-
)
31+
created_skill = client.skills.create(
32+
skill_id="my-skill-to-get-revision",
33+
display_name="Replay Revision Test Skill",
34+
description="A temporary skill to test revisions E2E",
35+
config=types.CreateSkillConfig(
36+
local_path=str(tmp_path), wait_for_completion=True
37+
),
38+
)
3839

39-
try:
40-
assert created_skill.name is not None
40+
try:
41+
assert created_skill.name is not None
4142

42-
# 2. List revisions to dynamically discover the revision ID
43-
revisions_response = client.skills.revisions.list(name=created_skill.name)
44-
revisions_list = revisions_response.skill_revisions
43+
# 2. List revisions to dynamically discover the revision ID
44+
revisions_response = client.skills.revisions.list(name=created_skill.name)
45+
revisions_list = revisions_response.skill_revisions
4546

46-
assert len(revisions_list) > 0
47-
first_revision = revisions_list[0]
48-
assert isinstance(first_revision, types.SkillRevision)
49-
assert first_revision.name is not None
47+
assert len(revisions_list) > 0
48+
first_revision = revisions_list[0]
49+
assert isinstance(first_revision, types.SkillRevision)
50+
assert first_revision.name is not None
5051

51-
# 3. Explicitly GET the revision by its resource name
52-
revision = client.skills.revisions.get(name=first_revision.name)
52+
# 3. Explicitly GET the revision by its resource name
53+
revision = client.skills.revisions.get(name=first_revision.name)
5354

54-
assert isinstance(revision, types.SkillRevision)
55-
assert revision.name == first_revision.name
56-
assert revision.state == types.SkillState.ACTIVE
55+
assert isinstance(revision, types.SkillRevision)
56+
assert revision.name == first_revision.name
57+
assert revision.state == types.SkillState.ACTIVE
5758

58-
finally:
59-
# 4. Clean up the temporary skill
60-
client.skills.delete(
59+
finally:
60+
# 4. Clean up the temporary skill
61+
client.skills.delete(
6162
name=created_skill.name,
6263
config=types.DeleteSkillConfig(wait_for_completion=True),
6364
)

0 commit comments

Comments
 (0)