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 @@ -37,6 +37,13 @@ public static final class SSEEventType {
public static final String SESSION_STATUS = "session_status";
public static final String ERROR = "error";
public static final String SESSION_UPDATED = "session_updated";
public static final String THREAD_CREATED = "thread_created";
public static final String THREAD_STATUS = "thread_status";
public static final String THREAD_MESSAGE_SENT = "thread_message_sent";
public static final String THREAD_MESSAGE_RECEIVED = "thread_message_received";
public static final String THREAD_CONTEXT_COMPACTED = "thread_context_compacted";
public static final String MODEL_REQUEST_START = "model_request_start";
public static final String MODEL_REQUEST_END = "model_request_end";
public static final String OUTCOME_EVALUATION = "outcome_evaluation";

private SSEEventType() {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ public class Message {
@SerializedName("session_thread_id")
private String sessionThreadId;

/** Thread this event belongs to; server sends it on all {@code thread_*} events. */
@SerializedName("thread_id")
private String threadId;

@SerializedName("code")
private String code;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import com.alibaba.dashscope.agentstudio.model.Configs.McpServerConfig;
import com.alibaba.dashscope.agentstudio.model.Configs.ModelConfig;
import com.alibaba.dashscope.agentstudio.model.Configs.MultiAgentConfig;
import com.alibaba.dashscope.agentstudio.model.Configs.SkillConfig;
import com.alibaba.dashscope.agentstudio.model.Configs.ToolConfig;
import com.alibaba.dashscope.common.FlattenResultBase;
Expand Down Expand Up @@ -42,6 +43,9 @@ public class Agent extends FlattenResultBase {
@SerializedName("mcp_servers")
private List<McpServerConfig> mcpServers;

@SerializedName("multiagent")
private MultiAgentConfig multiagent;

@SerializedName("version")
private Integer version;

Expand Down
29 changes: 29 additions & 0 deletions src/main/java/com/alibaba/dashscope/agentstudio/model/Configs.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,33 @@ public static class McpServerConfig {
@SerializedName("url")
private String url;
}

/**
* The {@code multiagent} field on an agent: {@code type} is currently always {@code
* "coordinator"}, {@code agents} is the roster of 1-20 entries (an empty list clears it).
*/
@Data
public static class MultiAgentConfig {
@SerializedName("type")
private String type;

@SerializedName("agents")
private List<RosterEntry> agents;

/**
* One roster entry: {@code type} is {@code "agent"} (reference another agent by {@code id} plus
* optional {@code version}) or {@code "self"} (a copy of the coordinator; at most one).
*/
@Data
public static class RosterEntry {
@SerializedName("type")
private String type;

@SerializedName("id")
private String id;

@SerializedName("version")
private Integer version;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
package com.alibaba.dashscope.agentstudio.param;

import com.alibaba.dashscope.agentstudio.model.Configs.McpServerConfig;
import com.alibaba.dashscope.agentstudio.model.Configs.MultiAgentConfig;
import com.alibaba.dashscope.agentstudio.model.Configs.SkillConfig;
import com.alibaba.dashscope.agentstudio.model.Configs.ToolConfig;
import com.alibaba.dashscope.base.FlattenHalfDuplexParamBase;
Expand All @@ -26,6 +27,7 @@ public class AgentCreateParam extends FlattenHalfDuplexParamBase {
@Default private List<ToolConfig> tools = null;
@Default private List<McpServerConfig> mcpServers = null;
@Default private List<SkillConfig> skills = null;
@Default private MultiAgentConfig multiagent = null;
@Default private Map<String, String> metadata = null;

@Override
Expand All @@ -50,6 +52,9 @@ public JsonObject getHttpBody() {
if (skills != null) {
body.add("skills", JsonUtils.toJsonElement(skills));
}
if (multiagent != null) {
body.add("multiagent", JsonUtils.toJsonElement(multiagent));
}
if (metadata != null && !metadata.isEmpty()) {
body.add("metadata", JsonUtils.toJsonElement(metadata));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
package com.alibaba.dashscope.agentstudio.param;

import com.alibaba.dashscope.agentstudio.model.Configs.McpServerConfig;
import com.alibaba.dashscope.agentstudio.model.Configs.MultiAgentConfig;
import com.alibaba.dashscope.agentstudio.model.Configs.SkillConfig;
import com.alibaba.dashscope.agentstudio.model.Configs.ToolConfig;
import com.alibaba.dashscope.base.FlattenHalfDuplexParamBase;
Expand Down Expand Up @@ -29,6 +30,7 @@ public class AgentUpdateParam extends FlattenHalfDuplexParamBase {
@Default private List<ToolConfig> tools = null;
@Default private List<McpServerConfig> mcpServers = null;
@Default private List<SkillConfig> skills = null;
@Default private MultiAgentConfig multiagent = null;
@Default private Map<String, String> metadata = null;

@Override
Expand Down Expand Up @@ -60,6 +62,9 @@ public JsonObject getHttpBody() {
if (skills != null) {
body.add("skills", JsonUtils.toJsonElement(skills));
}
if (multiagent != null) {
body.add("multiagent", JsonUtils.toJsonElement(multiagent));
}
if (metadata != null && !metadata.isEmpty()) {
body.add("metadata", JsonUtils.toJsonElement(metadata));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public class SessionCreateParam extends FlattenHalfDuplexParamBase {
@Default private String environmentId = null;
@Default private String title = null;
@Default private List<Map<String, Object>> resources = null;
@Default private List<String> vaultIds = null;
@Default private Map<String, String> metadata = null;

@Override
Expand All @@ -35,6 +36,9 @@ public JsonObject getHttpBody() {
if (resources != null && !resources.isEmpty()) {
body.add("resources", JsonUtils.toJsonElement(resources));
}
if (vaultIds != null && !vaultIds.isEmpty()) {
body.add("vault_ids", JsonUtils.toJsonElement(vaultIds));
}
if (metadata != null && !metadata.isEmpty()) {
body.add("metadata", JsonUtils.toJsonElement(metadata));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright (c) Alibaba, Inc. and its affiliates.
package com.alibaba.dashscope.agentstudio.resource;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Objects;

/**
* Binary content of a downloaded file.
*
* <p>Mirrors the Python SDK's {@code FileContent}: a thin wrapper over the raw bytes with a {@link
* #writeToFile(Path)} helper, so callers can do {@code
* client.files().download(fileId).writeToFile("output.txt")}.
*/
public final class FileContent {
private final byte[] data;

public FileContent(byte[] data) {
this.data = data != null ? data : new byte[0];
}

/** The raw file bytes. */
public byte[] getBytes() {
return data;
}

/** Number of bytes. */
public int length() {
return data.length;
}

/** Write the content to {@code path} (creating parent directories) and return it. */
public Path writeToFile(String path) throws IOException {
return writeToFile(Paths.get(path));
}

/** Write the content to {@code path} (creating parent directories) and return it. */
public Path writeToFile(Path path) throws IOException {
Objects.requireNonNull(path, "path");
if (path.getParent() != null) {
Files.createDirectories(path.getParent());
}
Files.write(path, data);
return path;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,61 @@ public AgentStudioDeletionStatus delete(
return AsyncHelper.joinAndUnwrap(deleteAsync(fileId, apiKey, headers));
}

/**
* Download a file's binary content.
*
* <p>Only files whose {@code downloadable} flag is true can be fetched; the service answers 403
* otherwise. Use {@link FileContent#writeToFile(String)} to persist the bytes to disk.
*/
public FileContent download(String fileId) {
return AsyncHelper.joinAndUnwrap(downloadAsync(fileId));
}

public CompletableFuture<FileContent> downloadAsync(String fileId) {
if (fileId == null || fileId.isEmpty()) {
return AsyncHelper.failedFuture(new InputRequiredException("fileId is required!"));
}
String key;
try {
key = ApiKey.getApiKey(this.apiKey);
} catch (Exception e) {
return AsyncHelper.failedFuture(e);
}
String resolvedBase = resolveUploadBaseUrl();
String url = resolvedBase + StringUtils.format("/files/%s/content", fileId);
Request request =
new Request.Builder().url(url).header("Authorization", "Bearer " + key).get().build();

CompletableFuture<FileContent> future = new CompletableFuture<>();
uploadClient
.newCall(request)
.enqueue(
new Callback() {
@Override
public void onFailure(Call call, IOException e) {
future.completeExceptionally(new ApiException(e));
}

@Override
public void onResponse(Call call, Response response) {
try (Response r = response) {
if (!r.isSuccessful()) {
String body = r.body() != null ? r.body().string() : "";
future.completeExceptionally(
new ApiException(
Status.builder().statusCode(r.code()).message(body).build()));
return;
}
byte[] bytes = r.body() != null ? r.body().bytes() : new byte[0];
future.complete(new FileContent(bytes));
} catch (Exception e) {
future.completeExceptionally(new ApiException(e));
}
}
});
return future;
}

public CompletableFuture<AgentStudioFile> uploadAsync(String filePath, String mimeType) {
if (filePath == null || filePath.isEmpty()) {
return AsyncHelper.failedFuture(new InputRequiredException("filePath is required!"));
Expand Down
Loading
Loading