agentscope-runtime 0.2.0b2__py3-none-any.whl → 1.0.0__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.
- agentscope_runtime/adapters/__init__.py +0 -0
- agentscope_runtime/adapters/agentscope/__init__.py +0 -0
- agentscope_runtime/adapters/agentscope/long_term_memory/__init__.py +6 -0
- agentscope_runtime/adapters/agentscope/long_term_memory/_long_term_memory_adapter.py +258 -0
- agentscope_runtime/adapters/agentscope/memory/__init__.py +6 -0
- agentscope_runtime/adapters/agentscope/memory/_memory_adapter.py +152 -0
- agentscope_runtime/adapters/agentscope/message.py +535 -0
- agentscope_runtime/adapters/agentscope/stream.py +506 -0
- agentscope_runtime/adapters/agentscope/tool/__init__.py +9 -0
- agentscope_runtime/adapters/agentscope/tool/sandbox_tool.py +69 -0
- agentscope_runtime/adapters/agentscope/tool/tool.py +233 -0
- agentscope_runtime/adapters/autogen/__init__.py +0 -0
- agentscope_runtime/adapters/autogen/tool/__init__.py +7 -0
- agentscope_runtime/adapters/autogen/tool/tool.py +211 -0
- agentscope_runtime/adapters/text/__init__.py +0 -0
- agentscope_runtime/adapters/text/stream.py +29 -0
- agentscope_runtime/common/collections/redis_mapping.py +4 -1
- agentscope_runtime/common/container_clients/fc_client.py +855 -0
- agentscope_runtime/common/utils/__init__.py +0 -0
- agentscope_runtime/common/utils/lazy_loader.py +57 -0
- agentscope_runtime/engine/__init__.py +25 -18
- agentscope_runtime/engine/app/agent_app.py +161 -91
- agentscope_runtime/engine/app/base_app.py +4 -118
- agentscope_runtime/engine/constant.py +8 -0
- agentscope_runtime/engine/deployers/__init__.py +8 -0
- agentscope_runtime/engine/deployers/adapter/__init__.py +2 -0
- agentscope_runtime/engine/deployers/adapter/a2a/a2a_adapter_utils.py +0 -21
- agentscope_runtime/engine/deployers/adapter/a2a/a2a_protocol_adapter.py +28 -9
- agentscope_runtime/engine/deployers/adapter/responses/__init__.py +2 -0
- agentscope_runtime/engine/deployers/adapter/responses/response_api_adapter_utils.py +5 -2
- agentscope_runtime/engine/deployers/adapter/responses/response_api_protocol_adapter.py +1 -1
- agentscope_runtime/engine/deployers/agentrun_deployer.py +2541 -0
- agentscope_runtime/engine/deployers/cli_fc_deploy.py +1 -1
- agentscope_runtime/engine/deployers/kubernetes_deployer.py +9 -21
- agentscope_runtime/engine/deployers/local_deployer.py +47 -74
- agentscope_runtime/engine/deployers/modelstudio_deployer.py +216 -50
- agentscope_runtime/engine/deployers/utils/app_runner_utils.py +29 -0
- agentscope_runtime/engine/deployers/utils/detached_app.py +510 -0
- agentscope_runtime/engine/deployers/utils/docker_image_utils/__init__.py +1 -1
- agentscope_runtime/engine/deployers/utils/docker_image_utils/dockerfile_generator.py +1 -1
- agentscope_runtime/engine/deployers/utils/docker_image_utils/{runner_image_factory.py → image_factory.py} +121 -61
- agentscope_runtime/engine/deployers/utils/package.py +693 -0
- agentscope_runtime/engine/deployers/utils/service_utils/__init__.py +0 -5
- agentscope_runtime/engine/deployers/utils/service_utils/fastapi_factory.py +301 -282
- agentscope_runtime/engine/deployers/utils/service_utils/fastapi_templates.py +2 -4
- agentscope_runtime/engine/deployers/utils/service_utils/process_manager.py +23 -1
- agentscope_runtime/engine/deployers/utils/templates/app_main.py.j2 +84 -0
- agentscope_runtime/engine/deployers/utils/templates/runner_main.py.j2 +95 -0
- agentscope_runtime/engine/deployers/utils/{service_utils → templates}/standalone_main.py.j2 +0 -45
- agentscope_runtime/engine/deployers/utils/wheel_packager.py +119 -18
- agentscope_runtime/engine/helpers/runner.py +40 -0
- agentscope_runtime/engine/runner.py +171 -130
- agentscope_runtime/engine/schemas/agent_schemas.py +114 -3
- agentscope_runtime/engine/schemas/modelstudio_llm.py +4 -2
- agentscope_runtime/engine/schemas/oai_llm.py +23 -23
- agentscope_runtime/engine/schemas/response_api.py +65 -0
- agentscope_runtime/engine/schemas/session.py +24 -0
- agentscope_runtime/engine/services/__init__.py +0 -9
- agentscope_runtime/engine/services/agent_state/__init__.py +16 -0
- agentscope_runtime/engine/services/agent_state/redis_state_service.py +113 -0
- agentscope_runtime/engine/services/agent_state/state_service.py +179 -0
- agentscope_runtime/engine/services/memory/__init__.py +24 -0
- agentscope_runtime/engine/services/{mem0_memory_service.py → memory/mem0_memory_service.py} +17 -13
- agentscope_runtime/engine/services/{memory_service.py → memory/memory_service.py} +28 -7
- agentscope_runtime/engine/services/{redis_memory_service.py → memory/redis_memory_service.py} +1 -1
- agentscope_runtime/engine/services/{reme_personal_memory_service.py → memory/reme_personal_memory_service.py} +9 -6
- agentscope_runtime/engine/services/{reme_task_memory_service.py → memory/reme_task_memory_service.py} +2 -2
- agentscope_runtime/engine/services/{tablestore_memory_service.py → memory/tablestore_memory_service.py} +12 -18
- agentscope_runtime/engine/services/sandbox/__init__.py +13 -0
- agentscope_runtime/engine/services/{sandbox_service.py → sandbox/sandbox_service.py} +86 -71
- agentscope_runtime/engine/services/session_history/__init__.py +23 -0
- agentscope_runtime/engine/services/{redis_session_history_service.py → session_history/redis_session_history_service.py} +3 -2
- agentscope_runtime/engine/services/{session_history_service.py → session_history/session_history_service.py} +44 -34
- agentscope_runtime/engine/services/{tablestore_session_history_service.py → session_history/tablestore_session_history_service.py} +14 -19
- agentscope_runtime/engine/services/utils/tablestore_service_utils.py +2 -2
- agentscope_runtime/engine/tracing/base.py +10 -9
- agentscope_runtime/engine/tracing/message_util.py +1 -1
- agentscope_runtime/engine/tracing/tracing_util.py +7 -2
- agentscope_runtime/engine/tracing/wrapper.py +49 -31
- agentscope_runtime/sandbox/__init__.py +10 -2
- agentscope_runtime/sandbox/box/agentbay/__init__.py +4 -0
- agentscope_runtime/sandbox/box/agentbay/agentbay_sandbox.py +559 -0
- agentscope_runtime/sandbox/box/base/base_sandbox.py +12 -0
- agentscope_runtime/sandbox/box/browser/browser_sandbox.py +115 -11
- agentscope_runtime/sandbox/box/cloud/__init__.py +4 -0
- agentscope_runtime/sandbox/box/cloud/cloud_sandbox.py +254 -0
- agentscope_runtime/sandbox/box/filesystem/filesystem_sandbox.py +66 -0
- agentscope_runtime/sandbox/box/gui/gui_sandbox.py +42 -0
- agentscope_runtime/sandbox/box/mobile/__init__.py +4 -0
- agentscope_runtime/sandbox/box/mobile/box/__init__.py +0 -0
- agentscope_runtime/sandbox/box/mobile/mobile_sandbox.py +216 -0
- agentscope_runtime/sandbox/box/training_box/training_box.py +2 -2
- agentscope_runtime/sandbox/client/http_client.py +1 -0
- agentscope_runtime/sandbox/enums.py +2 -0
- agentscope_runtime/sandbox/manager/sandbox_manager.py +15 -2
- agentscope_runtime/sandbox/manager/server/app.py +12 -0
- agentscope_runtime/sandbox/manager/server/config.py +19 -0
- agentscope_runtime/sandbox/model/manager_config.py +79 -2
- agentscope_runtime/sandbox/utils.py +0 -18
- agentscope_runtime/tools/RAGs/__init__.py +0 -0
- agentscope_runtime/tools/RAGs/modelstudio_rag.py +377 -0
- agentscope_runtime/tools/RAGs/modelstudio_rag_lite.py +219 -0
- agentscope_runtime/tools/__init__.py +119 -0
- agentscope_runtime/tools/_constants.py +18 -0
- agentscope_runtime/tools/alipay/__init__.py +4 -0
- agentscope_runtime/tools/alipay/base.py +334 -0
- agentscope_runtime/tools/alipay/payment.py +835 -0
- agentscope_runtime/tools/alipay/subscribe.py +551 -0
- agentscope_runtime/tools/base.py +264 -0
- agentscope_runtime/tools/cli/__init__.py +0 -0
- agentscope_runtime/tools/cli/modelstudio_mcp_server.py +78 -0
- agentscope_runtime/tools/generations/__init__.py +75 -0
- agentscope_runtime/tools/generations/async_image_to_video.py +350 -0
- agentscope_runtime/tools/generations/async_image_to_video_wan25.py +366 -0
- agentscope_runtime/tools/generations/async_speech_to_video.py +422 -0
- agentscope_runtime/tools/generations/async_text_to_video.py +320 -0
- agentscope_runtime/tools/generations/async_text_to_video_wan25.py +334 -0
- agentscope_runtime/tools/generations/image_edit.py +208 -0
- agentscope_runtime/tools/generations/image_edit_wan25.py +193 -0
- agentscope_runtime/tools/generations/image_generation.py +202 -0
- agentscope_runtime/tools/generations/image_generation_wan25.py +201 -0
- agentscope_runtime/tools/generations/image_style_repaint.py +208 -0
- agentscope_runtime/tools/generations/image_to_video.py +233 -0
- agentscope_runtime/tools/generations/qwen_image_edit.py +205 -0
- agentscope_runtime/tools/generations/qwen_image_generation.py +214 -0
- agentscope_runtime/tools/generations/qwen_text_to_speech.py +154 -0
- agentscope_runtime/tools/generations/speech_to_text.py +260 -0
- agentscope_runtime/tools/generations/speech_to_video.py +314 -0
- agentscope_runtime/tools/generations/text_to_video.py +221 -0
- agentscope_runtime/tools/mcp_wrapper.py +215 -0
- agentscope_runtime/tools/realtime_clients/__init__.py +13 -0
- agentscope_runtime/tools/realtime_clients/asr_client.py +27 -0
- agentscope_runtime/tools/realtime_clients/azure_asr_client.py +195 -0
- agentscope_runtime/tools/realtime_clients/azure_tts_client.py +383 -0
- agentscope_runtime/tools/realtime_clients/modelstudio_asr_client.py +151 -0
- agentscope_runtime/tools/realtime_clients/modelstudio_tts_client.py +199 -0
- agentscope_runtime/tools/realtime_clients/realtime_tool.py +55 -0
- agentscope_runtime/tools/realtime_clients/tts_client.py +33 -0
- agentscope_runtime/tools/searches/__init__.py +3 -0
- agentscope_runtime/tools/searches/modelstudio_search.py +877 -0
- agentscope_runtime/tools/searches/modelstudio_search_lite.py +310 -0
- agentscope_runtime/tools/utils/__init__.py +0 -0
- agentscope_runtime/tools/utils/api_key_util.py +45 -0
- agentscope_runtime/tools/utils/crypto_utils.py +99 -0
- agentscope_runtime/tools/utils/mcp_util.py +35 -0
- agentscope_runtime/version.py +1 -1
- {agentscope_runtime-0.2.0b2.dist-info → agentscope_runtime-1.0.0.dist-info}/METADATA +240 -168
- agentscope_runtime-1.0.0.dist-info/RECORD +240 -0
- {agentscope_runtime-0.2.0b2.dist-info → agentscope_runtime-1.0.0.dist-info}/entry_points.txt +1 -0
- agentscope_runtime/engine/agents/__init__.py +0 -2
- agentscope_runtime/engine/agents/agentscope_agent.py +0 -488
- agentscope_runtime/engine/agents/agno_agent.py +0 -220
- agentscope_runtime/engine/agents/autogen_agent.py +0 -250
- agentscope_runtime/engine/agents/base_agent.py +0 -29
- agentscope_runtime/engine/agents/langgraph_agent.py +0 -59
- agentscope_runtime/engine/agents/utils.py +0 -53
- agentscope_runtime/engine/deployers/utils/package_project_utils.py +0 -1163
- agentscope_runtime/engine/deployers/utils/service_utils/service_config.py +0 -75
- agentscope_runtime/engine/deployers/utils/service_utils/service_factory.py +0 -220
- agentscope_runtime/engine/helpers/helper.py +0 -179
- agentscope_runtime/engine/schemas/context.py +0 -54
- agentscope_runtime/engine/services/context_manager.py +0 -164
- agentscope_runtime/engine/services/environment_manager.py +0 -50
- agentscope_runtime/engine/services/manager.py +0 -174
- agentscope_runtime/engine/services/rag_service.py +0 -195
- agentscope_runtime/engine/services/tablestore_rag_service.py +0 -143
- agentscope_runtime/sandbox/tools/__init__.py +0 -12
- agentscope_runtime/sandbox/tools/base/__init__.py +0 -8
- agentscope_runtime/sandbox/tools/base/tool.py +0 -52
- agentscope_runtime/sandbox/tools/browser/__init__.py +0 -57
- agentscope_runtime/sandbox/tools/browser/tool.py +0 -597
- agentscope_runtime/sandbox/tools/filesystem/__init__.py +0 -32
- agentscope_runtime/sandbox/tools/filesystem/tool.py +0 -319
- agentscope_runtime/sandbox/tools/function_tool.py +0 -321
- agentscope_runtime/sandbox/tools/gui/__init__.py +0 -7
- agentscope_runtime/sandbox/tools/gui/tool.py +0 -77
- agentscope_runtime/sandbox/tools/mcp_tool.py +0 -195
- agentscope_runtime/sandbox/tools/sandbox_tool.py +0 -104
- agentscope_runtime/sandbox/tools/tool.py +0 -238
- agentscope_runtime/sandbox/tools/utils.py +0 -68
- agentscope_runtime-0.2.0b2.dist-info/RECORD +0 -183
- {agentscope_runtime-0.2.0b2.dist-info → agentscope_runtime-1.0.0.dist-info}/WHEEL +0 -0
- {agentscope_runtime-0.2.0b2.dist-info → agentscope_runtime-1.0.0.dist-info}/licenses/LICENSE +0 -0
- {agentscope_runtime-0.2.0b2.dist-info → agentscope_runtime-1.0.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,2541 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# flake8: noqa: E501
|
|
3
|
+
# pylint: disable=line-too-long, too-many-branches, too-many-statements
|
|
4
|
+
# pylint: disable=protected-access, too-many-nested-blocks
|
|
5
|
+
import asyncio
|
|
6
|
+
import logging
|
|
7
|
+
import os
|
|
8
|
+
import time
|
|
9
|
+
from dataclasses import dataclass
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Dict, Optional, List, Any, Union, Tuple
|
|
12
|
+
|
|
13
|
+
from alibabacloud_agentrun20250910.client import Client as AgentRunClient
|
|
14
|
+
from alibabacloud_agentrun20250910.models import (
|
|
15
|
+
CreateAgentRuntimeRequest,
|
|
16
|
+
CreateAgentRuntimeInput,
|
|
17
|
+
GetAgentRuntimeRequest,
|
|
18
|
+
UpdateAgentRuntimeRequest,
|
|
19
|
+
UpdateAgentRuntimeInput,
|
|
20
|
+
CreateAgentRuntimeEndpointRequest,
|
|
21
|
+
CreateAgentRuntimeEndpointInput,
|
|
22
|
+
UpdateAgentRuntimeEndpointRequest,
|
|
23
|
+
UpdateAgentRuntimeEndpointInput,
|
|
24
|
+
ListAgentRuntimeEndpointsRequest,
|
|
25
|
+
PublishRuntimeVersionRequest,
|
|
26
|
+
PublishRuntimeVersionInput,
|
|
27
|
+
CodeConfiguration,
|
|
28
|
+
LogConfiguration,
|
|
29
|
+
NetworkConfiguration,
|
|
30
|
+
)
|
|
31
|
+
from alibabacloud_tea_openapi import models as open_api_models
|
|
32
|
+
from pydantic import BaseModel, Field
|
|
33
|
+
|
|
34
|
+
from .adapter.protocol_adapter import ProtocolAdapter
|
|
35
|
+
from .base import DeployManager
|
|
36
|
+
from .local_deployer import LocalDeployManager
|
|
37
|
+
from .utils.detached_app import get_bundle_entry_script
|
|
38
|
+
from .utils.wheel_packager import (
|
|
39
|
+
default_deploy_name,
|
|
40
|
+
generate_wrapper_project,
|
|
41
|
+
build_wheel,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
logger = logging.getLogger(__name__)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@dataclass
|
|
48
|
+
class EndpointConfig:
|
|
49
|
+
"""Configuration for agent runtime endpoint."""
|
|
50
|
+
|
|
51
|
+
agent_runtime_endpoint_name: Optional[str] = None
|
|
52
|
+
description: Optional[str] = None
|
|
53
|
+
tags: Optional[List[str]] = None
|
|
54
|
+
target_version: Optional[str] = "LATEST"
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@dataclass
|
|
58
|
+
class CodeConfig:
|
|
59
|
+
"""Configuration for code-based runtimes."""
|
|
60
|
+
|
|
61
|
+
command: Optional[List[str]] = None
|
|
62
|
+
oss_bucket_name: Optional[str] = None
|
|
63
|
+
oss_object_name: Optional[str] = None
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@dataclass
|
|
67
|
+
class LogConfig:
|
|
68
|
+
"""Configuration for logging."""
|
|
69
|
+
|
|
70
|
+
logstore: Optional[str] = None
|
|
71
|
+
project: Optional[str] = None
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@dataclass
|
|
75
|
+
class NetworkConfig:
|
|
76
|
+
"""Network configuration for the runtime."""
|
|
77
|
+
|
|
78
|
+
network_mode: str = "PUBLIC"
|
|
79
|
+
security_group_id: Optional[str] = None
|
|
80
|
+
vpc_id: Optional[str] = None
|
|
81
|
+
vswitch_ids: Optional[list[str]] = None
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class AgentRunConfig(BaseModel):
|
|
85
|
+
access_key_id: Optional[str] = None
|
|
86
|
+
access_key_secret: Optional[str] = None
|
|
87
|
+
region_id: str = "cn-hangzhou"
|
|
88
|
+
endpoint: Optional[str] = None
|
|
89
|
+
|
|
90
|
+
log_config: Optional[LogConfig] = None
|
|
91
|
+
network_config: Optional[NetworkConfig] = NetworkConfig()
|
|
92
|
+
|
|
93
|
+
cpu: float = 2.0
|
|
94
|
+
memory: int = 2048
|
|
95
|
+
|
|
96
|
+
execution_role_arn: Optional[str] = None
|
|
97
|
+
|
|
98
|
+
session_concurrency_limit: Optional[int] = 1
|
|
99
|
+
session_idle_timeout_seconds: Optional[int] = 3600
|
|
100
|
+
|
|
101
|
+
@classmethod
|
|
102
|
+
def from_env(cls) -> "AgentRunConfig":
|
|
103
|
+
"""Create AgentRunConfig from environment variables.
|
|
104
|
+
|
|
105
|
+
Returns:
|
|
106
|
+
AgentRunConfig: Configuration loaded from environment variables.
|
|
107
|
+
"""
|
|
108
|
+
# Read region_id
|
|
109
|
+
region_id = os.environ.get("AGENT_RUN_REGION_ID", "cn-hangzhou")
|
|
110
|
+
|
|
111
|
+
# Read log-related environment variables
|
|
112
|
+
log_store = os.environ.get("AGENT_RUN_LOG_STORE")
|
|
113
|
+
log_project = os.environ.get("AGENT_RUN_LOG_PROJECT")
|
|
114
|
+
log_config = None
|
|
115
|
+
if log_store and log_project:
|
|
116
|
+
log_config = LogConfig(
|
|
117
|
+
logstore=log_store,
|
|
118
|
+
project=log_project,
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
# Read network-related environment variables
|
|
122
|
+
network_mode = os.environ.get("AGENT_RUN_NETWORK_MODE", "PUBLIC")
|
|
123
|
+
vpc_id = os.environ.get("AGENT_RUN_VPC_ID")
|
|
124
|
+
security_group_id = os.environ.get("AGENT_RUN_SECURITY_GROUP_ID")
|
|
125
|
+
vswitch_ids_str = os.environ.get("AGENT_RUN_VSWITCH_IDS")
|
|
126
|
+
|
|
127
|
+
network_config = None
|
|
128
|
+
if network_mode:
|
|
129
|
+
vswitch_ids = None
|
|
130
|
+
if vswitch_ids_str:
|
|
131
|
+
import json
|
|
132
|
+
|
|
133
|
+
vswitch_ids = json.loads(vswitch_ids_str)
|
|
134
|
+
if not isinstance(vswitch_ids, list):
|
|
135
|
+
raise ValueError("vswitch_ids must be a list")
|
|
136
|
+
|
|
137
|
+
network_config = NetworkConfig(
|
|
138
|
+
network_mode=network_mode,
|
|
139
|
+
vpc_id=vpc_id,
|
|
140
|
+
security_group_id=security_group_id,
|
|
141
|
+
vswitch_ids=vswitch_ids,
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
# Read CPU and Memory with type conversion
|
|
145
|
+
cpu_str = os.environ.get("AGENT_RUN_CPU", "2.0")
|
|
146
|
+
memory_str = os.environ.get("AGENT_RUN_MEMORY", "2048")
|
|
147
|
+
|
|
148
|
+
session_concurrency_limit_str = os.environ.get(
|
|
149
|
+
"AGENT_RUN_SESSION_CONCURRENCY_LIMIT",
|
|
150
|
+
"1",
|
|
151
|
+
)
|
|
152
|
+
session_idle_timeout_seconds_str = os.environ.get(
|
|
153
|
+
"AGENT_RUN_SESSION_IDLE_TIMEOUT_SECONDS",
|
|
154
|
+
"600",
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
try:
|
|
158
|
+
cpu = float(cpu_str)
|
|
159
|
+
except (ValueError, TypeError):
|
|
160
|
+
cpu = 2.0
|
|
161
|
+
|
|
162
|
+
try:
|
|
163
|
+
memory = int(memory_str)
|
|
164
|
+
except (ValueError, TypeError):
|
|
165
|
+
memory = 2048
|
|
166
|
+
|
|
167
|
+
execution_role_arn = os.environ.get("AGENT_RUN_EXECUTION_ROLE_ARN")
|
|
168
|
+
|
|
169
|
+
try:
|
|
170
|
+
session_concurrency_limit = int(session_concurrency_limit_str)
|
|
171
|
+
except (ValueError, TypeError):
|
|
172
|
+
session_concurrency_limit = 1
|
|
173
|
+
|
|
174
|
+
try:
|
|
175
|
+
session_idle_timeout_seconds = int(
|
|
176
|
+
session_idle_timeout_seconds_str,
|
|
177
|
+
)
|
|
178
|
+
except (ValueError, TypeError):
|
|
179
|
+
session_idle_timeout_seconds = 600
|
|
180
|
+
|
|
181
|
+
return cls(
|
|
182
|
+
access_key_id=os.environ.get("ALIBABA_CLOUD_ACCESS_KEY_ID"),
|
|
183
|
+
access_key_secret=os.environ.get(
|
|
184
|
+
"ALIBABA_CLOUD_ACCESS_KEY_SECRET",
|
|
185
|
+
),
|
|
186
|
+
region_id=region_id,
|
|
187
|
+
endpoint=os.environ.get(
|
|
188
|
+
"AGENT_RUN_ENDPOINT",
|
|
189
|
+
f"agentrun.{region_id}.aliyuncs.com",
|
|
190
|
+
),
|
|
191
|
+
log_config=log_config,
|
|
192
|
+
network_config=network_config,
|
|
193
|
+
cpu=cpu,
|
|
194
|
+
memory=memory,
|
|
195
|
+
execution_role_arn=execution_role_arn,
|
|
196
|
+
session_concurrency_limit=session_concurrency_limit,
|
|
197
|
+
session_idle_timeout_seconds=session_idle_timeout_seconds,
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
def ensure_valid(self) -> None:
|
|
201
|
+
"""Validate that all required configuration fields are present.
|
|
202
|
+
|
|
203
|
+
Raises:
|
|
204
|
+
ValueError: If required environment variables are missing.
|
|
205
|
+
"""
|
|
206
|
+
missing = []
|
|
207
|
+
if not self.access_key_id:
|
|
208
|
+
missing.append("ALIBABA_CLOUD_ACCESS_KEY_ID")
|
|
209
|
+
if not self.access_key_secret:
|
|
210
|
+
missing.append("ALIBABA_CLOUD_ACCESS_KEY_SECRET")
|
|
211
|
+
if missing:
|
|
212
|
+
raise ValueError(
|
|
213
|
+
f"Missing required AgentRun env vars: {', '.join(missing)}",
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
class OSSConfig(BaseModel):
|
|
218
|
+
region: str = Field("cn-hangzhou", description="OSS region")
|
|
219
|
+
access_key_id: Optional[str] = None
|
|
220
|
+
access_key_secret: Optional[str] = None
|
|
221
|
+
|
|
222
|
+
@classmethod
|
|
223
|
+
def from_env(cls) -> "OSSConfig":
|
|
224
|
+
"""Create OSSConfig from environment variables.
|
|
225
|
+
|
|
226
|
+
Returns:
|
|
227
|
+
OSSConfig: Configuration loaded from environment variables.
|
|
228
|
+
"""
|
|
229
|
+
return cls(
|
|
230
|
+
region=os.environ.get("OSS_REGION", "cn-hangzhou"),
|
|
231
|
+
access_key_id=os.environ.get(
|
|
232
|
+
"OSS_ACCESS_KEY_ID",
|
|
233
|
+
os.environ.get("ALIBABA_CLOUD_ACCESS_KEY_ID"),
|
|
234
|
+
),
|
|
235
|
+
access_key_secret=os.environ.get(
|
|
236
|
+
"OSS_ACCESS_KEY_SECRET",
|
|
237
|
+
os.environ.get("ALIBABA_CLOUD_ACCESS_KEY_SECRET"),
|
|
238
|
+
),
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
def ensure_valid(self) -> None:
|
|
242
|
+
"""Validate that all required OSS configuration fields are present.
|
|
243
|
+
|
|
244
|
+
Raises:
|
|
245
|
+
RuntimeError: If required AccessKey credentials are missing.
|
|
246
|
+
"""
|
|
247
|
+
# Allow fallback to Alibaba Cloud AK/SK via from_env()
|
|
248
|
+
if not self.access_key_id or not self.access_key_secret:
|
|
249
|
+
raise RuntimeError(
|
|
250
|
+
"Missing AccessKey for OSS. Set either OSS_ACCESS_KEY_ID/OSS_ACCESS_KEY_SECRET "
|
|
251
|
+
"or ALIBABA_CLOUD_ACCESS_KEY_ID/ALIBABA_CLOUD_ACCESS_KEY_SECRET.",
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
class AgentRunDeployManager(DeployManager):
|
|
256
|
+
"""Manager for deploying agents to Alibaba Cloud AgentRun service.
|
|
257
|
+
|
|
258
|
+
This class handles the complete deployment workflow including:
|
|
259
|
+
- Building and packaging agent projects
|
|
260
|
+
- Uploading artifacts to OSS
|
|
261
|
+
- Creating and managing agent runtimes
|
|
262
|
+
- Creating and managing runtime endpoints
|
|
263
|
+
"""
|
|
264
|
+
|
|
265
|
+
# Maximum attempts for polling agent runtime status
|
|
266
|
+
GET_AGENT_RUNTIME_STATUS_MAX_ATTEMPTS = 60
|
|
267
|
+
# Interval in seconds between status polling attempts
|
|
268
|
+
GET_AGENT_RUNTIME_STATUS_INTERVAL = 1
|
|
269
|
+
|
|
270
|
+
# Default version identifier for latest runtime
|
|
271
|
+
LATEST_VERSION = "LATEST"
|
|
272
|
+
|
|
273
|
+
# Default name for runtime endpoints
|
|
274
|
+
DEFAULT_ENDPOINT_NAME = "default-endpoint"
|
|
275
|
+
|
|
276
|
+
def __init__(
|
|
277
|
+
self,
|
|
278
|
+
oss_config: Optional[OSSConfig] = None,
|
|
279
|
+
agentrun_config: Optional[AgentRunConfig] = None,
|
|
280
|
+
build_root: Optional[Union[str, Path]] = None,
|
|
281
|
+
):
|
|
282
|
+
"""Initialize AgentRun deployment manager.
|
|
283
|
+
|
|
284
|
+
Args:
|
|
285
|
+
oss_config: OSS configuration for artifact storage. If None, loads from environment.
|
|
286
|
+
agentrun_config: AgentRun service configuration. If None, loads from environment.
|
|
287
|
+
build_root: Root directory for build artifacts. If None, uses parent directory of current working directory.
|
|
288
|
+
"""
|
|
289
|
+
super().__init__()
|
|
290
|
+
self.oss_config = oss_config or OSSConfig.from_env()
|
|
291
|
+
self.agentrun_config = agentrun_config or AgentRunConfig.from_env()
|
|
292
|
+
self.build_root = (
|
|
293
|
+
Path(build_root)
|
|
294
|
+
if build_root
|
|
295
|
+
else Path(os.getcwd()).parent / ".agentscope_runtime_builds"
|
|
296
|
+
)
|
|
297
|
+
self.client = self._create_agent_run_client()
|
|
298
|
+
self._get_agent_runtime_status_max_attempts = (
|
|
299
|
+
self.GET_AGENT_RUNTIME_STATUS_MAX_ATTEMPTS
|
|
300
|
+
)
|
|
301
|
+
self._get_agent_runtime_status_interval = (
|
|
302
|
+
self.GET_AGENT_RUNTIME_STATUS_INTERVAL
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
def _create_agent_run_client(self) -> AgentRunClient:
|
|
306
|
+
"""Create and configure AgentRun SDK client.
|
|
307
|
+
|
|
308
|
+
Returns:
|
|
309
|
+
AgentRunClient: Configured client for AgentRun service API calls.
|
|
310
|
+
"""
|
|
311
|
+
config = open_api_models.Config(
|
|
312
|
+
access_key_id=self.agentrun_config.access_key_id,
|
|
313
|
+
access_key_secret=self.agentrun_config.access_key_secret,
|
|
314
|
+
region_id=self.agentrun_config.region_id,
|
|
315
|
+
read_timeout=60 * 1000,
|
|
316
|
+
)
|
|
317
|
+
config.endpoint = (
|
|
318
|
+
f"agentrun.{self.agentrun_config.region_id}.aliyuncs.com"
|
|
319
|
+
)
|
|
320
|
+
return AgentRunClient(config)
|
|
321
|
+
|
|
322
|
+
def _adapt_code_config(
|
|
323
|
+
self,
|
|
324
|
+
config: Optional[CodeConfig],
|
|
325
|
+
) -> Optional[CodeConfiguration]:
|
|
326
|
+
"""Convert internal CodeConfig to SDK's CodeConfiguration format.
|
|
327
|
+
|
|
328
|
+
Args:
|
|
329
|
+
config: Internal code configuration object.
|
|
330
|
+
|
|
331
|
+
Returns:
|
|
332
|
+
SDK-compatible CodeConfiguration object, or None if input is None.
|
|
333
|
+
"""
|
|
334
|
+
if config is None:
|
|
335
|
+
return None
|
|
336
|
+
return CodeConfiguration(
|
|
337
|
+
language="python3.12",
|
|
338
|
+
command=config.command,
|
|
339
|
+
oss_bucket_name=config.oss_bucket_name,
|
|
340
|
+
oss_object_name=config.oss_object_name,
|
|
341
|
+
)
|
|
342
|
+
|
|
343
|
+
def _adapt_log_config(
|
|
344
|
+
self,
|
|
345
|
+
config: Optional[LogConfig],
|
|
346
|
+
) -> Optional[LogConfiguration]:
|
|
347
|
+
"""Convert internal LogConfig to SDK's LogConfiguration format.
|
|
348
|
+
|
|
349
|
+
Args:
|
|
350
|
+
config: Internal log configuration object.
|
|
351
|
+
|
|
352
|
+
Returns:
|
|
353
|
+
SDK-compatible LogConfiguration object, or None if input is None.
|
|
354
|
+
"""
|
|
355
|
+
if config is None:
|
|
356
|
+
return None
|
|
357
|
+
return LogConfiguration(
|
|
358
|
+
logstore=config.logstore,
|
|
359
|
+
project=config.project,
|
|
360
|
+
)
|
|
361
|
+
|
|
362
|
+
def _adapt_network_config(
|
|
363
|
+
self,
|
|
364
|
+
config: Optional[NetworkConfig],
|
|
365
|
+
) -> Optional[NetworkConfiguration]:
|
|
366
|
+
"""Convert internal NetworkConfig to SDK's NetworkConfiguration format.
|
|
367
|
+
|
|
368
|
+
Args:
|
|
369
|
+
config: Internal network configuration object.
|
|
370
|
+
|
|
371
|
+
Returns:
|
|
372
|
+
SDK-compatible NetworkConfiguration object, or None if input is None.
|
|
373
|
+
"""
|
|
374
|
+
if config is None:
|
|
375
|
+
return None
|
|
376
|
+
return NetworkConfiguration(
|
|
377
|
+
network_mode=config.network_mode,
|
|
378
|
+
security_group_id=config.security_group_id,
|
|
379
|
+
vpc_id=config.vpc_id,
|
|
380
|
+
vswitch_ids=config.vswitch_ids,
|
|
381
|
+
)
|
|
382
|
+
|
|
383
|
+
async def _generate_wrapper_and_build_wheel(
|
|
384
|
+
self,
|
|
385
|
+
project_dir: Union[Optional[str], Path],
|
|
386
|
+
cmd: Optional[str] = None,
|
|
387
|
+
deploy_name: Optional[str] = None,
|
|
388
|
+
telemetry_enabled: bool = True,
|
|
389
|
+
) -> Tuple[Path, str]:
|
|
390
|
+
"""Generate wrapper project and build wheel package.
|
|
391
|
+
|
|
392
|
+
Args:
|
|
393
|
+
project_dir: Path to the user's project directory.
|
|
394
|
+
cmd: Command to start the agent application.
|
|
395
|
+
deploy_name: Name for the deployment. If None, generates default name.
|
|
396
|
+
telemetry_enabled: Whether to enable telemetry in the wrapper.
|
|
397
|
+
|
|
398
|
+
Returns:
|
|
399
|
+
Tuple containing:
|
|
400
|
+
- wheel_path: Path to the built wheel file
|
|
401
|
+
- name: Deployment name used
|
|
402
|
+
|
|
403
|
+
Raises:
|
|
404
|
+
ValueError: If project_dir or cmd is not provided.
|
|
405
|
+
FileNotFoundError: If project directory does not exist.
|
|
406
|
+
"""
|
|
407
|
+
if not project_dir or not cmd:
|
|
408
|
+
raise ValueError(
|
|
409
|
+
"project_dir and cmd are required for deployment",
|
|
410
|
+
)
|
|
411
|
+
|
|
412
|
+
project_dir = Path(project_dir).resolve()
|
|
413
|
+
if not project_dir.is_dir():
|
|
414
|
+
raise FileNotFoundError(
|
|
415
|
+
f"Project directory not found: {project_dir}",
|
|
416
|
+
)
|
|
417
|
+
|
|
418
|
+
name = deploy_name or default_deploy_name()
|
|
419
|
+
proj_root = project_dir.resolve()
|
|
420
|
+
if isinstance(self.build_root, Path):
|
|
421
|
+
effective_build_root = self.build_root.resolve()
|
|
422
|
+
else:
|
|
423
|
+
if self.build_root:
|
|
424
|
+
effective_build_root = Path(self.build_root).resolve()
|
|
425
|
+
else:
|
|
426
|
+
effective_build_root = (
|
|
427
|
+
proj_root.parent / ".agentscope_runtime_builds"
|
|
428
|
+
).resolve()
|
|
429
|
+
|
|
430
|
+
build_dir = effective_build_root / f"build-{int(time.time())}"
|
|
431
|
+
build_dir.mkdir(parents=True, exist_ok=True)
|
|
432
|
+
|
|
433
|
+
logger.info("Generating wrapper project: %s", name)
|
|
434
|
+
wrapper_project_dir, _ = generate_wrapper_project(
|
|
435
|
+
build_root=build_dir,
|
|
436
|
+
user_project_dir=project_dir,
|
|
437
|
+
start_cmd=cmd,
|
|
438
|
+
deploy_name=name,
|
|
439
|
+
telemetry_enabled=telemetry_enabled,
|
|
440
|
+
)
|
|
441
|
+
|
|
442
|
+
logger.info("Building wheel package from: %s", wrapper_project_dir)
|
|
443
|
+
wheel_path = build_wheel(wrapper_project_dir)
|
|
444
|
+
logger.info("Wheel package created: %s", wheel_path)
|
|
445
|
+
return wheel_path, name
|
|
446
|
+
|
|
447
|
+
def _generate_env_file(
|
|
448
|
+
self,
|
|
449
|
+
project_dir: Union[str, Path],
|
|
450
|
+
environment: Optional[Dict[str, str]] = None,
|
|
451
|
+
env_filename: str = ".env",
|
|
452
|
+
) -> Optional[Path]:
|
|
453
|
+
"""Generate .env file from environment variables dictionary.
|
|
454
|
+
|
|
455
|
+
Args:
|
|
456
|
+
project_dir: Project directory where the .env file will be created.
|
|
457
|
+
environment: Dictionary of environment variables to write to .env file.
|
|
458
|
+
env_filename: Name of the env file (default: ".env").
|
|
459
|
+
|
|
460
|
+
Returns:
|
|
461
|
+
Path to the created .env file, or None if no environment variables provided.
|
|
462
|
+
|
|
463
|
+
Raises:
|
|
464
|
+
FileNotFoundError: If project directory does not exist.
|
|
465
|
+
"""
|
|
466
|
+
if not environment:
|
|
467
|
+
return None
|
|
468
|
+
|
|
469
|
+
project_path = Path(project_dir).resolve()
|
|
470
|
+
if not project_path.exists():
|
|
471
|
+
raise FileNotFoundError(
|
|
472
|
+
f"Project directory not found: {project_path}",
|
|
473
|
+
)
|
|
474
|
+
|
|
475
|
+
env_file_path = project_path / env_filename
|
|
476
|
+
|
|
477
|
+
try:
|
|
478
|
+
with env_file_path.open("w", encoding="utf-8") as f:
|
|
479
|
+
f.write("# Environment variables used by AgentScope Runtime\n")
|
|
480
|
+
|
|
481
|
+
for key, value in environment.items():
|
|
482
|
+
# Skip None values
|
|
483
|
+
if value is None:
|
|
484
|
+
continue
|
|
485
|
+
|
|
486
|
+
# Quote values that contain spaces or special characters
|
|
487
|
+
if " " in str(value) or any(
|
|
488
|
+
char in str(value)
|
|
489
|
+
for char in ["$", "`", '"', "'", "\\"]
|
|
490
|
+
):
|
|
491
|
+
# Escape existing quotes and wrap in double quotes
|
|
492
|
+
escaped_value = (
|
|
493
|
+
str(value)
|
|
494
|
+
.replace("\\", "\\\\")
|
|
495
|
+
.replace('"', '\\"')
|
|
496
|
+
)
|
|
497
|
+
f.write(f'{key}="{escaped_value}"\n')
|
|
498
|
+
else:
|
|
499
|
+
f.write(f"{key}={value}\n")
|
|
500
|
+
|
|
501
|
+
logger.info("Environment file created: %s", env_file_path)
|
|
502
|
+
return env_file_path
|
|
503
|
+
|
|
504
|
+
except Exception as e:
|
|
505
|
+
logger.warning("Failed to create environment file: %s", e)
|
|
506
|
+
return None
|
|
507
|
+
|
|
508
|
+
async def deploy(
|
|
509
|
+
self,
|
|
510
|
+
runner=None,
|
|
511
|
+
endpoint_path: str = "/process",
|
|
512
|
+
protocol_adapters: Optional[list[ProtocolAdapter]] = None,
|
|
513
|
+
requirements: Optional[Union[str, List[str]]] = None,
|
|
514
|
+
extra_packages: Optional[List[str]] = None,
|
|
515
|
+
environment: Optional[Dict[str, str]] = None,
|
|
516
|
+
project_dir: Optional[Union[str, Path]] = None,
|
|
517
|
+
cmd: Optional[str] = None,
|
|
518
|
+
deploy_name: Optional[str] = None,
|
|
519
|
+
skip_upload: bool = False,
|
|
520
|
+
external_whl_path: Optional[str] = None,
|
|
521
|
+
agentrun_id: Optional[str] = None,
|
|
522
|
+
custom_endpoints: Optional[List[Dict]] = None,
|
|
523
|
+
app=None,
|
|
524
|
+
**kwargs,
|
|
525
|
+
) -> Dict[str, str]:
|
|
526
|
+
"""Deploy agent to AgentRun service.
|
|
527
|
+
|
|
528
|
+
Args:
|
|
529
|
+
app: AgentApp instance to deploy.
|
|
530
|
+
runner: Runner instance containing the agent to deploy.
|
|
531
|
+
endpoint_path: HTTP endpoint path for the agent service.
|
|
532
|
+
protocol_adapters: List of protocol adapters for the agent.
|
|
533
|
+
requirements: Python requirements for the agent (file path or list).
|
|
534
|
+
extra_packages: Additional Python packages to install.
|
|
535
|
+
environment: Environment variables for the runtime.
|
|
536
|
+
project_dir: Project directory to deploy.
|
|
537
|
+
cmd: Command to start the agent application.
|
|
538
|
+
deploy_name: Name for this deployment.
|
|
539
|
+
skip_upload: If True, skip uploading to AgentRun service.
|
|
540
|
+
external_whl_path: Path to pre-built wheel file.
|
|
541
|
+
agentrun_id: ID of existing agent to update.
|
|
542
|
+
custom_endpoints: Custom endpoints for the agent.
|
|
543
|
+
**kwargs: Additional deployment parameters.
|
|
544
|
+
|
|
545
|
+
Returns:
|
|
546
|
+
Dictionary containing deployment results with keys:
|
|
547
|
+
- success: Whether deployment succeeded
|
|
548
|
+
- message: Status message
|
|
549
|
+
- agentrun_id: ID of the agent runtime
|
|
550
|
+
- agentrun_endpoint_url: Public endpoint URL
|
|
551
|
+
- build_dir: Build directory path
|
|
552
|
+
- wheel_path: Path to wheel file
|
|
553
|
+
- artifact_url: OSS artifact URL
|
|
554
|
+
- url: Console URL for the deployment
|
|
555
|
+
- deploy_id: Deployment ID
|
|
556
|
+
- resource_name: Resource name
|
|
557
|
+
|
|
558
|
+
Raises:
|
|
559
|
+
ValueError: If required parameters are missing.
|
|
560
|
+
FileNotFoundError: If specified files/directories don't exist.
|
|
561
|
+
"""
|
|
562
|
+
if not agentrun_id:
|
|
563
|
+
if not runner and not project_dir and not external_whl_path:
|
|
564
|
+
raise ValueError(
|
|
565
|
+
"Must provide either runner, project_dir, or external_whl_path",
|
|
566
|
+
)
|
|
567
|
+
try:
|
|
568
|
+
if runner or app:
|
|
569
|
+
logger.info("Creating detached project from runner")
|
|
570
|
+
if "agent" in kwargs:
|
|
571
|
+
kwargs.pop("agent")
|
|
572
|
+
|
|
573
|
+
# Create package project for detached deployment
|
|
574
|
+
project_dir = await LocalDeployManager.create_detached_project(
|
|
575
|
+
app=app,
|
|
576
|
+
runner=runner,
|
|
577
|
+
endpoint_path=endpoint_path,
|
|
578
|
+
custom_endpoints=custom_endpoints,
|
|
579
|
+
protocol_adapters=protocol_adapters,
|
|
580
|
+
requirements=requirements,
|
|
581
|
+
extra_packages=extra_packages,
|
|
582
|
+
**kwargs,
|
|
583
|
+
)
|
|
584
|
+
if project_dir:
|
|
585
|
+
self._generate_env_file(project_dir, environment)
|
|
586
|
+
entry_script = get_bundle_entry_script(project_dir)
|
|
587
|
+
cmd = f"python {entry_script}"
|
|
588
|
+
deploy_name = deploy_name or default_deploy_name()
|
|
589
|
+
|
|
590
|
+
if agentrun_id:
|
|
591
|
+
if not external_whl_path:
|
|
592
|
+
raise FileNotFoundError(
|
|
593
|
+
"Wheel file required for agent update. "
|
|
594
|
+
"Specify wheel file path with '--whl-path <path>'",
|
|
595
|
+
)
|
|
596
|
+
# Use external wheel if provided, skip project packaging
|
|
597
|
+
if external_whl_path:
|
|
598
|
+
wheel_path = Path(external_whl_path).resolve()
|
|
599
|
+
if not wheel_path.is_file():
|
|
600
|
+
raise FileNotFoundError(
|
|
601
|
+
f"External wheel file not found: {wheel_path}",
|
|
602
|
+
)
|
|
603
|
+
name = deploy_name or default_deploy_name()
|
|
604
|
+
# Keep existing name when updating agent without specifying deploy_name
|
|
605
|
+
if agentrun_id and (deploy_name is None):
|
|
606
|
+
name = None
|
|
607
|
+
logger.info("Using external wheel file: %s", wheel_path)
|
|
608
|
+
else:
|
|
609
|
+
logger.info("Building wheel package from project")
|
|
610
|
+
(
|
|
611
|
+
wheel_path,
|
|
612
|
+
name,
|
|
613
|
+
) = await self._generate_wrapper_and_build_wheel(
|
|
614
|
+
project_dir=project_dir,
|
|
615
|
+
cmd=cmd,
|
|
616
|
+
deploy_name=deploy_name,
|
|
617
|
+
)
|
|
618
|
+
logger.info(
|
|
619
|
+
"Wheel file ready: %s (deploy name: %s)",
|
|
620
|
+
wheel_path,
|
|
621
|
+
name,
|
|
622
|
+
)
|
|
623
|
+
|
|
624
|
+
timestamp = time.strftime("%Y%m%d%H%M%S")
|
|
625
|
+
|
|
626
|
+
# Step 1: Build and package in Docker container
|
|
627
|
+
logger.info(
|
|
628
|
+
"Building dependencies and creating zip package in Docker",
|
|
629
|
+
)
|
|
630
|
+
zip_file_path = await self._build_and_zip_in_docker(
|
|
631
|
+
wheel_path=wheel_path,
|
|
632
|
+
output_dir=wheel_path.parent,
|
|
633
|
+
zip_filename=f"{name or agentrun_id}-{timestamp}.zip",
|
|
634
|
+
)
|
|
635
|
+
logger.info("Zip package created: %s", zip_file_path)
|
|
636
|
+
|
|
637
|
+
if skip_upload:
|
|
638
|
+
logger.info(
|
|
639
|
+
"Deployment completed (skipped upload to AgentRun)",
|
|
640
|
+
)
|
|
641
|
+
return {
|
|
642
|
+
"message": "Agent package built successfully (upload skipped)",
|
|
643
|
+
"deploy_name": name,
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
# Step 2: Upload to OSS
|
|
647
|
+
logger.info("Uploading zip package to OSS")
|
|
648
|
+
oss_result = await self._upload_to_fixed_oss_bucket(
|
|
649
|
+
zip_file_path=zip_file_path,
|
|
650
|
+
bucket_name="tmp-agentscope-agentrun-code",
|
|
651
|
+
)
|
|
652
|
+
logger.info("Zip package uploaded to OSS successfully")
|
|
653
|
+
|
|
654
|
+
# Deploy to AgentRun service
|
|
655
|
+
logger.info("Deploying to AgentRun service")
|
|
656
|
+
agentrun_deploy_result = await self.deploy_to_agentrun(
|
|
657
|
+
agentrun_id=agentrun_id,
|
|
658
|
+
agent_runtime_name=name,
|
|
659
|
+
oss_bucket_name=oss_result["bucket_name"],
|
|
660
|
+
oss_object_name=oss_result["object_key"],
|
|
661
|
+
environment=environment,
|
|
662
|
+
)
|
|
663
|
+
|
|
664
|
+
# Return deployment results
|
|
665
|
+
logger.info(
|
|
666
|
+
"Deployment completed successfully. Agent runtime ID: %s",
|
|
667
|
+
agentrun_deploy_result["agent_runtime_id"],
|
|
668
|
+
)
|
|
669
|
+
return {
|
|
670
|
+
"message": "Agent deployed successfully to AgentRun",
|
|
671
|
+
"agentrun_id": agentrun_deploy_result["agent_runtime_id"],
|
|
672
|
+
"agentrun_endpoint_url": agentrun_deploy_result[
|
|
673
|
+
"agent_runtime_public_endpoint_url"
|
|
674
|
+
],
|
|
675
|
+
"wheel_path": str(wheel_path),
|
|
676
|
+
"artifact_url": oss_result["presigned_url"],
|
|
677
|
+
"url": f'https://functionai.console.aliyun.com/{self.agentrun_config.region_id}/agent/infra/agent-runtime/agent-detail?id={agentrun_deploy_result["agent_runtime_id"]}',
|
|
678
|
+
"deploy_id": agentrun_deploy_result["agent_runtime_id"],
|
|
679
|
+
"resource_name": name,
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
except Exception as e:
|
|
683
|
+
logger.error("Deployment failed: %s", str(e))
|
|
684
|
+
raise
|
|
685
|
+
|
|
686
|
+
async def _build_and_zip_in_docker(
|
|
687
|
+
self,
|
|
688
|
+
wheel_path: Path,
|
|
689
|
+
output_dir: Path,
|
|
690
|
+
zip_filename: str,
|
|
691
|
+
) -> Path:
|
|
692
|
+
"""Build dependencies and create zip package in Docker container.
|
|
693
|
+
|
|
694
|
+
All build logic runs in container, only final zip file is returned to host.
|
|
695
|
+
|
|
696
|
+
Args:
|
|
697
|
+
wheel_path: Path to the wheel file on host machine.
|
|
698
|
+
output_dir: Local directory to save the final zip file.
|
|
699
|
+
zip_filename: Name of the output zip file.
|
|
700
|
+
|
|
701
|
+
Returns:
|
|
702
|
+
Path to the created zip file.
|
|
703
|
+
|
|
704
|
+
Raises:
|
|
705
|
+
RuntimeError: If Docker is not available or build fails.
|
|
706
|
+
FileNotFoundError: If Docker is not installed.
|
|
707
|
+
"""
|
|
708
|
+
import subprocess
|
|
709
|
+
|
|
710
|
+
try:
|
|
711
|
+
logger.info("Starting Docker build for wheel: %s", wheel_path)
|
|
712
|
+
logger.debug("Output directory: %s", output_dir)
|
|
713
|
+
logger.debug("Zip filename: %s", zip_filename)
|
|
714
|
+
|
|
715
|
+
# Ensure output directory exists
|
|
716
|
+
output_dir.mkdir(parents=True, exist_ok=True)
|
|
717
|
+
|
|
718
|
+
# Convert paths to absolute paths for Docker volume mounting
|
|
719
|
+
wheel_path_abs = wheel_path.resolve()
|
|
720
|
+
output_dir_abs = output_dir.resolve()
|
|
721
|
+
|
|
722
|
+
# Keep original wheel filename for pip to parse metadata
|
|
723
|
+
wheel_filename = wheel_path.name
|
|
724
|
+
wheel_path_in_container = f"/tmp/{wheel_filename}"
|
|
725
|
+
|
|
726
|
+
# Docker image to use
|
|
727
|
+
docker_image = "registry.cn-beijing.aliyuncs.com/aliyunfc/runtime:custom.debian11-build-3.1.0"
|
|
728
|
+
|
|
729
|
+
# Build script that runs in container:
|
|
730
|
+
# 1. Install wheel and dependencies to /tmp/python
|
|
731
|
+
# 2. Use Python's zipfile module to create zip
|
|
732
|
+
# 3. Save zip to /output
|
|
733
|
+
build_script = f"""
|
|
734
|
+
set -e
|
|
735
|
+
echo "=== Installing dependencies to /tmp/python ==="
|
|
736
|
+
pip install {wheel_path_in_container} -t /tmp/python --no-cache-dir
|
|
737
|
+
|
|
738
|
+
echo "=== Creating zip package using Python ==="
|
|
739
|
+
python3 << 'PYTHON_EOF'
|
|
740
|
+
import os
|
|
741
|
+
import zipfile
|
|
742
|
+
from pathlib import Path
|
|
743
|
+
|
|
744
|
+
python_dir = Path("/tmp/python")
|
|
745
|
+
zip_path = Path("/output/{zip_filename}")
|
|
746
|
+
|
|
747
|
+
print(f"Creating zip from {{python_dir}}")
|
|
748
|
+
with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
|
|
749
|
+
for root, dirs, files in os.walk(python_dir):
|
|
750
|
+
for file in files:
|
|
751
|
+
file_path = Path(root) / file
|
|
752
|
+
arcname = file_path.relative_to(python_dir)
|
|
753
|
+
zipf.write(file_path, arcname)
|
|
754
|
+
|
|
755
|
+
zip_size_mb = zip_path.stat().st_size / (1024 * 1024)
|
|
756
|
+
print(f"Created zip ({{zip_size_mb:.2f}} MB): {{zip_path}}")
|
|
757
|
+
PYTHON_EOF
|
|
758
|
+
|
|
759
|
+
echo "=== Build complete ==="
|
|
760
|
+
ls -lh /output/{zip_filename}
|
|
761
|
+
"""
|
|
762
|
+
|
|
763
|
+
# Docker run command with x86_64 platform for AgentRun compatibility
|
|
764
|
+
cmd = [
|
|
765
|
+
"docker",
|
|
766
|
+
"run",
|
|
767
|
+
"--rm",
|
|
768
|
+
"--platform",
|
|
769
|
+
"linux/amd64",
|
|
770
|
+
"-v",
|
|
771
|
+
f"{wheel_path_abs}:{wheel_path_in_container}:ro",
|
|
772
|
+
"-v",
|
|
773
|
+
f"{output_dir_abs}:/output",
|
|
774
|
+
docker_image,
|
|
775
|
+
"bash",
|
|
776
|
+
"-c",
|
|
777
|
+
build_script,
|
|
778
|
+
]
|
|
779
|
+
|
|
780
|
+
logger.info("Executing Docker build command")
|
|
781
|
+
logger.debug("Build script:\n%s", build_script)
|
|
782
|
+
|
|
783
|
+
result = subprocess.run(
|
|
784
|
+
cmd,
|
|
785
|
+
capture_output=True,
|
|
786
|
+
text=True,
|
|
787
|
+
check=False,
|
|
788
|
+
)
|
|
789
|
+
|
|
790
|
+
if result.returncode != 0:
|
|
791
|
+
logger.error("Docker build failed: %s", result.stderr)
|
|
792
|
+
raise RuntimeError(
|
|
793
|
+
f"Docker build failed: {result.stderr}",
|
|
794
|
+
)
|
|
795
|
+
|
|
796
|
+
logger.info("Docker build completed successfully")
|
|
797
|
+
if result.stdout:
|
|
798
|
+
logger.debug("Docker output:\n%s", result.stdout)
|
|
799
|
+
|
|
800
|
+
# Verify zip file was created
|
|
801
|
+
zip_file_path = output_dir / zip_filename
|
|
802
|
+
if not zip_file_path.exists():
|
|
803
|
+
raise RuntimeError(f"Zip file not created: {zip_file_path}")
|
|
804
|
+
|
|
805
|
+
zip_size_mb = zip_file_path.stat().st_size / (1024 * 1024)
|
|
806
|
+
logger.info(
|
|
807
|
+
"Zip package created successfully (%.2f MB): %s",
|
|
808
|
+
zip_size_mb,
|
|
809
|
+
zip_file_path,
|
|
810
|
+
)
|
|
811
|
+
|
|
812
|
+
return zip_file_path
|
|
813
|
+
|
|
814
|
+
except FileNotFoundError as e:
|
|
815
|
+
if "docker" in str(e).lower():
|
|
816
|
+
logger.error(
|
|
817
|
+
"Docker is not installed or not available in PATH",
|
|
818
|
+
)
|
|
819
|
+
raise RuntimeError(
|
|
820
|
+
"Docker is required for building. "
|
|
821
|
+
"Install Docker Desktop: https://www.docker.com/products/docker-desktop",
|
|
822
|
+
) from e
|
|
823
|
+
raise
|
|
824
|
+
except Exception as e:
|
|
825
|
+
logger.error("Error during Docker build: %s", str(e))
|
|
826
|
+
raise
|
|
827
|
+
|
|
828
|
+
async def _upload_to_fixed_oss_bucket(
|
|
829
|
+
self,
|
|
830
|
+
zip_file_path: Path,
|
|
831
|
+
bucket_name: str,
|
|
832
|
+
) -> Dict[str, str]:
|
|
833
|
+
"""Upload zip file to a fixed OSS bucket.
|
|
834
|
+
|
|
835
|
+
Args:
|
|
836
|
+
zip_file_path: Path to the zip file to upload.
|
|
837
|
+
bucket_name: Target OSS bucket name (e.g., "tmp-agentscope-agentrun-code").
|
|
838
|
+
|
|
839
|
+
Returns:
|
|
840
|
+
Dictionary containing:
|
|
841
|
+
- bucket_name: OSS bucket name
|
|
842
|
+
- object_key: Object key in OSS
|
|
843
|
+
- presigned_url: Presigned URL for downloading (valid for 3 hours)
|
|
844
|
+
|
|
845
|
+
Raises:
|
|
846
|
+
RuntimeError: If OSS SDK is not installed or upload fails.
|
|
847
|
+
"""
|
|
848
|
+
try:
|
|
849
|
+
from alibabacloud_oss_v2 import Client as OSSClient
|
|
850
|
+
from alibabacloud_oss_v2.models import (
|
|
851
|
+
PutObjectRequest,
|
|
852
|
+
GetObjectRequest,
|
|
853
|
+
PutBucketRequest,
|
|
854
|
+
CreateBucketConfiguration,
|
|
855
|
+
PutBucketTagsRequest,
|
|
856
|
+
Tagging,
|
|
857
|
+
TagSet,
|
|
858
|
+
Tag,
|
|
859
|
+
)
|
|
860
|
+
from alibabacloud_oss_v2 import config as oss_config
|
|
861
|
+
from alibabacloud_oss_v2.credentials import (
|
|
862
|
+
StaticCredentialsProvider,
|
|
863
|
+
)
|
|
864
|
+
import datetime
|
|
865
|
+
except ImportError as e:
|
|
866
|
+
logger.error(
|
|
867
|
+
"OSS SDK not available. Install with: pip install alibabacloud-oss-v2",
|
|
868
|
+
)
|
|
869
|
+
raise RuntimeError(
|
|
870
|
+
"OSS SDK not installed. Run: pip install alibabacloud-oss-v2",
|
|
871
|
+
) from e
|
|
872
|
+
|
|
873
|
+
# Create OSS client
|
|
874
|
+
logger.info("Initializing OSS client")
|
|
875
|
+
|
|
876
|
+
credentials_provider = StaticCredentialsProvider(
|
|
877
|
+
access_key_id=self.oss_config.access_key_id,
|
|
878
|
+
access_key_secret=self.oss_config.access_key_secret,
|
|
879
|
+
)
|
|
880
|
+
|
|
881
|
+
cfg = oss_config.Config(
|
|
882
|
+
credentials_provider=credentials_provider,
|
|
883
|
+
region=self.oss_config.region,
|
|
884
|
+
)
|
|
885
|
+
oss_client = OSSClient(cfg)
|
|
886
|
+
|
|
887
|
+
logger.info("Using OSS bucket: %s", bucket_name)
|
|
888
|
+
|
|
889
|
+
# Create bucket if not exists
|
|
890
|
+
try:
|
|
891
|
+
bucket_exists = oss_client.is_bucket_exist(bucket=bucket_name)
|
|
892
|
+
except Exception:
|
|
893
|
+
bucket_exists = False
|
|
894
|
+
|
|
895
|
+
if not bucket_exists:
|
|
896
|
+
logger.info("OSS bucket does not exist, creating: %s", bucket_name)
|
|
897
|
+
try:
|
|
898
|
+
put_bucket_req = PutBucketRequest(
|
|
899
|
+
bucket=bucket_name,
|
|
900
|
+
acl="private",
|
|
901
|
+
create_bucket_configuration=CreateBucketConfiguration(
|
|
902
|
+
storage_class="IA",
|
|
903
|
+
),
|
|
904
|
+
)
|
|
905
|
+
put_bucket_result = oss_client.put_bucket(put_bucket_req)
|
|
906
|
+
logger.info(
|
|
907
|
+
"OSS bucket created (Status: %s, Request ID: %s)",
|
|
908
|
+
put_bucket_result.status_code,
|
|
909
|
+
put_bucket_result.request_id,
|
|
910
|
+
)
|
|
911
|
+
|
|
912
|
+
# Add tag for AgentRun access permission
|
|
913
|
+
tag_result = oss_client.put_bucket_tags(
|
|
914
|
+
PutBucketTagsRequest(
|
|
915
|
+
bucket=bucket_name,
|
|
916
|
+
tagging=Tagging(
|
|
917
|
+
tag_set=TagSet(
|
|
918
|
+
tags=[
|
|
919
|
+
Tag(
|
|
920
|
+
key="agentrun-deploy-access",
|
|
921
|
+
value="ReadAndAdd",
|
|
922
|
+
),
|
|
923
|
+
],
|
|
924
|
+
),
|
|
925
|
+
),
|
|
926
|
+
),
|
|
927
|
+
)
|
|
928
|
+
logger.info(
|
|
929
|
+
"OSS bucket tags configured (Status: %s)",
|
|
930
|
+
tag_result.status_code,
|
|
931
|
+
)
|
|
932
|
+
except Exception as e:
|
|
933
|
+
logger.error("Failed to create OSS bucket: %s", str(e))
|
|
934
|
+
raise
|
|
935
|
+
else:
|
|
936
|
+
logger.debug("OSS bucket already exists: %s", bucket_name)
|
|
937
|
+
|
|
938
|
+
# Upload zip file
|
|
939
|
+
object_key = zip_file_path.name
|
|
940
|
+
logger.info("Uploading to OSS: %s", object_key)
|
|
941
|
+
|
|
942
|
+
try:
|
|
943
|
+
with open(zip_file_path, "rb") as f:
|
|
944
|
+
file_bytes = f.read()
|
|
945
|
+
|
|
946
|
+
put_obj_req = PutObjectRequest(
|
|
947
|
+
bucket=bucket_name,
|
|
948
|
+
key=object_key,
|
|
949
|
+
body=file_bytes,
|
|
950
|
+
)
|
|
951
|
+
put_obj_result = oss_client.put_object(put_obj_req)
|
|
952
|
+
logger.info(
|
|
953
|
+
"File uploaded to OSS successfully (Status: %s)",
|
|
954
|
+
put_obj_result.status_code,
|
|
955
|
+
)
|
|
956
|
+
except Exception as e:
|
|
957
|
+
logger.error("Failed to upload file to OSS: %s", str(e))
|
|
958
|
+
raise RuntimeError(
|
|
959
|
+
f"Failed to upload file to OSS: {str(e)}",
|
|
960
|
+
) from e
|
|
961
|
+
|
|
962
|
+
# Generate presigned URL (valid for 3 hours)
|
|
963
|
+
logger.info("Generating presigned URL for artifact")
|
|
964
|
+
try:
|
|
965
|
+
presign_result = oss_client.presign(
|
|
966
|
+
GetObjectRequest(bucket=bucket_name, key=object_key),
|
|
967
|
+
expires=datetime.timedelta(hours=3),
|
|
968
|
+
)
|
|
969
|
+
presigned_url = presign_result.url
|
|
970
|
+
logger.info("Presigned URL generated (valid for 3 hours)")
|
|
971
|
+
except Exception as e:
|
|
972
|
+
logger.error("Failed to generate presigned URL: %s", str(e))
|
|
973
|
+
raise RuntimeError(
|
|
974
|
+
f"Failed to generate presigned URL: {str(e)}",
|
|
975
|
+
) from e
|
|
976
|
+
|
|
977
|
+
return {
|
|
978
|
+
"bucket_name": bucket_name,
|
|
979
|
+
"object_key": object_key,
|
|
980
|
+
"presigned_url": presigned_url,
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
async def deploy_to_agentrun(
|
|
984
|
+
self,
|
|
985
|
+
agent_runtime_name: str,
|
|
986
|
+
oss_bucket_name: str,
|
|
987
|
+
oss_object_name: str,
|
|
988
|
+
agentrun_id: Optional[str] = None,
|
|
989
|
+
environment: Optional[Dict[str, str]] = None,
|
|
990
|
+
):
|
|
991
|
+
"""Deploy agent runtime and endpoint to AgentRun service.
|
|
992
|
+
|
|
993
|
+
Args:
|
|
994
|
+
agent_runtime_name: Name for the agent runtime.
|
|
995
|
+
oss_bucket_name: OSS bucket containing the code artifact.
|
|
996
|
+
oss_object_name: Object key of the code artifact in OSS.
|
|
997
|
+
agentrun_id: AgentRun ID to update deploy to.
|
|
998
|
+
environment: Environment variables for the runtime.
|
|
999
|
+
|
|
1000
|
+
Returns:
|
|
1001
|
+
Dictionary containing deployment results:
|
|
1002
|
+
- success: Whether deployment succeeded
|
|
1003
|
+
- agent_runtime_id: ID of the created runtime
|
|
1004
|
+
- agent_runtime_endpoint_id: ID of the created endpoint
|
|
1005
|
+
- agent_runtime_endpoint_name: Name of the endpoint
|
|
1006
|
+
- agent_runtime_public_endpoint_url: Public URL of the endpoint
|
|
1007
|
+
- status: Status of the deployment
|
|
1008
|
+
- request_id: Request ID for tracking
|
|
1009
|
+
"""
|
|
1010
|
+
try:
|
|
1011
|
+
logger.info("Starting AgentRun deployment: %s", agent_runtime_name)
|
|
1012
|
+
|
|
1013
|
+
if agentrun_id:
|
|
1014
|
+
# Update existing agent runtime
|
|
1015
|
+
logger.info(
|
|
1016
|
+
"Updating agent runtime: %s (ID: %s)",
|
|
1017
|
+
agent_runtime_name,
|
|
1018
|
+
agentrun_id,
|
|
1019
|
+
)
|
|
1020
|
+
update_agent_runtime_resp = await self.update_agent_runtime(
|
|
1021
|
+
agent_runtime_id=agentrun_id,
|
|
1022
|
+
artifact_type="Code",
|
|
1023
|
+
cpu=self.agentrun_config.cpu,
|
|
1024
|
+
memory=self.agentrun_config.memory,
|
|
1025
|
+
port=8090,
|
|
1026
|
+
code_configuration=CodeConfig(
|
|
1027
|
+
command=["python3", "/code/deploy_starter/main.py"],
|
|
1028
|
+
oss_bucket_name=oss_bucket_name,
|
|
1029
|
+
oss_object_name=oss_object_name,
|
|
1030
|
+
),
|
|
1031
|
+
description=f"AgentScope auto-generated runtime for {agent_runtime_name}",
|
|
1032
|
+
environment_variables=environment,
|
|
1033
|
+
)
|
|
1034
|
+
|
|
1035
|
+
# Verify runtime update
|
|
1036
|
+
if not update_agent_runtime_resp.get("success"):
|
|
1037
|
+
logger.error(
|
|
1038
|
+
"Failed to update agent runtime: %s",
|
|
1039
|
+
update_agent_runtime_resp.get("message"),
|
|
1040
|
+
)
|
|
1041
|
+
return update_agent_runtime_resp
|
|
1042
|
+
|
|
1043
|
+
logger.info(
|
|
1044
|
+
"Listing agent runtime endpoints to find '%s'",
|
|
1045
|
+
self.DEFAULT_ENDPOINT_NAME,
|
|
1046
|
+
)
|
|
1047
|
+
endpoint_id = None
|
|
1048
|
+
endpoint_name = None
|
|
1049
|
+
endpoint_url = None
|
|
1050
|
+
endpoint_status = None
|
|
1051
|
+
|
|
1052
|
+
try:
|
|
1053
|
+
list_endpoints_request = ListAgentRuntimeEndpointsRequest()
|
|
1054
|
+
list_endpoints_response = (
|
|
1055
|
+
await self.client.list_agent_runtime_endpoints_async(
|
|
1056
|
+
agentrun_id,
|
|
1057
|
+
list_endpoints_request,
|
|
1058
|
+
)
|
|
1059
|
+
)
|
|
1060
|
+
|
|
1061
|
+
if (
|
|
1062
|
+
list_endpoints_response.body
|
|
1063
|
+
and list_endpoints_response.body.code == "SUCCESS"
|
|
1064
|
+
and list_endpoints_response.body.data
|
|
1065
|
+
):
|
|
1066
|
+
endpoints = (
|
|
1067
|
+
list_endpoints_response.body.data.items
|
|
1068
|
+
if hasattr(
|
|
1069
|
+
list_endpoints_response.body.data,
|
|
1070
|
+
"items",
|
|
1071
|
+
)
|
|
1072
|
+
else []
|
|
1073
|
+
)
|
|
1074
|
+
|
|
1075
|
+
for endpoint in endpoints:
|
|
1076
|
+
if (
|
|
1077
|
+
hasattr(
|
|
1078
|
+
endpoint,
|
|
1079
|
+
"agent_runtime_endpoint_name",
|
|
1080
|
+
)
|
|
1081
|
+
and endpoint.agent_runtime_endpoint_name
|
|
1082
|
+
== self.DEFAULT_ENDPOINT_NAME
|
|
1083
|
+
):
|
|
1084
|
+
endpoint_id = (
|
|
1085
|
+
endpoint.agent_runtime_endpoint_id
|
|
1086
|
+
if hasattr(
|
|
1087
|
+
endpoint,
|
|
1088
|
+
"agent_runtime_endpoint_id",
|
|
1089
|
+
)
|
|
1090
|
+
else None
|
|
1091
|
+
)
|
|
1092
|
+
endpoint_name = (
|
|
1093
|
+
endpoint.agent_runtime_endpoint_name
|
|
1094
|
+
)
|
|
1095
|
+
endpoint_url = (
|
|
1096
|
+
endpoint.endpoint_public_url
|
|
1097
|
+
if hasattr(
|
|
1098
|
+
endpoint,
|
|
1099
|
+
"endpoint_public_url",
|
|
1100
|
+
)
|
|
1101
|
+
else None
|
|
1102
|
+
)
|
|
1103
|
+
endpoint_status = (
|
|
1104
|
+
endpoint.status
|
|
1105
|
+
if hasattr(
|
|
1106
|
+
endpoint,
|
|
1107
|
+
"status",
|
|
1108
|
+
)
|
|
1109
|
+
else None
|
|
1110
|
+
)
|
|
1111
|
+
|
|
1112
|
+
logger.info(
|
|
1113
|
+
"Found endpoint (ID: %s, Name: %s, URL: %s, Status: %s)",
|
|
1114
|
+
endpoint_id,
|
|
1115
|
+
endpoint_name,
|
|
1116
|
+
endpoint_url,
|
|
1117
|
+
endpoint_status,
|
|
1118
|
+
)
|
|
1119
|
+
break
|
|
1120
|
+
|
|
1121
|
+
if not endpoint_id:
|
|
1122
|
+
logger.warning(
|
|
1123
|
+
"Endpoint with name '%s' not found in list",
|
|
1124
|
+
self.DEFAULT_ENDPOINT_NAME,
|
|
1125
|
+
)
|
|
1126
|
+
else:
|
|
1127
|
+
logger.warning(
|
|
1128
|
+
"Failed to list agent runtime endpoints: %s",
|
|
1129
|
+
list_endpoints_response.body.message
|
|
1130
|
+
if list_endpoints_response.body
|
|
1131
|
+
else "Unknown error",
|
|
1132
|
+
)
|
|
1133
|
+
except Exception as e:
|
|
1134
|
+
logger.warning(
|
|
1135
|
+
"Exception occurred while listing endpoints: %s",
|
|
1136
|
+
str(e),
|
|
1137
|
+
)
|
|
1138
|
+
|
|
1139
|
+
result = {
|
|
1140
|
+
"success": True,
|
|
1141
|
+
"agent_runtime_id": agentrun_id,
|
|
1142
|
+
"agent_runtime_endpoint_id": endpoint_id,
|
|
1143
|
+
"agent_runtime_endpoint_name": endpoint_name,
|
|
1144
|
+
"agent_runtime_public_endpoint_url": endpoint_url,
|
|
1145
|
+
"status": endpoint_status
|
|
1146
|
+
or update_agent_runtime_resp.get("status"),
|
|
1147
|
+
"request_id": update_agent_runtime_resp.get("request_id"),
|
|
1148
|
+
"deploy_id": self.deploy_id
|
|
1149
|
+
if hasattr(self, "deploy_id")
|
|
1150
|
+
else None,
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
return result
|
|
1154
|
+
|
|
1155
|
+
# Create new agent runtime
|
|
1156
|
+
logger.info("Creating agent runtime: %s", agent_runtime_name)
|
|
1157
|
+
create_agent_runtime_resp = await self.create_agent_runtime(
|
|
1158
|
+
agent_runtime_name=agent_runtime_name,
|
|
1159
|
+
artifact_type="Code",
|
|
1160
|
+
cpu=self.agentrun_config.cpu,
|
|
1161
|
+
memory=self.agentrun_config.memory,
|
|
1162
|
+
port=8090,
|
|
1163
|
+
code_configuration=CodeConfig(
|
|
1164
|
+
command=["python3", "/code/deploy_starter/main.py"],
|
|
1165
|
+
oss_bucket_name=oss_bucket_name,
|
|
1166
|
+
oss_object_name=oss_object_name,
|
|
1167
|
+
),
|
|
1168
|
+
description=f"AgentScope auto-generated runtime for {agent_runtime_name}",
|
|
1169
|
+
environment_variables=environment,
|
|
1170
|
+
execution_role_arn=self.agentrun_config.execution_role_arn,
|
|
1171
|
+
log_configuration=self.agentrun_config.log_config,
|
|
1172
|
+
network_configuration=self.agentrun_config.network_config,
|
|
1173
|
+
session_concurrency_limit_per_instance=self.agentrun_config.session_concurrency_limit,
|
|
1174
|
+
session_idle_timeout_seconds=self.agentrun_config.session_idle_timeout_seconds,
|
|
1175
|
+
)
|
|
1176
|
+
|
|
1177
|
+
# Verify runtime creation
|
|
1178
|
+
if not create_agent_runtime_resp.get("success"):
|
|
1179
|
+
logger.error(
|
|
1180
|
+
"Failed to create agent runtime: %s",
|
|
1181
|
+
create_agent_runtime_resp.get("message"),
|
|
1182
|
+
)
|
|
1183
|
+
return create_agent_runtime_resp
|
|
1184
|
+
|
|
1185
|
+
agent_runtime_id = create_agent_runtime_resp["agent_runtime_id"]
|
|
1186
|
+
logger.info(
|
|
1187
|
+
"Agent runtime created successfully (ID: %s)",
|
|
1188
|
+
agent_runtime_id,
|
|
1189
|
+
)
|
|
1190
|
+
|
|
1191
|
+
# Step 2: Create agent runtime endpoint
|
|
1192
|
+
logger.info("Creating agent runtime endpoint")
|
|
1193
|
+
endpoint_config = EndpointConfig(
|
|
1194
|
+
agent_runtime_endpoint_name=self.DEFAULT_ENDPOINT_NAME,
|
|
1195
|
+
target_version=self.LATEST_VERSION,
|
|
1196
|
+
description=f"AgentScope auto-generated endpoint for {agent_runtime_name}",
|
|
1197
|
+
)
|
|
1198
|
+
|
|
1199
|
+
create_agent_runtime_endpoint_resp = (
|
|
1200
|
+
await self.create_agent_runtime_endpoint(
|
|
1201
|
+
agent_runtime_id=agent_runtime_id,
|
|
1202
|
+
endpoint_config=endpoint_config,
|
|
1203
|
+
)
|
|
1204
|
+
)
|
|
1205
|
+
|
|
1206
|
+
# Verify endpoint creation
|
|
1207
|
+
if not create_agent_runtime_endpoint_resp.get("success"):
|
|
1208
|
+
logger.error(
|
|
1209
|
+
"Failed to create agent runtime endpoint: %s",
|
|
1210
|
+
create_agent_runtime_endpoint_resp.get("message"),
|
|
1211
|
+
)
|
|
1212
|
+
return create_agent_runtime_endpoint_resp
|
|
1213
|
+
|
|
1214
|
+
endpoint_id = create_agent_runtime_endpoint_resp.get(
|
|
1215
|
+
"agent_runtime_endpoint_id",
|
|
1216
|
+
)
|
|
1217
|
+
logger.info(
|
|
1218
|
+
"Agent runtime endpoint created successfully (ID: %s)",
|
|
1219
|
+
endpoint_id,
|
|
1220
|
+
)
|
|
1221
|
+
|
|
1222
|
+
# Return success result
|
|
1223
|
+
logger.info(
|
|
1224
|
+
"AgentRun deployment completed successfully: %s",
|
|
1225
|
+
agent_runtime_name,
|
|
1226
|
+
)
|
|
1227
|
+
result = {
|
|
1228
|
+
"success": True,
|
|
1229
|
+
"agent_runtime_id": agent_runtime_id,
|
|
1230
|
+
"agent_runtime_endpoint_id": create_agent_runtime_endpoint_resp.get(
|
|
1231
|
+
"agent_runtime_endpoint_id",
|
|
1232
|
+
),
|
|
1233
|
+
"agent_runtime_endpoint_name": create_agent_runtime_endpoint_resp.get(
|
|
1234
|
+
"agent_runtime_endpoint_name",
|
|
1235
|
+
),
|
|
1236
|
+
"agent_runtime_public_endpoint_url": create_agent_runtime_endpoint_resp.get(
|
|
1237
|
+
"agent_runtime_public_endpoint_url",
|
|
1238
|
+
),
|
|
1239
|
+
"status": create_agent_runtime_endpoint_resp.get("status"),
|
|
1240
|
+
"request_id": create_agent_runtime_endpoint_resp.get(
|
|
1241
|
+
"request_id",
|
|
1242
|
+
),
|
|
1243
|
+
"deploy_id": self.deploy_id
|
|
1244
|
+
if hasattr(self, "deploy_id")
|
|
1245
|
+
else None,
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
return result
|
|
1249
|
+
|
|
1250
|
+
except Exception as e:
|
|
1251
|
+
logger.error("Exception during AgentRun deployment: %s", str(e))
|
|
1252
|
+
return {
|
|
1253
|
+
"success": False,
|
|
1254
|
+
"error": str(e),
|
|
1255
|
+
"message": f"Exception during AgentRun deployment: {str(e)}",
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1258
|
+
async def delete(self, agent_runtime_id: str):
|
|
1259
|
+
"""
|
|
1260
|
+
Delete an agent runtime on AgentRun.
|
|
1261
|
+
|
|
1262
|
+
Args:
|
|
1263
|
+
agent_runtime_id (str): The ID of the agent runtime to delete.
|
|
1264
|
+
|
|
1265
|
+
Returns:
|
|
1266
|
+
Dict[str, Any]: A dictionary containing the delete result with:
|
|
1267
|
+
- success (bool): Whether the operation was successful
|
|
1268
|
+
- message (str): Status message
|
|
1269
|
+
- agent_runtime_id (str): The ID of the deleted agent runtime
|
|
1270
|
+
- status (str): The status of the agent runtime
|
|
1271
|
+
- status_reason (str): The reason for the status
|
|
1272
|
+
- request_id (str): The request ID for tracking
|
|
1273
|
+
"""
|
|
1274
|
+
try:
|
|
1275
|
+
logger.info(
|
|
1276
|
+
f"Deleting agent runtime with ID: {agent_runtime_id}",
|
|
1277
|
+
)
|
|
1278
|
+
|
|
1279
|
+
# Call the SDK method
|
|
1280
|
+
response = await self.client.delete_agent_runtime_async(
|
|
1281
|
+
agent_runtime_id,
|
|
1282
|
+
)
|
|
1283
|
+
|
|
1284
|
+
# Check if the response is successful
|
|
1285
|
+
if response.body and response.body.code == "SUCCESS":
|
|
1286
|
+
logger.info(
|
|
1287
|
+
"Agent runtime deletion initiated (ID: %s)",
|
|
1288
|
+
agent_runtime_id,
|
|
1289
|
+
)
|
|
1290
|
+
|
|
1291
|
+
# Poll for status
|
|
1292
|
+
status_result = None
|
|
1293
|
+
status_reason = None
|
|
1294
|
+
if agent_runtime_id:
|
|
1295
|
+
logger.info(
|
|
1296
|
+
"Polling deletion status for agent runtime: %s",
|
|
1297
|
+
agent_runtime_id,
|
|
1298
|
+
)
|
|
1299
|
+
poll_status = await self._poll_agent_runtime_status(
|
|
1300
|
+
agent_runtime_id,
|
|
1301
|
+
)
|
|
1302
|
+
if isinstance(poll_status, dict):
|
|
1303
|
+
status_result = poll_status.get("status")
|
|
1304
|
+
status_reason = poll_status.get("status_reason")
|
|
1305
|
+
logger.info(
|
|
1306
|
+
"Agent runtime deletion status: %s",
|
|
1307
|
+
status_result,
|
|
1308
|
+
)
|
|
1309
|
+
|
|
1310
|
+
# Return a dictionary with relevant information from the response
|
|
1311
|
+
return {
|
|
1312
|
+
"success": True,
|
|
1313
|
+
"message": "Agent runtime deletion initiated successfully",
|
|
1314
|
+
"agent_runtime_id": agent_runtime_id,
|
|
1315
|
+
"status": status_result,
|
|
1316
|
+
"status_reason": status_reason,
|
|
1317
|
+
"request_id": response.body.request_id,
|
|
1318
|
+
}
|
|
1319
|
+
else:
|
|
1320
|
+
logger.error("Failed to delete agent runtime")
|
|
1321
|
+
# Return error information if the request was not successful
|
|
1322
|
+
return {
|
|
1323
|
+
"success": False,
|
|
1324
|
+
"code": response.body.code if response.body else None,
|
|
1325
|
+
"message": "Failed to delete agent runtime",
|
|
1326
|
+
"request_id": response.body.request_id
|
|
1327
|
+
if response.body
|
|
1328
|
+
else None,
|
|
1329
|
+
}
|
|
1330
|
+
except Exception as e:
|
|
1331
|
+
logger.error(
|
|
1332
|
+
f"Exception occurred while deleting agent runtime: {str(e)}",
|
|
1333
|
+
)
|
|
1334
|
+
# Return error information if an exception occurred
|
|
1335
|
+
return {
|
|
1336
|
+
"success": False,
|
|
1337
|
+
"error": str(e),
|
|
1338
|
+
"message": f"Exception occurred while deleting agent runtime: {str(e)}",
|
|
1339
|
+
}
|
|
1340
|
+
|
|
1341
|
+
async def get_agent_runtime(
|
|
1342
|
+
self,
|
|
1343
|
+
agent_runtime_id: str,
|
|
1344
|
+
agent_runtime_version: str = None,
|
|
1345
|
+
):
|
|
1346
|
+
"""
|
|
1347
|
+
Get agent runtime details.
|
|
1348
|
+
|
|
1349
|
+
Args:
|
|
1350
|
+
agent_runtime_id (str): The ID of the agent runtime.
|
|
1351
|
+
agent_runtime_version (str, optional): The version of the agent runtime.
|
|
1352
|
+
|
|
1353
|
+
Returns:
|
|
1354
|
+
Dict[str, Any]: A dictionary containing the agent runtime details with:
|
|
1355
|
+
- success (bool): Whether the operation was successful
|
|
1356
|
+
- data (dict): The agent runtime data
|
|
1357
|
+
- request_id (str): The request ID for tracking
|
|
1358
|
+
"""
|
|
1359
|
+
try:
|
|
1360
|
+
logger.info(
|
|
1361
|
+
f"Getting agent runtime details for ID: {agent_runtime_id}",
|
|
1362
|
+
)
|
|
1363
|
+
|
|
1364
|
+
# Create the request object
|
|
1365
|
+
request = GetAgentRuntimeRequest(
|
|
1366
|
+
agent_runtime_version=agent_runtime_version,
|
|
1367
|
+
)
|
|
1368
|
+
|
|
1369
|
+
# Call the SDK method
|
|
1370
|
+
response = await self.client.get_agent_runtime_async(
|
|
1371
|
+
agent_runtime_id,
|
|
1372
|
+
request,
|
|
1373
|
+
)
|
|
1374
|
+
|
|
1375
|
+
# Check if the response is successful
|
|
1376
|
+
if response.body and response.body.code == "SUCCESS":
|
|
1377
|
+
logger.info(
|
|
1378
|
+
"Agent runtime details retrieved successfully (ID: %s)",
|
|
1379
|
+
agent_runtime_id,
|
|
1380
|
+
)
|
|
1381
|
+
# Return the agent runtime data as a dictionary
|
|
1382
|
+
agent_runtime_data = (
|
|
1383
|
+
response.body.data.to_map() if response.body.data else {}
|
|
1384
|
+
)
|
|
1385
|
+
return {
|
|
1386
|
+
"success": True,
|
|
1387
|
+
"data": agent_runtime_data,
|
|
1388
|
+
"request_id": response.body.request_id,
|
|
1389
|
+
}
|
|
1390
|
+
else:
|
|
1391
|
+
logger.error("Failed to get agent runtime details")
|
|
1392
|
+
# Return error information if the request was not successful
|
|
1393
|
+
return {
|
|
1394
|
+
"success": False,
|
|
1395
|
+
"code": response.body.code if response.body else None,
|
|
1396
|
+
"message": "Failed to get agent runtime details",
|
|
1397
|
+
"request_id": response.body.request_id
|
|
1398
|
+
if response.body
|
|
1399
|
+
else None,
|
|
1400
|
+
}
|
|
1401
|
+
except Exception as e:
|
|
1402
|
+
logger.error(
|
|
1403
|
+
f"Exception occurred while getting agent runtime: {str(e)}",
|
|
1404
|
+
)
|
|
1405
|
+
# Return error information if an exception occurred
|
|
1406
|
+
return {
|
|
1407
|
+
"success": False,
|
|
1408
|
+
"error": str(e),
|
|
1409
|
+
"message": f"Exception occurred while getting agent runtime: {str(e)}",
|
|
1410
|
+
}
|
|
1411
|
+
|
|
1412
|
+
async def _get_agent_runtime_status(
|
|
1413
|
+
self,
|
|
1414
|
+
agent_runtime_id: str,
|
|
1415
|
+
agent_runtime_version: str = None,
|
|
1416
|
+
):
|
|
1417
|
+
"""
|
|
1418
|
+
Get agent runtime status.
|
|
1419
|
+
|
|
1420
|
+
Args:
|
|
1421
|
+
agent_runtime_id (str): The ID of the agent runtime.
|
|
1422
|
+
agent_runtime_version (str, optional): The version of the agent runtime.
|
|
1423
|
+
|
|
1424
|
+
Returns:
|
|
1425
|
+
Dict[str, Any]: A dictionary containing the agent runtime status with:
|
|
1426
|
+
- success (bool): Whether the operation was successful
|
|
1427
|
+
- status (str): The status of the agent runtime
|
|
1428
|
+
- status_reason (str): The reason for the status
|
|
1429
|
+
- request_id (str): The request ID for tracking
|
|
1430
|
+
"""
|
|
1431
|
+
try:
|
|
1432
|
+
logger.debug(
|
|
1433
|
+
f"Getting agent runtime status for ID: {agent_runtime_id}",
|
|
1434
|
+
)
|
|
1435
|
+
|
|
1436
|
+
# Create the request object
|
|
1437
|
+
request = GetAgentRuntimeRequest(
|
|
1438
|
+
agent_runtime_version=agent_runtime_version,
|
|
1439
|
+
)
|
|
1440
|
+
|
|
1441
|
+
# Call the SDK method
|
|
1442
|
+
response = await self.client.get_agent_runtime_async(
|
|
1443
|
+
agent_runtime_id,
|
|
1444
|
+
request,
|
|
1445
|
+
)
|
|
1446
|
+
|
|
1447
|
+
# Check if the response is successful
|
|
1448
|
+
if (
|
|
1449
|
+
response.body
|
|
1450
|
+
and response.body.code == "SUCCESS"
|
|
1451
|
+
and response.body.data
|
|
1452
|
+
):
|
|
1453
|
+
status = (
|
|
1454
|
+
response.body.data.status
|
|
1455
|
+
if hasattr(response.body.data, "status")
|
|
1456
|
+
else None
|
|
1457
|
+
)
|
|
1458
|
+
logger.debug(
|
|
1459
|
+
f"Agent runtime status for ID {agent_runtime_id}: {status}",
|
|
1460
|
+
)
|
|
1461
|
+
# Return the status from the agent runtime data
|
|
1462
|
+
return {
|
|
1463
|
+
"success": True,
|
|
1464
|
+
"status": status,
|
|
1465
|
+
"status_reason": response.body.data.status_reason
|
|
1466
|
+
if hasattr(response.body.data, "status_reason")
|
|
1467
|
+
else None,
|
|
1468
|
+
"request_id": response.body.request_id,
|
|
1469
|
+
}
|
|
1470
|
+
else:
|
|
1471
|
+
logger.debug("Failed to get agent runtime status")
|
|
1472
|
+
# Return error information if the request was not successful
|
|
1473
|
+
return {
|
|
1474
|
+
"success": False,
|
|
1475
|
+
"code": response.body.code if response.body else None,
|
|
1476
|
+
"message": "Failed to get agent runtime status",
|
|
1477
|
+
"request_id": response.body.request_id
|
|
1478
|
+
if response.body
|
|
1479
|
+
else None,
|
|
1480
|
+
}
|
|
1481
|
+
except Exception as e:
|
|
1482
|
+
logger.debug(
|
|
1483
|
+
f"Exception occurred while getting agent runtime status: {str(e)}",
|
|
1484
|
+
)
|
|
1485
|
+
# Return error information if an exception occurred
|
|
1486
|
+
return {
|
|
1487
|
+
"success": False,
|
|
1488
|
+
"error": str(e),
|
|
1489
|
+
"message": f"Exception occurred while getting agent runtime status: {str(e)}",
|
|
1490
|
+
}
|
|
1491
|
+
|
|
1492
|
+
async def _get_agent_runtime_endpoint_status(
|
|
1493
|
+
self,
|
|
1494
|
+
agent_runtime_id: str,
|
|
1495
|
+
agent_runtime_endpoint_id: str,
|
|
1496
|
+
):
|
|
1497
|
+
"""
|
|
1498
|
+
Get agent runtime endpoint status.
|
|
1499
|
+
|
|
1500
|
+
Args:
|
|
1501
|
+
agent_runtime_id (str): The ID of the agent runtime.
|
|
1502
|
+
agent_runtime_endpoint_id (str): The ID of the agent runtime endpoint.
|
|
1503
|
+
|
|
1504
|
+
Returns:
|
|
1505
|
+
Dict[str, Any]: A dictionary containing the agent runtime endpoint status with:
|
|
1506
|
+
- success (bool): Whether the operation was successful
|
|
1507
|
+
- status (str): The status of the agent runtime endpoint
|
|
1508
|
+
- status_reason (str): The reason for the status
|
|
1509
|
+
- request_id (str): The request ID for tracking
|
|
1510
|
+
"""
|
|
1511
|
+
try:
|
|
1512
|
+
logger.debug(
|
|
1513
|
+
f"Getting agent runtime endpoint status for ID: {agent_runtime_endpoint_id}",
|
|
1514
|
+
)
|
|
1515
|
+
|
|
1516
|
+
# Call the SDK method
|
|
1517
|
+
response = await self.client.get_agent_runtime_endpoint_async(
|
|
1518
|
+
agent_runtime_id,
|
|
1519
|
+
agent_runtime_endpoint_id,
|
|
1520
|
+
)
|
|
1521
|
+
|
|
1522
|
+
# Check if the response is successful
|
|
1523
|
+
if (
|
|
1524
|
+
response.body
|
|
1525
|
+
and response.body.code == "SUCCESS"
|
|
1526
|
+
and response.body.data
|
|
1527
|
+
):
|
|
1528
|
+
status = (
|
|
1529
|
+
response.body.data.status
|
|
1530
|
+
if hasattr(response.body.data, "status")
|
|
1531
|
+
else None
|
|
1532
|
+
)
|
|
1533
|
+
logger.debug(
|
|
1534
|
+
f"Agent runtime endpoint status for ID {agent_runtime_endpoint_id}: {status}",
|
|
1535
|
+
)
|
|
1536
|
+
# Return the status from the agent runtime endpoint data
|
|
1537
|
+
return {
|
|
1538
|
+
"success": True,
|
|
1539
|
+
"status": status,
|
|
1540
|
+
"status_reason": response.body.data.status_reason
|
|
1541
|
+
if hasattr(response.body.data, "status_reason")
|
|
1542
|
+
else None,
|
|
1543
|
+
"request_id": response.body.request_id,
|
|
1544
|
+
}
|
|
1545
|
+
else:
|
|
1546
|
+
logger.debug(
|
|
1547
|
+
"Failed to get agent runtime endpoint status",
|
|
1548
|
+
)
|
|
1549
|
+
# Return error information if the request was not successful
|
|
1550
|
+
return {
|
|
1551
|
+
"success": False,
|
|
1552
|
+
"code": response.body.code if response.body else None,
|
|
1553
|
+
"message": "Failed to get agent runtime endpoint status",
|
|
1554
|
+
"request_id": response.body.request_id
|
|
1555
|
+
if response.body
|
|
1556
|
+
else None,
|
|
1557
|
+
}
|
|
1558
|
+
except Exception as e:
|
|
1559
|
+
logger.debug(
|
|
1560
|
+
f"Exception occurred while getting agent runtime endpoint status: {str(e)}",
|
|
1561
|
+
)
|
|
1562
|
+
# Return error information if an exception occurred
|
|
1563
|
+
return {
|
|
1564
|
+
"success": False,
|
|
1565
|
+
"error": str(e),
|
|
1566
|
+
"message": f"Exception occurred while getting agent runtime endpoint status: {str(e)}",
|
|
1567
|
+
}
|
|
1568
|
+
|
|
1569
|
+
async def _poll_agent_runtime_status(
|
|
1570
|
+
self,
|
|
1571
|
+
agent_runtime_id: str,
|
|
1572
|
+
agent_runtime_version: str = None,
|
|
1573
|
+
) -> Dict[str, Any]:
|
|
1574
|
+
"""
|
|
1575
|
+
Poll agent runtime status until a terminal state is reached or max attempts exceeded.
|
|
1576
|
+
|
|
1577
|
+
Args:
|
|
1578
|
+
agent_runtime_id (str): The ID of the agent runtime.
|
|
1579
|
+
agent_runtime_version (str, optional): The version of the agent runtime.
|
|
1580
|
+
|
|
1581
|
+
Returns:
|
|
1582
|
+
Dict[str, Any]: A dictionary containing the final agent runtime status with:
|
|
1583
|
+
- success (bool): Whether the operation was successful
|
|
1584
|
+
- status (str): The final status of the agent runtime
|
|
1585
|
+
- status_reason (str): The reason for the status
|
|
1586
|
+
- request_id (str): The request ID for tracking
|
|
1587
|
+
"""
|
|
1588
|
+
# Terminal states that indicate the end of polling for agent runtimes
|
|
1589
|
+
terminal_states = {
|
|
1590
|
+
"CREATE_FAILED",
|
|
1591
|
+
"UPDATE_FAILED",
|
|
1592
|
+
"READY",
|
|
1593
|
+
"ACTIVE",
|
|
1594
|
+
"FAILED",
|
|
1595
|
+
"DELETING",
|
|
1596
|
+
}
|
|
1597
|
+
|
|
1598
|
+
# Polling configuration
|
|
1599
|
+
max_attempts = self._get_agent_runtime_status_max_attempts
|
|
1600
|
+
interval_seconds = self._get_agent_runtime_status_interval
|
|
1601
|
+
|
|
1602
|
+
logger.info("Polling agent runtime status (ID: %s)", agent_runtime_id)
|
|
1603
|
+
|
|
1604
|
+
for attempt in range(1, max_attempts + 1):
|
|
1605
|
+
# Get current status
|
|
1606
|
+
status_response = await self._get_agent_runtime_status(
|
|
1607
|
+
agent_runtime_id,
|
|
1608
|
+
agent_runtime_version,
|
|
1609
|
+
)
|
|
1610
|
+
|
|
1611
|
+
# Check if the request was successful
|
|
1612
|
+
if not status_response.get("success"):
|
|
1613
|
+
logger.warning(
|
|
1614
|
+
"Status poll attempt %d/%d failed: %s",
|
|
1615
|
+
attempt,
|
|
1616
|
+
max_attempts,
|
|
1617
|
+
status_response.get("message"),
|
|
1618
|
+
)
|
|
1619
|
+
# Wait before next attempt unless this is the last attempt
|
|
1620
|
+
if attempt < max_attempts:
|
|
1621
|
+
await asyncio.sleep(interval_seconds)
|
|
1622
|
+
continue
|
|
1623
|
+
|
|
1624
|
+
# Extract status information
|
|
1625
|
+
current_status = status_response.get("status")
|
|
1626
|
+
status_reason = status_response.get("status_reason")
|
|
1627
|
+
|
|
1628
|
+
# Log current status
|
|
1629
|
+
logger.debug(
|
|
1630
|
+
"Status poll attempt %d/%d: %s",
|
|
1631
|
+
attempt,
|
|
1632
|
+
max_attempts,
|
|
1633
|
+
current_status,
|
|
1634
|
+
)
|
|
1635
|
+
if status_reason:
|
|
1636
|
+
logger.debug("Status reason: %s", status_reason)
|
|
1637
|
+
|
|
1638
|
+
# Check if we've reached a terminal state
|
|
1639
|
+
if current_status in terminal_states:
|
|
1640
|
+
logger.info(
|
|
1641
|
+
"Agent runtime reached terminal state '%s' (after %d attempts)",
|
|
1642
|
+
current_status,
|
|
1643
|
+
attempt,
|
|
1644
|
+
)
|
|
1645
|
+
return status_response
|
|
1646
|
+
|
|
1647
|
+
# Wait before next attempt unless this is the last attempt
|
|
1648
|
+
if attempt < max_attempts:
|
|
1649
|
+
await asyncio.sleep(interval_seconds)
|
|
1650
|
+
|
|
1651
|
+
# If we've exhausted all attempts without reaching a terminal state
|
|
1652
|
+
logger.warning(
|
|
1653
|
+
"Status polling exceeded maximum attempts (%d) without reaching terminal state",
|
|
1654
|
+
max_attempts,
|
|
1655
|
+
)
|
|
1656
|
+
return await self._get_agent_runtime_status(
|
|
1657
|
+
agent_runtime_id,
|
|
1658
|
+
agent_runtime_version,
|
|
1659
|
+
)
|
|
1660
|
+
|
|
1661
|
+
async def _poll_agent_runtime_endpoint_status(
|
|
1662
|
+
self,
|
|
1663
|
+
agent_runtime_id: str,
|
|
1664
|
+
agent_runtime_endpoint_id: str,
|
|
1665
|
+
) -> Dict[str, Any]:
|
|
1666
|
+
"""
|
|
1667
|
+
Poll agent runtime endpoint status until a terminal state is reached or max attempts exceeded.
|
|
1668
|
+
|
|
1669
|
+
Args:
|
|
1670
|
+
agent_runtime_id (str): The ID of the agent runtime.
|
|
1671
|
+
agent_runtime_endpoint_id (str): The ID of the agent runtime endpoint.
|
|
1672
|
+
|
|
1673
|
+
Returns:
|
|
1674
|
+
Dict[str, Any]: A dictionary containing the final agent runtime endpoint status with:
|
|
1675
|
+
- success (bool): Whether the operation was successful
|
|
1676
|
+
- status (str): The final status of the agent runtime endpoint
|
|
1677
|
+
- status_reason (str): The reason for the status
|
|
1678
|
+
- request_id (str): The request ID for tracking
|
|
1679
|
+
"""
|
|
1680
|
+
# Terminal states that indicate the end of polling for endpoints
|
|
1681
|
+
terminal_states = {
|
|
1682
|
+
"CREATE_FAILED",
|
|
1683
|
+
"UPDATE_FAILED",
|
|
1684
|
+
"READY",
|
|
1685
|
+
"ACTIVE",
|
|
1686
|
+
"FAILED",
|
|
1687
|
+
"DELETING",
|
|
1688
|
+
}
|
|
1689
|
+
|
|
1690
|
+
# Polling configuration
|
|
1691
|
+
max_attempts = self._get_agent_runtime_status_max_attempts
|
|
1692
|
+
interval_seconds = self._get_agent_runtime_status_interval
|
|
1693
|
+
|
|
1694
|
+
logger.info(
|
|
1695
|
+
"Polling agent runtime endpoint status (ID: %s)",
|
|
1696
|
+
agent_runtime_endpoint_id,
|
|
1697
|
+
)
|
|
1698
|
+
|
|
1699
|
+
for attempt in range(1, max_attempts + 1):
|
|
1700
|
+
# Get current status
|
|
1701
|
+
status_response = await self._get_agent_runtime_endpoint_status(
|
|
1702
|
+
agent_runtime_id,
|
|
1703
|
+
agent_runtime_endpoint_id,
|
|
1704
|
+
)
|
|
1705
|
+
|
|
1706
|
+
# Check if the request was successful
|
|
1707
|
+
if not status_response.get("success"):
|
|
1708
|
+
logger.warning(
|
|
1709
|
+
"Endpoint status poll attempt %d/%d failed: %s",
|
|
1710
|
+
attempt,
|
|
1711
|
+
max_attempts,
|
|
1712
|
+
status_response.get("message"),
|
|
1713
|
+
)
|
|
1714
|
+
# Wait before next attempt unless this is the last attempt
|
|
1715
|
+
if attempt < max_attempts:
|
|
1716
|
+
await asyncio.sleep(interval_seconds)
|
|
1717
|
+
continue
|
|
1718
|
+
|
|
1719
|
+
# Extract status information
|
|
1720
|
+
current_status = status_response.get("status")
|
|
1721
|
+
status_reason = status_response.get("status_reason")
|
|
1722
|
+
|
|
1723
|
+
# Log current status
|
|
1724
|
+
logger.debug(
|
|
1725
|
+
"Endpoint status poll attempt %d/%d: %s",
|
|
1726
|
+
attempt,
|
|
1727
|
+
max_attempts,
|
|
1728
|
+
current_status,
|
|
1729
|
+
)
|
|
1730
|
+
if status_reason:
|
|
1731
|
+
logger.debug("Status reason: %s", status_reason)
|
|
1732
|
+
|
|
1733
|
+
# Check if we've reached a terminal state
|
|
1734
|
+
if current_status in terminal_states:
|
|
1735
|
+
logger.info(
|
|
1736
|
+
"Endpoint reached terminal state '%s' (after %d attempts)",
|
|
1737
|
+
current_status,
|
|
1738
|
+
attempt,
|
|
1739
|
+
)
|
|
1740
|
+
return status_response
|
|
1741
|
+
|
|
1742
|
+
# Wait before next attempt unless this is the last attempt
|
|
1743
|
+
if attempt < max_attempts:
|
|
1744
|
+
await asyncio.sleep(interval_seconds)
|
|
1745
|
+
|
|
1746
|
+
# If we've exhausted all attempts without reaching a terminal state
|
|
1747
|
+
logger.warning(
|
|
1748
|
+
"Endpoint status polling exceeded maximum attempts (%d) without reaching terminal state",
|
|
1749
|
+
max_attempts,
|
|
1750
|
+
)
|
|
1751
|
+
return await self._get_agent_runtime_endpoint_status(
|
|
1752
|
+
agent_runtime_id,
|
|
1753
|
+
agent_runtime_endpoint_id,
|
|
1754
|
+
)
|
|
1755
|
+
|
|
1756
|
+
async def create_agent_runtime(
|
|
1757
|
+
self,
|
|
1758
|
+
agent_runtime_name: str,
|
|
1759
|
+
artifact_type: str,
|
|
1760
|
+
cpu: float,
|
|
1761
|
+
memory: int,
|
|
1762
|
+
port: int,
|
|
1763
|
+
code_configuration: Optional[CodeConfig] = None,
|
|
1764
|
+
description: Optional[str] = None,
|
|
1765
|
+
environment_variables: Optional[Dict[str, str]] = None,
|
|
1766
|
+
execution_role_arn: Optional[str] = None,
|
|
1767
|
+
log_configuration: Optional[LogConfig] = None,
|
|
1768
|
+
network_configuration: Optional[NetworkConfig] = None,
|
|
1769
|
+
session_concurrency_limit_per_instance: Optional[int] = None,
|
|
1770
|
+
session_idle_timeout_seconds: Optional[int] = None,
|
|
1771
|
+
):
|
|
1772
|
+
"""
|
|
1773
|
+
Create an agent runtime on AgentRun.
|
|
1774
|
+
|
|
1775
|
+
Args:
|
|
1776
|
+
agent_runtime_name (str): The name of the agent runtime.
|
|
1777
|
+
artifact_type (str): The type of the artifact.
|
|
1778
|
+
cpu (float): The CPU allocated to the runtime.
|
|
1779
|
+
memory (int): The memory allocated to the runtime.
|
|
1780
|
+
port (int): The port on which the runtime will listen.
|
|
1781
|
+
code_configuration (Optional[CodeConfig]): Configuration for code-based runtimes.
|
|
1782
|
+
description (Optional[str]): Description of the agent runtime.
|
|
1783
|
+
environment_variables (Optional[Dict[str, str]]): Environment variables for the runtime.
|
|
1784
|
+
execution_role_arn (Optional[str]): The execution role ARN for accessing cloud services.
|
|
1785
|
+
log_configuration (Optional[LogConfig]): Configuration for logging.
|
|
1786
|
+
network_configuration (Optional[NetworkConfig]): Network configuration for the runtime, including:
|
|
1787
|
+
- network_mode: The network mode for the runtime
|
|
1788
|
+
- security_group_id: The security group ID for the runtime
|
|
1789
|
+
- vpc_id: The VPC ID for the runtime
|
|
1790
|
+
- vswitch_ids: List of vswitch IDs for the runtime
|
|
1791
|
+
session_concurrency_limit_per_instance (Optional[int]): Maximum concurrent sessions per instance.
|
|
1792
|
+
session_idle_timeout_seconds (Optional[int]): Maximum idle timeout for sessions.
|
|
1793
|
+
|
|
1794
|
+
Returns:
|
|
1795
|
+
Dict[str, Any]: A dictionary containing the creation result with:
|
|
1796
|
+
- success (bool): Whether the operation was successful
|
|
1797
|
+
- agent_runtime_id (str): The ID of the created agent runtime
|
|
1798
|
+
- status (str): The status of the agent runtime
|
|
1799
|
+
- status_reason (str): The reason for the status
|
|
1800
|
+
- request_id (str): The request ID for tracking
|
|
1801
|
+
"""
|
|
1802
|
+
try:
|
|
1803
|
+
logger.info(f"Creating agent runtime: {agent_runtime_name}")
|
|
1804
|
+
|
|
1805
|
+
# Adapt custom configurations to SDK configurations
|
|
1806
|
+
sdk_code_config = self._adapt_code_config(code_configuration)
|
|
1807
|
+
sdk_log_config = self._adapt_log_config(log_configuration)
|
|
1808
|
+
sdk_network_config = self._adapt_network_config(
|
|
1809
|
+
network_configuration,
|
|
1810
|
+
)
|
|
1811
|
+
|
|
1812
|
+
# Create the input object with all provided parameters
|
|
1813
|
+
input_data = CreateAgentRuntimeInput(
|
|
1814
|
+
agent_runtime_name=agent_runtime_name,
|
|
1815
|
+
artifact_type=artifact_type,
|
|
1816
|
+
cpu=cpu,
|
|
1817
|
+
memory=memory,
|
|
1818
|
+
port=port,
|
|
1819
|
+
code_configuration=sdk_code_config,
|
|
1820
|
+
description=description,
|
|
1821
|
+
environment_variables=environment_variables,
|
|
1822
|
+
execution_role_arn=execution_role_arn,
|
|
1823
|
+
log_configuration=sdk_log_config,
|
|
1824
|
+
network_configuration=sdk_network_config,
|
|
1825
|
+
session_concurrency_limit_per_instance=session_concurrency_limit_per_instance,
|
|
1826
|
+
session_idle_timeout_seconds=session_idle_timeout_seconds,
|
|
1827
|
+
)
|
|
1828
|
+
|
|
1829
|
+
# Create the request object
|
|
1830
|
+
request = CreateAgentRuntimeRequest(body=input_data)
|
|
1831
|
+
|
|
1832
|
+
# Call the SDK method
|
|
1833
|
+
response = await self.client.create_agent_runtime_async(request)
|
|
1834
|
+
|
|
1835
|
+
# Check if the response is successful
|
|
1836
|
+
if (
|
|
1837
|
+
response.body
|
|
1838
|
+
and response.body.code == "SUCCESS"
|
|
1839
|
+
and response.body.data
|
|
1840
|
+
):
|
|
1841
|
+
agent_runtime_id = (
|
|
1842
|
+
response.body.data.agent_runtime_id
|
|
1843
|
+
if hasattr(response.body.data, "agent_runtime_id")
|
|
1844
|
+
else None
|
|
1845
|
+
)
|
|
1846
|
+
logger.info(
|
|
1847
|
+
"Agent runtime created successfully (ID: %s)",
|
|
1848
|
+
agent_runtime_id,
|
|
1849
|
+
)
|
|
1850
|
+
|
|
1851
|
+
# Poll for status if we have an agent_runtime_id
|
|
1852
|
+
status_result = None
|
|
1853
|
+
status_reason = None
|
|
1854
|
+
if agent_runtime_id:
|
|
1855
|
+
logger.info(
|
|
1856
|
+
"Polling status for agent runtime: %s",
|
|
1857
|
+
agent_runtime_id,
|
|
1858
|
+
)
|
|
1859
|
+
poll_status = await self._poll_agent_runtime_status(
|
|
1860
|
+
agent_runtime_id,
|
|
1861
|
+
)
|
|
1862
|
+
if isinstance(poll_status, dict):
|
|
1863
|
+
status_result = poll_status.get("status")
|
|
1864
|
+
status_reason = poll_status.get("status_reason")
|
|
1865
|
+
logger.info("Agent runtime status: %s", status_result)
|
|
1866
|
+
|
|
1867
|
+
# Check if the agent runtime is in a valid state for endpoint creation
|
|
1868
|
+
if status_result not in ["READY", "ACTIVE"]:
|
|
1869
|
+
logger.warning(
|
|
1870
|
+
"Agent runtime not in READY/ACTIVE state: %s",
|
|
1871
|
+
status_result,
|
|
1872
|
+
)
|
|
1873
|
+
|
|
1874
|
+
# Return a dictionary with relevant information from the response
|
|
1875
|
+
return {
|
|
1876
|
+
"success": True,
|
|
1877
|
+
"agent_runtime_id": agent_runtime_id,
|
|
1878
|
+
"status": status_result,
|
|
1879
|
+
"status_reason": status_reason,
|
|
1880
|
+
"request_id": response.body.request_id,
|
|
1881
|
+
}
|
|
1882
|
+
else:
|
|
1883
|
+
logger.error("Failed to create agent runtime")
|
|
1884
|
+
# Return error information if the request was not successful
|
|
1885
|
+
return {
|
|
1886
|
+
"success": False,
|
|
1887
|
+
"code": response.body.code if response.body else None,
|
|
1888
|
+
"message": "Failed to create agent runtime",
|
|
1889
|
+
"request_id": response.body.request_id
|
|
1890
|
+
if response.body
|
|
1891
|
+
else None,
|
|
1892
|
+
}
|
|
1893
|
+
except Exception as e:
|
|
1894
|
+
logger.error(
|
|
1895
|
+
f"Exception occurred while creating agent runtime: {str(e)}",
|
|
1896
|
+
)
|
|
1897
|
+
# Return error information if an exception occurred
|
|
1898
|
+
return {
|
|
1899
|
+
"success": False,
|
|
1900
|
+
"error": str(e),
|
|
1901
|
+
"message": f"Exception occurred while creating agent runtime: {str(e)}",
|
|
1902
|
+
}
|
|
1903
|
+
|
|
1904
|
+
async def update_agent_runtime(
|
|
1905
|
+
self,
|
|
1906
|
+
agent_runtime_id: str,
|
|
1907
|
+
agent_runtime_name: Optional[str] = None,
|
|
1908
|
+
artifact_type: Optional[str] = None,
|
|
1909
|
+
cpu: Optional[float] = None,
|
|
1910
|
+
memory: Optional[int] = None,
|
|
1911
|
+
port: Optional[int] = None,
|
|
1912
|
+
code_configuration: Optional[CodeConfig] = None,
|
|
1913
|
+
description: Optional[str] = None,
|
|
1914
|
+
environment_variables: Optional[Dict[str, str]] = None,
|
|
1915
|
+
execution_role_arn: Optional[str] = None,
|
|
1916
|
+
log_configuration: Optional[LogConfig] = None,
|
|
1917
|
+
network_configuration: Optional[NetworkConfig] = None,
|
|
1918
|
+
session_concurrency_limit_per_instance: Optional[int] = None,
|
|
1919
|
+
session_idle_timeout_seconds: Optional[int] = None,
|
|
1920
|
+
):
|
|
1921
|
+
"""
|
|
1922
|
+
Update an agent runtime on AgentRun.
|
|
1923
|
+
|
|
1924
|
+
Args:
|
|
1925
|
+
agent_runtime_id (str): The ID of the agent runtime to update.
|
|
1926
|
+
agent_runtime_name (Optional[str]): The name of the agent runtime.
|
|
1927
|
+
artifact_type (Optional[str]): The type of the artifact.
|
|
1928
|
+
cpu (Optional[float]): The CPU allocated to the runtime.
|
|
1929
|
+
memory (Optional[int]): The memory allocated to the runtime.
|
|
1930
|
+
port (Optional[int]): The port on which the runtime will listen.
|
|
1931
|
+
code_configuration (Optional[CodeConfig]): Configuration for code-based runtimes.
|
|
1932
|
+
description (Optional[str]): Description of the agent runtime.
|
|
1933
|
+
environment_variables (Optional[Dict[str, str]]): Environment variables for the runtime.
|
|
1934
|
+
execution_role_arn (Optional[str]): The execution role ARN for accessing cloud services.
|
|
1935
|
+
log_configuration (Optional[LogConfig]): Configuration for logging.
|
|
1936
|
+
network_configuration (Optional[NetworkConfig]): Network configuration for the runtime, including:
|
|
1937
|
+
- network_mode: The network mode for the runtime
|
|
1938
|
+
- security_group_id: The security group ID for the runtime
|
|
1939
|
+
- vpc_id: The VPC ID for the runtime
|
|
1940
|
+
- vswitch_ids: List of vswitch IDs for the runtime
|
|
1941
|
+
session_concurrency_limit_per_instance (Optional[int]): Maximum concurrent sessions per instance.
|
|
1942
|
+
session_idle_timeout_seconds (Optional[int]): Maximum idle timeout for sessions.
|
|
1943
|
+
|
|
1944
|
+
Returns:
|
|
1945
|
+
Dict[str, Any]: A dictionary containing the update result with:
|
|
1946
|
+
- success (bool): Whether the operation was successful
|
|
1947
|
+
- agent_runtime_id (str): The ID of the updated agent runtime
|
|
1948
|
+
- status (str): The status of the agent runtime
|
|
1949
|
+
- status_reason (str): The reason for the status
|
|
1950
|
+
- request_id (str): The request ID for tracking
|
|
1951
|
+
"""
|
|
1952
|
+
try:
|
|
1953
|
+
logger.info(
|
|
1954
|
+
f"Updating agent runtime with ID: {agent_runtime_id}",
|
|
1955
|
+
)
|
|
1956
|
+
|
|
1957
|
+
# Adapt custom configurations to SDK configurations
|
|
1958
|
+
sdk_code_config = self._adapt_code_config(code_configuration)
|
|
1959
|
+
|
|
1960
|
+
sdk_log_config = self._adapt_log_config(log_configuration)
|
|
1961
|
+
sdk_network_config = self._adapt_network_config(
|
|
1962
|
+
network_configuration,
|
|
1963
|
+
)
|
|
1964
|
+
|
|
1965
|
+
# Create the input object with provided parameters
|
|
1966
|
+
input_data = UpdateAgentRuntimeInput(
|
|
1967
|
+
agent_runtime_name=agent_runtime_name,
|
|
1968
|
+
artifact_type=artifact_type,
|
|
1969
|
+
cpu=cpu,
|
|
1970
|
+
memory=memory,
|
|
1971
|
+
port=port,
|
|
1972
|
+
code_configuration=sdk_code_config,
|
|
1973
|
+
description=description,
|
|
1974
|
+
environment_variables=environment_variables,
|
|
1975
|
+
execution_role_arn=execution_role_arn,
|
|
1976
|
+
log_configuration=sdk_log_config,
|
|
1977
|
+
network_configuration=sdk_network_config,
|
|
1978
|
+
session_concurrency_limit_per_instance=session_concurrency_limit_per_instance,
|
|
1979
|
+
session_idle_timeout_seconds=session_idle_timeout_seconds,
|
|
1980
|
+
)
|
|
1981
|
+
|
|
1982
|
+
# Create the request object
|
|
1983
|
+
request = UpdateAgentRuntimeRequest(body=input_data)
|
|
1984
|
+
|
|
1985
|
+
# Call the SDK method
|
|
1986
|
+
response = await self.client.update_agent_runtime_async(
|
|
1987
|
+
agent_runtime_id,
|
|
1988
|
+
request,
|
|
1989
|
+
)
|
|
1990
|
+
|
|
1991
|
+
# Check if the response is successful
|
|
1992
|
+
if response.body and response.body.code == "SUCCESS":
|
|
1993
|
+
logger.info(
|
|
1994
|
+
"Agent runtime updated successfully (ID: %s)",
|
|
1995
|
+
agent_runtime_id,
|
|
1996
|
+
)
|
|
1997
|
+
|
|
1998
|
+
# Poll for status
|
|
1999
|
+
status_result = None
|
|
2000
|
+
status_reason = None
|
|
2001
|
+
if agent_runtime_id:
|
|
2002
|
+
logger.info(
|
|
2003
|
+
"Polling status for updated agent runtime: %s",
|
|
2004
|
+
agent_runtime_id,
|
|
2005
|
+
)
|
|
2006
|
+
poll_status = await self._poll_agent_runtime_status(
|
|
2007
|
+
agent_runtime_id,
|
|
2008
|
+
)
|
|
2009
|
+
if isinstance(poll_status, dict):
|
|
2010
|
+
status_result = poll_status.get("status")
|
|
2011
|
+
status_reason = poll_status.get("status_reason")
|
|
2012
|
+
logger.info(
|
|
2013
|
+
"Updated agent runtime status: %s",
|
|
2014
|
+
status_result,
|
|
2015
|
+
)
|
|
2016
|
+
|
|
2017
|
+
# Return a dictionary with relevant information from the response
|
|
2018
|
+
return {
|
|
2019
|
+
"success": True,
|
|
2020
|
+
"agent_runtime_id": agent_runtime_id,
|
|
2021
|
+
"status": status_result,
|
|
2022
|
+
"status_reason": status_reason,
|
|
2023
|
+
"request_id": response.body.request_id,
|
|
2024
|
+
}
|
|
2025
|
+
else:
|
|
2026
|
+
logger.error("Failed to update agent runtime")
|
|
2027
|
+
# Return error information if the request was not successful
|
|
2028
|
+
return {
|
|
2029
|
+
"success": False,
|
|
2030
|
+
"code": response.body.code if response.body else None,
|
|
2031
|
+
"message": "Failed to update_agent_runtime agent runtime",
|
|
2032
|
+
"request_id": response.body.request_id
|
|
2033
|
+
if response.body
|
|
2034
|
+
else None,
|
|
2035
|
+
}
|
|
2036
|
+
except Exception as e:
|
|
2037
|
+
logger.error(
|
|
2038
|
+
f"Exception occurred while updating agent runtime: {str(e)}",
|
|
2039
|
+
)
|
|
2040
|
+
# Return error information if an exception occurred
|
|
2041
|
+
return {
|
|
2042
|
+
"success": False,
|
|
2043
|
+
"error": str(e),
|
|
2044
|
+
"message": f"Exception occurred while updating agent runtime: {str(e)}",
|
|
2045
|
+
}
|
|
2046
|
+
|
|
2047
|
+
async def create_agent_runtime_endpoint(
|
|
2048
|
+
self,
|
|
2049
|
+
agent_runtime_id: str,
|
|
2050
|
+
endpoint_config: Optional[EndpointConfig] = None,
|
|
2051
|
+
):
|
|
2052
|
+
"""
|
|
2053
|
+
Create an agent runtime endpoint.
|
|
2054
|
+
|
|
2055
|
+
Args:
|
|
2056
|
+
agent_runtime_id (str): The ID of the agent runtime.
|
|
2057
|
+
endpoint_config (Optional[EndpointConfig]): Configuration for the endpoint, including:
|
|
2058
|
+
- agent_runtime_endpoint_name: The name of the endpoint
|
|
2059
|
+
- description: Description of the endpoint
|
|
2060
|
+
- target_version: Target version for the endpoint
|
|
2061
|
+
|
|
2062
|
+
Returns:
|
|
2063
|
+
Dict[str, Any]: A dictionary containing the creation result with:
|
|
2064
|
+
- success (bool): Whether the operation was successful
|
|
2065
|
+
- agent_runtime_endpoint_id (str): The ID of the created endpoint
|
|
2066
|
+
- agent_runtime_endpoint_name (str): The name of the created endpoint
|
|
2067
|
+
- agent_runtime_public_endpoint_url (str): The public URL of the endpoint
|
|
2068
|
+
- status (str): The status of the endpoint
|
|
2069
|
+
- status_reason (str): The reason for the status
|
|
2070
|
+
- request_id (str): The request ID for tracking
|
|
2071
|
+
"""
|
|
2072
|
+
try:
|
|
2073
|
+
endpoint_name = (
|
|
2074
|
+
endpoint_config.agent_runtime_endpoint_name
|
|
2075
|
+
if endpoint_config
|
|
2076
|
+
else "unnamed"
|
|
2077
|
+
)
|
|
2078
|
+
logger.info(
|
|
2079
|
+
f"Creating agent runtime endpoint '{endpoint_name}' for runtime ID: {agent_runtime_id}",
|
|
2080
|
+
)
|
|
2081
|
+
|
|
2082
|
+
# Create the input object with provided parameters
|
|
2083
|
+
input_data = CreateAgentRuntimeEndpointInput(
|
|
2084
|
+
agent_runtime_endpoint_name=endpoint_config.agent_runtime_endpoint_name
|
|
2085
|
+
if endpoint_config
|
|
2086
|
+
else None,
|
|
2087
|
+
description=endpoint_config.description
|
|
2088
|
+
if endpoint_config
|
|
2089
|
+
else None,
|
|
2090
|
+
target_version=endpoint_config.target_version
|
|
2091
|
+
if endpoint_config
|
|
2092
|
+
else None,
|
|
2093
|
+
)
|
|
2094
|
+
|
|
2095
|
+
# Create the request object
|
|
2096
|
+
request = CreateAgentRuntimeEndpointRequest(body=input_data)
|
|
2097
|
+
|
|
2098
|
+
# Call the SDK method
|
|
2099
|
+
response = await self.client.create_agent_runtime_endpoint_async(
|
|
2100
|
+
agent_runtime_id,
|
|
2101
|
+
request,
|
|
2102
|
+
)
|
|
2103
|
+
|
|
2104
|
+
# Check if the response is successful
|
|
2105
|
+
if (
|
|
2106
|
+
response.body
|
|
2107
|
+
and response.body.code == "SUCCESS"
|
|
2108
|
+
and response.body.data
|
|
2109
|
+
):
|
|
2110
|
+
agent_runtime_endpoint_id = (
|
|
2111
|
+
response.body.data.agent_runtime_endpoint_id
|
|
2112
|
+
if hasattr(response.body.data, "agent_runtime_endpoint_id")
|
|
2113
|
+
else None
|
|
2114
|
+
)
|
|
2115
|
+
logger.info(
|
|
2116
|
+
"Agent runtime endpoint created successfully (ID: %s)",
|
|
2117
|
+
agent_runtime_endpoint_id,
|
|
2118
|
+
)
|
|
2119
|
+
|
|
2120
|
+
# Poll for status if we have an agent_runtime_endpoint_id
|
|
2121
|
+
status_result = None
|
|
2122
|
+
status_reason = None
|
|
2123
|
+
if agent_runtime_endpoint_id:
|
|
2124
|
+
logger.info(
|
|
2125
|
+
"Polling status for agent runtime endpoint: %s",
|
|
2126
|
+
agent_runtime_endpoint_id,
|
|
2127
|
+
)
|
|
2128
|
+
poll_status = (
|
|
2129
|
+
await self._poll_agent_runtime_endpoint_status(
|
|
2130
|
+
agent_runtime_id,
|
|
2131
|
+
agent_runtime_endpoint_id,
|
|
2132
|
+
)
|
|
2133
|
+
)
|
|
2134
|
+
if isinstance(poll_status, dict):
|
|
2135
|
+
status_result = poll_status.get("status")
|
|
2136
|
+
status_reason = poll_status.get("status_reason")
|
|
2137
|
+
logger.info(
|
|
2138
|
+
"Agent runtime endpoint status: %s",
|
|
2139
|
+
status_result,
|
|
2140
|
+
)
|
|
2141
|
+
|
|
2142
|
+
# Return a dictionary with relevant information from the response
|
|
2143
|
+
return {
|
|
2144
|
+
"success": True,
|
|
2145
|
+
"agent_runtime_endpoint_id": agent_runtime_endpoint_id,
|
|
2146
|
+
"agent_runtime_endpoint_name": response.body.data.agent_runtime_endpoint_name
|
|
2147
|
+
if hasattr(
|
|
2148
|
+
response.body.data,
|
|
2149
|
+
"agent_runtime_endpoint_name",
|
|
2150
|
+
)
|
|
2151
|
+
else None,
|
|
2152
|
+
"agent_runtime_public_endpoint_url": response.body.data.endpoint_public_url
|
|
2153
|
+
if hasattr(response.body.data, "endpoint_public_url")
|
|
2154
|
+
else None,
|
|
2155
|
+
"status": status_result,
|
|
2156
|
+
"status_reason": status_reason,
|
|
2157
|
+
"request_id": response.body.request_id,
|
|
2158
|
+
}
|
|
2159
|
+
else:
|
|
2160
|
+
logger.error("Failed to create agent runtime endpoint")
|
|
2161
|
+
# Return error information if the request was not successful
|
|
2162
|
+
return {
|
|
2163
|
+
"success": False,
|
|
2164
|
+
"code": response.body.code if response.body else None,
|
|
2165
|
+
"message": "Failed to create agent runtime endpoint",
|
|
2166
|
+
"request_id": response.body.request_id
|
|
2167
|
+
if response.body
|
|
2168
|
+
else None,
|
|
2169
|
+
}
|
|
2170
|
+
except Exception as e:
|
|
2171
|
+
logger.error(
|
|
2172
|
+
f"Exception occurred while creating agent runtime endpoint: {str(e)}",
|
|
2173
|
+
)
|
|
2174
|
+
# Return error information if an exception occurred
|
|
2175
|
+
return {
|
|
2176
|
+
"success": False,
|
|
2177
|
+
"error": str(e),
|
|
2178
|
+
"message": f"Exception occurred while creating agent runtime endpoint: {str(e)}",
|
|
2179
|
+
}
|
|
2180
|
+
|
|
2181
|
+
async def update_agent_runtime_endpoint(
|
|
2182
|
+
self,
|
|
2183
|
+
agent_runtime_id: str,
|
|
2184
|
+
agent_runtime_endpoint_id: str,
|
|
2185
|
+
endpoint_config: Optional[EndpointConfig] = None,
|
|
2186
|
+
):
|
|
2187
|
+
"""
|
|
2188
|
+
Update an agent runtime endpoint.
|
|
2189
|
+
|
|
2190
|
+
Args:
|
|
2191
|
+
agent_runtime_id (str): The ID of the agent runtime.
|
|
2192
|
+
agent_runtime_endpoint_id (str): The ID of the agent runtime endpoint.
|
|
2193
|
+
endpoint_config (Optional[EndpointConfig]): Configuration for the endpoint, including:
|
|
2194
|
+
- agent_runtime_endpoint_name: The name of the endpoint
|
|
2195
|
+
- description: Description of the endpoint
|
|
2196
|
+
- target_version: Target version for the endpoint
|
|
2197
|
+
|
|
2198
|
+
Returns:
|
|
2199
|
+
Dict[str, Any]: A dictionary containing the update result with:
|
|
2200
|
+
- success (bool): Whether the operation was successful
|
|
2201
|
+
- agent_runtime_endpoint_id (str): The ID of the updated endpoint
|
|
2202
|
+
- status (str): The status of the endpoint
|
|
2203
|
+
- status_reason (str): The reason for the status
|
|
2204
|
+
- request_id (str): The request ID for tracking
|
|
2205
|
+
"""
|
|
2206
|
+
try:
|
|
2207
|
+
endpoint_name = (
|
|
2208
|
+
endpoint_config.agent_runtime_endpoint_name
|
|
2209
|
+
if endpoint_config
|
|
2210
|
+
else "unnamed"
|
|
2211
|
+
)
|
|
2212
|
+
logger.info(
|
|
2213
|
+
f"Updating agent runtime endpoint '{endpoint_name}' with ID: {agent_runtime_endpoint_id}",
|
|
2214
|
+
)
|
|
2215
|
+
|
|
2216
|
+
# Create the input object with provided parameters
|
|
2217
|
+
input_data = UpdateAgentRuntimeEndpointInput(
|
|
2218
|
+
agent_runtime_endpoint_name=endpoint_config.agent_runtime_endpoint_name
|
|
2219
|
+
if endpoint_config
|
|
2220
|
+
else None,
|
|
2221
|
+
description=endpoint_config.description
|
|
2222
|
+
if endpoint_config
|
|
2223
|
+
else None,
|
|
2224
|
+
target_version=endpoint_config.target_version
|
|
2225
|
+
if endpoint_config
|
|
2226
|
+
else None,
|
|
2227
|
+
)
|
|
2228
|
+
|
|
2229
|
+
# Create the request object
|
|
2230
|
+
request = UpdateAgentRuntimeEndpointRequest(body=input_data)
|
|
2231
|
+
|
|
2232
|
+
# Call the SDK method
|
|
2233
|
+
response = await self.client.update_agent_runtime_endpoint_async(
|
|
2234
|
+
agent_runtime_id,
|
|
2235
|
+
agent_runtime_endpoint_id,
|
|
2236
|
+
request,
|
|
2237
|
+
)
|
|
2238
|
+
|
|
2239
|
+
# Check if the response is successful
|
|
2240
|
+
if response.body and response.body.code == "SUCCESS":
|
|
2241
|
+
logger.info(
|
|
2242
|
+
"Agent runtime endpoint updated successfully (ID: %s)",
|
|
2243
|
+
agent_runtime_endpoint_id,
|
|
2244
|
+
)
|
|
2245
|
+
|
|
2246
|
+
# Poll for status if we have an agent_runtime_endpoint_id
|
|
2247
|
+
status_result = None
|
|
2248
|
+
status_reason = None
|
|
2249
|
+
if agent_runtime_endpoint_id:
|
|
2250
|
+
logger.info(
|
|
2251
|
+
"Polling status for updated agent runtime endpoint: %s",
|
|
2252
|
+
agent_runtime_endpoint_id,
|
|
2253
|
+
)
|
|
2254
|
+
poll_status = (
|
|
2255
|
+
await self._poll_agent_runtime_endpoint_status(
|
|
2256
|
+
agent_runtime_id,
|
|
2257
|
+
agent_runtime_endpoint_id,
|
|
2258
|
+
)
|
|
2259
|
+
)
|
|
2260
|
+
if isinstance(poll_status, dict):
|
|
2261
|
+
status_result = poll_status.get("status")
|
|
2262
|
+
status_reason = poll_status.get("status_reason")
|
|
2263
|
+
logger.info(
|
|
2264
|
+
"Updated agent runtime endpoint status: %s",
|
|
2265
|
+
status_result,
|
|
2266
|
+
)
|
|
2267
|
+
|
|
2268
|
+
# Return a dictionary with relevant information from the response
|
|
2269
|
+
return {
|
|
2270
|
+
"success": True,
|
|
2271
|
+
"agent_runtime_endpoint_id": agent_runtime_endpoint_id,
|
|
2272
|
+
"status": status_result,
|
|
2273
|
+
"status_reason": status_reason,
|
|
2274
|
+
"request_id": response.body.request_id,
|
|
2275
|
+
}
|
|
2276
|
+
else:
|
|
2277
|
+
logger.error("Failed to update agent runtime endpoint")
|
|
2278
|
+
# Return error information if the request was not successful
|
|
2279
|
+
return {
|
|
2280
|
+
"success": False,
|
|
2281
|
+
"code": response.body.code if response.body else None,
|
|
2282
|
+
"message": "Failed to update agent runtime endpoint",
|
|
2283
|
+
"request_id": response.body.request_id
|
|
2284
|
+
if response.body
|
|
2285
|
+
else None,
|
|
2286
|
+
}
|
|
2287
|
+
except Exception as e:
|
|
2288
|
+
logger.error(
|
|
2289
|
+
f"Exception occurred while updating agent runtime endpoint: {str(e)}",
|
|
2290
|
+
)
|
|
2291
|
+
# Return error information if an exception occurred
|
|
2292
|
+
return {
|
|
2293
|
+
"success": False,
|
|
2294
|
+
"error": str(e),
|
|
2295
|
+
"message": f"Exception occurred while updating agent runtime endpoint: {str(e)}",
|
|
2296
|
+
}
|
|
2297
|
+
|
|
2298
|
+
async def get_agent_runtime_endpoint(
|
|
2299
|
+
self,
|
|
2300
|
+
agent_runtime_id: str,
|
|
2301
|
+
agent_runtime_endpoint_id: str,
|
|
2302
|
+
):
|
|
2303
|
+
"""
|
|
2304
|
+
Get an agent runtime endpoint.
|
|
2305
|
+
|
|
2306
|
+
Args:
|
|
2307
|
+
agent_runtime_id (str): The ID of the agent runtime.
|
|
2308
|
+
agent_runtime_endpoint_id (str): The ID of the agent runtime endpoint.
|
|
2309
|
+
|
|
2310
|
+
Returns:
|
|
2311
|
+
Dict[str, Any]: A dictionary containing the endpoint details with:
|
|
2312
|
+
- success (bool): Whether the operation was successful
|
|
2313
|
+
- agent_runtime_endpoint_id (str): The ID of the endpoint
|
|
2314
|
+
- agent_runtime_endpoint_name (str): The name of the endpoint
|
|
2315
|
+
- agent_runtime_id (str): The ID of the agent runtime
|
|
2316
|
+
- agent_runtime_public_endpoint_url (str): The public URL of the endpoint
|
|
2317
|
+
- status (str): The status of the endpoint
|
|
2318
|
+
- status_reason (str): The reason for the status
|
|
2319
|
+
- request_id (str): The request ID for tracking
|
|
2320
|
+
"""
|
|
2321
|
+
try:
|
|
2322
|
+
logger.info(
|
|
2323
|
+
f"Getting agent runtime endpoint details for ID: {agent_runtime_endpoint_id}",
|
|
2324
|
+
)
|
|
2325
|
+
|
|
2326
|
+
# Call the SDK method
|
|
2327
|
+
response = await self.client.get_agent_runtime_endpoint_async(
|
|
2328
|
+
agent_runtime_id,
|
|
2329
|
+
agent_runtime_endpoint_id,
|
|
2330
|
+
)
|
|
2331
|
+
|
|
2332
|
+
# Check if the response is successful
|
|
2333
|
+
if (
|
|
2334
|
+
response.body
|
|
2335
|
+
and response.body.code == "SUCCESS"
|
|
2336
|
+
and response.body.data
|
|
2337
|
+
):
|
|
2338
|
+
logger.info(
|
|
2339
|
+
"Agent runtime endpoint details retrieved successfully (ID: %s)",
|
|
2340
|
+
agent_runtime_endpoint_id,
|
|
2341
|
+
)
|
|
2342
|
+
# Return the endpoint data as a dictionary
|
|
2343
|
+
return {
|
|
2344
|
+
"success": True,
|
|
2345
|
+
"agent_runtime_endpoint_id": response.body.data.agent_runtime_endpoint_id
|
|
2346
|
+
if hasattr(response.body.data, "agent_runtime_endpoint_id")
|
|
2347
|
+
else None,
|
|
2348
|
+
"agent_runtime_endpoint_name": response.body.data.agent_runtime_endpoint_name
|
|
2349
|
+
if hasattr(
|
|
2350
|
+
response.body.data,
|
|
2351
|
+
"agent_runtime_endpoint_name",
|
|
2352
|
+
)
|
|
2353
|
+
else None,
|
|
2354
|
+
"agent_runtime_id": response.body.data.agent_runtime_id
|
|
2355
|
+
if hasattr(response.body.data, "agent_runtime_id")
|
|
2356
|
+
else None,
|
|
2357
|
+
"agent_runtime_public_endpoint_url": response.body.data.endpoint_public_url
|
|
2358
|
+
if hasattr(response.body.data, "endpoint_public_url")
|
|
2359
|
+
else None,
|
|
2360
|
+
"status": response.body.data.status
|
|
2361
|
+
if hasattr(response.body.data, "status")
|
|
2362
|
+
else None,
|
|
2363
|
+
"status_reason": response.body.data.status_reason
|
|
2364
|
+
if hasattr(response.body.data, "status_reason")
|
|
2365
|
+
else None,
|
|
2366
|
+
"request_id": response.body.request_id,
|
|
2367
|
+
}
|
|
2368
|
+
else:
|
|
2369
|
+
logger.error("Failed to get agent runtime endpoint")
|
|
2370
|
+
# Return error information if the request was not successful
|
|
2371
|
+
return {
|
|
2372
|
+
"success": False,
|
|
2373
|
+
"code": response.body.code if response.body else None,
|
|
2374
|
+
"message": "Failed to get agent runtime endpoint",
|
|
2375
|
+
"request_id": response.body.request_id
|
|
2376
|
+
if response.body
|
|
2377
|
+
else None,
|
|
2378
|
+
}
|
|
2379
|
+
except Exception as e:
|
|
2380
|
+
logger.error(
|
|
2381
|
+
f"Exception occurred while getting agent runtime endpoint: {str(e)}",
|
|
2382
|
+
)
|
|
2383
|
+
# Return error information if an exception occurred
|
|
2384
|
+
return {
|
|
2385
|
+
"success": False,
|
|
2386
|
+
"error": str(e),
|
|
2387
|
+
"message": f"Exception occurred while getting agent runtime endpoint: {str(e)}",
|
|
2388
|
+
}
|
|
2389
|
+
|
|
2390
|
+
async def delete_agent_runtime_endpoint(
|
|
2391
|
+
self,
|
|
2392
|
+
agent_runtime_id: str,
|
|
2393
|
+
agent_runtime_endpoint_id: str,
|
|
2394
|
+
):
|
|
2395
|
+
"""
|
|
2396
|
+
Delete an agent runtime endpoint.
|
|
2397
|
+
|
|
2398
|
+
Args:
|
|
2399
|
+
agent_runtime_id (str): The ID of the agent runtime.
|
|
2400
|
+
agent_runtime_endpoint_id (str): The ID of the agent runtime endpoint.
|
|
2401
|
+
|
|
2402
|
+
Returns:
|
|
2403
|
+
Dict[str, Any]: A dictionary containing the delete result with:
|
|
2404
|
+
- success (bool): Whether the operation was successful
|
|
2405
|
+
- message (str): Status message
|
|
2406
|
+
- agent_runtime_endpoint_id (str): The ID of the deleted endpoint
|
|
2407
|
+
- request_id (str): The request ID for tracking
|
|
2408
|
+
"""
|
|
2409
|
+
try:
|
|
2410
|
+
logger.info(
|
|
2411
|
+
f"Deleting agent runtime endpoint with ID: {agent_runtime_endpoint_id}",
|
|
2412
|
+
)
|
|
2413
|
+
|
|
2414
|
+
# Call the SDK method
|
|
2415
|
+
response = await self.client.delete_agent_runtime_endpoint_async(
|
|
2416
|
+
agent_runtime_id,
|
|
2417
|
+
agent_runtime_endpoint_id,
|
|
2418
|
+
)
|
|
2419
|
+
|
|
2420
|
+
# Check if the response is successful
|
|
2421
|
+
if response.body and response.body.code == "SUCCESS":
|
|
2422
|
+
logger.info(
|
|
2423
|
+
"Agent runtime endpoint deletion initiated (ID: %s)",
|
|
2424
|
+
agent_runtime_endpoint_id,
|
|
2425
|
+
)
|
|
2426
|
+
# Return a dictionary with relevant information from the response
|
|
2427
|
+
return {
|
|
2428
|
+
"success": True,
|
|
2429
|
+
"message": "Agent runtime endpoint deletion initiated successfully",
|
|
2430
|
+
"agent_runtime_endpoint_id": agent_runtime_endpoint_id,
|
|
2431
|
+
"request_id": response.body.request_id,
|
|
2432
|
+
}
|
|
2433
|
+
else:
|
|
2434
|
+
logger.error("Failed to delete agent runtime endpoint")
|
|
2435
|
+
# Return error information if the request was not successful
|
|
2436
|
+
return {
|
|
2437
|
+
"success": False,
|
|
2438
|
+
"code": response.body.code if response.body else None,
|
|
2439
|
+
"message": "Failed to delete agent runtime endpoint",
|
|
2440
|
+
"request_id": response.body.request_id
|
|
2441
|
+
if response.body
|
|
2442
|
+
else None,
|
|
2443
|
+
}
|
|
2444
|
+
except Exception as e:
|
|
2445
|
+
logger.error(
|
|
2446
|
+
f"Exception occurred while deleting agent runtime endpoint: {str(e)}",
|
|
2447
|
+
)
|
|
2448
|
+
# Return error information if an exception occurred
|
|
2449
|
+
return {
|
|
2450
|
+
"success": False,
|
|
2451
|
+
"error": str(e),
|
|
2452
|
+
"message": f"Exception occurred while deleting agent runtime endpoint: {str(e)}",
|
|
2453
|
+
}
|
|
2454
|
+
|
|
2455
|
+
async def publish_agent_runtime_version(
|
|
2456
|
+
self,
|
|
2457
|
+
agent_runtime_id: str,
|
|
2458
|
+
description: Optional[str] = None,
|
|
2459
|
+
):
|
|
2460
|
+
"""
|
|
2461
|
+
Publish an agent runtime version.
|
|
2462
|
+
|
|
2463
|
+
Args:
|
|
2464
|
+
agent_runtime_id (str): The ID of the agent runtime.
|
|
2465
|
+
description (Optional[str]): Description of the version.
|
|
2466
|
+
|
|
2467
|
+
Returns:
|
|
2468
|
+
Dict[str, Any]: A dictionary containing the publish result with:
|
|
2469
|
+
- success (bool): Whether the operation was successful
|
|
2470
|
+
- agent_runtime_id (str): The ID of the agent runtime
|
|
2471
|
+
- agent_runtime_version (str): The published version
|
|
2472
|
+
- description (str): Description of the version
|
|
2473
|
+
- request_id (str): The request ID for tracking
|
|
2474
|
+
"""
|
|
2475
|
+
try:
|
|
2476
|
+
logger.info(
|
|
2477
|
+
f"Publishing agent runtime version for ID: {agent_runtime_id}",
|
|
2478
|
+
)
|
|
2479
|
+
|
|
2480
|
+
# Create the input object with provided parameters
|
|
2481
|
+
input_data = PublishRuntimeVersionInput(
|
|
2482
|
+
description=description,
|
|
2483
|
+
)
|
|
2484
|
+
|
|
2485
|
+
# Create the request object
|
|
2486
|
+
request = PublishRuntimeVersionRequest(body=input_data)
|
|
2487
|
+
|
|
2488
|
+
# Call the SDK method
|
|
2489
|
+
response = await self.client.publish_runtime_version_async(
|
|
2490
|
+
agent_runtime_id,
|
|
2491
|
+
request,
|
|
2492
|
+
)
|
|
2493
|
+
|
|
2494
|
+
# Check if the response is successful
|
|
2495
|
+
if (
|
|
2496
|
+
response.body
|
|
2497
|
+
and response.body.code == "SUCCESS"
|
|
2498
|
+
and response.body.data
|
|
2499
|
+
):
|
|
2500
|
+
version = (
|
|
2501
|
+
response.body.data.agent_runtime_version
|
|
2502
|
+
if hasattr(response.body.data, "agent_runtime_version")
|
|
2503
|
+
else None
|
|
2504
|
+
)
|
|
2505
|
+
logger.info(
|
|
2506
|
+
"Agent runtime version published successfully: %s",
|
|
2507
|
+
version,
|
|
2508
|
+
)
|
|
2509
|
+
# Return a dictionary with relevant information from the response
|
|
2510
|
+
return {
|
|
2511
|
+
"success": True,
|
|
2512
|
+
"agent_runtime_id": response.body.data.agent_runtime_id
|
|
2513
|
+
if hasattr(response.body.data, "agent_runtime_id")
|
|
2514
|
+
else None,
|
|
2515
|
+
"agent_runtime_version": version,
|
|
2516
|
+
"description": response.body.data.description
|
|
2517
|
+
if hasattr(response.body.data, "description")
|
|
2518
|
+
else None,
|
|
2519
|
+
"request_id": response.body.request_id,
|
|
2520
|
+
}
|
|
2521
|
+
else:
|
|
2522
|
+
logger.error("Failed to publish agent runtime version")
|
|
2523
|
+
# Return error information if the request was not successful
|
|
2524
|
+
return {
|
|
2525
|
+
"success": False,
|
|
2526
|
+
"code": response.body.code if response.body else None,
|
|
2527
|
+
"message": "Failed to publish agent runtime version",
|
|
2528
|
+
"request_id": response.body.request_id
|
|
2529
|
+
if response.body
|
|
2530
|
+
else None,
|
|
2531
|
+
}
|
|
2532
|
+
except Exception as e:
|
|
2533
|
+
logger.error(
|
|
2534
|
+
f"Exception occurred while publishing agent runtime version: {str(e)}",
|
|
2535
|
+
)
|
|
2536
|
+
# Return error information if an exception occurred
|
|
2537
|
+
return {
|
|
2538
|
+
"success": False,
|
|
2539
|
+
"error": str(e),
|
|
2540
|
+
"message": f"Exception occurred while publishing agent runtime version: {str(e)}",
|
|
2541
|
+
}
|