agentscope-runtime 0.1.5b2__py3-none-any.whl → 0.2.0b2__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/common/__init__.py +0 -0
- agentscope_runtime/common/collections/in_memory_mapping.py +27 -0
- agentscope_runtime/common/collections/redis_mapping.py +42 -0
- agentscope_runtime/common/container_clients/__init__.py +0 -0
- agentscope_runtime/common/container_clients/agentrun_client.py +1098 -0
- agentscope_runtime/common/container_clients/docker_client.py +250 -0
- agentscope_runtime/{sandbox/manager → common}/container_clients/kubernetes_client.py +6 -13
- agentscope_runtime/engine/__init__.py +12 -0
- agentscope_runtime/engine/agents/agentscope_agent.py +488 -0
- agentscope_runtime/engine/agents/agno_agent.py +26 -27
- agentscope_runtime/engine/agents/autogen_agent.py +13 -8
- agentscope_runtime/engine/agents/utils.py +53 -0
- agentscope_runtime/engine/app/__init__.py +6 -0
- agentscope_runtime/engine/app/agent_app.py +239 -0
- agentscope_runtime/engine/app/base_app.py +181 -0
- agentscope_runtime/engine/app/celery_mixin.py +92 -0
- agentscope_runtime/engine/deployers/base.py +1 -0
- agentscope_runtime/engine/deployers/cli_fc_deploy.py +39 -20
- agentscope_runtime/engine/deployers/kubernetes_deployer.py +12 -5
- agentscope_runtime/engine/deployers/local_deployer.py +61 -3
- agentscope_runtime/engine/deployers/modelstudio_deployer.py +10 -11
- agentscope_runtime/engine/deployers/utils/docker_image_utils/runner_image_factory.py +9 -0
- agentscope_runtime/engine/deployers/utils/package_project_utils.py +234 -3
- agentscope_runtime/engine/deployers/utils/service_utils/fastapi_factory.py +567 -7
- agentscope_runtime/engine/deployers/utils/service_utils/standalone_main.py.j2 +211 -0
- agentscope_runtime/engine/deployers/utils/wheel_packager.py +1 -1
- agentscope_runtime/engine/helpers/helper.py +60 -41
- agentscope_runtime/engine/runner.py +35 -24
- agentscope_runtime/engine/schemas/agent_schemas.py +42 -0
- agentscope_runtime/engine/schemas/modelstudio_llm.py +14 -14
- agentscope_runtime/engine/services/sandbox_service.py +62 -70
- agentscope_runtime/engine/services/tablestore_memory_service.py +307 -0
- agentscope_runtime/engine/services/tablestore_rag_service.py +143 -0
- agentscope_runtime/engine/services/tablestore_session_history_service.py +293 -0
- agentscope_runtime/engine/services/utils/__init__.py +0 -0
- agentscope_runtime/engine/services/utils/tablestore_service_utils.py +352 -0
- agentscope_runtime/engine/tracing/__init__.py +9 -3
- agentscope_runtime/engine/tracing/asyncio_util.py +24 -0
- agentscope_runtime/engine/tracing/base.py +66 -34
- agentscope_runtime/engine/tracing/local_logging_handler.py +45 -31
- agentscope_runtime/engine/tracing/message_util.py +528 -0
- agentscope_runtime/engine/tracing/tracing_metric.py +20 -8
- agentscope_runtime/engine/tracing/tracing_util.py +130 -0
- agentscope_runtime/engine/tracing/wrapper.py +794 -169
- agentscope_runtime/sandbox/__init__.py +2 -0
- agentscope_runtime/sandbox/box/base/__init__.py +4 -0
- agentscope_runtime/sandbox/box/base/base_sandbox.py +6 -4
- agentscope_runtime/sandbox/box/browser/__init__.py +4 -0
- agentscope_runtime/sandbox/box/browser/browser_sandbox.py +10 -14
- agentscope_runtime/sandbox/box/dummy/__init__.py +4 -0
- agentscope_runtime/sandbox/box/dummy/dummy_sandbox.py +2 -1
- agentscope_runtime/sandbox/box/filesystem/__init__.py +4 -0
- agentscope_runtime/sandbox/box/filesystem/filesystem_sandbox.py +10 -7
- agentscope_runtime/sandbox/box/gui/__init__.py +4 -0
- agentscope_runtime/sandbox/box/gui/box/__init__.py +0 -0
- agentscope_runtime/sandbox/box/gui/gui_sandbox.py +81 -0
- agentscope_runtime/sandbox/box/sandbox.py +5 -2
- agentscope_runtime/sandbox/box/shared/routers/generic.py +20 -1
- agentscope_runtime/sandbox/box/training_box/__init__.py +4 -0
- agentscope_runtime/sandbox/box/training_box/training_box.py +7 -54
- agentscope_runtime/sandbox/build.py +143 -58
- agentscope_runtime/sandbox/client/http_client.py +87 -59
- agentscope_runtime/sandbox/client/training_client.py +0 -1
- agentscope_runtime/sandbox/constant.py +27 -1
- agentscope_runtime/sandbox/custom/custom_sandbox.py +7 -6
- agentscope_runtime/sandbox/custom/example.py +4 -3
- agentscope_runtime/sandbox/enums.py +1 -1
- agentscope_runtime/sandbox/manager/sandbox_manager.py +212 -106
- agentscope_runtime/sandbox/manager/server/app.py +82 -14
- agentscope_runtime/sandbox/manager/server/config.py +50 -3
- agentscope_runtime/sandbox/model/container.py +12 -23
- agentscope_runtime/sandbox/model/manager_config.py +93 -5
- agentscope_runtime/sandbox/registry.py +1 -1
- agentscope_runtime/sandbox/tools/gui/__init__.py +7 -0
- agentscope_runtime/sandbox/tools/gui/tool.py +77 -0
- agentscope_runtime/sandbox/tools/mcp_tool.py +6 -2
- agentscope_runtime/sandbox/tools/tool.py +4 -0
- agentscope_runtime/sandbox/utils.py +124 -0
- agentscope_runtime/version.py +1 -1
- {agentscope_runtime-0.1.5b2.dist-info → agentscope_runtime-0.2.0b2.dist-info}/METADATA +214 -102
- {agentscope_runtime-0.1.5b2.dist-info → agentscope_runtime-0.2.0b2.dist-info}/RECORD +94 -78
- agentscope_runtime/engine/agents/agentscope_agent/__init__.py +0 -6
- agentscope_runtime/engine/agents/agentscope_agent/agent.py +0 -401
- agentscope_runtime/engine/agents/agentscope_agent/hooks.py +0 -169
- agentscope_runtime/engine/agents/llm_agent.py +0 -51
- agentscope_runtime/engine/llms/__init__.py +0 -3
- agentscope_runtime/engine/llms/base_llm.py +0 -60
- agentscope_runtime/engine/llms/qwen_llm.py +0 -47
- agentscope_runtime/sandbox/manager/collections/in_memory_mapping.py +0 -22
- agentscope_runtime/sandbox/manager/collections/redis_mapping.py +0 -26
- agentscope_runtime/sandbox/manager/container_clients/__init__.py +0 -10
- agentscope_runtime/sandbox/manager/container_clients/docker_client.py +0 -422
- /agentscope_runtime/{sandbox/manager → common}/collections/__init__.py +0 -0
- /agentscope_runtime/{sandbox/manager → common}/collections/base_mapping.py +0 -0
- /agentscope_runtime/{sandbox/manager → common}/collections/base_queue.py +0 -0
- /agentscope_runtime/{sandbox/manager → common}/collections/base_set.py +0 -0
- /agentscope_runtime/{sandbox/manager → common}/collections/in_memory_queue.py +0 -0
- /agentscope_runtime/{sandbox/manager → common}/collections/in_memory_set.py +0 -0
- /agentscope_runtime/{sandbox/manager → common}/collections/redis_queue.py +0 -0
- /agentscope_runtime/{sandbox/manager → common}/collections/redis_set.py +0 -0
- /agentscope_runtime/{sandbox/manager → common}/container_clients/base_client.py +0 -0
- {agentscope_runtime-0.1.5b2.dist-info → agentscope_runtime-0.2.0b2.dist-info}/WHEEL +0 -0
- {agentscope_runtime-0.1.5b2.dist-info → agentscope_runtime-0.2.0b2.dist-info}/entry_points.txt +0 -0
- {agentscope_runtime-0.1.5b2.dist-info → agentscope_runtime-0.2.0b2.dist-info}/licenses/LICENSE +0 -0
- {agentscope_runtime-0.1.5b2.dist-info → agentscope_runtime-0.2.0b2.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
import traceback
|
|
3
|
+
import logging
|
|
4
|
+
import socket
|
|
5
|
+
|
|
6
|
+
import docker
|
|
7
|
+
|
|
8
|
+
from .base_client import BaseClient
|
|
9
|
+
from ..collections import (
|
|
10
|
+
RedisSetCollection,
|
|
11
|
+
InMemorySetCollection,
|
|
12
|
+
RedisMapping,
|
|
13
|
+
InMemoryMapping,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
logger = logging.getLogger(__name__)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def is_port_available(port):
|
|
21
|
+
"""
|
|
22
|
+
Check if a given port is available (not in use) on the local system.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
port (int): The port number to check.
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
bool: True if the port is available, False if it is in use.
|
|
29
|
+
"""
|
|
30
|
+
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
|
31
|
+
try:
|
|
32
|
+
s.bind(("", port))
|
|
33
|
+
# Port is available
|
|
34
|
+
return True
|
|
35
|
+
except OSError:
|
|
36
|
+
# Port is in use
|
|
37
|
+
return False
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class DockerClient(BaseClient):
|
|
41
|
+
def __init__(self, config=None):
|
|
42
|
+
self.config = config
|
|
43
|
+
self.port_range = range(*self.config.port_range)
|
|
44
|
+
|
|
45
|
+
if self.config.redis_enabled:
|
|
46
|
+
import redis
|
|
47
|
+
|
|
48
|
+
redis_client = redis.Redis(
|
|
49
|
+
host=self.config.redis_server,
|
|
50
|
+
port=self.config.redis_port,
|
|
51
|
+
db=self.config.redis_db,
|
|
52
|
+
username=self.config.redis_user,
|
|
53
|
+
password=self.config.redis_password,
|
|
54
|
+
decode_responses=True,
|
|
55
|
+
)
|
|
56
|
+
try:
|
|
57
|
+
redis_client.ping()
|
|
58
|
+
except ConnectionError as e:
|
|
59
|
+
raise RuntimeError(
|
|
60
|
+
"Unable to connect to the Redis server.",
|
|
61
|
+
) from e
|
|
62
|
+
|
|
63
|
+
self.port_set = RedisSetCollection(
|
|
64
|
+
redis_client,
|
|
65
|
+
set_name=self.config.redis_port_key,
|
|
66
|
+
)
|
|
67
|
+
self.ports_cache = RedisMapping(
|
|
68
|
+
redis_client,
|
|
69
|
+
prefix=self.config.redis_port_key,
|
|
70
|
+
)
|
|
71
|
+
else:
|
|
72
|
+
self.port_set = InMemorySetCollection()
|
|
73
|
+
self.ports_cache = InMemoryMapping()
|
|
74
|
+
|
|
75
|
+
try:
|
|
76
|
+
self.client = docker.from_env()
|
|
77
|
+
except Exception as e:
|
|
78
|
+
raise RuntimeError(
|
|
79
|
+
f"Docker client initialization failed: {str(e)}\n"
|
|
80
|
+
"Solutions:\n"
|
|
81
|
+
"• Ensure Docker is running\n"
|
|
82
|
+
"• Check Docker permissions\n"
|
|
83
|
+
"• For Colima: "
|
|
84
|
+
"export DOCKER_HOST=unix://$HOME/.colima/docker.sock",
|
|
85
|
+
) from e
|
|
86
|
+
|
|
87
|
+
def create(
|
|
88
|
+
self,
|
|
89
|
+
image,
|
|
90
|
+
name=None,
|
|
91
|
+
ports=None,
|
|
92
|
+
volumes=None,
|
|
93
|
+
environment=None,
|
|
94
|
+
runtime_config=None,
|
|
95
|
+
):
|
|
96
|
+
"""Create a new Docker container."""
|
|
97
|
+
if runtime_config is None:
|
|
98
|
+
runtime_config = {}
|
|
99
|
+
|
|
100
|
+
port_mapping = {}
|
|
101
|
+
|
|
102
|
+
if ports:
|
|
103
|
+
free_port = self._find_free_ports(len(ports))
|
|
104
|
+
for container_port, host_port in zip(ports, free_port):
|
|
105
|
+
port_mapping[container_port] = host_port
|
|
106
|
+
|
|
107
|
+
try:
|
|
108
|
+
try:
|
|
109
|
+
# Check if the image exists locally
|
|
110
|
+
self.client.images.get(image)
|
|
111
|
+
logger.debug(f"Image '{image}' found locally.")
|
|
112
|
+
except docker.errors.ImageNotFound:
|
|
113
|
+
logger.info(
|
|
114
|
+
f"Image '{image}' not found locally. "
|
|
115
|
+
f"Attempting to pull it...",
|
|
116
|
+
)
|
|
117
|
+
try:
|
|
118
|
+
logger.info(
|
|
119
|
+
f"Attempting to pull: {image}, "
|
|
120
|
+
f"it might take several minutes.",
|
|
121
|
+
)
|
|
122
|
+
self.client.images.pull(image)
|
|
123
|
+
logger.debug(
|
|
124
|
+
f"Image '{image}' successfully pulled.",
|
|
125
|
+
)
|
|
126
|
+
except Exception as e:
|
|
127
|
+
logger.error(
|
|
128
|
+
f"Failed to pull image '{image}': {str(e)}",
|
|
129
|
+
)
|
|
130
|
+
return None, None, None
|
|
131
|
+
|
|
132
|
+
except docker.errors.APIError as e:
|
|
133
|
+
logger.error(f"Error occurred while checking the image: {e}")
|
|
134
|
+
return None, None, None
|
|
135
|
+
|
|
136
|
+
# Create and run the container
|
|
137
|
+
container = self.client.containers.run(
|
|
138
|
+
image,
|
|
139
|
+
detach=True,
|
|
140
|
+
ports=port_mapping,
|
|
141
|
+
name=name,
|
|
142
|
+
volumes=volumes,
|
|
143
|
+
environment=environment,
|
|
144
|
+
**runtime_config,
|
|
145
|
+
)
|
|
146
|
+
container.reload()
|
|
147
|
+
_id = container.id
|
|
148
|
+
|
|
149
|
+
self.ports_cache.set(_id, list(port_mapping.values()))
|
|
150
|
+
|
|
151
|
+
return _id, list(port_mapping.values()), "localhost"
|
|
152
|
+
except Exception as e:
|
|
153
|
+
logger.warning(f"An error occurred: {e}")
|
|
154
|
+
logger.debug(f"{traceback.format_exc()}")
|
|
155
|
+
return None, None, None
|
|
156
|
+
|
|
157
|
+
def start(self, container_id):
|
|
158
|
+
"""Start a Docker container."""
|
|
159
|
+
try:
|
|
160
|
+
container = self.client.containers.get(
|
|
161
|
+
container_id,
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
container.start()
|
|
165
|
+
return True
|
|
166
|
+
except Exception as e:
|
|
167
|
+
logger.warning(f"An error occurred: {e}")
|
|
168
|
+
logger.debug(f"{traceback.format_exc()}")
|
|
169
|
+
return False
|
|
170
|
+
|
|
171
|
+
def stop(self, container_id, timeout=None):
|
|
172
|
+
"""Stop a Docker container."""
|
|
173
|
+
try:
|
|
174
|
+
container = self.client.containers.get(
|
|
175
|
+
container_id,
|
|
176
|
+
)
|
|
177
|
+
container.stop(timeout=timeout)
|
|
178
|
+
return True
|
|
179
|
+
except Exception as e:
|
|
180
|
+
logger.warning(f"An error occurred: {e}")
|
|
181
|
+
logger.debug(f"{traceback.format_exc()}")
|
|
182
|
+
return False
|
|
183
|
+
|
|
184
|
+
def remove(self, container_id, force=False):
|
|
185
|
+
"""Remove a Docker container."""
|
|
186
|
+
try:
|
|
187
|
+
container = self.client.containers.get(
|
|
188
|
+
container_id,
|
|
189
|
+
)
|
|
190
|
+
ports = self.ports_cache.get(container_id)
|
|
191
|
+
self.ports_cache.delete(container_id)
|
|
192
|
+
|
|
193
|
+
# Remove container
|
|
194
|
+
container.remove(force=force)
|
|
195
|
+
|
|
196
|
+
# Remove ports
|
|
197
|
+
if ports:
|
|
198
|
+
for host_port in ports:
|
|
199
|
+
self.port_set.remove(host_port)
|
|
200
|
+
|
|
201
|
+
return True
|
|
202
|
+
except Exception as e:
|
|
203
|
+
logger.warning(f"An error occurred: {e}")
|
|
204
|
+
logger.debug(f"{traceback.format_exc()}")
|
|
205
|
+
return False
|
|
206
|
+
|
|
207
|
+
def inspect(self, container_id):
|
|
208
|
+
"""Inspect a Docker container."""
|
|
209
|
+
try:
|
|
210
|
+
# Get the container object
|
|
211
|
+
container = self.client.containers.get(container_id)
|
|
212
|
+
# Access the detailed information
|
|
213
|
+
return container.attrs
|
|
214
|
+
except Exception:
|
|
215
|
+
return None
|
|
216
|
+
|
|
217
|
+
def get_status(self, container_id):
|
|
218
|
+
"""Get the current status of the specified container."""
|
|
219
|
+
container_attrs = self.inspect(container_id=container_id)
|
|
220
|
+
if container_attrs:
|
|
221
|
+
return container_attrs["State"]["Status"]
|
|
222
|
+
return None
|
|
223
|
+
|
|
224
|
+
def _find_free_ports(self, n):
|
|
225
|
+
free_ports = []
|
|
226
|
+
|
|
227
|
+
for port in self.port_range:
|
|
228
|
+
if len(free_ports) >= n:
|
|
229
|
+
break # We have found enough ports
|
|
230
|
+
|
|
231
|
+
if not self.port_set.add(port):
|
|
232
|
+
continue
|
|
233
|
+
|
|
234
|
+
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
|
235
|
+
try:
|
|
236
|
+
s.bind(("", port))
|
|
237
|
+
free_ports.append(port) # Port is available
|
|
238
|
+
|
|
239
|
+
except OSError:
|
|
240
|
+
# Bind failed, port is in use
|
|
241
|
+
self.port_set.remove(port)
|
|
242
|
+
# Try the next one
|
|
243
|
+
continue
|
|
244
|
+
|
|
245
|
+
if len(free_ports) < n:
|
|
246
|
+
raise RuntimeError(
|
|
247
|
+
"Not enough free ports available in the specified range.",
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
return free_ports
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
|
-
# pylint: disable=too-many-branches,
|
|
3
|
-
# pylint: disable=too-many-statements
|
|
4
|
-
|
|
5
|
-
import hashlib
|
|
6
|
-
import logging
|
|
2
|
+
# pylint: disable=too-many-branches,too-many-statements
|
|
7
3
|
import time
|
|
4
|
+
import hashlib
|
|
8
5
|
import traceback
|
|
6
|
+
import logging
|
|
7
|
+
|
|
9
8
|
from typing import Optional, Tuple
|
|
10
9
|
|
|
11
10
|
from kubernetes import client
|
|
@@ -16,14 +15,12 @@ from .base_client import BaseClient
|
|
|
16
15
|
|
|
17
16
|
logger = logging.getLogger(__name__)
|
|
18
17
|
|
|
19
|
-
DEFAULT_IMAGE_REGISTRY = "agentscope-registry.ap-southeast-1.cr.aliyuncs.com"
|
|
20
|
-
|
|
21
18
|
|
|
22
19
|
class KubernetesClient(BaseClient):
|
|
23
20
|
def __init__(
|
|
24
21
|
self,
|
|
25
22
|
config=None,
|
|
26
|
-
image_registry: Optional[str] =
|
|
23
|
+
image_registry: Optional[str] = None,
|
|
27
24
|
):
|
|
28
25
|
self.config = config
|
|
29
26
|
namespace = self.config.k8s_namespace
|
|
@@ -157,11 +154,7 @@ class KubernetesClient(BaseClient):
|
|
|
157
154
|
container_name = name or "main-container"
|
|
158
155
|
|
|
159
156
|
# Container specification
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
if not self.image_registry:
|
|
163
|
-
image = image
|
|
164
|
-
else:
|
|
157
|
+
if self.image_registry:
|
|
165
158
|
image = f"{self.image_registry}/{image}"
|
|
166
159
|
|
|
167
160
|
container = client.V1Container(
|
|
@@ -7,3 +7,15 @@ from .services import (
|
|
|
7
7
|
)
|
|
8
8
|
from .deployers import DeployManager, LocalDeployManager
|
|
9
9
|
from .runner import Runner
|
|
10
|
+
from .app import AgentApp
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
"Service",
|
|
14
|
+
"SandboxService",
|
|
15
|
+
"MemoryService",
|
|
16
|
+
"SessionHistoryService",
|
|
17
|
+
"DeployManager",
|
|
18
|
+
"LocalDeployManager",
|
|
19
|
+
"Runner",
|
|
20
|
+
"AgentApp",
|
|
21
|
+
]
|