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.
Files changed (105) hide show
  1. agentscope_runtime/common/__init__.py +0 -0
  2. agentscope_runtime/common/collections/in_memory_mapping.py +27 -0
  3. agentscope_runtime/common/collections/redis_mapping.py +42 -0
  4. agentscope_runtime/common/container_clients/__init__.py +0 -0
  5. agentscope_runtime/common/container_clients/agentrun_client.py +1098 -0
  6. agentscope_runtime/common/container_clients/docker_client.py +250 -0
  7. agentscope_runtime/{sandbox/manager → common}/container_clients/kubernetes_client.py +6 -13
  8. agentscope_runtime/engine/__init__.py +12 -0
  9. agentscope_runtime/engine/agents/agentscope_agent.py +488 -0
  10. agentscope_runtime/engine/agents/agno_agent.py +26 -27
  11. agentscope_runtime/engine/agents/autogen_agent.py +13 -8
  12. agentscope_runtime/engine/agents/utils.py +53 -0
  13. agentscope_runtime/engine/app/__init__.py +6 -0
  14. agentscope_runtime/engine/app/agent_app.py +239 -0
  15. agentscope_runtime/engine/app/base_app.py +181 -0
  16. agentscope_runtime/engine/app/celery_mixin.py +92 -0
  17. agentscope_runtime/engine/deployers/base.py +1 -0
  18. agentscope_runtime/engine/deployers/cli_fc_deploy.py +39 -20
  19. agentscope_runtime/engine/deployers/kubernetes_deployer.py +12 -5
  20. agentscope_runtime/engine/deployers/local_deployer.py +61 -3
  21. agentscope_runtime/engine/deployers/modelstudio_deployer.py +10 -11
  22. agentscope_runtime/engine/deployers/utils/docker_image_utils/runner_image_factory.py +9 -0
  23. agentscope_runtime/engine/deployers/utils/package_project_utils.py +234 -3
  24. agentscope_runtime/engine/deployers/utils/service_utils/fastapi_factory.py +567 -7
  25. agentscope_runtime/engine/deployers/utils/service_utils/standalone_main.py.j2 +211 -0
  26. agentscope_runtime/engine/deployers/utils/wheel_packager.py +1 -1
  27. agentscope_runtime/engine/helpers/helper.py +60 -41
  28. agentscope_runtime/engine/runner.py +35 -24
  29. agentscope_runtime/engine/schemas/agent_schemas.py +42 -0
  30. agentscope_runtime/engine/schemas/modelstudio_llm.py +14 -14
  31. agentscope_runtime/engine/services/sandbox_service.py +62 -70
  32. agentscope_runtime/engine/services/tablestore_memory_service.py +307 -0
  33. agentscope_runtime/engine/services/tablestore_rag_service.py +143 -0
  34. agentscope_runtime/engine/services/tablestore_session_history_service.py +293 -0
  35. agentscope_runtime/engine/services/utils/__init__.py +0 -0
  36. agentscope_runtime/engine/services/utils/tablestore_service_utils.py +352 -0
  37. agentscope_runtime/engine/tracing/__init__.py +9 -3
  38. agentscope_runtime/engine/tracing/asyncio_util.py +24 -0
  39. agentscope_runtime/engine/tracing/base.py +66 -34
  40. agentscope_runtime/engine/tracing/local_logging_handler.py +45 -31
  41. agentscope_runtime/engine/tracing/message_util.py +528 -0
  42. agentscope_runtime/engine/tracing/tracing_metric.py +20 -8
  43. agentscope_runtime/engine/tracing/tracing_util.py +130 -0
  44. agentscope_runtime/engine/tracing/wrapper.py +794 -169
  45. agentscope_runtime/sandbox/__init__.py +2 -0
  46. agentscope_runtime/sandbox/box/base/__init__.py +4 -0
  47. agentscope_runtime/sandbox/box/base/base_sandbox.py +6 -4
  48. agentscope_runtime/sandbox/box/browser/__init__.py +4 -0
  49. agentscope_runtime/sandbox/box/browser/browser_sandbox.py +10 -14
  50. agentscope_runtime/sandbox/box/dummy/__init__.py +4 -0
  51. agentscope_runtime/sandbox/box/dummy/dummy_sandbox.py +2 -1
  52. agentscope_runtime/sandbox/box/filesystem/__init__.py +4 -0
  53. agentscope_runtime/sandbox/box/filesystem/filesystem_sandbox.py +10 -7
  54. agentscope_runtime/sandbox/box/gui/__init__.py +4 -0
  55. agentscope_runtime/sandbox/box/gui/box/__init__.py +0 -0
  56. agentscope_runtime/sandbox/box/gui/gui_sandbox.py +81 -0
  57. agentscope_runtime/sandbox/box/sandbox.py +5 -2
  58. agentscope_runtime/sandbox/box/shared/routers/generic.py +20 -1
  59. agentscope_runtime/sandbox/box/training_box/__init__.py +4 -0
  60. agentscope_runtime/sandbox/box/training_box/training_box.py +7 -54
  61. agentscope_runtime/sandbox/build.py +143 -58
  62. agentscope_runtime/sandbox/client/http_client.py +87 -59
  63. agentscope_runtime/sandbox/client/training_client.py +0 -1
  64. agentscope_runtime/sandbox/constant.py +27 -1
  65. agentscope_runtime/sandbox/custom/custom_sandbox.py +7 -6
  66. agentscope_runtime/sandbox/custom/example.py +4 -3
  67. agentscope_runtime/sandbox/enums.py +1 -1
  68. agentscope_runtime/sandbox/manager/sandbox_manager.py +212 -106
  69. agentscope_runtime/sandbox/manager/server/app.py +82 -14
  70. agentscope_runtime/sandbox/manager/server/config.py +50 -3
  71. agentscope_runtime/sandbox/model/container.py +12 -23
  72. agentscope_runtime/sandbox/model/manager_config.py +93 -5
  73. agentscope_runtime/sandbox/registry.py +1 -1
  74. agentscope_runtime/sandbox/tools/gui/__init__.py +7 -0
  75. agentscope_runtime/sandbox/tools/gui/tool.py +77 -0
  76. agentscope_runtime/sandbox/tools/mcp_tool.py +6 -2
  77. agentscope_runtime/sandbox/tools/tool.py +4 -0
  78. agentscope_runtime/sandbox/utils.py +124 -0
  79. agentscope_runtime/version.py +1 -1
  80. {agentscope_runtime-0.1.5b2.dist-info → agentscope_runtime-0.2.0b2.dist-info}/METADATA +214 -102
  81. {agentscope_runtime-0.1.5b2.dist-info → agentscope_runtime-0.2.0b2.dist-info}/RECORD +94 -78
  82. agentscope_runtime/engine/agents/agentscope_agent/__init__.py +0 -6
  83. agentscope_runtime/engine/agents/agentscope_agent/agent.py +0 -401
  84. agentscope_runtime/engine/agents/agentscope_agent/hooks.py +0 -169
  85. agentscope_runtime/engine/agents/llm_agent.py +0 -51
  86. agentscope_runtime/engine/llms/__init__.py +0 -3
  87. agentscope_runtime/engine/llms/base_llm.py +0 -60
  88. agentscope_runtime/engine/llms/qwen_llm.py +0 -47
  89. agentscope_runtime/sandbox/manager/collections/in_memory_mapping.py +0 -22
  90. agentscope_runtime/sandbox/manager/collections/redis_mapping.py +0 -26
  91. agentscope_runtime/sandbox/manager/container_clients/__init__.py +0 -10
  92. agentscope_runtime/sandbox/manager/container_clients/docker_client.py +0 -422
  93. /agentscope_runtime/{sandbox/manager → common}/collections/__init__.py +0 -0
  94. /agentscope_runtime/{sandbox/manager → common}/collections/base_mapping.py +0 -0
  95. /agentscope_runtime/{sandbox/manager → common}/collections/base_queue.py +0 -0
  96. /agentscope_runtime/{sandbox/manager → common}/collections/base_set.py +0 -0
  97. /agentscope_runtime/{sandbox/manager → common}/collections/in_memory_queue.py +0 -0
  98. /agentscope_runtime/{sandbox/manager → common}/collections/in_memory_set.py +0 -0
  99. /agentscope_runtime/{sandbox/manager → common}/collections/redis_queue.py +0 -0
  100. /agentscope_runtime/{sandbox/manager → common}/collections/redis_set.py +0 -0
  101. /agentscope_runtime/{sandbox/manager → common}/container_clients/base_client.py +0 -0
  102. {agentscope_runtime-0.1.5b2.dist-info → agentscope_runtime-0.2.0b2.dist-info}/WHEEL +0 -0
  103. {agentscope_runtime-0.1.5b2.dist-info → agentscope_runtime-0.2.0b2.dist-info}/entry_points.txt +0 -0
  104. {agentscope_runtime-0.1.5b2.dist-info → agentscope_runtime-0.2.0b2.dist-info}/licenses/LICENSE +0 -0
  105. {agentscope_runtime-0.1.5b2.dist-info → agentscope_runtime-0.2.0b2.dist-info}/top_level.txt +0 -0
@@ -1,5 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
- # pylint: disable=too-many-statements
2
+ # pylint: disable=too-many-statements,too-many-branches
3
3
  import argparse
4
4
  import logging
5
5
  import os
@@ -11,6 +11,15 @@ import requests
11
11
 
12
12
  from .enums import SandboxType
13
13
  from .registry import SandboxRegistry
14
+ from .utils import dynamic_import, get_platform
15
+
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+ DOCKER_PLATFORMS = [
20
+ "linux/amd64",
21
+ "linux/arm64",
22
+ ]
14
23
 
15
24
 
16
25
  def find_free_port(start_port, end_port):
@@ -18,7 +27,7 @@ def find_free_port(start_port, end_port):
18
27
  with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
19
28
  if sock.connect_ex(("localhost", port)) != 0:
20
29
  return port
21
- logging.error(
30
+ logger.error(
22
31
  f"No free ports available in the range {start_port}-{end_port}",
23
32
  )
24
33
  raise RuntimeError(
@@ -30,7 +39,7 @@ def check_health(url, secret_token, timeout=120, interval=5):
30
39
  headers = {"Authorization": f"Bearer {secret_token}"}
31
40
  spent_time = 0
32
41
  while spent_time < timeout:
33
- logging.info(
42
+ logger.info(
34
43
  f"Attempting to connect to {url} (Elapsed time: {spent_time} "
35
44
  f"seconds)...",
36
45
  )
@@ -41,35 +50,52 @@ def check_health(url, secret_token, timeout=120, interval=5):
41
50
  return True
42
51
  except requests.exceptions.RequestException:
43
52
  pass
44
- logging.info(
53
+ logger.info(
45
54
  f"Health check failed for {url}. Retrying in {interval} "
46
55
  f"seconds...",
47
56
  )
48
57
  time.sleep(interval)
49
58
  spent_time += interval
50
- logging.error(f"Health check failed for {url} after {timeout} seconds.")
59
+ logger.error(f"Health check failed for {url} after {timeout} seconds.")
51
60
  return False
52
61
 
53
62
 
54
- def build_image(build_type, dockerfile_path=None):
63
+ def build_image(
64
+ build_type,
65
+ dockerfile_path=None,
66
+ platform_choice="linux/amd64",
67
+ ):
68
+ assert platform_choice in DOCKER_PLATFORMS, (
69
+ f"Invalid platform: {platform_choice}. Valid options:"
70
+ f" {DOCKER_PLATFORMS}"
71
+ )
72
+
73
+ platform_tag = ""
74
+ if platform_choice == "linux/arm64":
75
+ platform_tag = "-arm64"
76
+
77
+ buildx_enable = platform_choice != get_platform()
78
+
55
79
  if dockerfile_path is None:
56
80
  dockerfile_path = (
57
81
  f"src/agentscope_runtime/sandbox/box/{build_type}/Dockerfile"
58
82
  )
59
83
 
60
- logging.info(f"Building {build_type} with `{dockerfile_path}`...")
84
+ logger.info(f"Building {build_type} with `{dockerfile_path}`...")
61
85
 
62
86
  # Initialize and update Git submodule
63
- logging.info("Initializing and updating Git submodule...")
87
+ logger.info("Initializing and updating Git submodule...")
64
88
  subprocess.run(
65
89
  ["git", "submodule", "update", "--init", "--recursive"],
66
90
  check=True,
67
91
  )
68
92
 
69
93
  secret_token = "secret_token123"
70
- image_name = SandboxRegistry.get_image_by_type(build_type)
71
94
 
72
- logging.info(f"Building Docker image {image_name}...")
95
+ # Add platform tag
96
+ image_name = SandboxRegistry.get_image_by_type(build_type) + platform_tag
97
+
98
+ logger.info(f"Building Docker image {image_name}...")
73
99
 
74
100
  # Check if image exists
75
101
  result = subprocess.run(
@@ -87,7 +113,7 @@ def build_image(build_type, dockerfile_path=None):
87
113
  f"you want to overwrite it? (y/N): ",
88
114
  )
89
115
  if choice.lower() != "y":
90
- logging.info("Exiting without overwriting the existing image.")
116
+ logger.info("Exiting without overwriting the existing image.")
91
117
  return
92
118
 
93
119
  if not os.path.exists(dockerfile_path):
@@ -97,70 +123,101 @@ def build_image(build_type, dockerfile_path=None):
97
123
  )
98
124
 
99
125
  # Build Docker image
100
- subprocess.run(
101
- [
102
- "docker",
103
- "build",
104
- "-f",
105
- dockerfile_path,
106
- "-t",
107
- f"{image_name}dev",
108
- ".",
109
- ],
110
- check=False,
111
- )
112
- logging.info(f"Docker image {image_name}dev built successfully.")
126
+ if not buildx_enable:
127
+ subprocess.run(
128
+ [
129
+ "docker",
130
+ "build",
131
+ "-f",
132
+ dockerfile_path,
133
+ "-t",
134
+ f"{image_name}dev",
135
+ ".",
136
+ ],
137
+ check=False,
138
+ )
139
+ else:
140
+ subprocess.run(
141
+ [
142
+ "docker",
143
+ "buildx",
144
+ "build",
145
+ "--platform",
146
+ platform_choice,
147
+ "-f",
148
+ dockerfile_path,
149
+ "-t",
150
+ f"{image_name}dev",
151
+ "--load",
152
+ ".",
153
+ ],
154
+ check=False,
155
+ )
113
156
 
114
- logging.info(f"Start to build image {image_name}.")
157
+ logger.info(f"Docker image {image_name}dev built successfully.")
158
+
159
+ logger.info(f"Start to build image {image_name}.")
115
160
 
116
161
  # Run the container with port mapping and environment variable
117
162
  free_port = find_free_port(8080, 8090)
118
- result = subprocess.run(
119
- [
120
- "docker",
121
- "run",
122
- "-d",
123
- "-p",
124
- f"{free_port}:80",
125
- "-e",
126
- f"SECRET_TOKEN={secret_token}",
127
- f"{image_name}dev",
128
- ],
129
- capture_output=True,
130
- text=True,
131
- check=False,
132
- )
163
+
164
+ if not buildx_enable:
165
+ result = subprocess.run(
166
+ [
167
+ "docker",
168
+ "run",
169
+ "-d",
170
+ "-p",
171
+ f"{free_port}:80",
172
+ "-e",
173
+ f"SECRET_TOKEN={secret_token}",
174
+ f"{image_name}dev",
175
+ ],
176
+ capture_output=True,
177
+ text=True,
178
+ check=False,
179
+ )
180
+ else:
181
+ result = subprocess.run(
182
+ [
183
+ "docker",
184
+ "run",
185
+ "--platform",
186
+ platform_choice,
187
+ "-d",
188
+ "-p",
189
+ f"{free_port}:80",
190
+ "-e",
191
+ f"SECRET_TOKEN={secret_token}",
192
+ f"{image_name}dev",
193
+ ],
194
+ capture_output=True,
195
+ text=True,
196
+ check=False,
197
+ )
198
+
133
199
  container_id = result.stdout.strip()
134
- logging.info(f"Running container {container_id} on port {free_port}")
200
+ logger.info(f"Running container {container_id} on port {free_port}")
135
201
 
136
202
  # Check health endpoints
137
203
  fastapi_health_url = f"http://localhost:{free_port}/fastapi/healthz"
138
- steelapi_health_url = (
139
- f"http://localhost:{free_port}/steel-api/{secret_token}/v1/health"
140
- )
141
204
 
142
205
  # Check health for FASTAPI
143
206
  fastapi_healthy = check_health(fastapi_health_url, secret_token)
144
207
 
145
- # Check health for Browser
146
- if build_type in [SandboxType.BROWSER.value]:
147
- browser_healthy = check_health(steelapi_health_url, secret_token)
148
- else:
149
- browser_healthy = True
150
-
151
- if browser_healthy and fastapi_healthy:
152
- logging.info("Health checks passed.")
208
+ if fastapi_healthy:
209
+ logger.info("Health checks passed.")
153
210
  subprocess.run(
154
211
  ["docker", "commit", container_id, f"{image_name}"],
155
212
  check=True,
156
213
  )
157
- logging.info(
214
+ logger.info(
158
215
  f"Docker image {image_name} committed successfully.",
159
216
  )
160
217
  subprocess.run(["docker", "stop", container_id], check=True)
161
218
  subprocess.run(["docker", "rm", container_id], check=True)
162
219
  else:
163
- logging.error("Health checks failed.")
220
+ logger.error("Health checks failed.")
164
221
  subprocess.run(["docker", "stop", container_id], check=True)
165
222
 
166
223
  choice = input(
@@ -171,9 +228,9 @@ def build_image(build_type, dockerfile_path=None):
171
228
  ["docker", "rmi", "-f", f"{image_name}dev"],
172
229
  check=True,
173
230
  )
174
- logging.info(f"Dev image {image_name}dev deleted.")
231
+ logger.info(f"Dev image {image_name}dev deleted.")
175
232
  else:
176
- logging.info(f"Dev image {image_name}dev retained.")
233
+ logger.info(f"Dev image {image_name}dev retained.")
177
234
 
178
235
 
179
236
  def main():
@@ -182,8 +239,8 @@ def main():
182
239
  )
183
240
  parser.add_argument(
184
241
  "build_type",
242
+ nargs="?",
185
243
  default="base",
186
- choices=[x.value for x in SandboxType] + ["all"],
187
244
  help="Specify the build type to execute.",
188
245
  )
189
246
 
@@ -193,20 +250,48 @@ def main():
193
250
  help="Specify the path for the Dockerfile.",
194
251
  )
195
252
 
253
+ parser.add_argument(
254
+ "--extension",
255
+ action="append",
256
+ help="Path to a Python file or module name to load as an extension",
257
+ )
258
+
259
+ parser.add_argument(
260
+ "--platform",
261
+ default=get_platform(),
262
+ choices=DOCKER_PLATFORMS,
263
+ help="Specify target platform for Docker image (default: current "
264
+ f"system platform: {get_platform()})",
265
+ )
266
+
196
267
  args = parser.parse_args()
197
268
 
269
+ if args.extension:
270
+ for ext in args.extension:
271
+ logger.info(f"Loading extension: {ext}")
272
+ mod = dynamic_import(ext)
273
+ logger.info(f"Extension loaded: {mod.__name__}")
274
+
198
275
  if args.build_type == "all":
199
276
  # Only build the built-in images
200
277
  for build_type in [x.value for x in SandboxType.get_builtin_members()]:
201
278
  build_image(build_type)
202
279
  else:
280
+ assert args.build_type in [
281
+ x.value for x in SandboxType
282
+ ], f"Invalid build type: {args.build_type}"
283
+
203
284
  if args.build_type not in [
204
285
  x.value for x in SandboxType.get_builtin_members()
205
286
  ]:
206
287
  assert (
207
288
  args.dockerfile_path is not None
208
289
  ), "Dockerfile path is required for custom images"
209
- build_image(args.build_type, args.dockerfile_path)
290
+ build_image(
291
+ args.build_type,
292
+ args.dockerfile_path,
293
+ platform_choice=args.platform,
294
+ )
210
295
 
211
296
 
212
297
  if __name__ == "__main__":
@@ -3,15 +3,16 @@
3
3
  import logging
4
4
  import time
5
5
  from typing import Any, Optional
6
+ from urllib.parse import urljoin
6
7
 
7
8
  import requests
8
9
  from pydantic import Field
9
- from steel import Steel
10
10
 
11
11
  from ..model import ContainerModel
12
- from ..constant import BROWSER_SESSION_ID
13
12
 
14
13
 
14
+ DEFAULT_TIMEOUT = 60
15
+
15
16
  logging.getLogger("httpx").setLevel(logging.CRITICAL)
16
17
  logging.basicConfig(level=logging.INFO)
17
18
  logger = logging.getLogger(__name__)
@@ -69,8 +70,7 @@ class SandboxHttpClient:
69
70
  def __init__(
70
71
  self,
71
72
  model: Optional[ContainerModel] = None,
72
- timeout: int = 30,
73
- enable_browser: bool = True,
73
+ timeout: int = 60,
74
74
  domain: str = "localhost",
75
75
  ) -> None:
76
76
  """
@@ -81,54 +81,39 @@ class SandboxHttpClient:
81
81
  runtime sandbox.
82
82
  """
83
83
  self.session_id = model.session_id
84
- self.base_url = model.base_url.replace("localhost", domain)
85
- self.browser_url = model.browser_url.replace("localhost", domain)
86
- self.client_browser_ws = model.client_browser_ws.replace(
87
- "localhost",
88
- domain,
84
+ self.base_url = urljoin(
85
+ model.url.replace("localhost", domain),
86
+ "fastapi",
89
87
  )
90
88
 
91
- self.enable_browser = enable_browser
92
- self.timeout = timeout
89
+ self.start_timeout = timeout
90
+ self.timeout = model.timeout or DEFAULT_TIMEOUT
93
91
  self.session = requests.Session()
94
92
  self.built_in_tools = []
95
93
  self.secret = model.runtime_token
96
94
 
97
95
  # Update headers with secret if provided
98
- headers = {"Content-Type": "application/json"}
96
+ headers = {
97
+ "Content-Type": "application/json",
98
+ "x-agentrun-session-id": "s" + self.session_id,
99
+ }
99
100
  if self.secret:
100
101
  headers["Authorization"] = f"Bearer {self.secret}"
101
102
  self.session.headers.update(headers)
102
103
 
103
- self.steel_client = None
104
-
105
104
  def __enter__(self):
106
105
  # Wait for the runtime api server to be healthy
107
106
  self.wait_until_healthy()
108
-
109
- if self.enable_browser:
110
- self.steel_client = Steel(
111
- steel_api_key="dummy",
112
- base_url=self.browser_url,
113
- )
114
-
115
- # Create a new browser session if it doesn't exist
116
- try:
117
- # Try to connet to existing session
118
- self.steel_client.sessions.retrieve(
119
- BROWSER_SESSION_ID,
120
- )
121
- except Exception:
122
- # Session not found, create a new one
123
- self.steel_client.sessions.create(
124
- session_id=BROWSER_SESSION_ID,
125
- )
126
-
127
107
  return self
128
108
 
129
109
  def __exit__(self, exc_type, exc_value, traceback):
130
110
  pass
131
111
 
112
+ def _request(self, method: str, url: str, **kwargs):
113
+ if "timeout" not in kwargs:
114
+ kwargs["timeout"] = self.timeout
115
+ return self.session.request(method, url, **kwargs)
116
+
132
117
  def check_health(self) -> bool:
133
118
  """
134
119
  Checks if the runtime service is running by verifying the health
@@ -138,17 +123,9 @@ class SandboxHttpClient:
138
123
  bool: True if the service is reachable, False otherwise
139
124
  """
140
125
  endpoint = f"{self.base_url}/healthz"
141
- browser_endpoint = f"{self.browser_url}/v1/health"
142
126
  try:
143
127
  response_api = self.session.get(endpoint)
144
- if self.enable_browser:
145
- response_browser = self.session.get(browser_endpoint)
146
- return (
147
- response_api.status_code == 200
148
- and response_browser.status_code == 200
149
- )
150
- else:
151
- return response_api.status_code == 200
128
+ return response_api.status_code == 200
152
129
  except requests.RequestException:
153
130
  return False
154
131
 
@@ -157,7 +134,7 @@ class SandboxHttpClient:
157
134
  Waits until the runtime service is running for a specified timeout.
158
135
  """
159
136
  start_time = time.time()
160
- while time.time() - start_time < self.timeout:
137
+ while time.time() - start_time < self.start_timeout:
161
138
  if self.check_health():
162
139
  return
163
140
  time.sleep(1)
@@ -171,7 +148,8 @@ class SandboxHttpClient:
171
148
  """
172
149
  try:
173
150
  endpoint = f"{self.base_url}/mcp/add_servers"
174
- response = self.session.post(
151
+ response = self._request(
152
+ "post",
175
153
  endpoint,
176
154
  json={
177
155
  "server_configs": server_configs,
@@ -190,7 +168,10 @@ class SandboxHttpClient:
190
168
  def list_tools(self, tool_type=None, **kwargs) -> dict:
191
169
  try:
192
170
  endpoint = f"{self.base_url}/mcp/list_tools"
193
- response = self.session.get(endpoint)
171
+ response = self._request(
172
+ "get",
173
+ endpoint,
174
+ )
194
175
  response.raise_for_status()
195
176
  mcp_tools = response.json()
196
177
  mcp_tools["generic"] = self.generic_tools
@@ -220,7 +201,8 @@ class SandboxHttpClient:
220
201
 
221
202
  try:
222
203
  endpoint = f"{self.base_url}/mcp/call_tool"
223
- response = self.session.post(
204
+ response = self._request(
205
+ "post",
224
206
  endpoint,
225
207
  json={
226
208
  "tool_name": name,
@@ -246,7 +228,11 @@ class SandboxHttpClient:
246
228
  """Run an IPython cell."""
247
229
  try:
248
230
  endpoint = f"{self.base_url}/tools/run_ipython_cell"
249
- response = self.session.post(endpoint, json={"code": code})
231
+ response = self._request(
232
+ "post",
233
+ endpoint,
234
+ json={"code": code},
235
+ )
250
236
  response.raise_for_status()
251
237
  return response.json()
252
238
  except requests.exceptions.RequestException as e:
@@ -265,7 +251,11 @@ class SandboxHttpClient:
265
251
  """Run a shell command."""
266
252
  try:
267
253
  endpoint = f"{self.base_url}/tools/run_shell_command"
268
- response = self.session.post(endpoint, json={"command": command})
254
+ response = self._request(
255
+ "post",
256
+ endpoint,
257
+ json={"command": command},
258
+ )
269
259
  response.raise_for_status()
270
260
  return response.json()
271
261
  except requests.exceptions.RequestException as e:
@@ -286,7 +276,8 @@ class SandboxHttpClient:
286
276
  """
287
277
  try:
288
278
  endpoint = f"{self.base_url}/watcher/commit_changes"
289
- response = self.session.post(
279
+ response = self._request(
280
+ "post",
290
281
  endpoint,
291
282
  json={"commit_message": commit_message},
292
283
  )
@@ -310,7 +301,8 @@ class SandboxHttpClient:
310
301
  """
311
302
  try:
312
303
  endpoint = f"{self.base_url}/watcher/generate_diff"
313
- response = self.session.post(
304
+ response = self._request(
305
+ "post",
314
306
  endpoint,
315
307
  json={"commit_a": commit_a, "commit_b": commit_b},
316
308
  )
@@ -329,7 +321,10 @@ class SandboxHttpClient:
329
321
  """
330
322
  try:
331
323
  endpoint = f"{self.base_url}/watcher/git_logs"
332
- response = self.session.get(endpoint)
324
+ response = self._request(
325
+ "get",
326
+ endpoint,
327
+ )
333
328
  response.raise_for_status()
334
329
  return response.json()
335
330
  except requests.exceptions.RequestException as e:
@@ -346,7 +341,11 @@ class SandboxHttpClient:
346
341
  try:
347
342
  endpoint = f"{self.base_url}/workspace/files"
348
343
  params = {"file_path": file_path}
349
- response = self.session.get(endpoint, params=params)
344
+ response = self._request(
345
+ "get",
346
+ endpoint,
347
+ params=params,
348
+ )
350
349
  response.raise_for_status()
351
350
  # Return the binary content of the file
352
351
  # Check for empty content
@@ -379,7 +378,12 @@ class SandboxHttpClient:
379
378
  endpoint = f"{self.base_url}/workspace/files"
380
379
  params = {"file_path": file_path}
381
380
  data = {"content": content}
382
- response = self.session.post(endpoint, params=params, json=data)
381
+ response = self._request(
382
+ "post",
383
+ endpoint,
384
+ params=params,
385
+ json=data,
386
+ )
383
387
  response.raise_for_status()
384
388
  return response.json()
385
389
  except requests.exceptions.RequestException as e:
@@ -402,7 +406,11 @@ class SandboxHttpClient:
402
406
  try:
403
407
  endpoint = f"{self.base_url}/workspace/list-directories"
404
408
  params = {"directory": directory}
405
- response = self.session.get(endpoint, params=params)
409
+ response = self._request(
410
+ "get",
411
+ endpoint,
412
+ params=params,
413
+ )
406
414
  response.raise_for_status()
407
415
  return response.json()
408
416
  except requests.exceptions.RequestException as e:
@@ -419,7 +427,11 @@ class SandboxHttpClient:
419
427
  try:
420
428
  endpoint = f"{self.base_url}/workspace/directories"
421
429
  params = {"directory_path": directory_path}
422
- response = self.session.post(endpoint, params=params)
430
+ response = self._request(
431
+ "post",
432
+ endpoint,
433
+ params=params,
434
+ )
423
435
  response.raise_for_status()
424
436
  return response.json()
425
437
  except requests.exceptions.RequestException as e:
@@ -438,7 +450,11 @@ class SandboxHttpClient:
438
450
  try:
439
451
  endpoint = f"{self.base_url}/workspace/files"
440
452
  params = {"file_path": file_path}
441
- response = self.session.delete(endpoint, params=params)
453
+ response = self._request(
454
+ "delete",
455
+ endpoint,
456
+ params=params,
457
+ )
442
458
  response.raise_for_status()
443
459
  return response.json()
444
460
  except requests.exceptions.RequestException as e:
@@ -461,7 +477,11 @@ class SandboxHttpClient:
461
477
  try:
462
478
  endpoint = f"{self.base_url}/workspace/directories"
463
479
  params = {"directory_path": directory_path, "recursive": recursive}
464
- response = self.session.delete(endpoint, params=params)
480
+ response = self._request(
481
+ "delete",
482
+ endpoint,
483
+ params=params,
484
+ )
465
485
  response.raise_for_status()
466
486
  return response.json()
467
487
  except requests.exceptions.RequestException as e:
@@ -487,7 +507,11 @@ class SandboxHttpClient:
487
507
  "source_path": source_path,
488
508
  "destination_path": destination_path,
489
509
  }
490
- response = self.session.put(endpoint, params=params)
510
+ response = self._request(
511
+ "put",
512
+ endpoint,
513
+ params=params,
514
+ )
491
515
  response.raise_for_status()
492
516
  return response.json()
493
517
  except requests.exceptions.RequestException as e:
@@ -514,7 +538,11 @@ class SandboxHttpClient:
514
538
  "source_path": source_path,
515
539
  "destination_path": destination_path,
516
540
  }
517
- response = self.session.post(endpoint, params=params)
541
+ response = self._request(
542
+ "post",
543
+ endpoint,
544
+ params=params,
545
+ )
518
546
  response.raise_for_status()
519
547
  return response.json()
520
548
  except requests.exceptions.RequestException as e:
@@ -212,7 +212,6 @@ class TrainingSandboxClient:
212
212
  def list_tools(self, **kwargs):
213
213
  """list tools"""
214
214
  if "instance_id" in kwargs:
215
- # 只传get_tools_info的方法参数
216
215
  return self.get_tools_info(
217
216
  instance_id=kwargs.get("instance_id"),
218
217
  messages=kwargs.get("messages", {}),
@@ -1,5 +1,31 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  import os
3
+ import sys
4
+ import logging
3
5
 
6
+ logger = logging.getLogger(__name__)
7
+
8
+ # Image Registry: default "", means using Docker Hub.
9
+ # For AgentScope official registry, use
10
+ # "agentscope-registry.ap-southeast-1.cr.aliyuncs.com"
11
+ REGISTRY = os.getenv("RUNTIME_SANDBOX_REGISTRY", "")
12
+ if REGISTRY == "":
13
+ agentscope_acr = "agentscope-registry.ap-southeast-1.cr.aliyuncs.com"
14
+ if sys.platform.startswith("win"):
15
+ cmd = f"set RUNTIME_SANDBOX_REGISTRY={agentscope_acr}"
16
+ else:
17
+ cmd = f"export RUNTIME_SANDBOX_REGISTRY={agentscope_acr}"
18
+ logger.warning(
19
+ "Using Docker Hub as image registry. If pulling is slow or fails, "
20
+ f"you can switch to the AgentScope official registry by running:\n "
21
+ f"{cmd}\n",
22
+ )
23
+
24
+ # Image Namespace
25
+ IMAGE_NAMESPACE = os.getenv("RUNTIME_SANDBOX_IMAGE_NAMESPACE", "agentscope")
26
+
27
+ # Image Tag
4
28
  IMAGE_TAG = os.getenv("RUNTIME_SANDBOX_IMAGE_TAG", "latest")
5
- BROWSER_SESSION_ID = "123e4567-e89b-12d3-a456-426614174000"
29
+
30
+ # Timeout
31
+ TIMEOUT = int(os.getenv("RUNTIME_SANDBOX_TIMEOUT", "60"))