Skip to content

Commit c0e7489

Browse files
authored
Merge pull request #28 from Serverless-Devs/feat-dynamic-mount
feat(sandbox): add NAS, OSS, and PolarFS configuration support with m…
2 parents 6ae8e64 + 309a59b commit c0e7489

22 files changed

+465
-132
lines changed

AGENTS.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,3 +447,27 @@ A: 建议:
447447
- [Python SDK 文档](./python/README.md)
448448
- [示例代码](./python/examples/)
449449
- [阿里云 AgentRun 官方文档](https://help.aliyun.com/zh/agentrun/)
450+
451+
## 工作流程
452+
453+
### 为特定模块增加参数
454+
455+
名词解释
456+
- AgentRun SDK:当前项目
457+
- 底层 SDK:我们会依赖底层 SDK 与平台进行交互,如果是 python sdk,则为 `agentrun-20250910`;如果是 nodejs sdk,则为 `@alicloud/agentrun20250910`
458+
- 要修改模块:sandbox、model 等
459+
460+
此时,应该遵循如下流程
461+
462+
该模块的代码位于 ${component} 目录,包含如下部分
463+
- api/ 和底层 SDK 交互的逻辑。你可以根据该文件的调用方式,跳转到底层 sdk 的逻辑,进行检查
464+
- client 为用户封装的客户端,你需要检查一下是否需要修改
465+
- model 相关类型描述,你需要严格检查当前文件是否需要修改,这里可能存在大量修改
466+
- 其他文件 你也需要一并检查,如果是 nodejs sdk,需要检查 class 的属性
467+
- _xxx_async_template.py python sdk 中生成 xxx.py 文件的模板,只需要声明 async 即可(使用 `make codegen` 进行生成)
468+
469+
1. 请严格检查底层 SDK 的输入、输出参数,并对照现有类型定义,整理出新增的参数列表
470+
2. 根据新增的参数列表,在 agentrun sdk 中进行修改,补充对应的中英文注释
471+
3. 执行相关模块的 ut 测试,确保可以正确执行
472+
4. 进行修改内容的总结汇报
473+
5. 根据汇报内容进行检查,重新检查底层 SDK 和 AgentRun SDK 的定义

agentrun/agent_runtime/api/control.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
)
3636
from alibabacloud_tea_openapi.exceptions._client import ClientException
3737
from alibabacloud_tea_openapi.exceptions._server import ServerException
38-
from alibabacloud_tea_util.models import RuntimeOptions
38+
from darabonba.runtime import RuntimeOptions
3939
import pydash
4040

4141
from agentrun.utils.config import Config

agentrun/credential/api/control.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
)
2626
from alibabacloud_tea_openapi.exceptions._client import ClientException
2727
from alibabacloud_tea_openapi.exceptions._server import ServerException
28-
from alibabacloud_tea_util.models import RuntimeOptions
28+
from darabonba.runtime import RuntimeOptions
2929
import pydash
3030

3131
from agentrun.utils.config import Config

agentrun/model/api/control.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
)
3333
from alibabacloud_tea_openapi.exceptions._client import ClientException
3434
from alibabacloud_tea_openapi.exceptions._server import ServerException
35-
from alibabacloud_tea_util.models import RuntimeOptions
35+
from darabonba.runtime import RuntimeOptions
3636
import pydash
3737

3838
from agentrun.utils.config import Config

agentrun/sandbox/__client_async_template.py

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"""
66

77
import time
8-
from typing import List, Optional, TYPE_CHECKING
8+
from typing import Any, Dict, List, Optional, TYPE_CHECKING
99

1010
from alibabacloud_agentrun20250910.models import (
1111
CreateTemplateInput,
@@ -18,7 +18,10 @@
1818
from agentrun.sandbox.model import (
1919
ListSandboxesInput,
2020
ListSandboxesOutput,
21+
NASConfig,
22+
OSSMountConfig,
2123
PageableInput,
24+
PolarFsConfig,
2225
TemplateInput,
2326
)
2427
from agentrun.utils.config import Config
@@ -273,25 +276,47 @@ async def create_sandbox_async(
273276
self,
274277
template_name: str,
275278
sandbox_idle_timeout_seconds: Optional[int] = 600,
279+
nas_config: Optional[NASConfig] = None,
280+
oss_mount_config: Optional[OSSMountConfig] = None,
281+
polar_fs_config: Optional[PolarFsConfig] = None,
276282
config: Optional[Config] = None,
277283
) -> Sandbox:
278-
"""创建 Sandbox(异步)
284+
"""创建 Sandbox(异步) / Create Sandbox (async)
279285
280286
Args:
281-
input: Sandbox 配置
282-
config: 配置对象
287+
template_name: 模板名称 / Template name
288+
sandbox_idle_timeout_seconds: 沙箱空闲超时时间(秒) / Sandbox idle timeout (seconds)
289+
nas_config: NAS 配置 / NAS configuration
290+
oss_mount_config: OSS 挂载配置 / OSS mount configuration
291+
polar_fs_config: PolarFS 配置 / PolarFS configuration
292+
config: 配置对象 / Config object
283293
284294
Returns:
285-
Sandbox: 创建的 Sandbox 对象
295+
Sandbox: 创建的 Sandbox 对象 / Created Sandbox object
286296
287297
Raises:
288-
ClientError: 客户端错误
289-
ServerError: 服务器错误
298+
ClientError: 客户端错误 / Client error
299+
ServerError: 服务器错误 / Server error
290300
"""
301+
# 将配置对象转换为字典格式
302+
nas_config_dict: Optional[Dict[str, Any]] = None
303+
if nas_config is not None:
304+
nas_config_dict = nas_config.model_dump(by_alias=True)
305+
306+
oss_mount_config_dict: Optional[Dict[str, Any]] = None
307+
if oss_mount_config is not None:
308+
oss_mount_config_dict = oss_mount_config.model_dump(by_alias=True)
309+
310+
polar_fs_config_dict: Optional[Dict[str, Any]] = None
311+
if polar_fs_config is not None:
312+
polar_fs_config_dict = polar_fs_config.model_dump(by_alias=True)
291313

292314
result = await self.__sandbox_data_api.create_sandbox_async(
293315
template_name=template_name,
294316
sandbox_idle_timeout_seconds=sandbox_idle_timeout_seconds,
317+
nas_config=nas_config_dict,
318+
oss_mount_config=oss_mount_config_dict,
319+
polar_fs_config=polar_fs_config_dict,
295320
config=config,
296321
)
297322

agentrun/sandbox/__init__.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@
1010
CodeLanguage,
1111
ListSandboxesInput,
1212
ListSandboxesOutput,
13+
NASConfig,
14+
NASMountConfig,
15+
OSSMountConfig,
16+
OSSMountPoint,
1317
PageableInput,
18+
PolarFsConfig,
1419
SandboxInput,
1520
TemplateArmsConfiguration,
1621
TemplateContainerConfiguration,
@@ -55,4 +60,10 @@
5560
"ListSandboxesOutput",
5661
"CodeLanguage",
5762
"TemplateOSSPermission",
63+
"NASConfig",
64+
"NASMountConfig",
65+
"OSSMountConfig",
66+
"OSSMountPoint",
67+
"PolarFsConfig",
68+
"PolarFsConfig",
5869
]

agentrun/sandbox/__sandbox_async_template.py

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,16 @@
44
This module defines the high-level API for sandbox resources.
55
"""
66

7-
from typing import List, Literal, Optional, overload, TYPE_CHECKING, Union
7+
from typing import (
8+
Any,
9+
Dict,
10+
List,
11+
Literal,
12+
Optional,
13+
overload,
14+
TYPE_CHECKING,
15+
Union,
16+
)
817

918
from agentrun.sandbox.model import TemplateType
1019
from agentrun.utils.config import Config
@@ -17,7 +26,10 @@
1726
from agentrun.sandbox.model import (
1827
ListSandboxesInput,
1928
ListSandboxesOutput,
29+
NASConfig,
30+
OSSMountConfig,
2031
PageableInput,
32+
PolarFsConfig,
2133
TemplateInput,
2234
)
2335
from agentrun.sandbox.template import Template
@@ -32,23 +44,29 @@ class Sandbox(BaseModel):
3244
_template_type: Optional[TemplateType]
3345

3446
created_at: Optional[str] = None
35-
"""沙箱创建时间"""
47+
"""沙箱创建时间 / Sandbox creation time"""
48+
ended_at: Optional[str] = None
49+
"""沙箱结束时间 / Sandbox end time"""
3650
last_updated_at: Optional[str] = None
37-
"""最后更新时间"""
51+
"""最后更新时间 / Last updated time"""
52+
metadata: Optional[Dict[str, Any]] = None
53+
"""元数据 / Metadata"""
3854
sandbox_arn: Optional[str] = None
39-
"""沙箱全局唯一资源名称"""
55+
"""沙箱全局唯一资源名称 / Sandbox ARN"""
4056
sandbox_id: Optional[str] = None
41-
"""沙箱 ID"""
57+
"""沙箱 ID / Sandbox ID"""
58+
sandbox_idle_ttlin_seconds: Optional[int] = None
59+
"""沙箱空闲 TTL(秒) / Sandbox Idle TTL (seconds)"""
4260
sandbox_idle_timeout_seconds: Optional[int] = None
43-
"""沙箱空闲超时时间(秒)"""
61+
"""沙箱空闲超时时间(秒) / Sandbox Idle Timeout (seconds)"""
4462
status: Optional[str] = None
45-
"""沙箱状态"""
63+
"""沙箱状态 / Sandbox status"""
4664
template_id: Optional[str] = None
47-
"""模板 ID"""
65+
"""模板 ID / Template ID"""
4866
template_name: Optional[str] = None
49-
"""模板名称"""
67+
"""模板名称 / Template name"""
5068
_config: Optional[Config] = None
51-
"""配置对象,用于子类的 data_api 初始化"""
69+
"""配置对象,用于子类的 data_api 初始化 / Config object for data_api initialization"""
5270

5371
@classmethod
5472
def __get_client(cls):
@@ -64,6 +82,9 @@ async def create_async(
6482
template_type: Literal[TemplateType.CODE_INTERPRETER],
6583
template_name: Optional[str] = None,
6684
sandbox_idle_timeout_seconds: Optional[int] = 600,
85+
nas_config: Optional["NASConfig"] = None,
86+
oss_mount_config: Optional["OSSMountConfig"] = None,
87+
polar_fs_config: Optional["PolarFsConfig"] = None,
6788
config: Optional[Config] = None,
6889
) -> "CodeInterpreterSandbox":
6990
...
@@ -75,6 +96,9 @@ async def create_async(
7596
template_type: Literal[TemplateType.BROWSER],
7697
template_name: Optional[str] = None,
7798
sandbox_idle_timeout_seconds: Optional[int] = 600,
99+
nas_config: Optional["NASConfig"] = None,
100+
oss_mount_config: Optional["OSSMountConfig"] = None,
101+
polar_fs_config: Optional["PolarFsConfig"] = None,
78102
config: Optional[Config] = None,
79103
) -> "BrowserSandbox":
80104
...
@@ -86,6 +110,9 @@ async def create_async(
86110
template_type: Literal[TemplateType.AIO],
87111
template_name: Optional[str] = None,
88112
sandbox_idle_timeout_seconds: Optional[int] = 600,
113+
nas_config: Optional["NASConfig"] = None,
114+
oss_mount_config: Optional["OSSMountConfig"] = None,
115+
polar_fs_config: Optional["PolarFsConfig"] = None,
89116
config: Optional[Config] = None,
90117
) -> "AioSandbox":
91118
...
@@ -96,6 +123,9 @@ async def create_async(
96123
template_type: TemplateType,
97124
template_name: Optional[str] = None,
98125
sandbox_idle_timeout_seconds: Optional[int] = 600,
126+
nas_config: Optional["NASConfig"] = None,
127+
oss_mount_config: Optional["OSSMountConfig"] = None,
128+
polar_fs_config: Optional["PolarFsConfig"] = None,
99129
config: Optional[Config] = None,
100130
) -> Union["CodeInterpreterSandbox", "BrowserSandbox", "AioSandbox"]:
101131

@@ -123,6 +153,9 @@ async def create_async(
123153
base_sandbox = await cls.__get_client().create_sandbox_async(
124154
template_name=template_name,
125155
sandbox_idle_timeout_seconds=sandbox_idle_timeout_seconds,
156+
nas_config=nas_config,
157+
oss_mount_config=oss_mount_config,
158+
polar_fs_config=polar_fs_config,
126159
)
127160

128161
# 根据 template 类型转换为对应的子类实例

agentrun/sandbox/__template_async_template.py

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -29,59 +29,61 @@ class Template(BaseModel):
2929
"""
3030

3131
template_id: Optional[str] = None
32-
"""模板 ID"""
32+
"""模板 ID / Template ID"""
3333
template_name: Optional[str] = None
34-
"""模板名称"""
34+
"""模板名称 / Template Name"""
3535
template_version: Optional[str] = None
36-
"""模板版本"""
36+
"""模板版本 / Template Version"""
3737
template_arn: Optional[str] = None
38-
"""模板 ARN"""
38+
"""模板 ARN / Template ARN"""
3939
resource_name: Optional[str] = None
40-
"""资源名称"""
40+
"""资源名称 / Resource Name"""
4141
template_type: Optional[TemplateType] = None
42-
"""模板类型"""
42+
"""模板类型 / Template Type"""
4343
cpu: Optional[float] = None
44-
"""CPU 核数"""
44+
"""CPU 核数 / CPU Cores"""
4545
memory: Optional[int] = None
46-
"""内存大小(MB)"""
46+
"""内存大小(MB) / Memory Size (MB)"""
4747
disk_size: Optional[int] = None
48-
"""磁盘大小(GB)"""
48+
"""磁盘大小(GB) / Disk Size (GB)"""
4949
description: Optional[str] = None
50-
"""描述"""
50+
"""描述 / Description"""
5151
execution_role_arn: Optional[str] = None
52-
"""执行角色 ARN"""
52+
"""执行角色 ARN / Execution Role ARN"""
5353
sandbox_idle_timeout_in_seconds: Optional[int] = None
54-
"""沙箱空闲超时时间(秒)"""
54+
"""沙箱空闲超时时间(秒) / Sandbox Idle Timeout (seconds)"""
5555
sandbox_ttlin_seconds: Optional[int] = None
56-
"""沙箱存活时间(秒)"""
56+
"""沙箱存活时间(秒) / Sandbox TTL (seconds)"""
5757
share_concurrency_limit_per_sandbox: Optional[int] = None
58-
"""每个沙箱的最大并发会话数"""
58+
"""每个沙箱的最大并发会话数 / Max Concurrency Limit Per Sandbox"""
5959
template_configuration: Optional[Dict] = None
60-
"""模板配置"""
60+
"""模板配置 / Template Configuration"""
6161
environment_variables: Optional[Dict] = None
62-
"""环境变量"""
62+
"""环境变量 / Environment Variables"""
6363
network_configuration: Optional[TemplateNetworkConfiguration] = None
64-
"""网络配置"""
64+
"""网络配置 / Network Configuration"""
6565
oss_configuration: Optional[List[TemplateOssConfiguration]] = None
66-
"""OSS 配置列表"""
66+
"""OSS 配置列表 / OSS Configuration List"""
6767
log_configuration: Optional[TemplateLogConfiguration] = None
68-
"""日志配置"""
68+
"""日志配置 / Log Configuration"""
6969
credential_configuration: Optional[TemplateCredentialConfiguration] = None
70-
"""凭证配置"""
70+
"""凭证配置 / Credential Configuration"""
7171
container_configuration: Optional[TemplateContainerConfiguration] = None
72-
"""容器配置"""
72+
"""容器配置 / Container Configuration"""
7373
mcp_options: Optional[TemplateMcpOptions] = None
74-
"""MCP 选项"""
74+
"""MCP 选项 / MCP Options"""
7575
mcp_state: Optional[TemplateMcpState] = None
76-
"""MCP 状态"""
76+
"""MCP 状态 / MCP State"""
77+
allow_anonymous_manage: Optional[bool] = None
78+
"""是否允许匿名管理 / Whether to allow anonymous management"""
7779
created_at: Optional[str] = None
78-
"""创建时间"""
80+
"""创建时间 / Creation Time"""
7981
last_updated_at: Optional[str] = None
80-
"""最后更新时间"""
82+
"""最后更新时间 / Last Updated Time"""
8183
status: Optional[str] = None
82-
"""状态"""
84+
"""状态 / Status"""
8385
status_reason: Optional[str] = None
84-
"""状态原因"""
86+
"""状态原因 / Status Reason"""
8587

8688
@classmethod
8789
def __get_client(cls, config: Optional[Config] = None):

agentrun/sandbox/aio_sandbox.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -763,8 +763,7 @@ def __enter__(self):
763763

764764
except Exception as e:
765765
logger.error(
766-
f"[{retry_count}/{max_retries}] Health check failed,"
767-
f" retrying: {e}"
766+
f"[{retry_count}/{max_retries}] Health check failed: {e}"
768767
)
769768

770769
if retry_count < max_retries:
@@ -806,8 +805,12 @@ async def check_health_async(self):
806805
"""Check sandbox health status (async)."""
807806
return await self.data_api.check_health_async()
808807

808+
# ========================================
809+
# Browser API Methods
810+
# ========================================
811+
809812
def check_health(self):
810-
"""Check sandbox health status (sync)."""
813+
"""Check sandbox health status (async)."""
811814
return self.data_api.check_health()
812815

813816
# ========================================
@@ -868,8 +871,12 @@ async def delete_recording_async(self, filename: str):
868871
"""Delete a recording file (async)."""
869872
return await self.data_api.delete_recording_async(filename)
870873

874+
# ========================================
875+
# Code Interpreter API Properties
876+
# ========================================
877+
871878
def delete_recording(self, filename: str):
872-
"""Delete a recording file (sync)."""
879+
"""Delete a recording file (async)."""
873880
return self.data_api.delete_recording(filename)
874881

875882
# ========================================

0 commit comments

Comments
 (0)