agentscope-runtime 1.0.4__py3-none-any.whl → 1.0.4a1__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 (46) hide show
  1. agentscope_runtime/adapters/agentscope/stream.py +7 -1
  2. agentscope_runtime/cli/commands/deploy.py +0 -371
  3. agentscope_runtime/engine/__init__.py +0 -4
  4. agentscope_runtime/engine/constant.py +0 -1
  5. agentscope_runtime/engine/deployers/__init__.py +0 -12
  6. agentscope_runtime/engine/deployers/adapter/a2a/__init__.py +51 -26
  7. agentscope_runtime/engine/deployers/adapter/a2a/a2a_protocol_adapter.py +10 -19
  8. agentscope_runtime/engine/deployers/adapter/a2a/a2a_registry.py +201 -4
  9. agentscope_runtime/engine/deployers/adapter/a2a/nacos_a2a_registry.py +25 -134
  10. agentscope_runtime/engine/deployers/agentrun_deployer.py +2 -2
  11. agentscope_runtime/engine/runner.py +0 -12
  12. agentscope_runtime/engine/tracing/wrapper.py +4 -18
  13. agentscope_runtime/sandbox/__init__.py +6 -14
  14. agentscope_runtime/sandbox/box/base/__init__.py +2 -2
  15. agentscope_runtime/sandbox/box/base/base_sandbox.py +1 -51
  16. agentscope_runtime/sandbox/box/browser/__init__.py +2 -2
  17. agentscope_runtime/sandbox/box/browser/browser_sandbox.py +2 -198
  18. agentscope_runtime/sandbox/box/filesystem/__init__.py +2 -2
  19. agentscope_runtime/sandbox/box/filesystem/filesystem_sandbox.py +2 -99
  20. agentscope_runtime/sandbox/box/gui/__init__.py +2 -2
  21. agentscope_runtime/sandbox/box/gui/gui_sandbox.py +1 -117
  22. agentscope_runtime/sandbox/box/mobile/__init__.py +2 -2
  23. agentscope_runtime/sandbox/box/mobile/mobile_sandbox.py +100 -247
  24. agentscope_runtime/sandbox/box/sandbox.py +65 -98
  25. agentscope_runtime/sandbox/box/shared/routers/generic.py +29 -36
  26. agentscope_runtime/sandbox/client/__init__.py +1 -6
  27. agentscope_runtime/sandbox/client/http_client.py +329 -108
  28. agentscope_runtime/sandbox/enums.py +0 -7
  29. agentscope_runtime/sandbox/manager/sandbox_manager.py +4 -264
  30. agentscope_runtime/sandbox/manager/server/app.py +1 -7
  31. agentscope_runtime/version.py +1 -1
  32. {agentscope_runtime-1.0.4.dist-info → agentscope_runtime-1.0.4a1.dist-info}/METADATA +28 -102
  33. {agentscope_runtime-1.0.4.dist-info → agentscope_runtime-1.0.4a1.dist-info}/RECORD +37 -46
  34. agentscope_runtime/adapters/ms_agent_framework/__init__.py +0 -0
  35. agentscope_runtime/adapters/ms_agent_framework/message.py +0 -205
  36. agentscope_runtime/adapters/ms_agent_framework/stream.py +0 -418
  37. agentscope_runtime/adapters/utils.py +0 -6
  38. agentscope_runtime/common/container_clients/knative_client.py +0 -466
  39. agentscope_runtime/engine/deployers/fc_deployer.py +0 -1506
  40. agentscope_runtime/engine/deployers/knative_deployer.py +0 -290
  41. agentscope_runtime/sandbox/client/async_http_client.py +0 -339
  42. agentscope_runtime/sandbox/client/base.py +0 -74
  43. {agentscope_runtime-1.0.4.dist-info → agentscope_runtime-1.0.4a1.dist-info}/WHEEL +0 -0
  44. {agentscope_runtime-1.0.4.dist-info → agentscope_runtime-1.0.4a1.dist-info}/entry_points.txt +0 -0
  45. {agentscope_runtime-1.0.4.dist-info → agentscope_runtime-1.0.4a1.dist-info}/licenses/LICENSE +0 -0
  46. {agentscope_runtime-1.0.4.dist-info → agentscope_runtime-1.0.4a1.dist-info}/top_level.txt +0 -0
@@ -3,11 +3,11 @@
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
10
 
10
- from .base import SandboxHttpBase
11
11
  from ..model import ContainerModel
12
12
 
13
13
 
@@ -18,12 +18,55 @@ logging.basicConfig(level=logging.INFO)
18
18
  logger = logging.getLogger(__name__)
19
19
 
20
20
 
21
- class SandboxHttpClient(SandboxHttpBase):
21
+ class SandboxHttpClient:
22
22
  """
23
23
  A Python client for interacting with the runtime API. Connect with
24
24
  container directly.
25
25
  """
26
26
 
27
+ _generic_tools = {
28
+ "run_ipython_cell": {
29
+ "name": "run_ipython_cell",
30
+ "json_schema": {
31
+ "type": "function",
32
+ "function": {
33
+ "name": "run_ipython_cell",
34
+ "description": "Run an IPython cell.",
35
+ "parameters": {
36
+ "type": "object",
37
+ "properties": {
38
+ "code": {
39
+ "type": "string",
40
+ "description": "IPython code to execute",
41
+ },
42
+ },
43
+ "required": ["code"],
44
+ },
45
+ },
46
+ },
47
+ },
48
+ "run_shell_command": {
49
+ "name": "run_shell_command",
50
+ "json_schema": {
51
+ "type": "function",
52
+ "function": {
53
+ "name": "run_shell_command",
54
+ "description": "Run a shell command.",
55
+ "parameters": {
56
+ "type": "object",
57
+ "properties": {
58
+ "command": {
59
+ "type": "string",
60
+ "description": "Shell command to execute",
61
+ },
62
+ },
63
+ "required": ["command"],
64
+ },
65
+ },
66
+ },
67
+ },
68
+ }
69
+
27
70
  def __init__(
28
71
  self,
29
72
  model: Optional[ContainerModel] = None,
@@ -37,9 +80,27 @@ class SandboxHttpClient(SandboxHttpBase):
37
80
  model (ContainerModel): The pydantic model representing the
38
81
  runtime sandbox.
39
82
  """
40
- super().__init__(model, timeout, domain)
83
+ self.session_id = model.session_id
84
+ self.base_url = urljoin(
85
+ model.url.replace("localhost", domain),
86
+ "fastapi",
87
+ )
88
+
89
+ self.start_timeout = timeout
90
+ self.timeout = model.timeout or DEFAULT_TIMEOUT
41
91
  self.session = requests.Session()
42
- self.session.headers.update(self.headers)
92
+ self.built_in_tools = []
93
+ self.secret = model.runtime_token
94
+
95
+ # Update headers with secret if provided
96
+ headers = {
97
+ "Content-Type": "application/json",
98
+ "x-agentrun-session-id": "s" + self.session_id,
99
+ "x-agentscope-runtime-session-id": "s" + self.session_id,
100
+ }
101
+ if self.secret:
102
+ headers["Authorization"] = f"Bearer {self.secret}"
103
+ self.session.headers.update(headers)
43
104
 
44
105
  def __enter__(self):
45
106
  # Wait for the runtime api server to be healthy
@@ -54,21 +115,6 @@ class SandboxHttpClient(SandboxHttpBase):
54
115
  kwargs["timeout"] = self.timeout
55
116
  return self.session.request(method, url, **kwargs)
56
117
 
57
- def safe_request(self, method, url, **kwargs):
58
- try:
59
- r = self._request(method, url, **kwargs)
60
- r.raise_for_status()
61
- try:
62
- return r.json()
63
- except ValueError:
64
- return r.text
65
- except requests.exceptions.RequestException as e:
66
- logger.error(f"HTTP error: {e}")
67
- return {
68
- "isError": True,
69
- "content": [{"type": "text", "text": str(e)}],
70
- }
71
-
72
118
  def check_health(self) -> bool:
73
119
  """
74
120
  Checks if the runtime service is running by verifying the health
@@ -77,8 +123,9 @@ class SandboxHttpClient(SandboxHttpBase):
77
123
  Returns:
78
124
  bool: True if the service is reachable, False otherwise
79
125
  """
126
+ endpoint = f"{self.base_url}/healthz"
80
127
  try:
81
- response_api = self._request("get", f"{self.base_url}/healthz")
128
+ response_api = self.session.get(endpoint)
82
129
  return response_api.status_code == 200
83
130
  except requests.RequestException:
84
131
  return False
@@ -100,36 +147,50 @@ class SandboxHttpClient(SandboxHttpBase):
100
147
  """
101
148
  Add MCP servers to runtime.
102
149
  """
103
- return self.safe_request(
104
- "post",
105
- f"{self.base_url}/mcp/add_servers",
106
- json={
107
- "server_configs": server_configs,
108
- "overwrite": overwrite,
109
- },
110
- )
150
+ try:
151
+ endpoint = f"{self.base_url}/mcp/add_servers"
152
+ response = self._request(
153
+ "post",
154
+ endpoint,
155
+ json={
156
+ "server_configs": server_configs,
157
+ "overwrite": overwrite,
158
+ },
159
+ )
160
+ response.raise_for_status()
161
+ return response.text
162
+ except requests.exceptions.RequestException as e:
163
+ logger.error(f"An error occurred while adding MCP servers: {e}")
164
+ return {
165
+ "isError": True,
166
+ "content": [{"type": "text", "text": str(e)}],
167
+ }
111
168
 
112
169
  def list_tools(self, tool_type=None, **kwargs) -> dict:
113
- """
114
- List available MCP tools plus generic built-in tools.
115
- """
116
- data = self.safe_request("get", f"{self.base_url}/mcp/list_tools")
117
- if isinstance(data, dict) and "isError" not in data:
118
- data["generic"] = self.generic_tools
170
+ try:
171
+ endpoint = f"{self.base_url}/mcp/list_tools"
172
+ response = self._request(
173
+ "get",
174
+ endpoint,
175
+ )
176
+ response.raise_for_status()
177
+ mcp_tools = response.json()
178
+ mcp_tools["generic"] = self.generic_tools
119
179
  if tool_type:
120
- return {tool_type: data.get(tool_type, {})}
121
- return data
180
+ return {tool_type: mcp_tools.get(tool_type, {})}
181
+ return mcp_tools
182
+ except requests.exceptions.RequestException as e:
183
+ logging.error(f"An error occurred: {e}")
184
+ return {
185
+ "isError": True,
186
+ "content": [{"type": "text", "text": str(e)}],
187
+ }
122
188
 
123
189
  def call_tool(
124
190
  self,
125
191
  name: str,
126
192
  arguments: Optional[dict[str, Any]] = None,
127
193
  ) -> dict:
128
- """
129
- Call a specific MCP tool.
130
-
131
- If it's a generic tool, call the corresponding local method.
132
- """
133
194
  if arguments is None:
134
195
  arguments = {}
135
196
 
@@ -139,14 +200,25 @@ class SandboxHttpClient(SandboxHttpBase):
139
200
  elif name == "run_shell_command":
140
201
  return self.run_shell_command(**arguments)
141
202
 
142
- return self.safe_request(
143
- "post",
144
- f"{self.base_url}/mcp/call_tool",
145
- json={
146
- "tool_name": name,
147
- "arguments": arguments,
148
- },
149
- )
203
+ try:
204
+ endpoint = f"{self.base_url}/mcp/call_tool"
205
+ response = self._request(
206
+ "post",
207
+ endpoint,
208
+ json={
209
+ "tool_name": name,
210
+ "arguments": arguments,
211
+ },
212
+ )
213
+ response.raise_for_status()
214
+
215
+ return response.json()
216
+ except requests.exceptions.RequestException as e:
217
+ logger.error(f"An error occurred: {e}")
218
+ return {
219
+ "isError": True,
220
+ "content": [{"type": "text", "text": str(e)}],
221
+ }
150
222
 
151
223
  def run_ipython_cell(
152
224
  self,
@@ -155,11 +227,21 @@ class SandboxHttpClient(SandboxHttpBase):
155
227
  ),
156
228
  ) -> dict:
157
229
  """Run an IPython cell."""
158
- return self.safe_request(
159
- "post",
160
- f"{self.base_url}/tools/run_ipython_cell",
161
- json={"code": code},
162
- )
230
+ try:
231
+ endpoint = f"{self.base_url}/tools/run_ipython_cell"
232
+ response = self._request(
233
+ "post",
234
+ endpoint,
235
+ json={"code": code},
236
+ )
237
+ response.raise_for_status()
238
+ return response.json()
239
+ except requests.exceptions.RequestException as e:
240
+ logger.error(f"An error occurred: {e}")
241
+ return {
242
+ "isError": True,
243
+ "content": [{"type": "text", "text": str(e)}],
244
+ }
163
245
 
164
246
  def run_shell_command(
165
247
  self,
@@ -168,22 +250,46 @@ class SandboxHttpClient(SandboxHttpBase):
168
250
  ),
169
251
  ) -> dict:
170
252
  """Run a shell command."""
171
- return self.safe_request(
172
- "post",
173
- f"{self.base_url}/tools/run_shell_command",
174
- json={"command": command},
175
- )
253
+ try:
254
+ endpoint = f"{self.base_url}/tools/run_shell_command"
255
+ response = self._request(
256
+ "post",
257
+ endpoint,
258
+ json={"command": command},
259
+ )
260
+ response.raise_for_status()
261
+ return response.json()
262
+ except requests.exceptions.RequestException as e:
263
+ logger.error(f"An error occurred: {e}")
264
+ return {
265
+ "isError": True,
266
+ "content": [{"type": "text", "text": str(e)}],
267
+ }
268
+
269
+ @property
270
+ def generic_tools(self) -> dict:
271
+ return self._generic_tools
176
272
 
177
273
  # Below the method is used by API Server
178
274
  def commit_changes(self, commit_message: str = "Automated commit") -> dict:
179
275
  """
180
276
  Commit the uncommitted changes with a given commit message.
181
277
  """
182
- return self.safe_request(
183
- "post",
184
- f"{self.base_url}/watcher/commit_changes",
185
- json={"commit_message": commit_message},
186
- )
278
+ try:
279
+ endpoint = f"{self.base_url}/watcher/commit_changes"
280
+ response = self._request(
281
+ "post",
282
+ endpoint,
283
+ json={"commit_message": commit_message},
284
+ )
285
+ response.raise_for_status()
286
+ return response.json()
287
+ except requests.exceptions.RequestException as e:
288
+ logger.error(f"An error occurred while committing changes: {e}")
289
+ return {
290
+ "isError": True,
291
+ "content": [{"type": "text", "text": str(e)}],
292
+ }
187
293
 
188
294
  def generate_diff(
189
295
  self,
@@ -194,17 +300,40 @@ class SandboxHttpClient(SandboxHttpBase):
194
300
  Generate the diff between two commits or between uncommitted changes
195
301
  and the latest commit.
196
302
  """
197
- return self.safe_request(
198
- "post",
199
- f"{self.base_url}/watcher/generate_diff",
200
- json={"commit_a": commit_a, "commit_b": commit_b},
201
- )
303
+ try:
304
+ endpoint = f"{self.base_url}/watcher/generate_diff"
305
+ response = self._request(
306
+ "post",
307
+ endpoint,
308
+ json={"commit_a": commit_a, "commit_b": commit_b},
309
+ )
310
+ response.raise_for_status()
311
+ return response.json()
312
+ except requests.exceptions.RequestException as e:
313
+ logger.error(f"An error occurred while generating diff: {e}")
314
+ return {
315
+ "isError": True,
316
+ "content": [{"type": "text", "text": str(e)}],
317
+ }
202
318
 
203
319
  def git_logs(self) -> dict:
204
320
  """
205
321
  Retrieve the git logs.
206
322
  """
207
- return self.safe_request("get", f"{self.base_url}/watcher/git_logs")
323
+ try:
324
+ endpoint = f"{self.base_url}/watcher/git_logs"
325
+ response = self._request(
326
+ "get",
327
+ endpoint,
328
+ )
329
+ response.raise_for_status()
330
+ return response.json()
331
+ except requests.exceptions.RequestException as e:
332
+ logger.error(f"An error occurred while retrieving git logs: {e}")
333
+ return {
334
+ "isError": True,
335
+ "content": [{"type": "text", "text": str(e)}],
336
+ }
208
337
 
209
338
  def get_workspace_file(self, file_path: str) -> dict:
210
339
  """
@@ -246,12 +375,27 @@ class SandboxHttpClient(SandboxHttpBase):
246
375
  """
247
376
  Create or edit a file within the /workspace directory.
248
377
  """
249
- return self.safe_request(
250
- "post",
251
- f"{self.base_url}/workspace/files",
252
- params={"file_path": file_path},
253
- json={"content": content},
254
- )
378
+ try:
379
+ endpoint = f"{self.base_url}/workspace/files"
380
+ params = {"file_path": file_path}
381
+ data = {"content": content}
382
+ response = self._request(
383
+ "post",
384
+ endpoint,
385
+ params=params,
386
+ json=data,
387
+ )
388
+ response.raise_for_status()
389
+ return response.json()
390
+ except requests.exceptions.RequestException as e:
391
+ logger.error(
392
+ f"An error occurred while creating or editing a workspace "
393
+ f"file: {e}",
394
+ )
395
+ return {
396
+ "isError": True,
397
+ "content": [{"type": "text", "text": str(e)}],
398
+ }
255
399
 
256
400
  def list_workspace_directories(
257
401
  self,
@@ -260,31 +404,68 @@ class SandboxHttpClient(SandboxHttpBase):
260
404
  """
261
405
  List files in the specified directory within the /workspace.
262
406
  """
263
- return self.safe_request(
264
- "get",
265
- f"{self.base_url}/workspace/list-directories",
266
- params={"directory": directory},
267
- )
407
+ try:
408
+ endpoint = f"{self.base_url}/workspace/list-directories"
409
+ params = {"directory": directory}
410
+ response = self._request(
411
+ "get",
412
+ endpoint,
413
+ params=params,
414
+ )
415
+ response.raise_for_status()
416
+ return response.json()
417
+ except requests.exceptions.RequestException as e:
418
+ logger.error(f"An error occurred while listing files: {e}")
419
+ return {
420
+ "isError": True,
421
+ "content": [{"type": "text", "text": str(e)}],
422
+ }
268
423
 
269
424
  def create_workspace_directory(self, directory_path: str) -> dict:
270
425
  """
271
426
  Create a directory within the /workspace directory.
272
427
  """
273
- return self.safe_request(
274
- "post",
275
- f"{self.base_url}/workspace/directories",
276
- params={"directory_path": directory_path},
277
- )
428
+ try:
429
+ endpoint = f"{self.base_url}/workspace/directories"
430
+ params = {"directory_path": directory_path}
431
+ response = self._request(
432
+ "post",
433
+ endpoint,
434
+ params=params,
435
+ )
436
+ response.raise_for_status()
437
+ return response.json()
438
+ except requests.exceptions.RequestException as e:
439
+ logger.error(
440
+ f"An error occurred while creating a workspace directory: {e}",
441
+ )
442
+ return {
443
+ "isError": True,
444
+ "content": [{"type": "text", "text": str(e)}],
445
+ }
278
446
 
279
447
  def delete_workspace_file(self, file_path: str) -> dict:
280
448
  """
281
449
  Delete a file within the /workspace directory.
282
450
  """
283
- return self.safe_request(
284
- "delete",
285
- f"{self.base_url}/workspace/files",
286
- params={"file_path": file_path},
287
- )
451
+ try:
452
+ endpoint = f"{self.base_url}/workspace/files"
453
+ params = {"file_path": file_path}
454
+ response = self._request(
455
+ "delete",
456
+ endpoint,
457
+ params=params,
458
+ )
459
+ response.raise_for_status()
460
+ return response.json()
461
+ except requests.exceptions.RequestException as e:
462
+ logger.error(
463
+ f"An error occurred while deleting a workspace file: {e}",
464
+ )
465
+ return {
466
+ "isError": True,
467
+ "content": [{"type": "text", "text": str(e)}],
468
+ }
288
469
 
289
470
  def delete_workspace_directory(
290
471
  self,
@@ -294,11 +475,24 @@ class SandboxHttpClient(SandboxHttpBase):
294
475
  """
295
476
  Delete a directory within the /workspace directory.
296
477
  """
297
- return self.safe_request(
298
- "delete",
299
- f"{self.base_url}/workspace/directories",
300
- params={"directory_path": directory_path, "recursive": recursive},
301
- )
478
+ try:
479
+ endpoint = f"{self.base_url}/workspace/directories"
480
+ params = {"directory_path": directory_path, "recursive": recursive}
481
+ response = self._request(
482
+ "delete",
483
+ endpoint,
484
+ params=params,
485
+ )
486
+ response.raise_for_status()
487
+ return response.json()
488
+ except requests.exceptions.RequestException as e:
489
+ logger.error(
490
+ f"An error occurred while deleting a workspace directory: {e}",
491
+ )
492
+ return {
493
+ "isError": True,
494
+ "content": [{"type": "text", "text": str(e)}],
495
+ }
302
496
 
303
497
  def move_or_rename_workspace_item(
304
498
  self,
@@ -308,14 +502,28 @@ class SandboxHttpClient(SandboxHttpBase):
308
502
  """
309
503
  Move or rename a file or directory within the /workspace directory.
310
504
  """
311
- return self.safe_request(
312
- "put",
313
- f"{self.base_url}/workspace/move",
314
- params={
505
+ try:
506
+ endpoint = f"{self.base_url}/workspace/move"
507
+ params = {
315
508
  "source_path": source_path,
316
509
  "destination_path": destination_path,
317
- },
318
- )
510
+ }
511
+ response = self._request(
512
+ "put",
513
+ endpoint,
514
+ params=params,
515
+ )
516
+ response.raise_for_status()
517
+ return response.json()
518
+ except requests.exceptions.RequestException as e:
519
+ logger.error(
520
+ f"An error occurred while moving or renaming a workspace "
521
+ f"item: {e}",
522
+ )
523
+ return {
524
+ "isError": True,
525
+ "content": [{"type": "text", "text": str(e)}],
526
+ }
319
527
 
320
528
  def copy_workspace_item(
321
529
  self,
@@ -325,11 +533,24 @@ class SandboxHttpClient(SandboxHttpBase):
325
533
  """
326
534
  Copy a file or directory within the /workspace directory.
327
535
  """
328
- return self.safe_request(
329
- "post",
330
- f"{self.base_url}/workspace/copy",
331
- params={
536
+ try:
537
+ endpoint = f"{self.base_url}/workspace/copy"
538
+ params = {
332
539
  "source_path": source_path,
333
540
  "destination_path": destination_path,
334
- },
335
- )
541
+ }
542
+ response = self._request(
543
+ "post",
544
+ endpoint,
545
+ params=params,
546
+ )
547
+ response.raise_for_status()
548
+ return response.json()
549
+ except requests.exceptions.RequestException as e:
550
+ logger.error(
551
+ f"An error occurred while copying a workspace item: {e}",
552
+ )
553
+ return {
554
+ "isError": True,
555
+ "content": [{"type": "text", "text": str(e)}],
556
+ }
@@ -70,10 +70,3 @@ class SandboxType(DynamicEnum):
70
70
  APPWORLD = "appworld"
71
71
  BFCL = "bfcl"
72
72
  AGENTBAY = "agentbay"
73
-
74
- # Async sandbox
75
- BASE_ASYNC = "base_async"
76
- BROWSER_ASYNC = "browser_async"
77
- FILESYSTEM_ASYNC = "filesystem_async"
78
- GUI_ASYNC = "gui_async"
79
- MOBILE_ASYNC = "mobile_async"