Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import com.google.gson.annotations.SerializedName;
import java.util.List;
import java.util.Map;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
Expand Down Expand Up @@ -82,6 +83,13 @@ public static class PerToolConfig {

@SerializedName("permission_policy")
private PermissionPolicy permissionPolicy;

/**
* Per-tool parameters, e.g. {@code knowledge_application_id} for the {@code
* search_knowledgebases} knowledge-retrieval tool. Serialized only when set.
*/
@SerializedName("params")
private Map<String, Object> params;
}
}

Expand Down
127 changes: 127 additions & 0 deletions src/main/java/com/alibaba/dashscope/agentstudio/model/Mount.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package com.alibaba.dashscope.agentstudio.model;

import java.util.LinkedHashMap;
import java.util.List;

/**
* Typed session-resource mount descriptor (create-time input on POST /sessions).
*
* <p>Extends {@link LinkedHashMap} so it fits the existing {@code List<Map<String, Object>>}
* resources parameter without conversion:
*
* <pre>{@code
* List<Map<String, Object>> resources = new ArrayList<>();
* resources.add(Mount.oss("cn-beijing", "my-bucket", "datasets/", "/data")
* .readOnly());
* resources.add(Mount.bailianMemory("lib_xxx", "customer_001")
* .projectIds(Arrays.asList("fact_rule_1"))
* .profileSchema("schema_xxx"));
* }</pre>
*/
public class Mount extends LinkedHashMap<String, Object> {

private static final long serialVersionUID = 1L;

public static Mount file(String fileId, String mountPath) {
return new Mount().putType("file").fileId(fileId).mountPath(mountPath);
}

public static Mount memoryStore(String memoryStoreId) {
return new Mount().putType("memory_store").memoryStoreId(memoryStoreId);
}

public static Mount bailianMemory(String memoryStoreId, String entityId) {
return new Mount()
.putType("memory_store")
.provider("agentstudio_memory")
.memoryStoreId(memoryStoreId)
.entityId(entityId);
}

public static Mount oss(String region, String bucket, String ossPath, String mountPath) {
return new Mount()
.putType("oss")
.region(region)
.bucket(bucket)
.ossPath(ossPath)
.mountPath(mountPath);
}

public Mount putType(String type) {
put("type", type);
return this;
}

public Mount fileId(String fileId) {
put("file_id", fileId);
return this;
}

public Mount mountPath(String mountPath) {
put("mount_path", mountPath);
return this;
}

public Mount memoryStoreId(String memoryStoreId) {
put("memory_store_id", memoryStoreId);
return this;
}

public Mount provider(String provider) {
put("provider", provider);
return this;
}

public Mount entityId(String entityId) {
put("entity_id", entityId);
return this;
}

public Mount projectIds(List<String> projectIds) {
put("project_ids", projectIds);
return this;
}

public Mount profileSchema(String profileSchema) {
put("profile_schema", profileSchema);
return this;
}

public Mount description(String description) {
put("description", description);
return this;
}

public Mount access(String access) {
put("access", access);
return this;
}

public Mount readOnly() {
return access("read_only");
}

public Mount readWrite() {
return access("read_write");
}

public Mount instructions(String instructions) {
put("instructions", instructions);
return this;
}

public Mount region(String region) {
put("region", region);
return this;
}

public Mount bucket(String bucket) {
put("bucket", bucket);
return this;
}

public Mount ossPath(String ossPath) {
put("oss_path", ossPath);
return this;
}
}
45 changes: 45 additions & 0 deletions src/main/java/com/alibaba/dashscope/agentstudio/model/Session.java
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,15 @@ public static class StopReason {
private List<String> pendingCallIds;
}

/**
* A resource mounted into a session. Fields depend on {@code type}: {@code file} carries {@code
* fileId}/{@code mountPath}; {@code memory_store} carries {@code memoryStoreId}/{@code
* access}/{@code instructions}/{@code name}/{@code description} and — when {@code provider} is
* {@code agentstudio_memory} — {@code entityId}/{@code projectIds}/{@code profileSchema} (Bailian
* memory mounts carry no mount path); {@code oss} carries {@code region}/{@code bucket}/{@code
* ossPath}/{@code mountPath}/{@code access}. {@code provider} values are not validated so
* historical responses stay readable. Memory and OSS mounts are create-only.
*/
@Data
@EqualsAndHashCode(callSuper = true)
public static class SessionResource extends FlattenResultBase {
Expand All @@ -126,9 +135,45 @@ public static class SessionResource extends FlattenResultBase {
@SerializedName("file_id")
private String fileId;

@SerializedName("memory_store_id")
private String memoryStoreId;

@SerializedName("provider")
private String provider;

@SerializedName("entity_id")
private String entityId;

@SerializedName("project_ids")
private List<String> projectIds;

@SerializedName("profile_schema")
private String profileSchema;

@SerializedName("access")
private String access;

@SerializedName("instructions")
private String instructions;

@SerializedName("name")
private String name;

@SerializedName("description")
private String description;

@SerializedName("mount_path")
private String mountPath;

@SerializedName("region")
private String region;

@SerializedName("bucket")
private String bucket;

@SerializedName("oss_path")
private String ossPath;

@SerializedName("created_at")
private String createdAt;

Expand Down
109 changes: 109 additions & 0 deletions src/test/java/com/alibaba/dashscope/TestAgentStudioProtocol.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.alibaba.dashscope.agentstudio.message.ContentBlock;
import com.alibaba.dashscope.agentstudio.message.Message;
import com.alibaba.dashscope.agentstudio.model.Configs;
import com.alibaba.dashscope.agentstudio.model.Mount;
import com.alibaba.dashscope.agentstudio.model.Session;
import com.alibaba.dashscope.agentstudio.param.AgentCreateParam;
import com.alibaba.dashscope.agentstudio.param.SessionEventListParam;
Expand All @@ -20,6 +21,7 @@
import com.google.gson.JsonObject;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.mockwebserver.MockResponse;
Expand Down Expand Up @@ -212,4 +214,111 @@ void testPermissionPolicySerializedInToolConfig() {
assertEquals(
"always_ask", dcJson.getAsJsonObject("permission_policy").get("type").getAsString());
}

@Test
void testMountUsesWireKeys() {
Mount bailian =
Mount.bailianMemory("0123", "customer_001")
.projectIds(Arrays.asList("fact_rule_1"))
.profileSchema("schema_demo")
.description("ctx")
.readOnly();
assertEquals(
new HashSet<>(
Arrays.asList(
"type",
"provider",
"memory_store_id",
"entity_id",
"project_ids",
"profile_schema",
"description",
"access")),
bailian.keySet());
assertEquals("agentstudio_memory", bailian.get("provider"));
assertEquals("read_only", bailian.get("access"));

Mount oss = Mount.oss("cn-beijing", "bkt", "datasets/", "/data").readOnly();
assertEquals(
new HashSet<>(
Arrays.asList("type", "region", "bucket", "oss_path", "mount_path", "access")),
oss.keySet());
}

@Test
void testToolConfigParamsSerialized() {
Configs.ToolConfig.PerToolConfig perTool = new Configs.ToolConfig.PerToolConfig();
perTool.setName("search_knowledgebases");
perTool.setEnabled(true);
java.util.HashMap<String, Object> params = new java.util.HashMap<>();
params.put("knowledge_application_id", "aid_demo");
perTool.setParams(params);

Configs.ToolConfig tool = new Configs.ToolConfig();
tool.setType("builtin_toolkit");
tool.setConfigs(Arrays.asList(perTool));

JsonObject body =
AgentCreateParam.builder()
.name("rag")
.model("qwen-max")
.tools(Arrays.asList(tool))
.build()
.getHttpBody();
JsonObject perToolJson =
body.getAsJsonArray("tools")
.get(0)
.getAsJsonObject()
.getAsJsonArray("configs")
.get(0)
.getAsJsonObject();
assertEquals(
"aid_demo",
perToolJson.getAsJsonObject("params").get("knowledge_application_id").getAsString());

// Read back: Agent.tools keeps params, so read-modify-write resubmits them.
Configs.ToolConfig parsed =
GSON.fromJson(body.getAsJsonArray("tools").get(0), Configs.ToolConfig.class);
assertEquals(
"aid_demo", parsed.getConfigs().get(0).getParams().get("knowledge_application_id"));
}

@Test
void testSessionResourceParsesMountFields() {
Session.SessionResource memory =
GSON.fromJson(
"{\"id\":\"mount_1\",\"type\":\"memory_store\",\"memory_store_id\":\"0123\","
+ "\"provider\":\"agentstudio_memory\",\"entity_id\":\"customer_001\","
+ "\"project_ids\":[\"fact_rule_1\"],\"profile_schema\":\"schema_demo\","
+ "\"description\":\"ctx\",\"access\":\"read_only\"}",
Session.SessionResource.class);
assertEquals("agentstudio_memory", memory.getProvider());
assertEquals("customer_001", memory.getEntityId());
assertEquals(Arrays.asList("fact_rule_1"), memory.getProjectIds());
assertEquals("schema_demo", memory.getProfileSchema());
assertEquals("read_only", memory.getAccess());
assertNull(memory.getMountPath());

Session.SessionResource oss =
GSON.fromJson(
"{\"id\":\"sesrsc_1\",\"type\":\"oss\",\"region\":\"cn-beijing\","
+ "\"bucket\":\"agentstudio-ma-oss-mnt\",\"oss_path\":\"datasets/\","
+ "\"mount_path\":\"/data\",\"access\":\"read_only\"}",
Session.SessionResource.class);
assertEquals("cn-beijing", oss.getRegion());
assertEquals("agentstudio-ma-oss-mnt", oss.getBucket());
assertEquals("datasets/", oss.getOssPath());
assertEquals("/data", oss.getMountPath());

// Historical built-in mounts predate provider; those fields stay null.
Session.SessionResource legacy =
GSON.fromJson(
"{\"id\":\"mount_2\",\"type\":\"memory_store\",\"memory_store_id\":\"memstore_1\","
+ "\"mount_path\":\"/uploads/memory\"}",
Session.SessionResource.class);
assertNull(legacy.getProvider());
assertNull(legacy.getEntityId());
assertEquals("memstore_1", legacy.getMemoryStoreId());
assertEquals("/uploads/memory", legacy.getMountPath());
}
}
Loading