diff --git a/acp-ktor-test/src/commonTest/kotlin/com/agentclientprotocol/SimpleAgentTest.kt b/acp-ktor-test/src/commonTest/kotlin/com/agentclientprotocol/SimpleAgentTest.kt index ebad6c9..37a2b5e 100644 --- a/acp-ktor-test/src/commonTest/kotlin/com/agentclientprotocol/SimpleAgentTest.kt +++ b/acp-ktor-test/src/commonTest/kotlin/com/agentclientprotocol/SimpleAgentTest.kt @@ -1,47 +1,19 @@ package com.agentclientprotocol -import com.agentclientprotocol.agent.Agent -import com.agentclientprotocol.agent.AgentInfo -import com.agentclientprotocol.agent.AgentSession -import com.agentclientprotocol.agent.AgentSupport -import com.agentclientprotocol.agent.client +import com.agentclientprotocol.agent.* +import com.agentclientprotocol.annotations.UnstableApi import com.agentclientprotocol.client.Client import com.agentclientprotocol.client.ClientInfo import com.agentclientprotocol.common.ClientSessionOperations import com.agentclientprotocol.common.Event import com.agentclientprotocol.common.SessionCreationParameters import com.agentclientprotocol.framework.ProtocolDriver -import com.agentclientprotocol.model.AcpMethod -import com.agentclientprotocol.model.ContentBlock -import com.agentclientprotocol.model.LATEST_PROTOCOL_VERSION -import com.agentclientprotocol.model.PermissionOption -import com.agentclientprotocol.model.PermissionOptionId -import com.agentclientprotocol.model.PermissionOptionKind -import com.agentclientprotocol.model.PromptResponse -import com.agentclientprotocol.model.RequestPermissionOutcome -import com.agentclientprotocol.model.RequestPermissionResponse -import com.agentclientprotocol.model.SessionId -import com.agentclientprotocol.model.SessionNotification -import com.agentclientprotocol.model.SessionUpdate -import com.agentclientprotocol.model.StopReason -import com.agentclientprotocol.model.ToolCallId +import com.agentclientprotocol.model.* import com.agentclientprotocol.protocol.invoke -import io.github.oshai.kotlinlogging.KotlinLogging.logger -import kotlinx.coroutines.CancellationException -import kotlinx.coroutines.CompletableDeferred -import kotlinx.coroutines.awaitCancellation -import kotlinx.coroutines.currentCoroutineContext -import kotlinx.coroutines.delay -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.collect -import kotlinx.coroutines.flow.flow -import kotlinx.coroutines.launch -import kotlinx.coroutines.withTimeout +import kotlinx.coroutines.* +import kotlinx.coroutines.flow.* import kotlinx.serialization.json.JsonElement -import kotlin.test.Test -import kotlin.test.assertContentEquals -import kotlin.test.assertEquals -import kotlin.test.assertTrue +import kotlin.test.* import kotlin.time.Duration.Companion.milliseconds abstract class SimpleAgentTest(protocolDriver: ProtocolDriver) : ProtocolDriver by protocolDriver { @@ -681,5 +653,321 @@ abstract class SimpleAgentTest(protocolDriver: ProtocolDriver) : ProtocolDriver assertTrue(notification is SessionUpdate.AvailableCommandsUpdate) } + @OptIn(UnstableApi::class) + @Test + fun `list sessions returns paginated results`() = testWithProtocols { clientProtocol, agentProtocol -> + val testSessions = (1..25).map { i -> + SessionInfo( + sessionId = SessionId("session-$i"), + cwd = "/test/path/$i", + title = "Session $i" + ) + } + + val client = Client(protocol = clientProtocol) + val agent = Agent(protocol = agentProtocol, agentSupport = object : AgentSupport { + override suspend fun initialize(clientInfo: ClientInfo): AgentInfo { + return AgentInfo( + clientInfo.protocolVersion, + capabilities = AgentCapabilities( + sessionCapabilities = SessionCapabilities(list = SessionListCapabilities()) + ) + ) + } + + override suspend fun listSessions(cwd: String?, _meta: kotlinx.serialization.json.JsonElement?): Sequence { + return if (cwd != null) { + testSessions.filter { it.cwd.contains(cwd) }.asSequence() + } else { + testSessions.asSequence() + } + } + + override suspend fun createSession(sessionParameters: SessionCreationParameters): AgentSession { + TODO("Not yet implemented") + } + + override suspend fun loadSession( + sessionId: SessionId, + sessionParameters: SessionCreationParameters, + ): AgentSession { + TODO("Not yet implemented") + } + }) + + client.initialize(ClientInfo(protocolVersion = LATEST_PROTOCOL_VERSION)) + + val flow = client.listSessions() + val allSessions = flow.toList() + + assertEquals(25, allSessions.size) + assertEquals("session-1", allSessions.first().sessionId.value) + assertEquals("session-25", allSessions.last().sessionId.value) + } + + @OptIn(UnstableApi::class) + @Test + fun `list sessions with cwd filter`() = testWithProtocols { clientProtocol, agentProtocol -> + val testSessions = listOf( + SessionInfo(sessionId = SessionId("session-1"), cwd = "/project/a"), + SessionInfo(sessionId = SessionId("session-2"), cwd = "/project/b"), + SessionInfo(sessionId = SessionId("session-3"), cwd = "/project/a/subdir"), + SessionInfo(sessionId = SessionId("session-4"), cwd = "/other/path"), + ) + + val client = Client(protocol = clientProtocol) + val agent = Agent(protocol = agentProtocol, agentSupport = object : AgentSupport { + override suspend fun initialize(clientInfo: ClientInfo): AgentInfo { + return AgentInfo( + clientInfo.protocolVersion, + capabilities = AgentCapabilities( + sessionCapabilities = SessionCapabilities(list = SessionListCapabilities()) + ) + ) + } + + override suspend fun listSessions(cwd: String?, _meta: kotlinx.serialization.json.JsonElement?): Sequence { + return if (cwd != null) { + testSessions.filter { it.cwd.contains(cwd) }.asSequence() + } else { + testSessions.asSequence() + } + } + + override suspend fun createSession(sessionParameters: SessionCreationParameters): AgentSession { + TODO("Not yet implemented") + } + + override suspend fun loadSession( + sessionId: SessionId, + sessionParameters: SessionCreationParameters, + ): AgentSession { + TODO("Not yet implemented") + } + }) + + client.initialize(ClientInfo(protocolVersion = LATEST_PROTOCOL_VERSION)) + + val flow = client.listSessions(cwd = "/project/a") + val filteredSessions = flow.toList() + + assertEquals(2, filteredSessions.size) + assertTrue(filteredSessions.all { it.cwd.contains("/project/a") }) + } + + @OptIn(UnstableApi::class) + @Test + fun `list sessions with partial iteration works correctly`() = testWithProtocols { clientProtocol, agentProtocol -> + // Create 30 test sessions + val allSessions = (1..30).map { i -> + SessionInfo(sessionId = SessionId("session-$i"), cwd = "/project") + } + + val client = Client(protocol = clientProtocol) + val agent = Agent(protocol = agentProtocol, agentSupport = object : AgentSupport { + override suspend fun initialize(clientInfo: ClientInfo): AgentInfo { + return AgentInfo( + clientInfo.protocolVersion, + capabilities = AgentCapabilities( + sessionCapabilities = SessionCapabilities(list = SessionListCapabilities()) + ) + ) + } + + override suspend fun listSessions(cwd: String?, _meta: JsonElement?): Sequence { + // Return all sessions - the adapter will handle pagination + return allSessions.asSequence() + } + + override suspend fun createSession(sessionParameters: SessionCreationParameters): AgentSession { + TODO("Not yet implemented") + } + + override suspend fun loadSession( + sessionId: SessionId, + sessionParameters: SessionCreationParameters, + ): AgentSession { + TODO("Not yet implemented") + } + }) + + client.initialize(ClientInfo(protocolVersion = LATEST_PROTOCOL_VERSION)) + + // Take only 12 items from 30 available + val flow = client.listSessions() + val partialSessions = flow.take(12).toList() + + // Verify we got exactly 12 items even though 30 were available + assertEquals(12, partialSessions.size) + assertEquals("session-1", partialSessions.first().sessionId.value) + assertEquals("session-12", partialSessions[11].sessionId.value) + } + + @OptIn(UnstableApi::class) + @Test + fun `list sessions stops cleanly on early termination`() = testWithProtocols { clientProtocol, agentProtocol -> + var resourcesAcquired = 0 + var resourcesReleased = 0 + + val client = Client(protocol = clientProtocol) + val agent = Agent(protocol = agentProtocol, agentSupport = object : AgentSupport { + override suspend fun initialize(clientInfo: ClientInfo): AgentInfo { + return AgentInfo( + clientInfo.protocolVersion, + capabilities = AgentCapabilities( + sessionCapabilities = SessionCapabilities(list = SessionListCapabilities()) + ) + ) + } + + override suspend fun listSessions(cwd: String?, _meta: JsonElement?): Sequence { + resourcesAcquired++ + + return sequence { + try { + // Simulate paginated data + repeat(10) { i -> + yield(SessionInfo(sessionId = SessionId("session-$i"), cwd = "/project")) + } + } finally { + // Cleanup should happen even on early termination + resourcesReleased++ + } + } + } + + override suspend fun createSession(sessionParameters: SessionCreationParameters): AgentSession { + TODO("Not yet implemented") + } + + override suspend fun loadSession( + sessionId: SessionId, + sessionParameters: SessionCreationParameters, + ): AgentSession { + TODO("Not yet implemented") + } + }) + + client.initialize(ClientInfo(protocolVersion = LATEST_PROTOCOL_VERSION)) + + // Take only 3 items and stop + val flow = client.listSessions() + val limitedSessions = flow.take(3).toList() + + assertEquals(3, limitedSessions.size) + assertEquals("session-0", limitedSessions.first().sessionId.value) + assertEquals("session-2", limitedSessions.last().sessionId.value) + + // Resources should be properly cleaned up + assertEquals(resourcesAcquired, resourcesReleased) + assertTrue(resourcesReleased > 0) + } + + @OptIn(UnstableApi::class) + @Test + fun `list sessions does not fetch second page when only first is consumed`() = testWithProtocols { clientProtocol, agentProtocol -> + var itemsGenerated = 0 + + val client = Client(protocol = clientProtocol) + val agent = Agent(protocol = agentProtocol, agentSupport = object : AgentSupport { + override suspend fun initialize(clientInfo: ClientInfo): AgentInfo { + return AgentInfo( + clientInfo.protocolVersion, + capabilities = AgentCapabilities( + sessionCapabilities = SessionCapabilities(list = SessionListCapabilities()) + ) + ) + } + + override suspend fun listSessions(cwd: String?, _meta: JsonElement?): Sequence { + // The Agent's setPaginatedRequestHandler with batchSize=10 will consume + // items from this sequence in batches of 10 + return sequence { + for (i in 1..20) { + itemsGenerated++ + yield(SessionInfo(sessionId = SessionId("session-$i"), cwd = "/project")) + } + } + } + + override suspend fun createSession(sessionParameters: SessionCreationParameters): AgentSession { + TODO("Not yet implemented") + } + + override suspend fun loadSession( + sessionId: SessionId, + sessionParameters: SessionCreationParameters, + ): AgentSession { + TODO("Not yet implemented") + } + }) + + client.initialize(ClientInfo(protocolVersion = LATEST_PROTOCOL_VERSION)) + + // Take only 5 items - the flow should lazily fetch data + val flow = client.listSessions() + val limitedSessions = flow.take(5).toList() + + assertEquals(5, limitedSessions.size) + assertEquals("session-1", limitedSessions.first().sessionId.value) + assertEquals("session-5", limitedSessions.last().sessionId.value) + + // Due to batchSize=10 in Agent.setPaginatedRequestHandler, + // the sequence should generate approximately 10 items for the first batch + // (might be 11 due to iterator checking for next) + assertTrue(itemsGenerated <= 11, "Should have generated only first batch (~10 items), but generated $itemsGenerated") + assertTrue(itemsGenerated < 15, "Should not have fetched second batch") + } + + @OptIn(UnstableApi::class) + @Test + fun `list sessions is truly lazy and cold`() = testWithProtocols { clientProtocol, agentProtocol -> + var fetchStarted = false + + val client = Client(protocol = clientProtocol) + val agent = Agent(protocol = agentProtocol, agentSupport = object : AgentSupport { + override suspend fun initialize(clientInfo: ClientInfo): AgentInfo { + return AgentInfo( + clientInfo.protocolVersion, + capabilities = AgentCapabilities( + sessionCapabilities = SessionCapabilities(list = SessionListCapabilities()) + ) + ) + } + + override suspend fun listSessions(cwd: String?, _meta: JsonElement?): Sequence { + fetchStarted = true + return sequenceOf( + SessionInfo(sessionId = SessionId("session-1"), cwd = "/project") + ) + } + + override suspend fun createSession(sessionParameters: SessionCreationParameters): AgentSession { + TODO("Not yet implemented") + } + + override suspend fun loadSession( + sessionId: SessionId, + sessionParameters: SessionCreationParameters, + ): AgentSession { + TODO("Not yet implemented") + } + }) + + client.initialize(ClientInfo(protocolVersion = LATEST_PROTOCOL_VERSION)) + + // Create flow but don't collect yet + val flow = client.listSessions() + + // Flow is cold - should not start fetching until collection begins + assertFalse(fetchStarted, "Flow should not start fetching before collection") + + // Now start collecting + val sessions = flow.toList() + + // Now fetching should have started + assertTrue(fetchStarted, "Flow should start fetching when collection begins") + assertEquals(1, sessions.size) + } } \ No newline at end of file diff --git a/acp-model/.schema-checksums b/acp-model/.schema-checksums index b55fb0b..1a177c9 100644 --- a/acp-model/.schema-checksums +++ b/acp-model/.schema-checksums @@ -3,9 +3,9 @@ # Format: SHA256 FILENAME # Stable schemas -796e38e275a1587b5a711a4b4508cb69825448b70e79b14bdb4256b24688b89d schema/schema.json +07f2cdfd7814496ebdab83fb7417787fa1dddc6276b11cd31b51be2f8ba95f2b schema/schema.json f242b95def9a9cbfddd2db1a45d8d3d489ad1b4f564a1322547c90a94c647637 schema/meta.json # Unstable schemas -4a886716877f97bc24c4c7f1ae24c9ad06a779107afbdf0718110fc50b5135b7 schema/schema.unstable.json -8ad80116767e0921970b28766c214d7921268653544d5996a8e2814e1244d4d2 schema/meta.unstable.json +75d180b9c589cd7d79a5a9cbb6680d52e1bce71238839871441d30c753b497a9 schema/schema.unstable.json +e87ae9b3fc3b05f88da6dfc06d003e5263d6a041b1c934ed13b83173b39ed111 schema/meta.unstable.json diff --git a/acp-model/.schema-revision b/acp-model/.schema-revision index d668dd8..ae6c846 100644 --- a/acp-model/.schema-revision +++ b/acp-model/.schema-revision @@ -1 +1 @@ -e23620fe29cb24555db8fb8b58b641b680788e5f +37d12f4bb4b0cf1dca60421d48cb17decc119b8e diff --git a/acp-model/SCHEMA_VERSION.md b/acp-model/SCHEMA_VERSION.md index e2004f7..22ad1a9 100644 --- a/acp-model/SCHEMA_VERSION.md +++ b/acp-model/SCHEMA_VERSION.md @@ -11,60 +11,59 @@ This file tracks the version of the Agent Client Protocol schema that the model ### Stable Schema - **schema.json** - - Commit: `e23620fe29cb24555db8fb8b58b641b680788e5f` - - Date: 2025-12-01 17:17:19 +0100 - - SHA256: `796e38e275a1587b5a711a4b4508cb69825448b70e79b14bdb4256b24688b89d` + - Commit: `37d12f4bb4b0cf1dca60421d48cb17decc119b8e` + - Date: 2025-12-20 18:25:51 +0000 + - SHA256: `07f2cdfd7814496ebdab83fb7417787fa1dddc6276b11cd31b51be2f8ba95f2b` - URL: https://github.com/agentclientprotocol/agent-client-protocol/blob/main/schema/schema.json - **meta.json** - - Commit: `e23620fe29cb24555db8fb8b58b641b680788e5f` - - Date: 2025-12-01 17:17:19 +0100 + - Commit: `37d12f4bb4b0cf1dca60421d48cb17decc119b8e` + - Date: 2025-12-20 18:25:51 +0000 - SHA256: `f242b95def9a9cbfddd2db1a45d8d3d489ad1b4f564a1322547c90a94c647637` - URL: https://github.com/agentclientprotocol/agent-client-protocol/blob/main/schema/meta.json ### Unstable Schema - **schema.unstable.json** - - Commit: `e23620fe29cb24555db8fb8b58b641b680788e5f` - - Date: 2025-12-01 17:17:19 +0100 - - SHA256: `4a886716877f97bc24c4c7f1ae24c9ad06a779107afbdf0718110fc50b5135b7` + - Commit: `37d12f4bb4b0cf1dca60421d48cb17decc119b8e` + - Date: 2025-12-20 18:25:51 +0000 + - SHA256: `75d180b9c589cd7d79a5a9cbb6680d52e1bce71238839871441d30c753b497a9` - URL: https://github.com/agentclientprotocol/agent-client-protocol/blob/main/schema/schema.unstable.json - **meta.unstable.json** - - Commit: `e23620fe29cb24555db8fb8b58b641b680788e5f` - - Date: 2025-12-01 17:17:19 +0100 - - SHA256: `8ad80116767e0921970b28766c214d7921268653544d5996a8e2814e1244d4d2` + - Commit: `37d12f4bb4b0cf1dca60421d48cb17decc119b8e` + - Date: 2025-12-20 18:25:51 +0000 + - SHA256: `e87ae9b3fc3b05f88da6dfc06d003e5263d6a041b1c934ed13b83173b39ed111` - URL: https://github.com/agentclientprotocol/agent-client-protocol/blob/main/schema/meta.unstable.json **Note:** All types from unstable schema must be marked with `@UnstableApi` annotation. ## Last Updated -- Date: 2025-12-01 +- Date: 2025-12-20 - Updated by: Manual schema synchronization ## Changes in This Version -- Added `Implementation` type for client/agent identification -- Added `SessionCapabilities` type (empty, for future expansion) -- Added `clientInfo` field to `InitializeRequest` -- Added `agentInfo` field to `InitializeResponse` -- Added `sessionCapabilities` field to `AgentCapabilities` -- Changed `AvailableCommandInput` from data class to sealed class with `Unstructured` variant -- Added `_meta` field to `ToolCallContent.Terminal` -- Terminal types are now stable (removed unstable warning) +- Added `session/fork` method to agent methods (unstable) +- Added `session/list` method to agent methods (unstable) +- Added `session/resume` method to agent methods (unstable) +- Added `session/set_config_option` method to agent methods (unstable) +- Added `session/set_model` method to agent methods (unstable) +- Added `$/cancel_request` protocol method (unstable) +- Updated stable schema with bug fixes and improvements ## Verification To verify the schema files match: ```bash # Stable schemas curl -s https://raw.githubusercontent.com/agentclientprotocol/agent-client-protocol/main/schema/schema.json | sha256sum -# Expected: 796e38e275a1587b5a711a4b4508cb69825448b70e79b14bdb4256b24688b89d +# Expected: 07f2cdfd7814496ebdab83fb7417787fa1dddc6276b11cd31b51be2f8ba95f2b curl -s https://raw.githubusercontent.com/agentclientprotocol/agent-client-protocol/main/schema/meta.json | sha256sum # Expected: f242b95def9a9cbfddd2db1a45d8d3d489ad1b4f564a1322547c90a94c647637 # Unstable schemas curl -s https://raw.githubusercontent.com/agentclientprotocol/agent-client-protocol/main/schema/schema.unstable.json | sha256sum -# Expected: 4a886716877f97bc24c4c7f1ae24c9ad06a779107afbdf0718110fc50b5135b7 +# Expected: 75d180b9c589cd7d79a5a9cbb6680d52e1bce71238839871441d30c753b497a9 curl -s https://raw.githubusercontent.com/agentclientprotocol/agent-client-protocol/main/schema/meta.unstable.json | sha256sum -# Expected: 8ad80116767e0921970b28766c214d7921268653544d5996a8e2814e1244d4d2 +# Expected: e87ae9b3fc3b05f88da6dfc06d003e5263d6a041b1c934ed13b83173b39ed111 ``` diff --git a/acp-model/api/acp-model.api b/acp-model/api/acp-model.api index 6e97b33..b5030c4 100644 --- a/acp-model/api/acp-model.api +++ b/acp-model/api/acp-model.api @@ -9,6 +9,7 @@ public abstract interface class com/agentclientprotocol/model/AcpCapabilities { } public abstract interface class com/agentclientprotocol/model/AcpCreatedSessionResponse : com/agentclientprotocol/model/AcpWithMeta { + public abstract fun getConfigOptions ()Ljava/util/List; public abstract fun getModels ()Lcom/agentclientprotocol/model/SessionModelState; public abstract fun getModes ()Lcom/agentclientprotocol/model/SessionModeState; } @@ -54,6 +55,14 @@ public final class com/agentclientprotocol/model/AcpMethod$AgentMethods$SessionC public static final field INSTANCE Lcom/agentclientprotocol/model/AcpMethod$AgentMethods$SessionCancel; } +public final class com/agentclientprotocol/model/AcpMethod$AgentMethods$SessionFork : com/agentclientprotocol/model/AcpMethod$AcpSessionRequestResponseMethod { + public static final field INSTANCE Lcom/agentclientprotocol/model/AcpMethod$AgentMethods$SessionFork; +} + +public final class com/agentclientprotocol/model/AcpMethod$AgentMethods$SessionList : com/agentclientprotocol/model/AcpMethod$AcpRequestResponseMethod { + public static final field INSTANCE Lcom/agentclientprotocol/model/AcpMethod$AgentMethods$SessionList; +} + public final class com/agentclientprotocol/model/AcpMethod$AgentMethods$SessionLoad : com/agentclientprotocol/model/AcpMethod$AcpRequestResponseMethod { public static final field INSTANCE Lcom/agentclientprotocol/model/AcpMethod$AgentMethods$SessionLoad; } @@ -70,6 +79,10 @@ public final class com/agentclientprotocol/model/AcpMethod$AgentMethods$SessionR public static final field INSTANCE Lcom/agentclientprotocol/model/AcpMethod$AgentMethods$SessionResume; } +public final class com/agentclientprotocol/model/AcpMethod$AgentMethods$SessionSetConfigOption : com/agentclientprotocol/model/AcpMethod$AcpSessionRequestResponseMethod { + public static final field INSTANCE Lcom/agentclientprotocol/model/AcpMethod$AgentMethods$SessionSetConfigOption; +} + 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; } @@ -133,6 +146,15 @@ public final class com/agentclientprotocol/model/AcpMethod$UnknownMethod : com/a public abstract interface class com/agentclientprotocol/model/AcpNotification : com/agentclientprotocol/model/AcpWithMeta { } +public abstract interface class com/agentclientprotocol/model/AcpPaginatedRequest : com/agentclientprotocol/model/AcpRequest { + public abstract fun getCursor ()Ljava/lang/String; +} + +public abstract interface class com/agentclientprotocol/model/AcpPaginatedResponse : com/agentclientprotocol/model/AcpResponse { + public abstract fun getItemsBatch ()Ljava/util/List; + public abstract fun getNextCursor ()Ljava/lang/String; +} + public abstract interface class com/agentclientprotocol/model/AcpRequest : com/agentclientprotocol/model/AcpWithMeta { } @@ -933,6 +955,76 @@ public final class com/agentclientprotocol/model/FileSystemCapability$Companion public final fun serializer ()Lkotlinx/serialization/KSerializer; } +public final class com/agentclientprotocol/model/ForkSessionRequest : com/agentclientprotocol/model/AcpRequest, com/agentclientprotocol/model/AcpWithSessionId { + public static final field Companion Lcom/agentclientprotocol/model/ForkSessionRequest$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/ForkSessionRequest; + public static synthetic fun copy-wPMwmcM$default (Lcom/agentclientprotocol/model/ForkSessionRequest;Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Lkotlinx/serialization/json/JsonElement;ILjava/lang/Object;)Lcom/agentclientprotocol/model/ForkSessionRequest; + 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/ForkSessionRequest$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lcom/agentclientprotocol/model/ForkSessionRequest$$serializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/agentclientprotocol/model/ForkSessionRequest; + 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/ForkSessionRequest;)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/ForkSessionRequest$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + +public final class com/agentclientprotocol/model/ForkSessionResponse : com/agentclientprotocol/model/AcpCreatedSessionResponse, com/agentclientprotocol/model/AcpResponse, com/agentclientprotocol/model/AcpWithSessionId { + public static final field Companion Lcom/agentclientprotocol/model/ForkSessionResponse$Companion; + public synthetic fun (Ljava/lang/String;Lcom/agentclientprotocol/model/SessionModeState;Lcom/agentclientprotocol/model/SessionModelState;Ljava/util/List;Lkotlinx/serialization/json/JsonElement;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Ljava/lang/String;Lcom/agentclientprotocol/model/SessionModeState;Lcom/agentclientprotocol/model/SessionModelState;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 ()Lcom/agentclientprotocol/model/SessionModeState; + public final fun component3 ()Lcom/agentclientprotocol/model/SessionModelState; + public final fun component4 ()Ljava/util/List; + public final fun component5 ()Lkotlinx/serialization/json/JsonElement; + public final fun copy-8WrnS2s (Ljava/lang/String;Lcom/agentclientprotocol/model/SessionModeState;Lcom/agentclientprotocol/model/SessionModelState;Ljava/util/List;Lkotlinx/serialization/json/JsonElement;)Lcom/agentclientprotocol/model/ForkSessionResponse; + public static synthetic fun copy-8WrnS2s$default (Lcom/agentclientprotocol/model/ForkSessionResponse;Ljava/lang/String;Lcom/agentclientprotocol/model/SessionModeState;Lcom/agentclientprotocol/model/SessionModelState;Ljava/util/List;Lkotlinx/serialization/json/JsonElement;ILjava/lang/Object;)Lcom/agentclientprotocol/model/ForkSessionResponse; + public fun equals (Ljava/lang/Object;)Z + public fun getConfigOptions ()Ljava/util/List; + public fun getModels ()Lcom/agentclientprotocol/model/SessionModelState; + public fun getModes ()Lcom/agentclientprotocol/model/SessionModeState; + 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/ForkSessionResponse$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lcom/agentclientprotocol/model/ForkSessionResponse$$serializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/agentclientprotocol/model/ForkSessionResponse; + 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/ForkSessionResponse;)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/ForkSessionResponse$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + public final class com/agentclientprotocol/model/HttpHeader : com/agentclientprotocol/model/AcpWithMeta { public static final field Companion Lcom/agentclientprotocol/model/HttpHeader$Companion; public fun (Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;)V @@ -1130,6 +1222,72 @@ public final class com/agentclientprotocol/model/KillTerminalCommandResponse$Com public final fun serializer ()Lkotlinx/serialization/KSerializer; } +public final class com/agentclientprotocol/model/ListSessionsRequest : com/agentclientprotocol/model/AcpPaginatedRequest, com/agentclientprotocol/model/AcpRequest { + public static final field Companion Lcom/agentclientprotocol/model/ListSessionsRequest$Companion; + public fun ()V + public fun (Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;)V + public synthetic fun (Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1 ()Ljava/lang/String; + public final fun component2 ()Ljava/lang/String; + public final fun component3 ()Lkotlinx/serialization/json/JsonElement; + public final fun copy (Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;)Lcom/agentclientprotocol/model/ListSessionsRequest; + public static synthetic fun copy$default (Lcom/agentclientprotocol/model/ListSessionsRequest;Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;ILjava/lang/Object;)Lcom/agentclientprotocol/model/ListSessionsRequest; + public fun equals (Ljava/lang/Object;)Z + public fun getCursor ()Ljava/lang/String; + public final fun getCwd ()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/ListSessionsRequest$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lcom/agentclientprotocol/model/ListSessionsRequest$$serializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/agentclientprotocol/model/ListSessionsRequest; + 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/ListSessionsRequest;)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/ListSessionsRequest$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + +public final class com/agentclientprotocol/model/ListSessionsResponse : com/agentclientprotocol/model/AcpPaginatedResponse, com/agentclientprotocol/model/AcpResponse { + public static final field Companion Lcom/agentclientprotocol/model/ListSessionsResponse$Companion; + public fun (Ljava/util/List;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;)V + public synthetic fun (Ljava/util/List;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1 ()Ljava/util/List; + public final fun component2 ()Ljava/lang/String; + public final fun component3 ()Lkotlinx/serialization/json/JsonElement; + public final fun copy (Ljava/util/List;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;)Lcom/agentclientprotocol/model/ListSessionsResponse; + public static synthetic fun copy$default (Lcom/agentclientprotocol/model/ListSessionsResponse;Ljava/util/List;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;ILjava/lang/Object;)Lcom/agentclientprotocol/model/ListSessionsResponse; + public fun equals (Ljava/lang/Object;)Z + public fun getItemsBatch ()Ljava/util/List; + public fun getNextCursor ()Ljava/lang/String; + public final fun getSessions ()Ljava/util/List; + 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/ListSessionsResponse$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lcom/agentclientprotocol/model/ListSessionsResponse$$serializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/agentclientprotocol/model/ListSessionsResponse; + 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/ListSessionsResponse;)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/ListSessionsResponse$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + public final class com/agentclientprotocol/model/LoadSessionRequest : com/agentclientprotocol/model/AcpRequest, com/agentclientprotocol/model/AcpWithSessionId { public static final field Companion Lcom/agentclientprotocol/model/LoadSessionRequest$Companion; public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Lkotlinx/serialization/json/JsonElement;ILkotlin/jvm/internal/DefaultConstructorMarker;)V @@ -1167,14 +1325,16 @@ public final class com/agentclientprotocol/model/LoadSessionRequest$Companion { public final class com/agentclientprotocol/model/LoadSessionResponse : com/agentclientprotocol/model/AcpCreatedSessionResponse, com/agentclientprotocol/model/AcpResponse { public static final field Companion Lcom/agentclientprotocol/model/LoadSessionResponse$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 fun (Lcom/agentclientprotocol/model/SessionModeState;Lcom/agentclientprotocol/model/SessionModelState;Ljava/util/List;Lkotlinx/serialization/json/JsonElement;)V + public synthetic fun (Lcom/agentclientprotocol/model/SessionModeState;Lcom/agentclientprotocol/model/SessionModelState;Ljava/util/List;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/LoadSessionResponse; - public static synthetic fun copy$default (Lcom/agentclientprotocol/model/LoadSessionResponse;Lcom/agentclientprotocol/model/SessionModeState;Lcom/agentclientprotocol/model/SessionModelState;Lkotlinx/serialization/json/JsonElement;ILjava/lang/Object;)Lcom/agentclientprotocol/model/LoadSessionResponse; + public final fun component3 ()Ljava/util/List; + public final fun component4 ()Lkotlinx/serialization/json/JsonElement; + public final fun copy (Lcom/agentclientprotocol/model/SessionModeState;Lcom/agentclientprotocol/model/SessionModelState;Ljava/util/List;Lkotlinx/serialization/json/JsonElement;)Lcom/agentclientprotocol/model/LoadSessionResponse; + public static synthetic fun copy$default (Lcom/agentclientprotocol/model/LoadSessionResponse;Lcom/agentclientprotocol/model/SessionModeState;Lcom/agentclientprotocol/model/SessionModelState;Ljava/util/List;Lkotlinx/serialization/json/JsonElement;ILjava/lang/Object;)Lcom/agentclientprotocol/model/LoadSessionResponse; public fun equals (Ljava/lang/Object;)Z + public fun getConfigOptions ()Ljava/util/List; public fun getModels ()Lcom/agentclientprotocol/model/SessionModelState; public fun getModes ()Lcom/agentclientprotocol/model/SessionModeState; public fun get_meta ()Lkotlinx/serialization/json/JsonElement; @@ -1434,15 +1594,17 @@ public final class com/agentclientprotocol/model/NewSessionRequest$Companion { public final class com/agentclientprotocol/model/NewSessionResponse : com/agentclientprotocol/model/AcpCreatedSessionResponse, com/agentclientprotocol/model/AcpResponse, com/agentclientprotocol/model/AcpWithSessionId { public static final field Companion Lcom/agentclientprotocol/model/NewSessionResponse$Companion; - public synthetic fun (Ljava/lang/String;Lcom/agentclientprotocol/model/SessionModeState;Lcom/agentclientprotocol/model/SessionModelState;Lkotlinx/serialization/json/JsonElement;ILkotlin/jvm/internal/DefaultConstructorMarker;)V - public synthetic fun (Ljava/lang/String;Lcom/agentclientprotocol/model/SessionModeState;Lcom/agentclientprotocol/model/SessionModelState;Lkotlinx/serialization/json/JsonElement;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Ljava/lang/String;Lcom/agentclientprotocol/model/SessionModeState;Lcom/agentclientprotocol/model/SessionModelState;Ljava/util/List;Lkotlinx/serialization/json/JsonElement;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Ljava/lang/String;Lcom/agentclientprotocol/model/SessionModeState;Lcom/agentclientprotocol/model/SessionModelState;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 ()Lcom/agentclientprotocol/model/SessionModeState; public final fun component3 ()Lcom/agentclientprotocol/model/SessionModelState; - public final fun component4 ()Lkotlinx/serialization/json/JsonElement; - public final fun copy-wPMwmcM (Ljava/lang/String;Lcom/agentclientprotocol/model/SessionModeState;Lcom/agentclientprotocol/model/SessionModelState;Lkotlinx/serialization/json/JsonElement;)Lcom/agentclientprotocol/model/NewSessionResponse; - public static synthetic fun copy-wPMwmcM$default (Lcom/agentclientprotocol/model/NewSessionResponse;Ljava/lang/String;Lcom/agentclientprotocol/model/SessionModeState;Lcom/agentclientprotocol/model/SessionModelState;Lkotlinx/serialization/json/JsonElement;ILjava/lang/Object;)Lcom/agentclientprotocol/model/NewSessionResponse; + public final fun component4 ()Ljava/util/List; + public final fun component5 ()Lkotlinx/serialization/json/JsonElement; + public final fun copy-8WrnS2s (Ljava/lang/String;Lcom/agentclientprotocol/model/SessionModeState;Lcom/agentclientprotocol/model/SessionModelState;Ljava/util/List;Lkotlinx/serialization/json/JsonElement;)Lcom/agentclientprotocol/model/NewSessionResponse; + public static synthetic fun copy-8WrnS2s$default (Lcom/agentclientprotocol/model/NewSessionResponse;Ljava/lang/String;Lcom/agentclientprotocol/model/SessionModeState;Lcom/agentclientprotocol/model/SessionModelState;Ljava/util/List;Lkotlinx/serialization/json/JsonElement;ILjava/lang/Object;)Lcom/agentclientprotocol/model/NewSessionResponse; public fun equals (Ljava/lang/Object;)Z + public fun getConfigOptions ()Ljava/util/List; public fun getModels ()Lcom/agentclientprotocol/model/SessionModelState; public fun getModes ()Lcom/agentclientprotocol/model/SessionModeState; public fun getSessionId-7EW-EgU ()Ljava/lang/String; @@ -2046,14 +2208,16 @@ public final class com/agentclientprotocol/model/ResumeSessionRequest$Companion 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 fun (Lcom/agentclientprotocol/model/SessionModeState;Lcom/agentclientprotocol/model/SessionModelState;Ljava/util/List;Lkotlinx/serialization/json/JsonElement;)V + public synthetic fun (Lcom/agentclientprotocol/model/SessionModeState;Lcom/agentclientprotocol/model/SessionModelState;Ljava/util/List;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 final fun component3 ()Ljava/util/List; + public final fun component4 ()Lkotlinx/serialization/json/JsonElement; + public final fun copy (Lcom/agentclientprotocol/model/SessionModeState;Lcom/agentclientprotocol/model/SessionModelState;Ljava/util/List;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;Ljava/util/List;Lkotlinx/serialization/json/JsonElement;ILjava/lang/Object;)Lcom/agentclientprotocol/model/ResumeSessionResponse; public fun equals (Ljava/lang/Object;)Z + public fun getConfigOptions ()Ljava/util/List; public fun getModels ()Lcom/agentclientprotocol/model/SessionModelState; public fun getModes ()Lcom/agentclientprotocol/model/SessionModeState; public fun get_meta ()Lkotlinx/serialization/json/JsonElement; @@ -2092,13 +2256,17 @@ 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 (Lcom/agentclientprotocol/model/SessionResumeCapabilities;Lkotlinx/serialization/json/JsonElement;)V - public synthetic fun (Lcom/agentclientprotocol/model/SessionResumeCapabilities;Lkotlinx/serialization/json/JsonElement;ILkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun component1 ()Lcom/agentclientprotocol/model/SessionResumeCapabilities; - public final fun component2 ()Lkotlinx/serialization/json/JsonElement; - public final fun copy (Lcom/agentclientprotocol/model/SessionResumeCapabilities;Lkotlinx/serialization/json/JsonElement;)Lcom/agentclientprotocol/model/SessionCapabilities; - public static synthetic fun copy$default (Lcom/agentclientprotocol/model/SessionCapabilities;Lcom/agentclientprotocol/model/SessionResumeCapabilities;Lkotlinx/serialization/json/JsonElement;ILjava/lang/Object;)Lcom/agentclientprotocol/model/SessionCapabilities; + public fun (Lcom/agentclientprotocol/model/SessionForkCapabilities;Lcom/agentclientprotocol/model/SessionListCapabilities;Lcom/agentclientprotocol/model/SessionResumeCapabilities;Lkotlinx/serialization/json/JsonElement;)V + public synthetic fun (Lcom/agentclientprotocol/model/SessionForkCapabilities;Lcom/agentclientprotocol/model/SessionListCapabilities;Lcom/agentclientprotocol/model/SessionResumeCapabilities;Lkotlinx/serialization/json/JsonElement;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1 ()Lcom/agentclientprotocol/model/SessionForkCapabilities; + public final fun component2 ()Lcom/agentclientprotocol/model/SessionListCapabilities; + public final fun component3 ()Lcom/agentclientprotocol/model/SessionResumeCapabilities; + public final fun component4 ()Lkotlinx/serialization/json/JsonElement; + public final fun copy (Lcom/agentclientprotocol/model/SessionForkCapabilities;Lcom/agentclientprotocol/model/SessionListCapabilities;Lcom/agentclientprotocol/model/SessionResumeCapabilities;Lkotlinx/serialization/json/JsonElement;)Lcom/agentclientprotocol/model/SessionCapabilities; + public static synthetic fun copy$default (Lcom/agentclientprotocol/model/SessionCapabilities;Lcom/agentclientprotocol/model/SessionForkCapabilities;Lcom/agentclientprotocol/model/SessionListCapabilities;Lcom/agentclientprotocol/model/SessionResumeCapabilities;Lkotlinx/serialization/json/JsonElement;ILjava/lang/Object;)Lcom/agentclientprotocol/model/SessionCapabilities; public fun equals (Ljava/lang/Object;)Z + public final fun getFork ()Lcom/agentclientprotocol/model/SessionForkCapabilities; + public final fun getList ()Lcom/agentclientprotocol/model/SessionListCapabilities; public final fun getResume ()Lcom/agentclientprotocol/model/SessionResumeCapabilities; public fun get_meta ()Lkotlinx/serialization/json/JsonElement; public fun hashCode ()I @@ -2120,6 +2288,306 @@ public final class com/agentclientprotocol/model/SessionCapabilities$Companion { public final fun serializer ()Lkotlinx/serialization/KSerializer; } +public final class com/agentclientprotocol/model/SessionConfigGroupId { + public static final field Companion Lcom/agentclientprotocol/model/SessionConfigGroupId$Companion; + public static final synthetic fun box-impl (Ljava/lang/String;)Lcom/agentclientprotocol/model/SessionConfigGroupId; + public static fun constructor-impl (Ljava/lang/String;)Ljava/lang/String; + public fun equals (Ljava/lang/Object;)Z + public static fun equals-impl (Ljava/lang/String;Ljava/lang/Object;)Z + public static final fun equals-impl0 (Ljava/lang/String;Ljava/lang/String;)Z + public final fun getValue ()Ljava/lang/String; + public fun hashCode ()I + public static fun hashCode-impl (Ljava/lang/String;)I + public fun toString ()Ljava/lang/String; + public static fun toString-impl (Ljava/lang/String;)Ljava/lang/String; + public final synthetic fun unbox-impl ()Ljava/lang/String; +} + +public final synthetic class com/agentclientprotocol/model/SessionConfigGroupId$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lcom/agentclientprotocol/model/SessionConfigGroupId$$serializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public final fun deserialize-78x9OAc (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/String; + public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public final fun serialize-nC4u7i0 (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/String;)V + public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; +} + +public final class com/agentclientprotocol/model/SessionConfigGroupId$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + +public final class com/agentclientprotocol/model/SessionConfigId { + public static final field Companion Lcom/agentclientprotocol/model/SessionConfigId$Companion; + public static final synthetic fun box-impl (Ljava/lang/String;)Lcom/agentclientprotocol/model/SessionConfigId; + public static fun constructor-impl (Ljava/lang/String;)Ljava/lang/String; + public fun equals (Ljava/lang/Object;)Z + public static fun equals-impl (Ljava/lang/String;Ljava/lang/Object;)Z + public static final fun equals-impl0 (Ljava/lang/String;Ljava/lang/String;)Z + public final fun getValue ()Ljava/lang/String; + public fun hashCode ()I + public static fun hashCode-impl (Ljava/lang/String;)I + public fun toString ()Ljava/lang/String; + public static fun toString-impl (Ljava/lang/String;)Ljava/lang/String; + public final synthetic fun unbox-impl ()Ljava/lang/String; +} + +public final synthetic class com/agentclientprotocol/model/SessionConfigId$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lcom/agentclientprotocol/model/SessionConfigId$$serializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public final fun deserialize-osoXS-c (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/String; + public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public final fun serialize-kbQ7E_k (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/String;)V + public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; +} + +public final class com/agentclientprotocol/model/SessionConfigId$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + +public abstract class com/agentclientprotocol/model/SessionConfigOption : com/agentclientprotocol/model/AcpWithMeta { + public static final field Companion Lcom/agentclientprotocol/model/SessionConfigOption$Companion; + public synthetic fun (ILkotlinx/serialization/internal/SerializationConstructorMarker;)V + public abstract fun getDescription ()Ljava/lang/String; + public abstract fun getId-2Q23AbI ()Ljava/lang/String; + public abstract fun getName ()Ljava/lang/String; + public static final synthetic fun write$Self (Lcom/agentclientprotocol/model/SessionConfigOption;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V +} + +public final class com/agentclientprotocol/model/SessionConfigOption$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + +public final class com/agentclientprotocol/model/SessionConfigOption$Select : com/agentclientprotocol/model/SessionConfigOption { + public static final field Companion Lcom/agentclientprotocol/model/SessionConfigOption$Select$Companion; + public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/agentclientprotocol/model/SessionConfigSelectOptions;Lkotlinx/serialization/json/JsonElement;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/agentclientprotocol/model/SessionConfigSelectOptions;Lkotlinx/serialization/json/JsonElement;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1-2Q23AbI ()Ljava/lang/String; + public final fun component2 ()Ljava/lang/String; + public final fun component3 ()Ljava/lang/String; + public final fun component4-cDIbsdA ()Ljava/lang/String; + public final fun component5 ()Lcom/agentclientprotocol/model/SessionConfigSelectOptions; + public final fun component6 ()Lkotlinx/serialization/json/JsonElement; + public final fun copy-ajXSYlw (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/agentclientprotocol/model/SessionConfigSelectOptions;Lkotlinx/serialization/json/JsonElement;)Lcom/agentclientprotocol/model/SessionConfigOption$Select; + public static synthetic fun copy-ajXSYlw$default (Lcom/agentclientprotocol/model/SessionConfigOption$Select;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/agentclientprotocol/model/SessionConfigSelectOptions;Lkotlinx/serialization/json/JsonElement;ILjava/lang/Object;)Lcom/agentclientprotocol/model/SessionConfigOption$Select; + public fun equals (Ljava/lang/Object;)Z + public final fun getCurrentValue-cDIbsdA ()Ljava/lang/String; + public fun getDescription ()Ljava/lang/String; + public fun getId-2Q23AbI ()Ljava/lang/String; + public fun getName ()Ljava/lang/String; + public final fun getOptions ()Lcom/agentclientprotocol/model/SessionConfigSelectOptions; + 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/SessionConfigOption$Select$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lcom/agentclientprotocol/model/SessionConfigOption$Select$$serializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/agentclientprotocol/model/SessionConfigOption$Select; + 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/SessionConfigOption$Select;)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/SessionConfigOption$Select$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + +public final class com/agentclientprotocol/model/SessionConfigSelectGroup : com/agentclientprotocol/model/AcpWithMeta { + public static final field Companion Lcom/agentclientprotocol/model/SessionConfigSelectGroup$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-qNdPhfw ()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-OpfNXNI (Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Lkotlinx/serialization/json/JsonElement;)Lcom/agentclientprotocol/model/SessionConfigSelectGroup; + public static synthetic fun copy-OpfNXNI$default (Lcom/agentclientprotocol/model/SessionConfigSelectGroup;Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Lkotlinx/serialization/json/JsonElement;ILjava/lang/Object;)Lcom/agentclientprotocol/model/SessionConfigSelectGroup; + public fun equals (Ljava/lang/Object;)Z + public final fun getGroup-qNdPhfw ()Ljava/lang/String; + public final fun getName ()Ljava/lang/String; + public final fun getOptions ()Ljava/util/List; + 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/SessionConfigSelectGroup$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lcom/agentclientprotocol/model/SessionConfigSelectGroup$$serializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/agentclientprotocol/model/SessionConfigSelectGroup; + 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/SessionConfigSelectGroup;)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/SessionConfigSelectGroup$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + +public final class com/agentclientprotocol/model/SessionConfigSelectOption : com/agentclientprotocol/model/AcpWithMeta { + public static final field Companion Lcom/agentclientprotocol/model/SessionConfigSelectOption$Companion; + public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1-cDIbsdA ()Ljava/lang/String; + public final fun component2 ()Ljava/lang/String; + public final fun component3 ()Ljava/lang/String; + public final fun component4 ()Lkotlinx/serialization/json/JsonElement; + public final fun copy-FiZ2ShM (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;)Lcom/agentclientprotocol/model/SessionConfigSelectOption; + public static synthetic fun copy-FiZ2ShM$default (Lcom/agentclientprotocol/model/SessionConfigSelectOption;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;ILjava/lang/Object;)Lcom/agentclientprotocol/model/SessionConfigSelectOption; + public fun equals (Ljava/lang/Object;)Z + public final fun getDescription ()Ljava/lang/String; + public final fun getName ()Ljava/lang/String; + public final fun getValue-cDIbsdA ()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/SessionConfigSelectOption$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lcom/agentclientprotocol/model/SessionConfigSelectOption$$serializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/agentclientprotocol/model/SessionConfigSelectOption; + 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/SessionConfigSelectOption;)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/SessionConfigSelectOption$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + +public abstract class com/agentclientprotocol/model/SessionConfigSelectOptions { + public static final field Companion Lcom/agentclientprotocol/model/SessionConfigSelectOptions$Companion; +} + +public final class com/agentclientprotocol/model/SessionConfigSelectOptions$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + +public final class com/agentclientprotocol/model/SessionConfigSelectOptions$Flat : com/agentclientprotocol/model/SessionConfigSelectOptions { + public static final field Companion Lcom/agentclientprotocol/model/SessionConfigSelectOptions$Flat$Companion; + public fun (Ljava/util/List;)V + public final fun component1 ()Ljava/util/List; + public final fun copy (Ljava/util/List;)Lcom/agentclientprotocol/model/SessionConfigSelectOptions$Flat; + public static synthetic fun copy$default (Lcom/agentclientprotocol/model/SessionConfigSelectOptions$Flat;Ljava/util/List;ILjava/lang/Object;)Lcom/agentclientprotocol/model/SessionConfigSelectOptions$Flat; + public fun equals (Ljava/lang/Object;)Z + public final fun getOptions ()Ljava/util/List; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final synthetic class com/agentclientprotocol/model/SessionConfigSelectOptions$Flat$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lcom/agentclientprotocol/model/SessionConfigSelectOptions$Flat$$serializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/agentclientprotocol/model/SessionConfigSelectOptions$Flat; + 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/SessionConfigSelectOptions$Flat;)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/SessionConfigSelectOptions$Flat$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + +public final class com/agentclientprotocol/model/SessionConfigSelectOptions$Grouped : com/agentclientprotocol/model/SessionConfigSelectOptions { + public static final field Companion Lcom/agentclientprotocol/model/SessionConfigSelectOptions$Grouped$Companion; + public fun (Ljava/util/List;)V + public final fun component1 ()Ljava/util/List; + public final fun copy (Ljava/util/List;)Lcom/agentclientprotocol/model/SessionConfigSelectOptions$Grouped; + public static synthetic fun copy$default (Lcom/agentclientprotocol/model/SessionConfigSelectOptions$Grouped;Ljava/util/List;ILjava/lang/Object;)Lcom/agentclientprotocol/model/SessionConfigSelectOptions$Grouped; + public fun equals (Ljava/lang/Object;)Z + public final fun getGroups ()Ljava/util/List; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final synthetic class com/agentclientprotocol/model/SessionConfigSelectOptions$Grouped$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lcom/agentclientprotocol/model/SessionConfigSelectOptions$Grouped$$serializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/agentclientprotocol/model/SessionConfigSelectOptions$Grouped; + 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/SessionConfigSelectOptions$Grouped;)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/SessionConfigSelectOptions$Grouped$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + +public final class com/agentclientprotocol/model/SessionConfigValueId { + public static final field Companion Lcom/agentclientprotocol/model/SessionConfigValueId$Companion; + public static final synthetic fun box-impl (Ljava/lang/String;)Lcom/agentclientprotocol/model/SessionConfigValueId; + public static fun constructor-impl (Ljava/lang/String;)Ljava/lang/String; + public fun equals (Ljava/lang/Object;)Z + public static fun equals-impl (Ljava/lang/String;Ljava/lang/Object;)Z + public static final fun equals-impl0 (Ljava/lang/String;Ljava/lang/String;)Z + public final fun getValue ()Ljava/lang/String; + public fun hashCode ()I + public static fun hashCode-impl (Ljava/lang/String;)I + public fun toString ()Ljava/lang/String; + public static fun toString-impl (Ljava/lang/String;)Ljava/lang/String; + public final synthetic fun unbox-impl ()Ljava/lang/String; +} + +public final synthetic class com/agentclientprotocol/model/SessionConfigValueId$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lcom/agentclientprotocol/model/SessionConfigValueId$$serializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public final fun deserialize-zv_mjt0 (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/String; + public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public final fun serialize-w2GC3Xc (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/String;)V + public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; +} + +public final class com/agentclientprotocol/model/SessionConfigValueId$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + +public final class com/agentclientprotocol/model/SessionForkCapabilities : com/agentclientprotocol/model/AcpWithMeta { + public static final field Companion Lcom/agentclientprotocol/model/SessionForkCapabilities$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/SessionForkCapabilities; + public static synthetic fun copy$default (Lcom/agentclientprotocol/model/SessionForkCapabilities;Lkotlinx/serialization/json/JsonElement;ILjava/lang/Object;)Lcom/agentclientprotocol/model/SessionForkCapabilities; + public fun equals (Ljava/lang/Object;)Z + 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/SessionForkCapabilities$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lcom/agentclientprotocol/model/SessionForkCapabilities$$serializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/agentclientprotocol/model/SessionForkCapabilities; + 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/SessionForkCapabilities;)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/SessionForkCapabilities$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + public final class com/agentclientprotocol/model/SessionId { public static final field Companion Lcom/agentclientprotocol/model/SessionId$Companion; public static final synthetic fun box-impl (Ljava/lang/String;)Lcom/agentclientprotocol/model/SessionId; @@ -2150,6 +2618,71 @@ public final class com/agentclientprotocol/model/SessionId$Companion { public final fun serializer ()Lkotlinx/serialization/KSerializer; } +public final class com/agentclientprotocol/model/SessionInfo : com/agentclientprotocol/model/AcpWithMeta { + public static final field Companion Lcom/agentclientprotocol/model/SessionInfo$Companion; + public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;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/lang/String; + public final fun component4 ()Ljava/lang/String; + public final fun component5 ()Lkotlinx/serialization/json/JsonElement; + public final fun copy-8WrnS2s (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;)Lcom/agentclientprotocol/model/SessionInfo; + public static synthetic fun copy-8WrnS2s$default (Lcom/agentclientprotocol/model/SessionInfo;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;ILjava/lang/Object;)Lcom/agentclientprotocol/model/SessionInfo; + public fun equals (Ljava/lang/Object;)Z + public final fun getCwd ()Ljava/lang/String; + public final fun getSessionId-7EW-EgU ()Ljava/lang/String; + public final fun getTitle ()Ljava/lang/String; + public final fun getUpdatedAt ()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/SessionInfo$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lcom/agentclientprotocol/model/SessionInfo$$serializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/agentclientprotocol/model/SessionInfo; + 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/SessionInfo;)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/SessionInfo$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + +public final class com/agentclientprotocol/model/SessionListCapabilities : com/agentclientprotocol/model/AcpWithMeta { + public static final field Companion Lcom/agentclientprotocol/model/SessionListCapabilities$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/SessionListCapabilities; + public static synthetic fun copy$default (Lcom/agentclientprotocol/model/SessionListCapabilities;Lkotlinx/serialization/json/JsonElement;ILjava/lang/Object;)Lcom/agentclientprotocol/model/SessionListCapabilities; + public fun equals (Ljava/lang/Object;)Z + 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/SessionListCapabilities$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lcom/agentclientprotocol/model/SessionListCapabilities$$serializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/agentclientprotocol/model/SessionListCapabilities; + 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/SessionListCapabilities;)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/SessionListCapabilities$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + public final class com/agentclientprotocol/model/SessionMode : com/agentclientprotocol/model/AcpWithMeta { public static final field Companion Lcom/agentclientprotocol/model/SessionMode$Companion; public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;ILkotlin/jvm/internal/DefaultConstructorMarker;)V @@ -2430,6 +2963,36 @@ public final class com/agentclientprotocol/model/SessionUpdate$Companion { public final fun serializer ()Lkotlinx/serialization/KSerializer; } +public final class com/agentclientprotocol/model/SessionUpdate$ConfigOptionUpdate : com/agentclientprotocol/model/SessionUpdate, com/agentclientprotocol/model/AcpWithMeta { + public static final field Companion Lcom/agentclientprotocol/model/SessionUpdate$ConfigOptionUpdate$Companion; + public fun (Ljava/util/List;Lkotlinx/serialization/json/JsonElement;)V + public synthetic fun (Ljava/util/List;Lkotlinx/serialization/json/JsonElement;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1 ()Ljava/util/List; + public final fun component2 ()Lkotlinx/serialization/json/JsonElement; + public final fun copy (Ljava/util/List;Lkotlinx/serialization/json/JsonElement;)Lcom/agentclientprotocol/model/SessionUpdate$ConfigOptionUpdate; + public static synthetic fun copy$default (Lcom/agentclientprotocol/model/SessionUpdate$ConfigOptionUpdate;Ljava/util/List;Lkotlinx/serialization/json/JsonElement;ILjava/lang/Object;)Lcom/agentclientprotocol/model/SessionUpdate$ConfigOptionUpdate; + public fun equals (Ljava/lang/Object;)Z + public final fun getConfigOptions ()Ljava/util/List; + 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/SessionUpdate$ConfigOptionUpdate$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lcom/agentclientprotocol/model/SessionUpdate$ConfigOptionUpdate$$serializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/agentclientprotocol/model/SessionUpdate$ConfigOptionUpdate; + 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/SessionUpdate$ConfigOptionUpdate;)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/SessionUpdate$ConfigOptionUpdate$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + public final class com/agentclientprotocol/model/SessionUpdate$CurrentModeUpdate : com/agentclientprotocol/model/SessionUpdate { public static final field Companion Lcom/agentclientprotocol/model/SessionUpdate$CurrentModeUpdate$Companion; public synthetic fun (Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V @@ -2487,6 +3050,39 @@ public final class com/agentclientprotocol/model/SessionUpdate$PlanUpdate$Compan public final fun serializer ()Lkotlinx/serialization/KSerializer; } +public final class com/agentclientprotocol/model/SessionUpdate$SessionInfoUpdate : com/agentclientprotocol/model/SessionUpdate, com/agentclientprotocol/model/AcpWithMeta { + public static final field Companion Lcom/agentclientprotocol/model/SessionUpdate$SessionInfoUpdate$Companion; + public fun ()V + public fun (Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;)V + public synthetic fun (Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1 ()Ljava/lang/String; + public final fun component2 ()Ljava/lang/String; + public final fun component3 ()Lkotlinx/serialization/json/JsonElement; + public final fun copy (Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;)Lcom/agentclientprotocol/model/SessionUpdate$SessionInfoUpdate; + public static synthetic fun copy$default (Lcom/agentclientprotocol/model/SessionUpdate$SessionInfoUpdate;Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;ILjava/lang/Object;)Lcom/agentclientprotocol/model/SessionUpdate$SessionInfoUpdate; + public fun equals (Ljava/lang/Object;)Z + public final fun getTitle ()Ljava/lang/String; + public final fun getUpdatedAt ()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/SessionUpdate$SessionInfoUpdate$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lcom/agentclientprotocol/model/SessionUpdate$SessionInfoUpdate$$serializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/agentclientprotocol/model/SessionUpdate$SessionInfoUpdate; + 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/SessionUpdate$SessionInfoUpdate;)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/SessionUpdate$SessionInfoUpdate$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + public final class com/agentclientprotocol/model/SessionUpdate$ToolCall : com/agentclientprotocol/model/SessionUpdate, com/agentclientprotocol/model/AcpWithMeta { public static final field Companion Lcom/agentclientprotocol/model/SessionUpdate$ToolCall$Companion; public synthetic fun (Ljava/lang/String;Ljava/lang/String;Lcom/agentclientprotocol/model/ToolKind;Lcom/agentclientprotocol/model/ToolCallStatus;Ljava/util/List;Ljava/util/List;Lkotlinx/serialization/json/JsonElement;Lkotlinx/serialization/json/JsonElement;Lkotlinx/serialization/json/JsonElement;ILkotlin/jvm/internal/DefaultConstructorMarker;)V @@ -2602,6 +3198,70 @@ public final class com/agentclientprotocol/model/SessionUpdate$UserMessageChunk$ public final fun serializer ()Lkotlinx/serialization/KSerializer; } +public final class com/agentclientprotocol/model/SetSessionConfigOptionRequest : com/agentclientprotocol/model/AcpRequest, com/agentclientprotocol/model/AcpWithSessionId { + public static final field Companion Lcom/agentclientprotocol/model/SetSessionConfigOptionRequest$Companion; + public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1-7EW-EgU ()Ljava/lang/String; + public final fun component2-2Q23AbI ()Ljava/lang/String; + public final fun component3-cDIbsdA ()Ljava/lang/String; + public final fun component4 ()Lkotlinx/serialization/json/JsonElement; + public final fun copy--I3Tswc (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;)Lcom/agentclientprotocol/model/SetSessionConfigOptionRequest; + public static synthetic fun copy--I3Tswc$default (Lcom/agentclientprotocol/model/SetSessionConfigOptionRequest;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;ILjava/lang/Object;)Lcom/agentclientprotocol/model/SetSessionConfigOptionRequest; + public fun equals (Ljava/lang/Object;)Z + public final fun getConfigId-2Q23AbI ()Ljava/lang/String; + public fun getSessionId-7EW-EgU ()Ljava/lang/String; + public final fun getValue-cDIbsdA ()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/SetSessionConfigOptionRequest$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lcom/agentclientprotocol/model/SetSessionConfigOptionRequest$$serializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/agentclientprotocol/model/SetSessionConfigOptionRequest; + 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/SetSessionConfigOptionRequest;)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/SetSessionConfigOptionRequest$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + +public final class com/agentclientprotocol/model/SetSessionConfigOptionResponse : com/agentclientprotocol/model/AcpResponse { + public static final field Companion Lcom/agentclientprotocol/model/SetSessionConfigOptionResponse$Companion; + public fun (Ljava/util/List;Lkotlinx/serialization/json/JsonElement;)V + public synthetic fun (Ljava/util/List;Lkotlinx/serialization/json/JsonElement;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1 ()Ljava/util/List; + public final fun component2 ()Lkotlinx/serialization/json/JsonElement; + public final fun copy (Ljava/util/List;Lkotlinx/serialization/json/JsonElement;)Lcom/agentclientprotocol/model/SetSessionConfigOptionResponse; + public static synthetic fun copy$default (Lcom/agentclientprotocol/model/SetSessionConfigOptionResponse;Ljava/util/List;Lkotlinx/serialization/json/JsonElement;ILjava/lang/Object;)Lcom/agentclientprotocol/model/SetSessionConfigOptionResponse; + public fun equals (Ljava/lang/Object;)Z + public final fun getConfigOptions ()Ljava/util/List; + 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/SetSessionConfigOptionResponse$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lcom/agentclientprotocol/model/SetSessionConfigOptionResponse$$serializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/agentclientprotocol/model/SetSessionConfigOptionResponse; + 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/SetSessionConfigOptionResponse;)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/SetSessionConfigOptionResponse$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + public final class com/agentclientprotocol/model/SetSessionModeRequest : com/agentclientprotocol/model/AcpRequest, com/agentclientprotocol/model/AcpWithSessionId { public static final field Companion Lcom/agentclientprotocol/model/SetSessionModeRequest$Companion; public synthetic fun (Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;ILkotlin/jvm/internal/DefaultConstructorMarker;)V diff --git a/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/AcpCreatedSessionResponse.kt b/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/AcpCreatedSessionResponse.kt index 91dcccf..a706c12 100644 --- a/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/AcpCreatedSessionResponse.kt +++ b/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/AcpCreatedSessionResponse.kt @@ -6,4 +6,6 @@ public interface AcpCreatedSessionResponse : AcpWithMeta { public val modes: SessionModeState? @UnstableApi public val models: SessionModelState? + @UnstableApi + public val configOptions: List? } \ No newline at end of file diff --git a/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/AcpPaginatedRequest.kt b/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/AcpPaginatedRequest.kt new file mode 100644 index 0000000..67907a5 --- /dev/null +++ b/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/AcpPaginatedRequest.kt @@ -0,0 +1,15 @@ +package com.agentclientprotocol.model + +import com.agentclientprotocol.annotations.UnstableApi + +/** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Interface for paginated requests that include a cursor for pagination. + */ +@UnstableApi +public interface AcpPaginatedRequest : AcpRequest { + public val cursor: String? +} diff --git a/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/AcpPaginatedResponse.kt b/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/AcpPaginatedResponse.kt new file mode 100644 index 0000000..1ed2b8f --- /dev/null +++ b/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/AcpPaginatedResponse.kt @@ -0,0 +1,16 @@ +package com.agentclientprotocol.model + +import com.agentclientprotocol.annotations.UnstableApi + +/** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Interface for paginated responses that include a cursor for the next page. + */ +@UnstableApi +public interface AcpPaginatedResponse : AcpResponse { + public val nextCursor: String? + public fun getItemsBatch(): List +} 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 c8031cc..03e6d57 100644 --- a/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/Capabilities.kt +++ b/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/Capabilities.kt @@ -3,6 +3,7 @@ package com.agentclientprotocol.model +import com.agentclientprotocol.annotations.UnstableApi import kotlinx.serialization.EncodeDefault import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.Serializable @@ -62,8 +63,39 @@ public data class McpCapabilities( ) : AcpWithMeta /** - * Session resume capabilities supported by the agent. + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Capabilities for forking sessions. + */ +@UnstableApi +@Serializable +public data class SessionForkCapabilities( + override val _meta: JsonElement? = null +) : AcpWithMeta + +/** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Capabilities for listing sessions. */ +@UnstableApi +@Serializable +public data class SessionListCapabilities( + override val _meta: JsonElement? = null +) : AcpWithMeta + +/** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Capabilities for resuming sessions. + */ +@UnstableApi @Serializable public data class SessionResumeCapabilities( override val _meta: JsonElement? = null @@ -71,10 +103,12 @@ public data class SessionResumeCapabilities( /** * Session capabilities supported by the agent. - * */ +@OptIn(UnstableApi::class) @Serializable public data class SessionCapabilities( + val fork: SessionForkCapabilities? = null, + val list: SessionListCapabilities? = null, val resume: SessionResumeCapabilities? = null, override val _meta: JsonElement? = null ) : AcpWithMeta @@ -87,6 +121,7 @@ public data class SessionCapabilities( * * See protocol docs: [Agent Capabilities](https://agentclientprotocol.com/protocol/initialization#agent-capabilities) */ +@OptIn(UnstableApi::class) @Serializable public data class AgentCapabilities( @EncodeDefault val loadSession: Boolean = false, 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 564bfea..d971e89 100644 --- a/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/Methods.kt +++ b/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/Methods.kt @@ -46,8 +46,6 @@ 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()) @@ -55,6 +53,16 @@ public open class AcpMethod(public val methodName: MethodName) { public object SessionSetMode : AcpSessionRequestResponseMethod("session/set_mode", SetSessionModeRequest.serializer(), SetSessionModeResponse.serializer()) @UnstableApi public object SessionSetModel : AcpSessionRequestResponseMethod("session/set_model", SetSessionModelRequest.serializer(), SetSessionModelResponse.serializer()) + + // unstable session methods + @UnstableApi + public object SessionFork : AcpSessionRequestResponseMethod("session/fork", ForkSessionRequest.serializer(), ForkSessionResponse.serializer()) + @UnstableApi + public object SessionList : AcpRequestResponseMethod("session/list", ListSessionsRequest.serializer(), ListSessionsResponse.serializer()) + @UnstableApi + public object SessionResume : AcpSessionRequestResponseMethod("session/resume", ResumeSessionRequest.serializer(), ResumeSessionResponse.serializer()) + @UnstableApi + public object SessionSetConfigOption : AcpSessionRequestResponseMethod("session/set_config_option", SetSessionConfigOptionRequest.serializer(), SetSessionConfigOptionResponse.serializer()) } public object ClientMethods { 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 5339ac8..63b8358 100644 --- a/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/Requests.kt +++ b/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/Requests.kt @@ -212,26 +212,6 @@ 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. @@ -391,11 +371,15 @@ public data class SessionModelState( * * See protocol docs: [Creating a Session](https://agentclientprotocol.com/protocol/session-setup#creating-a-session) */ +@OptIn(UnstableApi::class) @Serializable public data class NewSessionResponse( override val sessionId: SessionId, override val modes: SessionModeState? = null, + @property:UnstableApi override val models: SessionModelState? = null, + @property:UnstableApi + override val configOptions: List? = null, override val _meta: JsonElement? = null ) : AcpCreatedSessionResponse, AcpResponse, AcpWithSessionId @@ -413,25 +397,14 @@ public data class PromptResponse( /** * Response from loading an existing session. */ +@OptIn(UnstableApi::class) @Serializable public data class LoadSessionResponse( override val modes: SessionModeState? = null, + @property:UnstableApi override val models: SessionModelState? = null, - 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, + @property:UnstableApi + override val configOptions: List? = null, override val _meta: JsonElement? = null ) : AcpCreatedSessionResponse, AcpResponse @@ -498,6 +471,139 @@ public data class ReleaseTerminalResponse( override val _meta: JsonElement? = null ) : AcpResponse +// === Unstable Request/Response Types === + +/** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Request to fork a session, creating a new session based on an existing session's context. + */ +@UnstableApi +@Serializable +public data class ForkSessionRequest( + override val sessionId: SessionId, + val cwd: String, + val mcpServers: List, + 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. + * + * Response from forking a session. + */ +@UnstableApi +@Serializable +public data class ForkSessionResponse( + override val sessionId: SessionId, + override val modes: SessionModeState? = null, + @property:UnstableApi + override val models: SessionModelState? = null, + @property:UnstableApi + override val configOptions: List? = null, + override val _meta: JsonElement? = null +) : AcpCreatedSessionResponse, AcpResponse, AcpWithSessionId + +/** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Request to list existing sessions with optional filtering and pagination. + */ +@UnstableApi +@Serializable +public data class ListSessionsRequest( + val cwd: String? = null, + override val cursor: String? = null, + override val _meta: JsonElement? = null +) : AcpRequest, AcpPaginatedRequest + +/** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Response from listing sessions. + */ +@UnstableApi +@Serializable +public data class ListSessionsResponse( + val sessions: List, + override val nextCursor: String? = null, + override val _meta: JsonElement? = null +) : AcpResponse, AcpPaginatedResponse { + override fun getItemsBatch(): List = sessions +} + +/** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Request to resume a session without replaying message history. + */ +@UnstableApi +@Serializable +public data class ResumeSessionRequest( + override val sessionId: SessionId, + val cwd: String, + val mcpServers: List, + 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. + * + * Response from resuming a session. + */ +@UnstableApi +@Serializable +public data class ResumeSessionResponse( + override val modes: SessionModeState? = null, + @property:UnstableApi + override val models: SessionModelState? = null, + @property:UnstableApi + override val configOptions: List? = null, + 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. + * + * Request to set a configuration option for a session. + */ +@UnstableApi +@Serializable +public data class SetSessionConfigOptionRequest( + override val sessionId: SessionId, + val configId: SessionConfigId, + val value: SessionConfigValueId, + 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. + * + * Response from setting a configuration option. + */ +@UnstableApi +@Serializable +public data class SetSessionConfigOptionResponse( + val configOptions: List, + override val _meta: JsonElement? = null +) : AcpResponse + // === Notification Types === /** diff --git a/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/SessionConfig.kt b/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/SessionConfig.kt new file mode 100644 index 0000000..8d2160a --- /dev/null +++ b/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/SessionConfig.kt @@ -0,0 +1,127 @@ +@file:Suppress("unused") +@file:OptIn(ExperimentalSerializationApi::class) + +package com.agentclientprotocol.model + +import com.agentclientprotocol.annotations.UnstableApi +import kotlinx.serialization.DeserializationStrategy +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.JsonClassDiscriminator +import kotlinx.serialization.json.JsonContentPolymorphicSerializer +import kotlinx.serialization.json.JsonElement +import kotlinx.serialization.json.jsonArray +import kotlinx.serialization.json.jsonObject + +/** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * A single option for a session configuration select. + */ +@UnstableApi +@Serializable +public data class SessionConfigSelectOption( + val value: SessionConfigValueId, + val name: String, + val description: String? = null, + override val _meta: JsonElement? = null +) : AcpWithMeta + +/** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * A group of options for a session configuration select. + */ +@UnstableApi +@Serializable +public data class SessionConfigSelectGroup( + val group: SessionConfigGroupId, + val name: String, + val options: List, + override val _meta: JsonElement? = null +) : AcpWithMeta + +/** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Options for a session configuration select, either as a flat list or grouped. + */ +@UnstableApi +@Serializable(with = SessionConfigSelectOptionsSerializer::class) +public sealed class SessionConfigSelectOptions { + /** + * A flat list of options. + */ + @Serializable + public data class Flat( + val options: List + ) : SessionConfigSelectOptions() + + /** + * Options organized into groups. + */ + @Serializable + public data class Grouped( + val groups: List + ) : SessionConfigSelectOptions() +} + +/** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Polymorphic serializer for [SessionConfigSelectOptions]. + */ +@OptIn(UnstableApi::class) +internal object SessionConfigSelectOptionsSerializer : + JsonContentPolymorphicSerializer(SessionConfigSelectOptions::class) { + override fun selectDeserializer(element: JsonElement): DeserializationStrategy { + val array = element.jsonArray + if (array.isEmpty()) return SessionConfigSelectOptions.Flat.serializer() + + val firstElement = array[0].jsonObject + return if ("group" in firstElement) { + SessionConfigSelectOptions.Grouped.serializer() + } else { + SessionConfigSelectOptions.Flat.serializer() + } + } +} + +/** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Configuration option types for sessions. + */ +@UnstableApi +@Serializable +@JsonClassDiscriminator("type") +public sealed class SessionConfigOption : AcpWithMeta { + public abstract val id: SessionConfigId + public abstract val name: String + public abstract val description: String? + + /** + * A select-type configuration option. + */ + @Serializable + @SerialName("select") + public data class Select( + override val id: SessionConfigId, + override val name: String, + override val description: String? = null, + val currentValue: SessionConfigValueId, + val options: SessionConfigSelectOptions, + override val _meta: JsonElement? = null + ) : SessionConfigOption() +} diff --git a/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/SessionUpdate.kt b/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/SessionUpdate.kt index 445b2eb..231f483 100644 --- a/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/SessionUpdate.kt +++ b/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/SessionUpdate.kt @@ -3,6 +3,7 @@ package com.agentclientprotocol.model +import com.agentclientprotocol.annotations.UnstableApi import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -146,4 +147,35 @@ public sealed class SessionUpdate { public data class CurrentModeUpdate( val currentModeId: SessionModeId ) : SessionUpdate() + + /** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Configuration options have been updated. + */ + @UnstableApi + @Serializable + @SerialName("config_option_update") + public data class ConfigOptionUpdate( + val configOptions: List, + override val _meta: JsonElement? = null + ) : SessionUpdate(), AcpWithMeta + + /** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Session information has been updated. + */ + @UnstableApi + @Serializable + @SerialName("session_info_update") + public data class SessionInfoUpdate( + val title: String? = null, + val updatedAt: String? = null, + override val _meta: JsonElement? = null + ) : SessionUpdate(), AcpWithMeta } \ No newline at end of file diff --git a/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/Types.kt b/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/Types.kt index 6d74cb5..1cabd21 100644 --- a/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/Types.kt +++ b/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/Types.kt @@ -88,6 +88,48 @@ public value class ModelId(public val value: String) { override fun toString(): String = value } +/** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Unique identifier for a session configuration option. + */ +@UnstableApi +@JvmInline +@Serializable +public value class SessionConfigId(public val value: String) { + override fun toString(): String = value +} + +/** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Unique identifier for a session configuration value. + */ +@UnstableApi +@JvmInline +@Serializable +public value class SessionConfigValueId(public val value: String) { + override fun toString(): String = value +} + +/** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Unique identifier for a session configuration group. + */ +@UnstableApi +@JvmInline +@Serializable +public value class SessionConfigGroupId(public val value: String) { + override fun toString(): String = value +} + /** * The sender or recipient of messages and data in a conversation. */ @@ -119,4 +161,21 @@ public data class Annotations( val priority: Double? = null, val lastModified: String? = null, override val _meta: JsonElement? = null +) : AcpWithMeta + +/** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Information about an existing session. + */ +@UnstableApi +@Serializable +public data class SessionInfo( + val sessionId: SessionId, + val cwd: String, + val title: String? = null, + val updatedAt: String? = null, + override val _meta: JsonElement? = null ) : AcpWithMeta \ No newline at end of file diff --git a/acp/api/acp.api b/acp/api/acp.api index 445a93f..311b163 100644 --- a/acp/api/acp.api +++ b/acp/api/acp.api @@ -45,11 +45,14 @@ public abstract interface class com/agentclientprotocol/agent/AgentSession { public static synthetic fun cancel$suspendImpl (Lcom/agentclientprotocol/agent/AgentSession;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun getAvailableModels ()Ljava/util/List; public fun getAvailableModes ()Ljava/util/List; + public fun getConfigOptions ()Ljava/util/List; public fun getDefaultMode-kyZWFqk ()Ljava/lang/String; public fun getDefaultModel-GMZLII8 ()Ljava/lang/String; public abstract fun getSessionId-7EW-EgU ()Ljava/lang/String; public abstract fun prompt (Ljava/util/List;Lkotlinx/serialization/json/JsonElement;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static synthetic fun prompt$default (Lcom/agentclientprotocol/agent/AgentSession;Ljava/util/List;Lkotlinx/serialization/json/JsonElement;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; + public fun setConfigOption-p1da2xM (Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static synthetic fun setConfigOption-p1da2xM$suspendImpl (Lcom/agentclientprotocol/agent/AgentSession;Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun setMode-tFeI3nk (Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static synthetic fun setMode-tFeI3nk$suspendImpl (Lcom/agentclientprotocol/agent/AgentSession;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun setModel-BrQ11X8 (Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; @@ -60,9 +63,11 @@ public final class com/agentclientprotocol/agent/AgentSession$DefaultImpls { public static fun cancel (Lcom/agentclientprotocol/agent/AgentSession;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static fun getAvailableModels (Lcom/agentclientprotocol/agent/AgentSession;)Ljava/util/List; public static fun getAvailableModes (Lcom/agentclientprotocol/agent/AgentSession;)Ljava/util/List; + public static fun getConfigOptions (Lcom/agentclientprotocol/agent/AgentSession;)Ljava/util/List; public static fun getDefaultMode-kyZWFqk (Lcom/agentclientprotocol/agent/AgentSession;)Ljava/lang/String; public static fun getDefaultModel-GMZLII8 (Lcom/agentclientprotocol/agent/AgentSession;)Ljava/lang/String; public static synthetic fun prompt$default (Lcom/agentclientprotocol/agent/AgentSession;Ljava/util/List;Lkotlinx/serialization/json/JsonElement;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; + public static fun setConfigOption-p1da2xM (Lcom/agentclientprotocol/agent/AgentSession;Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static fun setMode-tFeI3nk (Lcom/agentclientprotocol/agent/AgentSession;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static fun setModel-BrQ11X8 (Lcom/agentclientprotocol/agent/AgentSession;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } @@ -71,14 +76,22 @@ public abstract interface class com/agentclientprotocol/agent/AgentSupport { public fun authenticate-fMnwWJU (Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static synthetic fun authenticate-fMnwWJU$suspendImpl (Lcom/agentclientprotocol/agent/AgentSupport;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public abstract fun createSession (Lcom/agentclientprotocol/common/SessionCreationParameters;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public fun forkSession-nk3TnMc (Ljava/lang/String;Lcom/agentclientprotocol/common/SessionCreationParameters;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static synthetic fun forkSession-nk3TnMc$suspendImpl (Lcom/agentclientprotocol/agent/AgentSupport;Ljava/lang/String;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 listSessions (Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static synthetic fun listSessions$suspendImpl (Lcom/agentclientprotocol/agent/AgentSupport;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public fun loadSession-nk3TnMc (Ljava/lang/String;Lcom/agentclientprotocol/common/SessionCreationParameters;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static synthetic fun loadSession-nk3TnMc$suspendImpl (Lcom/agentclientprotocol/agent/AgentSupport;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 forkSession-nk3TnMc (Lcom/agentclientprotocol/agent/AgentSupport;Ljava/lang/String;Lcom/agentclientprotocol/common/SessionCreationParameters;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static fun listSessions (Lcom/agentclientprotocol/agent/AgentSupport;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static fun loadSession-nk3TnMc (Lcom/agentclientprotocol/agent/AgentSupport;Ljava/lang/String;Lcom/agentclientprotocol/common/SessionCreationParameters;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; } @@ -86,12 +99,15 @@ public final class com/agentclientprotocol/client/Client { public fun (Lcom/agentclientprotocol/protocol/Protocol;)V public final fun authenticate-fMnwWJU (Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static synthetic fun authenticate-fMnwWJU$default (Lcom/agentclientprotocol/client/Client;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; + public final fun forkSession-wPMwmcM (Ljava/lang/String;Lcom/agentclientprotocol/common/SessionCreationParameters;Lcom/agentclientprotocol/client/ClientOperationsFactory;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public final fun getAgentInfo ()Lcom/agentclientprotocol/agent/AgentInfo; public final fun getClientInfo ()Lcom/agentclientprotocol/client/ClientInfo; public final fun getProtocol ()Lcom/agentclientprotocol/protocol/Protocol; public final fun getSession-0izbxq0 (Ljava/lang/String;)Lcom/agentclientprotocol/client/ClientSession; public final fun initialize (Lcom/agentclientprotocol/client/ClientInfo;Lkotlinx/serialization/json/JsonElement;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; 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 listSessions (Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;)Lkotlinx/coroutines/flow/Flow; + public static synthetic fun listSessions$default (Lcom/agentclientprotocol/client/Client;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;ILjava/lang/Object;)Lkotlinx/coroutines/flow/Flow; 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; @@ -132,6 +148,8 @@ public abstract interface class com/agentclientprotocol/client/ClientSession { public abstract fun getAvailableModels ()Ljava/util/List; public abstract fun getAvailableModes ()Ljava/util/List; public abstract fun getClient ()Lcom/agentclientprotocol/client/Client; + public abstract fun getConfigOptions ()Lkotlinx/coroutines/flow/StateFlow; + public abstract fun getConfigOptionsSupported ()Z public abstract fun getCurrentMode ()Lkotlinx/coroutines/flow/StateFlow; public abstract fun getCurrentModel ()Lkotlinx/coroutines/flow/StateFlow; public abstract fun getModelsSupported ()Z @@ -141,6 +159,8 @@ public abstract interface class com/agentclientprotocol/client/ClientSession { public abstract fun getSessionId-7EW-EgU ()Ljava/lang/String; public abstract fun prompt (Ljava/util/List;Lkotlinx/serialization/json/JsonElement;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static synthetic fun prompt$default (Lcom/agentclientprotocol/client/ClientSession;Ljava/util/List;Lkotlinx/serialization/json/JsonElement;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; + public abstract fun setConfigOption-p1da2xM (Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static synthetic fun setConfigOption-p1da2xM$default (Lcom/agentclientprotocol/client/ClientSession;Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; public abstract fun setMode-tFeI3nk (Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static synthetic fun setMode-tFeI3nk$default (Lcom/agentclientprotocol/client/ClientSession;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; public abstract fun setModel-BrQ11X8 (Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; @@ -149,6 +169,7 @@ public abstract interface class com/agentclientprotocol/client/ClientSession { public final class com/agentclientprotocol/client/ClientSession$DefaultImpls { public static synthetic fun prompt$default (Lcom/agentclientprotocol/client/ClientSession;Ljava/util/List;Lkotlinx/serialization/json/JsonElement;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; + public static synthetic fun setConfigOption-p1da2xM$default (Lcom/agentclientprotocol/client/ClientSession;Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; public static synthetic fun setMode-tFeI3nk$default (Lcom/agentclientprotocol/client/ClientSession;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; public static synthetic fun setModel-BrQ11X8$default (Lcom/agentclientprotocol/client/ClientSession;Ljava/lang/String;Lkotlinx/serialization/json/JsonElement;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; } @@ -282,6 +303,7 @@ public final class com/agentclientprotocol/protocol/Protocol : com/agentclientpr public final class com/agentclientprotocol/protocol/ProtocolKt { public static final fun acpFail (Ljava/lang/String;)Ljava/lang/Void; + public static final fun jsonRpcInvalidParams (Ljava/lang/String;)Ljava/lang/Void; public static final fun jsonRpcMethodNotFound (Ljava/lang/String;)Ljava/lang/Void; } @@ -297,11 +319,14 @@ public final class com/agentclientprotocol/protocol/Protocol_extensionsKt { public static final fun getJsonRpcRequest (Lkotlin/coroutines/CoroutineContext;)Lcom/agentclientprotocol/rpc/JsonRpcRequest; public static final fun invoke (Lcom/agentclientprotocol/model/AcpMethod$AcpNotificationMethod;Lcom/agentclientprotocol/protocol/RpcMethodsOperations;Lcom/agentclientprotocol/model/AcpNotification;)V public static final fun invoke (Lcom/agentclientprotocol/model/AcpMethod$AcpRequestResponseMethod;Lcom/agentclientprotocol/protocol/RpcMethodsOperations;Lcom/agentclientprotocol/model/AcpRequest;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun sendBatchedRequest (Lcom/agentclientprotocol/protocol/RpcMethodsOperations;Lcom/agentclientprotocol/model/AcpMethod$AcpRequestResponseMethod;Lkotlin/jvm/functions/Function1;)Lkotlinx/coroutines/flow/Flow; public static final fun sendNotification (Lcom/agentclientprotocol/protocol/RpcMethodsOperations;Lcom/agentclientprotocol/model/AcpMethod$AcpNotificationMethod;Lcom/agentclientprotocol/model/AcpNotification;)V public static synthetic fun sendNotification$default (Lcom/agentclientprotocol/protocol/RpcMethodsOperations;Lcom/agentclientprotocol/model/AcpMethod$AcpNotificationMethod;Lcom/agentclientprotocol/model/AcpNotification;ILjava/lang/Object;)V public static final fun sendRequest (Lcom/agentclientprotocol/protocol/RpcMethodsOperations;Lcom/agentclientprotocol/model/AcpMethod$AcpRequestResponseMethod;Lcom/agentclientprotocol/model/AcpRequest;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static final fun setNotificationHandler (Lcom/agentclientprotocol/protocol/RpcMethodsOperations;Lcom/agentclientprotocol/model/AcpMethod$AcpNotificationMethod;Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function2;)V public static synthetic fun setNotificationHandler$default (Lcom/agentclientprotocol/protocol/RpcMethodsOperations;Lcom/agentclientprotocol/model/AcpMethod$AcpNotificationMethod;Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)V + public static final fun setPaginatedRequestHandler (Lcom/agentclientprotocol/protocol/RpcMethodsOperations;Lcom/agentclientprotocol/model/AcpMethod$AcpRequestResponseMethod;ILkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;)V + public static synthetic fun setPaginatedRequestHandler$default (Lcom/agentclientprotocol/protocol/RpcMethodsOperations;Lcom/agentclientprotocol/model/AcpMethod$AcpRequestResponseMethod;ILkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)V public static final fun setRequestHandler (Lcom/agentclientprotocol/protocol/RpcMethodsOperations;Lcom/agentclientprotocol/model/AcpMethod$AcpRequestResponseMethod;Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function2;)V public static synthetic fun setRequestHandler$default (Lcom/agentclientprotocol/protocol/RpcMethodsOperations;Lcom/agentclientprotocol/model/AcpMethod$AcpRequestResponseMethod;Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)V } @@ -368,3 +393,16 @@ public final class com/agentclientprotocol/transport/TransportKt { public static final fun asMessageChannel (Lcom/agentclientprotocol/transport/Transport;)Lkotlinx/coroutines/channels/Channel; } +public final class com/agentclientprotocol/util/PaginatedResponseToFlowAdapter { + public static final field INSTANCE Lcom/agentclientprotocol/util/PaginatedResponseToFlowAdapter; + public final fun asFlow (Lkotlin/jvm/functions/Function2;)Lkotlinx/coroutines/flow/Flow; +} + +public final class com/agentclientprotocol/util/SequenceToPaginatedResponseAdapter { + public synthetic fun (IJILkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (IJLkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun getBatchSize ()I + public final fun getOrphanedIteratorsEvictionTimeout-UwyO8pc ()J + public final fun next (Lcom/agentclientprotocol/model/AcpPaginatedRequest;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +} + diff --git a/acp/src/commonMain/kotlin/com/agentclientprotocol/agent/Agent.kt b/acp/src/commonMain/kotlin/com/agentclientprotocol/agent/Agent.kt index 3ad1fc6..5e876e0 100644 --- a/acp/src/commonMain/kotlin/com/agentclientprotocol/agent/Agent.kt +++ b/acp/src/commonMain/kotlin/com/agentclientprotocol/agent/Agent.kt @@ -1,5 +1,6 @@ package com.agentclientprotocol.agent +import com.agentclientprotocol.annotations.UnstableApi import com.agentclientprotocol.client.ClientInfo import com.agentclientprotocol.common.ClientSessionOperations import com.agentclientprotocol.common.Event @@ -20,6 +21,7 @@ import kotlin.coroutines.AbstractCoroutineContextElement import kotlin.coroutines.CoroutineContext import kotlin.coroutines.cancellation.CancellationException import kotlin.math.min +import kotlin.uuid.ExperimentalUuidApi private val logger = KotlinLogging.logger {} @@ -117,6 +119,8 @@ public class Agent( setHandlers(protocol) } + + @OptIn(ExperimentalUuidApi::class, UnstableApi::class) private fun setHandlers(protocol: Protocol) { // Set up request handlers for incoming client requests protocol.setRequestHandler(AcpMethod.AgentMethods.Initialize) { params: InitializeRequest -> @@ -132,25 +136,37 @@ public class Agent( return@setRequestHandler agentSupport.authenticate(params.methodId, params._meta) } + protocol.setPaginatedRequestHandler( + AcpMethod.AgentMethods.SessionList, + // TODO: move to some global agent/client settings + batchSize = 10, + batchedResultFactory = { _, batch, newCursor -> ListSessionsResponse(batch, newCursor) }, + sequenceFactory = { p -> agentSupport.listSessions(p.cwd, p._meta) } + ) + protocol.setRequestHandler(AcpMethod.AgentMethods.SessionNew) { params: NewSessionRequest -> val sessionParameters = SessionCreationParameters(params.cwd, params.mcpServers, params._meta) val session = createSession(sessionParameters) { agentSupport.createSession(it) } + @OptIn(UnstableApi::class) return@setRequestHandler NewSessionResponse( sessionId = session.sessionId, modes = session.asModeState(), - models = session.asModelState() + models = session.asModelState(), + configOptions = session.asConfigOptionsState() ) } protocol.setRequestHandler(AcpMethod.AgentMethods.SessionLoad) { params: LoadSessionRequest -> val sessionParameters = SessionCreationParameters(params.cwd, params.mcpServers, params._meta) val session = createSession(sessionParameters) { agentSupport.loadSession(params.sessionId, sessionParameters) } + @OptIn(UnstableApi::class) return@setRequestHandler LoadSessionResponse( // maybe unify result of these two methods to have sessionId in both // sessionId = session.sessionId, modes = session.asModeState(), - models = session.asModelState() + models = session.asModelState(), + configOptions = session.asConfigOptionsState() ) } @@ -169,6 +185,7 @@ public class Agent( session.agentSession.setMode(params.modeId, params._meta) } } + @OptIn(UnstableApi::class) protocol.setRequestHandler(AcpMethod.AgentMethods.SessionSetModel) { params: SetSessionModelRequest -> val session = getSessionOrThrow(params.sessionId) return@setRequestHandler session.executeWithSession { @@ -189,6 +206,37 @@ public class Agent( session.cancel() } } + + @OptIn(UnstableApi::class) + protocol.setRequestHandler(AcpMethod.AgentMethods.SessionFork) { params: ForkSessionRequest -> + val sessionParameters = SessionCreationParameters(params.cwd, params.mcpServers, params._meta) + val session = createSession(sessionParameters) { agentSupport.forkSession(params.sessionId, sessionParameters) } + return@setRequestHandler ForkSessionResponse( + sessionId = session.sessionId, + modes = session.asModeState(), + models = session.asModelState(), + configOptions = session.asConfigOptionsState() + ) + } + + @OptIn(UnstableApi::class) + 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(), + configOptions = session.asConfigOptionsState() + ) + } + + @OptIn(UnstableApi::class) + protocol.setRequestHandler(AcpMethod.AgentMethods.SessionSetConfigOption) { params: SetSessionConfigOptionRequest -> + val session = getSessionOrThrow(params.sessionId) + return@setRequestHandler session.executeWithSession { + session.agentSession.setConfigOption(params.configId, params.value, params._meta) + } + } } private suspend fun createSession(sessionParameters: SessionCreationParameters, sessionFactory: suspend (SessionCreationParameters) -> AgentSession): AgentSession { diff --git a/acp/src/commonMain/kotlin/com/agentclientprotocol/agent/AgentSession.kt b/acp/src/commonMain/kotlin/com/agentclientprotocol/agent/AgentSession.kt index a29f258..059728a 100644 --- a/acp/src/commonMain/kotlin/com/agentclientprotocol/agent/AgentSession.kt +++ b/acp/src/commonMain/kotlin/com/agentclientprotocol/agent/AgentSession.kt @@ -64,6 +64,29 @@ public interface AgentSession { public suspend fun setModel(modelId: ModelId, _meta: JsonElement?): SetSessionModelResponse { throw NotImplementedError("Must be implemented when providing non-empty ${::availableModels.name}") } + + /** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Return a list of available configuration options for the session. If the session doesn't support config options, return an empty list. + */ + @UnstableApi + public val configOptions: List + get() = emptyList() + + /** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Called when a client asks to change a configuration option. If the option is changed [SessionUpdate.ConfigOptionUpdate] must be sent to the client. + */ + @UnstableApi + public suspend fun setConfigOption(configId: SessionConfigId, value: SessionConfigValueId, _meta: JsonElement?): SetSessionConfigOptionResponse { + throw NotImplementedError("Must be implemented when providing non-empty ${::configOptions.name}") + } } @UnstableApi @@ -77,4 +100,11 @@ internal fun AgentSession.asModeState(): SessionModeState? { val modes = availableModes if (modes.isEmpty()) return null return SessionModeState(defaultMode, modes) +} + +@UnstableApi +internal fun AgentSession.asConfigOptionsState(): List? { + val options = configOptions + if (options.isEmpty()) return null + return options } \ No newline at end of file diff --git a/acp/src/commonMain/kotlin/com/agentclientprotocol/agent/AgentSupport.kt b/acp/src/commonMain/kotlin/com/agentclientprotocol/agent/AgentSupport.kt index b67a021..31c9db3 100644 --- a/acp/src/commonMain/kotlin/com/agentclientprotocol/agent/AgentSupport.kt +++ b/acp/src/commonMain/kotlin/com/agentclientprotocol/agent/AgentSupport.kt @@ -6,25 +6,94 @@ import com.agentclientprotocol.common.SessionCreationParameters import com.agentclientprotocol.model.AuthMethodId import com.agentclientprotocol.model.AuthenticateResponse import com.agentclientprotocol.model.SessionId +import com.agentclientprotocol.model.SessionInfo import kotlinx.serialization.json.JsonElement public interface AgentSupport { + /** + * Initializes the agent with the client information. + * + * Called when a client connects and sends an initialize request. + * + * @param clientInfo information about the connecting client + * @return an [AgentInfo] containing the agent's capabilities and information + */ public suspend fun initialize(clientInfo: ClientInfo): AgentInfo + + /** + * Performs authentication using the specified authentication method. + * + * @param methodId the id of the authentication method to use + * @param _meta optional metadata + * @return an [AuthenticateResponse] indicating the authentication result + */ public suspend fun authenticate(methodId: AuthMethodId, _meta: JsonElement?): AuthenticateResponse = AuthenticateResponse() + + /** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Lists existing sessions with optional filtering and pagination. + * Pagination is automatically handled by [com.agentclientprotocol.util.SequenceToPaginatedResponseAdapter]. + * + * @param cwd optional current working directory filter + * @param _meta optional metadata + * @return a sequence of [SessionInfo] + */ + @UnstableApi + public suspend fun listSessions(cwd: String?, _meta: JsonElement?): Sequence { + throw NotImplementedError("listSessions is not implemented. The capability is declared in AgentCapabilities.sessionCapabilities.list") + } + + /** + * Creates a new session with the specified parameters. + * + * @param sessionParameters parameters for creating the session + * @return an [AgentSession] instance for the new session + */ public suspend fun createSession(sessionParameters: SessionCreationParameters): AgentSession - public suspend fun loadSession(sessionId: SessionId, sessionParameters: SessionCreationParameters): AgentSession + + /** + * Loads an existing session with the specified id and parameters. + * + * @param sessionId the id of the session to load + * @param sessionParameters parameters for loading the session + * @return an [AgentSession] instance for the loaded session + */ + public suspend fun loadSession(sessionId: SessionId, sessionParameters: SessionCreationParameters): AgentSession { + throw NotImplementedError("loadSession is not implemented. The capability is declared in AgentCapabilities.loadSession") + } + + /** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Forks an existing session, creating a new session based on the existing session's context. + * + * @param sessionId the id of the session to fork + * @param sessionParameters parameters for the forked session + * @return an [AgentSession] instance for the forked session + */ + @UnstableApi + public suspend fun forkSession(sessionId: SessionId, sessionParameters: SessionCreationParameters): AgentSession { + throw NotImplementedError("forkSession is not implemented. The capability is declared in AgentCapabilities.sessionCapabilities.fork") + } /** * **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. + * Resumes an existing session without replaying message history. * - * This method is only available if the agent advertises the `session.resume` capability. + * @param sessionId the id of the session to resume + * @param sessionParameters parameters for resuming the session + * @return an [AgentSession] instance for the resumed session */ @UnstableApi public suspend fun resumeSession(sessionId: SessionId, sessionParameters: SessionCreationParameters): AgentSession { - throw NotImplementedError("Must be implemented by agent when advertising session.resume capability") + throw NotImplementedError("resumeSession is not implemented. The capability is declared in AgentCapabilities.sessionCapabilities.resume") } } \ 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 bea5293..39cbbb3 100644 --- a/acp/src/commonMain/kotlin/com/agentclientprotocol/client/Client.kt +++ b/acp/src/commonMain/kotlin/com/agentclientprotocol/client/Client.kt @@ -3,17 +3,20 @@ package com.agentclientprotocol.client import com.agentclientprotocol.agent.AgentInfo +import com.agentclientprotocol.annotations.UnstableApi import com.agentclientprotocol.common.FileSystemOperations import com.agentclientprotocol.common.SessionCreationParameters import com.agentclientprotocol.common.TerminalOperations import com.agentclientprotocol.model.* import com.agentclientprotocol.protocol.* +import com.agentclientprotocol.util.PaginatedResponseToFlowAdapter import io.github.oshai.kotlinlogging.KotlinLogging import kotlinx.atomicfu.atomic import kotlinx.atomicfu.update import kotlinx.collections.immutable.persistentMapOf import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.update @@ -206,17 +209,75 @@ public class Client( * * 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. + * Lists all existing sessions as a cold flow, automatically handling pagination. The necessary pages are fetched on demand. + * + * The flow is cold and finite, so any aggregation operators may be used like `toList`, `take`, etc. + * + * Unlike the agent's side, this method returns a cold flow instead of a sequence because remote suspend calls are being done under the hood to fetch pages. + * Sequences don't support suspending operations between value yields. + * + * @param cwd optional current working directory filter + * @param _meta optional metadata + * @return a cold [Flow] of [SessionInfo] that lazily fetches pages as needed + */ + @UnstableApi + public fun listSessions( + cwd: String? = null, + _meta: JsonElement? = null + ): Flow { + return PaginatedResponseToFlowAdapter.asFlow { cursor -> + AcpMethod.AgentMethods.SessionList(protocol, ListSessionsRequest(cwd, cursor, _meta)) + } + } + + /** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Forks an existing session, creating a new session based on the existing session's context. + * + * @param sessionId the id of the session to fork + * @param sessionParameters parameters for the forked session + * @param operationsFactory a factory for creating [com.agentclientprotocol.common.ClientSessionOperations] for the new 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 forked session + */ + @UnstableApi + public suspend fun forkSession(sessionId: SessionId, sessionParameters: SessionCreationParameters, operationsFactory: ClientOperationsFactory): ClientSession { + return withInitializingSession { + val forkSessionResponse = AcpMethod.AgentMethods.SessionFork( + protocol, + ForkSessionRequest( + sessionId, + sessionParameters.cwd, + sessionParameters.mcpServers, + sessionParameters._meta + ) + ) + val newSessionId = forkSessionResponse.sessionId + return@withInitializingSession createSession(newSessionId, sessionParameters, forkSessionResponse, operationsFactory) + } + } + + /** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Resumes an existing session without replaying message history. * * This method is only available if the agent advertises the `session.resume` capability. * - * @param sessionId the id of the existing session to resume + * @param sessionId the id of the 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 */ + @UnstableApi public suspend fun resumeSession(sessionId: SessionId, sessionParameters: SessionCreationParameters, operationsFactory: ClientOperationsFactory): ClientSession { return withInitializingSession { val resumeSessionResponse = AcpMethod.AgentMethods.SessionResume( diff --git a/acp/src/commonMain/kotlin/com/agentclientprotocol/client/ClientSession.kt b/acp/src/commonMain/kotlin/com/agentclientprotocol/client/ClientSession.kt index 0c2564e..f7801c5 100644 --- a/acp/src/commonMain/kotlin/com/agentclientprotocol/client/ClientSession.kt +++ b/acp/src/commonMain/kotlin/com/agentclientprotocol/client/ClientSession.kt @@ -76,4 +76,42 @@ public interface ClientSession { */ @UnstableApi public suspend fun setModel(modelId: ModelId, _meta: JsonElement? = null): SetSessionModelResponse + + /** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * The flag indicates whether the agent supports session configuration options. + */ + @UnstableApi + public val configOptionsSupported: Boolean + + /** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Returns the current configuration options for the session. + * Check for [configOptionsSupported] before calling this method. + * + * @throws IllegalStateException if configuration options are not supported. + */ + @UnstableApi + public val configOptions: StateFlow> + + /** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Sets a configuration option for the session. + * + * @param configId the id of the configuration option to set + * @param value the value to set for the configuration option + * @param _meta optional metadata + * @return a [SetSessionConfigOptionResponse] containing the updated configuration options + */ + @UnstableApi + public suspend fun setConfigOption(configId: SessionConfigId, value: SessionConfigValueId, _meta: JsonElement? = null): SetSessionConfigOptionResponse } \ No newline at end of file diff --git a/acp/src/commonMain/kotlin/com/agentclientprotocol/client/ClientSessionImpl.kt b/acp/src/commonMain/kotlin/com/agentclientprotocol/client/ClientSessionImpl.kt index bd2135e..559d1ea 100644 --- a/acp/src/commonMain/kotlin/com/agentclientprotocol/client/ClientSessionImpl.kt +++ b/acp/src/commonMain/kotlin/com/agentclientprotocol/client/ClientSessionImpl.kt @@ -48,6 +48,12 @@ internal class ClientSessionImpl( MutableStateFlow(models.currentModelId) } + @UnstableApi + private val _configOptions by lazy { + val configOptions = createdResponse.configOptions ?: error("Config options are not provided by the agent") + MutableStateFlow(configOptions) + } + override suspend fun prompt( content: List, _meta: JsonElement?, @@ -117,6 +123,21 @@ internal class ClientSessionImpl( return AcpMethod.AgentMethods.SessionSetModel(protocol, SetSessionModelRequest(sessionId, modelId, _meta)) } + @UnstableApi + override val configOptionsSupported: Boolean + get() = createdResponse.configOptions != null + + @UnstableApi + override val configOptions: StateFlow> + get() = _configOptions + + @UnstableApi + override suspend fun setConfigOption(configId: SessionConfigId, value: SessionConfigValueId, _meta: JsonElement?): SetSessionConfigOptionResponse { + val response = AcpMethod.AgentMethods.SessionSetConfigOption(protocol, SetSessionConfigOptionRequest(sessionId, configId, value, _meta)) + _configOptions.value = response.configOptions + return response + } + internal suspend fun executeWithSession(block: suspend () -> T): T { return withContext(this.asContextElement()) { block() @@ -136,6 +157,10 @@ internal class ClientSessionImpl( // if (notification is SessionUpdate.CurrentModelUpdate) { // _currentModel.value = notification.currentModelId // } + @OptIn(UnstableApi::class) + if (notification is SessionUpdate.ConfigOptionUpdate && configOptionsSupported) { + _configOptions.value = notification.configOptions + } val promptSession = activePrompt.value @OptIn(DelicateCoroutinesApi::class) diff --git a/acp/src/commonMain/kotlin/com/agentclientprotocol/protocol/Protocol.extensions.kt b/acp/src/commonMain/kotlin/com/agentclientprotocol/protocol/Protocol.extensions.kt index eff50cd..95b642c 100644 --- a/acp/src/commonMain/kotlin/com/agentclientprotocol/protocol/Protocol.extensions.kt +++ b/acp/src/commonMain/kotlin/com/agentclientprotocol/protocol/Protocol.extensions.kt @@ -1,15 +1,19 @@ package com.agentclientprotocol.protocol +import com.agentclientprotocol.annotations.UnstableApi import com.agentclientprotocol.model.AcpMethod import com.agentclientprotocol.model.AcpNotification +import com.agentclientprotocol.model.AcpPaginatedRequest +import com.agentclientprotocol.model.AcpPaginatedResponse import com.agentclientprotocol.model.AcpRequest import com.agentclientprotocol.model.AcpResponse import com.agentclientprotocol.rpc.ACPJson import com.agentclientprotocol.rpc.JsonRpcRequest +import com.agentclientprotocol.util.PaginatedResponseToFlowAdapter +import com.agentclientprotocol.util.SequenceToPaginatedResponseAdapter +import kotlinx.coroutines.flow.Flow import kotlinx.serialization.json.JsonNull import kotlinx.serialization.json.buildJsonObject -import kotlinx.serialization.json.decodeFromJsonElement -import kotlinx.serialization.json.encodeToJsonElement import kotlin.coroutines.AbstractCoroutineContextElement import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext @@ -28,6 +32,20 @@ public suspend fun RpcMethodsOp return ACPJson.decodeFromJsonElement(method.responseSerializer, responseJson) } +/** + * Send a batched request and return a cold [Flow] that automatically fetches subsequent pages. + * The flow is cold - it won't start fetching until collection begins. + */ +@UnstableApi +public fun , TItem> RpcMethodsOperations.sendBatchedRequest( + method: AcpMethod.AcpRequestResponseMethod, + requestFactory: (cursor: String?) -> TRequest +): Flow { + return PaginatedResponseToFlowAdapter.asFlow { cursor -> + sendRequest(method, requestFactory(cursor)) + } +} + /** * Send a notification (no response expected). */ @@ -53,6 +71,24 @@ public fun RpcMethodsOperations. ACPJson.encodeToJsonElement(method.responseSerializer, responseObject) } } + +@OptIn(UnstableApi::class) +public fun, TItem> RpcMethodsOperations.setPaginatedRequestHandler( + method: AcpMethod.AcpRequestResponseMethod, + batchSize: Int = 10, + additionalContext: CoroutineContext = EmptyCoroutineContext, + batchedResultFactory: (request: TRequest, batch: List, newCursor: String?) -> TResponse, + sequenceFactory: suspend (request: TRequest) -> Sequence +) { + val paginatedResponseAdapter = SequenceToPaginatedResponseAdapter(batchSize = batchSize) + this.setRequestHandler(method, additionalContext) { params -> + return@setRequestHandler paginatedResponseAdapter.next( + params = params, + sequenceFactory = sequenceFactory, + resultFactory = { _, batch, newCursor -> batchedResultFactory(params, batch, newCursor) } + ) + } +} /** * Register a handler for incoming notifications. */ diff --git a/acp/src/commonMain/kotlin/com/agentclientprotocol/protocol/Protocol.kt b/acp/src/commonMain/kotlin/com/agentclientprotocol/protocol/Protocol.kt index b372ab5..bb17d28 100644 --- a/acp/src/commonMain/kotlin/com/agentclientprotocol/protocol/Protocol.kt +++ b/acp/src/commonMain/kotlin/com/agentclientprotocol/protocol/Protocol.kt @@ -46,6 +46,9 @@ public fun acpFail(message: String): Nothing = throw AcpExpectedError(message) public fun jsonRpcMethodNotFound(message: String): Nothing = throw JsonRpcException(JsonRpcErrorCode.METHOD_NOT_FOUND.code, message) +public fun jsonRpcInvalidParams(message: String): Nothing = + throw JsonRpcException(JsonRpcErrorCode.INVALID_PARAMS.code, message) + /** * Exception thrown for JSON-RPC protocol errors. */ diff --git a/acp/src/commonMain/kotlin/com/agentclientprotocol/util/PaginatedResponseToFlowAdapter.kt b/acp/src/commonMain/kotlin/com/agentclientprotocol/util/PaginatedResponseToFlowAdapter.kt new file mode 100644 index 0000000..3f016de --- /dev/null +++ b/acp/src/commonMain/kotlin/com/agentclientprotocol/util/PaginatedResponseToFlowAdapter.kt @@ -0,0 +1,55 @@ +package com.agentclientprotocol.util + +import com.agentclientprotocol.annotations.UnstableApi +import com.agentclientprotocol.model.AcpPaginatedResponse +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow + +/** + * Adapter that converts paginated responses into a [Flow] for convenient iteration on the client side. + * + * This adapter lazily fetches pages as the flow is collected, making subsequent requests + * only when needed. It handles cursor-based pagination automatically. + * + * Example usage: + * ```kotlin + * val sessionsFlow: Flow = PaginatedResponseToFlowAdapter.asFlow( + * batchFetcher = { cursor -> client.listSessions(cwd = "/project", cursor = cursor) } + * ) + * + * // Consume all sessions across all pages + * sessionsFlow.collect { session -> + * println(session.sessionId) + * } + * ``` + */ +@UnstableApi +public object PaginatedResponseToFlowAdapter { + + /** + * Converts paginated responses into a cold [Flow] that automatically fetches subsequent pages. + * The flow is cold - it doesn't start fetching until collection begins, and each collector + * gets its own independent execution. + * + * @param TItem the type of items in the paginated response + * @param TResponse the paginated response type + * @param batchFetcher suspending function to fetch a page by cursor (null for first page) + * @return a cold [Flow] that lazily iterates through all items across all pages + */ + public fun > asFlow( + batchFetcher: suspend (cursor: String?) -> TResponse + ): Flow = flow { + var nextCursor: String? = null + + while (true) { + val response = batchFetcher(nextCursor) + + for (item in response.getItemsBatch()) { + emit(item) + } + + nextCursor = response.nextCursor + if (nextCursor == null) break + } + } +} \ No newline at end of file diff --git a/acp/src/commonMain/kotlin/com/agentclientprotocol/util/SequenceToPaginatedResponseAdapter.kt b/acp/src/commonMain/kotlin/com/agentclientprotocol/util/SequenceToPaginatedResponseAdapter.kt new file mode 100644 index 0000000..673c199 --- /dev/null +++ b/acp/src/commonMain/kotlin/com/agentclientprotocol/util/SequenceToPaginatedResponseAdapter.kt @@ -0,0 +1,92 @@ +package com.agentclientprotocol.util + +import com.agentclientprotocol.annotations.UnstableApi +import com.agentclientprotocol.model.AcpPaginatedRequest +import com.agentclientprotocol.model.AcpPaginatedResponse +import com.agentclientprotocol.protocol.JsonRpcException +import com.agentclientprotocol.protocol.jsonRpcInvalidParams +import com.agentclientprotocol.rpc.JsonRpcErrorCode +import kotlinx.collections.immutable.persistentMapOf +import kotlinx.coroutines.CoroutineName +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import kotlin.concurrent.atomics.AtomicReference +import kotlin.concurrent.atomics.ExperimentalAtomicApi +import kotlin.concurrent.atomics.update +import kotlin.time.Duration +import kotlin.time.Duration.Companion.minutes +import kotlin.uuid.ExperimentalUuidApi +import kotlin.uuid.Uuid + +/** + * Adapter that converts a [Sequence] into paginated responses for cursor-based pagination. + * + * This class stores iterators internally and uses cursors to track pagination state across + * multiple requests. Each cursor can only be used once — after retrieving a batch, the cursor + * is invalidated and a new cursor is returned for the next batch (if more items are available). + * + * @param TItem the type of items in the sequence + * @param TInput the paginated request type containing an optional cursor + * @param TOutput the paginated response type containing items and the next cursor + * @param batchSize the number of items to return per page (default: 10) + */ +@OptIn(ExperimentalAtomicApi::class, UnstableApi::class) +public class SequenceToPaginatedResponseAdapter>( + public val batchSize: Int = 10, + public val orphanedIteratorsEvictionTimeout: Duration = 1.minutes +) { + init { + require(orphanedIteratorsEvictionTimeout > Duration.ZERO) { "orphanedIteratorsEvictionTimeout must be positive" } + } + + private class IteratorState(val iterator: Iterator, val timeoutJob: Job) + private val iterators = AtomicReference(persistentMapOf>()) + + // Since all jobs are stopped by timeout we can omit a separate method for closing this scope because eventually it has no active jobs + private val timeoutJobScope = CoroutineScope(Dispatchers.Default + SupervisorJob() + CoroutineName("SequenceToPaginatedResponseAdapter.timeoutJobScope")) + + /** + * Creates [TOutput] instance for the next [batchSize] items from the sequence either stored + * by the provided [params.cursor] or if no cursor is provided a new sequence is created by [sequenceFactory]. + * + * @throws JsonRpcException with [JsonRpcErrorCode.INVALID_PARAMS] if there is no such cursor. + */ + public suspend fun next(params: TInput, sequenceFactory: suspend (TInput) -> Sequence, resultFactory: (params: TInput, batch: List, newCursor: String?) -> TOutput): TOutput { + val givenCursor = params.cursor + val iterator = if (givenCursor == null) { + sequenceFactory(params).iterator() + } + else { + var iteratorFromMap: Iterator? = null + var timeoutJob: Job? = null + iterators.update { map -> + iteratorFromMap = map[givenCursor]?.iterator + timeoutJob = map[givenCursor]?.timeoutJob + map.remove(givenCursor) + } + timeoutJob?.cancel() + iteratorFromMap ?: jsonRpcInvalidParams("No such cursor: $givenCursor") + } + val batch = iterator.asSequence().take(batchSize).toList() + + val newCursor = if (iterator.hasNext()) { + @OptIn(ExperimentalUuidApi::class) + val newCursor = Uuid.random().toHexDashString() + val timeoutJob = timeoutJobScope.launch { + delay(orphanedIteratorsEvictionTimeout) + iterators.update { map -> map.remove(newCursor) } + } + iterators.update { map -> map.put(newCursor, IteratorState(iterator, timeoutJob)) } + newCursor + } + else { + null + } + + return resultFactory(params, batch, newCursor) + } +} diff --git a/acp/src/jvmTest/kotlin/com/agentclientprotocol/util/PaginatedResponseToFlowAdapterTest.kt b/acp/src/jvmTest/kotlin/com/agentclientprotocol/util/PaginatedResponseToFlowAdapterTest.kt new file mode 100644 index 0000000..80e8904 --- /dev/null +++ b/acp/src/jvmTest/kotlin/com/agentclientprotocol/util/PaginatedResponseToFlowAdapterTest.kt @@ -0,0 +1,185 @@ +package com.agentclientprotocol.util + +import com.agentclientprotocol.annotations.UnstableApi +import com.agentclientprotocol.model.AcpPaginatedResponse +import kotlinx.coroutines.CancellationException +import kotlinx.coroutines.flow.take +import kotlinx.coroutines.flow.toList +import kotlinx.coroutines.runBlocking +import kotlinx.serialization.json.JsonElement +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertFalse +import kotlin.test.assertTrue + +@OptIn(UnstableApi::class) +class PaginatedResponseToFlowAdapterTest { + + private data class TestResponse( + val items: List, + override val nextCursor: String?, + override val _meta: JsonElement? = null + ) : AcpPaginatedResponse { + override fun getItemsBatch(): List = items + } + + @Test + fun `iterates through all pages`() = runBlocking { + val pages = mapOf( + null to TestResponse(listOf(1, 2, 3), "cursor1"), + "cursor1" to TestResponse(listOf(4, 5, 6), "cursor2"), + "cursor2" to TestResponse(listOf(7, 8), null) + ) + + val flow = PaginatedResponseToFlowAdapter.asFlow( + batchFetcher = { cursor -> pages[cursor]!! } + ) + + val result = flow.toList() + assertEquals(listOf(1, 2, 3, 4, 5, 6, 7, 8), result) + } + + @Test + fun `handles single page without cursor`() = runBlocking { + val response = TestResponse(listOf(1, 2, 3), null) + + val flow = PaginatedResponseToFlowAdapter.asFlow( + batchFetcher = { cursor -> + if (cursor == null) response else error("Should not be called") + } + ) + + val result = flow.toList() + assertEquals(listOf(1, 2, 3), result) + } + + @Test + fun `handles empty first page`() = runBlocking { + val response = TestResponse(emptyList(), null) + + val flow = PaginatedResponseToFlowAdapter.asFlow( + batchFetcher = { cursor -> + if (cursor == null) response else error("Should not be called") + } + ) + + val result = flow.toList() + assertEquals(emptyList(), result) + } + + @Test + fun `passes correct cursor to batch fetcher`() = runBlocking { + val cursors = mutableListOf() + + val flow = PaginatedResponseToFlowAdapter.asFlow( + batchFetcher = { cursor -> + cursors.add(cursor) + when (cursor) { + null -> TestResponse(listOf(1), "first-cursor") + "first-cursor" -> TestResponse(listOf(2), "second-cursor") + else -> TestResponse(listOf(3), null) + } + } + ) + + flow.toList() // consume all + + assertEquals(listOf(null, "first-cursor", "second-cursor"), cursors) + } + + @Test + fun `does not fetch unnecessary pages when taking limited items`() = runBlocking { + var fetchCount = 0 + val pages = mapOf( + null to TestResponse(listOf(1, 2, 3), "cursor1"), + "cursor1" to TestResponse(listOf(4, 5, 6), "cursor2"), + "cursor2" to TestResponse(listOf(7, 8, 9), null) + ) + + val flow = PaginatedResponseToFlowAdapter.asFlow( + batchFetcher = { cursor -> + fetchCount++ + pages[cursor]!! + } + ) + + // Take only 5 items - should fetch only first two pages + val result = flow.take(5).toList() + + assertEquals(listOf(1, 2, 3, 4, 5), result) + assertEquals(2, fetchCount) // Only first two pages should be fetched + } + + @Test + fun `verifies laziness - does not prefetch pages`() = runBlocking { + val fetchLog = mutableListOf() + + val flow = PaginatedResponseToFlowAdapter.asFlow( + batchFetcher = { cursor -> + when (cursor) { + null -> { + fetchLog.add("Fetching first page") + TestResponse(listOf(1, 2), "cursor1") + } + "cursor1" -> { + fetchLog.add("Fetching second page") + TestResponse(listOf(3, 4), "cursor2") + } + else -> { + fetchLog.add("Fetching third page") + TestResponse(listOf(5, 6), null) + } + } + } + ) + + // Before collecting, nothing should be fetched + assertEquals(emptyList(), fetchLog) + + // Take only first 4 items - should not fetch third page + val result = flow.take(4).toList() + + assertEquals(listOf(1, 2, 3, 4), result) + // Should have fetched only first two pages + assertEquals(listOf("Fetching first page", "Fetching second page"), fetchLog) + // Third page should never be fetched + assertFalse(fetchLog.contains("Fetching third page")) + } + + @Test + fun `handles exceptions in batch fetcher gracefully`() = runBlocking { + var resourceAcquired = false + var resourceReleased = false + + val flow = PaginatedResponseToFlowAdapter.asFlow( + batchFetcher = { cursor -> + resourceAcquired = true + try { + when (cursor) { + null -> TestResponse(listOf(1, 2), "cursor1") + "cursor1" -> throw RuntimeException("Network error") + else -> TestResponse(listOf(3, 4), null) + } + } finally { + // Always cleanup resources + if (cursor == "cursor1") { + resourceReleased = true + } + } + } + ) + + val result = mutableListOf() + try { + flow.collect { value -> + result.add(value) + } + } catch (e: RuntimeException) { + assertEquals("Network error", e.message) + } + + assertEquals(listOf(1, 2), result) // Should have collected first page items + assertTrue(resourceAcquired) + assertTrue(resourceReleased) // Resources should be cleaned up even on error + } +} diff --git a/acp/src/jvmTest/kotlin/com/agentclientprotocol/util/SequenceToPaginatedResponseAdapterTest.kt b/acp/src/jvmTest/kotlin/com/agentclientprotocol/util/SequenceToPaginatedResponseAdapterTest.kt new file mode 100644 index 0000000..bde1724 --- /dev/null +++ b/acp/src/jvmTest/kotlin/com/agentclientprotocol/util/SequenceToPaginatedResponseAdapterTest.kt @@ -0,0 +1,464 @@ +package com.agentclientprotocol.util + +import com.agentclientprotocol.annotations.UnstableApi +import com.agentclientprotocol.model.AcpPaginatedRequest +import com.agentclientprotocol.model.AcpPaginatedResponse +import com.agentclientprotocol.protocol.JsonRpcException +import com.agentclientprotocol.rpc.JsonRpcErrorCode +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking +import kotlinx.serialization.json.JsonElement +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertFailsWith +import kotlin.test.assertNotNull +import kotlin.test.assertNull +import kotlin.time.Duration.Companion.milliseconds +import kotlin.time.Duration.Companion.seconds + +@OptIn(UnstableApi::class) +class SequenceToPaginatedResponseAdapterTest { + + private data class TestRequest( + override val cursor: String? = null, override val _meta: JsonElement? = null + ) : AcpPaginatedRequest + + private data class TestResponse( + val items: List, + override val nextCursor: String?, override val _meta: JsonElement? = null + ) : AcpPaginatedResponse { + override fun getItemsBatch(): List = items + } + + @Test + fun `returns first batch without cursor`(): Unit = runBlocking { + val storage = SequenceToPaginatedResponseAdapter(batchSize = 3) + val sequence = sequenceOf(1, 2, 3, 4, 5) + + val result = storage.next( + params = TestRequest(), + sequenceFactory = { sequence }, + resultFactory = { _, batch, cursor -> TestResponse(batch, cursor) } + ) + + assertEquals(listOf(1, 2, 3), result.items) + assertNotNull(result.nextCursor) + } + + @Test + fun `returns next batch with valid cursor`(): Unit = runBlocking { + val storage = SequenceToPaginatedResponseAdapter(batchSize = 3) + val sequence = sequenceOf(1, 2, 3, 4, 5) + + val firstResult = storage.next( + params = TestRequest(), + sequenceFactory = { sequence }, + resultFactory = { _, batch, cursor -> TestResponse(batch, cursor) } + ) + + val cursor = firstResult.nextCursor + assertNotNull(cursor) + + val secondResult = storage.next( + params = TestRequest(cursor = cursor), + sequenceFactory = { error("Should not be called") }, + resultFactory = { _, batch, cursor -> TestResponse(batch, cursor) } + ) + + assertEquals(listOf(4, 5), secondResult.items) + assertNull(secondResult.nextCursor) + } + + @Test + fun `returns null cursor when sequence exhausted`(): Unit = runBlocking { + val storage = SequenceToPaginatedResponseAdapter(batchSize = 5) + val sequence = sequenceOf(1, 2, 3) + + val result = storage.next( + params = TestRequest(), + sequenceFactory = { sequence }, + resultFactory = { _, batch, cursor -> TestResponse(batch, cursor) } + ) + + assertEquals(listOf(1, 2, 3), result.items) + assertNull(result.nextCursor) + } + + @Test + fun `returns empty batch for empty sequence`(): Unit = runBlocking { + val storage = SequenceToPaginatedResponseAdapter(batchSize = 3) + val sequence = emptySequence() + + val result = storage.next( + params = TestRequest(), + sequenceFactory = { sequence }, + resultFactory = { _, batch, cursor -> TestResponse(batch, cursor) } + ) + + assertEquals(emptyList(), result.items) + assertNull(result.nextCursor) + } + + @Test + fun `throws exception for invalid cursor`(): Unit = runBlocking { + val storage = SequenceToPaginatedResponseAdapter(batchSize = 3) + + val exception = assertFailsWith { + storage.next( + params = TestRequest(cursor = "invalid-cursor"), + sequenceFactory = { error("Should not be called") }, + resultFactory = { _, batch, cursor -> TestResponse(batch, cursor) } + ) + } + + assertEquals(JsonRpcErrorCode.INVALID_PARAMS.code, exception.code) + } + + @Test + fun `cursor can only be used once`(): Unit = runBlocking { + val storage = SequenceToPaginatedResponseAdapter(batchSize = 2) + val sequence = sequenceOf(1, 2, 3, 4, 5, 6) + + val firstResult = storage.next( + params = TestRequest(), + sequenceFactory = { sequence }, + resultFactory = { _, batch, cursor -> TestResponse(batch, cursor) } + ) + + val cursor = firstResult.nextCursor + assertNotNull(cursor) + + // Use cursor once + storage.next( + params = TestRequest(cursor = cursor), + sequenceFactory = { error("Should not be called") }, + resultFactory = { _, batch, cursor -> TestResponse(batch, cursor) } + ) + + // Try to use the same cursor again - should fail + val exception = assertFailsWith { + storage.next( + params = TestRequest(cursor = cursor), + sequenceFactory = { error("Should not be called") }, + resultFactory = { _, batch, cursor -> TestResponse(batch, cursor) } + ) + } + + assertEquals(JsonRpcErrorCode.INVALID_PARAMS.code, exception.code) + } + + @Test + fun `iterates through entire sequence in batches`(): Unit = runBlocking { + val storage = SequenceToPaginatedResponseAdapter(batchSize = 3) + val sequence = sequenceOf(1, 2, 3, 4, 5, 6, 7, 8) + val allItems = mutableListOf() + + var result = storage.next( + params = TestRequest(), + sequenceFactory = { sequence }, + resultFactory = { _, batch, cursor -> TestResponse(batch, cursor) } + ) + allItems.addAll(result.items) + + while (result.nextCursor != null) { + result = storage.next( + params = TestRequest(cursor = result.nextCursor), + sequenceFactory = { error("Should not be called") }, + resultFactory = { _, batch, cursor -> TestResponse(batch, cursor) } + ) + allItems.addAll(result.items) + } + + assertEquals(listOf(1, 2, 3, 4, 5, 6, 7, 8), allItems) + } + + @Test + fun `uses default batch size of 10`(): Unit = runBlocking { + val storage = SequenceToPaginatedResponseAdapter() + val sequence = (1..15).asSequence() + + val result = storage.next( + params = TestRequest(), + sequenceFactory = { sequence }, + resultFactory = { _, batch, cursor -> TestResponse(batch, cursor) } + ) + + assertEquals(10, result.items.size) + assertEquals((1..10).toList(), result.items) + assertNotNull(result.nextCursor) + } + + @Test + fun `passes params to result factory`(): Unit = runBlocking { + val storage = SequenceToPaginatedResponseAdapter(batchSize = 3) + val sequence = sequenceOf(1, 2, 3) + val originalParams = TestRequest(cursor = null) + var receivedParams: TestRequest? = null + + storage.next( + params = originalParams, + sequenceFactory = { sequence }, + resultFactory = { params, batch, cursor -> + receivedParams = params + TestResponse(batch, cursor) + } + ) + + assertEquals(originalParams, receivedParams) + } + + @Test + fun `iterator is removed after timeout`(): Unit = runBlocking { + val storage = SequenceToPaginatedResponseAdapter( + batchSize = 3, + orphanedIteratorsEvictionTimeout = 500.milliseconds + ) + val sequence = sequenceOf(1, 2, 3, 4, 5, 6, 7, 8) + + val firstResult = storage.next( + params = TestRequest(), + sequenceFactory = { sequence }, + resultFactory = { _, batch, cursor -> TestResponse(batch, cursor) } + ) + + val cursor = firstResult.nextCursor + assertNotNull(cursor) + + // Wait for timeout to expire + delay(700.milliseconds) + + // Try to use the expired cursor - should fail + val exception = assertFailsWith { + storage.next( + params = TestRequest(cursor = cursor), + sequenceFactory = { error("Should not be called") }, + resultFactory = { _, batch, cursor -> TestResponse(batch, cursor) } + ) + } + + assertEquals(JsonRpcErrorCode.INVALID_PARAMS.code, exception.code) + } + + @Test + fun `each cursor has its own timeout`(): Unit = runBlocking { + val storage = SequenceToPaginatedResponseAdapter( + batchSize = 2, + orphanedIteratorsEvictionTimeout = 500.milliseconds + ) + val sequence = sequenceOf(1, 2, 3, 4, 5, 6) + + val firstResult = storage.next( + params = TestRequest(), + sequenceFactory = { sequence }, + resultFactory = { _, batch, cursor -> TestResponse(batch, cursor) } + ) + + val firstCursor = firstResult.nextCursor + assertNotNull(firstCursor) + + // Use the first cursor immediately + val secondResult = storage.next( + params = TestRequest(cursor = firstCursor), + sequenceFactory = { error("Should not be called") }, + resultFactory = { _, batch, cursor -> TestResponse(batch, cursor) } + ) + + assertEquals(listOf(3, 4), secondResult.items) + val secondCursor = secondResult.nextCursor + assertNotNull(secondCursor) + + // The second cursor has its own timeout, independent of the first + // Wait less than the timeout + delay(300.milliseconds) + + // The second cursor should still be valid + val thirdResult = storage.next( + params = TestRequest(cursor = secondCursor), + sequenceFactory = { error("Should not be called") }, + resultFactory = { _, batch, cursor -> TestResponse(batch, cursor) } + ) + + assertEquals(listOf(5, 6), thirdResult.items) + assertNull(thirdResult.nextCursor) + } + + @Test + fun `multiple iterators can have independent timeouts`(): Unit = runBlocking { + val storage = SequenceToPaginatedResponseAdapter( + batchSize = 2, + orphanedIteratorsEvictionTimeout = 600.milliseconds + ) + + // Create first iterator + val sequence1 = sequenceOf(1, 2, 3, 4) + val result1 = storage.next( + params = TestRequest(), + sequenceFactory = { sequence1 }, + resultFactory = { _, batch, cursor -> TestResponse(batch, cursor) } + ) + val cursor1 = result1.nextCursor + assertNotNull(cursor1) + + // Wait a bit + delay(200.milliseconds) + + // Create second iterator + val sequence2 = sequenceOf(10, 20, 30, 40) + val result2 = storage.next( + params = TestRequest(), + sequenceFactory = { sequence2 }, + resultFactory = { _, batch, cursor -> TestResponse(batch, cursor) } + ) + val cursor2 = result2.nextCursor + assertNotNull(cursor2) + + // Wait for first cursor to expire but not second + delay(500.milliseconds) + + // First cursor should be expired + assertFailsWith { + storage.next( + params = TestRequest(cursor = cursor1), + sequenceFactory = { error("Should not be called") }, + resultFactory = { _, batch, cursor -> TestResponse(batch, cursor) } + ) + } + + // Second cursor should still work + val result2Next = storage.next( + params = TestRequest(cursor = cursor2), + sequenceFactory = { error("Should not be called") }, + resultFactory = { _, batch, cursor -> TestResponse(batch, cursor) } + ) + assertEquals(listOf(30, 40), result2Next.items) + } + + @Test + fun `concurrent access to same cursor fails for second request`(): Unit = runBlocking { + val storage = SequenceToPaginatedResponseAdapter( + batchSize = 2, + orphanedIteratorsEvictionTimeout = 2.seconds + ) + val sequence = sequenceOf(1, 2, 3, 4, 5, 6) + + val firstResult = storage.next( + params = TestRequest(), + sequenceFactory = { sequence }, + resultFactory = { _, batch, cursor -> TestResponse(batch, cursor) } + ) + + val cursor = firstResult.nextCursor + assertNotNull(cursor) + + // Launch two concurrent requests with the same cursor + val job1 = launch { + delay(20.milliseconds) // Small delay to ensure consistent ordering + storage.next( + params = TestRequest(cursor = cursor), + sequenceFactory = { error("Should not be called") }, + resultFactory = { _, batch, cursor -> TestResponse(batch, cursor) } + ) + } + + val job2 = launch { + delay(50.milliseconds) // Slightly larger delay + assertFailsWith { + storage.next( + params = TestRequest(cursor = cursor), + sequenceFactory = { error("Should not be called") }, + resultFactory = { _, batch, cursor -> TestResponse(batch, cursor) } + ) + } + } + + job1.join() + job2.join() + } + + @Test + fun `very short timeout should work`(): Unit = runBlocking { + // Test with very short timeout + val storage = SequenceToPaginatedResponseAdapter( + batchSize = 2, + orphanedIteratorsEvictionTimeout = 1.milliseconds + ) + val sequence = sequenceOf(1, 2, 3, 4) + + val result = storage.next( + params = TestRequest(), + sequenceFactory = { sequence }, + resultFactory = { _, batch, cursor -> TestResponse(batch, cursor) } + ) + + val cursor = result.nextCursor + assertNotNull(cursor) + + // Even a small delay should trigger timeout + delay(50.milliseconds) + + assertFailsWith { + storage.next( + params = TestRequest(cursor = cursor), + sequenceFactory = { error("Should not be called") }, + resultFactory = { _, batch, cursor -> TestResponse(batch, cursor) } + ) + } + } + + @Test + fun `zero or negative timeout should throw exception`() { + // Zero timeout should be rejected + assertFailsWith { + SequenceToPaginatedResponseAdapter( + batchSize = 2, + orphanedIteratorsEvictionTimeout = 0.milliseconds + ) + } + + // Negative timeout should be rejected + assertFailsWith { + SequenceToPaginatedResponseAdapter( + batchSize = 2, + orphanedIteratorsEvictionTimeout = (-100).milliseconds + ) + } + } + + @Test + fun `large number of iterators with timeouts`(): Unit = runBlocking { + val storage = SequenceToPaginatedResponseAdapter( + batchSize = 2, + orphanedIteratorsEvictionTimeout = 300.milliseconds + ) + + val cursors = mutableListOf() + + // Create many iterators + repeat(100) { i -> + val sequence = sequenceOf(i * 10, i * 10 + 1, i * 10 + 2, i * 10 + 3) + val result = storage.next( + params = TestRequest(), + sequenceFactory = { sequence }, + resultFactory = { _, batch, cursor -> TestResponse(batch, cursor) } + ) + result.nextCursor?.let { cursors.add(it) } + } + + assertEquals(100, cursors.size) + + // Wait for all to expire + delay(500.milliseconds) + + // All cursors should be invalid now + cursors.forEach { cursor -> + assertFailsWith { + storage.next( + params = TestRequest(cursor = cursor), + sequenceFactory = { error("Should not be called") }, + resultFactory = { _, batch, cursor -> TestResponse(batch, cursor) } + ) + } + } + } +} diff --git a/samples/kotlin-acp-client-sample/src/main/kotlin/com/agentclientprotocol/samples/util.kt b/samples/kotlin-acp-client-sample/src/main/kotlin/com/agentclientprotocol/samples/util.kt index 7fc3e2e..f9cd3af 100644 --- a/samples/kotlin-acp-client-sample/src/main/kotlin/com/agentclientprotocol/samples/util.kt +++ b/samples/kotlin-acp-client-sample/src/main/kotlin/com/agentclientprotocol/samples/util.kt @@ -40,6 +40,13 @@ fun SessionUpdate.render() { println("User: ${this.content.render()}") } + is SessionUpdate.ConfigOptionUpdate -> { + println("Configuration options updated") + } + + is SessionUpdate.SessionInfoUpdate -> { + println("Session info updated: title=${this.title}, updatedAt=${this.updatedAt}") + } } }