From a8a3ae6be8c0239f79293996b89cd9a01262279e Mon Sep 17 00:00:00 2001 From: yuluo-yx Date: Fri, 26 Jun 2026 22:26:59 +0800 Subject: [PATCH 1/2] feat: add workspace interface Signed-off-by: yuluo-yx --- .../agentscope/core/workspace/Workspace.java | 147 ++++++++++++++++++ .../core/workspace/package-info.java | 7 +- 2 files changed, 150 insertions(+), 4 deletions(-) create mode 100644 agentscope-core/src/main/java/io/agentscope/core/workspace/Workspace.java diff --git a/agentscope-core/src/main/java/io/agentscope/core/workspace/Workspace.java b/agentscope-core/src/main/java/io/agentscope/core/workspace/Workspace.java new file mode 100644 index 0000000000..e69a7b18b5 --- /dev/null +++ b/agentscope-core/src/main/java/io/agentscope/core/workspace/Workspace.java @@ -0,0 +1,147 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 + * + * http://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.core.workspace; + +import io.agentscope.core.message.DataBlock; +import io.agentscope.core.skill.AgentSkill; +import io.agentscope.core.tool.mcp.McpClientWrapper; +import java.util.Optional; +import java.util.Set; +import reactor.core.publisher.Mono; + +/** + * @author yuluo + * @author yuluo + */ +public interface Workspace extends Sandbox, OffLoader, Mcp, SkillCatalog { + + default String workspaceId() { + return sandboxId(); + } + + String workspaceRoot(); + + String getInstructions(); +} + +/** Contract for the workspace sandbox lifecycle. */ +interface Sandbox extends AutoCloseable { + + /** + * Gets the sandbox id. + * + * @return the current sandbox id. + */ + String sandboxId(); + + /** + * Checks whether the workspace is still alive. + * + * @return true when the workspace is alive, false otherwise. + */ + boolean isAlive(); + + /** Initializes the workspace sandbox. */ + void init(); + + /** Resets the workspace sandbox. */ + boolean reset(); +} + +/** Persists data that should be moved out of the active model context. */ +interface OffLoader { + + String offloadContext(); + + String offloadToolResult(); + + DataBlock offloadMessage(); +} + +/** Contract for managing MCP clients available in a workspace. */ +interface Mcp { + + /** + * Lists the names of MCP clients registered in the current workspace. + * + * @return the MCP client names. + */ + Set listMcpClients(); + + /** + * Looks up an MCP client by name. + * + * @param mcpClientName the MCP client name. + * @return the matching MCP client, or empty when it does not exist. + */ + Optional getMcpClient(String mcpClientName); + + /** + * Registers an MCP client and returns it after the asynchronous initialization chain + * completes. + * + * @param mcpClient the MCP client wrapper. + * @return the registered MCP client. + */ + Mono addMcpClient(McpClientWrapper mcpClient); + + /** + * Removes the specified MCP client and returns the removed client. + * + * @param mcpClientName the MCP client name. + * @return the removed MCP client, or an empty Mono when the client does not exist. + */ + Mono removeMcpClient(String mcpClientName); +} + +/** Contract for managing skills available in a workspace. */ +interface SkillCatalog { + + /** + * Lists the skill ids registered in the current workspace. + * + * @return the registered skill ids. + */ + Set listSkills(); + + /** + * Looks up a skill by id. + * + * @param skillId the skill id. + * @return the matching skill, or empty when it does not exist. + */ + Optional getSkill(String skillId); + + /** + * Registers a skill and returns the actual registered skill. + * + * @param skill the skill instance. + * @return the registered skill. + */ + AgentSkill addSkill(AgentSkill skill); + + /** + * Removes the specified skill and returns the removed skill. + * + * @param skillId the skill id. + * @return the removed skill, or empty when the skill does not exist. + */ + Optional removeSkill(String skillId); +} diff --git a/agentscope-core/src/main/java/io/agentscope/core/workspace/package-info.java b/agentscope-core/src/main/java/io/agentscope/core/workspace/package-info.java index 2e58ca2f7a..5f3599aa58 100644 --- a/agentscope-core/src/main/java/io/agentscope/core/workspace/package-info.java +++ b/agentscope-core/src/main/java/io/agentscope/core/workspace/package-info.java @@ -15,10 +15,9 @@ */ /** - * Agent execution environment abstraction for AgentScope Java. + * Agent execution environment abstractions for AgentScope Java. * - *

The package will host the {@code WorkspaceBase} contract (initialize, close, - * getInstructions, listTools, listSkills, offloadContext, offloadToolResult) - * and a {@code LocalWorkspace} default implementation. + *

This package hosts the {@code Workspace} contract, covering sandbox lifecycle, + * instructions, MCP clients, skill catalogs, and context offloading. */ package io.agentscope.core.workspace; From f8f0f2f1259a2ccf89053a234f974e8c62004b8a Mon Sep 17 00:00:00 2001 From: yuluo-yx Date: Fri, 26 Jun 2026 22:52:45 +0800 Subject: [PATCH 2/2] feat: add demo Signed-off-by: yuluo-yx --- .../core/workspace/AbstractWorkspace.java | 46 +++++++ .../agentscope/core/workspace/Workspace.java | 31 ++--- .../workspace/impl/local/LocalWorkSpace.java | 113 ++++++++++++++++++ 3 files changed, 176 insertions(+), 14 deletions(-) create mode 100644 agentscope-core/src/main/java/io/agentscope/core/workspace/AbstractWorkspace.java create mode 100644 agentscope-core/src/main/java/io/agentscope/core/workspace/impl/local/LocalWorkSpace.java diff --git a/agentscope-core/src/main/java/io/agentscope/core/workspace/AbstractWorkspace.java b/agentscope-core/src/main/java/io/agentscope/core/workspace/AbstractWorkspace.java new file mode 100644 index 0000000000..b1bc073a5f --- /dev/null +++ b/agentscope-core/src/main/java/io/agentscope/core/workspace/AbstractWorkspace.java @@ -0,0 +1,46 @@ +/* + * Copyright 2026-2027 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 + * + * http://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.core.workspace; + +import java.util.UUID; + +/** + * @author yuluo + * @author yuluo + */ + +public abstract class AbstractWorkspace implements Workspace { + + private static final String DEFAULT_HOME_DIR = "/workspace"; + + @Override + public String workspaceRoot() { + + return DEFAULT_HOME_DIR; + } + + @Override + public String sandboxId() { + + return uuid(); + } + + private static String uuid() { + + return UUID.randomUUID().toString().replace("-", ""); + } +} diff --git a/agentscope-core/src/main/java/io/agentscope/core/workspace/Workspace.java b/agentscope-core/src/main/java/io/agentscope/core/workspace/Workspace.java index e69a7b18b5..f406fbf543 100644 --- a/agentscope-core/src/main/java/io/agentscope/core/workspace/Workspace.java +++ b/agentscope-core/src/main/java/io/agentscope/core/workspace/Workspace.java @@ -1,20 +1,17 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 + * Copyright 2026-2027 the original author or authors. * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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 * - * 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. + * http://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.core.workspace; @@ -63,6 +60,12 @@ interface Sandbox extends AutoCloseable { /** Resets the workspace sandbox. */ boolean reset(); + + /** + * Closes the sandbox and releases any associated resources. + */ + @Override + void close(); } /** Persists data that should be moved out of the active model context. */ diff --git a/agentscope-core/src/main/java/io/agentscope/core/workspace/impl/local/LocalWorkSpace.java b/agentscope-core/src/main/java/io/agentscope/core/workspace/impl/local/LocalWorkSpace.java new file mode 100644 index 0000000000..4ebace6513 --- /dev/null +++ b/agentscope-core/src/main/java/io/agentscope/core/workspace/impl/local/LocalWorkSpace.java @@ -0,0 +1,113 @@ +/* + * Copyright 2026-2027 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 + * + * http://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.core.workspace.impl.local; + +import io.agentscope.core.message.DataBlock; +import io.agentscope.core.skill.AgentSkill; +import io.agentscope.core.tool.mcp.McpClientWrapper; +import io.agentscope.core.workspace.AbstractWorkspace; + +import java.util.Optional; +import java.util.Set; + +/** + * @author yuluo + * @author yuluo + */ + +public class LocalWorkSpace extends AbstractWorkspace { + + @Override + public String getInstructions() { + return ""; + } + + @Override + public Set listMcpClients() { + return Set.of(); + } + + @Override + public Optional getMcpClient(String mcpClientName) { + return Optional.empty(); + } + + @Override + public Mono addMcpClient(McpClientWrapper mcpClient) { + return null; + } + + @Override + public Mono removeMcpClient(String mcpClientName) { + return null; + } + + @Override + public String offloadContext() { + return ""; + } + + @Override + public String offloadToolResult() { + return ""; + } + + @Override + public DataBlock offloadMessage() { + return null; + } + + @Override + public boolean isAlive() { + return false; + } + + @Override + public void init() { + + } + + @Override + public boolean reset() { + return false; + } + + @Override + public void close() { + + } + + @Override + public Set listSkills() { + return Set.of(); + } + + @Override + public Optional getSkill(String skillId) { + return Optional.empty(); + } + + @Override + public AgentSkill addSkill(AgentSkill skill) { + return null; + } + + @Override + public Optional removeSkill(String skillId) { + return Optional.empty(); + } +}