agentrun-sdk 0.0.4__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 (128) hide show
  1. agentrun/__init__.py +209 -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 +97 -0
  31. agentrun/integration/builtin/sandbox.py +276 -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 +27 -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 +43 -0
  43. agentrun/integration/google_adk/tool_adapter.py +25 -0
  44. agentrun/integration/langchain/__init__.py +9 -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 +13 -0
  51. agentrun/integration/langgraph/adapter.py +20 -0
  52. agentrun/integration/langgraph/builtin.py +65 -0
  53. agentrun/integration/pydantic_ai/__init__.py +12 -0
  54. agentrun/integration/pydantic_ai/adapter.py +13 -0
  55. agentrun/integration/pydantic_ai/builtin.py +65 -0
  56. agentrun/integration/pydantic_ai/model_adapter.py +44 -0
  57. agentrun/integration/pydantic_ai/tool_adapter.py +19 -0
  58. agentrun/integration/utils/__init__.py +112 -0
  59. agentrun/integration/utils/adapter.py +167 -0
  60. agentrun/integration/utils/canonical.py +157 -0
  61. agentrun/integration/utils/converter.py +134 -0
  62. agentrun/integration/utils/model.py +107 -0
  63. agentrun/integration/utils/tool.py +1714 -0
  64. agentrun/model/__client_async_template.py +357 -0
  65. agentrun/model/__init__.py +57 -0
  66. agentrun/model/__model_proxy_async_template.py +270 -0
  67. agentrun/model/__model_service_async_template.py +267 -0
  68. agentrun/model/api/__init__.py +6 -0
  69. agentrun/model/api/control.py +1173 -0
  70. agentrun/model/api/data.py +196 -0
  71. agentrun/model/client.py +674 -0
  72. agentrun/model/model.py +218 -0
  73. agentrun/model/model_proxy.py +439 -0
  74. agentrun/model/model_service.py +438 -0
  75. agentrun/sandbox/__browser_sandbox_async_template.py +113 -0
  76. agentrun/sandbox/__client_async_template.py +466 -0
  77. agentrun/sandbox/__code_interpreter_sandbox_async_template.py +466 -0
  78. agentrun/sandbox/__init__.py +54 -0
  79. agentrun/sandbox/__sandbox_async_template.py +398 -0
  80. agentrun/sandbox/__template_async_template.py +150 -0
  81. agentrun/sandbox/api/__browser_data_async_template.py +140 -0
  82. agentrun/sandbox/api/__code_interpreter_data_async_template.py +206 -0
  83. agentrun/sandbox/api/__init__.py +17 -0
  84. agentrun/sandbox/api/__sandbox_data_async_template.py +100 -0
  85. agentrun/sandbox/api/browser_data.py +172 -0
  86. agentrun/sandbox/api/code_interpreter_data.py +396 -0
  87. agentrun/sandbox/api/control.py +1051 -0
  88. agentrun/sandbox/api/playwright_async.py +492 -0
  89. agentrun/sandbox/api/playwright_sync.py +492 -0
  90. agentrun/sandbox/api/sandbox_data.py +140 -0
  91. agentrun/sandbox/browser_sandbox.py +191 -0
  92. agentrun/sandbox/client.py +878 -0
  93. agentrun/sandbox/code_interpreter_sandbox.py +829 -0
  94. agentrun/sandbox/model.py +269 -0
  95. agentrun/sandbox/sandbox.py +737 -0
  96. agentrun/sandbox/template.py +215 -0
  97. agentrun/server/__init__.py +82 -0
  98. agentrun/server/invoker.py +131 -0
  99. agentrun/server/model.py +225 -0
  100. agentrun/server/openai_protocol.py +798 -0
  101. agentrun/server/protocol.py +96 -0
  102. agentrun/server/server.py +192 -0
  103. agentrun/toolset/__client_async_template.py +62 -0
  104. agentrun/toolset/__init__.py +51 -0
  105. agentrun/toolset/__toolset_async_template.py +204 -0
  106. agentrun/toolset/api/__init__.py +17 -0
  107. agentrun/toolset/api/control.py +262 -0
  108. agentrun/toolset/api/mcp.py +100 -0
  109. agentrun/toolset/api/openapi.py +1184 -0
  110. agentrun/toolset/client.py +102 -0
  111. agentrun/toolset/model.py +160 -0
  112. agentrun/toolset/toolset.py +271 -0
  113. agentrun/utils/__data_api_async_template.py +715 -0
  114. agentrun/utils/__init__.py +5 -0
  115. agentrun/utils/__resource_async_template.py +158 -0
  116. agentrun/utils/config.py +258 -0
  117. agentrun/utils/control_api.py +78 -0
  118. agentrun/utils/data_api.py +1110 -0
  119. agentrun/utils/exception.py +149 -0
  120. agentrun/utils/helper.py +34 -0
  121. agentrun/utils/log.py +77 -0
  122. agentrun/utils/model.py +168 -0
  123. agentrun/utils/resource.py +291 -0
  124. agentrun_sdk-0.0.4.dist-info/METADATA +262 -0
  125. agentrun_sdk-0.0.4.dist-info/RECORD +128 -0
  126. agentrun_sdk-0.0.4.dist-info/WHEEL +5 -0
  127. agentrun_sdk-0.0.4.dist-info/licenses/LICENSE +201 -0
  128. agentrun_sdk-0.0.4.dist-info/top_level.txt +1 -0
@@ -0,0 +1,737 @@
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/__sandbox_async_template.py
10
+
11
+ Sandbox 高层 API / Sandbox High-Level API
12
+
13
+ 此模块定义沙箱资源的高级API。
14
+ This module defines the high-level API for sandbox resources.
15
+ """
16
+
17
+ from typing import List, Literal, Optional, overload, TYPE_CHECKING, Union
18
+
19
+ from agentrun.sandbox.model import TemplateType
20
+ from agentrun.utils.config import Config
21
+ from agentrun.utils.model import BaseModel
22
+
23
+ if TYPE_CHECKING:
24
+ from agentrun.sandbox.browser_sandbox import BrowserSandbox
25
+ from agentrun.sandbox.code_interpreter_sandbox import CodeInterpreterSandbox
26
+ from agentrun.sandbox.model import (
27
+ ListSandboxesInput,
28
+ ListSandboxesOutput,
29
+ PageableInput,
30
+ TemplateInput,
31
+ )
32
+ from agentrun.sandbox.template import Template
33
+
34
+
35
+ class Sandbox(BaseModel):
36
+ """Sandbox 实例
37
+
38
+ 封装了 Sandbox 的基本信息和操作方法
39
+ """
40
+
41
+ _template_type: Optional[TemplateType]
42
+
43
+ created_at: Optional[str] = None
44
+ """沙箱创建时间"""
45
+ last_updated_at: Optional[str] = None
46
+ """最后更新时间"""
47
+ sandbox_arn: Optional[str] = None
48
+ """沙箱全局唯一资源名称"""
49
+ sandbox_id: Optional[str] = None
50
+ """沙箱 ID"""
51
+ sandbox_idle_timeout_seconds: Optional[int] = None
52
+ """沙箱空闲超时时间(秒)"""
53
+ status: Optional[str] = None
54
+ """沙箱状态"""
55
+ template_id: Optional[str] = None
56
+ """模板 ID"""
57
+ template_name: Optional[str] = None
58
+ """模板名称"""
59
+ _config: Optional[Config] = None
60
+ """配置对象,用于子类的 data_api 初始化"""
61
+
62
+ @classmethod
63
+ def __get_client(cls):
64
+ """获取 Sandbox 客户端"""
65
+ from .client import SandboxClient
66
+
67
+ return SandboxClient()
68
+
69
+ @classmethod
70
+ @overload
71
+ async def create_async(
72
+ cls,
73
+ template_type: Literal[TemplateType.CODE_INTERPRETER],
74
+ template_name: Optional[str] = None,
75
+ sandbox_idle_timeout_seconds: Optional[int] = 600,
76
+ config: Optional[Config] = None,
77
+ ) -> "CodeInterpreterSandbox":
78
+ ...
79
+
80
+ @classmethod
81
+ @overload
82
+ def create(
83
+ cls,
84
+ template_type: Literal[TemplateType.CODE_INTERPRETER],
85
+ template_name: Optional[str] = None,
86
+ sandbox_idle_timeout_seconds: Optional[int] = 600,
87
+ config: Optional[Config] = None,
88
+ ) -> "CodeInterpreterSandbox":
89
+ ...
90
+
91
+ @classmethod
92
+ @overload
93
+ async def create_async(
94
+ cls,
95
+ template_type: Literal[TemplateType.BROWSER],
96
+ template_name: Optional[str] = None,
97
+ sandbox_idle_timeout_seconds: Optional[int] = 600,
98
+ config: Optional[Config] = None,
99
+ ) -> "BrowserSandbox":
100
+ ...
101
+
102
+ @classmethod
103
+ @overload
104
+ def create(
105
+ cls,
106
+ template_type: Literal[TemplateType.BROWSER],
107
+ template_name: Optional[str] = None,
108
+ sandbox_idle_timeout_seconds: Optional[int] = 600,
109
+ config: Optional[Config] = None,
110
+ ) -> "BrowserSandbox":
111
+ ...
112
+
113
+ @classmethod
114
+ async def create_async(
115
+ cls,
116
+ template_type: TemplateType,
117
+ template_name: Optional[str] = None,
118
+ sandbox_idle_timeout_seconds: Optional[int] = 600,
119
+ config: Optional[Config] = None,
120
+ ) -> Union["CodeInterpreterSandbox", "BrowserSandbox"]:
121
+
122
+ if template_name is None:
123
+ # todo 可以考虑为用户创建一个模板?
124
+ raise ValueError("template_name is required")
125
+
126
+ # 先根据传入的template_name,获取template的类型
127
+ template = await cls.get_template_async(template_name, config=config)
128
+
129
+ # 根据 template 类型创建相应的 Sandbox 子类
130
+ from agentrun.sandbox.browser_sandbox import BrowserSandbox
131
+ from agentrun.sandbox.code_interpreter_sandbox import (
132
+ CodeInterpreterSandbox,
133
+ )
134
+
135
+ if template_type != template.template_type:
136
+ raise ValueError(
137
+ f"template_type of {template_name} is {template.template_type},"
138
+ f" not {template_type}"
139
+ )
140
+
141
+ # 创建 Sandbox(返回基类实例)
142
+ base_sandbox = await cls.__get_client().create_sandbox_async(
143
+ template_name=template_name,
144
+ sandbox_idle_timeout_seconds=sandbox_idle_timeout_seconds,
145
+ )
146
+
147
+ # 根据 template 类型转换为对应的子类实例
148
+ sandbox = None
149
+ if template.template_type == TemplateType.CODE_INTERPRETER:
150
+ sandbox = CodeInterpreterSandbox.model_validate(
151
+ base_sandbox.model_dump(by_alias=False)
152
+ )
153
+ elif template.template_type == TemplateType.BROWSER:
154
+ sandbox = BrowserSandbox.model_validate(
155
+ base_sandbox.model_dump(by_alias=False)
156
+ )
157
+ else:
158
+ raise ValueError(
159
+ f"template_type {template.template_type} is not supported"
160
+ )
161
+
162
+ sandbox._config = config
163
+ return sandbox
164
+
165
+ @classmethod
166
+ def create(
167
+ cls,
168
+ template_type: TemplateType,
169
+ template_name: Optional[str] = None,
170
+ sandbox_idle_timeout_seconds: Optional[int] = 600,
171
+ config: Optional[Config] = None,
172
+ ) -> Union["CodeInterpreterSandbox", "BrowserSandbox"]:
173
+
174
+ if template_name is None:
175
+ # todo 可以考虑为用户创建一个模板?
176
+ raise ValueError("template_name is required")
177
+
178
+ # 先根据传入的template_name,获取template的类型
179
+ template = cls.get_template(template_name, config=config)
180
+
181
+ # 根据 template 类型创建相应的 Sandbox 子类
182
+ from agentrun.sandbox.browser_sandbox import BrowserSandbox
183
+ from agentrun.sandbox.code_interpreter_sandbox import (
184
+ CodeInterpreterSandbox,
185
+ )
186
+
187
+ if template_type != template.template_type:
188
+ raise ValueError(
189
+ f"template_type of {template_name} is {template.template_type},"
190
+ f" not {template_type}"
191
+ )
192
+
193
+ # 创建 Sandbox(返回基类实例)
194
+ base_sandbox = cls.__get_client().create_sandbox(
195
+ template_name=template_name,
196
+ sandbox_idle_timeout_seconds=sandbox_idle_timeout_seconds,
197
+ )
198
+
199
+ # 根据 template 类型转换为对应的子类实例
200
+ sandbox = None
201
+ if template.template_type == TemplateType.CODE_INTERPRETER:
202
+ sandbox = CodeInterpreterSandbox.model_validate(
203
+ base_sandbox.model_dump(by_alias=False)
204
+ )
205
+ elif template.template_type == TemplateType.BROWSER:
206
+ sandbox = BrowserSandbox.model_validate(
207
+ base_sandbox.model_dump(by_alias=False)
208
+ )
209
+ else:
210
+ raise ValueError(
211
+ f"template_type {template.template_type} is not supported"
212
+ )
213
+
214
+ sandbox._config = config
215
+ return sandbox
216
+
217
+ @classmethod
218
+ async def stop_by_id_async(cls, sandbox_id: str):
219
+ """通过 ID 停止 Sandbox(异步)
220
+
221
+ Args:
222
+ sandbox_id: Sandbox ID
223
+ config: 配置对象
224
+
225
+ Returns:
226
+ Sandbox: Sandbox 对象
227
+ """
228
+ if sandbox_id is None:
229
+ raise ValueError("sandbox_id is required")
230
+ # todo 后续适配后使用 stop()
231
+ return await cls.__get_client().delete_sandbox_async(sandbox_id)
232
+
233
+ @classmethod
234
+ def stop_by_id(cls, sandbox_id: str):
235
+ """通过 ID 停止 Sandbox(同步)
236
+
237
+ Args:
238
+ sandbox_id: Sandbox ID
239
+ config: 配置对象
240
+
241
+ Returns:
242
+ Sandbox: Sandbox 对象
243
+ """
244
+ if sandbox_id is None:
245
+ raise ValueError("sandbox_id is required")
246
+ # todo 后续适配后使用 stop()
247
+ return cls.__get_client().delete_sandbox(sandbox_id)
248
+
249
+ @classmethod
250
+ async def delete_by_id_async(cls, sandbox_id: str):
251
+ """通过 ID 删除 Sandbox(异步)
252
+
253
+ Args:
254
+ sandbox_id: Sandbox ID
255
+ config: 配置对象
256
+
257
+ Returns:
258
+ Sandbox: Sandbox 对象
259
+ """
260
+ if sandbox_id is None:
261
+ raise ValueError("sandbox_id is required")
262
+ return await cls.__get_client().delete_sandbox_async(sandbox_id)
263
+
264
+ @classmethod
265
+ def delete_by_id(cls, sandbox_id: str):
266
+ """通过 ID 删除 Sandbox(同步)
267
+
268
+ Args:
269
+ sandbox_id: Sandbox ID
270
+ config: 配置对象
271
+
272
+ Returns:
273
+ Sandbox: Sandbox 对象
274
+ """
275
+ if sandbox_id is None:
276
+ raise ValueError("sandbox_id is required")
277
+ return cls.__get_client().delete_sandbox(sandbox_id)
278
+
279
+ @classmethod
280
+ async def list_async(
281
+ cls,
282
+ input: Optional["ListSandboxesInput"] = None,
283
+ config: Optional[Config] = None,
284
+ ) -> "ListSandboxesOutput":
285
+ """列出 Sandboxes(异步)
286
+
287
+ Args:
288
+ input: 列表查询配置
289
+ config: 配置对象
290
+
291
+ Returns:
292
+ ListSandboxesOutput: Sandbox 列表结果
293
+ """
294
+ return await cls.__get_client().list_sandboxes_async(input, config)
295
+
296
+ @classmethod
297
+ def list(
298
+ cls,
299
+ input: Optional["ListSandboxesInput"] = None,
300
+ config: Optional[Config] = None,
301
+ ) -> "ListSandboxesOutput":
302
+ """列出 Sandboxes(同步)
303
+
304
+ Args:
305
+ input: 列表查询配置
306
+ config: 配置对象
307
+
308
+ Returns:
309
+ ListSandboxesOutput: Sandbox 列表结果
310
+ """
311
+ return cls.__get_client().list_sandboxes(input, config)
312
+
313
+ @classmethod
314
+ @overload
315
+ async def connect_async(
316
+ cls,
317
+ sandbox_id: str,
318
+ template_type: Literal[TemplateType.CODE_INTERPRETER],
319
+ config: Optional[Config] = None,
320
+ ) -> "CodeInterpreterSandbox":
321
+ ...
322
+
323
+ @classmethod
324
+ @overload
325
+ def connect(
326
+ cls,
327
+ sandbox_id: str,
328
+ template_type: Literal[TemplateType.CODE_INTERPRETER],
329
+ config: Optional[Config] = None,
330
+ ) -> "CodeInterpreterSandbox":
331
+ ...
332
+
333
+ @classmethod
334
+ @overload
335
+ async def connect_async(
336
+ cls,
337
+ sandbox_id: str,
338
+ template_type: Literal[TemplateType.BROWSER],
339
+ config: Optional[Config] = None,
340
+ ) -> "BrowserSandbox":
341
+ ...
342
+
343
+ @classmethod
344
+ @overload
345
+ def connect(
346
+ cls,
347
+ sandbox_id: str,
348
+ template_type: Literal[TemplateType.BROWSER],
349
+ config: Optional[Config] = None,
350
+ ) -> "BrowserSandbox":
351
+ ...
352
+
353
+ @classmethod
354
+ @overload
355
+ async def connect_async(
356
+ cls,
357
+ sandbox_id: str,
358
+ template_type: None = None,
359
+ config: Optional[Config] = None,
360
+ ) -> Union["CodeInterpreterSandbox", "BrowserSandbox"]:
361
+ ...
362
+
363
+ @classmethod
364
+ @overload
365
+ def connect(
366
+ cls,
367
+ sandbox_id: str,
368
+ template_type: None = None,
369
+ config: Optional[Config] = None,
370
+ ) -> Union["CodeInterpreterSandbox", "BrowserSandbox"]:
371
+ ...
372
+
373
+ @classmethod
374
+ async def connect_async(
375
+ cls,
376
+ sandbox_id: str,
377
+ template_type: Optional[TemplateType] = None,
378
+ config: Optional[Config] = None,
379
+ ) -> Union["CodeInterpreterSandbox", "BrowserSandbox"]:
380
+ """连接一个SandBox(异步)
381
+
382
+ Args:
383
+ sandbox_id: Sandbox ID
384
+ type: 可选的类型参数,用于类型提示和运行时验证
385
+ config: 配置对象
386
+
387
+ Returns:
388
+ Sandbox: 根据模板类型返回对应的 Sandbox 子类对象
389
+
390
+ Raises:
391
+ ValueError: 如果模板类型不支持或与预期类型不匹配
392
+ """
393
+ if sandbox_id is None:
394
+ raise ValueError("sandbox_id is required")
395
+
396
+ # 先获取 sandbox 信息
397
+ sandbox = await cls.__get_client().get_sandbox_async(
398
+ sandbox_id, config=config
399
+ )
400
+
401
+ # 根据 template_name 获取 template 类型
402
+ if sandbox.template_name is None:
403
+ raise ValueError(f"Sandbox {sandbox_id} has no template_name")
404
+
405
+ template = await cls.get_template_async(
406
+ sandbox.template_name, config=config
407
+ )
408
+
409
+ # 如果提供了 type 参数,验证类型是否匹配
410
+ if (
411
+ template_type is not None
412
+ and template.template_type != template_type
413
+ ):
414
+ raise ValueError(
415
+ f"Sandbox {sandbox_id} has template type"
416
+ f" {template.template_type}, but expected {template_type}"
417
+ )
418
+
419
+ # 根据 template 类型创建相应的 Sandbox 子类
420
+ from agentrun.sandbox.browser_sandbox import BrowserSandbox
421
+ from agentrun.sandbox.code_interpreter_sandbox import (
422
+ CodeInterpreterSandbox,
423
+ )
424
+
425
+ result = None
426
+ if template.template_type == TemplateType.CODE_INTERPRETER:
427
+ result = CodeInterpreterSandbox.model_validate(
428
+ sandbox.model_dump(by_alias=False)
429
+ )
430
+ elif template.template_type == TemplateType.BROWSER:
431
+ result = BrowserSandbox.model_validate(
432
+ sandbox.model_dump(by_alias=False)
433
+ )
434
+ else:
435
+ raise ValueError(
436
+ f"Unsupported template type: {template.template_type}. "
437
+ "Expected 'code-interpreter' or 'browser'"
438
+ )
439
+
440
+ result._config = config
441
+ return result
442
+
443
+ # ==================== Template 相关类方法 ====================
444
+
445
+ @classmethod
446
+ def connect(
447
+ cls,
448
+ sandbox_id: str,
449
+ template_type: Optional[TemplateType] = None,
450
+ config: Optional[Config] = None,
451
+ ) -> Union["CodeInterpreterSandbox", "BrowserSandbox"]:
452
+ """连接一个SandBox(同步)
453
+
454
+ Args:
455
+ sandbox_id: Sandbox ID
456
+ type: 可选的类型参数,用于类型提示和运行时验证
457
+ config: 配置对象
458
+
459
+ Returns:
460
+ Sandbox: 根据模板类型返回对应的 Sandbox 子类对象
461
+
462
+ Raises:
463
+ ValueError: 如果模板类型不支持或与预期类型不匹配
464
+ """
465
+ if sandbox_id is None:
466
+ raise ValueError("sandbox_id is required")
467
+
468
+ # 先获取 sandbox 信息
469
+ sandbox = cls.__get_client().get_sandbox(sandbox_id, config=config)
470
+
471
+ # 根据 template_name 获取 template 类型
472
+ if sandbox.template_name is None:
473
+ raise ValueError(f"Sandbox {sandbox_id} has no template_name")
474
+
475
+ template = cls.get_template(sandbox.template_name, config=config)
476
+
477
+ # 如果提供了 type 参数,验证类型是否匹配
478
+ if (
479
+ template_type is not None
480
+ and template.template_type != template_type
481
+ ):
482
+ raise ValueError(
483
+ f"Sandbox {sandbox_id} has template type"
484
+ f" {template.template_type}, but expected {template_type}"
485
+ )
486
+
487
+ # 根据 template 类型创建相应的 Sandbox 子类
488
+ from agentrun.sandbox.browser_sandbox import BrowserSandbox
489
+ from agentrun.sandbox.code_interpreter_sandbox import (
490
+ CodeInterpreterSandbox,
491
+ )
492
+
493
+ result = None
494
+ if template.template_type == TemplateType.CODE_INTERPRETER:
495
+ result = CodeInterpreterSandbox.model_validate(
496
+ sandbox.model_dump(by_alias=False)
497
+ )
498
+ elif template.template_type == TemplateType.BROWSER:
499
+ result = BrowserSandbox.model_validate(
500
+ sandbox.model_dump(by_alias=False)
501
+ )
502
+ else:
503
+ raise ValueError(
504
+ f"Unsupported template type: {template.template_type}. "
505
+ "Expected 'code-interpreter' or 'browser'"
506
+ )
507
+
508
+ result._config = config
509
+ return result
510
+
511
+ # ==================== Template 相关类方法 ====================
512
+
513
+ @classmethod
514
+ async def create_template_async(
515
+ cls, input: "TemplateInput", config: Optional[Config] = None
516
+ ) -> "Template":
517
+ """创建 Template(异步)
518
+
519
+ Args:
520
+ input: Template 配置
521
+ config: 配置对象
522
+
523
+ Returns:
524
+ Template: 创建的 Template 对象
525
+ """
526
+ if input.template_type is None:
527
+ raise ValueError("template_type is required")
528
+ return await cls.__get_client().create_template_async(
529
+ input, config=config
530
+ )
531
+
532
+ @classmethod
533
+ def create_template(
534
+ cls, input: "TemplateInput", config: Optional[Config] = None
535
+ ) -> "Template":
536
+ """创建 Template(同步)
537
+
538
+ Args:
539
+ input: Template 配置
540
+ config: 配置对象
541
+
542
+ Returns:
543
+ Template: 创建的 Template 对象
544
+ """
545
+ if input.template_type is None:
546
+ raise ValueError("template_type is required")
547
+ return cls.__get_client().create_template(input, config=config)
548
+
549
+ @classmethod
550
+ async def get_template_async(
551
+ cls, template_name: str, config: Optional[Config] = None
552
+ ) -> "Template":
553
+ """获取 Template(异步)
554
+
555
+ Args:
556
+ template_name: Template 名称
557
+ config: 配置对象
558
+
559
+ Returns:
560
+ Template: Template 对象
561
+ """
562
+ if template_name is None:
563
+ raise ValueError("template_name is required")
564
+ return await cls.__get_client().get_template_async(
565
+ template_name, config=config
566
+ )
567
+
568
+ @classmethod
569
+ def get_template(
570
+ cls, template_name: str, config: Optional[Config] = None
571
+ ) -> "Template":
572
+ """获取 Template(同步)
573
+
574
+ Args:
575
+ template_name: Template 名称
576
+ config: 配置对象
577
+
578
+ Returns:
579
+ Template: Template 对象
580
+ """
581
+ if template_name is None:
582
+ raise ValueError("template_name is required")
583
+ return cls.__get_client().get_template(template_name, config=config)
584
+
585
+ @classmethod
586
+ async def update_template_async(
587
+ cls,
588
+ template_name: str,
589
+ input: "TemplateInput",
590
+ config: Optional[Config] = None,
591
+ ) -> "Template":
592
+ """更新 Template(异步)
593
+
594
+ Args:
595
+ template_name: Template 名称
596
+ input: Template 更新配置
597
+ config: 配置对象
598
+
599
+ Returns:
600
+ Template: 更新后的 Template 对象
601
+ """
602
+ if template_name is None:
603
+ raise ValueError("template_name is required")
604
+ return await cls.__get_client().update_template_async(
605
+ template_name, input, config=config
606
+ )
607
+
608
+ @classmethod
609
+ def update_template(
610
+ cls,
611
+ template_name: str,
612
+ input: "TemplateInput",
613
+ config: Optional[Config] = None,
614
+ ) -> "Template":
615
+ """更新 Template(同步)
616
+
617
+ Args:
618
+ template_name: Template 名称
619
+ input: Template 更新配置
620
+ config: 配置对象
621
+
622
+ Returns:
623
+ Template: 更新后的 Template 对象
624
+ """
625
+ if template_name is None:
626
+ raise ValueError("template_name is required")
627
+ return cls.__get_client().update_template(
628
+ template_name, input, config=config
629
+ )
630
+
631
+ @classmethod
632
+ async def delete_template_async(
633
+ cls, template_name: str, config: Optional[Config] = None
634
+ ) -> "Template":
635
+ """删除 Template(异步)
636
+
637
+ Args:
638
+ template_name: Template 名称
639
+ config: 配置对象
640
+
641
+ Returns:
642
+ Template: 删除的 Template 对象
643
+ """
644
+ if template_name is None:
645
+ raise ValueError("template_name is required")
646
+ return await cls.__get_client().delete_template_async(
647
+ template_name, config=config
648
+ )
649
+
650
+ @classmethod
651
+ def delete_template(
652
+ cls, template_name: str, config: Optional[Config] = None
653
+ ) -> "Template":
654
+ """删除 Template(同步)
655
+
656
+ Args:
657
+ template_name: Template 名称
658
+ config: 配置对象
659
+
660
+ Returns:
661
+ Template: 删除的 Template 对象
662
+ """
663
+ if template_name is None:
664
+ raise ValueError("template_name is required")
665
+ return cls.__get_client().delete_template(template_name, config=config)
666
+
667
+ @classmethod
668
+ async def list_templates_async(
669
+ cls,
670
+ input: Optional["PageableInput"] = None,
671
+ config: Optional[Config] = None,
672
+ ) -> List["Template"]:
673
+ """列出 Templates(异步)
674
+
675
+ Args:
676
+ input: 分页配置
677
+ config: 配置对象
678
+
679
+ Returns:
680
+ List[Template]: Template 列表
681
+ """
682
+ return await cls.__get_client().list_templates_async(
683
+ input, config=config
684
+ )
685
+
686
+ @classmethod
687
+ def list_templates(
688
+ cls,
689
+ input: Optional["PageableInput"] = None,
690
+ config: Optional[Config] = None,
691
+ ) -> List["Template"]:
692
+ """列出 Templates(同步)
693
+
694
+ Args:
695
+ input: 分页配置
696
+ config: 配置对象
697
+
698
+ Returns:
699
+ List[Template]: Template 列表
700
+ """
701
+ return cls.__get_client().list_templates(input, config=config)
702
+
703
+ async def get_async(self):
704
+ if self.sandbox_id is None:
705
+ raise ValueError("sandbox_id is required to get a Sandbox")
706
+
707
+ return await self.connect_async(self.sandbox_id)
708
+
709
+ def get(self):
710
+ if self.sandbox_id is None:
711
+ raise ValueError("sandbox_id is required to get a Sandbox")
712
+
713
+ return self.connect(self.sandbox_id)
714
+
715
+ async def delete_async(self):
716
+ if self.sandbox_id is None:
717
+ raise ValueError("sandbox_id is required to delete a Sandbox")
718
+
719
+ return await self.delete_by_id_async(self.sandbox_id)
720
+
721
+ def delete(self):
722
+ if self.sandbox_id is None:
723
+ raise ValueError("sandbox_id is required to delete a Sandbox")
724
+
725
+ return self.delete_by_id(self.sandbox_id)
726
+
727
+ async def stop_async(self):
728
+ if self.sandbox_id is None:
729
+ raise ValueError("sandbox_id is required to stop a Sandbox")
730
+ # todo 后续适配后使用 stop()
731
+ return await self.delete_by_id_async(self.sandbox_id)
732
+
733
+ def stop(self):
734
+ if self.sandbox_id is None:
735
+ raise ValueError("sandbox_id is required to stop a Sandbox")
736
+ # todo 后续适配后使用 stop()
737
+ return self.delete_by_id(self.sandbox_id)