agentkit-sdk-python 0.1.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agentkit/__init__.py +23 -0
- agentkit/apps/__init__.py +58 -0
- agentkit/apps/a2a_app/__init__.py +13 -0
- agentkit/apps/a2a_app/a2a_app.py +134 -0
- agentkit/apps/a2a_app/telemetry.py +119 -0
- agentkit/apps/agent_server_app/__init__.py +13 -0
- agentkit/apps/agent_server_app/agent_server_app.py +85 -0
- agentkit/apps/base_app.py +20 -0
- agentkit/apps/mcp_app/__init__.py +13 -0
- agentkit/apps/mcp_app/mcp_app.py +150 -0
- agentkit/apps/mcp_app/telemetry.py +115 -0
- agentkit/apps/simple_app/__init__.py +13 -0
- agentkit/apps/simple_app/simple_app.py +94 -0
- agentkit/apps/simple_app/simple_app_handlers.py +325 -0
- agentkit/apps/simple_app/telemetry.py +124 -0
- agentkit/apps/utils.py +45 -0
- agentkit/client/__init__.py +26 -0
- agentkit/client/base_client.py +219 -0
- agentkit/identity/__init__.py +13 -0
- agentkit/identity/auth.py +70 -0
- agentkit/knowledge/__init__.py +47 -0
- agentkit/knowledge/knowledge.py +203 -0
- agentkit/knowledge/knowledge_all_types.py +191 -0
- agentkit/mcp/__init__.py +79 -0
- agentkit/mcp/mcp.py +294 -0
- agentkit/mcp/mcp_all_types.py +1212 -0
- agentkit/memory/__init__.py +71 -0
- agentkit/memory/memory.py +236 -0
- agentkit/memory/memory_all_types.py +358 -0
- agentkit/runtime/__init__.py +13 -0
- agentkit/runtime/runtime.py +191 -0
- agentkit/runtime/runtime_all_types.py +624 -0
- agentkit/runtime/runtime_v1.py +178 -0
- agentkit/runtime/types.py +188 -0
- agentkit/toolkit/__init__.py +13 -0
- agentkit/toolkit/cli/__init__.py +13 -0
- agentkit/toolkit/cli/__main__.py +7 -0
- agentkit/toolkit/cli/cli.py +97 -0
- agentkit/toolkit/cli/cli_build.py +53 -0
- agentkit/toolkit/cli/cli_config.py +170 -0
- agentkit/toolkit/cli/cli_deploy.py +52 -0
- agentkit/toolkit/cli/cli_destroy.py +53 -0
- agentkit/toolkit/cli/cli_init.py +364 -0
- agentkit/toolkit/cli/cli_invoke.py +168 -0
- agentkit/toolkit/cli/cli_launch.py +34 -0
- agentkit/toolkit/cli/cli_status.py +53 -0
- agentkit/toolkit/cli/cli_version.py +87 -0
- agentkit/toolkit/cli/utils.py +47 -0
- agentkit/toolkit/config/__init__.py +52 -0
- agentkit/toolkit/config/auto_prompt.py +752 -0
- agentkit/toolkit/config/build_config.py +28 -0
- agentkit/toolkit/config/common_config.py +18 -0
- agentkit/toolkit/config/config.py +306 -0
- agentkit/toolkit/config/config_handler.py +331 -0
- agentkit/toolkit/config/config_manager.py +48 -0
- agentkit/toolkit/config/config_validator.py +121 -0
- agentkit/toolkit/config/constants.py +18 -0
- agentkit/toolkit/config/dataclass_utils.py +153 -0
- agentkit/toolkit/config/deploy_config.py +1 -0
- agentkit/toolkit/config/utils.py +57 -0
- agentkit/toolkit/config/workflow_configs.py +149 -0
- agentkit/toolkit/consts.py +1 -0
- agentkit/toolkit/core/__init__.py +13 -0
- agentkit/toolkit/core/build/__init__.py +13 -0
- agentkit/toolkit/core/build/base_builder.py +6 -0
- agentkit/toolkit/core/build/cloud_builder.py +0 -0
- agentkit/toolkit/core/build/local_builder.py +0 -0
- agentkit/toolkit/core/deploy/__init__.py +13 -0
- agentkit/toolkit/core/deploy/base_deployer.py +6 -0
- agentkit/toolkit/core/deploy/cloud_deployer.py +0 -0
- agentkit/toolkit/core/deploy/local_deployer.py +0 -0
- agentkit/toolkit/integrations/__init__.py +17 -0
- agentkit/toolkit/integrations/builder/__init__.py +23 -0
- agentkit/toolkit/integrations/builder/base.py +59 -0
- agentkit/toolkit/integrations/builder/local_docker_builder.py +163 -0
- agentkit/toolkit/integrations/builder/ve_core_pipeline_builder.py +853 -0
- agentkit/toolkit/integrations/container.py +843 -0
- agentkit/toolkit/integrations/runner/__init__.py +26 -0
- agentkit/toolkit/integrations/runner/base.py +222 -0
- agentkit/toolkit/integrations/runner/local_docker_runner.py +407 -0
- agentkit/toolkit/integrations/runner/ve_agentkit_runner.py +665 -0
- agentkit/toolkit/integrations/services/__init__.py +26 -0
- agentkit/toolkit/integrations/services/cr_service.py +449 -0
- agentkit/toolkit/integrations/services/tos_service.py +291 -0
- agentkit/toolkit/integrations/utils/__init__.py +21 -0
- agentkit/toolkit/integrations/utils/project_archiver.py +276 -0
- agentkit/toolkit/integrations/ve_code_pipeline.py +643 -0
- agentkit/toolkit/integrations/ve_cr.py +385 -0
- agentkit/toolkit/integrations/ve_iam.py +210 -0
- agentkit/toolkit/resources/samples/basic.py +79 -0
- agentkit/toolkit/resources/samples/basic_stream.py +100 -0
- agentkit/toolkit/resources/samples/customer_support_assistant.py +3 -0
- agentkit/toolkit/resources/samples/financial_analyst.py +140 -0
- agentkit/toolkit/resources/samples/simple_a2a_veadk.py +32 -0
- agentkit/toolkit/resources/samples/simple_app_veadk.py +55 -0
- agentkit/toolkit/resources/samples/simple_mcp_veadk.py +50 -0
- agentkit/toolkit/resources/templates/Dockerfile.j2 +27 -0
- agentkit/toolkit/resources/templates/code-pipeline-tos-cr-step.j2 +52 -0
- agentkit/toolkit/workflows/__init__.py +27 -0
- agentkit/toolkit/workflows/base.py +87 -0
- agentkit/toolkit/workflows/hybird_local_ve_workflow_v1.py +381 -0
- agentkit/toolkit/workflows/local_workflow_v1.py +262 -0
- agentkit/toolkit/workflows/ve_agentkit_workflow.py +369 -0
- agentkit/tools/__init__.py +17 -0
- agentkit/tools/tools.py +106 -0
- agentkit/tools/tools_all_types.py +337 -0
- agentkit/utils/__init__.py +41 -0
- agentkit/utils/credential.py +44 -0
- agentkit/utils/logging_config.py +366 -0
- agentkit/utils/misc.py +70 -0
- agentkit/utils/request.py +59 -0
- agentkit/utils/template_utils.py +256 -0
- agentkit/utils/ve_sign.py +247 -0
- agentkit/version.py +15 -0
- agentkit_sdk_python-0.1.5.dist-info/METADATA +262 -0
- agentkit_sdk_python-0.1.5.dist-info/RECORD +120 -0
- agentkit_sdk_python-0.1.5.dist-info/WHEEL +5 -0
- agentkit_sdk_python-0.1.5.dist-info/entry_points.txt +2 -0
- agentkit_sdk_python-0.1.5.dist-info/licenses/LICENSE +201 -0
- agentkit_sdk_python-0.1.5.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,665 @@
|
|
|
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
|
+
import logging
|
|
16
|
+
import requests
|
|
17
|
+
import time
|
|
18
|
+
import json
|
|
19
|
+
from typing import Dict, Any, Optional, Tuple, List
|
|
20
|
+
from dataclasses import dataclass, field
|
|
21
|
+
from datetime import datetime
|
|
22
|
+
from urllib.parse import urljoin
|
|
23
|
+
from rich.console import Console
|
|
24
|
+
from rich.progress import Progress, SpinnerColumn, TextColumn, BarColumn, TaskProgressColumn, TimeElapsedColumn, TimeRemainingColumn
|
|
25
|
+
|
|
26
|
+
from agentkit.toolkit.config import CommonConfig, AUTO_CREATE_VE, is_valid_config
|
|
27
|
+
from agentkit.toolkit.config.dataclass_utils import AutoSerializableMixin
|
|
28
|
+
from agentkit.utils.misc import generate_random_id, generate_runtime_name, generate_runtime_role_name, generate_apikey_name, generate_client_token
|
|
29
|
+
from agentkit.runtime.runtime import AgentkitRuntime, ARTIFACT_TYPE_DOCKER_IMAGE, PROJECT_NAME_DEFAULT, API_KEY_LOCATION, RUNTIME_STATUS_READY, RUNTIME_STATUS_ERROR, RUNTIME_STATUS_UPDATING, RUNTIME_STATUS_UNRELEASED, GetAgentkitRuntimeRequest
|
|
30
|
+
from agentkit.runtime.runtime_v1 import AgentkitRuntime as AgentkitRuntimeV1
|
|
31
|
+
from agentkit.runtime.types import CreateAgentkitRuntimeRequest, CreateAgentkitRuntimeResponse, DeleteAgentkitRuntimeRequest, AuthorizerConfiguration, KeyAuth_
|
|
32
|
+
from agentkit.toolkit.integrations.ve_iam import VeIAM
|
|
33
|
+
import agentkit.runtime.runtime_all_types as runtime_all_types
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
from .base import Runner
|
|
38
|
+
|
|
39
|
+
logger = logging.getLogger(__name__)
|
|
40
|
+
|
|
41
|
+
console = Console()
|
|
42
|
+
|
|
43
|
+
@dataclass
|
|
44
|
+
class VeAgentkitRunnerConfig(AutoSerializableMixin):
|
|
45
|
+
"""VeAgentkit Runner配置"""
|
|
46
|
+
common_config: Optional[CommonConfig] = field(default=None, metadata={"system": True, "description": "公共配置"})
|
|
47
|
+
|
|
48
|
+
# Runtime配置
|
|
49
|
+
runtime_id: str = field(default=AUTO_CREATE_VE, metadata={"description": "Runtime ID,Auto表示自动创建"})
|
|
50
|
+
runtime_name: str = field(default=AUTO_CREATE_VE, metadata={"description": "Runtime名称,Auto表示自动生成"})
|
|
51
|
+
runtime_role_name: str = field(default=AUTO_CREATE_VE, metadata={"description": "Runtime角色名称,Auto表示自动创建"})
|
|
52
|
+
runtime_apikey: str = field(default="", metadata={"description": "Runtime API密钥"})
|
|
53
|
+
runtime_apikey_name: str = field(default=AUTO_CREATE_VE, metadata={"description": "Runtime API密钥名称,Auto表示自动生成"})
|
|
54
|
+
runtime_endpoint: str = field(default="", metadata={"description": "Runtime访问端点"})
|
|
55
|
+
runtime_envs: Dict[str, str] = field(default_factory=dict, metadata={"description": "Runtime环境变量"})
|
|
56
|
+
|
|
57
|
+
# 镜像配置
|
|
58
|
+
image_url: str = field(default="", metadata={"description": "容器镜像完整URL"})
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@dataclass
|
|
62
|
+
class VeAgentkitDeployResult(AutoSerializableMixin):
|
|
63
|
+
"""部署结果"""
|
|
64
|
+
success: bool = field(default=False)
|
|
65
|
+
runtime_id: str = field(default="")
|
|
66
|
+
runtime_name: str = field(default="")
|
|
67
|
+
runtime_endpoint: str = field(default="")
|
|
68
|
+
runtime_apikey: str = field(default="")
|
|
69
|
+
message: str = field(default="")
|
|
70
|
+
error: str = field(default="")
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class VeAgentkitRuntimeRunner(Runner):
|
|
74
|
+
"""VeAgentkit Runtime Runner
|
|
75
|
+
|
|
76
|
+
负责管理云上Runtime的生命周期,包括:
|
|
77
|
+
- 创建和管理Runtime实例
|
|
78
|
+
- 部署和更新Runtime配置
|
|
79
|
+
- 调用Runtime服务
|
|
80
|
+
- 监控Runtime状态
|
|
81
|
+
- 清理Runtime资源
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
def __init__(self):
|
|
85
|
+
self.agentkit_runtime = AgentkitRuntime()
|
|
86
|
+
self.agentkit_runtime_v1 = AgentkitRuntimeV1()
|
|
87
|
+
|
|
88
|
+
def deploy(self, config: Dict[str, Any]) -> Tuple[bool, Dict[str, Any]]:
|
|
89
|
+
"""部署Runtime
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
config: 部署配置,包含Runtime相关配置
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
(成功标志, 部署结果字典)
|
|
96
|
+
"""
|
|
97
|
+
try:
|
|
98
|
+
runner_config = VeAgentkitRunnerConfig.from_dict(config)
|
|
99
|
+
runner_config.common_config = CommonConfig.from_dict(runner_config.common_config)
|
|
100
|
+
|
|
101
|
+
if not runner_config.image_url:
|
|
102
|
+
return False, {"error": "镜像URL不能为空,请先构建镜像"}
|
|
103
|
+
|
|
104
|
+
# 准备Runtime配置
|
|
105
|
+
if not self._prepare_runtime_config(runner_config):
|
|
106
|
+
return False, {"error": "Runtime配置准备失败"}
|
|
107
|
+
|
|
108
|
+
# ensure_role_for_agentkit
|
|
109
|
+
ve_iam = VeIAM()
|
|
110
|
+
if not ve_iam.ensure_role_for_agentkit(runner_config.runtime_role_name):
|
|
111
|
+
return False, {"error": "创建Runtime角色失败"}
|
|
112
|
+
|
|
113
|
+
# 部署Runtime
|
|
114
|
+
if runner_config.runtime_id == AUTO_CREATE_VE:
|
|
115
|
+
return self._create_new_runtime(runner_config)
|
|
116
|
+
else:
|
|
117
|
+
return self._update_existing_runtime(runner_config)
|
|
118
|
+
|
|
119
|
+
except Exception as e:
|
|
120
|
+
logger.error(f"Runtime部署失败: {str(e)}")
|
|
121
|
+
return False, {"error": str(e)}
|
|
122
|
+
|
|
123
|
+
def destroy(self, config: Dict[str, Any]) -> bool:
|
|
124
|
+
"""销毁Runtime
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
config: 销毁配置,包含Runtime ID
|
|
128
|
+
|
|
129
|
+
Returns:
|
|
130
|
+
是否成功
|
|
131
|
+
"""
|
|
132
|
+
try:
|
|
133
|
+
runner_config = VeAgentkitRunnerConfig.from_dict(config)
|
|
134
|
+
|
|
135
|
+
if not runner_config.runtime_id or runner_config.runtime_id == AUTO_CREATE_VE:
|
|
136
|
+
console.print("未配置Runtime ID,跳过销毁")
|
|
137
|
+
return True
|
|
138
|
+
|
|
139
|
+
# 删除Runtime
|
|
140
|
+
delete_request = DeleteAgentkitRuntimeRequest(
|
|
141
|
+
RuntimeId=runner_config.runtime_id
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
self.agentkit_runtime.delete(delete_request)
|
|
145
|
+
console.print(f"[green]✅ Runtime销毁成功: {runner_config.runtime_id}[/green]")
|
|
146
|
+
return True
|
|
147
|
+
|
|
148
|
+
except Exception as e:
|
|
149
|
+
logger.error(f"Runtime销毁失败: {str(e)}")
|
|
150
|
+
return False
|
|
151
|
+
|
|
152
|
+
def status(self, config: Dict[str, Any]) -> Dict[str, Any]:
|
|
153
|
+
"""获取Runtime状态
|
|
154
|
+
|
|
155
|
+
Args:
|
|
156
|
+
config: 状态查询配置,包含Runtime ID
|
|
157
|
+
|
|
158
|
+
Returns:
|
|
159
|
+
Runtime状态信息
|
|
160
|
+
"""
|
|
161
|
+
try:
|
|
162
|
+
runner_config = VeAgentkitRunnerConfig.from_dict(config)
|
|
163
|
+
|
|
164
|
+
if not runner_config.runtime_id or runner_config.runtime_id == AUTO_CREATE_VE:
|
|
165
|
+
return {"status": "not_deployed", "message": "未部署Runtime"}
|
|
166
|
+
|
|
167
|
+
# 获取Runtime信息
|
|
168
|
+
runtime = self.agentkit_runtime.get(
|
|
169
|
+
GetAgentkitRuntimeRequest(RuntimeId=runner_config.runtime_id)
|
|
170
|
+
)
|
|
171
|
+
if runner_config.runtime_apikey == "":
|
|
172
|
+
runner_config.runtime_apikey = runtime.authorizer_configuration.KeyAuth.ApiKey
|
|
173
|
+
# 检查Endpoint连通性
|
|
174
|
+
ping_status = None
|
|
175
|
+
if runtime.status == RUNTIME_STATUS_READY and runtime.endpoint:
|
|
176
|
+
try:
|
|
177
|
+
ping_response = requests.get(
|
|
178
|
+
urljoin(runtime.endpoint, "ping"),
|
|
179
|
+
headers={"Authorization": f"Bearer {runner_config.runtime_apikey}"},
|
|
180
|
+
timeout=10
|
|
181
|
+
)
|
|
182
|
+
ping_status = ping_response.status_code == 200
|
|
183
|
+
except Exception as e:
|
|
184
|
+
logger.error(f"检查Endpoint连通性失败: {str(e)}")
|
|
185
|
+
ping_status = False
|
|
186
|
+
|
|
187
|
+
return {
|
|
188
|
+
"runtime_id": runner_config.runtime_id,
|
|
189
|
+
"runtime_name": runtime.name if hasattr(runtime, 'name') else runner_config.runtime_name,
|
|
190
|
+
"status": runtime.status,
|
|
191
|
+
"endpoint": runtime.endpoint if hasattr(runtime, 'endpoint') else "",
|
|
192
|
+
"image_url": runtime.artifact_url if hasattr(runtime, 'artifact_url') else "",
|
|
193
|
+
"ping_status": ping_status,
|
|
194
|
+
"timestamp": datetime.now().isoformat()
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
except Exception as e:
|
|
198
|
+
logger.error(f"获取Runtime状态失败: {str(e)}")
|
|
199
|
+
if "InvalidAgentKitRuntime.NotFound" in str(e):
|
|
200
|
+
return {"status": "not found", "message": f"Runtime未找到,可能已经被删除,请检查Runtime ID: {runner_config.runtime_id} 是否正确"}
|
|
201
|
+
return {"status": "error", "error": str(e)}
|
|
202
|
+
|
|
203
|
+
def invoke(self, config: Dict[str, Any], payload: Dict[str, Any], headers: Optional[Dict[str, str]] = None, stream: Optional[bool] = None) -> Tuple[bool, Any]:
|
|
204
|
+
"""调用Runtime服务
|
|
205
|
+
|
|
206
|
+
Args:
|
|
207
|
+
config: 调用配置,包含Runtime端点和API密钥
|
|
208
|
+
payload: 请求负载
|
|
209
|
+
headers: 请求头
|
|
210
|
+
stream: 是否使用流式调用。None=自动检测(默认), True=强制流式, False=强制非流式
|
|
211
|
+
|
|
212
|
+
Returns:
|
|
213
|
+
如果 stream=False: (成功标志, 响应数据字典)
|
|
214
|
+
如果 stream=True: (成功标志, 生成器对象) - 可通过 for 循环迭代事件
|
|
215
|
+
"""
|
|
216
|
+
try:
|
|
217
|
+
runner_config = VeAgentkitRunnerConfig.from_dict(config)
|
|
218
|
+
|
|
219
|
+
# 获取Runtime端点和API密钥
|
|
220
|
+
endpoint = runner_config.runtime_endpoint
|
|
221
|
+
api_key = runner_config.runtime_apikey
|
|
222
|
+
if not endpoint or not api_key:
|
|
223
|
+
if not runner_config.runtime_id or runner_config.runtime_id == AUTO_CREATE_VE:
|
|
224
|
+
return False, {"error": "Runtime未部署"}
|
|
225
|
+
|
|
226
|
+
# 自动获取Runtime信息
|
|
227
|
+
try:
|
|
228
|
+
runtime = self.agentkit_runtime.get(
|
|
229
|
+
GetAgentkitRuntimeRequest(RuntimeId=runner_config.runtime_id)
|
|
230
|
+
)
|
|
231
|
+
except Exception as e:
|
|
232
|
+
if "NotFound" in str(e):
|
|
233
|
+
return False, {"error": "配置的Runtime已被外部操作删除,请重新部署"}
|
|
234
|
+
raise e
|
|
235
|
+
endpoint = runtime.endpoint
|
|
236
|
+
api_key = runtime.authorizer_configuration.KeyAuth.ApiKey
|
|
237
|
+
|
|
238
|
+
if not endpoint or not api_key:
|
|
239
|
+
return False, {"error": f"无法获取Runtime端点或API密钥, runtime: {runtime}"}
|
|
240
|
+
|
|
241
|
+
# 构造调用URL
|
|
242
|
+
invoke_endpoint = urljoin(endpoint, "invoke")
|
|
243
|
+
|
|
244
|
+
# 准备请求头
|
|
245
|
+
if headers is None:
|
|
246
|
+
headers = {}
|
|
247
|
+
|
|
248
|
+
if not headers.get("Authorization"):
|
|
249
|
+
headers["Authorization"] = f"Bearer {api_key}"
|
|
250
|
+
|
|
251
|
+
# 使用基类的通用 HTTP 调用方法
|
|
252
|
+
return self._http_post_invoke(
|
|
253
|
+
endpoint=invoke_endpoint,
|
|
254
|
+
payload=payload,
|
|
255
|
+
headers=headers,
|
|
256
|
+
stream=stream,
|
|
257
|
+
timeout=60
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
except Exception as e:
|
|
261
|
+
logger.error(f"Runtime调用失败: {str(e)}")
|
|
262
|
+
return False, {"error": str(e)}
|
|
263
|
+
|
|
264
|
+
def _prepare_runtime_config(self, config: VeAgentkitRunnerConfig) -> bool:
|
|
265
|
+
"""准备Runtime配置
|
|
266
|
+
|
|
267
|
+
Args:
|
|
268
|
+
config: Runner配置
|
|
269
|
+
|
|
270
|
+
Returns:
|
|
271
|
+
是否成功
|
|
272
|
+
"""
|
|
273
|
+
try:
|
|
274
|
+
# 检查并创建Runtime名称
|
|
275
|
+
if config.runtime_name == AUTO_CREATE_VE or not config.runtime_name:
|
|
276
|
+
config.runtime_name = generate_runtime_name(config.common_config.agent_name)
|
|
277
|
+
console.print(f"✅ 生成Runtime名称: {config.runtime_name}")
|
|
278
|
+
|
|
279
|
+
# 检查并创建角色名称
|
|
280
|
+
if config.runtime_role_name == AUTO_CREATE_VE or not config.runtime_role_name:
|
|
281
|
+
# config.runtime_role_name = "TestRoleForAgentKit" #
|
|
282
|
+
config.runtime_role_name = generate_runtime_role_name()
|
|
283
|
+
console.print(f"✅ 生成角色名称: {config.runtime_role_name}")
|
|
284
|
+
|
|
285
|
+
# 检查并创建API密钥名称
|
|
286
|
+
if config.runtime_apikey_name == AUTO_CREATE_VE or not config.runtime_apikey_name:
|
|
287
|
+
config.runtime_apikey_name = generate_apikey_name()
|
|
288
|
+
console.print(f"✅ 生成API密钥名称: {config.runtime_apikey_name}")
|
|
289
|
+
|
|
290
|
+
return True
|
|
291
|
+
|
|
292
|
+
except Exception as e:
|
|
293
|
+
logger.error(f"Runtime配置准备失败: {str(e)}")
|
|
294
|
+
return False
|
|
295
|
+
|
|
296
|
+
def _create_new_runtime(self, config: VeAgentkitRunnerConfig) -> Tuple[bool, Dict[str, Any]]:
|
|
297
|
+
"""创建新Runtime
|
|
298
|
+
|
|
299
|
+
Args:
|
|
300
|
+
config: Runner配置
|
|
301
|
+
|
|
302
|
+
Returns:
|
|
303
|
+
(成功标志, 部署结果字典)
|
|
304
|
+
"""
|
|
305
|
+
try:
|
|
306
|
+
console.print(f"[blue]正在创建Runtime: {config.runtime_name}[/blue]")
|
|
307
|
+
|
|
308
|
+
# 构建创建请求
|
|
309
|
+
envs = [{"Key": str(k), "Value": str(v)} for k, v in config.runtime_envs.items()]
|
|
310
|
+
|
|
311
|
+
create_request = CreateAgentkitRuntimeRequest(
|
|
312
|
+
Name=config.runtime_name,
|
|
313
|
+
Description= config.common_config.description if is_valid_config(config.common_config.description) else f"Auto created by AgentKit CLI for agent project {config.common_config.agent_name}",
|
|
314
|
+
ArtifactType=ARTIFACT_TYPE_DOCKER_IMAGE,
|
|
315
|
+
ArtifactUrl=config.image_url,
|
|
316
|
+
RoleName=config.runtime_role_name,
|
|
317
|
+
Envs=envs,
|
|
318
|
+
ProjectName=PROJECT_NAME_DEFAULT,
|
|
319
|
+
AuthorizerConfiguration=AuthorizerConfiguration(
|
|
320
|
+
KeyAuth=KeyAuth_(
|
|
321
|
+
ApiKey=config.runtime_apikey,
|
|
322
|
+
ApiKeyName=config.runtime_apikey_name,
|
|
323
|
+
ApiKeyLocation=API_KEY_LOCATION
|
|
324
|
+
),
|
|
325
|
+
),
|
|
326
|
+
ClientToken=generate_client_token(),
|
|
327
|
+
Tags=[{"Key": "environment", "Value": "test"}],
|
|
328
|
+
ApmplusEnable=True,
|
|
329
|
+
)
|
|
330
|
+
|
|
331
|
+
# console.print("创建请求:")
|
|
332
|
+
# console.print(json.dumps(create_request.model_dump(by_alias=True), indent=2))
|
|
333
|
+
|
|
334
|
+
# 创建Runtime
|
|
335
|
+
runtime_resp, request_id = self.agentkit_runtime.create(create_request)
|
|
336
|
+
config.runtime_id = runtime_resp.id
|
|
337
|
+
|
|
338
|
+
console.print(f"✅ [green]创建Runtime成功: {runtime_resp.id}, request_id: {request_id}[/green]")
|
|
339
|
+
console.print("[blue]等待Runtime状态为Ready...[/blue]")
|
|
340
|
+
console.print("[blue]💡 提示:Runtime初始化中,请耐心等待,不要中断进程[/blue]")
|
|
341
|
+
|
|
342
|
+
# 等待Runtime就绪
|
|
343
|
+
success, runtime, error = self._wait_for_runtime_status(
|
|
344
|
+
runtime_id=config.runtime_id,
|
|
345
|
+
target_status=RUNTIME_STATUS_READY,
|
|
346
|
+
task_description="等待Runtime就绪...",
|
|
347
|
+
timeout=None, # 创建时不设超时
|
|
348
|
+
error_message="初始化失败"
|
|
349
|
+
)
|
|
350
|
+
|
|
351
|
+
if not success:
|
|
352
|
+
console.print(f"[yellow]⚠️ Runtime未成功初始化: {config.runtime_id}[/yellow]")
|
|
353
|
+
console.print(f"[yellow]错误信息: {error}[/yellow]")
|
|
354
|
+
|
|
355
|
+
# 交互式询问用户是否清理
|
|
356
|
+
user_input = input("\n是否清理失败的Runtime? (y/n): ").strip().lower()
|
|
357
|
+
|
|
358
|
+
if user_input in ['y', 'yes', '是']:
|
|
359
|
+
console.print(f"[blue]正在清理失败的Runtime: {config.runtime_id}[/blue]")
|
|
360
|
+
try:
|
|
361
|
+
delete_request = DeleteAgentkitRuntimeRequest(
|
|
362
|
+
RuntimeId=config.runtime_id
|
|
363
|
+
)
|
|
364
|
+
self.agentkit_runtime.delete(delete_request)
|
|
365
|
+
console.print(f"[green]✅ Runtime清理成功[/green]")
|
|
366
|
+
except Exception as e:
|
|
367
|
+
if not "InvalidAgentKitRuntime.NotFound" in str(e):
|
|
368
|
+
console.print(f"[red]清理Runtime失败: {str(e)}[/red]")
|
|
369
|
+
else:
|
|
370
|
+
console.print(f"[yellow]已跳过清理,Runtime保留: {config.runtime_id}[/yellow]")
|
|
371
|
+
|
|
372
|
+
return False, {"error": error}
|
|
373
|
+
|
|
374
|
+
console.print(f"Endpoint: {runtime.endpoint}")
|
|
375
|
+
config.runtime_endpoint = runtime.endpoint
|
|
376
|
+
config.runtime_apikey = runtime.authorizer_configuration.KeyAuth.ApiKey
|
|
377
|
+
|
|
378
|
+
return True, {
|
|
379
|
+
"runtime_id": config.runtime_id,
|
|
380
|
+
"runtime_name": config.runtime_name,
|
|
381
|
+
"runtime_endpoint": runtime.endpoint,
|
|
382
|
+
"runtime_apikey": config.runtime_apikey,
|
|
383
|
+
"runtime_apikey_name": config.runtime_apikey_name,
|
|
384
|
+
"runtime_role_name": config.runtime_role_name,
|
|
385
|
+
"message": "Runtime创建成功"
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
except Exception as e:
|
|
389
|
+
logger.error(f"创建Runtime失败: {str(e)}")
|
|
390
|
+
return False, {"error": str(e)}
|
|
391
|
+
|
|
392
|
+
def _wait_for_runtime_status(
|
|
393
|
+
self,
|
|
394
|
+
runtime_id: str,
|
|
395
|
+
target_status: str,
|
|
396
|
+
task_description: str,
|
|
397
|
+
timeout: Optional[int] = None,
|
|
398
|
+
error_message: str = "等待Runtime状态变化失败"
|
|
399
|
+
) -> Tuple[bool, Optional[Any], Optional[str]]:
|
|
400
|
+
"""等待Runtime达到目标状态(单状态版本)
|
|
401
|
+
|
|
402
|
+
Args:
|
|
403
|
+
runtime_id: Runtime ID
|
|
404
|
+
target_status: 目标状态
|
|
405
|
+
task_description: 进度条任务描述
|
|
406
|
+
timeout: 超时时间(秒),None表示不超时
|
|
407
|
+
error_message: 失败时的错误消息
|
|
408
|
+
|
|
409
|
+
Returns:
|
|
410
|
+
(是否成功, Runtime对象或None, 错误信息或None)
|
|
411
|
+
"""
|
|
412
|
+
# 调用多状态版本,传入单个状态作为列表
|
|
413
|
+
return self._wait_for_runtime_status_multiple(
|
|
414
|
+
runtime_id=runtime_id,
|
|
415
|
+
target_statuses=[target_status],
|
|
416
|
+
task_description=task_description,
|
|
417
|
+
timeout=timeout,
|
|
418
|
+
error_message=error_message
|
|
419
|
+
)
|
|
420
|
+
|
|
421
|
+
def _wait_for_runtime_status_multiple(
|
|
422
|
+
self,
|
|
423
|
+
runtime_id: str,
|
|
424
|
+
target_statuses: List[str],
|
|
425
|
+
task_description: str,
|
|
426
|
+
timeout: Optional[int] = None,
|
|
427
|
+
error_message: str = "等待Runtime状态变化失败"
|
|
428
|
+
) -> Tuple[bool, Optional[Any], Optional[str]]:
|
|
429
|
+
"""等待Runtime达到多个目标状态之一
|
|
430
|
+
|
|
431
|
+
Args:
|
|
432
|
+
runtime_id: Runtime ID
|
|
433
|
+
target_statuses: 目标状态列表
|
|
434
|
+
task_description: 进度条任务描述
|
|
435
|
+
timeout: 超时时间(秒),None表示不超时
|
|
436
|
+
error_message: 失败时的错误消息
|
|
437
|
+
|
|
438
|
+
Returns:
|
|
439
|
+
(是否成功, Runtime对象或None, 错误信息或None)
|
|
440
|
+
"""
|
|
441
|
+
last_status = None
|
|
442
|
+
start_time = time.time()
|
|
443
|
+
total_time = timeout if timeout else 300 # 用于进度条显示
|
|
444
|
+
|
|
445
|
+
with Progress(
|
|
446
|
+
SpinnerColumn(),
|
|
447
|
+
TextColumn("[progress.description]{task.description}"),
|
|
448
|
+
BarColumn(),
|
|
449
|
+
TaskProgressColumn(),
|
|
450
|
+
TimeElapsedColumn(),
|
|
451
|
+
console=console
|
|
452
|
+
) as progress:
|
|
453
|
+
|
|
454
|
+
task = progress.add_task(task_description, total=total_time)
|
|
455
|
+
|
|
456
|
+
while True:
|
|
457
|
+
runtime = self.agentkit_runtime.get(
|
|
458
|
+
GetAgentkitRuntimeRequest(RuntimeId=runtime_id)
|
|
459
|
+
)
|
|
460
|
+
|
|
461
|
+
# 检查是否达到任一目标状态
|
|
462
|
+
if runtime.status in target_statuses:
|
|
463
|
+
progress.update(task, completed=1, total=1)
|
|
464
|
+
console.print(f"✅ Runtime状态为{runtime.status}")
|
|
465
|
+
return True, runtime, None
|
|
466
|
+
|
|
467
|
+
# 检查是否出错
|
|
468
|
+
if runtime.status == RUNTIME_STATUS_ERROR:
|
|
469
|
+
progress.update(task, description="[red]Runtime操作失败[/red]")
|
|
470
|
+
return False, None, f"Runtime状态为Error,{error_message}"
|
|
471
|
+
|
|
472
|
+
# 计算已用时间
|
|
473
|
+
elapsed_time = time.time() - start_time
|
|
474
|
+
|
|
475
|
+
# 检查超时
|
|
476
|
+
if timeout and elapsed_time > timeout:
|
|
477
|
+
progress.update(task, description="[red]等待超时[/red]")
|
|
478
|
+
return False, None, f"{error_message}(超时{timeout}秒)"
|
|
479
|
+
|
|
480
|
+
# 状态变化时更新进度条描述
|
|
481
|
+
if runtime.status != last_status:
|
|
482
|
+
progress.update(task, description=f"Runtime状态: {runtime.status}")
|
|
483
|
+
last_status = runtime.status
|
|
484
|
+
|
|
485
|
+
# 更新进度
|
|
486
|
+
progress.update(task, completed=min(elapsed_time, total_time))
|
|
487
|
+
|
|
488
|
+
time.sleep(3)
|
|
489
|
+
|
|
490
|
+
def _needs_runtime_update(self, runtime: runtime_all_types.GetAgentKitRuntimeResponse, config: VeAgentkitRunnerConfig) -> Tuple[bool, str]:
|
|
491
|
+
"""检查Runtime是否需要更新
|
|
492
|
+
|
|
493
|
+
Args:
|
|
494
|
+
runtime: 现有Runtime对象
|
|
495
|
+
config: 新的Runner配置
|
|
496
|
+
|
|
497
|
+
Returns:
|
|
498
|
+
(是否需要更新, 更新原因描述)
|
|
499
|
+
"""
|
|
500
|
+
|
|
501
|
+
update_reasons = []
|
|
502
|
+
|
|
503
|
+
# 检查镜像URL是否变化
|
|
504
|
+
if runtime.artifact_url != config.image_url:
|
|
505
|
+
update_reasons.append(f"镜像URL变化: {runtime.artifact_url} -> {config.image_url}")
|
|
506
|
+
|
|
507
|
+
# 检查环境变量是否变化
|
|
508
|
+
# 系统自动注入的环境变量前缀,这些不应该被用户修改
|
|
509
|
+
SYSTEM_ENV_PREFIXES = ('OTEL_', 'ENABLE_APMPLUS', 'APMPLUS_')
|
|
510
|
+
|
|
511
|
+
# 将runtime的envs转换为字典进行比较(过滤系统环境变量)
|
|
512
|
+
runtime_envs = {}
|
|
513
|
+
if hasattr(runtime, 'envs') and runtime.envs:
|
|
514
|
+
for env in runtime.envs:
|
|
515
|
+
key = None
|
|
516
|
+
value = None
|
|
517
|
+
|
|
518
|
+
# 尝试小写属性名(runtime_all_types返回的对象)
|
|
519
|
+
if hasattr(env, 'key') and hasattr(env, 'value'):
|
|
520
|
+
key, value = env.key, env.value
|
|
521
|
+
# 尝试大写属性名(兼容其他类型)
|
|
522
|
+
elif hasattr(env, 'Key') and hasattr(env, 'Value'):
|
|
523
|
+
key, value = env.Key, env.Value
|
|
524
|
+
# 如果是字典类型
|
|
525
|
+
elif isinstance(env, dict):
|
|
526
|
+
key = env.get('key') or env.get('Key', '')
|
|
527
|
+
value = env.get('value') or env.get('Value', '')
|
|
528
|
+
|
|
529
|
+
# 过滤掉系统环境变量
|
|
530
|
+
if key and not key.startswith(SYSTEM_ENV_PREFIXES):
|
|
531
|
+
runtime_envs[key] = value
|
|
532
|
+
|
|
533
|
+
# 比较环境变量(只比较用户自定义的)
|
|
534
|
+
if runtime_envs != config.runtime_envs:
|
|
535
|
+
# 找出具体差异
|
|
536
|
+
added_keys = set(config.runtime_envs.keys()) - set(runtime_envs.keys())
|
|
537
|
+
removed_keys = set(runtime_envs.keys()) - set(config.runtime_envs.keys())
|
|
538
|
+
changed_keys = {k for k in set(runtime_envs.keys()) & set(config.runtime_envs.keys())
|
|
539
|
+
if runtime_envs[k] != config.runtime_envs.get(k)}
|
|
540
|
+
|
|
541
|
+
env_changes = []
|
|
542
|
+
if added_keys:
|
|
543
|
+
env_changes.append(f"新增环境变量: {', '.join(added_keys)}")
|
|
544
|
+
if removed_keys:
|
|
545
|
+
env_changes.append(f"删除环境变量: {', '.join(removed_keys)}")
|
|
546
|
+
if changed_keys:
|
|
547
|
+
env_changes.append(f"修改环境变量: {', '.join(changed_keys)}")
|
|
548
|
+
|
|
549
|
+
if env_changes:
|
|
550
|
+
update_reasons.append("环境变量变化: " + "; ".join(env_changes))
|
|
551
|
+
|
|
552
|
+
needs_update = len(update_reasons) > 0
|
|
553
|
+
reason = " | ".join(update_reasons) if needs_update else "配置无变化"
|
|
554
|
+
|
|
555
|
+
return needs_update, reason
|
|
556
|
+
|
|
557
|
+
def _update_existing_runtime(self, config: VeAgentkitRunnerConfig) -> Tuple[bool, Dict[str, Any]]:
|
|
558
|
+
"""更新现有Runtime
|
|
559
|
+
|
|
560
|
+
Args:
|
|
561
|
+
config: Runner配置
|
|
562
|
+
|
|
563
|
+
Returns:
|
|
564
|
+
(成功标志, 更新结果字典)
|
|
565
|
+
"""
|
|
566
|
+
try:
|
|
567
|
+
console.print("[red]当前功能正在测试,因此会打印较多日志,以供调试[/red]")
|
|
568
|
+
console.print(f"正在更新Runtime: {config.runtime_id}")
|
|
569
|
+
|
|
570
|
+
# 获取现有Runtime信息
|
|
571
|
+
runtime = self.agentkit_runtime_v1.get(
|
|
572
|
+
runtime_all_types.GetAgentKitRuntimeRequest(runtime_id=config.runtime_id)
|
|
573
|
+
)
|
|
574
|
+
|
|
575
|
+
if not runtime:
|
|
576
|
+
return False, {"error": f"未找到Runtime: {config.runtime_id},无法更新Runtime,请检查Runtime状态"}
|
|
577
|
+
|
|
578
|
+
if runtime.artifact_type != ARTIFACT_TYPE_DOCKER_IMAGE:
|
|
579
|
+
return False, {"error": f"不支持的Runtime类型: {runtime.artifact_type}"}
|
|
580
|
+
|
|
581
|
+
# 检查是否需要更新
|
|
582
|
+
# needs_update, update_reason = self._needs_runtime_update(runtime, config)
|
|
583
|
+
needs_update = True # 现在总是更新
|
|
584
|
+
|
|
585
|
+
if not needs_update:
|
|
586
|
+
console.print(f"✅ Runtime配置已是最新,无需更新")
|
|
587
|
+
config.runtime_endpoint = runtime.endpoint
|
|
588
|
+
config.runtime_apikey = runtime.authorizer_configuration.key_auth.api_key
|
|
589
|
+
|
|
590
|
+
return True, {
|
|
591
|
+
"runtime_id": config.runtime_id,
|
|
592
|
+
"runtime_name": runtime.name if hasattr(runtime, 'name') else config.runtime_name,
|
|
593
|
+
"runtime_endpoint": runtime.endpoint,
|
|
594
|
+
"runtime_apikey": config.runtime_apikey,
|
|
595
|
+
"message": "Runtime配置已是最新"
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
console.print(f"开始更新Runtime...")
|
|
599
|
+
|
|
600
|
+
envs = [{"Key": str(k), "Value": str(v)} for k, v in config.runtime_envs.items()]
|
|
601
|
+
self.agentkit_runtime_v1.update(runtime_all_types.UpdateAgentKitRuntimeRequest(
|
|
602
|
+
runtime_id=config.runtime_id,
|
|
603
|
+
artifact_url=config.image_url,
|
|
604
|
+
description=config.common_config.description,
|
|
605
|
+
envs=envs,
|
|
606
|
+
client_token=generate_client_token(),
|
|
607
|
+
))
|
|
608
|
+
|
|
609
|
+
console.print("✅ Runtime更新请求已提交")
|
|
610
|
+
|
|
611
|
+
# 阶段1:等待Runtime更新完成,状态可能变为UnReleased或直接变为Ready
|
|
612
|
+
console.print("[blue]等待Runtime更新完成...[/blue]")
|
|
613
|
+
success, updated_runtime, error = self._wait_for_runtime_status_multiple(
|
|
614
|
+
runtime_id=config.runtime_id,
|
|
615
|
+
target_statuses=[RUNTIME_STATUS_UNRELEASED, RUNTIME_STATUS_READY],
|
|
616
|
+
task_description="等待Runtime更新完成...",
|
|
617
|
+
timeout=180,
|
|
618
|
+
error_message="更新失败"
|
|
619
|
+
)
|
|
620
|
+
|
|
621
|
+
if not success:
|
|
622
|
+
return False, {"error": error}
|
|
623
|
+
|
|
624
|
+
# 检查当前状态:如果已经是Ready,说明更新直接完成,无需发布
|
|
625
|
+
if updated_runtime.status == RUNTIME_STATUS_READY:
|
|
626
|
+
console.print("[green]✅ Runtime已直接更新至Ready状态,无需发布步骤[/green]")
|
|
627
|
+
else:
|
|
628
|
+
# 阶段2:状态为UnReleased,需要发布更新
|
|
629
|
+
console.print("[blue]开始发布Runtime更新...[/blue]")
|
|
630
|
+
self.agentkit_runtime_v1.release(
|
|
631
|
+
runtime_all_types.ReleaseAgentKitRuntimeRequest(
|
|
632
|
+
runtime_id=config.runtime_id,
|
|
633
|
+
)
|
|
634
|
+
)
|
|
635
|
+
|
|
636
|
+
# 等待发布完成
|
|
637
|
+
console.print("[blue]等待Runtime发布完成,状态变为Ready...[/blue]")
|
|
638
|
+
console.print("[blue]💡 提示:Runtime发布中,请耐心等待,不要中断进程[/blue]")
|
|
639
|
+
|
|
640
|
+
success, updated_runtime, error = self._wait_for_runtime_status(
|
|
641
|
+
runtime_id=config.runtime_id,
|
|
642
|
+
target_status=RUNTIME_STATUS_READY,
|
|
643
|
+
task_description="等待Runtime发布完成...",
|
|
644
|
+
timeout=300,
|
|
645
|
+
error_message="发布失败"
|
|
646
|
+
)
|
|
647
|
+
|
|
648
|
+
if not success:
|
|
649
|
+
return False, {"error": error}
|
|
650
|
+
|
|
651
|
+
console.print(f"Endpoint: {updated_runtime.endpoint}")
|
|
652
|
+
config.runtime_endpoint = updated_runtime.endpoint
|
|
653
|
+
config.runtime_apikey = updated_runtime.authorizer_configuration.KeyAuth.ApiKey
|
|
654
|
+
|
|
655
|
+
return True, {
|
|
656
|
+
"runtime_id": config.runtime_id,
|
|
657
|
+
"runtime_name": runtime.name if hasattr(runtime, 'name') else config.runtime_name,
|
|
658
|
+
"runtime_endpoint": runtime.endpoint,
|
|
659
|
+
"runtime_apikey": config.runtime_apikey,
|
|
660
|
+
"message": "Runtime更新完成"
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
except Exception as e:
|
|
664
|
+
logger.error(f"更新Runtime失败: {str(e)}")
|
|
665
|
+
return False, {"error": str(e)}
|
|
@@ -0,0 +1,26 @@
|
|
|
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
|
+
from .cr_service import CRService, CRServiceConfig, CRServiceResult, CRConfigCallback, DefaultCRConfigCallback
|
|
16
|
+
from .tos_service import TOSService, TOSServiceConfig
|
|
17
|
+
|
|
18
|
+
__all__ = [
|
|
19
|
+
'CRService',
|
|
20
|
+
'CRServiceConfig',
|
|
21
|
+
'CRServiceResult',
|
|
22
|
+
'CRConfigCallback',
|
|
23
|
+
'DefaultCRConfigCallback',
|
|
24
|
+
'TOSService',
|
|
25
|
+
'TOSServiceConfig'
|
|
26
|
+
]
|