From 6de99ee711bf991cf4b06ecd278eadb200f4f8ba Mon Sep 17 00:00:00 2001 From: ShenJunkun <2458684728@qq.com> Date: Mon, 29 Dec 2025 19:48:58 +0800 Subject: [PATCH 1/5] refactor: replace enum sandboxType to string sandboxType --- .../agents/agentscope/tools/ToolkitInit.java | 17 ++-- .../agentscope/tools/mcp/AsMCPTool.java | 3 +- .../runtime/sandbox/box/CloudSandbox.java | 5 +- .../runtime/sandbox/box/DummySandbox.java | 4 +- .../runtime/sandbox/box/Sandbox.java | 8 +- .../runtime/sandbox/box/TrainingSandbox.java | 5 +- .../sandbox/manager/SandboxManager.java | 46 ++++----- .../collections/RedisContainerMapping.java | 9 +- .../sandbox/manager/model/ManagerConfig.java | 8 +- .../model/container/DynamicSandboxType.java | 62 +++++------- .../model/container/SandboxConfig.java | 8 +- .../manager/model/container/SandboxKey.java | 8 +- .../manager/model/container/SandboxType.java | 46 +++++---- .../manager/registry/RegisterSandbox.java | 2 +- .../registry/SandboxAnnotationProcessor.java | 4 +- .../manager/registry/SandboxRegistry.java | 22 ++--- .../registry/SandboxRegistryService.java | 22 ++--- .../runtime/sandbox/tools/MCPTool.java | 7 +- .../sandbox/tools/McpConfigConverter.java | 12 +-- .../manager/SandboxRegistryServiceTest.java | 6 +- .../sandbox/manager/SandboxTypeTest.java | 96 +++++++++++++++++++ 21 files changed, 239 insertions(+), 161 deletions(-) create mode 100644 core/src/test/java/io/agentscope/runtime/sandbox/manager/SandboxTypeTest.java diff --git a/agents/agentscope/src/main/java/io/agentscope/runtime/engine/agents/agentscope/tools/ToolkitInit.java b/agents/agentscope/src/main/java/io/agentscope/runtime/engine/agents/agentscope/tools/ToolkitInit.java index cf79c9ba..0262b822 100644 --- a/agents/agentscope/src/main/java/io/agentscope/runtime/engine/agents/agentscope/tools/ToolkitInit.java +++ b/agents/agentscope/src/main/java/io/agentscope/runtime/engine/agents/agentscope/tools/ToolkitInit.java @@ -24,7 +24,6 @@ import io.agentscope.runtime.engine.agents.agentscope.tools.mcp.AsMCPTool; import io.agentscope.runtime.sandbox.box.Sandbox; import io.agentscope.runtime.sandbox.manager.SandboxManager; -import io.agentscope.runtime.sandbox.manager.model.container.SandboxType; import io.agentscope.runtime.sandbox.tools.MCPTool; import io.agentscope.runtime.sandbox.tools.McpConfigConverter; import org.slf4j.Logger; @@ -299,19 +298,19 @@ public static AgentTool SearchFilesTool(Sandbox sandbox) { } public static List getMcpTools(String serverConfigs, - SandboxType sandboxType, + String sandboxType, SandboxManager sandboxManager) { return getMcpTools(serverConfigs, sandboxType, sandboxManager, null, null); } public static List getMcpTools(Map serverConfigs, - SandboxType sandboxType, + String sandboxType, SandboxManager sandboxManager) { return getMcpTools(serverConfigs, sandboxType, sandboxManager, null, null); } public static List getMcpTools(String serverConfigs, - SandboxType sandboxType, + String sandboxType, SandboxManager sandboxManager, Set whitelist, Set blacklist) { @@ -327,7 +326,7 @@ public static List getMcpTools(String serverConfigs, } public static List getMcpTools(Map serverConfigs, - SandboxType sandboxType, + String sandboxType, SandboxManager sandboxManager, Set whitelist, Set blacklist) { @@ -353,7 +352,7 @@ public static List getMcpTools(Map serverConfigs, } // public static List getAllToolsWithMcp(String mcpServerConfigs, -// SandboxType sandboxType, +// String sandboxType, // SandboxManager sandboxManager) { // List allTools = new ArrayList<>(getAllTools()); // @@ -371,7 +370,7 @@ public static List getMcpTools(Map serverConfigs, // } // public static List getAllToolsWithMcp(Map mcpServerConfigs, -// SandboxType sandboxType, +// String sandboxType, // SandboxManager sandboxManager) { // List allTools = new ArrayList<>(getAllTools()); // @@ -389,7 +388,7 @@ public static List getMcpTools(Map serverConfigs, // } public static List createMcpToolInstances(String serverConfigs, - SandboxType sandboxType, + String sandboxType, SandboxManager sandboxManager) { McpConfigConverter converter = McpConfigConverter.builder() .serverConfigs(serverConfigs) @@ -401,7 +400,7 @@ public static List createMcpToolInstances(String serverConfigs, } public static List createMcpToolInstances(Map serverConfigs, - SandboxType sandboxType, + String sandboxType, SandboxManager sandboxManager) { McpConfigConverter converter = McpConfigConverter.builder() .serverConfigs(serverConfigs) diff --git a/agents/agentscope/src/main/java/io/agentscope/runtime/engine/agents/agentscope/tools/mcp/AsMCPTool.java b/agents/agentscope/src/main/java/io/agentscope/runtime/engine/agents/agentscope/tools/mcp/AsMCPTool.java index e24b7a4e..f8a194bd 100644 --- a/agents/agentscope/src/main/java/io/agentscope/runtime/engine/agents/agentscope/tools/mcp/AsMCPTool.java +++ b/agents/agentscope/src/main/java/io/agentscope/runtime/engine/agents/agentscope/tools/mcp/AsMCPTool.java @@ -19,7 +19,6 @@ import io.agentscope.core.message.ToolResultBlock; import io.agentscope.runtime.engine.agents.agentscope.tools.AgentScopeSandboxAwareTool; import io.agentscope.runtime.sandbox.manager.SandboxManager; -import io.agentscope.runtime.sandbox.manager.model.container.SandboxType; import io.agentscope.runtime.sandbox.tools.MCPTool; import reactor.core.publisher.Mono; @@ -29,7 +28,7 @@ public class AsMCPTool extends AgentScopeSandboxAwareTool { public AsMCPTool(String name, String toolType, String description, Map schema, Map serverConfigs, - SandboxType sandboxType, SandboxManager sandboxManager) { + String sandboxType, SandboxManager sandboxManager) { super(new MCPTool(name, toolType, description, diff --git a/core/src/main/java/io/agentscope/runtime/sandbox/box/CloudSandbox.java b/core/src/main/java/io/agentscope/runtime/sandbox/box/CloudSandbox.java index 3f8d1b65..f5cd46d4 100644 --- a/core/src/main/java/io/agentscope/runtime/sandbox/box/CloudSandbox.java +++ b/core/src/main/java/io/agentscope/runtime/sandbox/box/CloudSandbox.java @@ -17,10 +17,9 @@ package io.agentscope.runtime.sandbox.box; import io.agentscope.runtime.sandbox.manager.SandboxManager; -import io.agentscope.runtime.sandbox.manager.model.container.SandboxType; public abstract class CloudSandbox extends Sandbox { - public CloudSandbox(SandboxManager managerApi, String userId, String sessionId, SandboxType sandboxType) { + public CloudSandbox(SandboxManager managerApi, String userId, String sessionId, String sandboxType) { this(managerApi, userId, sessionId, 3000, sandboxType); } @@ -29,7 +28,7 @@ public CloudSandbox( String userId, String sessionId, int timeout, - SandboxType sandboxType) { + String sandboxType) { super(managerApi, userId, sessionId, sandboxType, timeout); } } \ No newline at end of file diff --git a/core/src/main/java/io/agentscope/runtime/sandbox/box/DummySandbox.java b/core/src/main/java/io/agentscope/runtime/sandbox/box/DummySandbox.java index 5ff948a4..f0bfe33b 100644 --- a/core/src/main/java/io/agentscope/runtime/sandbox/box/DummySandbox.java +++ b/core/src/main/java/io/agentscope/runtime/sandbox/box/DummySandbox.java @@ -29,7 +29,7 @@ public class DummySandbox implements AutoCloseable { private final String sandboxId; private final String userId; private final String sessionId; - private final SandboxType sandboxType; + private final String sandboxType; private boolean closed = false; public DummySandbox(SandboxManager managerApi, String userId, String sessionId) { @@ -63,7 +63,7 @@ public String getSessionId() { return sessionId; } - public SandboxType getSandboxType() { + public String getSandboxType() { return sandboxType; } diff --git a/core/src/main/java/io/agentscope/runtime/sandbox/box/Sandbox.java b/core/src/main/java/io/agentscope/runtime/sandbox/box/Sandbox.java index e361f684..30c2876b 100644 --- a/core/src/main/java/io/agentscope/runtime/sandbox/box/Sandbox.java +++ b/core/src/main/java/io/agentscope/runtime/sandbox/box/Sandbox.java @@ -30,7 +30,7 @@ public abstract class Sandbox implements AutoCloseable { protected String sandboxId; protected final String userId; protected final String sessionId; - protected final SandboxType sandboxType; + protected final String sandboxType; protected final int timeout; protected final boolean autoRelease; protected boolean closed = false; @@ -39,7 +39,7 @@ public Sandbox( SandboxManager managerApi, String userId, String sessionId, - SandboxType sandboxType, + String sandboxType, int timeout) { this(managerApi, userId, sessionId, sandboxType, timeout, true); } @@ -48,7 +48,7 @@ public Sandbox( SandboxManager managerApi, String userId, String sessionId, - SandboxType sandboxType, + String sandboxType, int timeout, boolean autoRelease) { this.managerApi = managerApi; @@ -87,7 +87,7 @@ public String getSessionId() { return sessionId; } - public SandboxType getSandboxType() { + public String getSandboxType() { return sandboxType; } diff --git a/core/src/main/java/io/agentscope/runtime/sandbox/box/TrainingSandbox.java b/core/src/main/java/io/agentscope/runtime/sandbox/box/TrainingSandbox.java index 35a2ce58..90953c7a 100644 --- a/core/src/main/java/io/agentscope/runtime/sandbox/box/TrainingSandbox.java +++ b/core/src/main/java/io/agentscope/runtime/sandbox/box/TrainingSandbox.java @@ -16,7 +16,6 @@ package io.agentscope.runtime.sandbox.box; import io.agentscope.runtime.sandbox.manager.SandboxManager; -import io.agentscope.runtime.sandbox.manager.model.container.SandboxType; import java.util.HashMap; import java.util.Map; @@ -27,7 +26,7 @@ public TrainingSandbox( SandboxManager managerApi, String userId, String sessionId, - SandboxType sandboxType) { + String sandboxType) { this(managerApi, userId, sessionId, sandboxType, 3000); } @@ -35,7 +34,7 @@ public TrainingSandbox( SandboxManager managerApi, String userId, String sessionId, - SandboxType sandboxType, + String sandboxType, int timeout) { super(managerApi, userId, sessionId, sandboxType, timeout); } diff --git a/core/src/main/java/io/agentscope/runtime/sandbox/manager/SandboxManager.java b/core/src/main/java/io/agentscope/runtime/sandbox/manager/SandboxManager.java index 6038e4c1..3838b4c7 100644 --- a/core/src/main/java/io/agentscope/runtime/sandbox/manager/SandboxManager.java +++ b/core/src/main/java/io/agentscope/runtime/sandbox/manager/SandboxManager.java @@ -212,8 +212,8 @@ private void initContainerPool() { logger.info("Initializing container pool with size: {}", poolSize); while (poolQueue.size() < poolSize) { - for (SandboxType type : managerConfig.getDefaultSandboxType()) { - if (type == SandboxType.AGENTBAY) { + for (String type : managerConfig.getDefaultSandboxType()) { + if (Objects.equals(type, SandboxType.AGENTBAY)) { logger.warn("Skipping AgentBay sandbox type for container pool initialization"); continue; } @@ -242,7 +242,7 @@ private void initContainerPool() { logger.info("Container pool initialization complete. Pool size: {}", poolQueue.size()); } - public ContainerModel createFromPool(SandboxType sandboxType, String imageId, Map labels) { + public ContainerModel createFromPool(String sandboxType, String imageId, Map labels) { int attempts = 0; int maxAttempts = poolSize + 1; @@ -297,16 +297,16 @@ public ContainerModel createFromPool(SandboxType sandboxType, String imageId, Ma return createContainer(sandboxType, null, null, null, imageId, labels); } - public ContainerModel createFromPool(SandboxType sandboxType, String userID, String sessionID) { + public ContainerModel createFromPool(String sandboxType, String userID, String sessionID) { return createFromPool(sandboxType, userID, sessionID, null, null); } @RemoteWrapper - public ContainerModel createFromPool(SandboxType sandboxType, String userID, String sessionID, String imageId, Map labels) { + public ContainerModel createFromPool(String sandboxType, String userID, String sessionID, String imageId, Map labels) { if (remoteHttpClient != null && remoteHttpClient.isConfigured()) { logger.info("Remote mode: forwarding createFromPool(with userID/sessionID) to remote server"); Map requestData = new HashMap<>(); - requestData.put("sandboxType", sandboxType != null ? sandboxType.name() : null); + requestData.put("sandboxType", sandboxType); requestData.put("userID", userID); requestData.put("sessionID", sessionID); requestData.put("imageId", imageId); @@ -366,20 +366,20 @@ public ContainerModel createFromPool(SandboxType sandboxType, String userID, Str return containerModel; } - public ContainerModel createContainer(SandboxType sandboxType) { + public ContainerModel createContainer(String sandboxType) { return createContainer(sandboxType, null, null, null); } - public ContainerModel createContainer(SandboxType sandboxType, String mountDir, String storagePath, Map environment) { + public ContainerModel createContainer(String sandboxType, String mountDir, String storagePath, Map environment) { return createContainer(sandboxType, mountDir, storagePath, environment, null, null); } @RemoteWrapper - public ContainerModel createContainer(SandboxType sandboxType, String mountDir, String storagePath, Map environment, String imageId, Map labels) { + public ContainerModel createContainer(String sandboxType, String mountDir, String storagePath, Map environment, String imageId, Map labels) { if (remoteHttpClient != null && remoteHttpClient.isConfigured()) { logger.info("Remote mode: forwarding createContainer to remote server"); Map requestData = new HashMap<>(); - requestData.put("sandboxType", sandboxType != null ? sandboxType.name() : null); + requestData.put("sandboxType", sandboxType); requestData.put("mountDir", mountDir); requestData.put("storagePath", storagePath); requestData.put("environment", environment); @@ -618,19 +618,19 @@ private void releaseContainer(ContainerModel containerModel) { } } - public ContainerModel getSandbox(SandboxType sandboxType, String userID, String sessionID) { + public ContainerModel getSandbox(String sandboxType, String userID, String sessionID) { return getSandbox(sandboxType, null, null, null, userID, sessionID, null, null); } - public ContainerModel getSandbox(SandboxType sandboxType, String userID, String sessionID, String imageId, Map labels) { + public ContainerModel getSandbox(String sandboxType, String userID, String sessionID, String imageId, Map labels) { return getSandbox(sandboxType, null, null, null, userID, sessionID, imageId, labels); } - public ContainerModel getSandbox(SandboxType sandboxType, String mountDir, String storagePath, Map environment, String userID, String sessionID) { + public ContainerModel getSandbox(String sandboxType, String mountDir, String storagePath, Map environment, String userID, String sessionID) { return getSandbox(sandboxType, mountDir, storagePath, environment, userID, sessionID, null, null); } - public ContainerModel getSandbox(SandboxType sandboxType, String mountDir, String storagePath, Map environment, String userID, String sessionID, String imageId, Map labels) { + public ContainerModel getSandbox(String sandboxType, String mountDir, String storagePath, Map environment, String userID, String sessionID, String imageId, Map labels) { SandboxKey key = new SandboxKey(userID, sessionID, sandboxType); if (redisEnabled && redisContainerMapping != null) { @@ -660,11 +660,11 @@ public ContainerModel getSandbox(SandboxType sandboxType, String mountDir, Strin } @RemoteWrapper - public void startSandbox(SandboxType sandboxType, String userID, String sessionID) { + public void startSandbox(String sandboxType, String userID, String sessionID) { if (remoteHttpClient != null && remoteHttpClient.isConfigured()) { logger.info("Remote mode: forwarding startSandbox to remote server"); Map requestData = new HashMap<>(); - requestData.put("sandboxType", sandboxType != null ? sandboxType.name() : null); + requestData.put("sandboxType", sandboxType); requestData.put("userID", userID); requestData.put("sessionID", sessionID); remoteHttpClient.makeRequest( @@ -695,11 +695,11 @@ public void startSandbox(SandboxType sandboxType, String userID, String sessionI } @RemoteWrapper - public void stopSandbox(SandboxType sandboxType, String userID, String sessionID) { + public void stopSandbox(String sandboxType, String userID, String sessionID) { if (remoteHttpClient != null && remoteHttpClient.isConfigured()) { logger.info("Remote mode: forwarding stopSandbox to remote server"); Map requestData = new HashMap<>(); - requestData.put("sandboxType", sandboxType != null ? sandboxType.name() : null); + requestData.put("sandboxType", sandboxType); requestData.put("userID", userID); requestData.put("sessionID", sessionID); remoteHttpClient.makeRequest( @@ -729,7 +729,7 @@ public void stopSandbox(SandboxType sandboxType, String userID, String sessionID } } - public void removeSandbox(SandboxType sandboxType, String userID, String sessionID) { + public void removeSandbox(String sandboxType, String userID, String sessionID) { SandboxKey key = new SandboxKey(userID, sessionID, sandboxType); ContainerModel containerModel = sandboxMap.get(key); @@ -748,7 +748,7 @@ public void removeSandbox(SandboxType sandboxType, String userID, String session } } - public void stopAndRemoveSandbox(SandboxType sandboxType, String userID, String sessionID) { + public void stopAndRemoveSandbox(String sandboxType, String userID, String sessionID) { SandboxKey key = new SandboxKey(userID, sessionID, sandboxType); ContainerModel containerModel = sandboxMap.get(key); @@ -790,11 +790,11 @@ public void stopAndRemoveSandbox(SandboxType sandboxType, String userID, String } @RemoteWrapper - public String getSandboxStatus(SandboxType sandboxType, String userID, String sessionID) { + public String getSandboxStatus(String sandboxType, String userID, String sessionID) { if (remoteHttpClient != null && remoteHttpClient.isConfigured()) { logger.info("Remote mode: forwarding getSandboxStatus to remote server"); Map requestData = new HashMap<>(); - requestData.put("sandboxType", sandboxType != null ? sandboxType.name() : null); + requestData.put("sandboxType", sandboxType); requestData.put("userID", userID); requestData.put("sessionID", sessionID); Object result = remoteHttpClient.makeRequest( @@ -1168,7 +1168,7 @@ public Map addMcpServers(String sandboxId, String userId, String } } - public boolean releaseSandbox(SandboxType sandboxType, String userId, String sessionId) { + public boolean releaseSandbox(String sandboxType, String userId, String sessionId) { try { stopAndRemoveSandbox(sandboxType, userId, sessionId); logger.info("Released sandbox: type={}, user={}, session={}", sandboxType, userId, sessionId); diff --git a/core/src/main/java/io/agentscope/runtime/sandbox/manager/collections/RedisContainerMapping.java b/core/src/main/java/io/agentscope/runtime/sandbox/manager/collections/RedisContainerMapping.java index 3cd7384f..8c134102 100644 --- a/core/src/main/java/io/agentscope/runtime/sandbox/manager/collections/RedisContainerMapping.java +++ b/core/src/main/java/io/agentscope/runtime/sandbox/manager/collections/RedisContainerMapping.java @@ -19,7 +19,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; import io.agentscope.runtime.sandbox.manager.model.container.ContainerModel; import io.agentscope.runtime.sandbox.manager.model.container.SandboxKey; -import io.agentscope.runtime.sandbox.manager.model.container.SandboxType; import io.agentscope.runtime.sandbox.manager.util.RedisClientWrapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -53,7 +52,7 @@ private String getFullKey(SandboxKey key) { prefix, key.getUserID(), key.getSessionID(), - key.getSandboxType().getTypeName(), + key.getSandboxType(), key.getImageID()); } @@ -185,10 +184,8 @@ private SandboxKey parseSandboxKey(String keyString) { String userID = parts[0]; String sessionID = parts[1]; - String sandboxTypeStr = parts[2]; - - SandboxType sandboxType = SandboxType.valueOf(sandboxTypeStr.toUpperCase()); - + String sandboxType = parts[2]; + return new SandboxKey(userID, sessionID, sandboxType); } catch (Exception e) { logger.warn("Failed to parse SandboxKey from: {}, error: {}", keyString, e.getMessage()); diff --git a/core/src/main/java/io/agentscope/runtime/sandbox/manager/model/ManagerConfig.java b/core/src/main/java/io/agentscope/runtime/sandbox/manager/model/ManagerConfig.java index a7732968..58b362e7 100644 --- a/core/src/main/java/io/agentscope/runtime/sandbox/manager/model/ManagerConfig.java +++ b/core/src/main/java/io/agentscope/runtime/sandbox/manager/model/ManagerConfig.java @@ -47,7 +47,7 @@ public class ManagerConfig { private PortRange portRange; private int poolSize = 0; - private List defaultSandboxType; + private List defaultSandboxType; private BaseClientConfig clientConfig; private FileSystemConfig fileSystemConfig; @@ -116,7 +116,7 @@ private void validateRequired(String fieldName, Object value, String condition) } } - public List getDefaultSandboxType() { + public List getDefaultSandboxType() { return defaultSandboxType; } @@ -169,7 +169,7 @@ public static class Builder { private int poolSize = 0; private String baseUrl; private String bearerToken; - private List defaultSandboxType = List.of(SandboxType.BASE); + private List defaultSandboxType = List.of(SandboxType.BASE); private String agentBayApiKey; private FileSystemConfig fileSystemConfig = LocalFileSystemConfig.builder().build(); @@ -222,7 +222,7 @@ public Builder fileSystemConfig(FileSystemConfig fileSystemConfig) { return this; } - public Builder defaultSandboxType(List defaultSandboxType) { + public Builder defaultSandboxType(List defaultSandboxType) { this.defaultSandboxType = defaultSandboxType; return this; } diff --git a/core/src/main/java/io/agentscope/runtime/sandbox/manager/model/container/DynamicSandboxType.java b/core/src/main/java/io/agentscope/runtime/sandbox/manager/model/container/DynamicSandboxType.java index 649255ca..3425ad7d 100644 --- a/core/src/main/java/io/agentscope/runtime/sandbox/manager/model/container/DynamicSandboxType.java +++ b/core/src/main/java/io/agentscope/runtime/sandbox/manager/model/container/DynamicSandboxType.java @@ -25,27 +25,28 @@ public class DynamicSandboxType { private static final Map CUSTOM_TYPES = new ConcurrentHashMap<>(); - public static final DynamicSandboxType BASE = fromEnum(SandboxType.BASE); - public static final DynamicSandboxType BROWSER = fromEnum(SandboxType.BROWSER); - public static final DynamicSandboxType FILESYSTEM = fromEnum(SandboxType.FILESYSTEM); - public static final DynamicSandboxType TRAINING = fromEnum(SandboxType.TRAINING); - public static final DynamicSandboxType APPWORLD = fromEnum(SandboxType.APPWORLD); - public static final DynamicSandboxType BFCL = fromEnum(SandboxType.BFCL); - public static final DynamicSandboxType WEBSHOP = fromEnum(SandboxType.WEBSHOP); - public static final DynamicSandboxType GUI = fromEnum(SandboxType.GUI); - public static final DynamicSandboxType MOBILE = fromEnum(SandboxType.MOBILE); - public static final DynamicSandboxType AGENTBAY = fromEnum(SandboxType.AGENTBAY); + public static final DynamicSandboxType BASE = fromString(SandboxType.BASE); + public static final DynamicSandboxType BROWSER = fromString(SandboxType.BROWSER); + public static final DynamicSandboxType FILESYSTEM = fromString(SandboxType.FILESYSTEM); + public static final DynamicSandboxType TRAINING = fromString(SandboxType.TRAINING); + public static final DynamicSandboxType APPWORLD = fromString(SandboxType.APPWORLD); + public static final DynamicSandboxType BFCL = fromString(SandboxType.BFCL); + public static final DynamicSandboxType WEBSHOP = fromString(SandboxType.WEBSHOP); + public static final DynamicSandboxType GUI = fromString(SandboxType.GUI); + public static final DynamicSandboxType MOBILE = fromString(SandboxType.MOBILE); + public static final DynamicSandboxType AGENTBAY = fromString(SandboxType.AGENTBAY); private final String typeName; - private final SandboxType enumType; - private DynamicSandboxType(String typeName, SandboxType enumType) { + private final boolean isCustom; + + private DynamicSandboxType(String typeName, boolean isCustom) { this.typeName = typeName; - this.enumType = enumType; + this.isCustom = isCustom; } - public static DynamicSandboxType fromEnum(SandboxType sandboxType) { - return new DynamicSandboxType(sandboxType.getTypeName(), sandboxType); + public static DynamicSandboxType fromString(String sandboxType) { + return new DynamicSandboxType(sandboxType, false); } public static DynamicSandboxType custom(String typeName) { @@ -56,13 +57,14 @@ public static DynamicSandboxType custom(String typeName) { String normalizedName = typeName.toLowerCase(); try { - SandboxType enumType = SandboxType.valueOf(typeName.toUpperCase()); - return fromEnum(enumType); + if (SandboxType.isPredefinedType(typeName.toUpperCase())) { + return fromString(typeName); + } } catch (IllegalArgumentException e) { // Not a predefined type, create or get custom type } - return CUSTOM_TYPES.computeIfAbsent(normalizedName, name -> new DynamicSandboxType(name, null)); + return CUSTOM_TYPES.computeIfAbsent(normalizedName, name -> new DynamicSandboxType(name, true)); } public static DynamicSandboxType valueOf(String typeName) { @@ -70,10 +72,9 @@ public static DynamicSandboxType valueOf(String typeName) { throw new IllegalArgumentException("Type name cannot be null or empty"); } - try { - SandboxType enumType = SandboxType.valueOf(typeName.toUpperCase()); - return fromEnum(enumType); - } catch (IllegalArgumentException e) { + if (SandboxType.isPredefinedType(typeName.toUpperCase())) { + return fromString(typeName); + } else { String normalizedName = typeName.toLowerCase(); DynamicSandboxType customType = CUSTOM_TYPES.get(normalizedName); if (customType != null) { @@ -83,29 +84,14 @@ public static DynamicSandboxType valueOf(String typeName) { } } - public boolean isEnum() { - return enumType != null; - } - public boolean isCustom() { - return enumType == null; - } - - public SandboxType getEnumType() { - return enumType; + return isCustom; } public String getTypeName() { return typeName; } - public SandboxType toEnum() { - if (enumType == null) { - throw new UnsupportedOperationException("Cannot convert custom type '" + typeName + "' to SandboxType enum"); - } - return enumType; - } - public static Map getCustomTypes() { return new ConcurrentHashMap<>(CUSTOM_TYPES); } diff --git a/core/src/main/java/io/agentscope/runtime/sandbox/manager/model/container/SandboxConfig.java b/core/src/main/java/io/agentscope/runtime/sandbox/manager/model/container/SandboxConfig.java index 7236b803..1ab5b3d0 100644 --- a/core/src/main/java/io/agentscope/runtime/sandbox/manager/model/container/SandboxConfig.java +++ b/core/src/main/java/io/agentscope/runtime/sandbox/manager/model/container/SandboxConfig.java @@ -21,7 +21,7 @@ public class SandboxConfig { private final String imageName; - private final SandboxType sandboxType; + private final String sandboxType; private final Map resourceLimits; private final String securityLevel; private final int timeout; @@ -59,7 +59,7 @@ public String getImageName() { return imageName; } - public SandboxType getSandboxType() { + public String getSandboxType() { return sandboxType; } @@ -110,7 +110,7 @@ public String toString() { */ public static class Builder { private String imageName; - private SandboxType sandboxType; + private String sandboxType; private Map resourceLimits; private String securityLevel = "medium"; private int timeout = 300; @@ -123,7 +123,7 @@ public Builder imageName(String imageName) { return this; } - public Builder sandboxType(SandboxType sandboxType) { + public Builder sandboxType(String sandboxType) { this.sandboxType = sandboxType; return this; } diff --git a/core/src/main/java/io/agentscope/runtime/sandbox/manager/model/container/SandboxKey.java b/core/src/main/java/io/agentscope/runtime/sandbox/manager/model/container/SandboxKey.java index cb5df1f3..6b501605 100644 --- a/core/src/main/java/io/agentscope/runtime/sandbox/manager/model/container/SandboxKey.java +++ b/core/src/main/java/io/agentscope/runtime/sandbox/manager/model/container/SandboxKey.java @@ -24,17 +24,17 @@ public class SandboxKey { private static final Logger logger = LoggerFactory.getLogger(SandboxKey.class); private final String userID; private final String sessionID; - private final SandboxType sandboxType; + private final String sandboxType; private final String imageID; - public SandboxKey(String userID, String sessionID, SandboxType sandboxType, String imageID) { + public SandboxKey(String userID, String sessionID, String sandboxType, String imageID) { this.userID = userID; this.sessionID = sessionID; this.sandboxType = sandboxType; this.imageID = imageID; } - public SandboxKey(String userID, String sessionID, SandboxType sandboxType) { + public SandboxKey(String userID, String sessionID, String sandboxType) { this(userID, sessionID, sandboxType, sandboxType == SandboxType.AGENTBAY ? "linux_latest" : ""); if (sandboxType == SandboxType.AGENTBAY) { logger.warn("Creating SandboxKey without default \"linux_latest\" imageID for AGENTBAY type."); @@ -49,7 +49,7 @@ public String getSessionID() { return sessionID; } - public SandboxType getSandboxType() { + public String getSandboxType() { return sandboxType; } diff --git a/core/src/main/java/io/agentscope/runtime/sandbox/manager/model/container/SandboxType.java b/core/src/main/java/io/agentscope/runtime/sandbox/manager/model/container/SandboxType.java index 4d13e0a3..5b71c4fd 100644 --- a/core/src/main/java/io/agentscope/runtime/sandbox/manager/model/container/SandboxType.java +++ b/core/src/main/java/io/agentscope/runtime/sandbox/manager/model/container/SandboxType.java @@ -15,29 +15,37 @@ */ package io.agentscope.runtime.sandbox.manager.model.container; +import org.apache.commons.lang3.StringUtils; + +import java.lang.reflect.Field; + /** * Sandbox type enumeration */ -public enum SandboxType { - BASE("base"), - BROWSER("browser"), - FILESYSTEM("filesystem"), - TRAINING("training"), - APPWORLD("appworld"), - BFCL("bfcl"), - WEBSHOP("webshop"), - GUI("gui"), - MOBILE("mobile"), - CUSTOM("custom"), - AGENTBAY("agentbay"); +public class SandboxType { + public static final String BASE = "base"; + public static final String BROWSER = "browser"; + public static final String FILESYSTEM = "filesystem"; + public static final String TRAINING = "training"; + public static final String APPWORLD = "appworld"; + public static final String BFCL = "bfcl"; + public static final String WEBSHOP = "webshop"; + public static final String GUI = "gui"; + public static final String MOBILE = "mobile"; + public static final String CUSTOM = "custom"; + public static final String AGENTBAY = "agentbay"; - private final String typeName; - - SandboxType(String typeName) { - this.typeName = typeName; - } + public static boolean isPredefinedType(String typeName) { + if (StringUtils.isBlank(typeName)) { + return false; + } - public String getTypeName() { - return typeName; + Field[] fields = SandboxType.class.getDeclaredFields(); + for (Field field : fields) { + if (typeName.equals(field.getName())) { + return true; + } + } + return false; } } \ No newline at end of file diff --git a/core/src/main/java/io/agentscope/runtime/sandbox/manager/registry/RegisterSandbox.java b/core/src/main/java/io/agentscope/runtime/sandbox/manager/registry/RegisterSandbox.java index 8b07909d..b584faa5 100644 --- a/core/src/main/java/io/agentscope/runtime/sandbox/manager/registry/RegisterSandbox.java +++ b/core/src/main/java/io/agentscope/runtime/sandbox/manager/registry/RegisterSandbox.java @@ -27,7 +27,7 @@ public @interface RegisterSandbox { String imageName(); - SandboxType sandboxType() default SandboxType.BASE; + String sandboxType() default SandboxType.BASE; String customType() default ""; diff --git a/core/src/main/java/io/agentscope/runtime/sandbox/manager/registry/SandboxAnnotationProcessor.java b/core/src/main/java/io/agentscope/runtime/sandbox/manager/registry/SandboxAnnotationProcessor.java index a8b03707..25ab1a21 100644 --- a/core/src/main/java/io/agentscope/runtime/sandbox/manager/registry/SandboxAnnotationProcessor.java +++ b/core/src/main/java/io/agentscope/runtime/sandbox/manager/registry/SandboxAnnotationProcessor.java @@ -17,10 +17,8 @@ import io.agentscope.runtime.sandbox.box.*; import io.agentscope.runtime.sandbox.manager.model.container.SandboxConfig; -import io.agentscope.runtime.sandbox.manager.model.container.SandboxType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.util.HashMap; import java.util.Map; @@ -45,7 +43,7 @@ public static void processClass(Class clazz) { try { String imageName = annotation.imageName(); String customType = annotation.customType(); - SandboxType sandboxType = annotation.sandboxType(); + String sandboxType = annotation.sandboxType(); String securityLevel = annotation.securityLevel(); int timeout = annotation.timeout(); String description = annotation.description(); diff --git a/core/src/main/java/io/agentscope/runtime/sandbox/manager/registry/SandboxRegistry.java b/core/src/main/java/io/agentscope/runtime/sandbox/manager/registry/SandboxRegistry.java index 82bdbf50..476d8d9b 100644 --- a/core/src/main/java/io/agentscope/runtime/sandbox/manager/registry/SandboxRegistry.java +++ b/core/src/main/java/io/agentscope/runtime/sandbox/manager/registry/SandboxRegistry.java @@ -33,8 +33,8 @@ public class SandboxRegistry { private static final Logger logger = LoggerFactory.getLogger(SandboxRegistry.class); private static final Map, SandboxConfig> classRegistry = new ConcurrentHashMap<>(); - private static final Map> typeRegistry = new ConcurrentHashMap<>(); - private static final Map typeConfigRegistry = new ConcurrentHashMap<>(); + private static final Map> typeRegistry = new ConcurrentHashMap<>(); + private static final Map typeConfigRegistry = new ConcurrentHashMap<>(); private static final Map customTypeRegistry = new ConcurrentHashMap<>(); @@ -61,7 +61,7 @@ public static void register(Class targetClass, SandboxConfig config) { throw new IllegalArgumentException("Sandbox configuration cannot be null"); } - SandboxType sandboxType = config.getSandboxType(); + String sandboxType = config.getSandboxType(); classRegistry.put(targetClass, config); typeRegistry.put(sandboxType, targetClass); @@ -77,7 +77,7 @@ public static void register(Class targetClass, SandboxConfig config) { * @param sandboxType The sandbox type * @param imageName The Docker image name */ - public static void register(SandboxType sandboxType, String imageName) { + public static void register(String sandboxType, String imageName) { SandboxConfig config = new SandboxConfig.Builder() .sandboxType(sandboxType) .imageName(imageName) @@ -100,7 +100,7 @@ public static void register(SandboxType sandboxType, String imageName) { * @param runtimeConfig Runtime configuration */ public static void register( - SandboxType sandboxType, + String sandboxType, String imageName, Map resourceLimits, String securityLevel, @@ -141,7 +141,7 @@ public static Optional getConfig(Class targetClass) { * @param sandboxType The sandbox type * @return Optional containing the configuration if found */ - public static Optional getConfigByType(SandboxType sandboxType) { + public static Optional getConfigByType(String sandboxType) { return Optional.ofNullable(typeConfigRegistry.get(sandboxType)); } @@ -161,7 +161,7 @@ public static Optional getImage(Class targetClass) { * @param sandboxType The sandbox type * @return Optional containing the image name if found */ - public static Optional getImageByType(SandboxType sandboxType) { + public static Optional getImageByType(String sandboxType) { return getConfigByType(sandboxType).map(SandboxConfig::getImageName); } @@ -171,7 +171,7 @@ public static Optional getImageByType(SandboxType sandboxType) { * @param sandboxType The sandbox type * @return Optional containing the class if found */ - public static Optional> getClassesByType(SandboxType sandboxType) { + public static Optional> getClassesByType(String sandboxType) { return Optional.ofNullable(typeRegistry.get(sandboxType)); } @@ -189,7 +189,7 @@ public static Map, SandboxConfig> listAllSandboxes() { * * @return A copy of the type-based registry */ - public static Map listAllSandboxesByType() { + public static Map listAllSandboxesByType() { return new HashMap<>(typeConfigRegistry); } @@ -199,7 +199,7 @@ public static Map listAllSandboxesByType() { * @param sandboxType The sandbox type to check * @return true if registered, false otherwise */ - public static boolean isRegistered(SandboxType sandboxType) { + public static boolean isRegistered(String sandboxType) { return typeConfigRegistry.containsKey(sandboxType); } @@ -209,7 +209,7 @@ public static boolean isRegistered(SandboxType sandboxType) { * @param sandboxType The sandbox type to unregister * @return true if unregistered successfully, false if not found */ - public static boolean unregister(SandboxType sandboxType) { + public static boolean unregister(String sandboxType) { SandboxConfig config = typeConfigRegistry.remove(sandboxType); Class clazz = typeRegistry.remove(sandboxType); if (clazz != null) { diff --git a/core/src/main/java/io/agentscope/runtime/sandbox/manager/registry/SandboxRegistryService.java b/core/src/main/java/io/agentscope/runtime/sandbox/manager/registry/SandboxRegistryService.java index 3f760a4f..26d7c0dd 100644 --- a/core/src/main/java/io/agentscope/runtime/sandbox/manager/registry/SandboxRegistryService.java +++ b/core/src/main/java/io/agentscope/runtime/sandbox/manager/registry/SandboxRegistryService.java @@ -33,8 +33,8 @@ public class SandboxRegistryService { private static final Logger logger = LoggerFactory.getLogger(SandboxRegistryService.class); private static final Map, SandboxConfig> classRegistry = new ConcurrentHashMap<>(); - private static final Map> typeRegistry = new ConcurrentHashMap<>(); - private static final Map typeConfigRegistry = new ConcurrentHashMap<>(); + private static final Map> typeRegistry = new ConcurrentHashMap<>(); + private static final Map typeConfigRegistry = new ConcurrentHashMap<>(); private static final Map customTypeRegistry = new ConcurrentHashMap<>(); @@ -61,7 +61,7 @@ public static void register(Class targetClass, SandboxConfig config) { throw new IllegalArgumentException("Sandbox configuration cannot be null"); } - SandboxType sandboxType = config.getSandboxType(); + String sandboxType = config.getSandboxType(); classRegistry.put(targetClass, config); typeRegistry.put(sandboxType, targetClass); @@ -77,7 +77,7 @@ public static void register(Class targetClass, SandboxConfig config) { * @param sandboxType The sandbox type * @param imageName The Docker image name */ - public static void register(SandboxType sandboxType, String imageName) { + public static void register(String sandboxType, String imageName) { SandboxConfig config = new SandboxConfig.Builder() .sandboxType(sandboxType) .imageName(imageName) @@ -100,7 +100,7 @@ public static void register(SandboxType sandboxType, String imageName) { * @param runtimeConfig Runtime configuration */ public static void register( - SandboxType sandboxType, + String sandboxType, String imageName, Map resourceLimits, String securityLevel, @@ -141,7 +141,7 @@ public static Optional getConfig(Class targetClass) { * @param sandboxType The sandbox type * @return Optional containing the configuration if found */ - public static Optional getConfigByType(SandboxType sandboxType) { + public static Optional getConfigByType(String sandboxType) { return Optional.ofNullable(typeConfigRegistry.get(sandboxType)); } @@ -161,7 +161,7 @@ public static Optional getImage(Class targetClass) { * @param sandboxType The sandbox type * @return Optional containing the image name if found */ - public static Optional getImageByType(SandboxType sandboxType) { + public static Optional getImageByType(String sandboxType) { return getConfigByType(sandboxType).map(SandboxConfig::getImageName); } @@ -171,7 +171,7 @@ public static Optional getImageByType(SandboxType sandboxType) { * @param sandboxType The sandbox type * @return Optional containing the class if found */ - public static Optional> getClassesByType(SandboxType sandboxType) { + public static Optional> getClassesByType(String sandboxType) { return Optional.ofNullable(typeRegistry.get(sandboxType)); } @@ -189,7 +189,7 @@ public static Map, SandboxConfig> listAllSandboxes() { * * @return A copy of the type-based registry */ - public static Map listAllSandboxesByType() { + public static Map listAllSandboxesByType() { return new HashMap<>(typeConfigRegistry); } @@ -199,7 +199,7 @@ public static Map listAllSandboxesByType() { * @param sandboxType The sandbox type to check * @return true if registered, false otherwise */ - public static boolean isRegistered(SandboxType sandboxType) { + public static boolean isRegistered(String sandboxType) { return typeConfigRegistry.containsKey(sandboxType); } @@ -209,7 +209,7 @@ public static boolean isRegistered(SandboxType sandboxType) { * @param sandboxType The sandbox type to unregister * @return true if unregistered successfully, false if not found */ - public static boolean unregister(SandboxType sandboxType) { + public static boolean unregister(String sandboxType) { SandboxConfig config = typeConfigRegistry.remove(sandboxType); Class clazz = typeRegistry.remove(sandboxType); if (clazz != null) { diff --git a/core/src/main/java/io/agentscope/runtime/sandbox/tools/MCPTool.java b/core/src/main/java/io/agentscope/runtime/sandbox/tools/MCPTool.java index b995cef3..958a14c2 100644 --- a/core/src/main/java/io/agentscope/runtime/sandbox/tools/MCPTool.java +++ b/core/src/main/java/io/agentscope/runtime/sandbox/tools/MCPTool.java @@ -18,7 +18,6 @@ import io.agentscope.runtime.sandbox.box.BaseSandbox; import io.agentscope.runtime.sandbox.box.Sandbox; import io.agentscope.runtime.sandbox.manager.SandboxManager; -import io.agentscope.runtime.sandbox.manager.model.container.SandboxType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -30,11 +29,11 @@ public class MCPTool extends SandboxTool { private Map serverConfigs; private final String mcpToolName; - private final SandboxType sandboxType; + private final String sandboxType; public MCPTool(String name, String toolType, String description, Map schema, Map serverConfigs, - SandboxType sandboxType) { + String sandboxType) { super(name, toolType, description); this.mcpToolName = name; this.schema = schema; @@ -44,7 +43,7 @@ public MCPTool(String name, String toolType, String description, public MCPTool(String name, String toolType, String description, Map schema, Map serverConfigs, - SandboxType sandboxType, SandboxManager sandboxManager) { + String sandboxType, SandboxManager sandboxManager) { super(name, toolType, description, sandboxManager); this.mcpToolName = name; this.schema = schema; diff --git a/core/src/main/java/io/agentscope/runtime/sandbox/tools/McpConfigConverter.java b/core/src/main/java/io/agentscope/runtime/sandbox/tools/McpConfigConverter.java index c3212f83..64e618be 100644 --- a/core/src/main/java/io/agentscope/runtime/sandbox/tools/McpConfigConverter.java +++ b/core/src/main/java/io/agentscope/runtime/sandbox/tools/McpConfigConverter.java @@ -41,21 +41,21 @@ public class McpConfigConverter { private Set whitelist; private Set blacklist; private SandboxManager sandboxManager; - private SandboxType sandboxType; + private String sandboxType; private Sandbox sandbox = null; - public McpConfigConverter(Map serverConfigs, SandboxType sandboxType, + public McpConfigConverter(Map serverConfigs, String sandboxType, Set whitelist, Set blacklist) { this(serverConfigs, sandboxType, whitelist, blacklist, null); } - public McpConfigConverter(Map serverConfigs, SandboxType sandboxType, + public McpConfigConverter(Map serverConfigs, String sandboxType, Set whitelist, Set blacklist, SandboxManager sandboxManager) { this(serverConfigs, sandboxType, whitelist, blacklist, sandboxManager, null); } - public McpConfigConverter(Map serverConfigs, SandboxType sandboxType, + public McpConfigConverter(Map serverConfigs, String sandboxType, Set whitelist, Set blacklist, SandboxManager sandboxManager, Sandbox sandbox) { this.serverConfigs = serverConfigs; @@ -229,7 +229,7 @@ public static Builder builder() { public static class Builder { private Map serverConfigs; - private SandboxType sandboxType = SandboxType.BASE; + private String sandboxType = SandboxType.BASE; private Set whitelist; private Set blacklist; private SandboxManager sandboxManager; @@ -244,7 +244,7 @@ public Builder serverConfigs(String serverConfigsStr) { return this; } - public Builder sandboxType(SandboxType sandboxType) { + public Builder sandboxType(String sandboxType) { this.sandboxType = sandboxType; return this; } diff --git a/core/src/test/java/io/agentscope/runtime/sandbox/manager/SandboxRegistryServiceTest.java b/core/src/test/java/io/agentscope/runtime/sandbox/manager/SandboxRegistryServiceTest.java index 6b728491..ac2af58d 100644 --- a/core/src/test/java/io/agentscope/runtime/sandbox/manager/SandboxRegistryServiceTest.java +++ b/core/src/test/java/io/agentscope/runtime/sandbox/manager/SandboxRegistryServiceTest.java @@ -175,13 +175,11 @@ void testDynamicSandboxType() { assertTrue(customType.isCustom(), "Should be a custom type"); // Use predefined type via DynamicSandboxType - DynamicSandboxType baseType = DynamicSandboxType.fromEnum(SandboxType.BASE); + DynamicSandboxType baseType = DynamicSandboxType.fromString(SandboxType.BASE); System.out.println("\nPredefined type: " + baseType.getTypeName()); - System.out.println("Is enum type: " + baseType.isEnum()); assertEquals("base", baseType.getTypeName(), "Type name should be base"); - assertTrue(baseType.isEnum(), "Should be an enum type"); // Get type by name (works for both predefined and custom types) try { @@ -201,7 +199,7 @@ void testListAllRegistrations() { System.out.println("\n--- Test 5: List All Registrations ---"); // List all predefined sandbox types - Map allSandboxes = SandboxRegistryService.listAllSandboxesByType(); + Map allSandboxes = SandboxRegistryService.listAllSandboxesByType(); System.out.println("\nPredefined Sandbox Types (" + allSandboxes.size() + "):"); allSandboxes.forEach((type, config) -> System.out.println(" " + type + " -> " + config.getImageName()) diff --git a/core/src/test/java/io/agentscope/runtime/sandbox/manager/SandboxTypeTest.java b/core/src/test/java/io/agentscope/runtime/sandbox/manager/SandboxTypeTest.java new file mode 100644 index 00000000..84502885 --- /dev/null +++ b/core/src/test/java/io/agentscope/runtime/sandbox/manager/SandboxTypeTest.java @@ -0,0 +1,96 @@ +/* + * Copyright 2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.agentscope.runtime.sandbox.manager; + + +import io.agentscope.runtime.sandbox.manager.model.container.SandboxType; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + + +/** + * Unit tests for {@link SandboxType} + */ +class SandboxTypeTest { + + @ParameterizedTest + @DisplayName("Should return true for valid predefined field names") + @ValueSource(strings = { + "BASE", + "BROWSER", + "FILESYSTEM", + "TRAINING", + "APPWORLD", + "BFCL", + "WEBSHOP", + "GUI", + "MOBILE", + "CUSTOM", + "AGENTBAY" + }) + void shouldReturnTrueForValidFieldNames(String typeName) { + assertTrue(SandboxType.isPredefinedType(typeName), + "Should recognize " + typeName + " as a predefined field name"); + } + + @ParameterizedTest + @DisplayName("Should return false for invalid or unknown names") + @ValueSource(strings = { + "UNKNOWN", + "docker", + "PYTHON", + "123", + " " + }) + void shouldReturnFalseForInvalidNames(String typeName) { + assertFalse(SandboxType.isPredefinedType(typeName), + "Should not recognize " + typeName + " as a predefined field name"); + } + + @Test + @DisplayName("Should return false for null input") + void shouldReturnFalseForNull() { + assertFalse(SandboxType.isPredefinedType(null)); + } + + @Test + @DisplayName("Should return false for empty string") + void shouldReturnFalseForEmptyString() { + assertFalse(SandboxType.isPredefinedType("")); + } + + /** + * Note: Based on the current implementation using field.getName(), + * lowercase values (the actual constants) will return false. + */ + @ParameterizedTest + @DisplayName("Current implementation check: lowercase values should return false") + @ValueSource(strings = { + "base", + "browser", + "filesystem" + }) + void shouldReturnFalseForFieldValues(String typeValue) { + assertFalse(SandboxType.isPredefinedType(typeValue), + "Currently implementation checks field names (BASE), not values (base)"); + } +} \ No newline at end of file From c7db16ec6ab070eb1c11bdc7fa992260148e79be Mon Sep 17 00:00:00 2001 From: ShenJunkun <2458684728@qq.com> Date: Wed, 7 Jan 2026 14:55:34 +0800 Subject: [PATCH 2/5] refactor(RegisterSandbox): Remove customType in RegisterSandbox --- .../manager/registry/RegisterSandbox.java | 2 -- .../registry/SandboxAnnotationProcessor.java | 25 +++---------------- .../sandbox/manager/CustomSandboxTest.java | 4 +-- 3 files changed, 6 insertions(+), 25 deletions(-) diff --git a/core/src/main/java/io/agentscope/runtime/sandbox/manager/registry/RegisterSandbox.java b/core/src/main/java/io/agentscope/runtime/sandbox/manager/registry/RegisterSandbox.java index b584faa5..f7814fde 100644 --- a/core/src/main/java/io/agentscope/runtime/sandbox/manager/registry/RegisterSandbox.java +++ b/core/src/main/java/io/agentscope/runtime/sandbox/manager/registry/RegisterSandbox.java @@ -29,8 +29,6 @@ String sandboxType() default SandboxType.BASE; - String customType() default ""; - String securityLevel() default "medium"; int timeout() default 300; diff --git a/core/src/main/java/io/agentscope/runtime/sandbox/manager/registry/SandboxAnnotationProcessor.java b/core/src/main/java/io/agentscope/runtime/sandbox/manager/registry/SandboxAnnotationProcessor.java index 25ab1a21..0e86086b 100644 --- a/core/src/main/java/io/agentscope/runtime/sandbox/manager/registry/SandboxAnnotationProcessor.java +++ b/core/src/main/java/io/agentscope/runtime/sandbox/manager/registry/SandboxAnnotationProcessor.java @@ -42,7 +42,6 @@ public static void processClass(Class clazz) { try { String imageName = annotation.imageName(); - String customType = annotation.customType(); String sandboxType = annotation.sandboxType(); String securityLevel = annotation.securityLevel(); int timeout = annotation.timeout(); @@ -62,26 +61,10 @@ public static void processClass(Class clazz) { .resourceLimits(resourceLimits) .runtimeConfig(runtimeConfig) .build(); - - if (customType != null && !customType.isEmpty()) { - SandboxRegistryService.registerCustomType( - customType, - imageName, - resourceLimits, - securityLevel, - timeout, - description, - environment, - runtimeConfig - ); - logger.info("Registered custom sandbox via annotation: type={}, class={}, image={}", - customType, clazz.getSimpleName(), imageName); - } else { - SandboxRegistryService.register(clazz, config); - logger.info("Registered sandbox via annotation: type={}, class={}, image={}", - sandboxType, clazz.getSimpleName(), imageName); - } - + + SandboxRegistryService.register(clazz, config); + logger.info("Registered sandbox via annotation: type={}, class={}, image={}", + sandboxType, clazz.getSimpleName(), imageName); } catch (Exception e) { logger.error("Failed to process @RegisterSandbox annotation on class {}: {}", clazz.getName(), e.getMessage()); diff --git a/core/src/test/java/io/agentscope/runtime/sandbox/manager/CustomSandboxTest.java b/core/src/test/java/io/agentscope/runtime/sandbox/manager/CustomSandboxTest.java index d99152f4..a66c84f0 100644 --- a/core/src/test/java/io/agentscope/runtime/sandbox/manager/CustomSandboxTest.java +++ b/core/src/test/java/io/agentscope/runtime/sandbox/manager/CustomSandboxTest.java @@ -70,7 +70,7 @@ public String executePython(String code) { @RegisterSandbox( imageName = "agentscope-registry.ap-southeast-1.cr.aliyuncs.com/agentscope/runtime-sandbox-custom_sandbox:latest", - customType = "custom_sandbox", + sandboxType = "custom_sandbox", securityLevel = "medium", timeout = 60, description = "my sandbox", @@ -90,7 +90,7 @@ public MyCustomSandbox( @RegisterSandbox( imageName = "my-registry/my-advanced-sandbox:latest", - customType = "advanced_sandbox", + sandboxType = "advanced_sandbox", securityLevel = "high", timeout = 120, description = "Advanced custom sandbox with full configuration", From 748563a082f8e202a1f29e5d942ca8be6a9ef96e Mon Sep 17 00:00:00 2001 From: ShenJunkun <2458684728@qq.com> Date: Wed, 7 Jan 2026 17:04:35 +0800 Subject: [PATCH 3/5] refactor: clean up redundant code --- .../manager/model/container/SandboxType.java | 1 - .../registry/SandboxRegistryService.java | 110 ------------------ .../sandbox/manager/CustomSandboxTest.java | 20 ++-- .../manager/SandboxRegistryServiceTest.java | 22 ++-- 4 files changed, 21 insertions(+), 132 deletions(-) diff --git a/core/src/main/java/io/agentscope/runtime/sandbox/manager/model/container/SandboxType.java b/core/src/main/java/io/agentscope/runtime/sandbox/manager/model/container/SandboxType.java index 5b71c4fd..f5a1e17f 100644 --- a/core/src/main/java/io/agentscope/runtime/sandbox/manager/model/container/SandboxType.java +++ b/core/src/main/java/io/agentscope/runtime/sandbox/manager/model/container/SandboxType.java @@ -32,7 +32,6 @@ public class SandboxType { public static final String WEBSHOP = "webshop"; public static final String GUI = "gui"; public static final String MOBILE = "mobile"; - public static final String CUSTOM = "custom"; public static final String AGENTBAY = "agentbay"; public static boolean isPredefinedType(String typeName) { diff --git a/core/src/main/java/io/agentscope/runtime/sandbox/manager/registry/SandboxRegistryService.java b/core/src/main/java/io/agentscope/runtime/sandbox/manager/registry/SandboxRegistryService.java index 26d7c0dd..8355b692 100644 --- a/core/src/main/java/io/agentscope/runtime/sandbox/manager/registry/SandboxRegistryService.java +++ b/core/src/main/java/io/agentscope/runtime/sandbox/manager/registry/SandboxRegistryService.java @@ -15,7 +15,6 @@ */ package io.agentscope.runtime.sandbox.manager.registry; -import io.agentscope.runtime.sandbox.manager.model.container.DynamicSandboxType; import io.agentscope.runtime.sandbox.manager.model.container.SandboxConfig; import io.agentscope.runtime.sandbox.manager.model.container.SandboxType; import org.slf4j.Logger; @@ -36,8 +35,6 @@ public class SandboxRegistryService { private static final Map> typeRegistry = new ConcurrentHashMap<>(); private static final Map typeConfigRegistry = new ConcurrentHashMap<>(); - private static final Map customTypeRegistry = new ConcurrentHashMap<>(); - static { try { Class.forName(SandboxRegistryInitializer.class.getName()); @@ -230,7 +227,6 @@ public static void clear() { classRegistry.clear(); typeRegistry.clear(); typeConfigRegistry.clear(); - customTypeRegistry.clear(); logger.info("Cleared all sandbox registrations"); } @@ -242,111 +238,5 @@ public static void clear() { public static int getRegisteredCount() { return typeConfigRegistry.size(); } - - /** - * Register a custom sandbox type by string name - * This supports dynamic type registration. - * - * @param typeName The custom type name - * @param imageName The Docker image name - */ - public static void registerCustomType(String typeName, String imageName) { - DynamicSandboxType.custom(typeName); - - SandboxConfig config = new SandboxConfig.Builder() - .sandboxType(SandboxType.BASE) // Placeholder, actual type is identified by string name - .imageName(imageName) - .build(); - - customTypeRegistry.put(typeName.toLowerCase(), config); - logger.info("Registered custom sandbox type: name={}, image={}", typeName, imageName); - } - - /** - * Register a custom sandbox type with full configuration - * - * @param typeName The custom type name - * @param imageName The Docker image name - * @param resourceLimits Resource limits - * @param securityLevel Security level - * @param timeout Timeout in seconds - * @param description Description - * @param environment Environment variables - * @param runtimeConfig Runtime configuration - */ - public static void registerCustomType( - String typeName, - String imageName, - Map resourceLimits, - String securityLevel, - int timeout, - String description, - Map environment, - Map runtimeConfig) { - - // Create dynamic type to ensure it's registered in the type system - DynamicSandboxType.custom(typeName); - - // Create full config for the custom type - SandboxConfig config = new SandboxConfig.Builder() - .sandboxType(SandboxType.BASE) // Placeholder - .imageName(imageName) - .resourceLimits(resourceLimits) - .securityLevel(securityLevel) - .timeout(timeout) - .description(description) - .environment(environment) - .runtimeConfig(runtimeConfig) - .build(); - - customTypeRegistry.put(typeName.toLowerCase(), config); - - logger.info("Registered custom sandbox type with full config: name={}, image={}, timeout={}s", typeName, imageName, timeout); - } - - /** - * Get configuration for a custom sandbox type by name - * - * @param typeName The custom type name - * @return Optional containing the configuration if found - */ - public static Optional getCustomTypeConfig(String typeName) { - if (typeName == null) { - return Optional.empty(); - } - return Optional.ofNullable(customTypeRegistry.get(typeName.toLowerCase())); - } - - /** - * Get image name for a custom sandbox type - * - * @param typeName The custom type name - * @return Optional containing the image name if found - */ - public static Optional getCustomTypeImage(String typeName) { - return getCustomTypeConfig(typeName).map(SandboxConfig::getImageName); - } - - /** - * Check if a custom type is registered - * - * @param typeName The custom type name - * @return true if registered, false otherwise - */ - public static boolean isCustomTypeRegistered(String typeName) { - if (typeName == null) { - return false; - } - return customTypeRegistry.containsKey(typeName.toLowerCase()); - } - - /** - * List all registered custom sandbox types - * - * @return A copy of the custom type registry - */ - public static Map listAllCustomTypes() { - return new HashMap<>(customTypeRegistry); - } } diff --git a/core/src/test/java/io/agentscope/runtime/sandbox/manager/CustomSandboxTest.java b/core/src/test/java/io/agentscope/runtime/sandbox/manager/CustomSandboxTest.java index a66c84f0..16c01f5f 100644 --- a/core/src/test/java/io/agentscope/runtime/sandbox/manager/CustomSandboxTest.java +++ b/core/src/test/java/io/agentscope/runtime/sandbox/manager/CustomSandboxTest.java @@ -174,11 +174,11 @@ public void testCustomPythonSandboxRegistration() { public void testMyCustomSandboxRegistration() { System.out.println("\n--- Test MyCustomSandbox Registration ---"); - boolean customRegistered = SandboxRegistryService.isCustomTypeRegistered("custom_sandbox"); + boolean customRegistered = SandboxRegistryService.isRegistered("custom_sandbox"); assertTrue(customRegistered, "MyCustomSandbox should be registered"); System.out.println("✓ MyCustomSandbox registered (custom type: custom_sandbox)"); - SandboxRegistryService.getCustomTypeConfig("custom_sandbox").ifPresent(config -> { + SandboxRegistryService.getConfigByType("custom_sandbox").ifPresent(config -> { System.out.println("\nConfiguration:"); System.out.println(" Image: " + config.getImageName()); System.out.println(" Security Level: " + config.getSecurityLevel()); @@ -202,11 +202,11 @@ public void testMyCustomSandboxRegistration() { public void testAdvancedCustomSandboxRegistration() { System.out.println("\n--- Test AdvancedCustomSandbox Registration ---"); - boolean advancedRegistered = SandboxRegistryService.isCustomTypeRegistered("advanced_sandbox"); + boolean advancedRegistered = SandboxRegistryService.isRegistered("advanced_sandbox"); assertTrue(advancedRegistered, "AdvancedCustomSandbox should be registered"); System.out.println("✓ AdvancedCustomSandbox registered (custom type: advanced_sandbox)"); - SandboxRegistryService.getCustomTypeConfig("advanced_sandbox").ifPresent(config -> { + SandboxRegistryService.getConfigByType("advanced_sandbox").ifPresent(config -> { System.out.println("\nConfiguration:"); System.out.println(" Image: " + config.getImageName()); System.out.println(" Security Level: " + config.getSecurityLevel()); @@ -255,15 +255,15 @@ public void testAllCustomSandboxesRegistered() { assertTrue(SandboxRegistryService.isRegistered(SandboxType.BASE), "CustomPythonSandbox should be registered"); - assertTrue(SandboxRegistryService.isCustomTypeRegistered("custom_sandbox"), + assertTrue(SandboxRegistryService.isRegistered("custom_sandbox"), "MyCustomSandbox should be registered"); - assertTrue(SandboxRegistryService.isCustomTypeRegistered("advanced_sandbox"), + assertTrue(SandboxRegistryService.isRegistered("advanced_sandbox"), "AdvancedCustomSandbox should be registered"); System.out.println("✓ All custom sandboxes successfully registered"); Map customTypes = - SandboxRegistryService.listAllCustomTypes(); + SandboxRegistryService.listAllSandboxesByType(); System.out.println("\nRegistered custom types count: " + customTypes.size()); customTypes.forEach((name, config) -> System.out.println(" - " + name + " -> " + config.getImageName()) @@ -281,12 +281,12 @@ public void testGetImageNames() { assertTrue(image.contains("runtime-sandbox-python")); }); - SandboxRegistryService.getCustomTypeImage("custom_sandbox").ifPresent(image -> { + SandboxRegistryService.getImageByType("custom_sandbox").ifPresent(image -> { System.out.println("MyCustomSandbox image: " + image); assertFalse(image.isEmpty()); }); - SandboxRegistryService.getCustomTypeImage("advanced_sandbox").ifPresent(image -> { + SandboxRegistryService.getImageByType("advanced_sandbox").ifPresent(image -> { System.out.println("AdvancedCustomSandbox image: " + image); assertEquals("my-registry/my-advanced-sandbox:latest", image); }); @@ -314,7 +314,7 @@ public void testConfigurationOverride() { public void testAnnotationConfigurationCompleteness() { System.out.println("\n--- Verify Annotation Configuration Completeness ---"); - SandboxRegistryService.getCustomTypeConfig("advanced_sandbox").ifPresentOrElse( + SandboxRegistryService.getConfigByType("advanced_sandbox").ifPresentOrElse( config -> { System.out.println("Verifying AdvancedCustomSandbox configuration..."); diff --git a/core/src/test/java/io/agentscope/runtime/sandbox/manager/SandboxRegistryServiceTest.java b/core/src/test/java/io/agentscope/runtime/sandbox/manager/SandboxRegistryServiceTest.java index ac2af58d..1fd14445 100644 --- a/core/src/test/java/io/agentscope/runtime/sandbox/manager/SandboxRegistryServiceTest.java +++ b/core/src/test/java/io/agentscope/runtime/sandbox/manager/SandboxRegistryServiceTest.java @@ -80,10 +80,10 @@ void testRegisterCustomSandboxTypeBasic() { String customImage = "testcompany/custom-sandbox:latest"; // Register custom sandbox type - SandboxRegistryService.registerCustomType(customTypeName, customImage); + SandboxRegistryService.register(customTypeName, customImage); // Retrieve custom type configuration - Optional retrievedImage = SandboxRegistryService.getCustomTypeImage(customTypeName); + Optional retrievedImage = SandboxRegistryService.getImageByType(customTypeName); assertTrue(retrievedImage.isPresent(), "Custom type should be registered"); retrievedImage.ifPresent(image -> { @@ -92,7 +92,7 @@ void testRegisterCustomSandboxTypeBasic() { }); // Check if custom type is registered - boolean isCustomRegistered = SandboxRegistryService.isCustomTypeRegistered(customTypeName); + boolean isCustomRegistered = SandboxRegistryService.isRegistered(customTypeName); System.out.println("Custom type registered: " + isCustomRegistered); assertTrue(isCustomRegistered, "Custom type should be registered"); } @@ -121,7 +121,7 @@ void testRegisterCustomSandboxTypeAdvanced() { runtimeConfig.put("shm_size", "512m"); // Register with full configuration - SandboxRegistryService.registerCustomType( + SandboxRegistryService.register( customTypeName, "testcompany/advanced-sandbox:v1.0", resourceLimits, @@ -133,7 +133,7 @@ void testRegisterCustomSandboxTypeAdvanced() { ); // Retrieve and display configuration - Optional config = SandboxRegistryService.getCustomTypeConfig(customTypeName); + Optional config = SandboxRegistryService.getConfigByType(customTypeName); assertTrue(config.isPresent(), "Custom configuration should exist"); config.ifPresent(cfg -> { @@ -183,7 +183,7 @@ void testDynamicSandboxType() { // Get type by name (works for both predefined and custom types) try { - DynamicSandboxType retrievedType = DynamicSandboxType.valueOf("BROWSER"); + DynamicSandboxType retrievedType = DynamicSandboxType.valueOf("browser"); System.out.println("\nRetrieved type: " + retrievedType.getTypeName()); assertEquals("browser", retrievedType.getTypeName(), "Retrieved type name should match"); } catch (IllegalArgumentException e) { @@ -209,7 +209,7 @@ void testListAllRegistrations() { assertTrue(allSandboxes.containsKey(SandboxType.BASE), "Should contain BASE type"); // List all custom sandbox types - Map customTypes = SandboxRegistryService.listAllCustomTypes(); + Map customTypes = SandboxRegistryService.listAllSandboxesByType(); System.out.println("\nCustom Sandbox Types (" + customTypes.size() + "):"); customTypes.forEach((name, config) -> System.out.println(" " + name + " -> " + config.getImageName()) @@ -280,14 +280,14 @@ void testRegistrationIdempotency() { String image2 = "testcompany/sandbox:v2"; // First registration - SandboxRegistryService.registerCustomType(typeName, image1); - Optional firstImage = SandboxRegistryService.getCustomTypeImage(typeName); + SandboxRegistryService.register(typeName, image1); + Optional firstImage = SandboxRegistryService.getImageByType(typeName); assertTrue(firstImage.isPresent(), "First registration should succeed"); assertEquals(image1, firstImage.get(), "Should be the first image"); // Second registration (overwrite) - SandboxRegistryService.registerCustomType(typeName, image2); - Optional secondImage = SandboxRegistryService.getCustomTypeImage(typeName); + SandboxRegistryService.register(typeName, image2); + Optional secondImage = SandboxRegistryService.getImageByType(typeName); assertTrue(secondImage.isPresent(), "Second registration should succeed"); System.out.println("First image: " + image1); From ae4423ef74d41f8dbf906e8b2e31db91ff636f2f Mon Sep 17 00:00:00 2001 From: ShenJunkun <2458684728@qq.com> Date: Wed, 7 Jan 2026 19:08:33 +0800 Subject: [PATCH 4/5] fix: update CustomSandboxTest test case --- .../manager/model/container/SandboxType.java | 17 ++++++++++++++++ .../registry/SandboxRegistryService.java | 20 +++++++++++++++++++ .../sandbox/manager/CustomSandboxTest.java | 4 ++-- .../manager/SandboxRegistryServiceTest.java | 2 +- 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/io/agentscope/runtime/sandbox/manager/model/container/SandboxType.java b/core/src/main/java/io/agentscope/runtime/sandbox/manager/model/container/SandboxType.java index f5a1e17f..6b87519f 100644 --- a/core/src/main/java/io/agentscope/runtime/sandbox/manager/model/container/SandboxType.java +++ b/core/src/main/java/io/agentscope/runtime/sandbox/manager/model/container/SandboxType.java @@ -18,6 +18,8 @@ import org.apache.commons.lang3.StringUtils; import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; /** * Sandbox type enumeration @@ -47,4 +49,19 @@ public static boolean isPredefinedType(String typeName) { } return false; } + + public static List getAllPredefinedTypes() { + List types = new ArrayList<>(); + Field[] fields = SandboxType.class.getDeclaredFields(); + for (Field field : fields) { + if (field.getType().equals(String.class)) { + try { + types.add((String) field.get(null)); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + } + return types; + } } \ No newline at end of file diff --git a/core/src/main/java/io/agentscope/runtime/sandbox/manager/registry/SandboxRegistryService.java b/core/src/main/java/io/agentscope/runtime/sandbox/manager/registry/SandboxRegistryService.java index 8355b692..fe31defb 100644 --- a/core/src/main/java/io/agentscope/runtime/sandbox/manager/registry/SandboxRegistryService.java +++ b/core/src/main/java/io/agentscope/runtime/sandbox/manager/registry/SandboxRegistryService.java @@ -21,6 +21,7 @@ import org.slf4j.LoggerFactory; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; @@ -190,6 +191,25 @@ public static Map listAllSandboxesByType() { return new HashMap<>(typeConfigRegistry); } + /** + * List all registered custom sandbox types + * + * @return A map of custom sandbox types to their configurations + */ + public static Map listAllCustomSandboxes() { + if (typeConfigRegistry == null) { + return new HashMap<>(); + } + + Map customSandboxes = new HashMap<>(typeConfigRegistry); + List predefinedTypes = SandboxType.getAllPredefinedTypes(); + if (predefinedTypes != null) { + customSandboxes.keySet().removeAll(predefinedTypes); + } + return customSandboxes; + } + + /** * Check if a sandbox type is registered * diff --git a/core/src/test/java/io/agentscope/runtime/sandbox/manager/CustomSandboxTest.java b/core/src/test/java/io/agentscope/runtime/sandbox/manager/CustomSandboxTest.java index 16c01f5f..c33bdb93 100644 --- a/core/src/test/java/io/agentscope/runtime/sandbox/manager/CustomSandboxTest.java +++ b/core/src/test/java/io/agentscope/runtime/sandbox/manager/CustomSandboxTest.java @@ -262,8 +262,8 @@ public void testAllCustomSandboxesRegistered() { System.out.println("✓ All custom sandboxes successfully registered"); - Map customTypes = - SandboxRegistryService.listAllSandboxesByType(); + Map customTypes = + SandboxRegistryService.listAllCustomSandboxes(); System.out.println("\nRegistered custom types count: " + customTypes.size()); customTypes.forEach((name, config) -> System.out.println(" - " + name + " -> " + config.getImageName()) diff --git a/core/src/test/java/io/agentscope/runtime/sandbox/manager/SandboxRegistryServiceTest.java b/core/src/test/java/io/agentscope/runtime/sandbox/manager/SandboxRegistryServiceTest.java index 1fd14445..f11d7a70 100644 --- a/core/src/test/java/io/agentscope/runtime/sandbox/manager/SandboxRegistryServiceTest.java +++ b/core/src/test/java/io/agentscope/runtime/sandbox/manager/SandboxRegistryServiceTest.java @@ -209,7 +209,7 @@ void testListAllRegistrations() { assertTrue(allSandboxes.containsKey(SandboxType.BASE), "Should contain BASE type"); // List all custom sandbox types - Map customTypes = SandboxRegistryService.listAllSandboxesByType(); + Map customTypes = SandboxRegistryService.listAllCustomSandboxes(); System.out.println("\nCustom Sandbox Types (" + customTypes.size() + "):"); customTypes.forEach((name, config) -> System.out.println(" " + name + " -> " + config.getImageName()) From f551e4439383377c33591dd37cab95541abbc436 Mon Sep 17 00:00:00 2001 From: ShenJunkun <2458684728@qq.com> Date: Wed, 7 Jan 2026 19:37:14 +0800 Subject: [PATCH 5/5] feat: update docs about custom sandbox --- cookbook/en/sandbox/advanced.md | 79 ++++++++++++++------------------- cookbook/zh/sandbox/advanced.md | 9 ++-- 2 files changed, 37 insertions(+), 51 deletions(-) diff --git a/cookbook/en/sandbox/advanced.md b/cookbook/en/sandbox/advanced.md index 67a3154e..9d16109a 100644 --- a/cookbook/en/sandbox/advanced.md +++ b/cookbook/en/sandbox/advanced.md @@ -6,14 +6,14 @@ #### ManagerConfig Configuration -| Parameter | Type | Description | Default | Notes | -| ----------------------| ------------ | ---------------------- | -------------------------- | ------------------------------------------------------------ | -| `defaultSandboxType` | `List` | Default sandbox type(s) (can be multiple) | `SandboxType.BASE` | Can be a single type or a list of multiple types, enabling multiple independent sandbox warm-up pools. Valid values include `BASE`, `BROWSER`, `FILESYSTEM`, `GUI`, etc. | -| `bearerToken` | `String` | Authentication token for calling remote runtime sandbox | `null` | If set to `null`, no authentication will be performed when connecting | -| `baseUrl` | `String` | Server binding address for calling remote runtime sandbox | `null` | If set to `null`, local sandbox management will be used by default | -| `containerDeployment` | `BaseClientConfig` | Container runtime | `DockerClientConfig` | Currently supports `Docker`, `K8s`, and `AgentRun` | -| `poolSize` | `int` | Warm-up container pool size | `0` | Cached containers for faster startup. The `poolSize` parameter controls the number of pre-created containers cached in ready state. When a user requests a new sandbox, the system will first try to allocate from this warm-up pool, significantly reducing startup time compared to creating containers from scratch. For example, with `poolSize=10`, the system maintains 10 ready containers that can be immediately assigned to new requests | -| `fileSystemConfig` | `FileSystemConfig` | Container file system configuration | `LocalFileSystemConfig` | Manages container file system download method, defaults to `local file system`, can also use `oss` | +| Parameter | Type | Description | Default | Notes | +| ----------------------|----------------------| ---------------------- | -------------------------- | ------------------------------------------------------------ | +| `defaultSandboxType` | `List` | Default sandbox type(s) (can be multiple) | `SandboxType.BASE` | Can be a single type or a list of multiple types, enabling multiple independent sandbox warm-up pools. Valid values include `BASE`, `BROWSER`, `FILESYSTEM`, `GUI`, etc. | +| `bearerToken` | `String` | Authentication token for calling remote runtime sandbox | `null` | If set to `null`, no authentication will be performed when connecting | +| `baseUrl` | `String` | Server binding address for calling remote runtime sandbox | `null` | If set to `null`, local sandbox management will be used by default | +| `containerDeployment` | `BaseClientConfig` | Container runtime | `DockerClientConfig` | Currently supports `Docker`, `K8s`, and `AgentRun` | +| `poolSize` | `int` | Warm-up container pool size | `0` | Cached containers for faster startup. The `poolSize` parameter controls the number of pre-created containers cached in ready state. When a user requests a new sandbox, the system will first try to allocate from this warm-up pool, significantly reducing startup time compared to creating containers from scratch. For example, with `poolSize=10`, the system maintains 10 ready containers that can be immediately assigned to new requests | +| `fileSystemConfig` | `FileSystemConfig` | Container file system configuration | `LocalFileSystemConfig` | Manages container file system download method, defaults to `local file system`, can also use `oss` | | `redisConfig` | `RedisManagerConfig` | Redis support configuration | `null` | Enable Redis support, required for distributed deployment or when number of worker processes is greater than `1`, disabled by default | #### Redis Configuration @@ -149,47 +149,34 @@ pip install -e . ### Creating Custom Sandbox Class -You can define custom sandbox types and register them with the system to meet special requirements. Simply inherit from `Sandbox` and use the `SandboxRegistry.register` decorator, then place the file in `src/agentscope_runtime/sandbox/custom` (e.g., `src/agentscope_runtime/sandbox/custom/custom_sandbox.py`): +You can define custom sandbox types and register them with the system to meet special requirements. Simply inherit from the `Sandbox` class and use the `@RegisterSandbox` decorator, then place the file within your project folder: -```python -import os +```java +import io.agentscope.runtime.sandbox.box.Sandbox; +import io.agentscope.runtime.sandbox.manager.SandboxManager; +import io.agentscope.runtime.sandbox.manager.registry.RegisterSandbox; -from typing import Optional - -from agentscope_runtime.sandbox.utils import build_image_uri -from agentscope_runtime.sandbox.registry import SandboxRegistry -from agentscope_runtime.sandbox.enums import SandboxType -from agentscope_runtime.sandbox.box.sandbox import Sandbox - -SANDBOXTYPE = "my_custom_sandbox" - - -@SandboxRegistry.register( - build_image_uri(f"runtime-sandbox-{SANDBOXTYPE}"), - sandbox_type=SANDBOXTYPE, - security_level="medium", - timeout=60, - description="my sandbox", - environment={ - "TAVILY_API_KEY": os.getenv("TAVILY_API_KEY", ""), - "AMAP_MAPS_API_KEY": os.getenv("AMAP_MAPS_API_KEY", ""), - }, +@RegisterSandbox( + imageName = "YOUR-IMAGE-NAME", + sandboxType = "CustomSandboxType", + securityLevel = "medium", + timeout = 30, + description = "YOUR Sandbox" ) -class MyCustomSandbox(Sandbox): - def __init__( - self, - sandbox_id: Optional[str] = None, - timeout: int = 3000, - base_url: Optional[str] = None, - bearer_token: Optional[str] = None, - ): - super().__init__( - sandbox_id, - timeout, - base_url, - bearer_token, - SandboxType(SANDBOXTYPE), - ) +public class CustomSandbox extends Sandbox { + + public CustomSandbox(SandboxManager managerApi, String userId, String sessionId) { + this(managerApi, userId, sessionId, 3000); + } + + public CustomSandbox( + SandboxManager managerApi, + String userId, + String sessionId, + int timeout) { + super(managerApi, userId, sessionId, "CustomSandboxType", timeout); + } +} ``` ### Prepare Docker Image diff --git a/cookbook/zh/sandbox/advanced.md b/cookbook/zh/sandbox/advanced.md index e9e15869..c51c5da0 100644 --- a/cookbook/zh/sandbox/advanced.md +++ b/cookbook/zh/sandbox/advanced.md @@ -7,8 +7,8 @@ #### ManagerConfig 配置 | Parameter | Type | Description | Default | Notes | -| --------------------- | -------------------- | ----------------------------------- | ----------------------- | ------------------------------------------------------------ | -| `defaultSandboxType` | `List` | 默认沙箱类型(可多个) | `SandboxType.BASE` | 可以是单个类型,也可以是多个类型的列表,从而启用多个独立的沙箱预热池。合法取值包括 `BASE`、`BROWSER`、`FILESYSTEM`、`GUI` 等 | +| --------------------- |----------------------| ----------------------------------- | ----------------------- | ------------------------------------------------------------ | +| `defaultSandboxType` | `List` | 默认沙箱类型(可多个) | `SandboxType.BASE` | 可以是单个类型,也可以是多个类型的列表,从而启用多个独立的沙箱预热池。合法取值包括 `BASE`、`BROWSER`、`FILESYSTEM`、`GUI` 等 | | `bearerToken` | `String` | 调用远程runtime沙箱的身份验证令牌 | `null` | 如果设置为 `null`,将在连接的时候不会进行身份验证 | | `baseUrl` | `String` | 调用远程runtime沙箱的服务器绑定地址 | `null` | 如果设置为 `null`,将默认使用本地沙箱管理 | | `containerDeployment` | `BaseClientConfig` | 容器运行时 | `DockerClientConfig` | 目前支持 `Docker`、`K8s` 和 `AgentRun` | @@ -178,12 +178,11 @@ pip install -e . ```java import io.agentscope.runtime.sandbox.box.Sandbox; import io.agentscope.runtime.sandbox.manager.SandboxManager; -import io.agentscope.runtime.sandbox.manager.model.container.SandboxType; import io.agentscope.runtime.sandbox.manager.registry.RegisterSandbox; @RegisterSandbox( imageName = "YOUR-IMAGE-NAME", - sandboxType = SandboxType.CUSTOM, + sandboxType = "CustomSandboxType", securityLevel = "medium", timeout = 30, description = "YOUR Sandbox" @@ -199,7 +198,7 @@ public class CustomSandbox extends Sandbox { String userId, String sessionId, int timeout) { - super(managerApi, userId, sessionId, SandboxType.CUSTOM, timeout); + super(managerApi, userId, sessionId, "CustomSandboxType", timeout); } } ```