diff --git a/acp-model/api/acp-model.api b/acp-model/api/acp-model.api index 3ab25c3..c7f1989 100644 --- a/acp-model/api/acp-model.api +++ b/acp-model/api/acp-model.api @@ -66,6 +66,10 @@ public final class com/agentclientprotocol/model/AcpMethod$AgentMethods$SessionP public static final field INSTANCE Lcom/agentclientprotocol/model/AcpMethod$AgentMethods$SessionPrompt; } +public final class com/agentclientprotocol/model/AcpMethod$AgentMethods$SessionResume : com/agentclientprotocol/model/AcpMethod$AcpSessionRequestResponseMethod { + public static final field INSTANCE Lcom/agentclientprotocol/model/AcpMethod$AgentMethods$SessionResume; +} + public final class com/agentclientprotocol/model/AcpMethod$AgentMethods$SessionSetMode : com/agentclientprotocol/model/AcpMethod$AcpSessionRequestResponseMethod { public static final field INSTANCE Lcom/agentclientprotocol/model/AcpMethod$AgentMethods$SessionSetMode; } @@ -2005,6 +2009,73 @@ public final class com/agentclientprotocol/model/ResourceLink$Companion { public final fun serializer ()Lkotlinx/serialization/KSerializer; } +public final class com/agentclientprotocol/model/ResumeSessionRequest : com/agentclientprotocol/model/AcpRequest, com/agentclientprotocol/model/AcpWithSessionId { + public static final field Companion Lcom/agentclientprotocol/model/ResumeSessionRequest$Companion; + public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Lkotlinx/serialization/json/JsonElement;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Lkotlinx/serialization/json/JsonElement;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1-7EW-EgU ()Ljava/lang/String; + public final fun component2 ()Ljava/lang/String; + public final fun component3 ()Ljava/util/List; + public final fun component4 ()Lkotlinx/serialization/json/JsonElement; + public final fun copy-wPMwmcM (Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Lkotlinx/serialization/json/JsonElement;)Lcom/agentclientprotocol/model/ResumeSessionRequest; + public static synthetic fun copy-wPMwmcM$default (Lcom/agentclientprotocol/model/ResumeSessionRequest;Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Lkotlinx/serialization/json/JsonElement;ILjava/lang/Object;)Lcom/agentclientprotocol/model/ResumeSessionRequest; + public fun equals (Ljava/lang/Object;)Z + public final fun getCwd ()Ljava/lang/String; + public final fun getMcpServers ()Ljava/util/List; + public fun getSessionId-7EW-EgU ()Ljava/lang/String; + public fun get_meta ()Lkotlinx/serialization/json/JsonElement; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final synthetic class com/agentclientprotocol/model/ResumeSessionRequest$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lcom/agentclientprotocol/model/ResumeSessionRequest$$serializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/agentclientprotocol/model/ResumeSessionRequest; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lcom/agentclientprotocol/model/ResumeSessionRequest;)V + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; +} + +public final class com/agentclientprotocol/model/ResumeSessionRequest$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + +public final class com/agentclientprotocol/model/ResumeSessionResponse : com/agentclientprotocol/model/AcpCreatedSessionResponse, com/agentclientprotocol/model/AcpResponse { + public static final field Companion Lcom/agentclientprotocol/model/ResumeSessionResponse$Companion; + public fun ()V + public fun (Lcom/agentclientprotocol/model/SessionModeState;Lcom/agentclientprotocol/model/SessionModelState;Lkotlinx/serialization/json/JsonElement;)V + public synthetic fun (Lcom/agentclientprotocol/model/SessionModeState;Lcom/agentclientprotocol/model/SessionModelState;Lkotlinx/serialization/json/JsonElement;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1 ()Lcom/agentclientprotocol/model/SessionModeState; + public final fun component2 ()Lcom/agentclientprotocol/model/SessionModelState; + public final fun component3 ()Lkotlinx/serialization/json/JsonElement; + public final fun copy (Lcom/agentclientprotocol/model/SessionModeState;Lcom/agentclientprotocol/model/SessionModelState;Lkotlinx/serialization/json/JsonElement;)Lcom/agentclientprotocol/model/ResumeSessionResponse; + public static synthetic fun copy$default (Lcom/agentclientprotocol/model/ResumeSessionResponse;Lcom/agentclientprotocol/model/SessionModeState;Lcom/agentclientprotocol/model/SessionModelState;Lkotlinx/serialization/json/JsonElement;ILjava/lang/Object;)Lcom/agentclientprotocol/model/ResumeSessionResponse; + public fun equals (Ljava/lang/Object;)Z + public fun getModels ()Lcom/agentclientprotocol/model/SessionModelState; + public fun getModes ()Lcom/agentclientprotocol/model/SessionModeState; + public fun get_meta ()Lkotlinx/serialization/json/JsonElement; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final synthetic class com/agentclientprotocol/model/ResumeSessionResponse$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lcom/agentclientprotocol/model/ResumeSessionResponse$$serializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/agentclientprotocol/model/ResumeSessionResponse; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lcom/agentclientprotocol/model/ResumeSessionResponse;)V + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; +} + +public final class com/agentclientprotocol/model/ResumeSessionResponse$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + public final class com/agentclientprotocol/model/Role : java/lang/Enum { public static final field ASSISTANT Lcom/agentclientprotocol/model/Role; public static final field Companion Lcom/agentclientprotocol/model/Role$Companion; @@ -2021,12 +2092,14 @@ public final class com/agentclientprotocol/model/Role$Companion { public final class com/agentclientprotocol/model/SessionCapabilities : com/agentclientprotocol/model/AcpWithMeta { public static final field Companion Lcom/agentclientprotocol/model/SessionCapabilities$Companion; public fun ()V - public fun (Lkotlinx/serialization/json/JsonElement;)V - public synthetic fun (Lkotlinx/serialization/json/JsonElement;ILkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun component1 ()Lkotlinx/serialization/json/JsonElement; - public final fun copy (Lkotlinx/serialization/json/JsonElement;)Lcom/agentclientprotocol/model/SessionCapabilities; - public static synthetic fun copy$default (Lcom/agentclientprotocol/model/SessionCapabilities;Lkotlinx/serialization/json/JsonElement;ILjava/lang/Object;)Lcom/agentclientprotocol/model/SessionCapabilities; + public fun (ZLkotlinx/serialization/json/JsonElement;)V + public synthetic fun (ZLkotlinx/serialization/json/JsonElement;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1 ()Z + public final fun component2 ()Lkotlinx/serialization/json/JsonElement; + public final fun copy (ZLkotlinx/serialization/json/JsonElement;)Lcom/agentclientprotocol/model/SessionCapabilities; + public static synthetic fun copy$default (Lcom/agentclientprotocol/model/SessionCapabilities;ZLkotlinx/serialization/json/JsonElement;ILjava/lang/Object;)Lcom/agentclientprotocol/model/SessionCapabilities; public fun equals (Ljava/lang/Object;)Z + public final fun getResume ()Z public fun get_meta ()Lkotlinx/serialization/json/JsonElement; public fun hashCode ()I public fun toString ()Ljava/lang/String; diff --git a/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/Capabilities.kt b/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/Capabilities.kt index a06c3e7..503dd4d 100644 --- a/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/Capabilities.kt +++ b/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/Capabilities.kt @@ -68,6 +68,7 @@ public data class McpCapabilities( */ @Serializable public data class SessionCapabilities( + @EncodeDefault val resume: Boolean = false, override val _meta: JsonElement? = null ) : AcpWithMeta diff --git a/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/Methods.kt b/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/Methods.kt index e39fb2a..564bfea 100644 --- a/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/Methods.kt +++ b/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/Methods.kt @@ -46,6 +46,8 @@ public open class AcpMethod(public val methodName: MethodName) { public object Authenticate : AcpRequestResponseMethod("authenticate", AuthenticateRequest.serializer(), AuthenticateResponse.serializer()) public object SessionNew : AcpRequestResponseMethod("session/new", NewSessionRequest.serializer(), NewSessionResponse.serializer()) public object SessionLoad : AcpRequestResponseMethod("session/load", LoadSessionRequest.serializer(), LoadSessionResponse.serializer()) + @UnstableApi + public object SessionResume : AcpSessionRequestResponseMethod("session/resume", ResumeSessionRequest.serializer(), ResumeSessionResponse.serializer()) // session specific public object SessionPrompt : AcpSessionRequestResponseMethod("session/prompt", PromptRequest.serializer(), PromptResponse.serializer()) diff --git a/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/Requests.kt b/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/Requests.kt index fd530d5..8d2650a 100644 --- a/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/Requests.kt +++ b/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/Requests.kt @@ -211,6 +211,27 @@ public data class LoadSessionRequest( override val _meta: JsonElement? = null ) : AcpRequest, AcpWithSessionId +/** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Request parameters for resuming an existing session. + * + * Resumes an existing session without returning previous messages (unlike `session/load`). + * This is useful for agents that can resume sessions but don't implement full session loading. + * + * Only available if the Agent supports the `session.resume` capability. + */ +@UnstableApi +@Serializable +public data class ResumeSessionRequest( + override val sessionId: SessionId, + val cwd: String, + val mcpServers: List, + override val _meta: JsonElement? = null +) : AcpRequest, AcpWithSessionId + /** * Request parameters for sending a user prompt to the agent. * @@ -398,6 +419,21 @@ public data class LoadSessionResponse( override val _meta: JsonElement? = null ) : AcpCreatedSessionResponse, AcpResponse +/** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Response from resuming an existing session. + */ +@UnstableApi +@Serializable +public data class ResumeSessionResponse( + override val modes: SessionModeState? = null, + override val models: SessionModelState? = null, + override val _meta: JsonElement? = null +) : AcpCreatedSessionResponse, AcpResponse + /** * Response containing the contents of a text file. */ diff --git a/acp/api/acp.api b/acp/api/acp.api index f75626e..445a93f 100644 --- a/acp/api/acp.api +++ b/acp/api/acp.api @@ -73,10 +73,13 @@ public abstract interface class com/agentclientprotocol/agent/AgentSupport { public abstract fun createSession (Lcom/agentclientprotocol/common/SessionCreationParameters;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public abstract fun initialize (Lcom/agentclientprotocol/client/ClientInfo;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public abstract fun loadSession-nk3TnMc (Ljava/lang/String;Lcom/agentclientprotocol/common/SessionCreationParameters;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public fun resumeSession-nk3TnMc (Ljava/lang/String;Lcom/agentclientprotocol/common/SessionCreationParameters;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static synthetic fun resumeSession-nk3TnMc$suspendImpl (Lcom/agentclientprotocol/agent/AgentSupport;Ljava/lang/String;Lcom/agentclientprotocol/common/SessionCreationParameters;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } public final class com/agentclientprotocol/agent/AgentSupport$DefaultImpls { public static fun authenticate-fMnwWJU (Lcom/agentclientprotocol/agent/AgentSupport;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static fun resumeSession-nk3TnMc (Lcom/agentclientprotocol/agent/AgentSupport;Ljava/lang/String;Lcom/agentclientprotocol/common/SessionCreationParameters;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } public final class com/agentclientprotocol/client/Client { @@ -91,6 +94,7 @@ public final class com/agentclientprotocol/client/Client { public static synthetic fun initialize$default (Lcom/agentclientprotocol/client/Client;Lcom/agentclientprotocol/client/ClientInfo;Lkotlinx/serialization/json/JsonElement;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; public final fun loadSession-wPMwmcM (Ljava/lang/String;Lcom/agentclientprotocol/common/SessionCreationParameters;Lcom/agentclientprotocol/client/ClientOperationsFactory;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public final fun newSession (Lcom/agentclientprotocol/common/SessionCreationParameters;Lcom/agentclientprotocol/client/ClientOperationsFactory;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public final fun resumeSession-wPMwmcM (Ljava/lang/String;Lcom/agentclientprotocol/common/SessionCreationParameters;Lcom/agentclientprotocol/client/ClientOperationsFactory;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } public final class com/agentclientprotocol/client/ClientInfo { diff --git a/acp/src/commonMain/kotlin/com/agentclientprotocol/agent/Agent.kt b/acp/src/commonMain/kotlin/com/agentclientprotocol/agent/Agent.kt index 3a33082..3ad1fc6 100644 --- a/acp/src/commonMain/kotlin/com/agentclientprotocol/agent/Agent.kt +++ b/acp/src/commonMain/kotlin/com/agentclientprotocol/agent/Agent.kt @@ -153,6 +153,16 @@ public class Agent( models = session.asModelState() ) } + + protocol.setRequestHandler(AcpMethod.AgentMethods.SessionResume) { params: ResumeSessionRequest -> + val sessionParameters = SessionCreationParameters(params.cwd, params.mcpServers, params._meta) + val session = createSession(sessionParameters) { agentSupport.resumeSession(params.sessionId, sessionParameters) } + return@setRequestHandler ResumeSessionResponse( + modes = session.asModeState(), + models = session.asModelState() + ) + } + protocol.setRequestHandler(AcpMethod.AgentMethods.SessionSetMode) { params: SetSessionModeRequest -> val session = getSessionOrThrow(params.sessionId) return@setRequestHandler session.executeWithSession { diff --git a/acp/src/commonMain/kotlin/com/agentclientprotocol/agent/AgentSupport.kt b/acp/src/commonMain/kotlin/com/agentclientprotocol/agent/AgentSupport.kt index 4bd99b0..b67a021 100644 --- a/acp/src/commonMain/kotlin/com/agentclientprotocol/agent/AgentSupport.kt +++ b/acp/src/commonMain/kotlin/com/agentclientprotocol/agent/AgentSupport.kt @@ -1,5 +1,6 @@ package com.agentclientprotocol.agent +import com.agentclientprotocol.annotations.UnstableApi import com.agentclientprotocol.client.ClientInfo import com.agentclientprotocol.common.SessionCreationParameters import com.agentclientprotocol.model.AuthMethodId @@ -12,4 +13,18 @@ public interface AgentSupport { public suspend fun authenticate(methodId: AuthMethodId, _meta: JsonElement?): AuthenticateResponse = AuthenticateResponse() public suspend fun createSession(sessionParameters: SessionCreationParameters): AgentSession public suspend fun loadSession(sessionId: SessionId, sessionParameters: SessionCreationParameters): AgentSession + + /** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Resumes an existing session without returning previous messages. + * + * This method is only available if the agent advertises the `session.resume` capability. + */ + @UnstableApi + public suspend fun resumeSession(sessionId: SessionId, sessionParameters: SessionCreationParameters): AgentSession { + throw NotImplementedError("Must be implemented by agent when advertising session.resume capability") + } } \ No newline at end of file diff --git a/acp/src/commonMain/kotlin/com/agentclientprotocol/client/Client.kt b/acp/src/commonMain/kotlin/com/agentclientprotocol/client/Client.kt index 0841b58..bea5293 100644 --- a/acp/src/commonMain/kotlin/com/agentclientprotocol/client/Client.kt +++ b/acp/src/commonMain/kotlin/com/agentclientprotocol/client/Client.kt @@ -201,6 +201,37 @@ public class Client( } } + /** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Resume an existing session without returning previous messages. + * + * This method is only available if the agent advertises the `session.resume` capability. + * + * @param sessionId the id of the existing session to resume + * @param sessionParameters parameters for resuming the session + * @param operationsFactory a factory for creating [com.agentclientprotocol.common.ClientSessionOperations] for the session. + * A created object must also implement the necessary interfaces in the case when the client declares extra capabilities like file system or terminal support. + * See [ClientOperationsFactory.createClientOperations] for more details. + * @return a [ClientSession] instance for the resumed session + */ + public suspend fun resumeSession(sessionId: SessionId, sessionParameters: SessionCreationParameters, operationsFactory: ClientOperationsFactory): ClientSession { + return withInitializingSession { + val resumeSessionResponse = AcpMethod.AgentMethods.SessionResume( + protocol, + ResumeSessionRequest( + sessionId, + sessionParameters.cwd, + sessionParameters.mcpServers, + sessionParameters._meta + ) + ) + return@withInitializingSession createSession(sessionId, sessionParameters, resumeSessionResponse, operationsFactory) + } + } + private suspend fun createSession(sessionId: SessionId, sessionParameters: SessionCreationParameters, sessionResponse: AcpCreatedSessionResponse, factory: ClientOperationsFactory): ClientSession { val sessionDeferred = CompletableDeferred() return runCatching { diff --git a/build.gradle.kts b/build.gradle.kts index 82f2a4b..0b90c7d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,7 +7,7 @@ plugins { private val buildNumber: String? = System.getenv("GITHUB_RUN_NUMBER") private val isReleasePublication = System.getenv("RELEASE_PUBLICATION")?.toBoolean() ?: false -private val baseVersion = "0.10.5" +private val baseVersion = "0.11.0" allprojects { group = "com.agentclientprotocol"