agentscope-runtime 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. agentscope_runtime/__init__.py +4 -0
  2. agentscope_runtime/engine/__init__.py +9 -0
  3. agentscope_runtime/engine/agents/__init__.py +2 -0
  4. agentscope_runtime/engine/agents/agentscope_agent/__init__.py +6 -0
  5. agentscope_runtime/engine/agents/agentscope_agent/agent.py +342 -0
  6. agentscope_runtime/engine/agents/agentscope_agent/hooks.py +156 -0
  7. agentscope_runtime/engine/agents/agno_agent.py +220 -0
  8. agentscope_runtime/engine/agents/base_agent.py +29 -0
  9. agentscope_runtime/engine/agents/langgraph_agent.py +59 -0
  10. agentscope_runtime/engine/agents/llm_agent.py +51 -0
  11. agentscope_runtime/engine/deployers/__init__.py +3 -0
  12. agentscope_runtime/engine/deployers/adapter/__init__.py +0 -0
  13. agentscope_runtime/engine/deployers/adapter/a2a/__init__.py +2 -0
  14. agentscope_runtime/engine/deployers/adapter/a2a/a2a_adapter_utils.py +425 -0
  15. agentscope_runtime/engine/deployers/adapter/a2a/a2a_agent_adapter.py +69 -0
  16. agentscope_runtime/engine/deployers/adapter/a2a/a2a_protocol_adapter.py +60 -0
  17. agentscope_runtime/engine/deployers/adapter/protocol_adapter.py +24 -0
  18. agentscope_runtime/engine/deployers/base.py +17 -0
  19. agentscope_runtime/engine/deployers/local_deployer.py +586 -0
  20. agentscope_runtime/engine/helpers/helper.py +127 -0
  21. agentscope_runtime/engine/llms/__init__.py +3 -0
  22. agentscope_runtime/engine/llms/base_llm.py +60 -0
  23. agentscope_runtime/engine/llms/qwen_llm.py +47 -0
  24. agentscope_runtime/engine/misc/__init__.py +0 -0
  25. agentscope_runtime/engine/runner.py +186 -0
  26. agentscope_runtime/engine/schemas/__init__.py +0 -0
  27. agentscope_runtime/engine/schemas/agent_schemas.py +551 -0
  28. agentscope_runtime/engine/schemas/context.py +54 -0
  29. agentscope_runtime/engine/services/__init__.py +9 -0
  30. agentscope_runtime/engine/services/base.py +77 -0
  31. agentscope_runtime/engine/services/context_manager.py +129 -0
  32. agentscope_runtime/engine/services/environment_manager.py +50 -0
  33. agentscope_runtime/engine/services/manager.py +174 -0
  34. agentscope_runtime/engine/services/memory_service.py +270 -0
  35. agentscope_runtime/engine/services/sandbox_service.py +198 -0
  36. agentscope_runtime/engine/services/session_history_service.py +256 -0
  37. agentscope_runtime/engine/tracing/__init__.py +40 -0
  38. agentscope_runtime/engine/tracing/base.py +309 -0
  39. agentscope_runtime/engine/tracing/local_logging_handler.py +356 -0
  40. agentscope_runtime/engine/tracing/tracing_metric.py +69 -0
  41. agentscope_runtime/engine/tracing/wrapper.py +321 -0
  42. agentscope_runtime/sandbox/__init__.py +14 -0
  43. agentscope_runtime/sandbox/box/__init__.py +0 -0
  44. agentscope_runtime/sandbox/box/base/__init__.py +0 -0
  45. agentscope_runtime/sandbox/box/base/base_sandbox.py +37 -0
  46. agentscope_runtime/sandbox/box/base/box/__init__.py +0 -0
  47. agentscope_runtime/sandbox/box/browser/__init__.py +0 -0
  48. agentscope_runtime/sandbox/box/browser/box/__init__.py +0 -0
  49. agentscope_runtime/sandbox/box/browser/browser_sandbox.py +176 -0
  50. agentscope_runtime/sandbox/box/dummy/__init__.py +0 -0
  51. agentscope_runtime/sandbox/box/dummy/dummy_sandbox.py +26 -0
  52. agentscope_runtime/sandbox/box/filesystem/__init__.py +0 -0
  53. agentscope_runtime/sandbox/box/filesystem/box/__init__.py +0 -0
  54. agentscope_runtime/sandbox/box/filesystem/filesystem_sandbox.py +87 -0
  55. agentscope_runtime/sandbox/box/sandbox.py +115 -0
  56. agentscope_runtime/sandbox/box/shared/__init__.py +0 -0
  57. agentscope_runtime/sandbox/box/shared/app.py +44 -0
  58. agentscope_runtime/sandbox/box/shared/dependencies/__init__.py +5 -0
  59. agentscope_runtime/sandbox/box/shared/dependencies/deps.py +22 -0
  60. agentscope_runtime/sandbox/box/shared/routers/__init__.py +12 -0
  61. agentscope_runtime/sandbox/box/shared/routers/generic.py +173 -0
  62. agentscope_runtime/sandbox/box/shared/routers/mcp.py +207 -0
  63. agentscope_runtime/sandbox/box/shared/routers/mcp_utils.py +153 -0
  64. agentscope_runtime/sandbox/box/shared/routers/runtime_watcher.py +187 -0
  65. agentscope_runtime/sandbox/box/shared/routers/workspace.py +325 -0
  66. agentscope_runtime/sandbox/box/training_box/__init__.py +0 -0
  67. agentscope_runtime/sandbox/box/training_box/base.py +120 -0
  68. agentscope_runtime/sandbox/box/training_box/env_service.py +752 -0
  69. agentscope_runtime/sandbox/box/training_box/environments/__init__.py +0 -0
  70. agentscope_runtime/sandbox/box/training_box/environments/appworld/appworld_env.py +987 -0
  71. agentscope_runtime/sandbox/box/training_box/registry.py +54 -0
  72. agentscope_runtime/sandbox/box/training_box/src/trajectory.py +278 -0
  73. agentscope_runtime/sandbox/box/training_box/training_box.py +219 -0
  74. agentscope_runtime/sandbox/build.py +213 -0
  75. agentscope_runtime/sandbox/client/__init__.py +5 -0
  76. agentscope_runtime/sandbox/client/http_client.py +527 -0
  77. agentscope_runtime/sandbox/client/training_client.py +265 -0
  78. agentscope_runtime/sandbox/constant.py +5 -0
  79. agentscope_runtime/sandbox/custom/__init__.py +16 -0
  80. agentscope_runtime/sandbox/custom/custom_sandbox.py +40 -0
  81. agentscope_runtime/sandbox/custom/example.py +37 -0
  82. agentscope_runtime/sandbox/enums.py +68 -0
  83. agentscope_runtime/sandbox/manager/__init__.py +4 -0
  84. agentscope_runtime/sandbox/manager/collections/__init__.py +22 -0
  85. agentscope_runtime/sandbox/manager/collections/base_mapping.py +20 -0
  86. agentscope_runtime/sandbox/manager/collections/base_queue.py +25 -0
  87. agentscope_runtime/sandbox/manager/collections/base_set.py +25 -0
  88. agentscope_runtime/sandbox/manager/collections/in_memory_mapping.py +22 -0
  89. agentscope_runtime/sandbox/manager/collections/in_memory_queue.py +28 -0
  90. agentscope_runtime/sandbox/manager/collections/in_memory_set.py +27 -0
  91. agentscope_runtime/sandbox/manager/collections/redis_mapping.py +26 -0
  92. agentscope_runtime/sandbox/manager/collections/redis_queue.py +27 -0
  93. agentscope_runtime/sandbox/manager/collections/redis_set.py +23 -0
  94. agentscope_runtime/sandbox/manager/container_clients/__init__.py +8 -0
  95. agentscope_runtime/sandbox/manager/container_clients/base_client.py +39 -0
  96. agentscope_runtime/sandbox/manager/container_clients/docker_client.py +170 -0
  97. agentscope_runtime/sandbox/manager/sandbox_manager.py +694 -0
  98. agentscope_runtime/sandbox/manager/server/__init__.py +0 -0
  99. agentscope_runtime/sandbox/manager/server/app.py +194 -0
  100. agentscope_runtime/sandbox/manager/server/config.py +68 -0
  101. agentscope_runtime/sandbox/manager/server/models.py +17 -0
  102. agentscope_runtime/sandbox/manager/storage/__init__.py +10 -0
  103. agentscope_runtime/sandbox/manager/storage/data_storage.py +16 -0
  104. agentscope_runtime/sandbox/manager/storage/local_storage.py +44 -0
  105. agentscope_runtime/sandbox/manager/storage/oss_storage.py +89 -0
  106. agentscope_runtime/sandbox/manager/utils.py +78 -0
  107. agentscope_runtime/sandbox/mcp_server.py +192 -0
  108. agentscope_runtime/sandbox/model/__init__.py +12 -0
  109. agentscope_runtime/sandbox/model/api.py +16 -0
  110. agentscope_runtime/sandbox/model/container.py +72 -0
  111. agentscope_runtime/sandbox/model/manager_config.py +158 -0
  112. agentscope_runtime/sandbox/registry.py +129 -0
  113. agentscope_runtime/sandbox/tools/__init__.py +12 -0
  114. agentscope_runtime/sandbox/tools/base/__init__.py +8 -0
  115. agentscope_runtime/sandbox/tools/base/tool.py +52 -0
  116. agentscope_runtime/sandbox/tools/browser/__init__.py +57 -0
  117. agentscope_runtime/sandbox/tools/browser/tool.py +597 -0
  118. agentscope_runtime/sandbox/tools/filesystem/__init__.py +32 -0
  119. agentscope_runtime/sandbox/tools/filesystem/tool.py +319 -0
  120. agentscope_runtime/sandbox/tools/function_tool.py +321 -0
  121. agentscope_runtime/sandbox/tools/mcp_tool.py +191 -0
  122. agentscope_runtime/sandbox/tools/sandbox_tool.py +104 -0
  123. agentscope_runtime/sandbox/tools/tool.py +123 -0
  124. agentscope_runtime/sandbox/tools/utils.py +68 -0
  125. agentscope_runtime/version.py +2 -0
  126. agentscope_runtime-0.1.0.dist-info/METADATA +327 -0
  127. agentscope_runtime-0.1.0.dist-info/RECORD +131 -0
  128. agentscope_runtime-0.1.0.dist-info/WHEEL +5 -0
  129. agentscope_runtime-0.1.0.dist-info/entry_points.txt +4 -0
  130. agentscope_runtime-0.1.0.dist-info/licenses/LICENSE +202 -0
  131. agentscope_runtime-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,265 @@
1
+ # -*- coding: utf-8 -*-
2
+ """Module for the training sandbox client."""
3
+ # -*- coding: utf-8 -*-
4
+ # pylint: disable=unused-argument,too-many-return-statements
5
+ import time
6
+ import logging
7
+ from typing import Dict, List, Optional, Any
8
+
9
+ import requests
10
+ from requests.exceptions import HTTPError, JSONDecodeError
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+
15
+ class TrainingSandboxClient:
16
+ """Client for interacting with the training sandbox."""
17
+
18
+ def __init__(self, base_url: str = "http://localhost:8000"):
19
+ self.base_url = base_url.rstrip("/")
20
+ self.timeout = 100
21
+ self.session = requests.Session()
22
+
23
+ def __enter__(self):
24
+ # Wait for the runtime api server to be healthy
25
+ self.wait_until_healthy()
26
+ return self
27
+
28
+ def __exit__(self, exc_type, exc_value, traceback):
29
+ pass
30
+
31
+ def wait_until_healthy(self) -> None:
32
+ """
33
+ Waits until the runtime service is running for a specified timeout.
34
+ """
35
+ start_time = time.time()
36
+ while time.time() - start_time < self.timeout:
37
+ if self.check_health():
38
+ return
39
+ time.sleep(1)
40
+ raise TimeoutError(
41
+ "Runtime service did not start within the specified timeout.",
42
+ )
43
+
44
+ def check_health(self) -> bool:
45
+ """
46
+ Checks if the runtime service is running by verifying the health
47
+ endpoint.
48
+
49
+ Returns:
50
+ bool: True if the service is reachable, False otherwise
51
+ """
52
+ endpoint = f"{self.base_url}/healthz"
53
+
54
+ try:
55
+ response_api = self.session.get(endpoint)
56
+
57
+ return response_api.status_code == 200
58
+ except requests.RequestException:
59
+ return False
60
+
61
+ def _make_request(
62
+ self,
63
+ endpoint: str,
64
+ env_type: str = "default",
65
+ task_id: str = None,
66
+ instance_id: str = None,
67
+ messages: Dict[str, Any] = None,
68
+ params: Dict[str, Any] = None,
69
+ ) -> Dict:
70
+ """Request from fastapi"""
71
+ url = f"{self.base_url}/{endpoint}"
72
+ data = {
73
+ "env_type": env_type,
74
+ "task_id": task_id,
75
+ "instance_id": instance_id,
76
+ "messages": messages or {},
77
+ "params": params or {},
78
+ }
79
+ response = self.session.post(url, json=data)
80
+ try:
81
+ response.raise_for_status()
82
+ except HTTPError as e:
83
+ try:
84
+ detail = response.json().get("detail", "")
85
+ except JSONDecodeError:
86
+ detail = response.text
87
+
88
+ raise ValueError(
89
+ f"HTTP Error {e.response.status_code}: {detail}",
90
+ ) from e
91
+
92
+ return response.json()
93
+
94
+ def get_task_ids(
95
+ self,
96
+ env_type: str,
97
+ split: str = "train",
98
+ params: dict | None = None,
99
+ ) -> List[str]:
100
+ """Get task id list"""
101
+ payload = {"env_type": env_type}
102
+ if params:
103
+ payload["params"] = params
104
+ response = self._make_request(
105
+ endpoint="get_env_profile",
106
+ env_type=env_type,
107
+ params={"split": split},
108
+ )
109
+ return response["data"]
110
+
111
+ def get_env_profile(
112
+ self,
113
+ env_type: str,
114
+ split: str = "train",
115
+ params: dict | None = None,
116
+ ) -> List[str]:
117
+ """get environment profile"""
118
+ payload = {"env_type": env_type}
119
+ if params:
120
+ payload["params"] = params
121
+ response = self._make_request(
122
+ endpoint="get_env_profile",
123
+ env_type=env_type,
124
+ params={"split": split},
125
+ )
126
+ return response["data"]
127
+
128
+ def get_tools_info(
129
+ self,
130
+ instance_id: str,
131
+ messages: Dict = None,
132
+ params: Dict = None,
133
+ ) -> float:
134
+ """get tools information"""
135
+ messages = messages or {}
136
+ params = params or {}
137
+
138
+ response = self._make_request(
139
+ endpoint="get_info",
140
+ instance_id=instance_id,
141
+ messages=messages,
142
+ params=params,
143
+ )
144
+ return response["data"]
145
+
146
+ def create_instance(
147
+ self,
148
+ env_type: str,
149
+ task_id: str,
150
+ instance_id: str = None,
151
+ params: Dict = None,
152
+ ) -> Dict[str, str]:
153
+ """create instance of a task"""
154
+ response = self._make_request(
155
+ endpoint="create",
156
+ env_type=env_type,
157
+ task_id=task_id,
158
+ instance_id=instance_id,
159
+ params=params,
160
+ )
161
+ return response["data"]
162
+
163
+ def step(
164
+ self,
165
+ instance_id: str,
166
+ action: Dict = None,
167
+ params: Dict = None,
168
+ ) -> str:
169
+ """execute step transmission"""
170
+ action = action or {}
171
+ params = params or {}
172
+
173
+ response = self._make_request(
174
+ endpoint="step",
175
+ instance_id=instance_id,
176
+ messages=action,
177
+ params=params,
178
+ )
179
+ return response["data"]
180
+
181
+ def evaluate(
182
+ self,
183
+ instance_id: str,
184
+ messages: Dict = None,
185
+ params: Dict = None,
186
+ ) -> float:
187
+ """evaluate instance execution"""
188
+ messages = messages or {}
189
+ params = params or {}
190
+
191
+ response = self._make_request(
192
+ endpoint="evaluate",
193
+ instance_id=instance_id,
194
+ messages=messages,
195
+ params=params,
196
+ )
197
+ return response["data"]
198
+
199
+ def release_instance(self, instance_id: str) -> bool:
200
+ """release instance from memory"""
201
+ response = self._make_request(
202
+ endpoint="release",
203
+ instance_id=instance_id,
204
+ )
205
+ return response["success"]
206
+
207
+ # remined for future
208
+ def add_mcp_servers(self, server_configs, overwrite=False):
209
+ """add mcp for future"""
210
+ return None
211
+
212
+ def list_tools(self, **kwargs):
213
+ """list tools"""
214
+ if "instance_id" in kwargs:
215
+ # 只传get_tools_info的方法参数
216
+ return self.get_tools_info(
217
+ instance_id=kwargs.get("instance_id"),
218
+ messages=kwargs.get("messages", {}),
219
+ params=kwargs.get("params", {}),
220
+ )
221
+
222
+ return None
223
+
224
+ def call_tool(
225
+ self,
226
+ name: str,
227
+ arguments: Optional[dict[str, Any]] = None,
228
+ ) -> Any:
229
+ """release call tools"""
230
+ if arguments is None:
231
+ return None
232
+ if name == "create_instance":
233
+ return self.create_instance(
234
+ env_type=arguments.get("env_type", ""),
235
+ task_id=arguments.get("task_id", ""),
236
+ instance_id=arguments.get("instance_id", None),
237
+ params=arguments.get("params", {}),
238
+ )
239
+ if name == "release_instance":
240
+ return self.release_instance(instance_id=arguments["instance_id"])
241
+ if name == "evaluate":
242
+ return self.evaluate(
243
+ instance_id=arguments["instance_id"],
244
+ messages=arguments["messages"],
245
+ params=arguments["params"],
246
+ )
247
+
248
+ if name == "step":
249
+ return self.step(
250
+ instance_id=arguments["instance_id"],
251
+ action=arguments["action"],
252
+ params=arguments["params"],
253
+ )
254
+ if name in ["get_task_ids", "get_env_profile"]:
255
+ return self.get_env_profile(
256
+ env_type=arguments["env_type"],
257
+ split=arguments["split"],
258
+ params=arguments["params"],
259
+ )
260
+
261
+ logger.warning(
262
+ "missing function type of %s, please check the sandbox_client.py",
263
+ name,
264
+ )
265
+ return None
@@ -0,0 +1,5 @@
1
+ # -*- coding: utf-8 -*-
2
+ import os
3
+
4
+ IMAGE_TAG = os.getenv("RUNTIME_SANDBOX_IMAGE_TAG", "latest")
5
+ BROWSER_SESSION_ID = "123e4567-e89b-12d3-a456-426614174000"
@@ -0,0 +1,16 @@
1
+ # -*- coding: utf-8 -*-
2
+ import copy
3
+ from os.path import dirname, basename, isfile, join
4
+ import glob
5
+
6
+ modules = glob.glob(join(dirname(__file__), "*.py"))
7
+ __all__ = [
8
+ basename(f)[:-3]
9
+ for f in modules
10
+ if isfile(f) and not f.endswith("__init__.py")
11
+ ]
12
+
13
+ # to ensure the sub-configs registered before set up the global config
14
+ all_sub_configs_contrib = copy.copy(__all__)
15
+ if "config" in all_sub_configs_contrib:
16
+ all_sub_configs_contrib.remove("config")
@@ -0,0 +1,40 @@
1
+ # -*- coding: utf-8 -*-
2
+ import os
3
+
4
+ from typing import Optional
5
+
6
+ from ..constant import IMAGE_TAG
7
+ from ..registry import SandboxRegistry
8
+ from ..enums import SandboxType
9
+ from ..box.sandbox import Sandbox
10
+
11
+ SANDBOXTYPE = "custom_sandbox"
12
+
13
+
14
+ @SandboxRegistry.register(
15
+ f"agentscope/runtime-sandbox-{SANDBOXTYPE}:{IMAGE_TAG}",
16
+ sandbox_type=SANDBOXTYPE,
17
+ resource_limits={"memory": "16Gi", "cpu": "4"},
18
+ security_level="medium",
19
+ timeout=60,
20
+ description="my sandbox",
21
+ environment={
22
+ "TAVILY_API_KEY": os.getenv("TAVILY_API_KEY", ""),
23
+ "AMAP_MAPS_API_KEY": os.getenv("AMAP_MAPS_API_KEY", ""),
24
+ },
25
+ )
26
+ class CustomSandbox(Sandbox):
27
+ def __init__(
28
+ self,
29
+ sandbox_id: Optional[str] = None,
30
+ timeout: int = 3000,
31
+ base_url: Optional[str] = None,
32
+ bearer_token: Optional[str] = None,
33
+ ):
34
+ super().__init__(
35
+ sandbox_id,
36
+ timeout,
37
+ base_url,
38
+ bearer_token,
39
+ SandboxType(SANDBOXTYPE),
40
+ )
@@ -0,0 +1,37 @@
1
+ # -*- coding: utf-8 -*-
2
+ from typing import Optional
3
+
4
+ from ..constant import IMAGE_TAG
5
+ from ..registry import SandboxRegistry
6
+ from ..enums import SandboxType
7
+ from ..box.sandbox import Sandbox
8
+
9
+ SANDBOX_TYPE = "example"
10
+
11
+
12
+ @SandboxRegistry.register(
13
+ f"agentscope/runtime-sandbox-{SANDBOX_TYPE}:{IMAGE_TAG}",
14
+ sandbox_type=SANDBOX_TYPE,
15
+ resource_limits={"memory": "16Gi", "cpu": "4"},
16
+ security_level="medium",
17
+ timeout=60,
18
+ description="Example sandbox",
19
+ )
20
+ class ExampleSandbox(Sandbox):
21
+ def __init__(
22
+ self,
23
+ sandbox_id: Optional[str] = None,
24
+ timeout: int = 3000,
25
+ base_url: Optional[str] = None,
26
+ bearer_token: Optional[str] = None,
27
+ ):
28
+ super().__init__(
29
+ sandbox_id,
30
+ timeout,
31
+ base_url,
32
+ bearer_token,
33
+ SandboxType(SANDBOX_TYPE),
34
+ )
35
+ raise NotImplementedError(
36
+ "This sandbox is just a template and not implemented yet.",
37
+ )
@@ -0,0 +1,68 @@
1
+ # -*- coding: utf-8 -*-
2
+ from enum import Enum, EnumMeta
3
+
4
+
5
+ class DynamicEnumMeta(EnumMeta):
6
+ def __new__(
7
+ metacls,
8
+ cls,
9
+ bases,
10
+ classdict,
11
+ **kwds,
12
+ ): # pylint: disable=bad-mcs-classmethod-argument
13
+ enum_class = super().__new__(metacls, cls, bases, classdict, **kwds)
14
+ for member in enum_class:
15
+ member.builtin = True
16
+ return enum_class
17
+
18
+
19
+ class DynamicEnum(Enum, metaclass=DynamicEnumMeta):
20
+ def __init__(self, value): # pylint: disable=unused-argument
21
+ self.builtin = True
22
+
23
+ @classmethod
24
+ def add_member(cls, name: str, value=None):
25
+ if name in cls.__members__:
26
+ raise ValueError(f"Member '{name}' already exists.")
27
+
28
+ if value is None:
29
+ value = name.lower()
30
+
31
+ # Add new member
32
+ new_member = cls._create_pseudo_member(name, value)
33
+ new_member.builtin = False
34
+ cls._member_map_[name] = new_member
35
+ cls._value2member_map_[value] = new_member
36
+ # Update ordered members
37
+ cls._member_names_.append(name)
38
+
39
+ @classmethod
40
+ def _create_pseudo_member(cls, name, value):
41
+ temp = object.__new__(cls)
42
+ temp._value_ = value
43
+ temp._name_ = name
44
+ temp.__objclass__ = cls
45
+ return temp
46
+
47
+ @classmethod
48
+ def get_builtin_members(cls):
49
+ return [member for member in cls if getattr(member, "builtin", False)]
50
+
51
+ @classmethod
52
+ def get_dynamic_members(cls):
53
+ return [
54
+ member for member in cls if not getattr(member, "builtin", False)
55
+ ]
56
+
57
+ def is_builtin(self):
58
+ return getattr(self, "builtin", False)
59
+
60
+
61
+ class SandboxType(DynamicEnum):
62
+ """Sandbox type enumeration"""
63
+
64
+ DUMMY = "dummy"
65
+ BASE = "base"
66
+ BROWSER = "browser"
67
+ FILESYSTEM = "filesystem"
68
+ APPWORLD = "appworld"
@@ -0,0 +1,4 @@
1
+ # -*- coding: utf-8 -*-
2
+ from .sandbox_manager import SandboxManager
3
+
4
+ __all__ = ["SandboxManager"]
@@ -0,0 +1,22 @@
1
+ # -*- coding: utf-8 -*-
2
+ from .base_mapping import Mapping
3
+ from .base_set import SetCollection
4
+ from .base_queue import Queue
5
+ from .redis_set import RedisSetCollection
6
+ from .redis_queue import RedisQueue
7
+ from .redis_mapping import RedisMapping
8
+ from .in_memory_queue import InMemoryQueue
9
+ from .in_memory_set import InMemorySetCollection
10
+ from .in_memory_mapping import InMemoryMapping
11
+
12
+ __all__ = [
13
+ "Mapping",
14
+ "SetCollection",
15
+ "Queue",
16
+ "RedisSetCollection",
17
+ "RedisQueue",
18
+ "RedisMapping",
19
+ "InMemoryQueue",
20
+ "InMemorySetCollection",
21
+ "InMemoryMapping",
22
+ ]
@@ -0,0 +1,20 @@
1
+ # -*- coding: utf-8 -*-
2
+ from abc import ABC, abstractmethod
3
+
4
+
5
+ class Mapping(ABC):
6
+ @abstractmethod
7
+ def set(self, key: str, value: dict):
8
+ pass
9
+
10
+ @abstractmethod
11
+ def get(self, key: str) -> dict:
12
+ pass
13
+
14
+ @abstractmethod
15
+ def delete(self, key: str):
16
+ pass
17
+
18
+ @abstractmethod
19
+ def scan(self, prefix: str):
20
+ pass
@@ -0,0 +1,25 @@
1
+ # -*- coding: utf-8 -*-
2
+ # file: base_queue.py
3
+ from abc import ABC, abstractmethod
4
+
5
+
6
+ class Queue(ABC):
7
+ @abstractmethod
8
+ def enqueue(self, item: dict):
9
+ pass
10
+
11
+ @abstractmethod
12
+ def dequeue(self) -> dict:
13
+ pass
14
+
15
+ @abstractmethod
16
+ def peek(self) -> dict:
17
+ pass
18
+
19
+ @abstractmethod
20
+ def is_empty(self) -> bool:
21
+ pass
22
+
23
+ @abstractmethod
24
+ def size(self) -> int:
25
+ pass
@@ -0,0 +1,25 @@
1
+ # -*- coding: utf-8 -*-
2
+ # file: base_set_collection.py
3
+ from abc import ABC, abstractmethod
4
+
5
+
6
+ class SetCollection(ABC):
7
+ @abstractmethod
8
+ def add(self, value: str):
9
+ pass
10
+
11
+ @abstractmethod
12
+ def remove(self, value: str):
13
+ pass
14
+
15
+ @abstractmethod
16
+ def contains(self, value: str) -> bool:
17
+ pass
18
+
19
+ @abstractmethod
20
+ def clear(self):
21
+ pass
22
+
23
+ @abstractmethod
24
+ def to_list(self) -> list:
25
+ pass
@@ -0,0 +1,22 @@
1
+ # -*- coding: utf-8 -*-
2
+ from .base_mapping import Mapping
3
+
4
+
5
+ class InMemoryMapping(Mapping):
6
+ def __init__(self):
7
+ self.store = {}
8
+
9
+ def set(self, key: str, value: dict):
10
+ self.store[key] = value
11
+
12
+ def get(self, key: str) -> dict:
13
+ return self.store.get(key)
14
+
15
+ def delete(self, key: str):
16
+ if key in self.store:
17
+ del self.store[key]
18
+
19
+ def scan(self, prefix: str):
20
+ for key in list(self.store.keys()):
21
+ if key.startswith(prefix):
22
+ yield key
@@ -0,0 +1,28 @@
1
+ # -*- coding: utf-8 -*-
2
+ # file: in_memory_queue.py
3
+ from .base_queue import Queue
4
+
5
+
6
+ class InMemoryQueue(Queue):
7
+ def __init__(self):
8
+ self.queue = []
9
+
10
+ def enqueue(self, item: dict):
11
+ self.queue.append(item)
12
+
13
+ def dequeue(self):
14
+ if self.queue:
15
+ return self.queue.pop(0)
16
+ return None
17
+
18
+ def peek(self):
19
+ if self.queue:
20
+ return self.queue[0]
21
+ return None
22
+
23
+ def is_empty(self) -> bool:
24
+ return len(self.queue) == 0
25
+
26
+ def size(self) -> int:
27
+ """Returns the number of items in the queue."""
28
+ return len(self.queue)
@@ -0,0 +1,27 @@
1
+ # -*- coding: utf-8 -*-
2
+ # file: in_memory_set_collection.py
3
+ from .base_set import SetCollection
4
+
5
+
6
+ class InMemorySetCollection(SetCollection):
7
+ def __init__(self):
8
+ self.set = set()
9
+
10
+ def add(self, value: str):
11
+ if value in self.set:
12
+ return False
13
+ else:
14
+ self.set.add(value)
15
+ return True
16
+
17
+ def remove(self, value: str):
18
+ self.set.discard(value)
19
+
20
+ def contains(self, value: str) -> bool:
21
+ return value in self.set
22
+
23
+ def clear(self):
24
+ self.set.clear()
25
+
26
+ def to_list(self) -> list:
27
+ return list(self.set)
@@ -0,0 +1,26 @@
1
+ # -*- coding: utf-8 -*-
2
+ import json
3
+
4
+ from .base_mapping import Mapping
5
+
6
+
7
+ class RedisMapping(Mapping):
8
+ def __init__(self, redis_client):
9
+ self.client = redis_client
10
+
11
+ def set(self, key: str, value: dict):
12
+ self.client.set(key, json.dumps(value))
13
+
14
+ def get(self, key: str) -> dict:
15
+ value = self.client.get(key)
16
+ return json.loads(value) if value else None
17
+
18
+ def delete(self, key: str):
19
+ self.client.delete(key)
20
+
21
+ def scan(self, prefix: str):
22
+ cursor = 0
23
+ while cursor != 0:
24
+ cursor, keys = self.client.scan(cursor=cursor, match=f"{prefix}*")
25
+ for key in keys:
26
+ yield key.decode("utf-8")
@@ -0,0 +1,27 @@
1
+ # -*- coding: utf-8 -*-
2
+ # file: redis_queue.py
3
+ import json
4
+ from .base_queue import Queue
5
+
6
+
7
+ class RedisQueue(Queue):
8
+ def __init__(self, redis_client, queue_name: str):
9
+ self.client = redis_client
10
+ self.queue_name = queue_name
11
+
12
+ def enqueue(self, item: dict):
13
+ self.client.rpush(self.queue_name, json.dumps(item))
14
+
15
+ def dequeue(self) -> dict:
16
+ item = self.client.lpop(self.queue_name)
17
+ return json.loads(item) if item is not None else None
18
+
19
+ def peek(self) -> dict:
20
+ item = self.client.lindex(self.queue_name, 0)
21
+ return json.loads(item) if item is not None else None
22
+
23
+ def is_empty(self) -> bool:
24
+ return self.client.llen(self.queue_name) == 0
25
+
26
+ def size(self) -> int:
27
+ return self.client.llen(self.queue_name)
@@ -0,0 +1,23 @@
1
+ # -*- coding: utf-8 -*-
2
+ from .base_set import SetCollection
3
+
4
+
5
+ class RedisSetCollection(SetCollection):
6
+ def __init__(self, redis_client, set_name: str):
7
+ self.client = redis_client
8
+ self.set_name = set_name
9
+
10
+ def add(self, value: str):
11
+ return self.client.sadd(self.set_name, value) == 1
12
+
13
+ def remove(self, value: str):
14
+ self.client.srem(self.set_name, value)
15
+
16
+ def contains(self, value: str) -> bool:
17
+ return self.client.sismember(self.set_name, value)
18
+
19
+ def clear(self):
20
+ self.client.delete(self.set_name)
21
+
22
+ def to_list(self) -> list:
23
+ return list(self.client.smembers(self.set_name))