agentscope-runtime 0.2.0b2__py3-none-any.whl → 1.0.0b1__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 +474 -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 +256 -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 +170 -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/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 +18 -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.0b1.dist-info}/METADATA +234 -165
- agentscope_runtime-1.0.0b1.dist-info/RECORD +240 -0
- {agentscope_runtime-0.2.0b2.dist-info → agentscope_runtime-1.0.0b1.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.0b1.dist-info}/WHEEL +0 -0
- {agentscope_runtime-0.2.0b2.dist-info → agentscope_runtime-1.0.0b1.dist-info}/licenses/LICENSE +0 -0
- {agentscope_runtime-0.2.0b2.dist-info → agentscope_runtime-1.0.0b1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,855 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# flake8: noqa: E501
|
|
3
|
+
# pylint: disable=line-too-long, arguments-renamed, too-many-branches, too-many-statements
|
|
4
|
+
import json
|
|
5
|
+
import logging
|
|
6
|
+
import random
|
|
7
|
+
import secrets
|
|
8
|
+
import string
|
|
9
|
+
import time
|
|
10
|
+
from http.client import HTTPS_PORT
|
|
11
|
+
from typing import List, Dict, Optional
|
|
12
|
+
from urllib.parse import urlparse
|
|
13
|
+
|
|
14
|
+
from alibabacloud_fc20230330 import models as fc20230330_models
|
|
15
|
+
from alibabacloud_fc20230330.client import Client as FC20230330Client
|
|
16
|
+
from alibabacloud_tea_openapi import models as open_api_models
|
|
17
|
+
from alibabacloud_tea_util import models as util_models
|
|
18
|
+
|
|
19
|
+
from agentscope_runtime.sandbox.model import SandboxManagerEnvConfig
|
|
20
|
+
from .base_client import BaseClient
|
|
21
|
+
|
|
22
|
+
logger = logging.getLogger(__name__)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class FCSessionManager:
|
|
26
|
+
"""Manager for Function Compute sessions that handles creation, retrieval,
|
|
27
|
+
updating, and deletion of sessions.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
def __init__(self):
|
|
31
|
+
"""Initialize the session manager with an empty session dictionary."""
|
|
32
|
+
self.sessions = {}
|
|
33
|
+
logger.debug("FC Session Manager initialized")
|
|
34
|
+
|
|
35
|
+
def create_session(self, session_id: str, session_data: Dict):
|
|
36
|
+
"""Create a new session with the given session_id and session_data.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
session_id (str): Unique identifier for the session.
|
|
40
|
+
session_data (Dict): Data to store in the session.
|
|
41
|
+
"""
|
|
42
|
+
self.sessions[session_id] = session_data
|
|
43
|
+
logger.debug(f"Created FC session: {session_id}")
|
|
44
|
+
|
|
45
|
+
def get_session(self, session_id: str) -> Optional[Dict]:
|
|
46
|
+
"""Retrieve session data by session_id.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
session_id (str): Unique identifier for the session.
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
Optional[Dict]: Session data if found, None otherwise.
|
|
53
|
+
"""
|
|
54
|
+
return self.sessions.get(session_id)
|
|
55
|
+
|
|
56
|
+
def update_session(self, session_id: str, updates: Dict):
|
|
57
|
+
"""Update an existing session with new data.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
session_id (str): Unique identifier for the session.
|
|
61
|
+
updates (Dict): Data to update in the session.
|
|
62
|
+
"""
|
|
63
|
+
if session_id in self.sessions:
|
|
64
|
+
self.sessions[session_id].update(updates)
|
|
65
|
+
logger.debug(f"Updated FC session: {session_id}")
|
|
66
|
+
|
|
67
|
+
def delete_session(self, session_id: str):
|
|
68
|
+
"""Delete a session by session_id.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
session_id (str): Unique identifier for the session.
|
|
72
|
+
"""
|
|
73
|
+
if session_id in self.sessions:
|
|
74
|
+
del self.sessions[session_id]
|
|
75
|
+
logger.debug(f"Deleted FC session: {session_id}")
|
|
76
|
+
|
|
77
|
+
def list_sessions(self) -> List[str]:
|
|
78
|
+
"""List all session IDs.
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
List[str]: List of all session IDs.
|
|
82
|
+
"""
|
|
83
|
+
return list(self.sessions.keys())
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class FCClient(BaseClient):
|
|
87
|
+
"""Client for managing Function Compute containers in the sandbox environment.
|
|
88
|
+
|
|
89
|
+
This client provides methods to create, start, stop, remove,
|
|
90
|
+
and inspect Function Compute sessions. It also handles the underlying
|
|
91
|
+
Function Compute API calls and status polling.
|
|
92
|
+
"""
|
|
93
|
+
|
|
94
|
+
HTTPS_PROTOCOL = "https"
|
|
95
|
+
|
|
96
|
+
def __init__(self, config: SandboxManagerEnvConfig):
|
|
97
|
+
"""Initialize the Function Compute client with the provided configuration.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
config (SandboxManagerEnvConfig): Configuration object containing
|
|
101
|
+
Function Compute settings.
|
|
102
|
+
"""
|
|
103
|
+
self.config = config
|
|
104
|
+
self.fc_client = self._create_fc_client()
|
|
105
|
+
self.session_manager = FCSessionManager()
|
|
106
|
+
self.function_prefix = config.fc_prefix or "agentscope-sandbox"
|
|
107
|
+
|
|
108
|
+
logger.info(
|
|
109
|
+
f"FunctionComputeClient initialized successfully with config: {config}",
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
# Test connection
|
|
113
|
+
self._test_connection()
|
|
114
|
+
|
|
115
|
+
def _create_fc_client(self):
|
|
116
|
+
"""Create and configure the Function Compute client.
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
FC20230330Client: Configured Function Compute client instance.
|
|
120
|
+
"""
|
|
121
|
+
fc_config = open_api_models.Config(
|
|
122
|
+
access_key_id=self.config.fc_access_key_id,
|
|
123
|
+
access_key_secret=self.config.fc_access_key_secret,
|
|
124
|
+
endpoint=f"{self.config.fc_account_id}.{self.config.fc_region_id}.fc.aliyuncs.com",
|
|
125
|
+
)
|
|
126
|
+
return FC20230330Client(fc_config)
|
|
127
|
+
|
|
128
|
+
def _test_connection(self):
|
|
129
|
+
"""Test the connection to Function Compute service."""
|
|
130
|
+
try:
|
|
131
|
+
list_request = fc20230330_models.ListFunctionsRequest(limit=1)
|
|
132
|
+
|
|
133
|
+
response = self.fc_client.list_functions(request=list_request)
|
|
134
|
+
|
|
135
|
+
if hasattr(response, "body") and hasattr(
|
|
136
|
+
response.body,
|
|
137
|
+
"functions",
|
|
138
|
+
):
|
|
139
|
+
functions = response.body.functions
|
|
140
|
+
func_count = len(functions) if functions else 0
|
|
141
|
+
logger.debug(
|
|
142
|
+
f"FunctionComputeClient FC connection test successful: {func_count} functions",
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
except Exception as e:
|
|
146
|
+
logger.warning(
|
|
147
|
+
f"FunctionComputeClient FC connection test failed: {e}",
|
|
148
|
+
)
|
|
149
|
+
logger.warning(
|
|
150
|
+
"FunctionComputeClient This may not affect normal usage. If there are permission issues, please check AccessKey permission configuration.",
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
def create(
|
|
154
|
+
self,
|
|
155
|
+
image,
|
|
156
|
+
name=None,
|
|
157
|
+
ports=None,
|
|
158
|
+
volumes=None,
|
|
159
|
+
environment=None,
|
|
160
|
+
runtime_config=None,
|
|
161
|
+
):
|
|
162
|
+
"""Create a new Function Compute session with the specified parameters.
|
|
163
|
+
|
|
164
|
+
Args:
|
|
165
|
+
image (str): The container image to use for the Function Compute session.
|
|
166
|
+
name (str, optional): The name for the session. If not provided,
|
|
167
|
+
a random name will be generated.
|
|
168
|
+
ports (list, optional): List of ports to expose.
|
|
169
|
+
volumes (list, optional): List of volumes to mount.
|
|
170
|
+
environment (dict, optional): Environment variables to set in
|
|
171
|
+
the container.
|
|
172
|
+
runtime_config (dict, optional): Additional runtime configuration.
|
|
173
|
+
|
|
174
|
+
Returns:
|
|
175
|
+
tuple: A tuple containing (session_id, ports, endpoint_public_url_domain, protocol).
|
|
176
|
+
|
|
177
|
+
Raises:
|
|
178
|
+
Exception: If the Function Compute session creation fails.
|
|
179
|
+
"""
|
|
180
|
+
port = 80
|
|
181
|
+
if ports is not None and len(ports) > 0:
|
|
182
|
+
port = 80 if ports[0] == "80/tcp" else ports[0]
|
|
183
|
+
fc_image = self._replace_fc_images(image)
|
|
184
|
+
try:
|
|
185
|
+
# 1. Generate session ID and function name
|
|
186
|
+
session_id = name or self._generate_session_id()
|
|
187
|
+
function_name = f"{self.function_prefix}-{session_id}"
|
|
188
|
+
|
|
189
|
+
custom_container_config = fc20230330_models.CustomContainerConfig(
|
|
190
|
+
image=fc_image,
|
|
191
|
+
port=port,
|
|
192
|
+
acceleration_type="Default",
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
# 2. Build custom container configuration
|
|
196
|
+
health_check_url = "/"
|
|
197
|
+
health_check_config = fc20230330_models.CustomHealthCheckConfig(
|
|
198
|
+
failure_threshold=60,
|
|
199
|
+
http_get_url=health_check_url,
|
|
200
|
+
initial_delay_seconds=2,
|
|
201
|
+
period_seconds=1,
|
|
202
|
+
success_threshold=1,
|
|
203
|
+
timeout_seconds=1,
|
|
204
|
+
)
|
|
205
|
+
custom_container_config.health_check_config = health_check_config
|
|
206
|
+
logger.info(
|
|
207
|
+
f"FunctionComputeClient building custom health check configuration: {health_check_config}",
|
|
208
|
+
)
|
|
209
|
+
# 3. Build function creation parameters (based on tested successful configuration)
|
|
210
|
+
create_function_kwargs = {
|
|
211
|
+
"function_name": function_name,
|
|
212
|
+
"runtime": "custom-container",
|
|
213
|
+
"custom_container_config": custom_container_config,
|
|
214
|
+
"description": f"AgentScope Runtime Sandbox Function - {session_id}",
|
|
215
|
+
"timeout": 300,
|
|
216
|
+
"memory_size": self.config.fc_memory if self.config else 2048,
|
|
217
|
+
"disk_size": 512,
|
|
218
|
+
"cpu": self.config.fc_cpu if self.config else 2,
|
|
219
|
+
"instance_concurrency": 200,
|
|
220
|
+
"internet_access": True,
|
|
221
|
+
"environment_variables": environment or {},
|
|
222
|
+
"session_affinity": "HEADER_FIELD",
|
|
223
|
+
"instance_isolation_mode": "SESSION_EXCLUSIVE",
|
|
224
|
+
"session_affinity_config": '{"affinityHeaderFieldName":"x-agentscope-runtime-session-id","sessionTTLInSeconds":21600,"sessionConcurrencyPerInstance":1,"sessionIdleTimeoutInSeconds":3600}',
|
|
225
|
+
}
|
|
226
|
+
# 5. If log configuration exists
|
|
227
|
+
if hasattr(self.config, "fc_log_store") and hasattr(
|
|
228
|
+
self.config,
|
|
229
|
+
"fc_log_project",
|
|
230
|
+
):
|
|
231
|
+
if self.config.fc_log_store and self.config.fc_log_project:
|
|
232
|
+
log_config = fc20230330_models.LogConfig(
|
|
233
|
+
logstore=self.config.fc_log_store,
|
|
234
|
+
project=self.config.fc_log_project,
|
|
235
|
+
enable_request_metrics=True,
|
|
236
|
+
enable_instance_metrics=True,
|
|
237
|
+
log_begin_rule="DefaultRegex",
|
|
238
|
+
)
|
|
239
|
+
create_function_kwargs["log_config"] = log_config
|
|
240
|
+
logger.debug(
|
|
241
|
+
f"Configuring log service: {self.config.fc_log_project}/{self.config.fc_log_store}",
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
# 6. If VPC configuration exists
|
|
245
|
+
if (
|
|
246
|
+
hasattr(self.config, "fc_vpc_id")
|
|
247
|
+
and hasattr(self.config, "fc_vswitch_ids")
|
|
248
|
+
and hasattr(self.config, "fc_security_group_id")
|
|
249
|
+
):
|
|
250
|
+
if (
|
|
251
|
+
self.config.fc_vpc_id
|
|
252
|
+
and self.config.fc_vswitch_ids
|
|
253
|
+
and self.config.fc_security_group_id
|
|
254
|
+
):
|
|
255
|
+
vpc_config = fc20230330_models.VPCConfig(
|
|
256
|
+
vpc_id=self.config.fc_vpc_id,
|
|
257
|
+
v_switch_ids=self.config.fc_vswitch_ids,
|
|
258
|
+
security_group_id=self.config.fc_security_group_id,
|
|
259
|
+
)
|
|
260
|
+
create_function_kwargs["vpc_config"] = vpc_config
|
|
261
|
+
logger.debug(
|
|
262
|
+
f"Configuring VPC network: {self.config.fc_vpc_id}",
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
# 7. Create function (based on API call method)
|
|
266
|
+
create_function_input = fc20230330_models.CreateFunctionInput(
|
|
267
|
+
**create_function_kwargs,
|
|
268
|
+
)
|
|
269
|
+
create_function_request = fc20230330_models.CreateFunctionRequest(
|
|
270
|
+
body=create_function_input,
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
runtime_options = util_models.RuntimeOptions()
|
|
274
|
+
headers = {}
|
|
275
|
+
|
|
276
|
+
response = self.fc_client.create_function_with_options(
|
|
277
|
+
create_function_request,
|
|
278
|
+
headers,
|
|
279
|
+
runtime_options,
|
|
280
|
+
)
|
|
281
|
+
|
|
282
|
+
logger.debug(
|
|
283
|
+
"FunctionComputeClient function created successfully!",
|
|
284
|
+
)
|
|
285
|
+
logger.info(
|
|
286
|
+
f"FunctionComputeClient function name: {response.body.function_name}",
|
|
287
|
+
)
|
|
288
|
+
logger.info(
|
|
289
|
+
f"FunctionComputeClient runtime: {response.body.runtime}",
|
|
290
|
+
)
|
|
291
|
+
logger.info(
|
|
292
|
+
f"FunctionComputeClient create time: {response.body.created_time}",
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
# 8. Create HTTP trigger
|
|
296
|
+
trigger_info = self._create_http_trigger(function_name, session_id)
|
|
297
|
+
trigger_name = trigger_info["trigger_name"]
|
|
298
|
+
# 9. Build access URL (using the real URL returned by the trigger)
|
|
299
|
+
endpoint_internet_url = trigger_info["url_internet"]
|
|
300
|
+
endpoint_intranet_url = trigger_info["url_intranet"]
|
|
301
|
+
# Poll for function ready status
|
|
302
|
+
while True:
|
|
303
|
+
if self.check_function_ready(function_name):
|
|
304
|
+
break
|
|
305
|
+
time.sleep(3)
|
|
306
|
+
logger.info(
|
|
307
|
+
f"Check function deployment status, function name: {function_name}",
|
|
308
|
+
)
|
|
309
|
+
# 10. Create session data
|
|
310
|
+
session_data = {
|
|
311
|
+
"session_id": session_id,
|
|
312
|
+
"function_name": function_name,
|
|
313
|
+
"trigger_name": trigger_name,
|
|
314
|
+
"trigger_id": trigger_info["trigger_id"],
|
|
315
|
+
"created_time": time.time(),
|
|
316
|
+
"status": "running",
|
|
317
|
+
"image": fc_image,
|
|
318
|
+
"ports": ports,
|
|
319
|
+
"environment": environment,
|
|
320
|
+
"runtime_token": environment["SECRET_TOKEN"],
|
|
321
|
+
"url_internet": endpoint_internet_url,
|
|
322
|
+
"url_intranet": endpoint_intranet_url,
|
|
323
|
+
}
|
|
324
|
+
# 11. Register session
|
|
325
|
+
self.session_manager.create_session(session_id, session_data)
|
|
326
|
+
|
|
327
|
+
logger.info(
|
|
328
|
+
f"FunctionComputeClient FC function {session_id} created and registered session successfully",
|
|
329
|
+
)
|
|
330
|
+
|
|
331
|
+
parsed_url = urlparse(endpoint_internet_url)
|
|
332
|
+
|
|
333
|
+
endpoint_public_url_domain = parsed_url.netloc
|
|
334
|
+
endpoint_public_url_path = parsed_url.path
|
|
335
|
+
|
|
336
|
+
# FC should adapt for ip and port format
|
|
337
|
+
ports = [f"{HTTPS_PORT}{endpoint_public_url_path}"]
|
|
338
|
+
# If no port needed, we will return None
|
|
339
|
+
return (
|
|
340
|
+
session_id,
|
|
341
|
+
ports,
|
|
342
|
+
endpoint_public_url_domain,
|
|
343
|
+
self.HTTPS_PROTOCOL,
|
|
344
|
+
)
|
|
345
|
+
|
|
346
|
+
except Exception as e:
|
|
347
|
+
logger.error(f"Create FC function failed: {e}")
|
|
348
|
+
# Provide more detailed error information
|
|
349
|
+
if "InvalidAccessKeyId" in str(e):
|
|
350
|
+
logger.error(
|
|
351
|
+
"Authentication failed, please check if FC_ACCESS_KEY_ID is correct",
|
|
352
|
+
)
|
|
353
|
+
elif "SignatureDoesNotMatch" in str(e):
|
|
354
|
+
logger.error(
|
|
355
|
+
"Signature mismatch, please check if FC_ACCESS_KEY_SECRET is correct",
|
|
356
|
+
)
|
|
357
|
+
elif "Forbidden" in str(e):
|
|
358
|
+
logger.error(
|
|
359
|
+
"Insufficient permissions, please check if AccessKey has FC service permissions",
|
|
360
|
+
)
|
|
361
|
+
raise RuntimeError(f"FC function creation failed: {e}") from e
|
|
362
|
+
|
|
363
|
+
def check_function_ready(self, function_name):
|
|
364
|
+
"""Check if the function is ready.
|
|
365
|
+
|
|
366
|
+
Args:
|
|
367
|
+
function_name (str): The name of the function to check.
|
|
368
|
+
|
|
369
|
+
Returns:
|
|
370
|
+
bool: True if the function is ready, False otherwise.
|
|
371
|
+
"""
|
|
372
|
+
try:
|
|
373
|
+
status = self._get_function_status(function_name)
|
|
374
|
+
return status == "running"
|
|
375
|
+
except Exception as e:
|
|
376
|
+
logger.error(f"Error checking function status: {e}")
|
|
377
|
+
return False
|
|
378
|
+
|
|
379
|
+
def start(self, session_id):
|
|
380
|
+
"""Start function (FC functions run automatically).
|
|
381
|
+
|
|
382
|
+
Args:
|
|
383
|
+
session_id (str): The ID of the session to start.
|
|
384
|
+
|
|
385
|
+
Returns:
|
|
386
|
+
bool: True if the function was successfully started, False otherwise.
|
|
387
|
+
"""
|
|
388
|
+
session = self.session_manager.get_session(session_id)
|
|
389
|
+
if not session:
|
|
390
|
+
logger.warning(
|
|
391
|
+
f"FunctionComputeClient session record not found: {session_id}",
|
|
392
|
+
)
|
|
393
|
+
return False
|
|
394
|
+
|
|
395
|
+
timeout_seconds = 300
|
|
396
|
+
interval = 2
|
|
397
|
+
max_retries = timeout_seconds // interval
|
|
398
|
+
|
|
399
|
+
for i in range(max_retries):
|
|
400
|
+
time.sleep(interval)
|
|
401
|
+
function_status = self.get_status(session_id)
|
|
402
|
+
|
|
403
|
+
if function_status == "running":
|
|
404
|
+
break
|
|
405
|
+
|
|
406
|
+
logger.debug(
|
|
407
|
+
f"FunctionComputeClient waiting for FC function to be ready... ({i + 1}/{max_retries}) | "
|
|
408
|
+
f"Current status: {function_status}, session: {session_id}",
|
|
409
|
+
)
|
|
410
|
+
else:
|
|
411
|
+
logger.warning(
|
|
412
|
+
f"FunctionComputeClient start timeout: Waiting for FC function to enter running state exceeded {timeout_seconds} seconds, "
|
|
413
|
+
f"final status: {self.get_status(session_id)}, session: {session_id}",
|
|
414
|
+
)
|
|
415
|
+
return False
|
|
416
|
+
|
|
417
|
+
# Update session status to running
|
|
418
|
+
self.session_manager.update_session(session_id, {"status": "running"})
|
|
419
|
+
logger.info(f"FunctionComputeClient FC function started: {session_id}")
|
|
420
|
+
return True
|
|
421
|
+
|
|
422
|
+
def stop(self, session_id, timeout=None):
|
|
423
|
+
"""Stop function (update status, FC functions do not need explicit stopping).
|
|
424
|
+
|
|
425
|
+
Args:
|
|
426
|
+
session_id (str): The ID of the session to stop.
|
|
427
|
+
timeout (int, optional): Timeout for the stop operation.
|
|
428
|
+
|
|
429
|
+
Returns:
|
|
430
|
+
bool: True if the function was successfully stopped, False otherwise.
|
|
431
|
+
"""
|
|
432
|
+
session = self.session_manager.get_session(session_id)
|
|
433
|
+
if not session:
|
|
434
|
+
logger.warning(
|
|
435
|
+
f"FunctionComputeClient session record not found: {session_id}",
|
|
436
|
+
)
|
|
437
|
+
return False
|
|
438
|
+
|
|
439
|
+
try:
|
|
440
|
+
# FC functions cannot be directly stopped, only update session status
|
|
441
|
+
# TODO Need to call function disable interface
|
|
442
|
+
self.session_manager.update_session(
|
|
443
|
+
session_id,
|
|
444
|
+
{"status": "stopped"},
|
|
445
|
+
)
|
|
446
|
+
logger.info(
|
|
447
|
+
f"FunctionComputeClient FC function status set to stopped: {session_id}",
|
|
448
|
+
)
|
|
449
|
+
return True
|
|
450
|
+
|
|
451
|
+
except Exception as e:
|
|
452
|
+
logger.error(
|
|
453
|
+
f"FunctionComputeClient stop FC function failed {session_id}: {e}",
|
|
454
|
+
)
|
|
455
|
+
return False
|
|
456
|
+
|
|
457
|
+
def remove(self, session_id, force=False):
|
|
458
|
+
"""Remove function - Deletion process based on test verification.
|
|
459
|
+
|
|
460
|
+
Args:
|
|
461
|
+
session_id (str): The ID of the session to remove.
|
|
462
|
+
force (bool, optional): Whether to force removal. Defaults to False.
|
|
463
|
+
|
|
464
|
+
Returns:
|
|
465
|
+
bool: True if the function was successfully removed, False otherwise.
|
|
466
|
+
"""
|
|
467
|
+
session = self.session_manager.get_session(session_id)
|
|
468
|
+
if not session:
|
|
469
|
+
logger.warning(
|
|
470
|
+
f"FunctionComputeClient session record not found, skipping deletion: {session_id}",
|
|
471
|
+
)
|
|
472
|
+
return True
|
|
473
|
+
|
|
474
|
+
function_name = session.get("function_name")
|
|
475
|
+
trigger_name = session.get("trigger_name")
|
|
476
|
+
|
|
477
|
+
try:
|
|
478
|
+
logger.info(
|
|
479
|
+
f"FunctionComputeClient starting to delete FC function: {function_name}",
|
|
480
|
+
)
|
|
481
|
+
|
|
482
|
+
# 1. Delete trigger first (if exists)
|
|
483
|
+
if trigger_name:
|
|
484
|
+
try:
|
|
485
|
+
# Delete trigger API call based on test verification (without request object)
|
|
486
|
+
self.fc_client.delete_trigger_with_options(
|
|
487
|
+
function_name,
|
|
488
|
+
trigger_name,
|
|
489
|
+
{},
|
|
490
|
+
util_models.RuntimeOptions(),
|
|
491
|
+
)
|
|
492
|
+
logger.debug(
|
|
493
|
+
f"FunctionComputeClient trigger deleted: {trigger_name}",
|
|
494
|
+
)
|
|
495
|
+
except Exception as trigger_error:
|
|
496
|
+
logger.warning(
|
|
497
|
+
f"FunctionComputeClient delete trigger failed (continuing to delete function): {trigger_error}",
|
|
498
|
+
)
|
|
499
|
+
|
|
500
|
+
# 2. Delete function (API call method based on test verification)
|
|
501
|
+
self.fc_client.delete_function_with_options(
|
|
502
|
+
function_name,
|
|
503
|
+
{},
|
|
504
|
+
util_models.RuntimeOptions(),
|
|
505
|
+
)
|
|
506
|
+
|
|
507
|
+
# 3. Delete session record
|
|
508
|
+
self.session_manager.delete_session(session_id)
|
|
509
|
+
|
|
510
|
+
logger.info(
|
|
511
|
+
f"FunctionComputeClient FC function deleted successfully: {function_name}",
|
|
512
|
+
)
|
|
513
|
+
return True
|
|
514
|
+
|
|
515
|
+
except Exception as e:
|
|
516
|
+
logger.error(
|
|
517
|
+
f"FunctionComputeClient delete FC function failed: {e}",
|
|
518
|
+
)
|
|
519
|
+
if force:
|
|
520
|
+
# Force cleanup - delete session record even if API call fails
|
|
521
|
+
self.session_manager.delete_session(session_id)
|
|
522
|
+
logger.warning(
|
|
523
|
+
f"FunctionComputeClient force delete session record: {session_id}",
|
|
524
|
+
)
|
|
525
|
+
return True
|
|
526
|
+
raise RuntimeError(
|
|
527
|
+
f"FunctionComputeClient FC function removal failed: {e}",
|
|
528
|
+
) from e
|
|
529
|
+
|
|
530
|
+
def inspect(self, session_id):
|
|
531
|
+
"""Get function detailed information - Implementation based on test verification.
|
|
532
|
+
|
|
533
|
+
Args:
|
|
534
|
+
session_id (str): The ID of the session to inspect.
|
|
535
|
+
|
|
536
|
+
Returns:
|
|
537
|
+
dict: A dictionary containing session information, function info, and status.
|
|
538
|
+
"""
|
|
539
|
+
session = self.session_manager.get_session(session_id)
|
|
540
|
+
if not session:
|
|
541
|
+
logger.warning(
|
|
542
|
+
f"FunctionComputeClient session record not found: {session_id}",
|
|
543
|
+
)
|
|
544
|
+
return None
|
|
545
|
+
|
|
546
|
+
function_name = session.get("function_name")
|
|
547
|
+
|
|
548
|
+
try:
|
|
549
|
+
# Get function information (API call based on test verification)
|
|
550
|
+
function_query_request = fc20230330_models.GetFunctionRequest(
|
|
551
|
+
qualifier="LATEST",
|
|
552
|
+
)
|
|
553
|
+
|
|
554
|
+
response = self.fc_client.get_function(
|
|
555
|
+
function_name=function_name,
|
|
556
|
+
request=function_query_request,
|
|
557
|
+
)
|
|
558
|
+
logger.info(f"FunctionComputeClient function inspect ${response}")
|
|
559
|
+
|
|
560
|
+
function_info = {
|
|
561
|
+
"function_name": response.body.function_name
|
|
562
|
+
if hasattr(
|
|
563
|
+
response.body,
|
|
564
|
+
"function_name",
|
|
565
|
+
)
|
|
566
|
+
else function_name,
|
|
567
|
+
"runtime": response.body.runtime
|
|
568
|
+
if hasattr(response.body, "runtime")
|
|
569
|
+
else "unknown",
|
|
570
|
+
"state": response.body.state
|
|
571
|
+
if hasattr(response.body, "state")
|
|
572
|
+
else "unknown",
|
|
573
|
+
"created_time": response.body.created_time
|
|
574
|
+
if hasattr(response.body, "created_time")
|
|
575
|
+
else "unknown",
|
|
576
|
+
"last_modified_time": response.body.last_modified_time
|
|
577
|
+
if hasattr(
|
|
578
|
+
response.body,
|
|
579
|
+
"last_modified_time",
|
|
580
|
+
)
|
|
581
|
+
else "unknown",
|
|
582
|
+
"memory_size": response.body.memory_size
|
|
583
|
+
if hasattr(response.body, "memory_size")
|
|
584
|
+
else 0,
|
|
585
|
+
"timeout": response.body.timeout
|
|
586
|
+
if hasattr(response.body, "timeout")
|
|
587
|
+
else 0,
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
return {
|
|
591
|
+
"session": session,
|
|
592
|
+
"function_info": function_info,
|
|
593
|
+
"runtime_token": session.get("runtime_token"),
|
|
594
|
+
"status": session.get("status", "unknown"),
|
|
595
|
+
"endpoint_url": session.get("url_internet"),
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
except Exception as e:
|
|
599
|
+
logger.error(
|
|
600
|
+
f"FunctionComputeClient get FC function information failed: {e}",
|
|
601
|
+
)
|
|
602
|
+
# Even if API call fails, return session data
|
|
603
|
+
return {
|
|
604
|
+
"session": session,
|
|
605
|
+
"function_info": {},
|
|
606
|
+
"runtime_token": session.get("runtime_token"),
|
|
607
|
+
"status": session.get("status", "unknown"),
|
|
608
|
+
"error": str(e),
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
def _get_function_status(self, function_name):
|
|
612
|
+
"""Get function status.
|
|
613
|
+
|
|
614
|
+
Args:
|
|
615
|
+
function_name (str): The name of the function to get status for.
|
|
616
|
+
|
|
617
|
+
Returns:
|
|
618
|
+
str: The status of the function.
|
|
619
|
+
"""
|
|
620
|
+
try:
|
|
621
|
+
# Get function status (API call based on test verification)
|
|
622
|
+
function_query_request = fc20230330_models.GetFunctionRequest(
|
|
623
|
+
qualifier="LATEST",
|
|
624
|
+
)
|
|
625
|
+
response = self.fc_client.get_function(
|
|
626
|
+
function_name=function_name,
|
|
627
|
+
request=function_query_request,
|
|
628
|
+
)
|
|
629
|
+
# Return function status (Active, Inactive, Pending)
|
|
630
|
+
if hasattr(response.body, "state"):
|
|
631
|
+
state = response.body.state.lower()
|
|
632
|
+
# Map FC status to container status
|
|
633
|
+
if state == "active":
|
|
634
|
+
return "running"
|
|
635
|
+
elif state == "inactive":
|
|
636
|
+
return "exited"
|
|
637
|
+
elif state == "pending":
|
|
638
|
+
return "creating"
|
|
639
|
+
else:
|
|
640
|
+
return state
|
|
641
|
+
else:
|
|
642
|
+
return "unknown"
|
|
643
|
+
except Exception as e:
|
|
644
|
+
logger.error(
|
|
645
|
+
f"FunctionComputeClient get FC function status failed: {e}",
|
|
646
|
+
)
|
|
647
|
+
# If API call fails, return status from session
|
|
648
|
+
return "unknown"
|
|
649
|
+
|
|
650
|
+
def get_status(self, session_id):
|
|
651
|
+
"""Get function status - Implementation based on test verification.
|
|
652
|
+
|
|
653
|
+
Args:
|
|
654
|
+
session_id (str): The ID of the session to get status for.
|
|
655
|
+
|
|
656
|
+
Returns:
|
|
657
|
+
str: The status of the function (running, exited, creating, or unknown).
|
|
658
|
+
"""
|
|
659
|
+
session = self.session_manager.get_session(session_id)
|
|
660
|
+
if not session:
|
|
661
|
+
logger.warning(
|
|
662
|
+
f"FunctionComputeClient session record not found: {session_id}",
|
|
663
|
+
)
|
|
664
|
+
return "not_found"
|
|
665
|
+
|
|
666
|
+
function_name = session.get("function_name")
|
|
667
|
+
status = self._get_function_status(function_name)
|
|
668
|
+
if status == "unknown":
|
|
669
|
+
return session.get("status", "unknown")
|
|
670
|
+
return status
|
|
671
|
+
|
|
672
|
+
def _generate_session_id(self) -> str:
|
|
673
|
+
"""Generate a unique session ID - Method based on test verification.
|
|
674
|
+
|
|
675
|
+
Returns:
|
|
676
|
+
str: A randomly generated 6-character session ID.
|
|
677
|
+
"""
|
|
678
|
+
return "".join(
|
|
679
|
+
random.choices(string.ascii_letters + string.digits, k=6),
|
|
680
|
+
)
|
|
681
|
+
|
|
682
|
+
def _generate_runtime_token(self) -> str:
|
|
683
|
+
"""Generate a runtime token for authentication.
|
|
684
|
+
|
|
685
|
+
Returns:
|
|
686
|
+
str: A randomly generated 16-byte hex token.
|
|
687
|
+
"""
|
|
688
|
+
return secrets.token_hex(16)
|
|
689
|
+
|
|
690
|
+
def _create_http_trigger(
|
|
691
|
+
self,
|
|
692
|
+
function_name: str,
|
|
693
|
+
session_id: str,
|
|
694
|
+
) -> dict:
|
|
695
|
+
"""Create an HTTP trigger for the function - Implementation based on test verification.
|
|
696
|
+
|
|
697
|
+
Args:
|
|
698
|
+
function_name (str): The name of the function to create a trigger for.
|
|
699
|
+
session_id (str): The session ID for this trigger.
|
|
700
|
+
|
|
701
|
+
Returns:
|
|
702
|
+
dict: A dictionary containing trigger information in the format:
|
|
703
|
+
{
|
|
704
|
+
'trigger_name': str,
|
|
705
|
+
'url_internet': str,
|
|
706
|
+
'url_intranet': str,
|
|
707
|
+
'trigger_id': str
|
|
708
|
+
}
|
|
709
|
+
"""
|
|
710
|
+
trigger_name = f"sandbox-http-trigger-{session_id}"
|
|
711
|
+
|
|
712
|
+
try:
|
|
713
|
+
logger.debug(
|
|
714
|
+
f"FunctionComputeClient creating HTTP trigger: {trigger_name}",
|
|
715
|
+
)
|
|
716
|
+
|
|
717
|
+
# Build trigger configuration (based on test verified configuration)
|
|
718
|
+
trigger_config_dict = {
|
|
719
|
+
"authType": "anonymous",
|
|
720
|
+
"methods": ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS"],
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
# Create trigger input
|
|
724
|
+
trigger_input = fc20230330_models.CreateTriggerInput(
|
|
725
|
+
trigger_name=trigger_name,
|
|
726
|
+
trigger_type="http",
|
|
727
|
+
trigger_config=json.dumps(trigger_config_dict),
|
|
728
|
+
description=f"HTTP trigger for sandbox session {session_id}",
|
|
729
|
+
)
|
|
730
|
+
|
|
731
|
+
# Create trigger request
|
|
732
|
+
create_trigger_request = fc20230330_models.CreateTriggerRequest(
|
|
733
|
+
body=trigger_input,
|
|
734
|
+
)
|
|
735
|
+
|
|
736
|
+
# Call API to create trigger
|
|
737
|
+
response = self.fc_client.create_trigger_with_options(
|
|
738
|
+
function_name=function_name,
|
|
739
|
+
request=create_trigger_request,
|
|
740
|
+
headers={},
|
|
741
|
+
runtime=util_models.RuntimeOptions(),
|
|
742
|
+
)
|
|
743
|
+
|
|
744
|
+
logger.info(
|
|
745
|
+
f"FunctionComputeClient HTTP trigger created successfully: {trigger_name}",
|
|
746
|
+
)
|
|
747
|
+
logger.debug(
|
|
748
|
+
f"FunctionComputeClient HTTP trigger response: {response}",
|
|
749
|
+
)
|
|
750
|
+
|
|
751
|
+
# Extract trigger information from response
|
|
752
|
+
trigger_info = {
|
|
753
|
+
"trigger_name": trigger_name,
|
|
754
|
+
"url_internet": None,
|
|
755
|
+
"url_intranet": None,
|
|
756
|
+
"trigger_id": None,
|
|
757
|
+
"qualifier": "LATEST",
|
|
758
|
+
"last_modified_time": None,
|
|
759
|
+
"created_time": None,
|
|
760
|
+
"status": None,
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
# Parse response body to get URL information
|
|
764
|
+
if hasattr(response, "body") and response.body:
|
|
765
|
+
body = response.body
|
|
766
|
+
if hasattr(body, "http_trigger") and body.http_trigger:
|
|
767
|
+
http_trigger = body.http_trigger
|
|
768
|
+
if hasattr(http_trigger, "url_internet"):
|
|
769
|
+
trigger_info[
|
|
770
|
+
"url_internet"
|
|
771
|
+
] = http_trigger.url_internet
|
|
772
|
+
if hasattr(http_trigger, "url_intranet"):
|
|
773
|
+
trigger_info[
|
|
774
|
+
"url_intranet"
|
|
775
|
+
] = http_trigger.url_intranet
|
|
776
|
+
|
|
777
|
+
if hasattr(body, "trigger_id"):
|
|
778
|
+
trigger_info["trigger_id"] = body.trigger_id
|
|
779
|
+
if hasattr(body, "last_modified_time"):
|
|
780
|
+
trigger_info[
|
|
781
|
+
"last_modified_time"
|
|
782
|
+
] = body.last_modified_time
|
|
783
|
+
if hasattr(body, "createdTime"):
|
|
784
|
+
trigger_info["created_time"] = body.created_time
|
|
785
|
+
if hasattr(body, "status"):
|
|
786
|
+
trigger_info["status"] = body.status
|
|
787
|
+
if hasattr(body, "qualifier"):
|
|
788
|
+
trigger_info["qualifier"] = body.qualifier
|
|
789
|
+
|
|
790
|
+
logger.info("FunctionComputeClient trigger URL information:")
|
|
791
|
+
logger.info(
|
|
792
|
+
f"FunctionComputeClient - Internet URL: {trigger_info['url_internet']}",
|
|
793
|
+
)
|
|
794
|
+
logger.info(
|
|
795
|
+
f"FunctionComputeClient - Intranet URL: {trigger_info['url_intranet']}",
|
|
796
|
+
)
|
|
797
|
+
logger.info(
|
|
798
|
+
f"FunctionComputeClient - Trigger ID: {trigger_info['trigger_id']}",
|
|
799
|
+
)
|
|
800
|
+
|
|
801
|
+
return trigger_info
|
|
802
|
+
|
|
803
|
+
except Exception as e:
|
|
804
|
+
logger.error(
|
|
805
|
+
f"FunctionComputeClient create HTTP trigger failed: {e}",
|
|
806
|
+
)
|
|
807
|
+
# Even if creation fails, return basic information for subsequent cleanup
|
|
808
|
+
return {
|
|
809
|
+
"trigger_name": trigger_name,
|
|
810
|
+
"url_internet": None,
|
|
811
|
+
"url_intranet": None,
|
|
812
|
+
"qualifier": "LATEST",
|
|
813
|
+
"latest_modified_time": None,
|
|
814
|
+
"created_time": None,
|
|
815
|
+
"status": None,
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
def _replace_fc_images(self, image: str) -> str:
|
|
819
|
+
"""
|
|
820
|
+
Replace agent runtime images with their corresponding remote images.
|
|
821
|
+
|
|
822
|
+
Args:
|
|
823
|
+
image (str): The original image name.
|
|
824
|
+
|
|
825
|
+
Returns:
|
|
826
|
+
str: The replaced image name with remote registry path.
|
|
827
|
+
"""
|
|
828
|
+
replacement_map = {
|
|
829
|
+
"agentscope/runtime-sandbox-base": "serverless-registry.cn-hangzhou.cr.aliyuncs.com/functionai" # noqa: E501
|
|
830
|
+
"/agentscope_runtime-sandbox-base:20251027",
|
|
831
|
+
"agentscope/runtime-sandbox-browser": "serverless-registry.cn-hangzhou.cr.aliyuncs.com/functionai" # noqa: E501
|
|
832
|
+
"/agentscope_runtime-sandbox-browser:20251027",
|
|
833
|
+
"agentscope/runtime-sandbox-filesystem": "serverless-registry.cn-hangzhou.cr.aliyuncs.com/functionai" # noqa: E501
|
|
834
|
+
"/agentscope_runtime-sandbox-filesystem:20251027",
|
|
835
|
+
"agentscope/runtime-sandbox-gui": "serverless-registry.cn-hangzhou.cr.aliyuncs.com/functionai" # noqa: E501
|
|
836
|
+
"/agentscope_runtime-sandbox-gui:20251027",
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
if ":" in image:
|
|
840
|
+
image_name, _ = image.split(":", 1)
|
|
841
|
+
else:
|
|
842
|
+
image_name = image
|
|
843
|
+
|
|
844
|
+
return replacement_map.get(image_name.strip(), image)
|
|
845
|
+
|
|
846
|
+
def _is_browser_image(self, image: str) -> bool:
|
|
847
|
+
"""Check if the image is a browser image.
|
|
848
|
+
|
|
849
|
+
Args:
|
|
850
|
+
image (str): The image name to check.
|
|
851
|
+
|
|
852
|
+
Returns:
|
|
853
|
+
bool: True if the image is a browser image, False otherwise.
|
|
854
|
+
"""
|
|
855
|
+
return image.startswith("agentscope/runtime-sandbox-browser")
|