Skip to content

Commit 80c2524

Browse files
yuyushui66claude
authored andcommitted
refactor: normalize LATEST qualifier before send and reorder download_skill args
- Normalize qualifier to the canonical "LATEST" in _get_skill_download_url before building the URL, so the value sent to the backend agrees with the local .skill_version marker (skill_loader._canonical_qualifier) regardless of input casing. - Reorder download_skill / download_skill_async params to (target_dir, config, qualifier) and sync the docstring arg order. - Update tests to assert all LATEST casings produce the canonical URL. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: daoxun.yds <daoxun.yds@alibaba-inc.com>
1 parent 1548b1d commit 80c2524

3 files changed

Lines changed: 42 additions & 14 deletions

File tree

agentrun/tool/__tool_async_template.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -652,14 +652,24 @@ def _get_skill_download_url(
652652
if qualifier:
653653
from urllib.parse import quote
654654

655+
# LATEST 大小写不敏感,发送前统一归一为规范形式 "LATEST",使
656+
# "发送给后端的值 / 本地版本标记 / 下载决策" 三者一致(本地标记侧
657+
# 见 skill_loader._canonical_qualifier)。定版 qualifier 保持原样。
658+
# LATEST is case-insensitive; normalize to the canonical "LATEST"
659+
# before sending so the value sent to the backend, the local version
660+
# marker, and the download decision all agree (the marker side lives
661+
# in skill_loader._canonical_qualifier). Pinned versions are kept
662+
# as-is.
663+
if qualifier.upper() == "LATEST":
664+
qualifier = "LATEST"
655665
url = f"{url}?qualifier={quote(qualifier, safe='')}"
656666
return url
657667

658668
async def download_skill_async(
659669
self,
660670
target_dir: str = ".skills",
661-
qualifier: Optional[str] = None,
662671
config: Optional[Config] = None,
672+
qualifier: Optional[str] = None,
663673
) -> str:
664674
"""异步下载 Skill 包并解压到本地目录 / Download skill package and extract to local directory asynchronously
665675
@@ -670,9 +680,9 @@ async def download_skill_async(
670680
671681
Args:
672682
target_dir: 目标根目录,默认为 ".skills" / Target root directory, defaults to ".skills"
683+
config: 配置对象,可选 / Configuration object, optional
673684
qualifier: 版本标识,为空时后端返回 LATEST 代码 /
674685
Version qualifier; when None, the backend returns the LATEST code
675-
config: 配置对象,可选 / Configuration object, optional
676686
677687
Returns:
678688
str: 解压后的 skill 目录路径 / Extracted skill directory path

agentrun/tool/tool.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -822,14 +822,24 @@ def _get_skill_download_url(
822822
if qualifier:
823823
from urllib.parse import quote
824824

825+
# LATEST 大小写不敏感,发送前统一归一为规范形式 "LATEST",使
826+
# "发送给后端的值 / 本地版本标记 / 下载决策" 三者一致(本地标记侧
827+
# 见 skill_loader._canonical_qualifier)。定版 qualifier 保持原样。
828+
# LATEST is case-insensitive; normalize to the canonical "LATEST"
829+
# before sending so the value sent to the backend, the local version
830+
# marker, and the download decision all agree (the marker side lives
831+
# in skill_loader._canonical_qualifier). Pinned versions are kept
832+
# as-is.
833+
if qualifier.upper() == "LATEST":
834+
qualifier = "LATEST"
825835
url = f"{url}?qualifier={quote(qualifier, safe='')}"
826836
return url
827837

828838
async def download_skill_async(
829839
self,
830840
target_dir: str = ".skills",
831-
qualifier: Optional[str] = None,
832841
config: Optional[Config] = None,
842+
qualifier: Optional[str] = None,
833843
) -> str:
834844
"""异步下载 Skill 包并解压到本地目录 / Download skill package and extract to local directory asynchronously
835845
@@ -840,9 +850,9 @@ async def download_skill_async(
840850
841851
Args:
842852
target_dir: 目标根目录,默认为 ".skills" / Target root directory, defaults to ".skills"
853+
config: 配置对象,可选 / Configuration object, optional
843854
qualifier: 版本标识,为空时后端返回 LATEST 代码 /
844855
Version qualifier; when None, the backend returns the LATEST code
845-
config: 配置对象,可选 / Configuration object, optional
846856
847857
Returns:
848858
str: 解压后的 skill 目录路径 / Extracted skill directory path
@@ -895,8 +905,8 @@ async def download_skill_async(
895905
def download_skill(
896906
self,
897907
target_dir: str = ".skills",
898-
qualifier: Optional[str] = None,
899908
config: Optional[Config] = None,
909+
qualifier: Optional[str] = None,
900910
) -> str:
901911
"""同步下载 Skill 包并解压到本地目录 / Download skill package and extract to local directory synchronously
902912
@@ -907,9 +917,9 @@ def download_skill(
907917
908918
Args:
909919
target_dir: 目标根目录,默认为 ".skills" / Target root directory, defaults to ".skills"
920+
config: 配置对象,可选 / Configuration object, optional
910921
qualifier: 版本标识,为空时后端返回 LATEST 代码 /
911922
Version qualifier; when None, the backend returns the LATEST code
912-
config: 配置对象,可选 / Configuration object, optional
913923
914924
Returns:
915925
str: 解压后的 skill 目录路径 / Extracted skill directory path

tests/unittests/tool/test_tool.py

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -491,20 +491,28 @@ def test_get_skill_download_url_with_qualifier(self):
491491
data_endpoint="https://example.com",
492492
)
493493
url = tool._get_skill_download_url(qualifier="v1.0.0")
494-
assert url == "https://example.com/tools/my-skill/download?qualifier=v1.0.0"
494+
assert (
495+
url
496+
== "https://example.com/tools/my-skill/download?qualifier=v1.0.0"
497+
)
495498

496499
def test_get_skill_download_url_latest_case_insensitive(self):
497-
"""测试 LATEST 大小写不敏感均可通过校验并出现在 URL 中"""
500+
"""测试 LATEST 大小写不敏感均可通过校验,且发送前归一为规范 "LATEST"
501+
502+
无论传入何种大小写,构造出的 URL 都用规范形式 "LATEST",与本地版本
503+
标记(skill_loader._canonical_qualifier)保持一致,避免向后端发送
504+
未归一的 "latest"。/ Regardless of the input casing, the constructed
505+
URL uses the canonical "LATEST" so it agrees with the local version
506+
marker and never sends an un-normalized "latest" to the backend.
507+
"""
498508
tool = Tool(
499509
tool_name="my-skill",
500510
data_endpoint="https://example.com",
501511
)
502-
assert tool._get_skill_download_url(qualifier="LATEST") == (
503-
"https://example.com/tools/my-skill/download?qualifier=LATEST"
504-
)
505-
assert tool._get_skill_download_url(qualifier="latest") == (
506-
"https://example.com/tools/my-skill/download?qualifier=latest"
507-
)
512+
for variant in ("LATEST", "latest", "LaTeSt"):
513+
assert tool._get_skill_download_url(qualifier=variant) == (
514+
"https://example.com/tools/my-skill/download?qualifier=LATEST"
515+
)
508516

509517
def test_get_skill_download_url_invalid_qualifier_raises(self):
510518
"""测试非法 qualifier(含已废弃的 default)在构造 URL 时即抛错"""

0 commit comments

Comments
 (0)