add javadoc

This commit is contained in:
skyfire
2026-01-04 18:07:56 +08:00
parent 73848d3867
commit db9d5cb45d
62 changed files with 3395 additions and 91 deletions

View File

@@ -11,3 +11,4 @@
log/
target/
/docs/

View File

@@ -150,8 +150,8 @@ import com.alibaba.qwen.code.cli.protocol.message.control.CLIControlRequest;
import com.alibaba.qwen.code.cli.protocol.message.control.CLIControlResponse;
import com.alibaba.qwen.code.cli.protocol.data.AssistantContent;
import com.alibaba.qwen.code.cli.protocol.data.behavior.Behavior;
import com.alibaba.qwen.code.cli.session.event.SessionEventSimpleConsumers.AssistantMessageOutputType;
import com.alibaba.qwen.code.cli.utils.Timeout;
import java.util.List;
import java.util.concurrent.TimeUnit;
@@ -162,9 +162,9 @@ public class CustomEventHandlingExample {
@Override
public void onAssistantMessage(Session session, SDKAssistantMessage assistantMessage) {
String message = assistantMessage.getMessage().getContent().stream()
.findFirst()
.map(content -> content.getText())
.orElse("");
.findFirst()
.map(content -> content.getText())
.orElse("");
System.out.println("Assistant: " + message);
}
@@ -213,7 +213,7 @@ public class CustomEventHandlingExample {
public Behavior onPermissionRequest(Session session, CLIControlRequest<CLIControlPermissionRequest> permissionRequest) {
System.out.println("Permission request: " + permissionRequest.getRequest().getInput());
return new com.alibaba.qwen.code.cli.protocol.data.behavior.Allow()
.setUpdatedInput(permissionRequest.getRequest().getInput()); // Allow by default
.setUpdatedInput(permissionRequest.getRequest().getInput()); // Allow by default
}
@Override

View File

@@ -5,7 +5,7 @@
<groupId>com.alibaba</groupId>
<artifactId>qwencode-sdk</artifactId>
<packaging>jar</packaging>
<version>0.0.1</version>
<version>0.0.1-SNAPSHOT</version>
<name>qwencode-sdk</name>
<url>https://maven.apache.org</url>
<licenses>
@@ -202,8 +202,10 @@
<distributionManagement>
<snapshotRepository>
<id>central</id>
<url>https://central.sonatype.com/repository/maven-snapshots/</url>
<!-- <id>central</id>-->
<!-- <url>https://central.sonatype.com/repository/maven-snapshots/</url>-->
<id>snapshots</id>
<url>http://mvnrepo.alibaba-inc.com/mvn/snapshots</url>
</snapshotRepository>
</distributionManagement>
</project>

View File

@@ -2,13 +2,17 @@ package com.alibaba.qwen.code.cli;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import com.alibaba.fastjson2.JSON;
import com.alibaba.qwen.code.cli.protocol.data.AssistantUsage;
import com.alibaba.qwen.code.cli.protocol.data.AssistantContent;
import com.alibaba.qwen.code.cli.protocol.data.AssistantContent.TextAssistantContent;
import com.alibaba.qwen.code.cli.protocol.data.AssistantContent.ThingkingAssistantContent;
import com.alibaba.qwen.code.cli.protocol.data.AssistantContent.ToolResultAssistantContent;
import com.alibaba.qwen.code.cli.protocol.data.AssistantContent.ToolUseAssistantContent;
import com.alibaba.qwen.code.cli.protocol.data.behavior.Behavior.Operation;
import com.alibaba.qwen.code.cli.session.Session;
import com.alibaba.qwen.code.cli.session.event.AssistantContentConsumers;
import com.alibaba.qwen.code.cli.session.event.SessionEventSimpleConsumers;
import com.alibaba.qwen.code.cli.transport.Transport;
import com.alibaba.qwen.code.cli.transport.TransportOptions;
@@ -19,32 +23,77 @@ import com.alibaba.qwen.code.cli.utils.Timeout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Main entry point for interacting with the Qwen Code CLI. Provides static methods for simple queries and session management.
*/
public class QwenCodeCli {
private static final Logger log = LoggerFactory.getLogger(QwenCodeCli.class);
/**
* Sends a simple query to the Qwen Code CLI and returns a list of responses.
*
* @param prompt The input prompt to send to the CLI
* @return A list of strings representing the CLI's responses
*/
public static List<String> simpleQuery(String prompt) {
return simpleQuery(prompt, new TransportOptions());
}
/**
* Sends a simple query with custom transport options.
*
* @param prompt The input prompt to send to the CLI
* @param transportOptions Configuration options for the transport layer
* @return A list of strings representing the CLI's responses
*/
public static List<String> simpleQuery(String prompt, TransportOptions transportOptions) {
final List<String> response = new ArrayList<>();
MyConcurrentUtils.runAndWait(() -> simpleQuery(prompt, response::add), Timeout.TIMEOUT_30_MINUTES);
MyConcurrentUtils.runAndWait(() -> simpleQuery(prompt, transportOptions, new AssistantContentConsumers() {
@Override
public void onText(Session session, TextAssistantContent textAssistantContent) {
response.add(textAssistantContent.getText());
}
@Override
public void onThinking(Session session, ThingkingAssistantContent thingkingAssistantContent) {
response.add(thingkingAssistantContent.getThinking());
}
@Override
public void onToolUse(Session session, ToolUseAssistantContent toolUseAssistantContent) {
response.add(JSON.toJSONString(toolUseAssistantContent.getContentOfAssistant()));
}
@Override
public void onToolResult(Session session, ToolResultAssistantContent toolResultAssistantContent) {
response.add(JSON.toJSONString(toolResultAssistantContent));
}
public void onOtherContent(Session session, AssistantContent<?> other) {
response.add(JSON.toJSONString(other.getContentOfAssistant()));
}
@Override
public void onUsage(Session session, AssistantUsage assistantUsage) {
log.info("received usage {} of message {}", assistantUsage.getUsage(), assistantUsage.getMessageId());
}
}), Timeout.TIMEOUT_30_MINUTES);
return response;
}
public static void simpleQuery(String prompt, Consumer<String> messageConsumer) {
Session session = newSession(new TransportOptions());
/**
* Sends a query with custom content consumers.
*
* @param prompt The input prompt to send to the CLI
* @param transportOptions Configuration options for the transport layer
* @param assistantContentConsumers Consumers for handling different types of assistant content
*/
public static void simpleQuery(String prompt, TransportOptions transportOptions, AssistantContentConsumers assistantContentConsumers) {
Session session = newSession(transportOptions);
try {
session.sendPrompt(prompt, new SessionEventSimpleConsumers() {
@Override
public void onAssistantMessageIncludePartial(Session session, List<AssistantContent> assistantContents, AssistantMessageOutputType assistantMessageOutputType) {
messageConsumer.accept(assistantContents.stream()
.map(AssistantContent::getContent)
.map(content -> {
if (content instanceof String) {
return (String) content;
} else {
return JSON.toJSONString(content);
}
}).collect(Collectors.joining()));
}
}.setDefaultPermissionOperation(Operation.allow));
session.sendPrompt(prompt, new SessionEventSimpleConsumers()
.setDefaultPermissionOperation(Operation.allow)
.setBlockConsumer(assistantContentConsumers));
} catch (Exception e) {
throw new RuntimeException("sendPrompt error!", e);
} finally {
@@ -56,10 +105,21 @@ public class QwenCodeCli {
}
}
/**
* Creates a new session with default transport options.
*
* @return A new Session instance
*/
public static Session newSession() {
return newSession(new TransportOptions());
}
/**
* Creates a new session with custom transport options.
*
* @param transportOptions Configuration options for the transport layer
* @return A new Session instance
*/
public static Session newSession(TransportOptions transportOptions) {
Transport transport;
try {

View File

@@ -1,6 +1,93 @@
package com.alibaba.qwen.code.cli.protocol.data;
public interface AssistantContent {
import java.util.Map;
/**
* Represents content from the assistant in a Qwen Code session.
*
* @param <C> The type of content
*/
public interface AssistantContent<C> {
/**
* Gets the type of the assistant content.
*
* @return The type of the assistant content
*/
String getType();
Object getContent();
/**
* Gets the actual content from the assistant.
*
* @return The content from the assistant
*/
C getContentOfAssistant();
/**
* Gets the message ID associated with this content.
*
* @return The message ID
*/
String getMessageId();
/**
* Represents text content from the assistant.
*/
interface TextAssistantContent extends AssistantContent<String> {
/**
* Gets the text content.
*
* @return The text content
*/
String getText();
}
/**
* Represents thinking content from the assistant.
*/
interface ThingkingAssistantContent extends AssistantContent<String> {
/**
* Gets the thinking content.
*
* @return The thinking content
*/
String getThinking();
}
/**
* Represents tool use content from the assistant.
*/
interface ToolUseAssistantContent extends AssistantContent<Map<String, Object>> {
/**
* Gets the tool input.
*
* @return The tool input
*/
Map<String, Object> getInput();
}
/**
* Represents tool result content from the assistant.
*/
interface ToolResultAssistantContent extends AssistantContent<String> {
/**
* Gets whether the tool result indicates an error.
*
* @return Whether the tool result indicates an error
*/
Boolean getIsError();
/**
* Gets the tool result content.
*
* @return The tool result content
*/
String getContent();
/**
* Gets the tool use ID.
*
* @return The tool use ID
*/
String getToolUseId();
}
}

View File

@@ -0,0 +1,68 @@
package com.alibaba.qwen.code.cli.protocol.data;
import com.alibaba.fastjson2.JSON;
/**
* Represents usage information for an assistant message.
*/
public class AssistantUsage {
/**
* The ID of the message.
*/
String messageId;
/**
* The usage information.
*/
Usage usage;
/**
* Gets the message ID.
*
* @return The message ID
*/
public String getMessageId() {
return messageId;
}
/**
* Sets the message ID.
*
* @param messageId The message ID
*/
public void setMessageId(String messageId) {
this.messageId = messageId;
}
/**
* Gets the usage information.
*
* @return The usage information
*/
public Usage getUsage() {
return usage;
}
/**
* Sets the usage information.
*
* @param usage The usage information
*/
public void setUsage(Usage usage) {
this.usage = usage;
}
/**
* Constructs a new AssistantUsage instance.
*
* @param messageId The message ID
* @param usage The usage information
*/
public AssistantUsage(String messageId, Usage usage) {
this.messageId = messageId;
this.usage = usage;
}
public String toString() {
return JSON.toJSONString(this);
}
}

View File

@@ -2,36 +2,78 @@ package com.alibaba.qwen.code.cli.protocol.data;
import com.alibaba.fastjson2.annotation.JSONField;
/**
* Represents a permission denial from the CLI.
*/
public class CLIPermissionDenial {
/**
* The name of the denied tool.
*/
@JSONField(name = "tool_name")
private String toolName;
/**
* The ID of the denied tool use.
*/
@JSONField(name = "tool_use_id")
private String toolUseId;
/**
* The input for the denied tool.
*/
@JSONField(name = "tool_input")
private Object toolInput;
/**
* Gets the name of the denied tool.
*
* @return The name of the denied tool
*/
public String getToolName() {
return toolName;
}
/**
* Sets the name of the denied tool.
*
* @param toolName The name of the denied tool
*/
public void setToolName(String toolName) {
this.toolName = toolName;
}
/**
* Gets the ID of the denied tool use.
*
* @return The ID of the denied tool use
*/
public String getToolUseId() {
return toolUseId;
}
/**
* Sets the ID of the denied tool use.
*
* @param toolUseId The ID of the denied tool use
*/
public void setToolUseId(String toolUseId) {
this.toolUseId = toolUseId;
}
/**
* Gets the input for the denied tool.
*
* @return The input for the denied tool
*/
public Object getToolInput() {
return toolInput;
}
/**
* Sets the input for the denied tool.
*
* @param toolInput The input for the denied tool
*/
public void setToolInput(Object toolInput) {
this.toolInput = toolInput;
}

View File

@@ -2,58 +2,126 @@ package com.alibaba.qwen.code.cli.protocol.data;
import com.alibaba.fastjson2.annotation.JSONField;
/**
* Represents the capabilities of the Qwen Code CLI.
*/
public class Capabilities {
/**
* Whether the CLI can handle can_use_tool requests.
*/
@JSONField(name = "can_handle_can_use_tool")
boolean canHandleCanUseTool;
/**
* Whether the CLI can handle hook callbacks.
*/
@JSONField(name = "can_handle_hook_callback")
boolean canHandleHookCallback;
/**
* Whether the CLI can set permission mode.
*/
@JSONField(name = "can_set_permission_mode")
boolean canSetPermissionMode;
/**
* Whether the CLI can set the model.
*/
@JSONField(name = "can_set_model")
boolean canSetModel;
/**
* Whether the CLI can handle MCP messages.
*/
@JSONField(name = "can_handle_mcp_message")
boolean canHandleMcpMessage;
/**
* Checks if the CLI can handle can_use_tool requests.
*
* @return true if the CLI can handle can_use_tool requests, false otherwise
*/
public boolean isCanHandleCanUseTool() {
return canHandleCanUseTool;
}
/**
* Sets whether the CLI can handle can_use_tool requests.
*
* @param canHandleCanUseTool Whether the CLI can handle can_use_tool requests
*/
public void setCanHandleCanUseTool(boolean canHandleCanUseTool) {
this.canHandleCanUseTool = canHandleCanUseTool;
}
/**
* Checks if the CLI can handle hook callbacks.
*
* @return true if the CLI can handle hook callbacks, false otherwise
*/
public boolean isCanHandleHookCallback() {
return canHandleHookCallback;
}
/**
* Sets whether the CLI can handle hook callbacks.
*
* @param canHandleHookCallback Whether the CLI can handle hook callbacks
*/
public void setCanHandleHookCallback(boolean canHandleHookCallback) {
this.canHandleHookCallback = canHandleHookCallback;
}
/**
* Checks if the CLI can set permission mode.
*
* @return true if the CLI can set permission mode, false otherwise
*/
public boolean isCanSetPermissionMode() {
return canSetPermissionMode;
}
/**
* Sets whether the CLI can set permission mode.
*
* @param canSetPermissionMode Whether the CLI can set permission mode
*/
public void setCanSetPermissionMode(boolean canSetPermissionMode) {
this.canSetPermissionMode = canSetPermissionMode;
}
/**
* Checks if the CLI can set the model.
*
* @return true if the CLI can set the model, false otherwise
*/
public boolean isCanSetModel() {
return canSetModel;
}
/**
* Sets whether the CLI can set the model.
*
* @param canSetModel Whether the CLI can set the model
*/
public void setCanSetModel(boolean canSetModel) {
this.canSetModel = canSetModel;
}
/**
* Checks if the CLI can handle MCP messages.
*
* @return true if the CLI can handle MCP messages, false otherwise
*/
public boolean isCanHandleMcpMessage() {
return canHandleMcpMessage;
}
/**
* Sets whether the CLI can handle MCP messages.
*
* @param canHandleMcpMessage Whether the CLI can handle MCP messages
*/
public void setCanHandleMcpMessage(boolean canHandleMcpMessage) {
this.canHandleMcpMessage = canHandleMcpMessage;
}

View File

@@ -2,64 +2,141 @@ package com.alibaba.qwen.code.cli.protocol.data;
import com.alibaba.fastjson2.annotation.JSONField;
/**
* Extends the Usage class with additional usage information.
*/
public class ExtendedUsage extends Usage {
/**
* Server tool use information.
*/
@JSONField(name = "server_tool_use")
private ServerToolUse serverToolUse;
/**
* Service tier information.
*/
@JSONField(name = "service_tier")
private String serviceTier;
/**
* Cache creation information.
*/
@JSONField(name = "cache_creation")
private CacheCreation cacheCreation;
/**
* Gets the server tool use information.
*
* @return The server tool use information
*/
public ServerToolUse getServerToolUse() {
return serverToolUse;
}
/**
* Sets the server tool use information.
*
* @param serverToolUse The server tool use information
*/
public void setServerToolUse(ServerToolUse serverToolUse) {
this.serverToolUse = serverToolUse;
}
/**
* Gets the service tier information.
*
* @return The service tier information
*/
public String getServiceTier() {
return serviceTier;
}
/**
* Sets the service tier information.
*
* @param serviceTier The service tier information
*/
public void setServiceTier(String serviceTier) {
this.serviceTier = serviceTier;
}
/**
* Gets the cache creation information.
*
* @return The cache creation information
*/
public CacheCreation getCacheCreation() {
return cacheCreation;
}
/**
* Sets the cache creation information.
*
* @param cacheCreation The cache creation information
*/
public void setCacheCreation(CacheCreation cacheCreation) {
this.cacheCreation = cacheCreation;
}
/**
* Represents server tool use information.
*/
public static class ServerToolUse {
/**
* Number of web search requests.
*/
@JSONField(name = "web_search_requests")
private int webSearchRequests;
}
/**
* Represents cache creation information.
*/
public static class CacheCreation {
/**
* Number of ephemeral 1-hour input tokens.
*/
@JSONField(name = "ephemeral_1h_input_tokens")
private int ephemeral1hInputTokens;
/**
* Number of ephemeral 5-minute input tokens.
*/
@JSONField(name = "ephemeral_5m_input_tokens")
private int ephemeral5mInputTokens;
/**
* Gets the number of ephemeral 1-hour input tokens.
*
* @return The number of ephemeral 1-hour input tokens
*/
public int getEphemeral1hInputTokens() {
return ephemeral1hInputTokens;
}
/**
* Sets the number of ephemeral 1-hour input tokens.
*
* @param ephemeral1hInputTokens The number of ephemeral 1-hour input tokens
*/
public void setEphemeral1hInputTokens(int ephemeral1hInputTokens) {
this.ephemeral1hInputTokens = ephemeral1hInputTokens;
}
/**
* Gets the number of ephemeral 5-minute input tokens.
*
* @return The number of ephemeral 5-minute input tokens
*/
public int getEphemeral5mInputTokens() {
return ephemeral5mInputTokens;
}
/**
* Sets the number of ephemeral 5-minute input tokens.
*
* @param ephemeral5mInputTokens The number of ephemeral 5-minute input tokens
*/
public void setEphemeral5mInputTokens(int ephemeral5mInputTokens) {
this.ephemeral5mInputTokens = ephemeral5mInputTokens;
}

View File

@@ -1,39 +1,94 @@
package com.alibaba.qwen.code.cli.protocol.data;
/**
* Configuration for initializing the CLI.
*/
public class InitializeConfig {
/**
* Hooks configuration.
*/
String hooks;
/**
* SDK MCP servers configuration.
*/
String sdkMcpServers;
/**
* MCP servers configuration.
*/
String mcpServers;
/**
* Agents configuration.
*/
String agents;
/**
* Gets the hooks configuration.
*
* @return The hooks configuration
*/
public String getHooks() {
return hooks;
}
/**
* Sets the hooks configuration.
*
* @param hooks The hooks configuration
*/
public void setHooks(String hooks) {
this.hooks = hooks;
}
/**
* Gets the SDK MCP servers configuration.
*
* @return The SDK MCP servers configuration
*/
public String getSdkMcpServers() {
return sdkMcpServers;
}
/**
* Sets the SDK MCP servers configuration.
*
* @param sdkMcpServers The SDK MCP servers configuration
*/
public void setSdkMcpServers(String sdkMcpServers) {
this.sdkMcpServers = sdkMcpServers;
}
/**
* Gets the MCP servers configuration.
*
* @return The MCP servers configuration
*/
public String getMcpServers() {
return mcpServers;
}
/**
* Sets the MCP servers configuration.
*
* @param mcpServers The MCP servers configuration
*/
public void setMcpServers(String mcpServers) {
this.mcpServers = mcpServers;
}
/**
* Gets the agents configuration.
*
* @return The agents configuration
*/
public String getAgents() {
return agents;
}
/**
* Sets the agents configuration.
*
* @param agents The agents configuration
*/
public void setAgents(String agents) {
this.agents = agents;
}

View File

@@ -1,57 +1,138 @@
package com.alibaba.qwen.code.cli.protocol.data;
/**
* Represents usage information for a specific model.
*/
public class ModelUsage {
/**
* Number of input tokens.
*/
private int inputTokens;
/**
* Number of output tokens.
*/
private int outputTokens;
/**
* Number of cache read input tokens.
*/
private int cacheReadInputTokens;
/**
* Number of cache creation input tokens.
*/
private int cacheCreationInputTokens;
/**
* Number of web search requests.
*/
private int webSearchRequests;
/**
* Context window size.
*/
private int contextWindow;
/**
* Gets the number of input tokens.
*
* @return The number of input tokens
*/
public int getInputTokens() {
return inputTokens;
}
/**
* Sets the number of input tokens.
*
* @param inputTokens The number of input tokens
*/
public void setInputTokens(int inputTokens) {
this.inputTokens = inputTokens;
}
/**
* Gets the number of output tokens.
*
* @return The number of output tokens
*/
public int getOutputTokens() {
return outputTokens;
}
/**
* Sets the number of output tokens.
*
* @param outputTokens The number of output tokens
*/
public void setOutputTokens(int outputTokens) {
this.outputTokens = outputTokens;
}
/**
* Gets the number of cache read input tokens.
*
* @return The number of cache read input tokens
*/
public int getCacheReadInputTokens() {
return cacheReadInputTokens;
}
/**
* Sets the number of cache read input tokens.
*
* @param cacheReadInputTokens The number of cache read input tokens
*/
public void setCacheReadInputTokens(int cacheReadInputTokens) {
this.cacheReadInputTokens = cacheReadInputTokens;
}
/**
* Gets the number of cache creation input tokens.
*
* @return The number of cache creation input tokens
*/
public int getCacheCreationInputTokens() {
return cacheCreationInputTokens;
}
/**
* Sets the number of cache creation input tokens.
*
* @param cacheCreationInputTokens The number of cache creation input tokens
*/
public void setCacheCreationInputTokens(int cacheCreationInputTokens) {
this.cacheCreationInputTokens = cacheCreationInputTokens;
}
/**
* Gets the number of web search requests.
*
* @return The number of web search requests
*/
public int getWebSearchRequests() {
return webSearchRequests;
}
/**
* Sets the number of web search requests.
*
* @param webSearchRequests The number of web search requests
*/
public void setWebSearchRequests(int webSearchRequests) {
this.webSearchRequests = webSearchRequests;
}
/**
* Gets the context window size.
*
* @return The context window size
*/
public int getContextWindow() {
return contextWindow;
}
/**
* Sets the context window size.
*
* @param contextWindow The context window size
*/
public void setContextWindow(int contextWindow) {
this.contextWindow = contextWindow;
}

View File

@@ -1,9 +1,24 @@
package com.alibaba.qwen.code.cli.protocol.data;
/**
* Represents different permission modes for the CLI.
*/
public enum PermissionMode {
/**
* Default permission mode.
*/
DEFAULT("default"),
/**
* Plan permission mode.
*/
PLAN("plan"),
/**
* Auto-edit permission mode.
*/
AUTO_EDIT("auto-edit"),
/**
* YOLO permission mode.
*/
YOLO("yolo");
private final String value;
@@ -12,10 +27,21 @@ public enum PermissionMode {
this.value = value;
}
/**
* Gets the string value of the permission mode.
*
* @return The string value of the permission mode
*/
public String getValue() {
return value;
}
/**
* Gets the permission mode from its string value.
*
* @param value The string value
* @return The corresponding permission mode
*/
public static PermissionMode fromValue(String value) {
for (PermissionMode mode : PermissionMode.values()) {
if (mode.value.equals(value)) {

View File

@@ -1,56 +1,129 @@
package com.alibaba.qwen.code.cli.protocol.data;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.annotation.JSONField;
/**
* Represents usage information for a message.
*/
public class Usage {
/**
* Number of input tokens.
*/
@JSONField(name = "input_tokens")
private Integer inputTokens;
/**
* Number of output tokens.
*/
@JSONField(name = "output_tokens")
private Integer outputTokens;
/**
* Number of cache creation input tokens.
*/
@JSONField(name = "cache_creation_input_tokens")
private Integer cacheCreationInputTokens;
/**
* Number of cache read input tokens.
*/
@JSONField(name = "cache_read_input_tokens")
private Integer cacheReadInputTokens;
/**
* Total number of tokens.
*/
@JSONField(name = "total_tokens")
private Integer totalTokens;
/**
* Gets the number of input tokens.
*
* @return The number of input tokens
*/
public Integer getInputTokens() {
return inputTokens;
}
/**
* Sets the number of input tokens.
*
* @param inputTokens The number of input tokens
*/
public void setInputTokens(Integer inputTokens) {
this.inputTokens = inputTokens;
}
/**
* Gets the number of output tokens.
*
* @return The number of output tokens
*/
public Integer getOutputTokens() {
return outputTokens;
}
/**
* Sets the number of output tokens.
*
* @param outputTokens The number of output tokens
*/
public void setOutputTokens(Integer outputTokens) {
this.outputTokens = outputTokens;
}
/**
* Gets the number of cache creation input tokens.
*
* @return The number of cache creation input tokens
*/
public Integer getCacheCreationInputTokens() {
return cacheCreationInputTokens;
}
/**
* Sets the number of cache creation input tokens.
*
* @param cacheCreationInputTokens The number of cache creation input tokens
*/
public void setCacheCreationInputTokens(Integer cacheCreationInputTokens) {
this.cacheCreationInputTokens = cacheCreationInputTokens;
}
/**
* Gets the number of cache read input tokens.
*
* @return The number of cache read input tokens
*/
public Integer getCacheReadInputTokens() {
return cacheReadInputTokens;
}
/**
* Sets the number of cache read input tokens.
*
* @param cacheReadInputTokens The number of cache read input tokens
*/
public void setCacheReadInputTokens(Integer cacheReadInputTokens) {
this.cacheReadInputTokens = cacheReadInputTokens;
}
/**
* Gets the total number of tokens.
*
* @return The total number of tokens
*/
public Integer getTotalTokens() {
return totalTokens;
}
/**
* Sets the total number of tokens.
*
* @param totalTokens The total number of tokens
*/
public void setTotalTokens(Integer totalTokens) {
this.totalTokens = totalTokens;
}
public String toString() {
return JSON.toJSONString(this);
}
}

View File

@@ -4,18 +4,38 @@ import java.util.Map;
import com.alibaba.fastjson2.annotation.JSONType;
/**
* Represents an allow behavior that permits an operation.
*/
@JSONType(typeKey = "operation", typeName = "allow")
public class Allow extends Behavior {
/**
* Creates a new Allow instance and sets the behavior to allow.
*/
public Allow() {
super();
this.behavior = Operation.allow;
}
/**
* Updated input for the operation.
*/
Map<String, Object> updatedInput;
/**
* Gets the updated input.
*
* @return The updated input
*/
public Map<String, Object> getUpdatedInput() {
return updatedInput;
}
/**
* Sets the updated input.
*
* @param updatedInput The updated input
* @return This instance for method chaining
*/
public Allow setUpdatedInput(Map<String, Object> updatedInput) {
this.updatedInput = updatedInput;
return this;

View File

@@ -2,23 +2,53 @@ package com.alibaba.qwen.code.cli.protocol.data.behavior;
import com.alibaba.fastjson2.annotation.JSONType;
/**
* Base class for behavior objects that define how the CLI should handle requests.
*/
@JSONType(typeKey = "operation", typeName = "Behavior", seeAlso = {Allow.class, Deny.class})
public class Behavior {
/**
* The behavior operation (allow or deny).
*/
Operation behavior;
/**
* Gets the behavior operation.
*
* @return The behavior operation
*/
public Operation getBehavior() {
return behavior;
}
/**
* Sets the behavior operation.
*
* @param behavior The behavior operation
*/
public void setBehavior(Operation behavior) {
this.behavior = behavior;
}
/**
* Represents the type of operation.
*/
public enum Operation {
/**
* Allow the operation.
*/
allow,
/**
* Deny the operation.
*/
deny
}
/**
* Gets the default behavior (deny with message).
*
* @return The default behavior
*/
public static Behavior defaultBehavior() {
return new Deny().setMessage("Default Behavior Permission denied");
}

View File

@@ -2,19 +2,39 @@ package com.alibaba.qwen.code.cli.protocol.data.behavior;
import com.alibaba.fastjson2.annotation.JSONType;
/**
* Represents a deny behavior that rejects an operation.
*/
@JSONType(typeKey = "operation", typeName = "deny")
public class Deny extends Behavior {
/**
* Creates a new Deny instance and sets the behavior to deny.
*/
public Deny() {
super();
this.behavior = Operation.deny;
}
/**
* The message explaining why the operation was denied.
*/
String message;
/**
* Gets the denial message.
*
* @return The denial message
*/
public String getMessage() {
return message;
}
/**
* Sets the denial message.
*
* @param message The denial message
* @return This instance for method chaining
*/
public Deny setMessage(String message) {
this.message = message;
return this;

View File

@@ -1,5 +1,20 @@
package com.alibaba.qwen.code.cli.protocol.message;
/**
* Represents a message in the Qwen Code protocol.
*/
public interface Message {
/**
* Gets the type of the message.
*
* @return The type of the message
*/
String getType();
/**
* Gets the ID of the message.
*
* @return The ID of the message
*/
String getMessageId();
}

View File

@@ -1,12 +1,25 @@
package com.alibaba.qwen.code.cli.protocol.message;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.annotation.JSONField;
import com.alibaba.fastjson2.annotation.JSONType;
/**
* Base class for messages in the Qwen Code protocol.
*/
@JSONType(alphabetic = false, typeKey = "type", typeName = "MessageBase")
public class MessageBase implements Message{
/**
* The type of the message.
*/
protected String type;
/**
* The ID of the message.
*/
@JSONField(name = "message_id")
protected String messageId;
public String toString() {
return JSON.toJSONString(this);
}
@@ -16,7 +29,26 @@ public class MessageBase implements Message{
return type;
}
/**
* Sets the type of the message.
*
* @param type The type of the message
*/
public void setType(String type) {
this.type = type;
}
@Override
public String getMessageId() {
return messageId;
}
/**
* Sets the ID of the message.
*
* @param messageId The ID of the message
*/
public void setMessageId(String messageId) {
this.messageId = messageId;
}
}

View File

@@ -9,141 +9,319 @@ import com.alibaba.qwen.code.cli.protocol.data.CLIPermissionDenial;
import com.alibaba.qwen.code.cli.protocol.data.ExtendedUsage;
import com.alibaba.qwen.code.cli.protocol.data.Usage;
/**
* Represents a result message from the SDK.
*/
@JSONType(typeKey = "type", typeName = "result")
public class SDKResultMessage extends MessageBase {
/**
* The subtype of the result.
*/
private String subtype; // 'error_max_turns' | 'error_during_execution'
/**
* The UUID of the message.
*/
private String uuid;
/**
* The session ID.
*/
@JSONField(name = "session_id")
private String sessionId;
/**
* Whether the result represents an error.
*/
@JSONField(name = "is_error")
private boolean isError = true;
/**
* Duration in milliseconds.
*/
@JSONField(name = "duration_ms")
private Long durationMs;
/**
* API duration in milliseconds.
*/
@JSONField(name = "duration_api_ms")
private Long durationApiMs;
/**
* Number of turns.
*/
@JSONField(name = "num_turns")
private Integer numTurns;
/**
* Usage information.
*/
private ExtendedUsage usage;
/**
* Model usage information.
*/
private Map<String, Usage> modelUsage;
/**
* List of permission denials.
*/
@JSONField(name = "permission_denials")
private List<CLIPermissionDenial> permissionDenials;
/**
* Error information.
*/
private Error error;
/**
* Creates a new SDKResultMessage instance and sets the type to "result".
*/
public SDKResultMessage() {
super();
this.type = "result";
}
/**
* Gets the subtype of the result.
*
* @return The subtype of the result
*/
public String getSubtype() {
return subtype;
}
/**
* Sets the subtype of the result.
*
* @param subtype The subtype of the result
*/
public void setSubtype(String subtype) {
this.subtype = subtype;
}
/**
* Gets the UUID of the message.
*
* @return The UUID of the message
*/
public String getUuid() {
return uuid;
}
/**
* Sets the UUID of the message.
*
* @param uuid The UUID of the message
*/
public void setUuid(String uuid) {
this.uuid = uuid;
}
/**
* Gets the session ID.
*
* @return The session ID
*/
public String getSessionId() {
return sessionId;
}
/**
* Sets the session ID.
*
* @param sessionId The session ID
*/
public void setSessionId(String sessionId) {
this.sessionId = sessionId;
}
/**
* Checks if the result represents an error.
*
* @return Whether the result represents an error
*/
public boolean isError() {
return isError;
}
/**
* Sets whether the result represents an error.
*
* @param error Whether the result represents an error
*/
public void setError(boolean error) {
isError = error;
}
/**
* Gets the duration in milliseconds.
*
* @return The duration in milliseconds
*/
public Long getDurationMs() {
return durationMs;
}
/**
* Sets the duration in milliseconds.
*
* @param durationMs The duration in milliseconds
*/
public void setDurationMs(Long durationMs) {
this.durationMs = durationMs;
}
/**
* Gets the API duration in milliseconds.
*
* @return The API duration in milliseconds
*/
public Long getDurationApiMs() {
return durationApiMs;
}
/**
* Sets the API duration in milliseconds.
*
* @param durationApiMs The API duration in milliseconds
*/
public void setDurationApiMs(Long durationApiMs) {
this.durationApiMs = durationApiMs;
}
/**
* Gets the number of turns.
*
* @return The number of turns
*/
public Integer getNumTurns() {
return numTurns;
}
/**
* Sets the number of turns.
*
* @param numTurns The number of turns
*/
public void setNumTurns(Integer numTurns) {
this.numTurns = numTurns;
}
/**
* Gets the usage information.
*
* @return The usage information
*/
public ExtendedUsage getUsage() {
return usage;
}
/**
* Sets the usage information.
*
* @param usage The usage information
*/
public void setUsage(ExtendedUsage usage) {
this.usage = usage;
}
/**
* Gets the model usage information.
*
* @return The model usage information
*/
public Map<String, Usage> getModelUsage() {
return modelUsage;
}
/**
* Sets the model usage information.
*
* @param modelUsage The model usage information
*/
public void setModelUsage(Map<String, Usage> modelUsage) {
this.modelUsage = modelUsage;
}
/**
* Gets the list of permission denials.
*
* @return The list of permission denials
*/
public List<CLIPermissionDenial> getPermissionDenials() {
return permissionDenials;
}
/**
* Sets the list of permission denials.
*
* @param permissionDenials The list of permission denials
*/
public void setPermissionDenials(List<CLIPermissionDenial> permissionDenials) {
this.permissionDenials = permissionDenials;
}
/**
* Gets the error information.
*
* @return The error information
*/
public Error getError() {
return error;
}
/**
* Sets the error information.
*
* @param error The error information
*/
public void setError(Error error) {
this.error = error;
}
/**
* Represents error information.
*/
public static class Error {
/**
* Error type.
*/
private String type;
/**
* Error message.
*/
private String message;
/**
* Gets the error type.
*
* @return The error type
*/
public String getType() {
return type;
}
/**
* Sets the error type.
*
* @param type The error type
*/
public void setType(String type) {
this.type = type;
}
/**
* Gets the error message.
*
* @return The error message
*/
public String getMessage() {
return message;
}
/**
* Sets the error message.
*
* @param message The error message
*/
public void setMessage(String message) {
this.message = message;
}

View File

@@ -6,206 +6,476 @@ import java.util.Map;
import com.alibaba.fastjson2.annotation.JSONField;
import com.alibaba.fastjson2.annotation.JSONType;
/**
* Represents a system message from the SDK.
*/
@JSONType(typeKey = "type", typeName = "system")
public class SDKSystemMessage extends MessageBase {
/**
* The subtype of the system message.
*/
private String subtype;
/**
* The UUID of the message.
*/
private String uuid;
/**
* The session ID.
*/
@JSONField(name = "session_id")
private String sessionId;
/**
* Additional data.
*/
private Object data;
/**
* Current working directory.
*/
private String cwd;
/**
* List of available tools.
*/
private List<String> tools;
/**
* List of MCP servers.
*/
@JSONField(name = "mcp_servers")
private List<McpServer> mcpServers;
/**
* Model information.
*/
private String model;
/**
* Permission mode.
*/
@JSONField(name = "permission_mode")
private String permissionMode;
/**
* Available slash commands.
*/
@JSONField(name = "slash_commands")
private List<String> slashCommands;
/**
* Qwen Code version.
*/
@JSONField(name = "qwen_code_version")
private String qwenCodeVersion;
/**
* Output style.
*/
@JSONField(name = "output_style")
private String outputStyle;
/**
* Available agents.
*/
private List<String> agents;
/**
* Available skills.
*/
private List<String> skills;
/**
* Capabilities information.
*/
private Map<String, Object> capabilities;
/**
* Compact metadata.
*/
@JSONField(name = "compact_metadata")
private CompactMetadata compactMetadata;
/**
* Creates a new SDKSystemMessage instance and sets the type to "system".
*/
public SDKSystemMessage() {
super();
this.type = "system";
}
/**
* Gets the subtype of the system message.
*
* @return The subtype of the system message
*/
public String getSubtype() {
return subtype;
}
/**
* Sets the subtype of the system message.
*
* @param subtype The subtype of the system message
*/
public void setSubtype(String subtype) {
this.subtype = subtype;
}
/**
* Gets the UUID of the message.
*
* @return The UUID of the message
*/
public String getUuid() {
return uuid;
}
/**
* Sets the UUID of the message.
*
* @param uuid The UUID of the message
*/
public void setUuid(String uuid) {
this.uuid = uuid;
}
/**
* Gets the session ID.
*
* @return The session ID
*/
public String getSessionId() {
return sessionId;
}
/**
* Sets the session ID.
*
* @param sessionId The session ID
*/
public void setSessionId(String sessionId) {
this.sessionId = sessionId;
}
/**
* Gets the additional data.
*
* @return The additional data
*/
public Object getData() {
return data;
}
/**
* Sets the additional data.
*
* @param data The additional data
*/
public void setData(Object data) {
this.data = data;
}
/**
* Gets the current working directory.
*
* @return The current working directory
*/
public String getCwd() {
return cwd;
}
/**
* Sets the current working directory.
*
* @param cwd The current working directory
*/
public void setCwd(String cwd) {
this.cwd = cwd;
}
/**
* Gets the list of available tools.
*
* @return The list of available tools
*/
public List<String> getTools() {
return tools;
}
/**
* Sets the list of available tools.
*
* @param tools The list of available tools
*/
public void setTools(List<String> tools) {
this.tools = tools;
}
/**
* Gets the list of MCP servers.
*
* @return The list of MCP servers
*/
public List<McpServer> getMcpServers() {
return mcpServers;
}
/**
* Sets the list of MCP servers.
*
* @param mcpServers The list of MCP servers
*/
public void setMcpServers(List<McpServer> mcpServers) {
this.mcpServers = mcpServers;
}
/**
* Gets the model information.
*
* @return The model information
*/
public String getModel() {
return model;
}
/**
* Sets the model information.
*
* @param model The model information
*/
public void setModel(String model) {
this.model = model;
}
/**
* Gets the permission mode.
*
* @return The permission mode
*/
public String getPermissionMode() {
return permissionMode;
}
/**
* Sets the permission mode.
*
* @param permissionMode The permission mode
*/
public void setPermissionMode(String permissionMode) {
this.permissionMode = permissionMode;
}
/**
* Gets the available slash commands.
*
* @return The available slash commands
*/
public List<String> getSlashCommands() {
return slashCommands;
}
/**
* Sets the available slash commands.
*
* @param slashCommands The available slash commands
*/
public void setSlashCommands(List<String> slashCommands) {
this.slashCommands = slashCommands;
}
/**
* Gets the Qwen Code version.
*
* @return The Qwen Code version
*/
public String getQwenCodeVersion() {
return qwenCodeVersion;
}
/**
* Sets the Qwen Code version.
*
* @param qwenCodeVersion The Qwen Code version
*/
public void setQwenCodeVersion(String qwenCodeVersion) {
this.qwenCodeVersion = qwenCodeVersion;
}
/**
* Gets the output style.
*
* @return The output style
*/
public String getOutputStyle() {
return outputStyle;
}
/**
* Sets the output style.
*
* @param outputStyle The output style
*/
public void setOutputStyle(String outputStyle) {
this.outputStyle = outputStyle;
}
/**
* Gets the available agents.
*
* @return The available agents
*/
public List<String> getAgents() {
return agents;
}
/**
* Sets the available agents.
*
* @param agents The available agents
*/
public void setAgents(List<String> agents) {
this.agents = agents;
}
/**
* Gets the available skills.
*
* @return The available skills
*/
public List<String> getSkills() {
return skills;
}
/**
* Sets the available skills.
*
* @param skills The available skills
*/
public void setSkills(List<String> skills) {
this.skills = skills;
}
/**
* Gets the capabilities information.
*
* @return The capabilities information
*/
public Map<String, Object> getCapabilities() {
return capabilities;
}
/**
* Sets the capabilities information.
*
* @param capabilities The capabilities information
*/
public void setCapabilities(Map<String, Object> capabilities) {
this.capabilities = capabilities;
}
/**
* Gets the compact metadata.
*
* @return The compact metadata
*/
public CompactMetadata getCompactMetadata() {
return compactMetadata;
}
/**
* Sets the compact metadata.
*
* @param compactMetadata The compact metadata
*/
public void setCompactMetadata(CompactMetadata compactMetadata) {
this.compactMetadata = compactMetadata;
}
/**
* Represents MCP server information.
*/
public static class McpServer {
/**
* Server name.
*/
private String name;
/**
* Server status.
*/
private String status;
// Getters and setters
/**
* Gets the server name.
*
* @return The server name
*/
public String getName() {
return name;
}
/**
* Sets the server name.
*
* @param name The server name
*/
public void setName(String name) {
this.name = name;
}
/**
* Gets the server status.
*
* @return The server status
*/
public String getStatus() {
return status;
}
/**
* Sets the server status.
*
* @param status The server status
*/
public void setStatus(String status) {
this.status = status;
}
}
/**
* Represents compact metadata.
*/
public static class CompactMetadata {
/**
* Trigger information.
*/
private String trigger;
/**
* Pre-tokens information.
*/
@JSONField(name = "pre_tokens")
private Integer preTokens;
// Getters and setters
/**
* Gets the trigger information.
*
* @return The trigger information
*/
public String getTrigger() {
return trigger;
}
/**
* Sets the trigger information.
*
* @param trigger The trigger information
*/
public void setTrigger(String trigger) {
this.trigger = trigger;
}
/**
* Gets the pre-tokens information.
*
* @return The pre-tokens information
*/
public Integer getPreTokens() {
return preTokens;
}
/**
* Sets the pre-tokens information.
*
* @param preTokens The pre-tokens information
*/
public void setPreTokens(Integer preTokens) {
this.preTokens = preTokens;
}

View File

@@ -5,84 +5,187 @@ import java.util.Map;
import com.alibaba.fastjson2.annotation.JSONField;
import com.alibaba.fastjson2.annotation.JSONType;
/**
* Represents a user message in the SDK protocol.
*/
@JSONType(typeKey = "type", typeName = "user")
public class SDKUserMessage extends MessageBase {
/**
* The UUID of the message.
*/
private String uuid;
/**
* The session ID.
*/
@JSONField(name = "session_id")
private String sessionId;
/**
* The API user message.
*/
private final APIUserMessage message = new APIUserMessage();
/**
* The parent tool use ID.
*/
@JSONField(name = "parent_tool_use_id")
private String parentToolUseId;
/**
* Additional options.
*/
private Map<String, String> options;
/**
* Creates a new SDKUserMessage instance and sets the type to "user".
*/
public SDKUserMessage() {
super();
this.setType("user");
}
/**
* Gets the UUID of the message.
*
* @return The UUID of the message
*/
public String getUuid() {
return uuid;
}
/**
* Sets the UUID of the message.
*
* @param uuid The UUID of the message
*/
public void setUuid(String uuid) {
this.uuid = uuid;
}
/**
* Gets the session ID.
*
* @return The session ID
*/
public String getSessionId() {
return sessionId;
}
/**
* Sets the session ID.
*
* @param sessionId The session ID
* @return This instance for method chaining
*/
public SDKUserMessage setSessionId(String sessionId) {
this.sessionId = sessionId;
return this;
}
/**
* Sets the content of the message.
*
* @param content The content of the message
* @return This instance for method chaining
*/
public SDKUserMessage setContent(String content) {
message.setContent(content);
return this;
}
/**
* Gets the content of the message.
*
* @return The content of the message
*/
public String getContent() {
return message.getContent();
}
/**
* Gets the parent tool use ID.
*
* @return The parent tool use ID
*/
public String getParentToolUseId() {
return parentToolUseId;
}
/**
* Sets the parent tool use ID.
*
* @param parentToolUseId The parent tool use ID
* @return This instance for method chaining
*/
public SDKUserMessage setParentToolUseId(String parentToolUseId) {
this.parentToolUseId = parentToolUseId;
return this;
}
/**
* Gets the additional options.
*
* @return The additional options
*/
public Map<String, String> getOptions() {
return options;
}
/**
* Sets the additional options.
*
* @param options The additional options
* @return This instance for method chaining
*/
public SDKUserMessage setOptions(Map<String, String> options) {
this.options = options;
return this;
}
/**
* Represents the API user message.
*/
public static class APIUserMessage {
/**
* User role.
*/
private String role = "user";
/**
* Message content.
*/
private String content;
// Getters and Setters
/**
* Gets the user role.
*
* @return The user role
*/
public String getRole() {
return role;
}
/**
* Sets the user role.
*
* @param role The user role
*/
public void setRole(String role) {
this.role = role;
}
/**
* Gets the message content.
*
* @return The message content
*/
public String getContent() {
return content;
}
/**
* Sets the message content.
*
* @param content The message content
*/
public void setContent(String content) {
this.content = content;
}

View File

@@ -6,71 +6,164 @@ import com.alibaba.fastjson2.annotation.JSONField;
import com.alibaba.qwen.code.cli.protocol.data.Usage;
import com.alibaba.qwen.code.cli.protocol.message.assistant.block.ContentBlock;
/**
* Represents an API assistant message.
*/
public class APIAssistantMessage {
/**
* Message ID.
*/
private String id;
/**
* Message type.
*/
private String type = "message";
/**
* Message role.
*/
private String role = "assistant";
/**
* Message model.
*/
private String model;
private List<ContentBlock> content;
/**
* Message content.
*/
private List<ContentBlock<?>> content;
/**
* Stop reason.
*/
@JSONField(name = "stop_reason")
private String stopReason;
/**
* Usage information.
*/
private Usage usage;
// Getters and setters
/**
* Gets the message ID.
*
* @return The message ID
*/
public String getId() {
return id;
}
/**
* Sets the message ID.
*
* @param id The message ID
*/
public void setId(String id) {
this.id = id;
}
/**
* Gets the message type.
*
* @return The message type
*/
public String getType() {
return type;
}
/**
* Sets the message type.
*
* @param type The message type
*/
public void setType(String type) {
this.type = type;
}
/**
* Gets the message role.
*
* @return The message role
*/
public String getRole() {
return role;
}
/**
* Sets the message role.
*
* @param role The message role
*/
public void setRole(String role) {
this.role = role;
}
/**
* Gets the message model.
*
* @return The message model
*/
public String getModel() {
return model;
}
/**
* Sets the message model.
*
* @param model The message model
*/
public void setModel(String model) {
this.model = model;
}
/**
* Gets the stop reason.
*
* @return The stop reason
*/
public String getStopReason() {
return stopReason;
}
/**
* Sets the stop reason.
*
* @param stopReason The stop reason
*/
public void setStopReason(String stopReason) {
this.stopReason = stopReason;
}
/**
* Gets the usage information.
*
* @return The usage information
*/
public Usage getUsage() {
return usage;
}
/**
* Sets the usage information.
*
* @param usage The usage information
*/
public void setUsage(Usage usage) {
this.usage = usage;
}
public List<ContentBlock> getContent() {
/**
* Gets the message content.
*
* @return The message content
*/
public List<ContentBlock<?>> getContent() {
return content;
}
public void setContent(List<ContentBlock> content) {
/**
* Sets the message content.
*
* @param content The message content
*/
public void setContent(List<ContentBlock<?>> content) {
this.content = content;
}
}

View File

@@ -4,50 +4,113 @@ import com.alibaba.fastjson2.annotation.JSONField;
import com.alibaba.fastjson2.annotation.JSONType;
import com.alibaba.qwen.code.cli.protocol.message.MessageBase;
/**
* Represents an SDK assistant message.
*/
@JSONType(typeKey = "type", typeName = "assistant")
public class SDKAssistantMessage extends MessageBase {
/**
* The UUID of the message.
*/
private String uuid;
/**
* The session ID.
*/
@JSONField(name = "session_id")
private String sessionId;
/**
* The API assistant message.
*/
private APIAssistantMessage message;
/**
* The parent tool use ID.
*/
@JSONField(name = "parent_tool_use_id")
private String parentToolUseId;
/**
* Creates a new SDKAssistantMessage instance and sets the type to "assistant".
*/
public SDKAssistantMessage() {
super();
this.type = "assistant";
}
@Override
public String getMessageId() {
return this.getUuid();
}
/**
* Gets the UUID of the message.
*
* @return The UUID of the message
*/
public String getUuid() {
return uuid;
}
/**
* Sets the UUID of the message.
*
* @param uuid The UUID of the message
*/
public void setUuid(String uuid) {
this.uuid = uuid;
}
/**
* Gets the session ID.
*
* @return The session ID
*/
public String getSessionId() {
return sessionId;
}
/**
* Sets the session ID.
*
* @param sessionId The session ID
*/
public void setSessionId(String sessionId) {
this.sessionId = sessionId;
}
/**
* Gets the API assistant message.
*
* @return The API assistant message
*/
public APIAssistantMessage getMessage() {
return message;
}
/**
* Sets the API assistant message.
*
* @param message The API assistant message
*/
public void setMessage(APIAssistantMessage message) {
this.message = message;
}
/**
* Gets the parent tool use ID.
*
* @return The parent tool use ID
*/
public String getParentToolUseId() {
return parentToolUseId;
}
/**
* Sets the parent tool use ID.
*
* @param parentToolUseId The parent tool use ID
*/
public void setParentToolUseId(String parentToolUseId) {
this.parentToolUseId = parentToolUseId;
}

View File

@@ -5,50 +5,108 @@ import com.alibaba.fastjson2.annotation.JSONType;
import com.alibaba.qwen.code.cli.protocol.message.MessageBase;
import com.alibaba.qwen.code.cli.protocol.message.assistant.event.StreamEvent;
/**
* Represents a partial assistant message during streaming.
*/
@JSONType(typeKey = "type", typeName = "stream_event")
public class SDKPartialAssistantMessage extends MessageBase {
/**
* The UUID of the message.
*/
private String uuid;
/**
* The session ID.
*/
@JSONField(name = "session_id")
private String sessionId;
/**
* The stream event.
*/
private StreamEvent event;
/**
* The parent tool use ID.
*/
@JSONField(name = "parent_tool_use_id")
private String parentToolUseId;
/**
* Creates a new SDKPartialAssistantMessage instance and sets the type to "stream_event".
*/
public SDKPartialAssistantMessage() {
super();
this.type = "stream_event";
}
/**
* Gets the UUID of the message.
*
* @return The UUID of the message
*/
public String getUuid() {
return uuid;
}
/**
* Sets the UUID of the message.
*
* @param uuid The UUID of the message
*/
public void setUuid(String uuid) {
this.uuid = uuid;
}
/**
* Gets the session ID.
*
* @return The session ID
*/
public String getSessionId() {
return sessionId;
}
/**
* Sets the session ID.
*
* @param sessionId The session ID
*/
public void setSessionId(String sessionId) {
this.sessionId = sessionId;
}
/**
* Gets the stream event.
*
* @return The stream event
*/
public StreamEvent getEvent() {
return event;
}
/**
* Sets the stream event.
*
* @param event The stream event
*/
public void setEvent(StreamEvent event) {
this.event = event;
}
/**
* Gets the parent tool use ID.
*
* @return The parent tool use ID
*/
public String getParentToolUseId() {
return parentToolUseId;
}
/**
* Sets the parent tool use ID.
*
* @param parentToolUseId The parent tool use ID
*/
public void setParentToolUseId(String parentToolUseId) {
this.parentToolUseId = parentToolUseId;
}

View File

@@ -2,26 +2,54 @@ package com.alibaba.qwen.code.cli.protocol.message.assistant.block;
import com.alibaba.fastjson2.annotation.JSONField;
/**
* Represents an annotation for a content block.
*/
public class Annotation {
/**
* The annotation type.
*/
@JSONField(name = "type")
private String type;
/**
* The annotation value.
*/
@JSONField(name = "value")
private String value;
// Getters and setters
/**
* Gets the annotation type.
*
* @return The annotation type
*/
public String getType() {
return type;
}
/**
* Sets the annotation type.
*
* @param type The annotation type
*/
public void setType(String type) {
this.type = type;
}
/**
* Gets the annotation value.
*
* @return The annotation value
*/
public String getValue() {
return value;
}
/**
* Sets the annotation value.
*
* @param value The annotation value
*/
public void setValue(String value) {
this.value = value;
}

View File

@@ -6,27 +6,72 @@ import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.annotation.JSONType;
import com.alibaba.qwen.code.cli.protocol.data.AssistantContent;
/**
* Abstract base class for content blocks in assistant messages.
*
* @param <C> The type of content
*/
@JSONType(typeKey = "type", typeName = "ContentBlock", seeAlso = { TextBlock.class, ToolResultBlock.class, ThinkingBlock.class, ToolUseBlock.class })
public abstract class ContentBlock implements AssistantContent {
public abstract class ContentBlock<C> implements AssistantContent<C> {
/**
* The type of the content block.
*/
protected String type;
/**
* List of annotations.
*/
protected List<Annotation> annotations;
/**
* The message ID.
*/
protected String messageId;
@Override
public String getType() {
return type;
}
/**
* Sets the type of the content block.
*
* @param type The type of the content block
*/
public void setType(String type) {
this.type = type;
}
/**
* Gets the list of annotations.
*
* @return The list of annotations
*/
public List<Annotation> getAnnotations() {
return annotations;
}
/**
* Sets the list of annotations.
*
* @param annotations The list of annotations
*/
public void setAnnotations(List<Annotation> annotations) {
this.annotations = annotations;
}
@Override
public String getMessageId() {
return messageId;
}
/**
* Sets the message ID.
*
* @param messageId The message ID
*/
public void setMessageId(String messageId) {
this.messageId = messageId;
}
public String toString() {
return JSON.toJSONString(this);
}

View File

@@ -1,21 +1,38 @@
package com.alibaba.qwen.code.cli.protocol.message.assistant.block;
import com.alibaba.fastjson2.annotation.JSONType;
import com.alibaba.qwen.code.cli.protocol.data.AssistantContent.TextAssistantContent;
/**
* Represents a text content block.
*/
@JSONType(typeKey = "type", typeName = "text")
public class TextBlock extends ContentBlock {
public class TextBlock extends ContentBlock<String> implements TextAssistantContent {
/**
* The text content.
*/
private String text;
/**
* Gets the text content.
*
* @return The text content
*/
public String getText() {
return text;
}
/**
* Sets the text content.
*
* @param text The text content
*/
public void setText(String text) {
this.text = text;
}
@Override
public Object getContent() {
public String getContentOfAssistant() {
return text;
}
}

View File

@@ -1,30 +1,60 @@
package com.alibaba.qwen.code.cli.protocol.message.assistant.block;
import com.alibaba.fastjson2.annotation.JSONType;
import com.alibaba.qwen.code.cli.protocol.data.AssistantContent.ThingkingAssistantContent;
/**
* Represents a thinking content block.
*/
@JSONType(typeKey = "type", typeName = "thinking")
public class ThinkingBlock extends ContentBlock{
public class ThinkingBlock extends ContentBlock<String> implements ThingkingAssistantContent {
/**
* The thinking content.
*/
private String thinking;
/**
* The signature.
*/
private String signature;
/**
* Gets the thinking content.
*
* @return The thinking content
*/
public String getThinking() {
return thinking;
}
/**
* Sets the thinking content.
*
* @param thinking The thinking content
*/
public void setThinking(String thinking) {
this.thinking = thinking;
}
/**
* Gets the signature.
*
* @return The signature
*/
public String getSignature() {
return signature;
}
/**
* Sets the signature.
*
* @param signature The signature
*/
public void setSignature(String signature) {
this.signature = signature;
}
@Override
public Object getContent() {
public String getContentOfAssistant() {
return thinking;
}
}

View File

@@ -2,39 +2,87 @@ package com.alibaba.qwen.code.cli.protocol.message.assistant.block;
import com.alibaba.fastjson2.annotation.JSONField;
import com.alibaba.fastjson2.annotation.JSONType;
import com.alibaba.qwen.code.cli.protocol.data.AssistantContent.ToolResultAssistantContent;
/**
* Represents a tool result content block.
*/
@JSONType(typeKey = "type", typeName = "tool_result")
public class ToolResultBlock extends ContentBlock {
public class ToolResultBlock extends ContentBlock<String> implements ToolResultAssistantContent {
/**
* The tool use ID.
*/
@JSONField(name = "tool_use_id")
private String toolUseId;
/**
* The result content.
*/
@JSONField(name = "content")
private Object content; // Can be String or List<ContentBlock>
private String content;
/**
* Whether the result is an error.
*/
@JSONField(name = "is_error")
private Boolean isError;
/**
* Gets the tool use ID.
*
* @return The tool use ID
*/
public String getToolUseId() {
return toolUseId;
}
/**
* Sets the tool use ID.
*
* @param toolUseId The tool use ID
*/
public void setToolUseId(String toolUseId) {
this.toolUseId = toolUseId;
}
public Object getContent() {
/**
* Gets the result content.
*
* @return The result content
*/
public String getContent() {
return content;
}
public void setContent(Object content) {
/**
* Sets the result content.
*
* @param content The result content
*/
public void setContent(String content) {
this.content = content;
}
/**
* Gets whether the result is an error.
*
* @return Whether the result is an error
*/
public Boolean getIsError() {
return isError;
}
/**
* Sets whether the result is an error.
*
* @param isError Whether the result is an error
*/
public void setIsError(Boolean isError) {
this.isError = isError;
}
@Override
public String getContentOfAssistant() {
return content;
}
}

View File

@@ -1,54 +1,113 @@
package com.alibaba.qwen.code.cli.protocol.message.assistant.block;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import com.alibaba.fastjson2.annotation.JSONType;
import com.alibaba.qwen.code.cli.protocol.data.AssistantContent.ToolUseAssistantContent;
/**
* Represents a tool use content block.
*/
@JSONType(typeKey = "type", typeName = "tool_use")
public class ToolUseBlock extends ContentBlock {
public class ToolUseBlock extends ContentBlock<Map<String, Object>> implements ToolUseAssistantContent {
/**
* The tool use ID.
*/
private String id;
/**
* The tool name.
*/
private String name;
/**
* The tool input.
*/
private Map<String, Object> input;
/**
* List of annotations.
*/
private List<Annotation> annotations;
// 构造函数
/**
* Creates a new ToolUseBlock instance.
*/
public ToolUseBlock() {}
/**
* Gets the tool use ID.
*
* @return The tool use ID
*/
public String getId() {
return id;
}
/**
* Sets the tool use ID.
*
* @param id The tool use ID
*/
public void setId(String id) {
this.id = id;
}
/**
* Gets the tool name.
*
* @return The tool name
*/
public String getName() {
return name;
}
/**
* Sets the tool name.
*
* @param name The tool name
*/
public void setName(String name) {
this.name = name;
}
/**
* Gets the tool input.
*
* @return The tool input
*/
public Map<String, Object> getInput() {
return input;
}
/**
* Sets the tool input.
*
* @param input The tool input
*/
public void setInput(Map<String, Object> input) {
this.input = input;
}
/**
* Gets the list of annotations.
*
* @return The list of annotations
*/
public List<Annotation> getAnnotations() {
return annotations;
}
/**
* Sets the list of annotations.
*
* @param annotations The list of annotations
*/
public void setAnnotations(List<Annotation> annotations) {
this.annotations = annotations;
}
@Override
public Object getContent() {
return input;
public Map<String, Object> getContentOfAssistant() {
return Collections.emptyMap();
}
}

View File

@@ -1,96 +1,221 @@
package com.alibaba.qwen.code.cli.protocol.message.assistant.event;
import java.util.Map;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.TypeReference;
import com.alibaba.fastjson2.annotation.JSONField;
import com.alibaba.fastjson2.annotation.JSONType;
import com.alibaba.qwen.code.cli.protocol.data.AssistantContent;
import com.alibaba.qwen.code.cli.protocol.data.AssistantContent.TextAssistantContent;
import com.alibaba.qwen.code.cli.protocol.data.AssistantContent.ThingkingAssistantContent;
import com.alibaba.qwen.code.cli.protocol.data.AssistantContent.ToolUseAssistantContent;
/**
* Represents a content block delta event during streaming.
*/
@JSONType(typeKey = "type", typeName = "content_block_delta")
public class ContentBlockDeltaEvent extends StreamEvent {
/**
* The index of the content block.
*/
private int index;
private ContentBlockDelta delta;
/**
* The content block delta.
*/
private ContentBlockDelta<?> delta;
/**
* Gets the index of the content block.
*
* @return The index of the content block
*/
public int getIndex() {
return index;
}
/**
* Sets the index of the content block.
*
* @param index The index of the content block
*/
public void setIndex(int index) {
this.index = index;
}
public ContentBlockDelta getDelta() {
/**
* Gets the content block delta.
*
* @return The content block delta
*/
public ContentBlockDelta<?> getDelta() {
return delta;
}
public void setDelta(ContentBlockDelta delta) {
/**
* Sets the content block delta.
*
* @param delta The content block delta
*/
public void setDelta(ContentBlockDelta<?> delta) {
this.delta = delta;
}
/**
* Abstract base class for content block deltas.
*
* @param <C> The type of content
*/
@JSONType(typeKey = "type", typeName = "ContentBlockDelta",
seeAlso = {ContentBlockDeltaText.class, ContentBlockDeltaThinking.class, ContentBlockDeltaInputJson.class})
public abstract static class ContentBlockDelta implements AssistantContent {
private String type;
public abstract static class ContentBlockDelta<C> implements AssistantContent<C> {
/**
* The type of the content block delta.
*/
protected String type;
/**
* The message ID.
*/
protected String messageId;
@Override
public String getType() {
return type;
}
/**
* Sets the type of the content block delta.
*
* @param type The type of the content block delta
*/
public void setType(String type) {
this.type = type;
}
@Override
public String getMessageId() {
return messageId;
}
/**
* Sets the message ID.
*
* @param messageId The message ID
*/
public void setMessageId(String messageId) {
this.messageId = messageId;
}
public String toString() {
return JSON.toJSONString(this);
}
}
/**
* Represents a text delta.
*/
@JSONType(typeKey = "type", typeName = "text_delta")
public static class ContentBlockDeltaText extends ContentBlockDelta {
public static class ContentBlockDeltaText extends ContentBlockDelta<String> implements TextAssistantContent {
/**
* The text content.
*/
private String text;
/**
* Gets the text content.
*
* @return The text content
*/
public String getText() {
return text;
}
/**
* Sets the text content.
*
* @param text The text content
*/
public void setText(String text) {
this.text = text;
}
@Override
public Object getContent() {
public String getContentOfAssistant() {
return text;
}
}
/**
* Represents a thinking delta.
*/
@JSONType(typeKey = "type", typeName = "thinking_delta")
public static class ContentBlockDeltaThinking extends ContentBlockDelta {
public static class ContentBlockDeltaThinking extends ContentBlockDelta<String> implements ThingkingAssistantContent {
/**
* The thinking content.
*/
private String thinking;
/**
* Gets the thinking content.
*
* @return The thinking content
*/
public String getThinking() {
return thinking;
}
/**
* Sets the thinking content.
*
* @param thinking The thinking content
*/
public void setThinking(String thinking) {
this.thinking = thinking;
}
@Override
public Object getContent() {
public String getContentOfAssistant() {
return thinking;
}
}
/**
* Represents an input JSON delta.
*/
@JSONType(typeKey = "type", typeName = "input_json_delta")
public static class ContentBlockDeltaInputJson extends ContentBlockDelta {
public static class ContentBlockDeltaInputJson extends ContentBlockDelta<Map<String, Object>> implements ToolUseAssistantContent {
/**
* The partial JSON content.
*/
@JSONField(name = "partial_json")
private String partialJson;
/**
* Gets the partial JSON content.
*
* @return The partial JSON content
*/
public String getPartialJson() {
return partialJson;
}
/**
* Sets the partial JSON content.
*
* @param partialJson The partial JSON content
*/
public void setPartialJson(String partialJson) {
this.partialJson = partialJson;
}
@Override
public Object getContent() {
return partialJson;
public Map<String, Object> getContentOfAssistant() {
return getInput();
}
@Override
public Map<String, Object> getInput() {
return JSON.parseObject(partialJson, new TypeReference<Map<String, Object>>() {});
}
}
}

View File

@@ -4,10 +4,19 @@ import com.alibaba.fastjson2.annotation.JSONField;
import com.alibaba.fastjson2.annotation.JSONType;
import com.alibaba.qwen.code.cli.protocol.message.assistant.block.ContentBlock;
/**
* Represents a content block start event during message streaming.
*/
@JSONType(typeKey = "type", typeName = "content_block_start")
public class ContentBlockStartEvent extends StreamEvent{
/**
* The index of the content block.
*/
private int index;
/**
* The content block that is starting.
*/
@JSONField(name = "content_block")
private ContentBlock contentBlock;
}

View File

@@ -2,14 +2,30 @@ package com.alibaba.qwen.code.cli.protocol.message.assistant.event;
import com.alibaba.fastjson2.annotation.JSONType;
/**
* Represents a content block stop event during message streaming.
*/
@JSONType(typeKey = "type", typeName = "content_block_stop")
public class ContentBlockStopEvent extends StreamEvent{
/**
* The index of the content block.
*/
Long index;
/**
* Gets the index of the content block.
*
* @return The index of the content block
*/
public Long getIndex() {
return index;
}
/**
* Sets the index of the content block.
*
* @param index The index of the content block
*/
public void setIndex(Long index) {
this.index = index;
}

View File

@@ -2,45 +2,102 @@ package com.alibaba.qwen.code.cli.protocol.message.assistant.event;
import com.alibaba.fastjson2.annotation.JSONType;
/**
* Represents a message start event during message streaming.
*/
@JSONType(typeName = "message_start")
public class MessageStartStreamEvent extends StreamEvent{
/**
* The message that is starting.
*/
private Message message;
/**
* Represents the message information.
*/
public static class Message {
/**
* Message ID.
*/
private String id;
/**
* Message role.
*/
private String role;
/**
* Message model.
*/
private String model;
// Getters and setters
/**
* Gets the message ID.
*
* @return The message ID
*/
public String getId() {
return id;
}
/**
* Sets the message ID.
*
* @param id The message ID
*/
public void setId(String id) {
this.id = id;
}
/**
* Gets the message role.
*
* @return The message role
*/
public String getRole() {
return role;
}
/**
* Sets the message role.
*
* @param role The message role
*/
public void setRole(String role) {
this.role = role;
}
/**
* Gets the message model.
*
* @return The message model
*/
public String getModel() {
return model;
}
/**
* Sets the message model.
*
* @param model The message model
*/
public void setModel(String model) {
this.model = model;
}
}
/**
* Gets the message that is starting.
*
* @return The message that is starting
*/
public Message getMessage() {
return message;
}
/**
* Sets the message that is starting.
*
* @param message The message that is starting
*/
public void setMessage(Message message) {
this.message = message;
}

View File

@@ -2,6 +2,9 @@ package com.alibaba.qwen.code.cli.protocol.message.assistant.event;
import com.alibaba.fastjson2.annotation.JSONType;
/**
* Represents a message stop event during message streaming.
*/
@JSONType(typeName = "message_stop")
public class MessageStopStreamEvent extends StreamEvent{
}

View File

@@ -2,16 +2,32 @@ package com.alibaba.qwen.code.cli.protocol.message.assistant.event;
import com.alibaba.fastjson2.annotation.JSONType;
/**
* Base class for stream events during message streaming.
*/
@JSONType(typeKey = "type", typeName = "StreamEvent",
seeAlso = {MessageStartStreamEvent.class, MessageStopStreamEvent.class, ContentBlockStartEvent.class, ContentBlockStopEvent.class,
ContentBlockDeltaEvent.class})
public class StreamEvent {
/**
* The type of the stream event.
*/
protected String type;
/**
* Gets the type of the stream event.
*
* @return The type of the stream event
*/
public String getType() {
return type;
}
/**
* Sets the type of the stream event.
*
* @param type The type of the stream event
*/
public void setType(String type) {
this.type = type;
}

View File

@@ -3,24 +3,54 @@ package com.alibaba.qwen.code.cli.protocol.message.control;
import com.alibaba.fastjson2.annotation.JSONField;
import com.alibaba.qwen.code.cli.protocol.data.InitializeConfig;
/**
* Represents a control initialize request to the CLI.
*/
public class CLIControlInitializeRequest {
/**
* The subtype of the request.
*/
String subtype = "initialize";
/**
* The initialization configuration.
*/
@JSONField(unwrapped = true)
InitializeConfig initializeConfig = new InitializeConfig();
/**
* Gets the subtype of the request.
*
* @return The subtype of the request
*/
public String getSubtype() {
return subtype;
}
/**
* Sets the subtype of the request.
*
* @param subtype The subtype of the request
*/
public void setSubtype(String subtype) {
this.subtype = subtype;
}
/**
* Gets the initialization configuration.
*
* @return The initialization configuration
*/
public InitializeConfig getInitializeConfig() {
return initializeConfig;
}
/**
* Sets the initialization configuration.
*
* @param initializeConfig The initialization configuration
* @return This instance for method chaining
*/
public CLIControlInitializeRequest setInitializeConfig(InitializeConfig initializeConfig) {
this.initializeConfig = initializeConfig;
return this;

View File

@@ -2,22 +2,51 @@ package com.alibaba.qwen.code.cli.protocol.message.control;
import com.alibaba.qwen.code.cli.protocol.data.Capabilities;
/**
* Represents a control initialize response from the CLI.
*/
public class CLIControlInitializeResponse {
/**
* The subtype of the response.
*/
String subtype = "initialize";
/**
* The capabilities' information.
*/
Capabilities capabilities;
/**
* Gets the subtype of the response.
*
* @return The subtype of the response
*/
public String getSubtype() {
return subtype;
}
/**
* Sets the subtype of the response.
*
* @param subtype The subtype of the response
*/
public void setSubtype(String subtype) {
this.subtype = subtype;
}
/**
* Gets the capabilities information.
*
* @return The capabilities information
*/
public Capabilities getCapabilities() {
return capabilities;
}
/**
* Sets the capabilities information.
*
* @param capabilities The capabilities information
*/
public void setCapabilities(Capabilities capabilities) {
this.capabilities = capabilities;
}

View File

@@ -1,12 +1,28 @@
package com.alibaba.qwen.code.cli.protocol.message.control;
/**
* Represents a control interrupt request to the CLI.
*/
public class CLIControlInterruptRequest {
/**
* The subtype of the request ("interrupt").
*/
String subtype = "interrupt";
/**
* Gets the subtype of the request.
*
* @return The subtype of the request
*/
public String getSubtype() {
return subtype;
}
/**
* Sets the subtype of the request.
*
* @param subtype The subtype of the request
*/
public void setSubtype(String subtype) {
this.subtype = subtype;
}

View File

@@ -5,106 +5,242 @@ import java.util.Map;
import com.alibaba.fastjson2.annotation.JSONField;
/**
* Represents a control permission request to the CLI.
*/
public class CLIControlPermissionRequest {
/**
* The subtype of the request.
*/
private String subtype;
/**
* The name of the tool requesting permission.
*/
@JSONField(name = "tool_name")
private String toolName;
/**
* The ID of the tool use.
*/
@JSONField(name = "tool_use_id")
private String toolUseId;
/**
* The input for the tool.
*/
private Map<String, Object> input;
/**
* List of permission suggestions.
*/
@JSONField(name = "permission_suggestions")
private List<PermissionSuggestion> permissionSuggestions;
/**
* The blocked path.
*/
@JSONField(name = "blocked_path")
private String blockedPath;
/**
* Gets the subtype of the request.
*
* @return The subtype of the request
*/
public String getSubtype() {
return subtype;
}
/**
* Sets the subtype of the request.
*
* @param subtype The subtype of the request
*/
public void setSubtype(String subtype) {
this.subtype = subtype;
}
/**
* Gets the name of the tool requesting permission.
*
* @return The name of the tool requesting permission
*/
public String getToolName() {
return toolName;
}
/**
* Sets the name of the tool requesting permission.
*
* @param toolName The name of the tool requesting permission
*/
public void setToolName(String toolName) {
this.toolName = toolName;
}
/**
* Gets the ID of the tool use.
*
* @return The ID of the tool use
*/
public String getToolUseId() {
return toolUseId;
}
/**
* Sets the ID of the tool use.
*
* @param toolUseId The ID of the tool use
*/
public void setToolUseId(String toolUseId) {
this.toolUseId = toolUseId;
}
/**
* Gets the input for the tool.
*
* @return The input for the tool
*/
public Map<String, Object> getInput() {
return input;
}
/**
* Sets the input for the tool.
*
* @param input The input for the tool
*/
public void setInput(Map<String, Object> input) {
this.input = input;
}
/**
* Gets the list of permission suggestions.
*
* @return The list of permission suggestions
*/
public List<PermissionSuggestion> getPermissionSuggestions() {
return permissionSuggestions;
}
/**
* Sets the list of permission suggestions.
*
* @param permissionSuggestions The list of permission suggestions
*/
public void setPermissionSuggestions(
List<PermissionSuggestion> permissionSuggestions) {
this.permissionSuggestions = permissionSuggestions;
}
/**
* Gets the blocked path.
*
* @return The blocked path
*/
public String getBlockedPath() {
return blockedPath;
}
/**
* Sets the blocked path.
*
* @param blockedPath The blocked path
*/
public void setBlockedPath(String blockedPath) {
this.blockedPath = blockedPath;
}
/**
* Represents a permission suggestion.
*/
public static class PermissionSuggestion {
/**
* The type of suggestion (allow, deny, modify).
*/
private String type; // 'allow' | 'deny' | 'modify'
/**
* The label for the suggestion.
*/
private String label;
/**
* The description of the suggestion.
*/
private String description;
/**
* The modified input.
*/
private Object modifiedInput;
/**
* Gets the type of suggestion.
*
* @return The type of suggestion
*/
public String getType() {
return type;
}
/**
* Sets the type of suggestion.
*
* @param type The type of suggestion
*/
public void setType(String type) {
this.type = type;
}
/**
* Gets the label for the suggestion.
*
* @return The label for the suggestion
*/
public String getLabel() {
return label;
}
/**
* Sets the label for the suggestion.
*
* @param label The label for the suggestion
*/
public void setLabel(String label) {
this.label = label;
}
/**
* Gets the description of the suggestion.
*
* @return The description of the suggestion
*/
public String getDescription() {
return description;
}
/**
* Sets the description of the suggestion.
*
* @param description The description of the suggestion
*/
public void setDescription(String description) {
this.description = description;
}
/**
* Gets the modified input.
*
* @return The modified input
*/
public Object getModifiedInput() {
return modifiedInput;
}
/**
* Sets the modified input.
*
* @param modifiedInput The modified input
*/
public void setModifiedInput(Object modifiedInput) {
this.modifiedInput = modifiedInput;
}

View File

@@ -3,24 +3,54 @@ package com.alibaba.qwen.code.cli.protocol.message.control;
import com.alibaba.fastjson2.annotation.JSONField;
import com.alibaba.qwen.code.cli.protocol.data.behavior.Behavior;
/**
* Represents a control permission response from the CLI.
*/
public class CLIControlPermissionResponse {
/**
* The subtype of the response ("can_use_tool").
*/
private String subtype = "can_use_tool";
/**
* The behavior for the permission request.
*/
@JSONField(unwrapped = true)
Behavior behavior;
/**
* Gets the subtype of the response.
*
* @return The subtype of the response
*/
public String getSubtype() {
return subtype;
}
/**
* Sets the subtype of the response.
*
* @param subtype The subtype of the response
*/
public void setSubtype(String subtype) {
this.subtype = subtype;
}
/**
* Gets the behavior for the permission request.
*
* @return The behavior for the permission request
*/
public Behavior getBehavior() {
return behavior;
}
/**
* Sets the behavior for the permission request.
*
* @param behavior The behavior for the permission request
* @return This instance for method chaining
*/
public CLIControlPermissionResponse setBehavior(Behavior behavior) {
this.behavior = behavior;
return this;

View File

@@ -6,37 +6,80 @@ import com.alibaba.fastjson2.annotation.JSONField;
import com.alibaba.fastjson2.annotation.JSONType;
import com.alibaba.qwen.code.cli.protocol.message.MessageBase;
/**
* Represents a control request to the CLI.
*
* @param <R> The type of the request object
*/
@JSONType(typeKey = "type", typeName = "control_request")
public class CLIControlRequest<R> extends MessageBase {
/**
* The ID of the request.
*/
@JSONField(name = "request_id")
private String requestId = UUID.randomUUID().toString();
/**
* The actual request object.
*/
private R request;
/**
* Creates a new CLIControlRequest instance and sets the type to "control_request".
*/
public CLIControlRequest() {
super();
type = "control_request";
}
/**
* Creates a new control request with the specified request object.
*
* @param request The request object
* @param <T> The type of the request object
* @return A new control request instance
*/
public static <T> CLIControlRequest<T> create(T request) {
CLIControlRequest<T> controlRequest = new CLIControlRequest<>();
controlRequest.setRequest(request);
return controlRequest;
}
/**
* Gets the ID of the request.
*
* @return The ID of the request
*/
public String getRequestId() {
return requestId;
}
/**
* Sets the ID of the request.
*
* @param requestId The ID of the request
* @return This instance for method chaining
*/
public CLIControlRequest<R> setRequestId(String requestId) {
this.requestId = requestId;
return this;
}
/**
* Gets the actual request object.
*
* @return The actual request object
*/
public R getRequest() {
return request;
}
/**
* Sets the actual request object.
*
* @param request The actual request object
* @return This instance for method chaining
*/
public CLIControlRequest<R> setRequest(R request) {
this.request = request;
return this;

View File

@@ -4,57 +4,130 @@ import com.alibaba.fastjson2.annotation.JSONField;
import com.alibaba.fastjson2.annotation.JSONType;
import com.alibaba.qwen.code.cli.protocol.message.MessageBase;
/**
* Represents a control response from the CLI.
*
* @param <R> The type of the response object
*/
@JSONType(typeKey = "type", typeName = "control_response")
public class CLIControlResponse<R> extends MessageBase {
/**
* The response object.
*/
private Response<R> response;
/**
* Creates a new CLIControlResponse instance and sets the type to "control_response".
*/
public CLIControlResponse() {
super();
this.type = "control_response";
}
/**
* Gets the response object.
*
* @return The response object
*/
public Response<R> getResponse() {
return response;
}
/**
* Sets the response object.
*
* @param response The response object
*/
public void setResponse(Response<R> response) {
this.response = response;
}
/**
* Creates a new response object.
*
* @return A new response object
*/
public Response<R> createResponse() {
Response<R> response = new Response<>();
this.setResponse(response);
return response;
}
/**
* Represents the response information.
*
* @param <R> The type of the response object
*/
public static class Response<R> {
/**
* The ID of the request.
*/
@JSONField(name = "request_id")
private String requestId;
/**
* The subtype of the response.
*/
private String subtype = "success";
/**
* The actual response.
*/
R response;
/**
* Gets the ID of the request.
*
* @return The ID of the request
*/
public String getRequestId() {
return requestId;
}
/**
* Sets the ID of the request.
*
* @param requestId The ID of the request
* @return This instance for method chaining
*/
public Response<R> setRequestId(String requestId) {
this.requestId = requestId;
return this;
}
/**
* Gets the subtype of the response.
*
* @return The subtype of the response
*/
public String getSubtype() {
return subtype;
}
/**
* Sets the subtype of the response.
*
* @param subtype The subtype of the response
* @return This instance for method chaining
*/
public Response<R> setSubtype(String subtype) {
this.subtype = subtype;
return this;
}
/**
* Gets the actual response.
*
* @return The actual response
*/
public R getResponse() {
return response;
}
/**
* Sets the actual response.
*
* @param response The actual response
* @return This instance for method chaining
*/
public Response<R> setResponse(R response) {
this.response = response;
return this;

View File

@@ -1,21 +1,50 @@
package com.alibaba.qwen.code.cli.protocol.message.control;
/**
* Represents a control request to set the model in the CLI.
*/
public class CLIControlSetModelRequest {
/**
* The subtype of the request ("set_model").
*/
String subtype = "set_model";
/**
* The model to set.
*/
String model;
/**
* Gets the subtype of the request.
*
* @return The subtype of the request
*/
public String getSubtype() {
return subtype;
}
/**
* Sets the subtype of the request.
*
* @param subtype The subtype of the request
*/
public void setSubtype(String subtype) {
this.subtype = subtype;
}
/**
* Gets the model to set.
*
* @return The model to set
*/
public String getModel() {
return model;
}
/**
* Sets the model to set.
*
* @param model The model to set
*/
public void setModel(String model) {
this.model = model;
}

View File

@@ -1,21 +1,50 @@
package com.alibaba.qwen.code.cli.protocol.message.control;
/**
* Represents a control response for setting the model in the CLI.
*/
public class CLIControlSetModelResponse {
/**
* The subtype of the response ("set_model").
*/
String subtype = "set_model";
/**
* The model that was set.
*/
String model;
/**
* Gets the subtype of the response.
*
* @return The subtype of the response
*/
public String getSubtype() {
return subtype;
}
/**
* Sets the subtype of the response.
*
* @param subtype The subtype of the response
*/
public void setSubtype(String subtype) {
this.subtype = subtype;
}
/**
* Gets the model that was set.
*
* @return The model that was set
*/
public String getModel() {
return model;
}
/**
* Sets the model that was set.
*
* @param model The model that was set
*/
public void setModel(String model) {
this.model = model;
}

View File

@@ -1,22 +1,51 @@
package com.alibaba.qwen.code.cli.protocol.message.control;
/**
* Represents a control request to set the permission mode in the CLI.
*/
public class CLIControlSetPermissionModeRequest {
/**
* The subtype of the request ("set_permission_mode").
*/
String subtype = "set_permission_mode";
/**
* The permission mode to set.
*/
String mode;
/**
* Gets the subtype of the request.
*
* @return The subtype of the request
*/
public String getSubtype() {
return subtype;
}
/**
* Sets the subtype of the request.
*
* @param subtype The subtype of the request
*/
public void setSubtype(String subtype) {
this.subtype = subtype;
}
/**
* Gets the permission mode to set.
*
* @return The permission mode to set
*/
public String getMode() {
return mode;
}
/**
* Sets the permission mode to set.
*
* @param mode The permission mode to set
*/
public void setMode(String mode) {
this.mode = mode;
}

View File

@@ -31,6 +31,7 @@ import com.alibaba.qwen.code.cli.session.event.SessionEventConsumers;
import com.alibaba.qwen.code.cli.session.exception.SessionControlException;
import com.alibaba.qwen.code.cli.session.exception.SessionSendPromptException;
import com.alibaba.qwen.code.cli.transport.Transport;
import com.alibaba.qwen.code.cli.transport.TransportOptions;
import com.alibaba.qwen.code.cli.utils.MyConcurrentUtils;
import com.alibaba.qwen.code.cli.utils.Timeout;
@@ -38,6 +39,9 @@ import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Manages a session with the Qwen Code CLI, handling communication, sending prompts, and processing responses.
*/
public class Session {
private static final Logger log = LoggerFactory.getLogger(Session.class);
private final Transport transport;
@@ -45,6 +49,24 @@ public class Session {
private SDKSystemMessage lastSdkSystemMessage;
private final Timeout defaultEventTimeout = Timeout.TIMEOUT_60_SECONDS;
/**
* Checks if the session is configured for streaming.
*
* @return true if streaming is enabled, false otherwise
*/
public boolean isStreaming() {
return Optional.ofNullable(transport)
.map(Transport::getTransportOptions)
.map(TransportOptions::getIncludePartialMessages)
.orElse(false);
}
/**
* Constructs a new session with the specified transport.
*
* @param transport The transport layer to use for communication
* @throws SessionControlException if the transport is not available
*/
public Session(Transport transport) throws SessionControlException {
if (transport == null || !transport.isAvailable()) {
throw new SessionControlException("Transport is not available");
@@ -53,6 +75,11 @@ public class Session {
start();
}
/**
* Starts the session by initializing communication with the CLI.
*
* @throws SessionControlException if initialization fails
*/
public void start() throws SessionControlException {
try {
if (!transport.isAvailable()) {
@@ -67,6 +94,11 @@ public class Session {
}
}
/**
* Closes the session and releases resources.
*
* @throws SessionControlException if closing fails
*/
public void close() throws SessionControlException {
try {
transport.close();
@@ -75,11 +107,24 @@ public class Session {
}
}
/**
* Interrupts the current operation in the CLI.
*
* @return An optional boolean indicating success of the interrupt operation
* @throws SessionControlException if the operation fails
*/
public Optional<Boolean> interrupt() throws SessionControlException {
checkAvailable();
return processControlRequest(new CLIControlRequest<CLIControlInterruptRequest>().setRequest(new CLIControlInterruptRequest()).toString());
}
/**
* Sets the model to be used in the session.
*
* @param modelName The name of the model to use
* @return An optional boolean indicating success of the operation
* @throws SessionControlException if the operation fails
*/
public Optional<Boolean> setModel(String modelName) throws SessionControlException {
checkAvailable();
CLIControlSetModelRequest cliControlSetModelRequest = new CLIControlSetModelRequest();
@@ -87,6 +132,13 @@ public class Session {
return processControlRequest(new CLIControlRequest<CLIControlSetModelRequest>().setRequest(cliControlSetModelRequest).toString());
}
/**
* Sets the permission mode for the session.
*
* @param permissionMode The permission mode to use
* @return An optional boolean indicating success of the operation
* @throws SessionControlException if the operation fails
*/
public Optional<Boolean> setPermissionMode(PermissionMode permissionMode) throws SessionControlException {
checkAvailable();
CLIControlSetPermissionModeRequest cliControlSetPermissionModeRequest = new CLIControlSetPermissionModeRequest();
@@ -110,10 +162,21 @@ public class Session {
}
}
/**
* Continues the current session.
*
* @throws SessionControlException if the operation fails
*/
public void continueSession() throws SessionControlException {
resumeSession(getSessionId());
}
/**
* Resumes a session with the specified ID.
*
* @param sessionId The ID of the session to resume
* @throws SessionControlException if the operation fails
*/
public void resumeSession(String sessionId) throws SessionControlException {
if (StringUtils.isNotBlank(sessionId)) {
transport.getTransportOptions().setResumeSessionId(sessionId);
@@ -121,6 +184,14 @@ public class Session {
this.start();
}
/**
* Sends a prompt to the CLI and processes the response.
*
* @param prompt The prompt to send to the CLI
* @param sessionEventConsumers Consumers for handling different types of events
* @throws SessionSendPromptException if sending the prompt fails
* @throws SessionControlException if a control operation fails
*/
public void sendPrompt(String prompt, SessionEventConsumers sessionEventConsumers) throws SessionSendPromptException, SessionControlException {
checkAvailable();
try {
@@ -137,7 +208,8 @@ public class Session {
Optional.ofNullable(sessionEventConsumers.onAssistantMessageTimeout(this)).orElse(defaultEventTimeout));
return false;
} else if ("stream_event".equals(messageType)) {
MyConcurrentUtils.runAndWait(() -> sessionEventConsumers.onPartialAssistantMessage(this, jsonObject.to(SDKPartialAssistantMessage.class)),
MyConcurrentUtils.runAndWait(
() -> sessionEventConsumers.onPartialAssistantMessage(this, jsonObject.to(SDKPartialAssistantMessage.class)),
Optional.ofNullable(sessionEventConsumers.onPartialAssistantMessageTimeout(this)).orElse(defaultEventTimeout));
return false;
} else if ("user".equals(messageType)) {
@@ -234,14 +306,29 @@ public class Session {
return false;
}
/**
* Gets the current session ID.
*
* @return The session ID, or null if not available
*/
public String getSessionId() {
return Optional.ofNullable(lastSdkSystemMessage).map(SDKSystemMessage::getSessionId).orElse(null);
}
/**
* Checks if the session is available for operations.
*
* @return true if the session is available, false otherwise
*/
public boolean isAvailable() {
return transport.isAvailable();
}
/**
* Gets the capabilities of the CLI.
*
* @return A Capabilities object representing the CLI's capabilities
*/
public Capabilities getCapabilities() {
return Optional.ofNullable(lastCliControlInitializeResponse).map(CLIControlInitializeResponse::getCapabilities).orElse(new Capabilities());
}

View File

@@ -0,0 +1,62 @@
package com.alibaba.qwen.code.cli.session.event;
import com.alibaba.qwen.code.cli.protocol.data.AssistantUsage;
import com.alibaba.qwen.code.cli.protocol.data.AssistantContent;
import com.alibaba.qwen.code.cli.protocol.data.AssistantContent.TextAssistantContent;
import com.alibaba.qwen.code.cli.protocol.data.AssistantContent.ThingkingAssistantContent;
import com.alibaba.qwen.code.cli.protocol.data.AssistantContent.ToolResultAssistantContent;
import com.alibaba.qwen.code.cli.protocol.data.AssistantContent.ToolUseAssistantContent;
import com.alibaba.qwen.code.cli.session.Session;
/**
* Interface for handling different types of assistant content during a session.
*/
public interface AssistantContentConsumers {
/**
* Handles text content from the assistant.
*
* @param session The session
* @param textAssistantContent The text content from the assistant
*/
void onText(Session session, TextAssistantContent textAssistantContent);
/**
* Handles thinking content from the assistant.
*
* @param session The session
* @param thingkingAssistantContent The thinking content from the assistant
*/
void onThinking(Session session, ThingkingAssistantContent thingkingAssistantContent);
/**
* Handles tool use content from the assistant.
*
* @param session The session
* @param toolUseAssistantContent The tool use content from the assistant
*/
void onToolUse(Session session, ToolUseAssistantContent toolUseAssistantContent);
/**
* Handles tool result content from the assistant.
*
* @param session The session
* @param toolResultAssistantContent The tool result content from the assistant
*/
void onToolResult(Session session, ToolResultAssistantContent toolResultAssistantContent);
/**
* Handles other types of assistant content.
*
* @param session The session
* @param other The other content from the assistant
*/
void onOtherContent(Session session, AssistantContent<?> other);
/**
* Handles usage information from the assistant.
*
* @param session The session
* @param AssistantUsage The usage information from the assistant
*/
void onUsage(Session session, AssistantUsage AssistantUsage);
}

View File

@@ -0,0 +1,38 @@
package com.alibaba.qwen.code.cli.session.event;
import com.alibaba.qwen.code.cli.protocol.data.AssistantUsage;
import com.alibaba.qwen.code.cli.protocol.data.AssistantContent;
import com.alibaba.qwen.code.cli.protocol.data.AssistantContent.TextAssistantContent;
import com.alibaba.qwen.code.cli.protocol.data.AssistantContent.ThingkingAssistantContent;
import com.alibaba.qwen.code.cli.protocol.data.AssistantContent.ToolResultAssistantContent;
import com.alibaba.qwen.code.cli.protocol.data.AssistantContent.ToolUseAssistantContent;
import com.alibaba.qwen.code.cli.session.Session;
/**
* Simple implementation of AssistantContentConsumers that provides empty implementations for all methods.
*/
public class AssistantContentSimpleConsumers implements AssistantContentConsumers {
@Override
public void onText(Session session, TextAssistantContent textAssistantContent) {
}
@Override
public void onThinking(Session session, ThingkingAssistantContent thingkingAssistantContent) {
}
@Override
public void onToolUse(Session session, ToolUseAssistantContent toolUseAssistantContent) {
}
@Override
public void onToolResult(Session session, ToolResultAssistantContent toolResultAssistantContent) {
}
@Override
public void onOtherContent(Session session, AssistantContent<?> other) {
}
@Override
public void onUsage(Session session, AssistantUsage AssistantUsage) {
}
}

View File

@@ -12,40 +12,153 @@ import com.alibaba.qwen.code.cli.protocol.message.control.CLIControlResponse;
import com.alibaba.qwen.code.cli.session.Session;
import com.alibaba.qwen.code.cli.utils.Timeout;
/**
* Interface for handling different types of events during a session.
*/
public interface SessionEventConsumers {
/**
* Handles system messages.
*
* @param session The session
* @param systemMessage The system message
*/
void onSystemMessage(Session session, SDKSystemMessage systemMessage);
/**
* Handles result messages.
*
* @param session The session
* @param resultMessage The result message
*/
void onResultMessage(Session session, SDKResultMessage resultMessage);
/**
* Handles assistant messages.
*
* @param session The session
* @param assistantMessage The assistant message
*/
void onAssistantMessage(Session session, SDKAssistantMessage assistantMessage);
/**
* Handles partial assistant messages.
*
* @param session The session
* @param partialAssistantMessage The partial assistant message
*/
void onPartialAssistantMessage(Session session, SDKPartialAssistantMessage partialAssistantMessage);
/**
* Handles user messages.
*
* @param session The session
* @param userMessage The user message
*/
void onUserMessage(Session session, SDKUserMessage userMessage);
/**
* Handles other types of messages.
*
* @param session The session
* @param message The message
*/
void onOtherMessage(Session session, String message);
/**
* Handles control responses.
*
* @param session The session
* @param cliControlResponse The control response
*/
void onControlResponse(Session session, CLIControlResponse<?> cliControlResponse);
/**
* Handles control requests.
*
* @param session The session
* @param cliControlRequest The control request
* @return The control response
*/
CLIControlResponse<?> onControlRequest(Session session, CLIControlRequest<?> cliControlRequest);
/**
* Handles permission requests.
*
* @param session The session
* @param permissionRequest The permission request
* @return The behavior for the permission request
*/
Behavior onPermissionRequest(Session session, CLIControlRequest<CLIControlPermissionRequest> permissionRequest);
/**
* Gets timeout for system message handling.
*
* @param session The session
* @return The timeout for system message handling
*/
Timeout onSystemMessageTimeout(Session session);
/**
* Gets timeout for result message handling.
*
* @param session The session
* @return The timeout for result message handling
*/
Timeout onResultMessageTimeout(Session session);
/**
* Gets timeout for assistant message handling.
*
* @param session The session
* @return The timeout for assistant message handling
*/
Timeout onAssistantMessageTimeout(Session session);
/**
* Gets timeout for partial assistant message handling.
*
* @param session The session
* @return The timeout for partial assistant message handling
*/
Timeout onPartialAssistantMessageTimeout(Session session);
/**
* Gets timeout for user message handling.
*
* @param session The session
* @return The timeout for user message handling
*/
Timeout onUserMessageTimeout(Session session);
/**
* Gets timeout for other message handling.
*
* @param session The session
* @return The timeout for other message handling
*/
Timeout onOtherMessageTimeout(Session session);
/**
* Gets timeout for control response handling.
*
* @param session The session
* @return The timeout for control response handling
*/
Timeout onControlResponseTimeout(Session session);
/**
* Gets timeout for control request handling.
*
* @param session The session
* @return The timeout for control request handling
*/
Timeout onControlRequestTimeout(Session session);
/**
* Gets timeout for permission request handling.
*
* @param session The session
* @return The timeout for permission request handling
*/
Timeout onPermissionRequestTimeout(Session session);
}

View File

@@ -1,12 +1,13 @@
package com.alibaba.qwen.code.cli.session.event;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import com.alibaba.qwen.code.cli.protocol.data.AssistantContent;
import com.alibaba.qwen.code.cli.protocol.data.AssistantContent.TextAssistantContent;
import com.alibaba.qwen.code.cli.protocol.data.AssistantContent.ThingkingAssistantContent;
import com.alibaba.qwen.code.cli.protocol.data.AssistantContent.ToolResultAssistantContent;
import com.alibaba.qwen.code.cli.protocol.data.AssistantContent.ToolUseAssistantContent;
import com.alibaba.qwen.code.cli.protocol.data.AssistantUsage;
import com.alibaba.qwen.code.cli.protocol.data.behavior.Allow;
import com.alibaba.qwen.code.cli.protocol.data.behavior.Behavior;
import com.alibaba.qwen.code.cli.protocol.data.behavior.Behavior.Operation;
@@ -16,6 +17,7 @@ import com.alibaba.qwen.code.cli.protocol.message.SDKSystemMessage;
import com.alibaba.qwen.code.cli.protocol.message.SDKUserMessage;
import com.alibaba.qwen.code.cli.protocol.message.assistant.SDKAssistantMessage;
import com.alibaba.qwen.code.cli.protocol.message.assistant.SDKPartialAssistantMessage;
import com.alibaba.qwen.code.cli.protocol.message.assistant.block.ContentBlock;
import com.alibaba.qwen.code.cli.protocol.message.assistant.event.ContentBlockDeltaEvent;
import com.alibaba.qwen.code.cli.protocol.message.assistant.event.StreamEvent;
import com.alibaba.qwen.code.cli.protocol.message.control.CLIControlPermissionRequest;
@@ -24,6 +26,12 @@ import com.alibaba.qwen.code.cli.protocol.message.control.CLIControlResponse;
import com.alibaba.qwen.code.cli.session.Session;
import com.alibaba.qwen.code.cli.utils.Timeout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Simple implementation of SessionEventConsumers that provides basic implementations for all methods.
*/
public class SessionEventSimpleConsumers implements SessionEventConsumers {
@Override
public void onSystemMessage(Session session, SDKSystemMessage systemMessage) {
@@ -35,22 +43,42 @@ public class SessionEventSimpleConsumers implements SessionEventConsumers {
@Override
public void onAssistantMessage(Session session, SDKAssistantMessage assistantMessage) {
onAssistantMessageIncludePartial(session, Optional.ofNullable(assistantMessage.getMessage().getContent())
.map(cbs -> cbs.stream().map(cb -> (AssistantContent) cb).collect(Collectors.toList()))
.orElse(new ArrayList<>()), AssistantMessageOutputType.entire);
List<ContentBlock<?>> contentBlocks = assistantMessage.getMessage().getContent();
if (assistantContentConsumers == null || contentBlocks == null || contentBlocks.isEmpty()) {
return;
}
assistantContentConsumers.onUsage(session, new AssistantUsage(assistantMessage.getMessage().getId(), assistantMessage.getMessage().getUsage()));
if (!session.isStreaming()) {
contentBlocks.forEach(contentBlock -> consumeAssistantContent(session, contentBlock));
}
}
@Override
public void onPartialAssistantMessage(Session session, SDKPartialAssistantMessage partialAssistantMessage) {
StreamEvent event = partialAssistantMessage.getEvent();
if (!(event instanceof ContentBlockDeltaEvent)) {
log.debug("received partialAssistantMessage and is not instance of ContentBlockDeltaEvent, will ignore process. the message is {}",
partialAssistantMessage);
return;
}
onAssistantMessageIncludePartial(session, Collections.singletonList(((ContentBlockDeltaEvent) event).getDelta()), AssistantMessageOutputType.partial);
ContentBlockDeltaEvent contentBlockDeltaEvent = (ContentBlockDeltaEvent) event;
contentBlockDeltaEvent.getDelta().setMessageId(partialAssistantMessage.getMessageId());
consumeAssistantContent(session, contentBlockDeltaEvent.getDelta());
}
public void onAssistantMessageIncludePartial(Session session, List<AssistantContent> assistantContents,
AssistantMessageOutputType assistantMessageOutputType) {
protected void consumeAssistantContent(Session session, AssistantContent<?> assistantContent) {
if (assistantContent instanceof TextAssistantContent) {
assistantContentConsumers.onText(session, (TextAssistantContent) assistantContent);
} else if (assistantContent instanceof ThingkingAssistantContent) {
assistantContentConsumers.onThinking(session, (ThingkingAssistantContent) assistantContent);
} else if (assistantContent instanceof ToolUseAssistantContent) {
assistantContentConsumers.onToolUse(session, (ToolUseAssistantContent) assistantContent);
} else if (assistantContent instanceof ToolResultAssistantContent) {
assistantContentConsumers.onToolResult(session, (ToolResultAssistantContent) assistantContent);
} else {
assistantContentConsumers.onOtherContent(session, assistantContent);
}
}
@Override
@@ -124,37 +152,88 @@ public class SessionEventSimpleConsumers implements SessionEventConsumers {
return defaultEventTimeout;
}
public Timeout getDefaultEventTimeout() {
/**
* Gets the default event timeout.
*
* @return The default event timeout
*/
protected Timeout getDefaultEventTimeout() {
return defaultEventTimeout;
}
/**
* Sets the default event timeout.
*
* @param defaultEventTimeout The default event timeout
* @return This instance for method chaining
*/
public SessionEventSimpleConsumers setDefaultEventTimeout(Timeout defaultEventTimeout) {
this.defaultEventTimeout = defaultEventTimeout;
return this;
}
public Operation getDefaultPermissionOperation() {
/**
* Gets the default permission operation.
*
* @return The default permission operation
*/
protected Operation getDefaultPermissionOperation() {
return defaultPermissionOperation;
}
/**
* Sets the default permission operation.
*
* @param defaultPermissionOperation The default permission operation
* @return This instance for method chaining
*/
public SessionEventSimpleConsumers setDefaultPermissionOperation(Operation defaultPermissionOperation) {
this.defaultPermissionOperation = defaultPermissionOperation;
return this;
}
/**
* Creates a new SessionEventSimpleConsumers instance with default values.
*/
public SessionEventSimpleConsumers() {
}
public SessionEventSimpleConsumers(Operation defaultPermissionOperation, Timeout defaultEventTimeout) {
/**
* Creates a new SessionEventSimpleConsumers instance with the specified parameters.
*
* @param defaultPermissionOperation The default permission operation
* @param defaultEventTimeout The default event timeout
* @param assistantContentConsumers The assistant content consumers
*/
public SessionEventSimpleConsumers(Operation defaultPermissionOperation, Timeout defaultEventTimeout,
AssistantContentConsumers assistantContentConsumers) {
this.defaultPermissionOperation = defaultPermissionOperation;
this.defaultEventTimeout = defaultEventTimeout;
this.assistantContentConsumers = assistantContentConsumers;
}
/**
* The default permission operation.
*/
private Operation defaultPermissionOperation = Operation.deny;
/**
* The default event timeout.
*/
protected Timeout defaultEventTimeout = Timeout.TIMEOUT_60_SECONDS;
/**
* The assistant content consumers.
*/
protected AssistantContentConsumers assistantContentConsumers;
private static final Logger log = LoggerFactory.getLogger(SessionEventSimpleConsumers.class);
public enum AssistantMessageOutputType {
entire,
partial
/**
* Sets the assistant content consumers.
*
* @param assistantContentConsumers The assistant content consumers
* @return This instance for method chaining
*/
public SessionEventSimpleConsumers setBlockConsumer(AssistantContentConsumers assistantContentConsumers) {
this.assistantContentConsumers = assistantContentConsumers;
return this;
}
}

View File

@@ -1,21 +1,51 @@
package com.alibaba.qwen.code.cli.session.exception;
/**
* Exception thrown when a session control operation fails.
*/
public class SessionControlException extends Exception {
/**
* Creates a new exception.
*/
public SessionControlException() {
}
/**
* Creates a new exception with a message.
*
* @param message The exception message
*/
public SessionControlException(String message) {
super(message);
}
/**
* Creates a new exception with a message and cause.
*
* @param message The exception message
* @param cause The exception cause
*/
public SessionControlException(String message, Throwable cause) {
super(message, cause);
}
/**
* Creates a new exception with a cause.
*
* @param cause The exception cause
*/
public SessionControlException(Throwable cause) {
super(cause);
}
/**
* Creates a new exception with all parameters.
*
* @param message The exception message
* @param cause The exception cause
* @param enableSuppression Whether suppression is enabled
* @param writableStackTrace Whether the stack trace is writable
*/
public SessionControlException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}

View File

@@ -1,21 +1,51 @@
package com.alibaba.qwen.code.cli.session.exception;
/**
* Exception thrown when sending a prompt in a session fails.
*/
public class SessionSendPromptException extends Exception {
/**
* Creates a new exception.
*/
public SessionSendPromptException() {
}
/**
* Creates a new exception with a message.
*
* @param message The exception message
*/
public SessionSendPromptException(String message) {
super(message);
}
/**
* Creates a new exception with a message and cause.
*
* @param message The exception message
* @param cause The exception cause
*/
public SessionSendPromptException(String message, Throwable cause) {
super(message, cause);
}
/**
* Creates a new exception with a cause.
*
* @param cause The exception cause
*/
public SessionSendPromptException(Throwable cause) {
super(cause);
}
/**
* Creates a new exception with all parameters.
*
* @param message The exception message
* @param cause The exception cause
* @param enableSuppression Whether suppression is enabled
* @param writableStackTrace Whether the stack trace is writable
*/
public SessionSendPromptException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}

View File

@@ -5,20 +5,71 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import java.util.function.Function;
/**
* Defines the contract for communication with the Qwen Code CLI.
*/
public interface Transport {
/**
* Gets the transport options used by this transport.
*
* @return The transport options
*/
TransportOptions getTransportOptions();
/**
* Checks if the transport is currently reading.
*
* @return true if reading, false otherwise
*/
boolean isReading();
/**
* Starts the transport.
*
* @throws IOException if starting fails
*/
void start() throws IOException;
/**
* Closes the transport and releases resources.
*
* @throws IOException if closing fails
*/
void close() throws IOException;
/**
* Checks if the transport is available for communication.
*
* @return true if available, false otherwise
*/
boolean isAvailable();
/**
* Sends a message and waits for a single-line response.
*
* @param message The message to send
* @return The response message
* @throws IOException if an I/O error occurs
* @throws ExecutionException if an execution error occurs
* @throws InterruptedException if the operation is interrupted
* @throws TimeoutException if the operation times out
*/
String inputWaitForOneLine(String message) throws IOException, ExecutionException, InterruptedException, TimeoutException;
/**
* Sends a message and waits for a multi-line response.
*
* @param message The message to send
* @param callBackFunction A function to process each line of the response
* @throws IOException if an I/O error occurs
*/
void inputWaitForMultiLine(String message, Function<String, Boolean> callBackFunction) throws IOException;
/**
* Sends a message without waiting for a response.
*
* @param message The message to send
* @throws IOException if an I/O error occurs
*/
void inputNoWaitResponse(String message) throws IOException;
}

View File

@@ -6,163 +6,390 @@ import java.util.Map;
import com.alibaba.qwen.code.cli.protocol.data.PermissionMode;
import com.alibaba.qwen.code.cli.utils.Timeout;
/**
* Configuration options for the transport layer.
*/
public class TransportOptions implements Cloneable {
/**
* Path to the Qwen executable.
*/
private String pathToQwenExecutable;
/**
* Current working directory for the CLI process.
*/
private String cwd;
/**
* Model to use for the session.
*/
private String model;
/**
* Permission mode for the session.
*/
private PermissionMode permissionMode;
/**
* Environment variables to pass to the CLI process.
*/
private Map<String, String> env;
/**
* Maximum number of turns in a session.
*/
private Integer maxSessionTurns;
/**
* List of core tools to enable.
*/
private List<String> coreTools;
/**
* List of tools to exclude.
*/
private List<String> excludeTools;
/**
* List of tools that are allowed.
*/
private List<String> allowedTools;
/**
* Authentication type to use.
*/
private String authType;
/**
* Whether to include partial messages in responses.
*/
private Boolean includePartialMessages;
/**
* Whether to enable skills.
*/
private Boolean skillsEnable;
/**
* Timeout for individual turns.
*/
private Timeout turnTimeout;
/**
* Timeout for messages.
*/
private Timeout messageTimeout;
/**
* Session ID to resume.
*/
private String resumeSessionId;
/**
* Additional options to pass to the CLI.
*/
private List<String> otherOptions;
/**
* Gets the path to the Qwen executable.
*
* @return The path to the Qwen executable
*/
public String getPathToQwenExecutable() {
return pathToQwenExecutable;
}
/**
* Sets the path to the Qwen executable.
*
* @param pathToQwenExecutable The path to the Qwen executable
* @return This instance for method chaining
*/
public TransportOptions setPathToQwenExecutable(String pathToQwenExecutable) {
this.pathToQwenExecutable = pathToQwenExecutable;
return this;
}
/**
* Gets the current working directory.
*
* @return The current working directory
*/
public String getCwd() {
return cwd;
}
/**
* Sets the current working directory.
*
* @param cwd The current working directory
* @return This instance for method chaining
*/
public TransportOptions setCwd(String cwd) {
this.cwd = cwd;
return this;
}
/**
* Gets the model to use.
*
* @return The model name
*/
public String getModel() {
return model;
}
/**
* Sets the model to use.
*
* @param model The model name
* @return This instance for method chaining
*/
public TransportOptions setModel(String model) {
this.model = model;
return this;
}
/**
* Gets the permission mode.
*
* @return The permission mode
*/
public PermissionMode getPermissionMode() {
return permissionMode;
}
/**
* Sets the permission mode.
*
* @param permissionMode The permission mode
* @return This instance for method chaining
*/
public TransportOptions setPermissionMode(PermissionMode permissionMode) {
this.permissionMode = permissionMode;
return this;
}
/**
* Gets the environment variables.
*
* @return A map of environment variables
*/
public Map<String, String> getEnv() {
return env;
}
/**
* Sets the environment variables.
*
* @param env A map of environment variables
* @return This instance for method chaining
*/
public TransportOptions setEnv(Map<String, String> env) {
this.env = env;
return this;
}
/**
* Gets the maximum number of session turns.
*
* @return The maximum number of session turns
*/
public Integer getMaxSessionTurns() {
return maxSessionTurns;
}
/**
* Sets the maximum number of session turns.
*
* @param maxSessionTurns The maximum number of session turns
* @return This instance for method chaining
*/
public TransportOptions setMaxSessionTurns(Integer maxSessionTurns) {
this.maxSessionTurns = maxSessionTurns;
return this;
}
/**
* Gets the list of core tools.
*
* @return The list of core tools
*/
public List<String> getCoreTools() {
return coreTools;
}
/**
* Sets the list of core tools.
*
* @param coreTools The list of core tools
* @return This instance for method chaining
*/
public TransportOptions setCoreTools(List<String> coreTools) {
this.coreTools = coreTools;
return this;
}
/**
* Gets the list of excluded tools.
*
* @return The list of excluded tools
*/
public List<String> getExcludeTools() {
return excludeTools;
}
/**
* Sets the list of excluded tools.
*
* @param excludeTools The list of excluded tools
* @return This instance for method chaining
*/
public TransportOptions setExcludeTools(List<String> excludeTools) {
this.excludeTools = excludeTools;
return this;
}
/**
* Gets the list of allowed tools.
*
* @return The list of allowed tools
*/
public List<String> getAllowedTools() {
return allowedTools;
}
/**
* Sets the list of allowed tools.
*
* @param allowedTools The list of allowed tools
* @return This instance for method chaining
*/
public TransportOptions setAllowedTools(List<String> allowedTools) {
this.allowedTools = allowedTools;
return this;
}
/**
* Gets the authentication type.
*
* @return The authentication type
*/
public String getAuthType() {
return authType;
}
/**
* Sets the authentication type.
*
* @param authType The authentication type
* @return This instance for method chaining
*/
public TransportOptions setAuthType(String authType) {
this.authType = authType;
return this;
}
/**
* Gets whether to include partial messages.
*
* @return Whether to include partial messages
*/
public Boolean getIncludePartialMessages() {
return includePartialMessages;
}
/**
* Sets whether to include partial messages.
*
* @param includePartialMessages Whether to include partial messages
* @return This instance for method chaining
*/
public TransportOptions setIncludePartialMessages(Boolean includePartialMessages) {
this.includePartialMessages = includePartialMessages;
return this;
}
/**
* Gets whether skills are enabled.
*
* @return Whether skills are enabled
*/
public Boolean getSkillsEnable() {
return skillsEnable;
}
/**
* Sets whether skills are enabled.
*
* @param skillsEnable Whether skills are enabled
* @return This instance for method chaining
*/
public TransportOptions setSkillsEnable(Boolean skillsEnable) {
this.skillsEnable = skillsEnable;
return this;
}
/**
* Gets the turn timeout.
*
* @return The turn timeout
*/
public Timeout getTurnTimeout() {
return turnTimeout;
}
/**
* Sets the turn timeout.
*
* @param turnTimeout The turn timeout
* @return This instance for method chaining
*/
public TransportOptions setTurnTimeout(Timeout turnTimeout) {
this.turnTimeout = turnTimeout;
return this;
}
/**
* Gets the message timeout.
*
* @return The message timeout
*/
public Timeout getMessageTimeout() {
return messageTimeout;
}
/**
* Sets the message timeout.
*
* @param messageTimeout The message timeout
* @return This instance for method chaining
*/
public TransportOptions setMessageTimeout(Timeout messageTimeout) {
this.messageTimeout = messageTimeout;
return this;
}
/**
* Gets the session ID to resume.
*
* @return The session ID to resume
*/
public String getResumeSessionId() {
return resumeSessionId;
}
/**
* Sets the session ID to resume.
*
* @param resumeSessionId The session ID to resume
* @return This instance for method chaining
*/
public TransportOptions setResumeSessionId(String resumeSessionId) {
this.resumeSessionId = resumeSessionId;
return this;
}
/**
* Gets additional options.
*
* @return Additional options
*/
public List<String> getOtherOptions() {
return otherOptions;
}
/**
* Sets additional options.
*
* @param otherOptions Additional options
* @return This instance for method chaining
*/
public TransportOptions setOtherOptions(List<String> otherOptions) {
this.otherOptions = otherOptions;
return this;

View File

@@ -22,6 +22,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import java.util.function.Function;
/**
* Implementation of the Transport interface that communicates with the Qwen CLI via a process.
*/
public class ProcessTransport implements Transport {
private static final Logger log = LoggerFactory.getLogger(ProcessTransport.class);
private final TransportOptions transportOptions;
@@ -36,14 +39,32 @@ public class ProcessTransport implements Transport {
private final AtomicBoolean reading = new AtomicBoolean(false);
/**
* Constructs a new ProcessTransport with default options.
*
* @throws IOException if starting the process fails
*/
public ProcessTransport() throws IOException {
this(new TransportOptions());
}
/**
* Constructs a new ProcessTransport with the specified options.
*
* @param transportOptions The transport options to use
* @throws IOException if starting the process fails
*/
public ProcessTransport(TransportOptions transportOptions) throws IOException {
this(transportOptions, (line) -> log.error("process error: {}", line));
}
/**
* Constructs a new ProcessTransport with the specified options and error handler.
*
* @param transportOptions The transport options to use
* @param errorHandler The error handler to use
* @throws IOException if starting the process fails
*/
public ProcessTransport(TransportOptions transportOptions, Consumer<String> errorHandler) throws IOException {
this.transportOptions = transportOptions;
this.errorHandler = errorHandler;

View File

@@ -14,23 +14,55 @@ import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
/**
* Adapter that converts TransportOptions to command-line arguments for the CLI process.
*/
class TransportOptionsAdapter {
/**
* The adapted transport options.
*/
TransportOptions transportOptions;
/**
* Default timeout for turns.
*/
private static final Timeout DEFAULT_TURN_TIMEOUT = new Timeout(1000 * 60 * 30L, TimeUnit.MILLISECONDS);
/**
* Default timeout for messages.
*/
private static final Timeout DEFAULT_MESSAGE_TIMEOUT = new Timeout(1000 * 60 * 3L, TimeUnit.MILLISECONDS);
/**
* Constructs a new adapter with the specified options.
*
* @param userTransportOptions The user's transport options
*/
TransportOptionsAdapter(TransportOptions userTransportOptions) {
transportOptions = addDefaultTransportOptions(userTransportOptions);
}
/**
* Gets the processed transport options.
*
* @return The processed transport options
*/
TransportOptions getHandledTransportOptions() {
return transportOptions;
}
/**
* Gets the current working directory.
*
* @return The current working directory
*/
String getCwd() {
return transportOptions.getCwd();
}
/**
* Builds command-line arguments from the transport options.
*
* @return An array of command-line arguments
*/
String[] buildCommandArgs() {
List<String> args = new ArrayList<>(
Arrays.asList(transportOptions.getPathToQwenExecutable(), "--input-format", "stream-json", "--output-format",
@@ -90,6 +122,12 @@ class TransportOptionsAdapter {
return args.toArray(new String[] {});
}
/**
* Adds default values to the user's transport options.
*
* @param userTransportOptions The user's transport options
* @return The options with defaults added
*/
private TransportOptions addDefaultTransportOptions(TransportOptions userTransportOptions) {
TransportOptions transportOptions = Optional.ofNullable(userTransportOptions)
.map(TransportOptions::clone)

View File

@@ -9,9 +9,18 @@ import java.util.function.Supplier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Utility class for concurrent operations.
*/
public class MyConcurrentUtils {
private static final Logger log = LoggerFactory.getLogger(MyConcurrentUtils.class);
/**
* Runs a task and waits for it to complete with a timeout.
*
* @param runnable The task to run
* @param timeOut The timeout for the operation
*/
public static void runAndWait(Runnable runnable, Timeout timeOut) {
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
try {
@@ -34,6 +43,17 @@ public class MyConcurrentUtils {
}
}
/**
* Runs a task that returns a value and waits for it to complete with a timeout.
*
* @param supplier The task to run
* @param timeOut The timeout for the operation
* @param <T> The type of the result
* @return The result of the task
* @throws ExecutionException if an execution error occurs
* @throws InterruptedException if the operation is interrupted
* @throws TimeoutException if the operation times out
*/
public static <T> T runAndWait(Supplier<T> supplier, Timeout timeOut)
throws ExecutionException, InterruptedException, TimeoutException {
CompletableFuture<T> future = CompletableFuture.supplyAsync(() -> {
@@ -52,6 +72,12 @@ public class MyConcurrentUtils {
}
}
/**
* Runs a task asynchronously with an error callback.
*
* @param runnable The task to run
* @param errorCallback The error callback
*/
public static void asyncRun(Runnable runnable, BiConsumer<Void, Throwable> errorCallback) {
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
try {

View File

@@ -9,6 +9,9 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;
/**
* Configuration for the thread pool used by the SDK.
*/
public class ThreadPoolConfig {
private static final ThreadPoolExecutor defaultExecutor = new ThreadPoolExecutor(
10, 30, 60L, TimeUnit.SECONDS,
@@ -27,10 +30,21 @@ public class ThreadPoolConfig {
);
private static Supplier<ThreadPoolExecutor> executorSupplier;
/**
* Sets the supplier for the executor.
*
* @param executorSupplier The supplier for the executor
*/
public static void setExecutorSupplier(Supplier<ThreadPoolExecutor> executorSupplier) {
ThreadPoolConfig.executorSupplier = executorSupplier;
}
/**
* Gets the default executor.
*
* @return The default executor
*/
public static ThreadPoolExecutor getDefaultExecutor() {
return defaultExecutor;
}

View File

@@ -4,9 +4,25 @@ import java.util.concurrent.TimeUnit;
import org.apache.commons.lang3.Validate;
/**
* Represents a timeout value with a time unit.
*/
public class Timeout {
/**
* The timeout value.
*/
private final Long value;
/**
* The time unit.
*/
private final TimeUnit unit;
/**
* Creates a new Timeout instance.
*
* @param value The timeout value
* @param unit The time unit
*/
public Timeout(Long value, TimeUnit unit) {
Validate.notNull(value, "value can not be null");
Validate.notNull(unit, "unit can not be null");
@@ -14,14 +30,30 @@ public class Timeout {
this.unit = unit;
}
/**
* Gets the timeout value.
*
* @return The timeout value
*/
public Long getValue() {
return value;
}
/**
* Gets the time unit.
*
* @return The time unit
*/
public TimeUnit getUnit() {
return unit;
}
/**
* A timeout of 60 seconds.
*/
public static final Timeout TIMEOUT_60_SECONDS = new Timeout(60L, TimeUnit.SECONDS);
/**
* A timeout of 30 minutes.
*/
public static final Timeout TIMEOUT_30_MINUTES = new Timeout(60L, TimeUnit.MINUTES);
}

View File

@@ -2,6 +2,8 @@ package com.alibaba.qwen.code.cli;
import java.util.List;
import com.alibaba.qwen.code.cli.transport.TransportOptions;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -14,7 +16,14 @@ class QwenCodeCliTest {
@Test
void simpleQuery() {
List<String> result = QwenCodeCli.simpleQuery("hello world");
log.info("result: {}", result);
log.info("simpleQuery result: {}", result);
assertNotNull(result);
}
@Test
void simpleQueryWithModel() {
List<String> result = QwenCodeCli.simpleQuery("hello world", new TransportOptions().setModel("qwen-plus"));
log.info("simpleQueryWithModel result: {}", result);
assertNotNull(result);
}
}

View File

@@ -1,13 +1,16 @@
package com.alibaba.qwen.code.cli.session;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;
import com.alibaba.fastjson2.JSON;
import com.alibaba.qwen.code.cli.QwenCodeCli;
import com.alibaba.qwen.code.cli.protocol.data.AssistantUsage;
import com.alibaba.qwen.code.cli.protocol.data.AssistantContent;
import com.alibaba.qwen.code.cli.protocol.data.PermissionMode;
import com.alibaba.qwen.code.cli.protocol.data.AssistantContent.TextAssistantContent;
import com.alibaba.qwen.code.cli.protocol.data.AssistantContent.ThingkingAssistantContent;
import com.alibaba.qwen.code.cli.protocol.data.AssistantContent.ToolResultAssistantContent;
import com.alibaba.qwen.code.cli.protocol.data.AssistantContent.ToolUseAssistantContent;
import com.alibaba.qwen.code.cli.protocol.data.behavior.Allow;
import com.alibaba.qwen.code.cli.protocol.data.behavior.Behavior;
import com.alibaba.qwen.code.cli.protocol.data.behavior.Behavior.Operation;
@@ -17,6 +20,7 @@ import com.alibaba.qwen.code.cli.protocol.message.assistant.SDKAssistantMessage;
import com.alibaba.qwen.code.cli.protocol.message.control.CLIControlPermissionRequest;
import com.alibaba.qwen.code.cli.protocol.message.control.CLIControlRequest;
import com.alibaba.qwen.code.cli.protocol.message.control.CLIControlResponse;
import com.alibaba.qwen.code.cli.session.event.AssistantContentConsumers;
import com.alibaba.qwen.code.cli.session.event.SessionEventConsumers;
import com.alibaba.qwen.code.cli.session.event.SessionEventSimpleConsumers;
import com.alibaba.qwen.code.cli.session.exception.SessionControlException;
@@ -34,19 +38,43 @@ class SessionTest {
private static final Logger log = LoggerFactory.getLogger(SessionTest.class);
@Test
void partialSendPromptSuccessfully() throws IOException, SessionControlException, SessionSendPromptException {
void partialSendPromptSuccessfully() throws SessionControlException, SessionSendPromptException {
Session session = QwenCodeCli.newSession(new TransportOptions().setIncludePartialMessages(true));
session.sendPrompt("in the dir src/test/temp/, create file empty file test.touch", new SessionEventSimpleConsumers() {
}.setDefaultPermissionOperation(Operation.allow).setBlockConsumer(new AssistantContentConsumers() {
@Override
public void onAssistantMessageIncludePartial(Session session, List<AssistantContent> assistantContents,
AssistantMessageOutputType assistantMessageOutputType) {
log.info("onAssistantMessageIncludePartial: {}", JSON.toJSONString(assistantContents));
public void onText(Session session, TextAssistantContent textAssistantContent) {
log.info("receive textAssistantContent {}", textAssistantContent);
}
}.setDefaultPermissionOperation(Operation.allow));
@Override
public void onThinking(Session session, ThingkingAssistantContent thingkingAssistantContent) {
log.info("receive thingkingAssistantContent {}", thingkingAssistantContent);
}
@Override
public void onToolUse(Session session, ToolUseAssistantContent toolUseAssistantContent) {
log.info("receive toolUseAssistantContent {}", toolUseAssistantContent);
}
@Override
public void onToolResult(Session session, ToolResultAssistantContent toolResultAssistantContent) {
log.info("receive toolResultAssistantContent {}", toolResultAssistantContent);
}
public void onOtherContent(Session session, AssistantContent<?> other) {
log.info("receive otherContent {}", other);
}
@Override
public void onUsage(Session session, AssistantUsage assistantUsage) {
log.info("receive assistantUsage {}", assistantUsage);
}
}));
}
@Test
void setPermissionModeSuccessfully() throws IOException, SessionControlException, SessionSendPromptException {
void setPermissionModeSuccessfully() throws SessionControlException, SessionSendPromptException {
Session session = QwenCodeCli.newSession(new TransportOptions());
log.info(session.setPermissionMode(PermissionMode.YOLO).map(s -> s ? "setPermissionMode 1 success" : "setPermissionMode 1 error")
@@ -72,7 +100,7 @@ class SessionTest {
}
@Test
void sendPromptAndSetModelSuccessfully() throws IOException, SessionControlException, SessionSendPromptException {
void sendPromptAndSetModelSuccessfully() throws SessionControlException, SessionSendPromptException {
Session session = QwenCodeCli.newSession(new TransportOptions());
log.info(session.setModel("qwen3-coder-flash").map(s -> s ? "setModel 1 success" : "setModel 1 error").orElse("setModel 1 unknown"));
@@ -97,7 +125,7 @@ class SessionTest {
}
@Test
void sendPromptAndInterruptContinueSuccessfully() throws IOException, SessionControlException, SessionSendPromptException {
void sendPromptAndInterruptContinueSuccessfully() throws SessionControlException, SessionSendPromptException {
Session session = QwenCodeCli.newSession();
SessionEventConsumers sessionEventConsumers = new SessionEventSimpleConsumers() {