Skip to content

Commit 905aef5

Browse files
authored
Merge pull request #14 from volcengine/fix/sync-bugfix-and-service-check-cr-type
Sync: sycn bugfix and new features include service check, CR type, more global config, etc.
2 parents 8e1f22f + c5aca66 commit 905aef5

37 files changed

+1301
-327
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,4 +180,6 @@ local_docs/
180180
local_test/
181181

182182
# deprecated files
183-
*deprecated*
183+
*deprecated*
184+
185+
.trae/

agentkit/client/base_agentkit_client.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,11 @@
1717
Provides common initialization and API invocation logic.
1818
"""
1919

20-
from typing import Any, Dict, Union
20+
from typing import Any, Dict, Union, Optional
2121

2222
from agentkit.client.base_service_client import BaseServiceClient, ApiConfig
2323
from agentkit.utils.ve_sign import get_volc_agentkit_host_info
24+
from agentkit.toolkit.config.global_config import get_global_config
2425

2526

2627
class BaseAgentkitClient(BaseServiceClient):
@@ -47,6 +48,7 @@ def __init__(
4748
region: str = "",
4849
session_token: str = "",
4950
service_name: str = "",
51+
header: Optional[Dict[str, Any]] = {"Accept": "application/json"},
5052
) -> None:
5153
"""
5254
Initialize the AgentKit client.
@@ -65,6 +67,7 @@ def __init__(
6567
session_token=session_token,
6668
service_name=service_name,
6769
credential_env_prefix='AGENTKIT',
70+
header=header,
6871
)
6972

7073
def _get_service_config(self) -> Dict[str, str]:
@@ -75,10 +78,13 @@ def _get_service_config(self) -> Dict[str, str]:
7578
Dictionary with host, api_version, and service
7679
"""
7780
host, api_version, service = get_volc_agentkit_host_info()
81+
gc = get_global_config()
82+
scheme = gc.agentkit_schema or 'https'
7883
return {
79-
'host': host,
84+
'host': gc.agentkit_host or host,
8085
'api_version': api_version,
8186
'service': service,
87+
'scheme': scheme,
8288
}
8389

8490
def _get(self, api_action: str, params: Dict[str, Any] = None) -> str:

agentkit/client/base_iam_client.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from typing import Dict, Union
2121

2222
from agentkit.client.base_service_client import BaseServiceClient, ApiConfig
23+
from agentkit.toolkit.config.global_config import get_global_config
2324

2425

2526
class BaseIAMClient(BaseServiceClient):
@@ -42,7 +43,7 @@ class BaseIAMClient(BaseServiceClient):
4243
# IAM service specific configuration
4344
IAM_API_VERSION = "2018-01-01"
4445
IAM_SERVICE_CODE = "iam"
45-
IAM_HOST ="open.volcengineapi.com"
46+
IAM_HOST = "open.volcengineapi.com"
4647

4748
def __init__(
4849
self,
@@ -78,8 +79,12 @@ def _get_service_config(self) -> Dict[str, str]:
7879
Returns:
7980
Dictionary with host, api_version, and service
8081
"""
82+
gc = get_global_config()
83+
scheme = gc.iam_schema or 'https'
84+
host = gc.iam_host or self.IAM_HOST
8185
return {
82-
'host': self.IAM_HOST,
86+
'host': host,
8387
'api_version': self.IAM_API_VERSION,
8488
'service': self.IAM_SERVICE_CODE,
89+
'scheme': scheme,
8590
}

agentkit/client/base_service_client.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ def __init__(
7272
session_token: str = "",
7373
service_name: str = "",
7474
credential_env_prefix: str = "",
75+
header: Optional[Dict[str, Any]] = {"Accept": "application/json"},
7576
) -> None:
7677
"""
7778
Initialize the service client.
@@ -106,11 +107,12 @@ def __init__(
106107
self.host = config['host']
107108
self.api_version = config['api_version']
108109
self.service = config['service']
110+
self.scheme = config.get('scheme', 'https')
109111

110112
# Create ServiceInfo
111113
self.service_info = ServiceInfo(
112114
host=self.host,
113-
header={'Accept': 'application/json'},
115+
header=header,
114116
credentials=Credentials(
115117
ak=self.access_key,
116118
sk=self.secret_key,
@@ -120,7 +122,7 @@ def __init__(
120122
),
121123
connection_timeout=30,
122124
socket_timeout=30,
123-
scheme="https",
125+
scheme=self.scheme,
124126
)
125127

126128
# Generate ApiInfo for all actions

agentkit/sdk/account/client.py

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# Auto-generated from API JSON definition
16+
# Do not edit manually
17+
18+
from __future__ import annotations
19+
20+
from typing import Dict, List, Optional
21+
from agentkit.client import BaseAgentkitClient
22+
from agentkit.sdk.account.types import (
23+
ListAccountLinkedServicesRequest,
24+
ListAccountLinkedServicesResponse,
25+
)
26+
27+
28+
class AgentkitAccountClient(BaseAgentkitClient):
29+
"""AgentKit Account Management Service"""
30+
API_ACTIONS: Dict[str, str] = {
31+
"ListAccountLinkedServices": "ListAccountLinkedServices",
32+
}
33+
34+
def __init__(
35+
self,
36+
access_key: str = "",
37+
secret_key: str = "",
38+
region: str = "",
39+
session_token: str = "",
40+
) -> None:
41+
super().__init__(
42+
access_key=access_key,
43+
secret_key=secret_key,
44+
region=region,
45+
session_token=session_token,
46+
service_name="account",
47+
)
48+
49+
50+
def list_account_linked_services(self, request: ListAccountLinkedServicesRequest) -> ListAccountLinkedServicesResponse:
51+
return self._invoke_api(
52+
api_action="ListAccountLinkedServices",
53+
request=request,
54+
response_type=ListAccountLinkedServicesResponse,
55+
)
56+
57+
def get_service_status(self, service_name: str) -> Optional[str]:
58+
"""
59+
Query the LinkServices status for a specific service.
60+
61+
Args:
62+
service_name: The name of the service to query (e.g., 'ark', 'vefaas')
63+
64+
Returns:
65+
The status string ('Enabled' or 'Disabled'), or None if service not found.
66+
"""
67+
print(1)
68+
response = self.list_account_linked_services(ListAccountLinkedServicesRequest())
69+
print(2)
70+
if not response.service_statuses:
71+
return None
72+
for svc in response.service_statuses:
73+
if svc.service_name == service_name:
74+
return svc.status
75+
return None
76+
77+
def get_services_status(self, service_names: List[str]) -> Dict[str, Optional[str]]:
78+
"""
79+
Query the LinkServices status for multiple services.
80+
81+
Args:
82+
service_names: List of service names to query (e.g., ['ark', 'vefaas', 'cr'])
83+
84+
Returns:
85+
A dict mapping service_name -> status ('Enabled'/'Disabled'/None if not found).
86+
"""
87+
response = self.list_account_linked_services(ListAccountLinkedServicesRequest())
88+
status_map: Dict[str, Optional[str]] = {name: None for name in service_names}
89+
if response.service_statuses:
90+
for svc in response.service_statuses:
91+
if svc.service_name in status_map:
92+
status_map[svc.service_name] = svc.status
93+
return status_map
94+
95+
def has_disabled_services(self) -> List[str]:
96+
"""
97+
Check if any returned service has a disabled status.
98+
99+
Returns:
100+
A list of service names that are disabled (status != 'Enabled').
101+
Returns empty list if all services are enabled.
102+
"""
103+
response = self.list_account_linked_services(ListAccountLinkedServicesRequest())
104+
disabled = []
105+
if response.service_statuses:
106+
for svc in response.service_statuses:
107+
if svc.status != "Enabled":
108+
disabled.append(svc.service_name)
109+
return disabled
110+

agentkit/sdk/account/types.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# Auto-generated from API JSON definition
16+
# Do not edit manually
17+
18+
from __future__ import annotations
19+
20+
from typing import Optional
21+
from pydantic import BaseModel, Field
22+
23+
class AccountBaseModel(BaseModel):
24+
"""AgentKit auto-generated base model"""
25+
model_config = {
26+
"populate_by_name": True,
27+
"arbitrary_types_allowed": True
28+
}
29+
30+
31+
# Data Types
32+
class ServiceStatusesForListAccountLinkedServices(AccountBaseModel):
33+
service_name: Optional[str] = Field(default=None, alias="ServiceName")
34+
status: Optional[str] = Field(default=None, alias="Status")
35+
36+
37+
# ListAccountLinkedServices - Request
38+
class ListAccountLinkedServicesRequest(AccountBaseModel):
39+
pass
40+
41+
42+
# ListAccountLinkedServices - Response
43+
class ListAccountLinkedServicesResponse(AccountBaseModel):
44+
service_statuses: Optional[list[ServiceStatusesForListAccountLinkedServices]] = Field(default=None, alias="ServiceStatuses")
45+

agentkit/toolkit/builders/ve_pipeline.py

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ class VeCPCRBuilderConfig(AutoSerializableMixin):
5454
cr_instance_name: str = field(default=AUTO_CREATE_VE, metadata={"description": "CR instance name", "render_template": True})
5555
cr_namespace_name: str = field(default=AUTO_CREATE_VE, metadata={"description": "CR namespace", "render_template": True})
5656
cr_repo_name: str = field(default=AUTO_CREATE_VE, metadata={"description": "CR repository name"})
57+
cr_auto_create_instance_type: str = field(default="Micro", metadata={"description": "CR instance type when auto-creating (Micro or Enterprise)"})
5758
cr_region: str = field(default="cn-beijing", metadata={"description": "CR region"})
5859

5960
cp_workspace_name: str = field(default=DEFAULT_WORKSPACE_NAME, metadata={"description": "Code Pipeline workspace name"})
@@ -224,7 +225,7 @@ def build(self, config: VeCPCRBuilderConfig) -> BuildResult:
224225
if 'pipeline_id' in resources:
225226
builder_config.cp_pipeline_id = resources['pipeline_id']
226227

227-
error_msg = f"Build failed: {str(e)}"
228+
error_msg = str(e)
228229

229230
return BuildResult(
230231
success=False,
@@ -679,6 +680,10 @@ def _upload_to_tos(self, archive_path: str, config: VeCPCRBuilderConfig) -> str:
679680
return tos_url
680681

681682
except Exception as e:
683+
if "AccountDisable" in str(e):
684+
raise Exception(f"Tos Service is not enabled, please enable it in the console. Enable services at: https://console.volcengine.com/agentkit/region:agentkit+cn-beijing/auth")
685+
if "TooManyBuckets" in str(e):
686+
raise Exception(f"You have reached the maximum number of buckets allowed. Please delete some buckets and try again.")
682687
raise Exception(f"Failed to upload to TOS: {str(e)}")
683688

684689
def _prepare_cr_resources(self, config: VeCPCRBuilderConfig) -> CRServiceConfig:
@@ -698,6 +703,7 @@ def _prepare_cr_resources(self, config: VeCPCRBuilderConfig) -> CRServiceConfig:
698703
instance_name=config.cr_instance_name,
699704
namespace_name=config.cr_namespace_name,
700705
repo_name=config.cr_repo_name,
706+
auto_create_instance_type=config.cr_auto_create_instance_type,
701707
region=config.cr_region
702708
)
703709

@@ -726,18 +732,24 @@ def config_updater(service: str, cr_config_dict: Dict[str, Any]) -> None:
726732
cr_result = cr_service.ensure_cr_resources(cr_config, common_config)
727733

728734
if not cr_result.success:
729-
error_msg = f"CR resource preparation failed: {cr_result.error}"
730-
self.reporter.error(error_msg)
731-
raise Exception(error_msg)
735+
raise Exception(cr_result.error)
732736

733-
# Ensure public endpoint access for image pulls
734-
self.reporter.info("Ensuring CR public endpoint access...")
735-
public_result = cr_service.ensure_public_endpoint(cr_config)
736-
737-
if not public_result.success:
738-
error_msg = f"Public endpoint configuration failed: {public_result.error}"
739-
self.reporter.error(error_msg)
740-
raise Exception(error_msg)
737+
# Ensure public endpoint access for image pulls (controlled by global config)
738+
try:
739+
from agentkit.toolkit.config.global_config import get_global_config
740+
gc = get_global_config()
741+
do_check = getattr(getattr(gc, 'defaults', None), 'cr_public_endpoint_check', None)
742+
except Exception:
743+
do_check = None
744+
if do_check is False:
745+
self.reporter.info("Skipping CR public endpoint check per global config")
746+
else:
747+
self.reporter.info("Ensuring CR public endpoint access...")
748+
public_result = cr_service.ensure_public_endpoint(cr_config)
749+
750+
if not public_result.success:
751+
error_msg = f"Public endpoint configuration failed: {public_result.error}"
752+
raise Exception(error_msg)
741753

742754
self.reporter.success("CR resource preparation completed")
743755
self.reporter.info(f" Instance: {cr_result.instance_name}")
@@ -937,10 +949,10 @@ def _prepare_pipeline_resources(self, config: VeCPCRBuilderConfig, tos_url: str,
937949
{"Key": "DOCKERFILE_PATH", "Value": "/workspace/agentkit-app/Dockerfile", "Dynamic": True, "Env": True},
938950
{"Key": "DOWNLOAD_PATH", "Value": "/workspace", "Dynamic": True, "Env": True},
939951
{"Key": "PROJECT_ROOT_DIR", "Value": "/workspace/agentkit-app", "Dynamic": True, "Env": True},
940-
{"Key": "TOS_BUCKET_NAME", "Value": "", "Dynamic": True, "Env": True},
952+
{"Key": "TOS_BUCKET_NAME", "Value": "", "Dynamic": True},
953+
{"Key": "TOS_REGION", "Value": "", "Dynamic": True},
941954
{"Key": "TOS_PROJECT_FILE_NAME", "Value": "", "Dynamic": True, "Env": True},
942955
{"Key": "TOS_PROJECT_FILE_PATH", "Value": "", "Dynamic": True, "Env": True},
943-
{"Key": "TOS_REGION", "Value": "", "Dynamic": True, "Env": True},
944956
{"Key": "CR_NAMESPACE", "Value": "", "Dynamic": True, "Env": True},
945957
{"Key": "CR_INSTANCE", "Value": "", "Dynamic": True, "Env": True},
946958
{"Key": "CR_DOMAIN", "Value": "", "Dynamic": True, "Env": True},
@@ -1030,9 +1042,9 @@ def download_and_show_logs(run_id: str):
10301042
# Prepare build parameters for pipeline execution
10311043
build_parameters = [
10321044
{"Key": "TOS_BUCKET_NAME", "Value": config.tos_bucket},
1045+
{"Key": "TOS_REGION", "Value": config.tos_region},
10331046
{"Key": "TOS_PROJECT_FILE_NAME", "Value": os.path.basename(config.tos_object_key)},
10341047
{"Key": "TOS_PROJECT_FILE_PATH", "Value": config.tos_object_key},
1035-
{"Key": "TOS_REGION", "Value": config.tos_region},
10361048
{"Key": "PROJECT_ROOT_DIR", "Value": f"/workspace/{agent_name}"},
10371049
{"Key": "DOWNLOAD_PATH", "Value": "/workspace"},
10381050
{"Key": "DOCKERFILE_PATH", "Value": f"/workspace/{agent_name}/Dockerfile"},
@@ -1128,4 +1140,4 @@ def download_and_show_logs(run_id: str):
11281140
return image_url
11291141

11301142
except Exception as e:
1131-
raise Exception(f"Build execution failed: {str(e)}")
1143+
raise Exception(f"Build execution failed: {str(e)}")

0 commit comments

Comments
 (0)