agentrun-inner-test 0.0.46__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 (135) hide show
  1. agentrun/__init__.py +325 -0
  2. agentrun/agent_runtime/__client_async_template.py +466 -0
  3. agentrun/agent_runtime/__endpoint_async_template.py +345 -0
  4. agentrun/agent_runtime/__init__.py +53 -0
  5. agentrun/agent_runtime/__runtime_async_template.py +477 -0
  6. agentrun/agent_runtime/api/__data_async_template.py +58 -0
  7. agentrun/agent_runtime/api/__init__.py +6 -0
  8. agentrun/agent_runtime/api/control.py +1362 -0
  9. agentrun/agent_runtime/api/data.py +98 -0
  10. agentrun/agent_runtime/client.py +868 -0
  11. agentrun/agent_runtime/endpoint.py +649 -0
  12. agentrun/agent_runtime/model.py +362 -0
  13. agentrun/agent_runtime/runtime.py +904 -0
  14. agentrun/credential/__client_async_template.py +177 -0
  15. agentrun/credential/__credential_async_template.py +216 -0
  16. agentrun/credential/__init__.py +28 -0
  17. agentrun/credential/api/__init__.py +5 -0
  18. agentrun/credential/api/control.py +606 -0
  19. agentrun/credential/client.py +319 -0
  20. agentrun/credential/credential.py +381 -0
  21. agentrun/credential/model.py +248 -0
  22. agentrun/integration/__init__.py +21 -0
  23. agentrun/integration/agentscope/__init__.py +12 -0
  24. agentrun/integration/agentscope/adapter.py +17 -0
  25. agentrun/integration/agentscope/builtin.py +65 -0
  26. agentrun/integration/agentscope/message_adapter.py +185 -0
  27. agentrun/integration/agentscope/model_adapter.py +60 -0
  28. agentrun/integration/agentscope/tool_adapter.py +59 -0
  29. agentrun/integration/builtin/__init__.py +16 -0
  30. agentrun/integration/builtin/model.py +93 -0
  31. agentrun/integration/builtin/sandbox.py +1234 -0
  32. agentrun/integration/builtin/toolset.py +47 -0
  33. agentrun/integration/crewai/__init__.py +12 -0
  34. agentrun/integration/crewai/adapter.py +9 -0
  35. agentrun/integration/crewai/builtin.py +65 -0
  36. agentrun/integration/crewai/model_adapter.py +31 -0
  37. agentrun/integration/crewai/tool_adapter.py +26 -0
  38. agentrun/integration/google_adk/__init__.py +12 -0
  39. agentrun/integration/google_adk/adapter.py +15 -0
  40. agentrun/integration/google_adk/builtin.py +65 -0
  41. agentrun/integration/google_adk/message_adapter.py +144 -0
  42. agentrun/integration/google_adk/model_adapter.py +46 -0
  43. agentrun/integration/google_adk/tool_adapter.py +235 -0
  44. agentrun/integration/langchain/__init__.py +30 -0
  45. agentrun/integration/langchain/adapter.py +15 -0
  46. agentrun/integration/langchain/builtin.py +71 -0
  47. agentrun/integration/langchain/message_adapter.py +141 -0
  48. agentrun/integration/langchain/model_adapter.py +37 -0
  49. agentrun/integration/langchain/tool_adapter.py +50 -0
  50. agentrun/integration/langgraph/__init__.py +35 -0
  51. agentrun/integration/langgraph/adapter.py +20 -0
  52. agentrun/integration/langgraph/agent_converter.py +1073 -0
  53. agentrun/integration/langgraph/builtin.py +65 -0
  54. agentrun/integration/pydantic_ai/__init__.py +12 -0
  55. agentrun/integration/pydantic_ai/adapter.py +13 -0
  56. agentrun/integration/pydantic_ai/builtin.py +65 -0
  57. agentrun/integration/pydantic_ai/model_adapter.py +44 -0
  58. agentrun/integration/pydantic_ai/tool_adapter.py +19 -0
  59. agentrun/integration/utils/__init__.py +112 -0
  60. agentrun/integration/utils/adapter.py +560 -0
  61. agentrun/integration/utils/canonical.py +164 -0
  62. agentrun/integration/utils/converter.py +134 -0
  63. agentrun/integration/utils/model.py +110 -0
  64. agentrun/integration/utils/tool.py +1759 -0
  65. agentrun/model/__client_async_template.py +357 -0
  66. agentrun/model/__init__.py +57 -0
  67. agentrun/model/__model_proxy_async_template.py +270 -0
  68. agentrun/model/__model_service_async_template.py +267 -0
  69. agentrun/model/api/__init__.py +6 -0
  70. agentrun/model/api/control.py +1173 -0
  71. agentrun/model/api/data.py +196 -0
  72. agentrun/model/client.py +674 -0
  73. agentrun/model/model.py +235 -0
  74. agentrun/model/model_proxy.py +439 -0
  75. agentrun/model/model_service.py +438 -0
  76. agentrun/sandbox/__aio_sandbox_async_template.py +523 -0
  77. agentrun/sandbox/__browser_sandbox_async_template.py +110 -0
  78. agentrun/sandbox/__client_async_template.py +491 -0
  79. agentrun/sandbox/__code_interpreter_sandbox_async_template.py +463 -0
  80. agentrun/sandbox/__init__.py +69 -0
  81. agentrun/sandbox/__sandbox_async_template.py +463 -0
  82. agentrun/sandbox/__template_async_template.py +152 -0
  83. agentrun/sandbox/aio_sandbox.py +905 -0
  84. agentrun/sandbox/api/__aio_data_async_template.py +335 -0
  85. agentrun/sandbox/api/__browser_data_async_template.py +140 -0
  86. agentrun/sandbox/api/__code_interpreter_data_async_template.py +206 -0
  87. agentrun/sandbox/api/__init__.py +19 -0
  88. agentrun/sandbox/api/__sandbox_data_async_template.py +107 -0
  89. agentrun/sandbox/api/aio_data.py +551 -0
  90. agentrun/sandbox/api/browser_data.py +172 -0
  91. agentrun/sandbox/api/code_interpreter_data.py +396 -0
  92. agentrun/sandbox/api/control.py +1051 -0
  93. agentrun/sandbox/api/playwright_async.py +492 -0
  94. agentrun/sandbox/api/playwright_sync.py +492 -0
  95. agentrun/sandbox/api/sandbox_data.py +154 -0
  96. agentrun/sandbox/browser_sandbox.py +185 -0
  97. agentrun/sandbox/client.py +925 -0
  98. agentrun/sandbox/code_interpreter_sandbox.py +823 -0
  99. agentrun/sandbox/model.py +397 -0
  100. agentrun/sandbox/sandbox.py +848 -0
  101. agentrun/sandbox/template.py +217 -0
  102. agentrun/server/__init__.py +191 -0
  103. agentrun/server/agui_normalizer.py +180 -0
  104. agentrun/server/agui_protocol.py +797 -0
  105. agentrun/server/invoker.py +309 -0
  106. agentrun/server/model.py +427 -0
  107. agentrun/server/openai_protocol.py +535 -0
  108. agentrun/server/protocol.py +140 -0
  109. agentrun/server/server.py +208 -0
  110. agentrun/toolset/__client_async_template.py +62 -0
  111. agentrun/toolset/__init__.py +51 -0
  112. agentrun/toolset/__toolset_async_template.py +204 -0
  113. agentrun/toolset/api/__init__.py +17 -0
  114. agentrun/toolset/api/control.py +262 -0
  115. agentrun/toolset/api/mcp.py +100 -0
  116. agentrun/toolset/api/openapi.py +1251 -0
  117. agentrun/toolset/client.py +102 -0
  118. agentrun/toolset/model.py +321 -0
  119. agentrun/toolset/toolset.py +270 -0
  120. agentrun/utils/__data_api_async_template.py +720 -0
  121. agentrun/utils/__init__.py +5 -0
  122. agentrun/utils/__resource_async_template.py +158 -0
  123. agentrun/utils/config.py +258 -0
  124. agentrun/utils/control_api.py +78 -0
  125. agentrun/utils/data_api.py +1120 -0
  126. agentrun/utils/exception.py +151 -0
  127. agentrun/utils/helper.py +108 -0
  128. agentrun/utils/log.py +77 -0
  129. agentrun/utils/model.py +168 -0
  130. agentrun/utils/resource.py +291 -0
  131. agentrun_inner_test-0.0.46.dist-info/METADATA +263 -0
  132. agentrun_inner_test-0.0.46.dist-info/RECORD +135 -0
  133. agentrun_inner_test-0.0.46.dist-info/WHEEL +5 -0
  134. agentrun_inner_test-0.0.46.dist-info/licenses/LICENSE +201 -0
  135. agentrun_inner_test-0.0.46.dist-info/top_level.txt +1 -0
@@ -0,0 +1,107 @@
1
+ """Sandbox数据API模板 / Sandbox Data API Template
2
+
3
+ 此模板用于生成沙箱数据API代码。
4
+ This template is used to generate sandbox data API code.
5
+ """
6
+
7
+ from typing import Any, Dict, Optional
8
+
9
+ from agentrun.utils.config import Config
10
+ from agentrun.utils.data_api import DataAPI, ResourceType
11
+
12
+
13
+ class SandboxDataAPI(DataAPI):
14
+
15
+ def __init__(
16
+ self,
17
+ *,
18
+ sandbox_id: Optional[str] = None,
19
+ template_name: Optional[str] = None,
20
+ config: Optional[Config] = None,
21
+ ):
22
+
23
+ super().__init__(
24
+ resource_name="",
25
+ resource_type=ResourceType.Template,
26
+ namespace="sandboxes",
27
+ config=config,
28
+ )
29
+ self.access_token_map = {}
30
+
31
+ if sandbox_id or template_name:
32
+ self.__refresh_access_token(
33
+ sandbox_id=sandbox_id,
34
+ template_name=template_name,
35
+ config=config,
36
+ )
37
+
38
+ def __refresh_access_token(
39
+ self,
40
+ *,
41
+ sandbox_id: Optional[str] = None,
42
+ template_name: Optional[str] = None,
43
+ config: Optional[Config] = None,
44
+ ):
45
+ cfg = Config.with_configs(config, self.config)
46
+ token = self.access_token_map.get(sandbox_id or template_name)
47
+ if sandbox_id:
48
+ self.resource_name = sandbox_id
49
+ self.resource_type = ResourceType.Sandbox
50
+ self.namespace = f"sandboxes/{sandbox_id}"
51
+ else:
52
+ self.resource_name = template_name
53
+ self.resource_type = ResourceType.Template
54
+ self.namespace = "sandboxes"
55
+
56
+ if token:
57
+ self.access_token = token
58
+ return
59
+
60
+ # 没有缓存过的 token
61
+
62
+ self.access_token = None
63
+ self.auth(config=cfg)
64
+ self.access_token_map[sandbox_id or template_name] = self.access_token
65
+
66
+ async def check_health_async(self):
67
+ return await self.get_async("/health")
68
+
69
+ async def create_sandbox_async(
70
+ self,
71
+ template_name: str,
72
+ sandbox_idle_timeout_seconds: Optional[int] = 600,
73
+ nas_config: Optional[Dict[str, Any]] = None,
74
+ oss_mount_config: Optional[Dict[str, Any]] = None,
75
+ polar_fs_config: Optional[Dict[str, Any]] = None,
76
+ config: Optional[Config] = None,
77
+ ):
78
+ self.__refresh_access_token(template_name=template_name, config=config)
79
+ data: Dict[str, Any] = {
80
+ "templateName": template_name,
81
+ "sandboxIdleTimeoutSeconds": sandbox_idle_timeout_seconds,
82
+ }
83
+ if nas_config is not None:
84
+ data["nasConfig"] = nas_config
85
+ if oss_mount_config is not None:
86
+ data["ossMountConfig"] = oss_mount_config
87
+ if polar_fs_config is not None:
88
+ data["polarFsConfig"] = polar_fs_config
89
+ return await self.post_async("/", data=data)
90
+
91
+ async def delete_sandbox_async(
92
+ self, sandbox_id: str, config: Optional[Config] = None
93
+ ):
94
+ self.__refresh_access_token(sandbox_id=sandbox_id, config=config)
95
+ return await self.delete_async("/")
96
+
97
+ async def stop_sandbox_async(
98
+ self, sandbox_id: str, config: Optional[Config] = None
99
+ ):
100
+ self.__refresh_access_token(sandbox_id=sandbox_id, config=config)
101
+ return await self.post_async("/stop")
102
+
103
+ async def get_sandbox_async(
104
+ self, sandbox_id: str, config: Optional[Config] = None
105
+ ):
106
+ self.__refresh_access_token(sandbox_id=sandbox_id, config=config)
107
+ return await self.get_async("/")
@@ -0,0 +1,551 @@
1
+ """
2
+ This file is auto generated by the code generation script.
3
+ Do not modify this file manually.
4
+ Use the `make codegen` command to regenerate.
5
+
6
+ 当前文件为自动生成的控制 API 客户端代码。请勿手动修改此文件。
7
+ 使用 `make codegen` 命令重新生成。
8
+
9
+ source: agentrun/sandbox/api/__aio_data_async_template.py
10
+
11
+ All-in-One 沙箱数据API模板 / All-in-One Sandbox Data API Template
12
+
13
+ 此模板用于生成 All-in-One 沙箱数据API代码,结合了浏览器和代码解释器的功能。
14
+ This template is used to generate All-in-One sandbox data API code,
15
+ combining browser and code interpreter capabilities.
16
+ """
17
+
18
+ from typing import Any, Dict, Optional
19
+ from urllib.parse import parse_qs, urlencode, urlparse
20
+
21
+ from agentrun.sandbox.model import CodeLanguage
22
+ from agentrun.utils.config import Config
23
+
24
+ from .sandbox_data import SandboxDataAPI
25
+
26
+
27
+ class AioDataAPI(SandboxDataAPI):
28
+ """All-in-One Sandbox Data API
29
+
30
+ This class combines the functionality of BrowserDataAPI and CodeInterpreterDataAPI,
31
+ providing a unified interface for all-in-one sandbox operations.
32
+ """
33
+
34
+ def __init__(
35
+ self,
36
+ sandbox_id: str,
37
+ config: Optional[Config] = None,
38
+ ):
39
+ self.sandbox_id = sandbox_id
40
+ super().__init__(
41
+ sandbox_id=sandbox_id,
42
+ config=config,
43
+ )
44
+
45
+ # ========================================
46
+ # Browser API Methods
47
+ # ========================================
48
+
49
+ def get_cdp_url(self, record: Optional[bool] = False):
50
+ """
51
+ Generate the WebSocket URL for Chrome DevTools Protocol (CDP) connection.
52
+
53
+ This method constructs a WebSocket URL by:
54
+ 1. Converting the HTTP endpoint to WebSocket protocol (ws://)
55
+ 2. Parsing the existing URL and query parameters
56
+ 3. Adding the session ID to the query parameters
57
+ 4. Reconstructing the complete WebSocket URL
58
+
59
+ Returns:
60
+ str: The complete WebSocket URL for CDP automation connection,
61
+ including the session ID in the query parameters.
62
+
63
+ Example:
64
+ >>> api = AioDataAPI("sandbox123")
65
+ >>> api.get_cdp_url()
66
+ 'ws://example.com/ws/automation?sessionId=session456'
67
+ """
68
+ cdp_url = self.with_path("/ws/automation").replace("http", "ws")
69
+ u = urlparse(cdp_url)
70
+ query_dict = parse_qs(u.query)
71
+ query_dict["tenantId"] = [self.config.get_account_id()]
72
+ if record:
73
+ query_dict["recording"] = ["true"]
74
+ new_query = urlencode(query_dict, doseq=True)
75
+ new_u = u._replace(query=new_query)
76
+ return new_u.geturl()
77
+
78
+ def get_vnc_url(self, record: Optional[bool] = False):
79
+ """
80
+ Generate the WebSocket URL for VNC (Virtual Network Computing) live view connection.
81
+
82
+ This method constructs a WebSocket URL for real-time browser viewing by:
83
+ 1. Converting the HTTP endpoint to WebSocket protocol (ws://)
84
+ 2. Parsing the existing URL and query parameters
85
+ 3. Adding the session ID to the query parameters
86
+ 4. Reconstructing the complete WebSocket URL
87
+
88
+ Returns:
89
+ str: The complete WebSocket URL for VNC live view connection,
90
+ including the session ID in the query parameters.
91
+
92
+ Example:
93
+ >>> api = AioDataAPI("sandbox123")
94
+ >>> api.get_vnc_url()
95
+ 'ws://example.com/ws/liveview?sessionId=session456'
96
+ """
97
+ vnc_url = self.with_path("/ws/liveview").replace("http", "ws")
98
+ u = urlparse(vnc_url)
99
+ query_dict = parse_qs(u.query)
100
+ query_dict["tenantId"] = [self.config.get_account_id()]
101
+ if record:
102
+ query_dict["recording"] = ["true"]
103
+ new_query = urlencode(query_dict, doseq=True)
104
+ new_u = u._replace(query=new_query)
105
+ return new_u.geturl()
106
+
107
+ def sync_playwright(
108
+ self,
109
+ browser_type: str = "chrome",
110
+ record: Optional[bool] = False,
111
+ config: Optional[Config] = None,
112
+ ):
113
+ from .playwright_sync import BrowserPlaywrightSync
114
+
115
+ cfg = Config.with_configs(self.config, config)
116
+ _, headers, _ = self.auth(headers=cfg.get_headers(), config=cfg)
117
+ return BrowserPlaywrightSync(
118
+ self.get_cdp_url(record=record),
119
+ browser_type=browser_type,
120
+ headers=headers,
121
+ )
122
+
123
+ def async_playwright(
124
+ self,
125
+ browser_type: str = "chrome",
126
+ record: Optional[bool] = False,
127
+ config: Optional[Config] = None,
128
+ ):
129
+ from .playwright_async import BrowserPlaywrightAsync
130
+
131
+ cfg = Config.with_configs(self.config, config)
132
+ _, headers, _ = self.auth(headers=cfg.get_headers(), config=cfg)
133
+ return BrowserPlaywrightAsync(
134
+ self.get_cdp_url(record=record),
135
+ browser_type=browser_type,
136
+ headers=headers,
137
+ )
138
+
139
+ async def list_recordings_async(self):
140
+ return await self.get_async("/recordings")
141
+
142
+ def list_recordings(self):
143
+ return self.get("/recordings")
144
+
145
+ async def delete_recording_async(self, filename: str):
146
+ return await self.delete_async(f"/recordings/{filename}")
147
+
148
+ def delete_recording(self, filename: str):
149
+ return self.delete(f"/recordings/{filename}")
150
+
151
+ async def download_recording_async(self, filename: str, save_path: str):
152
+ """
153
+ Asynchronously download a recording video file and save it to local path.
154
+
155
+ Args:
156
+ filename: The name of the recording file to download
157
+ save_path: Local file path to save the downloaded video file (.mkv)
158
+
159
+ Returns:
160
+ Dictionary with 'saved_path' and 'size' keys
161
+
162
+ Examples:
163
+ >>> await api.download_recording_async("recording.mp4", "/local/video.mkv")
164
+ """
165
+ return await self.get_video_async(
166
+ f"/recordings/{filename}", save_path=save_path
167
+ )
168
+
169
+ # ========================================
170
+ # Code Interpreter API Methods
171
+ # ========================================
172
+
173
+ def download_recording(self, filename: str, save_path: str):
174
+ """
175
+ Synchronously download a recording video file and save it to local path.
176
+
177
+ Args:
178
+ filename: The name of the recording file to download
179
+ save_path: Local file path to save the downloaded video file (.mkv)
180
+
181
+ Returns:
182
+ Dictionary with 'saved_path' and 'size' keys
183
+
184
+ Examples:
185
+ >>> api.download_recording("recording.mp4", "/local/video.mkv")
186
+ """
187
+ return self.get_video(f"/recordings/{filename}", save_path=save_path)
188
+
189
+ # ========================================
190
+ # Code Interpreter API Methods
191
+ # ========================================
192
+
193
+ async def list_directory_async(
194
+ self,
195
+ path: Optional[str] = None,
196
+ depth: Optional[int] = None,
197
+ ):
198
+ query = {}
199
+ if path is not None:
200
+ query["path"] = path
201
+ if depth is not None:
202
+ query["depth"] = depth
203
+
204
+ return await self.get_async("/filesystem", query=query)
205
+
206
+ def list_directory(
207
+ self,
208
+ path: Optional[str] = None,
209
+ depth: Optional[int] = None,
210
+ ):
211
+ query = {}
212
+ if path is not None:
213
+ query["path"] = path
214
+ if depth is not None:
215
+ query["depth"] = depth
216
+
217
+ return self.get("/filesystem", query=query)
218
+
219
+ async def stat_async(
220
+ self,
221
+ path: str,
222
+ ):
223
+ query = {
224
+ "path": path,
225
+ }
226
+ return await self.get_async("/filesystem/stat", query=query)
227
+
228
+ def stat(
229
+ self,
230
+ path: str,
231
+ ):
232
+ query = {
233
+ "path": path,
234
+ }
235
+ return self.get("/filesystem/stat", query=query)
236
+
237
+ async def mkdir_async(
238
+ self,
239
+ path: str,
240
+ parents: Optional[bool] = True,
241
+ mode: Optional[str] = "0755",
242
+ ):
243
+ data = {
244
+ "path": path,
245
+ "parents": parents,
246
+ "mode": mode,
247
+ }
248
+ return await self.post_async("/filesystem/mkdir", data=data)
249
+
250
+ def mkdir(
251
+ self,
252
+ path: str,
253
+ parents: Optional[bool] = True,
254
+ mode: Optional[str] = "0755",
255
+ ):
256
+ data = {
257
+ "path": path,
258
+ "parents": parents,
259
+ "mode": mode,
260
+ }
261
+ return self.post("/filesystem/mkdir", data=data)
262
+
263
+ async def move_file_async(
264
+ self,
265
+ source: str,
266
+ destination: str,
267
+ ):
268
+ data = {
269
+ "source": source,
270
+ "destination": destination,
271
+ }
272
+ return await self.post_async("/filesystem/move", data=data)
273
+
274
+ def move_file(
275
+ self,
276
+ source: str,
277
+ destination: str,
278
+ ):
279
+ data = {
280
+ "source": source,
281
+ "destination": destination,
282
+ }
283
+ return self.post("/filesystem/move", data=data)
284
+
285
+ async def remove_file_async(
286
+ self,
287
+ path: str,
288
+ ):
289
+ data = {
290
+ "path": path,
291
+ }
292
+ return await self.post_async("/filesystem/remove", data=data)
293
+
294
+ def remove_file(
295
+ self,
296
+ path: str,
297
+ ):
298
+ data = {
299
+ "path": path,
300
+ }
301
+ return self.post("/filesystem/remove", data=data)
302
+
303
+ async def list_contexts_async(self):
304
+ return await self.get_async("/contexts")
305
+
306
+ def list_contexts(self):
307
+ return self.get("/contexts")
308
+
309
+ async def create_context_async(
310
+ self,
311
+ language: Optional[CodeLanguage] = CodeLanguage.PYTHON,
312
+ cwd: str = "/home/user",
313
+ ):
314
+ # Validate language parameter
315
+ if language not in ("python", "javascript"):
316
+ raise ValueError(
317
+ f"language must be 'python' or 'javascript', got: {language}"
318
+ )
319
+
320
+ data: Dict[str, Any] = {
321
+ "cwd": cwd,
322
+ "language": language,
323
+ }
324
+ return await self.post_async("/contexts", data=data)
325
+
326
+ def create_context(
327
+ self,
328
+ language: Optional[CodeLanguage] = CodeLanguage.PYTHON,
329
+ cwd: str = "/home/user",
330
+ ):
331
+ # Validate language parameter
332
+ if language not in ("python", "javascript"):
333
+ raise ValueError(
334
+ f"language must be 'python' or 'javascript', got: {language}"
335
+ )
336
+
337
+ data: Dict[str, Any] = {
338
+ "cwd": cwd,
339
+ "language": language,
340
+ }
341
+ return self.post("/contexts", data=data)
342
+
343
+ async def get_context_async(
344
+ self,
345
+ context_id: str,
346
+ ):
347
+ return await self.get_async(f"/contexts/{context_id}")
348
+
349
+ def get_context(
350
+ self,
351
+ context_id: str,
352
+ ):
353
+ return self.get(f"/contexts/{context_id}")
354
+
355
+ async def execute_code_async(
356
+ self,
357
+ code: str,
358
+ context_id: Optional[str],
359
+ language: Optional[CodeLanguage] = None,
360
+ timeout: Optional[int] = 30,
361
+ ):
362
+ if language and language not in ("python", "javascript"):
363
+ raise ValueError(
364
+ f"language must be 'python' or 'javascript', got: {language}"
365
+ )
366
+
367
+ data: Dict[str, Any] = {
368
+ "code": code,
369
+ }
370
+ if timeout is not None:
371
+ data["timeout"] = timeout
372
+ if language is not None:
373
+ data["language"] = language
374
+ if context_id is not None:
375
+ data["contextId"] = context_id
376
+ return await self.post_async(f"/contexts/execute", data=data)
377
+
378
+ def execute_code(
379
+ self,
380
+ code: str,
381
+ context_id: Optional[str],
382
+ language: Optional[CodeLanguage] = None,
383
+ timeout: Optional[int] = 30,
384
+ ):
385
+ if language and language not in ("python", "javascript"):
386
+ raise ValueError(
387
+ f"language must be 'python' or 'javascript', got: {language}"
388
+ )
389
+
390
+ data: Dict[str, Any] = {
391
+ "code": code,
392
+ }
393
+ if timeout is not None:
394
+ data["timeout"] = timeout
395
+ if language is not None:
396
+ data["language"] = language
397
+ if context_id is not None:
398
+ data["contextId"] = context_id
399
+ return self.post(f"/contexts/execute", data=data)
400
+
401
+ async def delete_context_async(
402
+ self,
403
+ context_id: str,
404
+ ):
405
+ return await self.delete_async(f"/contexts/{context_id}")
406
+
407
+ def delete_context(
408
+ self,
409
+ context_id: str,
410
+ ):
411
+ return self.delete(f"/contexts/{context_id}")
412
+
413
+ async def read_file_async(
414
+ self,
415
+ path: str,
416
+ ):
417
+ query = {
418
+ "path": path,
419
+ }
420
+ return await self.get_async("/files", query=query)
421
+
422
+ def read_file(
423
+ self,
424
+ path: str,
425
+ ):
426
+ query = {
427
+ "path": path,
428
+ }
429
+ return self.get("/files", query=query)
430
+
431
+ async def write_file_async(
432
+ self,
433
+ path: str,
434
+ content: str,
435
+ mode: Optional[str] = "644",
436
+ encoding: Optional[str] = "utf-8",
437
+ create_dir: Optional[bool] = True,
438
+ ):
439
+ data = {
440
+ "path": path,
441
+ "content": content,
442
+ "mode": mode,
443
+ "encoding": encoding,
444
+ "createDir": create_dir,
445
+ }
446
+ return await self.post_async("/files", data=data)
447
+
448
+ def write_file(
449
+ self,
450
+ path: str,
451
+ content: str,
452
+ mode: Optional[str] = "644",
453
+ encoding: Optional[str] = "utf-8",
454
+ create_dir: Optional[bool] = True,
455
+ ):
456
+ data = {
457
+ "path": path,
458
+ "content": content,
459
+ "mode": mode,
460
+ "encoding": encoding,
461
+ "createDir": create_dir,
462
+ }
463
+ return self.post("/files", data=data)
464
+
465
+ async def upload_file_async(
466
+ self,
467
+ local_file_path: str,
468
+ target_file_path: str,
469
+ ):
470
+ return await self.post_file_async(
471
+ path="/filesystem/upload",
472
+ local_file_path=local_file_path,
473
+ target_file_path=target_file_path,
474
+ )
475
+
476
+ def upload_file(
477
+ self,
478
+ local_file_path: str,
479
+ target_file_path: str,
480
+ ):
481
+ return self.post_file(
482
+ path="/filesystem/upload",
483
+ local_file_path=local_file_path,
484
+ target_file_path=target_file_path,
485
+ )
486
+
487
+ async def download_file_async(
488
+ self,
489
+ path: str,
490
+ save_path: str,
491
+ ):
492
+ query = {"path": path}
493
+ return await self.get_file_async(
494
+ path="/filesystem/download", save_path=save_path, query=query
495
+ )
496
+
497
+ def download_file(
498
+ self,
499
+ path: str,
500
+ save_path: str,
501
+ ):
502
+ query = {"path": path}
503
+ return self.get_file(
504
+ path="/filesystem/download", save_path=save_path, query=query
505
+ )
506
+
507
+ async def cmd_async(
508
+ self,
509
+ command: str,
510
+ cwd: str,
511
+ timeout: Optional[int] = 30,
512
+ ):
513
+ data: Dict[str, Any] = {
514
+ "command": command,
515
+ "cwd": cwd,
516
+ }
517
+ if timeout is not None:
518
+ data["timeout"] = timeout
519
+ return await self.post_async("/processes/cmd", data=data)
520
+
521
+ def cmd(
522
+ self,
523
+ command: str,
524
+ cwd: str,
525
+ timeout: Optional[int] = 30,
526
+ ):
527
+ data: Dict[str, Any] = {
528
+ "command": command,
529
+ "cwd": cwd,
530
+ }
531
+ if timeout is not None:
532
+ data["timeout"] = timeout
533
+ return self.post("/processes/cmd", data=data)
534
+
535
+ async def list_processes_async(self):
536
+ return await self.get_async("/processes")
537
+
538
+ def list_processes(self):
539
+ return self.get("/processes")
540
+
541
+ async def get_process_async(self, pid: str):
542
+ return await self.get_async(f"/processes/{pid}")
543
+
544
+ def get_process(self, pid: str):
545
+ return self.get(f"/processes/{pid}")
546
+
547
+ async def kill_process_async(self, pid: str):
548
+ return await self.delete_async(f"/processes/{pid}")
549
+
550
+ def kill_process(self, pid: str):
551
+ return self.delete(f"/processes/{pid}")