From fb9c52e53cd7169d6ea717af60e61c302a8c7f98 Mon Sep 17 00:00:00 2001 From: dawnguo Date: Thu, 26 Mar 2026 14:06:20 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat(skills):=20=E4=B8=BAvestack=E7=8E=AF?= =?UTF-8?q?=E5=A2=83=E6=B7=BB=E5=8A=A0=20minio=20=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E4=B8=8B=E8=BD=BD=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 添加对vestack环境的支持,包括: 1. 通过GenTempTosObjectUrl/GenTempTosObjectDownloadUrl API获取临时URL 2. 使用requests库实现文件上传下载 3. 使用环境变量AGENTKIT_TOOL_SCHEME配置请求协议 --- veadk/skills/utils.py | 2 + .../skills_tools/download_skills_tool.py | 90 ++++++++++++- .../skills_tools/register_skills_tool.py | 125 +++++++++++++----- veadk/tools/skills_tools/skills_tool.py | 123 +++++++++++++++-- 4 files changed, 285 insertions(+), 55 deletions(-) diff --git a/veadk/skills/utils.py b/veadk/skills/utils.py index 814a1164..95377983 100644 --- a/veadk/skills/utils.py +++ b/veadk/skills/utils.py @@ -174,6 +174,7 @@ def load_skills_from_cloud(skill_space_ids: str) -> list[Skill]: "InnerTags": {"source": "sandbox"}, } logger.debug(f"ListSkillsBySpaceId request body: {request_body}") + scheme = os.getenv("AGENTKIT_TOOL_SCHEME", "https").lower() response = ve_request( request_body=request_body, @@ -185,6 +186,7 @@ def load_skills_from_cloud(skill_space_ids: str) -> list[Skill]: region=region, host=host, header={"X-Security-Token": session_token}, + scheme=scheme, ) if isinstance(response, str): diff --git a/veadk/tools/skills_tools/download_skills_tool.py b/veadk/tools/skills_tools/download_skills_tool.py index 456db81d..61fad43b 100644 --- a/veadk/tools/skills_tools/download_skills_tool.py +++ b/veadk/tools/skills_tools/download_skills_tool.py @@ -92,6 +92,7 @@ def download_skills_tool( all_downloaded_skills = [] + scheme = os.getenv("AGENTKIT_TOOL_SCHEME", "https").lower() # Iterate through each skill space for skill_space_id in skill_space_ids_list: try: @@ -101,7 +102,7 @@ def download_skills_tool( "InnerTags": {"source": "sandbox"}, } logger.info(f"ListSkillsBySpaceId request body: {request_body}") - + response = ve_request( request_body=request_body, action="ListSkillsBySpaceId", @@ -112,6 +113,7 @@ def download_skills_tool( region=region, host=host, header={"X-Security-Token": session_token}, + scheme=scheme, ) if isinstance(response, str): @@ -161,11 +163,87 @@ def download_skills_tool( # Download zip file zip_path = download_dir / f"{skill_name}.zip" - success = tos_client.download( - bucket_name=tos_bucket, - object_key=tos_path, - save_path=str(zip_path), - ) + + if cloud_provider == "vestack": + import requests + + try: + path_parts = tos_path.split("/") + if len(path_parts) >= 3: + skill_id = path_parts[1] + skill_version = path_parts[2] + else: + logger.error( + f"Invalid TosPath format for skill '{skill_name}': {tos_path}" + ) + success = False + continue + except Exception as e: + logger.error( + f"Failed to parse TosPath for skill '{skill_name}': {e}" + ) + success = False + continue + + # Call GenTempTosObjectDownloadUrl API + temp_url_request_body = { + "SkillId": skill_id, + "SkillVersion": skill_version, + } + logger.debug( + f"GenTempTosObjectDownloadUrl request body: {temp_url_request_body}" + ) + + temp_url_res = ve_request( + request_body=temp_url_request_body, + action="GenTempTosObjectDownloadUrl", + ak=access_key, + sk=secret_key, + service=service, + version="2025-10-30", + region=region, + host=host, + header={"X-Security-Token": session_token}, + scheme=scheme, + ) + + if isinstance(temp_url_res, str): + temp_url_res = json.loads(temp_url_res) + + if ( + "ResponseMetadata" in temp_url_res + and "Error" in temp_url_res["ResponseMetadata"] + ): + error_details = temp_url_res["ResponseMetadata"]["Error"] + logger.error( + f"Failed to get temporary download URL for '{skill_name}': {error_details}" + ) + success = False + else: + signed_url = temp_url_res.get("Result", {}).get("SignedUrl") + if not signed_url: + logger.error( + f"Failed to get SignedUrl from GenTempTosObjectDownloadUrl response: {temp_url_res}" + ) + success = False + else: + try: + response = requests.get(signed_url) + response.raise_for_status() + with open(zip_path, "wb") as f: + f.write(response.content) + success = True + except Exception as e: + logger.warning( + f"Failed to download skill '{skill_name}' from minio: {e}" + ) + success = False + else: + success = tos_client.download( + bucket_name=tos_bucket, + object_key=tos_path, + save_path=str(zip_path), + ) if not success: logger.warning(f"Failed to download skill '{skill_name}'") diff --git a/veadk/tools/skills_tools/register_skills_tool.py b/veadk/tools/skills_tools/register_skills_tool.py index 7b8b55ee..7e72bc5c 100644 --- a/veadk/tools/skills_tools/register_skills_tool.py +++ b/veadk/tools/skills_tools/register_skills_tool.py @@ -111,46 +111,100 @@ def register_skills_tool( secret_key = cred.secret_access_key session_token = cred.session_token - res = ve_request( - request_body={}, - action="GetCallerIdentity", - ak=access_key, - sk=secret_key, - service="sts", - version="2018-01-01", - region=region, - host="sts.volcengineapi.com" - if cloud_provider != "byteplus" - else "open.byteplusapi.com", - header={"X-Security-Token": session_token}, - ) - try: - account_id = res["Result"]["AccountId"] - except KeyError as e: - logger.error( - f"Error occurred while getting account id: {e}, response is {res}" + account_id = "" + if cloud_provider != "vestack": + res = ve_request( + request_body={}, + action="GetCallerIdentity", + ak=access_key, + sk=secret_key, + service="sts", + version="2018-01-01", + region=region, + host="sts.volcengineapi.com" + if cloud_provider != "byteplus" + else "open.byteplusapi.com", + header={"X-Security-Token": session_token}, ) - return f"Error: Failed to get account id when registering skill '{skill_name}'." + try: + account_id = res["Result"]["AccountId"] + except KeyError as e: + logger.error( + f"Error occurred while getting account id: {e}, response is {res}" + ) + return f"Error: Failed to get account id when registering skill '{skill_name}'." tos_bucket = f"agentkit-platform-{region}-{account_id}-skill" + scheme = os.getenv("AGENTKIT_TOOL_SCHEME", "https").lower() + if cloud_provider == "vestack": + import requests + + # Call GenTempTosObjectUrl API + temp_url_request_body = { + "SkillName": skill_name, + } + logger.debug(f"GenTempTosObjectUrl request body: {temp_url_request_body}") + + temp_url_res = ve_request( + request_body=temp_url_request_body, + action="GenTempTosObjectUrl", + ak=access_key, + sk=secret_key, + service=agentkit_tool_service, + version="2025-10-30", + region=region, + host=agentkit_skill_host, + header={"X-Security-Token": session_token}, + scheme=scheme, + ) - tos_client = VeTOS( - ak=access_key, - sk=secret_key, - session_token=session_token, - bucket_name=tos_bucket, - region=region, - ) + if isinstance(temp_url_res, str): + temp_url_res = json.loads(temp_url_res) + + if ( + "ResponseMetadata" in temp_url_res + and "Error" in temp_url_res["ResponseMetadata"] + ): + error_details = temp_url_res["ResponseMetadata"]["Error"] + logger.error( + f"Failed to get temporary upload URL for '{skill_name}': {error_details}" + ) + return f"Failed to get temporary upload URL for '{skill_name}': {error_details}" + + signed_url = temp_url_res.get("Result", {}).get("SignedUrl") + tos_url = temp_url_res.get("Result", {}).get("TosUrl") + + if not signed_url or not tos_url: + logger.error( + f"Failed to get SignedUrl or TosUrl from GenTempTosObjectUrl response: {temp_url_res}" + ) + return f"Failed to get temporary upload URL for '{skill_name}'." + + try: + with open(zip_file_path, "rb") as f: + response = requests.put(signed_url, data=f) + response.raise_for_status() + except Exception as e: + logger.error(f"Failed to upload skill '{skill_name}' to minio: {e}") + return f"Failed to upload skill '{skill_name}' to minio: {e}" + else: + tos_client = VeTOS( + ak=access_key, + sk=secret_key, + session_token=session_token, + bucket_name=tos_bucket, + region=region, + ) - object_key = ( - f"uploads/{datetime.now().strftime('%Y%m%d_%H%M%S')}/{skill_name}.zip" - ) - tos_client.upload_file( - file_path=zip_file_path, bucket_name=tos_bucket, object_key=object_key - ) - tos_url = tos_client.build_tos_url( - bucket_name=tos_bucket, object_key=object_key - ) + object_key = ( + f"uploads/{datetime.now().strftime('%Y%m%d_%H%M%S')}/{skill_name}.zip" + ) + tos_client.upload_file( + file_path=zip_file_path, bucket_name=tos_bucket, object_key=object_key + ) + tos_url = tos_client.build_tos_url( + bucket_name=tos_bucket, object_key=object_key + ) skill_space_ids = os.getenv("SKILL_SPACE_ID", "") skill_space_ids_list = [ @@ -173,6 +227,7 @@ def register_skills_tool( region=region, host=agentkit_skill_host, header={"X-Security-Token": session_token}, + scheme=scheme, ) if isinstance(response, str): diff --git a/veadk/tools/skills_tools/skills_tool.py b/veadk/tools/skills_tools/skills_tool.py index fa06d485..20da1eed 100644 --- a/veadk/tools/skills_tools/skills_tool.py +++ b/veadk/tools/skills_tools/skills_tool.py @@ -117,6 +117,12 @@ def _invoke_skill(self, skill_name: str, tool_context: ToolContext) -> str: # 1. Download skill from TOS if not found locally user_skill_dir = skill_dir / skill_name if not user_skill_dir.exists() or not user_skill_dir.is_dir(): + cloud_provider = (os.getenv("CLOUD_PROVIDER") or "").lower() + if cloud_provider == "vestack": + error_msg = f"Error: Skill '{skill_name}' not found locally or in skill space. Downloading from TOS_SKILLS_DIR is not supported in vestack environment." + logger.error(error_msg) + return error_msg + # Try to download from TOS logger.info( f"Skill '{skill_name}' not found locally or in skill space, attempting to download from TOS..." @@ -240,22 +246,111 @@ def _invoke_skill(self, skill_name: str, tool_context: ToolContext) -> str: tos_bucket, tos_path = skill.bucket_name, skill.path - # Initialize VeTOS client - tos_client = VeTOS( - ak=access_key, - sk=secret_key, - session_token=session_token, - bucket_name=tos_bucket, - region=region, - ) - save_path = skill_dir / f"{skill_name}.zip" - success = tos_client.download( - bucket_name=tos_bucket, - object_key=tos_path, - save_path=save_path, - ) + cloud_provider = (os.getenv("CLOUD_PROVIDER") or "").lower() + if cloud_provider == "vestack": + import requests + from veadk.utils.volcengine_sign import ve_request + + # Extract skill_id and skill_version from TosPath + # skills/s-yeh6iwdnggwobasystug/v1/web-search.zip + skill_id = skill.id + skill_version = "" + try: + path_parts = tos_path.split("/") + if len(path_parts) >= 3: + skill_id = path_parts[1] + skill_version = path_parts[2] + except Exception: + pass + + # Call GenTempTosObjectDownloadUrl API + temp_url_request_body = { + "SkillId": skill_id, + "SkillVersion": skill_version, + } + logger.debug( + f"GenTempTosObjectDownloadUrl request body: {temp_url_request_body}" + ) + + agentkit_tool_service = os.getenv( + "AGENTKIT_TOOL_SERVICE_CODE", "agentkit" + ) + region = os.getenv("AGENTKIT_TOOL_REGION", "cn-beijing") + default_sld = ( + "byteplusapi" + if cloud_provider == "byteplus" + else "volcengineapi" + ) + agentkit_skill_host = os.getenv( + "AGENTKIT_SKILL_HOST", + agentkit_tool_service + + "." + + region + + f".{default_sld}.com", + ) + scheme = os.getenv("AGENTKIT_TOOL_SCHEME", "https").lower() + + temp_url_res = ve_request( + request_body=temp_url_request_body, + action="GenTempTosObjectDownloadUrl", + ak=access_key, + sk=secret_key, + service=agentkit_tool_service, + version="2025-10-30", + region=region, + host=agentkit_skill_host, + header={"X-Security-Token": session_token}, + scheme=scheme, + ) + + if isinstance(temp_url_res, str): + temp_url_res = json.loads(temp_url_res) + + if ( + "ResponseMetadata" in temp_url_res + and "Error" in temp_url_res["ResponseMetadata"] + ): + error_details = temp_url_res["ResponseMetadata"]["Error"] + logger.error( + f"Failed to get temporary download URL for '{skill_name}': {error_details}" + ) + success = False + else: + signed_url = temp_url_res.get("Result", {}).get("SignedUrl") + if not signed_url: + logger.error( + f"Failed to get SignedUrl from GenTempTosObjectDownloadUrl response: {temp_url_res}" + ) + success = False + else: + try: + response = requests.get(signed_url) + response.raise_for_status() + with open(save_path, "wb") as f: + f.write(response.content) + success = True + except Exception as e: + logger.error( + f"Failed to download skill '{skill_name}' from minio: {e}" + ) + success = False + else: + # Initialize VeTOS client + tos_client = VeTOS( + ak=access_key, + sk=secret_key, + session_token=session_token, + bucket_name=tos_bucket, + region=region, + ) + + success = tos_client.download( + bucket_name=tos_bucket, + object_key=tos_path, + save_path=save_path, + ) if not success: return ( From 0d05246ce7abe07c2705219d7e9f5608bde84110 Mon Sep 17 00:00:00 2001 From: dawnguo Date: Thu, 26 Mar 2026 17:31:49 +0800 Subject: [PATCH 2/2] =?UTF-8?q?refactor(skills):=20=E6=8F=90=E5=8F=96vesta?= =?UTF-8?q?ck=E6=8A=80=E8=83=BD=E4=B8=8B=E8=BD=BD=E9=80=BB=E8=BE=91?= =?UTF-8?q?=E5=88=B0=E7=8B=AC=E7=AB=8B=E5=87=BD=E6=95=B0=E5=B9=B6=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E7=8E=AF=E5=A2=83=E5=8F=98=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将vestack环境下的技能下载逻辑提取到独立函数`_download_skill_via_vestack`中,提高代码复用性 同时将环境变量`AGENTKIT_TOOL_SCHEME`统一更新为`AGENTKIT_TOP_SCHEME` --- docs/docs/tools/builtin.md | 1 + veadk/skills/utils.py | 2 +- veadk/tools/builtin_tools/execute_skills.py | 2 +- .../skills_tools/download_skills_tool.py | 164 ++++++++------- .../skills_tools/register_skills_tool.py | 2 +- veadk/tools/skills_tools/skills_tool.py | 194 ++++++++++-------- 6 files changed, 208 insertions(+), 157 deletions(-) diff --git a/docs/docs/tools/builtin.md b/docs/docs/tools/builtin.md index aa857444..b8350645 100644 --- a/docs/docs/tools/builtin.md +++ b/docs/docs/tools/builtin.md @@ -187,6 +187,7 @@ VeADK 集成了以下火山引擎工具: - `AGENTKIT_TOOL_HOST`:用于调用火山引擎AgentKit Tools的EndPoint - `AGENTKIT_TOOL_SERVICE_CODE`:用于调用AgentKit Tools的ServiceCode - `AGENTKIT_TOOL_SCHEME`:用于切换调用 AgentKit Tools 的协议,允许 `http`/`https`,默认 `https` + - `AGENTKIT_TOP_SCHEME`:用于切换调用 AgentKit TOP 的协议,允许 `http`/`https`,默认 `https` 环境变量列表: diff --git a/veadk/skills/utils.py b/veadk/skills/utils.py index 95377983..9a69d200 100644 --- a/veadk/skills/utils.py +++ b/veadk/skills/utils.py @@ -174,7 +174,7 @@ def load_skills_from_cloud(skill_space_ids: str) -> list[Skill]: "InnerTags": {"source": "sandbox"}, } logger.debug(f"ListSkillsBySpaceId request body: {request_body}") - scheme = os.getenv("AGENTKIT_TOOL_SCHEME", "https").lower() + scheme = os.getenv("AGENTKIT_TOP_SCHEME", "https").lower() response = ve_request( request_body=request_body, diff --git a/veadk/tools/builtin_tools/execute_skills.py b/veadk/tools/builtin_tools/execute_skills.py index f37fac04..5b358f8d 100644 --- a/veadk/tools/builtin_tools/execute_skills.py +++ b/veadk/tools/builtin_tools/execute_skills.py @@ -108,7 +108,7 @@ def execute_skills( tool_user_session_id = agent_name + "_" + user_id + "_" + session_id logger.debug(f"tool_user_session_id: {tool_user_session_id}") - scheme = getenv("AGENTKIT_TOOL_SCHEME", "https", allow_false_values=True).lower() + scheme = getenv("AGENTKIT_TOP_SCHEME", "https", allow_false_values=True).lower() if scheme not in {"http", "https"}: scheme = "https" diff --git a/veadk/tools/skills_tools/download_skills_tool.py b/veadk/tools/skills_tools/download_skills_tool.py index 61fad43b..b0d5088c 100644 --- a/veadk/tools/skills_tools/download_skills_tool.py +++ b/veadk/tools/skills_tools/download_skills_tool.py @@ -28,6 +28,93 @@ logger = get_logger(__name__) +def _download_skill_via_vestack( + tos_path: str, + skill_name: str, + access_key: str, + secret_key: str, + session_token: str, + service: str, + region: str, + host: str, + scheme: str, + zip_path: Path, +) -> bool: + import json + import requests + from veadk.utils.volcengine_sign import ve_request + + try: + path_parts = tos_path.split("/") + if len(path_parts) >= 3: + skill_id = path_parts[1] + skill_version = path_parts[2] + else: + logger.error( + f"Invalid TosPath format for skill '{skill_name}': {tos_path}" + ) + return False + except Exception as e: + logger.error( + f"Failed to parse TosPath for skill '{skill_name}': {e}" + ) + return False + + # Call GenTempTosObjectDownloadUrl API + temp_url_request_body = { + "SkillId": skill_id, + "SkillVersion": skill_version, + } + logger.debug( + f"GenTempTosObjectDownloadUrl request body: {temp_url_request_body}" + ) + + temp_url_res = ve_request( + request_body=temp_url_request_body, + action="GenTempTosObjectDownloadUrl", + ak=access_key, + sk=secret_key, + service=service, + version="2025-10-30", + region=region, + host=host, + header={"X-Security-Token": session_token}, + scheme=scheme, + ) + + if isinstance(temp_url_res, str): + temp_url_res = json.loads(temp_url_res) + + if ( + "ResponseMetadata" in temp_url_res + and "Error" in temp_url_res["ResponseMetadata"] + ): + error_details = temp_url_res["ResponseMetadata"]["Error"] + logger.error( + f"Failed to get temporary download URL for '{skill_name}': {error_details}" + ) + return False + else: + signed_url = temp_url_res.get("Result", {}).get("SignedUrl") + if not signed_url: + logger.error( + f"Failed to get SignedUrl from GenTempTosObjectDownloadUrl response: {temp_url_res}" + ) + return False + else: + try: + response = requests.get(signed_url) + response.raise_for_status() + with open(zip_path, "wb") as f: + f.write(response.content) + return True + except Exception as e: + logger.warning( + f"Failed to download skill '{skill_name}' from minio: {e}" + ) + return False + + def download_skills_tool( download_path: str, skill_names: Optional[list[str]] = None ) -> str: @@ -92,7 +179,7 @@ def download_skills_tool( all_downloaded_skills = [] - scheme = os.getenv("AGENTKIT_TOOL_SCHEME", "https").lower() + scheme = os.getenv("AGENTKIT_TOP_SCHEME", "https").lower() # Iterate through each skill space for skill_space_id in skill_space_ids_list: try: @@ -165,79 +252,18 @@ def download_skills_tool( zip_path = download_dir / f"{skill_name}.zip" if cloud_provider == "vestack": - import requests - - try: - path_parts = tos_path.split("/") - if len(path_parts) >= 3: - skill_id = path_parts[1] - skill_version = path_parts[2] - else: - logger.error( - f"Invalid TosPath format for skill '{skill_name}': {tos_path}" - ) - success = False - continue - except Exception as e: - logger.error( - f"Failed to parse TosPath for skill '{skill_name}': {e}" - ) - success = False - continue - - # Call GenTempTosObjectDownloadUrl API - temp_url_request_body = { - "SkillId": skill_id, - "SkillVersion": skill_version, - } - logger.debug( - f"GenTempTosObjectDownloadUrl request body: {temp_url_request_body}" - ) - - temp_url_res = ve_request( - request_body=temp_url_request_body, - action="GenTempTosObjectDownloadUrl", - ak=access_key, - sk=secret_key, + success = _download_skill_via_vestack( + tos_path=tos_path, + skill_name=skill_name, + access_key=access_key, + secret_key=secret_key, + session_token=session_token, service=service, - version="2025-10-30", region=region, host=host, - header={"X-Security-Token": session_token}, scheme=scheme, + zip_path=zip_path, ) - - if isinstance(temp_url_res, str): - temp_url_res = json.loads(temp_url_res) - - if ( - "ResponseMetadata" in temp_url_res - and "Error" in temp_url_res["ResponseMetadata"] - ): - error_details = temp_url_res["ResponseMetadata"]["Error"] - logger.error( - f"Failed to get temporary download URL for '{skill_name}': {error_details}" - ) - success = False - else: - signed_url = temp_url_res.get("Result", {}).get("SignedUrl") - if not signed_url: - logger.error( - f"Failed to get SignedUrl from GenTempTosObjectDownloadUrl response: {temp_url_res}" - ) - success = False - else: - try: - response = requests.get(signed_url) - response.raise_for_status() - with open(zip_path, "wb") as f: - f.write(response.content) - success = True - except Exception as e: - logger.warning( - f"Failed to download skill '{skill_name}' from minio: {e}" - ) - success = False else: success = tos_client.download( bucket_name=tos_bucket, diff --git a/veadk/tools/skills_tools/register_skills_tool.py b/veadk/tools/skills_tools/register_skills_tool.py index 7e72bc5c..b2686fdf 100644 --- a/veadk/tools/skills_tools/register_skills_tool.py +++ b/veadk/tools/skills_tools/register_skills_tool.py @@ -135,7 +135,7 @@ def register_skills_tool( return f"Error: Failed to get account id when registering skill '{skill_name}'." tos_bucket = f"agentkit-platform-{region}-{account_id}-skill" - scheme = os.getenv("AGENTKIT_TOOL_SCHEME", "https").lower() + scheme = os.getenv("AGENTKIT_TOP_SCHEME", "https").lower() if cloud_provider == "vestack": import requests diff --git a/veadk/tools/skills_tools/skills_tool.py b/veadk/tools/skills_tools/skills_tool.py index 20da1eed..ac5fc49c 100644 --- a/veadk/tools/skills_tools/skills_tool.py +++ b/veadk/tools/skills_tools/skills_tool.py @@ -250,92 +250,16 @@ def _invoke_skill(self, skill_name: str, tool_context: ToolContext) -> str: cloud_provider = (os.getenv("CLOUD_PROVIDER") or "").lower() if cloud_provider == "vestack": - import requests - from veadk.utils.volcengine_sign import ve_request - - # Extract skill_id and skill_version from TosPath - # skills/s-yeh6iwdnggwobasystug/v1/web-search.zip - skill_id = skill.id - skill_version = "" - try: - path_parts = tos_path.split("/") - if len(path_parts) >= 3: - skill_id = path_parts[1] - skill_version = path_parts[2] - except Exception: - pass - - # Call GenTempTosObjectDownloadUrl API - temp_url_request_body = { - "SkillId": skill_id, - "SkillVersion": skill_version, - } - logger.debug( - f"GenTempTosObjectDownloadUrl request body: {temp_url_request_body}" - ) - - agentkit_tool_service = os.getenv( - "AGENTKIT_TOOL_SERVICE_CODE", "agentkit" - ) - region = os.getenv("AGENTKIT_TOOL_REGION", "cn-beijing") - default_sld = ( - "byteplusapi" - if cloud_provider == "byteplus" - else "volcengineapi" - ) - agentkit_skill_host = os.getenv( - "AGENTKIT_SKILL_HOST", - agentkit_tool_service - + "." - + region - + f".{default_sld}.com", - ) - scheme = os.getenv("AGENTKIT_TOOL_SCHEME", "https").lower() - - temp_url_res = ve_request( - request_body=temp_url_request_body, - action="GenTempTosObjectDownloadUrl", - ak=access_key, - sk=secret_key, - service=agentkit_tool_service, - version="2025-10-30", - region=region, - host=agentkit_skill_host, - header={"X-Security-Token": session_token}, - scheme=scheme, + success = self._download_skill_via_vestack( + skill=skill, + tos_path=tos_path, + cloud_provider=cloud_provider, + access_key=access_key, + secret_key=secret_key, + session_token=session_token, + skill_name=skill_name, + save_path=save_path, ) - - if isinstance(temp_url_res, str): - temp_url_res = json.loads(temp_url_res) - - if ( - "ResponseMetadata" in temp_url_res - and "Error" in temp_url_res["ResponseMetadata"] - ): - error_details = temp_url_res["ResponseMetadata"]["Error"] - logger.error( - f"Failed to get temporary download URL for '{skill_name}': {error_details}" - ) - success = False - else: - signed_url = temp_url_res.get("Result", {}).get("SignedUrl") - if not signed_url: - logger.error( - f"Failed to get SignedUrl from GenTempTosObjectDownloadUrl response: {temp_url_res}" - ) - success = False - else: - try: - response = requests.get(signed_url) - response.raise_for_status() - with open(save_path, "wb") as f: - f.write(response.content) - success = True - except Exception as e: - logger.error( - f"Failed to download skill '{skill_name}' from minio: {e}" - ) - success = False else: # Initialize VeTOS client tos_client = VeTOS( @@ -439,6 +363,106 @@ def _invoke_skill(self, skill_name: str, tool_context: ToolContext) -> str: logger.error(f"Failed to invoke skill {skill_name}: {e}") return f"Error invoking skill '{skill_name}': {e}" + def _download_skill_via_vestack( + self, + skill: Any, + tos_path: str, + cloud_provider: str, + access_key: str, + secret_key: str, + session_token: str, + skill_name: str, + save_path: Any, + ) -> bool: + """Download a skill using the vestack environment GenTempTosObjectDownloadUrl API.""" + import json + import requests + from veadk.utils.volcengine_sign import ve_request + + # Extract skill_id and skill_version from TosPath + # skills/s-yeh6iwdnggwobasystug/v1/web-search.zip + skill_id = skill.id + skill_version = "" + try: + path_parts = tos_path.split("/") + if len(path_parts) >= 3: + skill_id = path_parts[1] + skill_version = path_parts[2] + except Exception: + pass + + # Call GenTempTosObjectDownloadUrl API + temp_url_request_body = { + "SkillId": skill_id, + "SkillVersion": skill_version, + } + logger.debug( + f"GenTempTosObjectDownloadUrl request body: {temp_url_request_body}" + ) + + agentkit_tool_service = os.getenv( + "AGENTKIT_TOOL_SERVICE_CODE", "agentkit" + ) + region = os.getenv("AGENTKIT_TOOL_REGION", "cn-beijing") + default_sld = ( + "byteplusapi" + if cloud_provider == "byteplus" + else "volcengineapi" + ) + agentkit_skill_host = os.getenv( + "AGENTKIT_SKILL_HOST", + agentkit_tool_service + + "." + + region + + f".{default_sld}.com", + ) + scheme = os.getenv("AGENTKIT_TOP_SCHEME", "https").lower() + + temp_url_res = ve_request( + request_body=temp_url_request_body, + action="GenTempTosObjectDownloadUrl", + ak=access_key, + sk=secret_key, + service=agentkit_tool_service, + version="2025-10-30", + region=region, + host=agentkit_skill_host, + header={"X-Security-Token": session_token}, + scheme=scheme, + ) + + if isinstance(temp_url_res, str): + temp_url_res = json.loads(temp_url_res) + + if ( + "ResponseMetadata" in temp_url_res + and "Error" in temp_url_res["ResponseMetadata"] + ): + error_details = temp_url_res["ResponseMetadata"]["Error"] + logger.error( + f"Failed to get temporary download URL for '{skill_name}': {error_details}" + ) + return False + else: + signed_url = temp_url_res.get("Result", {}).get("SignedUrl") + if not signed_url: + logger.error( + f"Failed to get SignedUrl from GenTempTosObjectDownloadUrl response: {temp_url_res}" + ) + return False + else: + try: + response = requests.get(signed_url) + response.raise_for_status() + with open(save_path, "wb") as f: + f.write(response.content) + return True + except Exception as e: + logger.error( + f"Failed to download skill '{skill_name}' from minio: {e}" + ) + return False + def _format_skill_content(self, skill_name: str, content: str, skill_dir) -> str: """Format skill content for display to the agent.""" header = (