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,823 @@
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/__code_interpreter_sandbox_async_template.py
10
+
11
+ 代码解释器沙箱高层API模板 / Code Interpreter Sandbox High-Level API Template
12
+
13
+ 此模板用于生成代码解释器沙箱资源的高级API代码。
14
+ This template is used to generate high-level API code for code interpreter sandbox resources.
15
+ """
16
+
17
+ import asyncio
18
+ import time
19
+ from typing import Optional
20
+
21
+ from agentrun.sandbox.api.code_interpreter_data import CodeInterpreterDataAPI
22
+ from agentrun.sandbox.model import CodeLanguage, TemplateType
23
+ from agentrun.utils.exception import ServerError
24
+ from agentrun.utils.log import logger
25
+
26
+ from .sandbox import Sandbox
27
+
28
+
29
+ class FileOperations:
30
+ """File upload/download operations."""
31
+
32
+ def __init__(self, sandbox: "CodeInterpreterSandbox"):
33
+ self._sandbox = sandbox
34
+
35
+ async def read_async(self, path: str):
36
+ """Read a file from the code interpreter (async).
37
+ Args:
38
+ path: Remote file path in the code interpreter
39
+ Returns:
40
+ File content
41
+ """
42
+ return await self._sandbox.data_api.read_file_async(path=path)
43
+
44
+ def read(self, path: str):
45
+ """Read a file from the code interpreter (async).
46
+ Args:
47
+ path: Remote file path in the code interpreter
48
+ Returns:
49
+ File content
50
+ """
51
+ return self._sandbox.data_api.read_file(path=path)
52
+
53
+ async def write_async(
54
+ self,
55
+ path: str,
56
+ content: str,
57
+ mode: str = "644",
58
+ encoding: str = "utf-8",
59
+ create_dir=True,
60
+ ):
61
+ """Write a file to the code interpreter (async).
62
+ Args:
63
+ path: Remote file path in the code interpreter
64
+ content: File content
65
+ """
66
+ return await self._sandbox.data_api.write_file_async(
67
+ path=path,
68
+ content=content,
69
+ mode=mode,
70
+ encoding=encoding,
71
+ create_dir=create_dir,
72
+ )
73
+
74
+ def write(
75
+ self,
76
+ path: str,
77
+ content: str,
78
+ mode: str = "644",
79
+ encoding: str = "utf-8",
80
+ create_dir=True,
81
+ ):
82
+ """Write a file to the code interpreter (async).
83
+ Args:
84
+ path: Remote file path in the code interpreter
85
+ content: File content
86
+ """
87
+ return self._sandbox.data_api.write_file(
88
+ path=path,
89
+ content=content,
90
+ mode=mode,
91
+ encoding=encoding,
92
+ create_dir=create_dir,
93
+ )
94
+
95
+
96
+ class FileSystemOperations:
97
+ """File system operations (list, move, remove, stat, mkdir)."""
98
+
99
+ def __init__(self, sandbox: "CodeInterpreterSandbox"):
100
+ self._sandbox = sandbox
101
+
102
+ async def list_async(
103
+ self, path: Optional[str] = None, depth: Optional[int] = None
104
+ ):
105
+ """List directory contents (async).
106
+
107
+ Args:
108
+ path: Directory path (optional)
109
+ depth: Traversal depth (optional)
110
+
111
+ Returns:
112
+ Directory contents
113
+ """
114
+ return await self._sandbox.data_api.list_directory_async(
115
+ path=path, depth=depth
116
+ )
117
+
118
+ def list(self, path: Optional[str] = None, depth: Optional[int] = None):
119
+ """List directory contents (async).
120
+
121
+ Args:
122
+ path: Directory path (optional)
123
+ depth: Traversal depth (optional)
124
+
125
+ Returns:
126
+ Directory contents
127
+ """
128
+ return self._sandbox.data_api.list_directory(path=path, depth=depth)
129
+
130
+ async def move_async(self, source: str, destination: str):
131
+ """Move a file or directory (async).
132
+
133
+ Args:
134
+ source: Source file or directory path
135
+ destination: Target file or directory path
136
+
137
+ Returns:
138
+ Move operation result
139
+ """
140
+ return await self._sandbox.data_api.move_file_async(
141
+ source=source, destination=destination
142
+ )
143
+
144
+ def move(self, source: str, destination: str):
145
+ """Move a file or directory (async).
146
+
147
+ Args:
148
+ source: Source file or directory path
149
+ destination: Target file or directory path
150
+
151
+ Returns:
152
+ Move operation result
153
+ """
154
+ return self._sandbox.data_api.move_file(
155
+ source=source, destination=destination
156
+ )
157
+
158
+ async def remove_async(self, path: str):
159
+ """Remove a file or directory (async).
160
+
161
+ Args:
162
+ path: File or directory path to remove
163
+
164
+ Returns:
165
+ Remove operation result
166
+ """
167
+ return await self._sandbox.data_api.remove_file_async(path=path)
168
+
169
+ def remove(self, path: str):
170
+ """Remove a file or directory (async).
171
+
172
+ Args:
173
+ path: File or directory path to remove
174
+
175
+ Returns:
176
+ Remove operation result
177
+ """
178
+ return self._sandbox.data_api.remove_file(path=path)
179
+
180
+ async def stat_async(self, path: str):
181
+ """Get file or directory statistics (async).
182
+
183
+ Args:
184
+ path: File or directory path
185
+
186
+ Returns:
187
+ File/directory statistics
188
+ """
189
+ return await self._sandbox.data_api.stat_async(path=path)
190
+
191
+ def stat(self, path: str):
192
+ """Get file or directory statistics (async).
193
+
194
+ Args:
195
+ path: File or directory path
196
+
197
+ Returns:
198
+ File/directory statistics
199
+ """
200
+ return self._sandbox.data_api.stat(path=path)
201
+
202
+ async def mkdir_async(
203
+ self,
204
+ path: str,
205
+ parents: Optional[bool] = True,
206
+ mode: Optional[str] = "0755",
207
+ ):
208
+ """Create a directory (async).
209
+
210
+ Args:
211
+ path: Directory path to create
212
+ parents: Whether to create parent directories (default: True)
213
+ mode: Directory permissions mode (default: "0755")
214
+
215
+ Returns:
216
+ Mkdir operation result
217
+ """
218
+ return await self._sandbox.data_api.mkdir_async(
219
+ path=path, parents=parents, mode=mode
220
+ )
221
+
222
+ def mkdir(
223
+ self,
224
+ path: str,
225
+ parents: Optional[bool] = True,
226
+ mode: Optional[str] = "0755",
227
+ ):
228
+ """Create a directory (async).
229
+
230
+ Args:
231
+ path: Directory path to create
232
+ parents: Whether to create parent directories (default: True)
233
+ mode: Directory permissions mode (default: "0755")
234
+
235
+ Returns:
236
+ Mkdir operation result
237
+ """
238
+ return self._sandbox.data_api.mkdir(
239
+ path=path, parents=parents, mode=mode
240
+ )
241
+
242
+ async def upload_async(
243
+ self,
244
+ local_file_path: str,
245
+ target_file_path: str,
246
+ ):
247
+ """Upload a file to the code interpreter (async).
248
+
249
+ Args:
250
+ local_file_path: Local file path to upload
251
+ target_file_path: Target file path in code interpreter
252
+
253
+ Returns:
254
+ Upload result
255
+ """
256
+ return await self._sandbox.data_api.upload_file_async(
257
+ local_file_path=local_file_path, target_file_path=target_file_path
258
+ )
259
+
260
+ def upload(
261
+ self,
262
+ local_file_path: str,
263
+ target_file_path: str,
264
+ ):
265
+ """Upload a file to the code interpreter (async).
266
+
267
+ Args:
268
+ local_file_path: Local file path to upload
269
+ target_file_path: Target file path in code interpreter
270
+
271
+ Returns:
272
+ Upload result
273
+ """
274
+ return self._sandbox.data_api.upload_file(
275
+ local_file_path=local_file_path, target_file_path=target_file_path
276
+ )
277
+
278
+ async def download_async(self, path: str, save_path: str):
279
+ """Download a file from the code interpreter (async).
280
+
281
+ Args:
282
+ path: Remote file path in the code interpreter
283
+ save_path: Local file path to save the downloaded file
284
+
285
+ Returns:
286
+ Download result with 'saved_path' and 'size'
287
+ """
288
+ return await self._sandbox.data_api.download_file_async(
289
+ path=path, save_path=save_path
290
+ )
291
+
292
+ def download(self, path: str, save_path: str):
293
+ """Download a file from the code interpreter (async).
294
+
295
+ Args:
296
+ path: Remote file path in the code interpreter
297
+ save_path: Local file path to save the downloaded file
298
+
299
+ Returns:
300
+ Download result with 'saved_path' and 'size'
301
+ """
302
+ return self._sandbox.data_api.download_file(
303
+ path=path, save_path=save_path
304
+ )
305
+
306
+
307
+ class ProcessOperations:
308
+ """Process management operations."""
309
+
310
+ def __init__(self, sandbox: "CodeInterpreterSandbox"):
311
+ self._sandbox = sandbox
312
+
313
+ async def cmd_async(
314
+ self, command: str, cwd: str, timeout: Optional[int] = 30
315
+ ):
316
+ """Execute a command in the code interpreter (async).
317
+
318
+ Args:
319
+ command: Command to execute
320
+ cwd: Working directory
321
+ timeout: Execution timeout in seconds (default: 30)
322
+
323
+ Returns:
324
+ Command execution result
325
+ """
326
+ return await self._sandbox.data_api.cmd_async(
327
+ command=command, cwd=cwd, timeout=timeout
328
+ )
329
+
330
+ def cmd(self, command: str, cwd: str, timeout: Optional[int] = 30):
331
+ """Execute a command in the code interpreter (async).
332
+
333
+ Args:
334
+ command: Command to execute
335
+ cwd: Working directory
336
+ timeout: Execution timeout in seconds (default: 30)
337
+
338
+ Returns:
339
+ Command execution result
340
+ """
341
+ return self._sandbox.data_api.cmd(
342
+ command=command, cwd=cwd, timeout=timeout
343
+ )
344
+
345
+ async def list_async(self):
346
+ """List all processes (async).
347
+
348
+ Returns:
349
+ List of processes
350
+ """
351
+ return await self._sandbox.data_api.list_processes_async()
352
+
353
+ def list(self):
354
+ """List all processes (async).
355
+
356
+ Returns:
357
+ List of processes
358
+ """
359
+ return self._sandbox.data_api.list_processes()
360
+
361
+ async def get_async(self, pid: str):
362
+ """Get a specific process by PID (async).
363
+
364
+ Args:
365
+ pid: Process ID
366
+
367
+ Returns:
368
+ Process information
369
+ """
370
+ return await self._sandbox.data_api.get_process_async(pid=pid)
371
+
372
+ def get(self, pid: str):
373
+ """Get a specific process by PID (async).
374
+
375
+ Args:
376
+ pid: Process ID
377
+
378
+ Returns:
379
+ Process information
380
+ """
381
+ return self._sandbox.data_api.get_process(pid=pid)
382
+
383
+ async def kill_async(self, pid: str):
384
+ """Kill a specific process by PID (async).
385
+
386
+ Args:
387
+ pid: Process ID
388
+
389
+ Returns:
390
+ Kill operation result
391
+ """
392
+ return await self._sandbox.data_api.kill_process_async(pid=pid)
393
+
394
+ def kill(self, pid: str):
395
+ """Kill a specific process by PID (async).
396
+
397
+ Args:
398
+ pid: Process ID
399
+
400
+ Returns:
401
+ Kill operation result
402
+ """
403
+ return self._sandbox.data_api.kill_process(pid=pid)
404
+
405
+
406
+ class ContextOperations:
407
+ """Context management operations."""
408
+
409
+ def __init__(self, sandbox: "CodeInterpreterSandbox"):
410
+ self._sandbox = sandbox
411
+ self._context_id: Optional[str] = None
412
+ self._language: Optional[str] = None
413
+ self._cwd: Optional[str] = None
414
+
415
+ @property
416
+ def context_id(self) -> Optional[str]:
417
+ """Get the current context ID."""
418
+ return self._context_id
419
+
420
+ async def list_async(self):
421
+ """List all contexts (async)."""
422
+ return await self._sandbox.data_api.list_contexts_async()
423
+
424
+ def list(self):
425
+ """List all contexts (async)."""
426
+ return self._sandbox.data_api.list_contexts()
427
+
428
+ async def create_async(
429
+ self,
430
+ language: Optional[CodeLanguage] = CodeLanguage.PYTHON,
431
+ cwd: str = "/home/user",
432
+ ) -> "ContextOperations":
433
+ """Create a new context and save its ID (async).
434
+
435
+ Args:
436
+ name: Context name
437
+ language: Programming language (default: "python")
438
+ config: Context configuration (optional)
439
+
440
+ Returns:
441
+ ContextOperations: Returns self for chaining and context manager support
442
+ """
443
+ result = await self._sandbox.data_api.create_context_async(
444
+ language=language, cwd=cwd
445
+ )
446
+ if all(result.get(key) for key in ("id", "cwd", "language")):
447
+ self._context_id = result["id"]
448
+ self._language = result["language"]
449
+ self._cwd = result["cwd"]
450
+ return self
451
+ raise ServerError(500, "Failed to create context")
452
+
453
+ def create(
454
+ self,
455
+ language: Optional[CodeLanguage] = CodeLanguage.PYTHON,
456
+ cwd: str = "/home/user",
457
+ ) -> "ContextOperations":
458
+ """Create a new context and save its ID (async).
459
+
460
+ Args:
461
+ name: Context name
462
+ language: Programming language (default: "python")
463
+ config: Context configuration (optional)
464
+
465
+ Returns:
466
+ ContextOperations: Returns self for chaining and context manager support
467
+ """
468
+ result = self._sandbox.data_api.create_context(
469
+ language=language, cwd=cwd
470
+ )
471
+ if all(result.get(key) for key in ("id", "cwd", "language")):
472
+ self._context_id = result["id"]
473
+ self._language = result["language"]
474
+ self._cwd = result["cwd"]
475
+ return self
476
+ raise ServerError(500, "Failed to create context")
477
+
478
+ async def get_async(
479
+ self, context_id: Optional[str] = None
480
+ ) -> "ContextOperations":
481
+ """Get a specific context by ID (async).
482
+ Args:
483
+ context_id: Context ID
484
+ Returns:
485
+ ContextOperations: Returns self for chaining and context manager support
486
+ """
487
+ if context_id is None:
488
+ context_id = self._context_id
489
+ if context_id is None:
490
+ logger.error(f"context id is not set")
491
+ raise ValueError("context id is not set,")
492
+ result = await self._sandbox.data_api.get_context_async(
493
+ context_id=context_id
494
+ )
495
+ if all(result.get(key) for key in ("id", "cwd", "language")):
496
+ self._context_id = result["id"]
497
+ self._language = result["language"]
498
+ self._cwd = result["cwd"]
499
+ return self
500
+ raise ServerError(500, "Failed to create context")
501
+
502
+ def get(self, context_id: Optional[str] = None) -> "ContextOperations":
503
+ """Get a specific context by ID (async).
504
+ Args:
505
+ context_id: Context ID
506
+ Returns:
507
+ ContextOperations: Returns self for chaining and context manager support
508
+ """
509
+ if context_id is None:
510
+ context_id = self._context_id
511
+ if context_id is None:
512
+ logger.error(f"context id is not set")
513
+ raise ValueError("context id is not set,")
514
+ result = self._sandbox.data_api.get_context(context_id=context_id)
515
+ if all(result.get(key) for key in ("id", "cwd", "language")):
516
+ self._context_id = result["id"]
517
+ self._language = result["language"]
518
+ self._cwd = result["cwd"]
519
+ return self
520
+ raise ServerError(500, "Failed to create context")
521
+
522
+ async def execute_async(
523
+ self,
524
+ code: str,
525
+ language: Optional[CodeLanguage] = None,
526
+ context_id: Optional[str] = None,
527
+ timeout: Optional[int] = 30,
528
+ ):
529
+ """Execute code in a context (async).
530
+
531
+ Args:
532
+ code: Code to execute
533
+ context_id: Context ID (optional, uses saved context_id if not provided)
534
+ timeout: Execution timeout in seconds (default: 30)
535
+
536
+ Returns:
537
+ Execution result
538
+
539
+ Raises:
540
+ ValueError: If no context_id is provided and none is saved
541
+ """
542
+ if context_id is None:
543
+ context_id = self._context_id
544
+ if context_id is None and language is None:
545
+ logger.debug("context id is not set, use default language: python")
546
+ language = CodeLanguage.PYTHON
547
+ return await self._sandbox.data_api.execute_code_async(
548
+ context_id=context_id, language=language, code=code, timeout=timeout
549
+ )
550
+
551
+ def execute(
552
+ self,
553
+ code: str,
554
+ language: Optional[CodeLanguage] = None,
555
+ context_id: Optional[str] = None,
556
+ timeout: Optional[int] = 30,
557
+ ):
558
+ """Execute code in a context (async).
559
+
560
+ Args:
561
+ code: Code to execute
562
+ context_id: Context ID (optional, uses saved context_id if not provided)
563
+ timeout: Execution timeout in seconds (default: 30)
564
+
565
+ Returns:
566
+ Execution result
567
+
568
+ Raises:
569
+ ValueError: If no context_id is provided and none is saved
570
+ """
571
+ if context_id is None:
572
+ context_id = self._context_id
573
+ if context_id is None and language is None:
574
+ logger.debug("context id is not set, use default language: python")
575
+ language = CodeLanguage.PYTHON
576
+ return self._sandbox.data_api.execute_code(
577
+ context_id=context_id, language=language, code=code, timeout=timeout
578
+ )
579
+
580
+ async def delete_async(self, context_id: Optional[str] = None):
581
+ """Delete a context (async).
582
+
583
+ Args:
584
+ context_id: Context ID (optional, uses saved context_id if not provided)
585
+
586
+ Returns:
587
+ Delete result
588
+
589
+ Raises:
590
+ ValueError: If no context_id is provided and none is saved
591
+ """
592
+ if context_id is None:
593
+ context_id = self._context_id
594
+ if context_id is None:
595
+ raise ValueError(
596
+ "context_id is required. Either pass it as parameter or create"
597
+ " a context first."
598
+ )
599
+ result = await self._sandbox.data_api.delete_context_async(
600
+ context_id=context_id
601
+ )
602
+ # Clear the saved context_id after deletion
603
+ self._context_id = None
604
+ return result
605
+
606
+ def delete(self, context_id: Optional[str] = None):
607
+ """Delete a context (async).
608
+
609
+ Args:
610
+ context_id: Context ID (optional, uses saved context_id if not provided)
611
+
612
+ Returns:
613
+ Delete result
614
+
615
+ Raises:
616
+ ValueError: If no context_id is provided and none is saved
617
+ """
618
+ if context_id is None:
619
+ context_id = self._context_id
620
+ if context_id is None:
621
+ raise ValueError(
622
+ "context_id is required. Either pass it as parameter or create"
623
+ " a context first."
624
+ )
625
+ result = self._sandbox.data_api.delete_context(context_id=context_id)
626
+ # Clear the saved context_id after deletion
627
+ self._context_id = None
628
+ return result
629
+
630
+ async def __aenter__(self):
631
+ """Asynchronous context manager entry."""
632
+ if self._context_id is None:
633
+ raise ValueError(
634
+ "No context has been created. Call create() first or use: "
635
+ "async with await sandbox.context.create_async(...) as ctx:"
636
+ )
637
+ return self
638
+
639
+ def __enter__(self):
640
+ """Synchronous context manager entry."""
641
+ if self._context_id is None:
642
+ raise ValueError(
643
+ "No context has been created. Call create() first or use: "
644
+ "with sandbox.context.create(...) as ctx:"
645
+ )
646
+ return self
647
+
648
+ async def __aexit__(self, exc_type, exc_val, exc_tb):
649
+ """Asynchronous context manager exit - deletes the context."""
650
+ if self._context_id is not None:
651
+ try:
652
+ await self._sandbox.data_api.delete_context_async(
653
+ self._context_id
654
+ )
655
+ except Exception as e:
656
+ logger.error(
657
+ f"Warning: Failed to delete context {self._context_id}: {e}"
658
+ )
659
+ return False
660
+
661
+ def __exit__(self, exc_type, exc_val, exc_tb):
662
+ """Synchronous context manager exit - deletes the context."""
663
+ if self._context_id is not None:
664
+ try:
665
+ self._sandbox.data_api.delete_context(self._context_id)
666
+ except Exception as e:
667
+ logger.error(
668
+ f"Warning: Failed to delete context {self._context_id}: {e}"
669
+ )
670
+ return False
671
+
672
+
673
+ class CodeInterpreterSandbox(Sandbox):
674
+ _template_type = TemplateType.CODE_INTERPRETER
675
+
676
+ _data_api: Optional["CodeInterpreterDataAPI"] = None
677
+ _file: Optional[FileOperations] = None
678
+ _file_system: Optional[FileSystemOperations] = None
679
+ _context: Optional[ContextOperations] = None
680
+ _process: Optional[ProcessOperations] = None
681
+
682
+ @property
683
+ def data_api(self) -> "CodeInterpreterDataAPI":
684
+ """Get data client."""
685
+ if self._data_api is None:
686
+ self._data_api = CodeInterpreterDataAPI(
687
+ sandbox_id=self.sandbox_id or "", config=self._config
688
+ )
689
+ return self._data_api
690
+
691
+ @property
692
+ def file(self) -> FileOperations:
693
+ """Access file upload/download operations."""
694
+ if self._file is None:
695
+ self._file = FileOperations(self)
696
+ return self._file
697
+
698
+ @property
699
+ def file_system(self) -> FileSystemOperations:
700
+ """Access file system operations."""
701
+ if self._file_system is None:
702
+ self._file_system = FileSystemOperations(self)
703
+ return self._file_system
704
+
705
+ @property
706
+ def context(self) -> ContextOperations:
707
+ """Access context management operations."""
708
+ if self._context is None:
709
+ self._context = ContextOperations(self)
710
+ return self._context
711
+
712
+ @property
713
+ def process(self) -> ProcessOperations:
714
+ """Access process management operations."""
715
+ if self._process is None:
716
+ self._process = ProcessOperations(self)
717
+ return self._process
718
+
719
+ async def check_health_async(self):
720
+ return await self.data_api.check_health_async()
721
+
722
+ def check_health(self):
723
+ return self.data_api.check_health()
724
+
725
+ async def __aenter__(self):
726
+ """Asynchronous context manager entry."""
727
+ # Poll health check asynchronously
728
+ max_retries = 60 # Maximum 60 seconds
729
+ retry_count = 0
730
+
731
+ logger.debug("Waiting for code interpreter to be ready...")
732
+
733
+ while retry_count < max_retries:
734
+ retry_count += 1
735
+
736
+ try:
737
+ health = await self.check_health_async()
738
+
739
+ if health["status"] == "ok":
740
+ logger.debug(
741
+ "Code Interpreter is ready! (took"
742
+ f" {retry_count} seconds)"
743
+ )
744
+ return self
745
+
746
+ logger.debug(
747
+ f"[{retry_count}/{max_retries}] Health status: not ready"
748
+ )
749
+
750
+ logger.debug(
751
+ f"[{retry_count}/{max_retries}] Health status:"
752
+ f" {health.get('code')} { health.get('message')}",
753
+ )
754
+
755
+ except Exception as e:
756
+ logger.error(
757
+ f"[{retry_count}/{max_retries}] Health check failed: {e}"
758
+ )
759
+
760
+ if retry_count < max_retries:
761
+ await asyncio.sleep(1)
762
+
763
+ raise RuntimeError(
764
+ f"Health check timeout after {max_retries} seconds. "
765
+ "Code interpreter did not become ready in time."
766
+ )
767
+
768
+ def __enter__(self):
769
+ """Synchronous context manager entry."""
770
+ # Poll health check asynchronously
771
+ max_retries = 60 # Maximum 60 seconds
772
+ retry_count = 0
773
+
774
+ logger.debug("Waiting for code interpreter to be ready...")
775
+
776
+ while retry_count < max_retries:
777
+ retry_count += 1
778
+
779
+ try:
780
+ health = self.check_health()
781
+
782
+ if health["status"] == "ok":
783
+ logger.debug(
784
+ "Code Interpreter is ready! (took"
785
+ f" {retry_count} seconds)"
786
+ )
787
+ return self
788
+
789
+ logger.debug(
790
+ f"[{retry_count}/{max_retries}] Health status: not ready"
791
+ )
792
+
793
+ logger.debug(
794
+ f"[{retry_count}/{max_retries}] Health status:"
795
+ f" {health.get('code')} { health.get('message')}",
796
+ )
797
+
798
+ except Exception as e:
799
+ logger.error(
800
+ f"[{retry_count}/{max_retries}] Health check failed: {e}"
801
+ )
802
+
803
+ if retry_count < max_retries:
804
+ time.sleep(1)
805
+
806
+ raise RuntimeError(
807
+ f"Health check timeout after {max_retries} seconds. "
808
+ "Code interpreter did not become ready in time."
809
+ )
810
+
811
+ async def __aexit__(self, exc_type, exc_val, exc_tb):
812
+ """Asynchronous context manager exit."""
813
+ if self.sandbox_id is None:
814
+ raise ValueError("Sandbox ID is not set")
815
+ logger.debug(f"Deleting code interpreter sandbox {self.sandbox_id}...")
816
+ await self.delete_async()
817
+
818
+ def __exit__(self, exc_type, exc_val, exc_tb):
819
+ """Synchronous context manager exit."""
820
+ if self.sandbox_id is None:
821
+ raise ValueError("Sandbox ID is not set")
822
+ logger.debug(f"Deleting code interpreter sandbox {self.sandbox_id}...")
823
+ self.delete()