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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,37 @@ abstract class FeaturesTest(protocolDriver: ProtocolDriver) : ProtocolDriver by



@Test
fun `authenticate returns null when agent returns null`() = testWithProtocols { clientProtocol, agentProtocol ->
val client = Client(protocol = clientProtocol)

val agentSupport = object : AgentSupport {
override suspend fun initialize(clientInfo: ClientInfo): AgentInfo {
return AgentInfo(clientInfo.protocolVersion)
}

override suspend fun authenticate(methodId: AuthMethodId, _meta: JsonElement?): AuthenticateResponse? {
// Return null to simulate {"jsonrpc":"2.0","id":3,"result":null} response
return null
}

override suspend fun createSession(sessionParameters: SessionCreationParameters): AgentSession {
return TestAgentSession()
}

override suspend fun loadSession(sessionId: SessionId, sessionParameters: SessionCreationParameters): AgentSession {
return TestAgentSession()
}
}
Agent(agentProtocol, agentSupport)

client.initialize(ClientInfo())

// This should correctly handle the null response without throwing an exception
val result = client.authenticate(AuthMethodId("test-auth"))
assertNull(result, "authenticate should return null when agent returns null")
}

// @Test
// fun `call agent extension from client`(): TestResult = testWithProtocols { clientProtocol, agentProtocol ->
//
Expand Down
24 changes: 17 additions & 7 deletions acp-model/api/acp-model.api
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ public class com/agentclientprotocol/model/AcpMethod$AcpRequestResponseMethod :
public final fun getResponseSerializer ()Lkotlinx/serialization/KSerializer;
}

public class com/agentclientprotocol/model/AcpMethod$AcpRequestResponseNullableMethod : com/agentclientprotocol/model/AcpMethod {
public fun <init> (Ljava/lang/String;Lkotlinx/serialization/KSerializer;Lkotlinx/serialization/KSerializer;)V
public final fun getRequestSerializer ()Lkotlinx/serialization/KSerializer;
public final fun getResponseSerializer ()Lkotlinx/serialization/KSerializer;
}

public class com/agentclientprotocol/model/AcpMethod$AcpSessionNotificationMethod : com/agentclientprotocol/model/AcpMethod$AcpNotificationMethod {
public fun <init> (Ljava/lang/String;Lkotlinx/serialization/KSerializer;)V
}
Expand All @@ -38,11 +44,15 @@ public class com/agentclientprotocol/model/AcpMethod$AcpSessionRequestResponseMe
public fun <init> (Ljava/lang/String;Lkotlinx/serialization/KSerializer;Lkotlinx/serialization/KSerializer;)V
}

public class com/agentclientprotocol/model/AcpMethod$AcpSessionRequestResponseNullableMethod : com/agentclientprotocol/model/AcpMethod$AcpRequestResponseNullableMethod {
public fun <init> (Ljava/lang/String;Lkotlinx/serialization/KSerializer;Lkotlinx/serialization/KSerializer;)V
}

public final class com/agentclientprotocol/model/AcpMethod$AgentMethods {
public static final field INSTANCE Lcom/agentclientprotocol/model/AcpMethod$AgentMethods;
}

public final class com/agentclientprotocol/model/AcpMethod$AgentMethods$Authenticate : com/agentclientprotocol/model/AcpMethod$AcpRequestResponseMethod {
public final class com/agentclientprotocol/model/AcpMethod$AgentMethods$Authenticate : com/agentclientprotocol/model/AcpMethod$AcpRequestResponseNullableMethod {
public static final field INSTANCE Lcom/agentclientprotocol/model/AcpMethod$AgentMethods$Authenticate;
}

Expand All @@ -66,11 +76,11 @@ public final class com/agentclientprotocol/model/AcpMethod$AgentMethods$SessionP
public static final field INSTANCE Lcom/agentclientprotocol/model/AcpMethod$AgentMethods$SessionPrompt;
}

public final class com/agentclientprotocol/model/AcpMethod$AgentMethods$SessionSetMode : com/agentclientprotocol/model/AcpMethod$AcpSessionRequestResponseMethod {
public final class com/agentclientprotocol/model/AcpMethod$AgentMethods$SessionSetMode : com/agentclientprotocol/model/AcpMethod$AcpSessionRequestResponseNullableMethod {
public static final field INSTANCE Lcom/agentclientprotocol/model/AcpMethod$AgentMethods$SessionSetMode;
}

public final class com/agentclientprotocol/model/AcpMethod$AgentMethods$SessionSetModel : com/agentclientprotocol/model/AcpMethod$AcpSessionRequestResponseMethod {
public final class com/agentclientprotocol/model/AcpMethod$AgentMethods$SessionSetModel : com/agentclientprotocol/model/AcpMethod$AcpSessionRequestResponseNullableMethod {
public static final field INSTANCE Lcom/agentclientprotocol/model/AcpMethod$AgentMethods$SessionSetModel;
}

Expand All @@ -82,7 +92,7 @@ public final class com/agentclientprotocol/model/AcpMethod$ClientMethods$FsReadT
public static final field INSTANCE Lcom/agentclientprotocol/model/AcpMethod$ClientMethods$FsReadTextFile;
}

public final class com/agentclientprotocol/model/AcpMethod$ClientMethods$FsWriteTextFile : com/agentclientprotocol/model/AcpMethod$AcpSessionRequestResponseMethod {
public final class com/agentclientprotocol/model/AcpMethod$ClientMethods$FsWriteTextFile : com/agentclientprotocol/model/AcpMethod$AcpSessionRequestResponseNullableMethod {
public static final field INSTANCE Lcom/agentclientprotocol/model/AcpMethod$ClientMethods$FsWriteTextFile;
}

Expand All @@ -98,19 +108,19 @@ public final class com/agentclientprotocol/model/AcpMethod$ClientMethods$Termina
public static final field INSTANCE Lcom/agentclientprotocol/model/AcpMethod$ClientMethods$TerminalCreate;
}

public final class com/agentclientprotocol/model/AcpMethod$ClientMethods$TerminalKill : com/agentclientprotocol/model/AcpMethod$AcpSessionRequestResponseMethod {
public final class com/agentclientprotocol/model/AcpMethod$ClientMethods$TerminalKill : com/agentclientprotocol/model/AcpMethod$AcpSessionRequestResponseNullableMethod {
public static final field INSTANCE Lcom/agentclientprotocol/model/AcpMethod$ClientMethods$TerminalKill;
}

public final class com/agentclientprotocol/model/AcpMethod$ClientMethods$TerminalOutput : com/agentclientprotocol/model/AcpMethod$AcpSessionRequestResponseMethod {
public static final field INSTANCE Lcom/agentclientprotocol/model/AcpMethod$ClientMethods$TerminalOutput;
}

public final class com/agentclientprotocol/model/AcpMethod$ClientMethods$TerminalRelease : com/agentclientprotocol/model/AcpMethod$AcpSessionRequestResponseMethod {
public final class com/agentclientprotocol/model/AcpMethod$ClientMethods$TerminalRelease : com/agentclientprotocol/model/AcpMethod$AcpSessionRequestResponseNullableMethod {
public static final field INSTANCE Lcom/agentclientprotocol/model/AcpMethod$ClientMethods$TerminalRelease;
}

public final class com/agentclientprotocol/model/AcpMethod$ClientMethods$TerminalWaitForExit : com/agentclientprotocol/model/AcpMethod$AcpSessionRequestResponseMethod {
public final class com/agentclientprotocol/model/AcpMethod$ClientMethods$TerminalWaitForExit : com/agentclientprotocol/model/AcpMethod$AcpSessionRequestResponseNullableMethod {
public static final field INSTANCE Lcom/agentclientprotocol/model/AcpMethod$ClientMethods$TerminalWaitForExit;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,24 @@ public open class AcpMethod(public val methodName: MethodName) {
public val responseSerializer: KSerializer<TResponse>
) : AcpMethod(MethodName(method))

public open class AcpRequestResponseNullableMethod<TRequest: AcpRequest, TResponse: AcpResponse>(
method: String,
public val requestSerializer: KSerializer<TRequest>,
public val responseSerializer: KSerializer<TResponse>
) : AcpMethod(MethodName(method))

public open class AcpSessionRequestResponseMethod<TRequest, TResponse: AcpResponse>(method: String,
requestSerializer: KSerializer<TRequest>,
responseSerializer: KSerializer<TResponse>
) : AcpRequestResponseMethod<TRequest, TResponse>(method, requestSerializer, responseSerializer)
where TRequest : AcpRequest, TRequest : AcpWithSessionId

public open class AcpSessionRequestResponseNullableMethod<TRequest, TResponse: AcpResponse>(method: String,
requestSerializer: KSerializer<TRequest>,
responseSerializer: KSerializer<TResponse>
) : AcpRequestResponseNullableMethod<TRequest, TResponse>(method, requestSerializer, responseSerializer)
where TRequest : AcpRequest, TRequest : AcpWithSessionId

public open class AcpNotificationMethod<TNotification: AcpNotification>(
method: String,
public val serializer: KSerializer<TNotification>,
Expand All @@ -43,16 +55,16 @@ public open class AcpMethod(public val methodName: MethodName) {
public object AgentMethods {
// Agent-side operations (methods that agents can call on clients)
public object Initialize : AcpRequestResponseMethod<InitializeRequest, InitializeResponse>("initialize", InitializeRequest.serializer(), InitializeResponse.serializer())
public object Authenticate : AcpRequestResponseMethod<AuthenticateRequest, AuthenticateResponse>("authenticate", AuthenticateRequest.serializer(), AuthenticateResponse.serializer())
public object Authenticate : AcpRequestResponseNullableMethod<AuthenticateRequest, AuthenticateResponse>("authenticate", AuthenticateRequest.serializer(), AuthenticateResponse.serializer())
public object SessionNew : AcpRequestResponseMethod<NewSessionRequest, NewSessionResponse>("session/new", NewSessionRequest.serializer(), NewSessionResponse.serializer())
public object SessionLoad : AcpRequestResponseMethod<LoadSessionRequest, LoadSessionResponse>("session/load", LoadSessionRequest.serializer(), LoadSessionResponse.serializer())

// session specific
public object SessionPrompt : AcpSessionRequestResponseMethod<PromptRequest, PromptResponse>("session/prompt", PromptRequest.serializer(), PromptResponse.serializer())
public object SessionCancel : AcpSessionNotificationMethod<CancelNotification>("session/cancel", CancelNotification.serializer())
public object SessionSetMode : AcpSessionRequestResponseMethod<SetSessionModeRequest, SetSessionModeResponse>("session/set_mode", SetSessionModeRequest.serializer(), SetSessionModeResponse.serializer())
public object SessionSetMode : AcpSessionRequestResponseNullableMethod<SetSessionModeRequest, SetSessionModeResponse>("session/set_mode", SetSessionModeRequest.serializer(), SetSessionModeResponse.serializer())
@UnstableApi
public object SessionSetModel : AcpSessionRequestResponseMethod<SetSessionModelRequest, SetSessionModelResponse>("session/set_model", SetSessionModelRequest.serializer(), SetSessionModelResponse.serializer())
public object SessionSetModel : AcpSessionRequestResponseNullableMethod<SetSessionModelRequest, SetSessionModelResponse>("session/set_model", SetSessionModelRequest.serializer(), SetSessionModelResponse.serializer())
}

public object ClientMethods {
Expand All @@ -62,12 +74,12 @@ public open class AcpMethod(public val methodName: MethodName) {

// extensions
public object FsReadTextFile : AcpSessionRequestResponseMethod<ReadTextFileRequest, ReadTextFileResponse>("fs/read_text_file", ReadTextFileRequest.serializer(), ReadTextFileResponse.serializer())
public object FsWriteTextFile : AcpSessionRequestResponseMethod<WriteTextFileRequest, WriteTextFileResponse>("fs/write_text_file", WriteTextFileRequest.serializer(), WriteTextFileResponse.serializer())
public object FsWriteTextFile : AcpSessionRequestResponseNullableMethod<WriteTextFileRequest, WriteTextFileResponse>("fs/write_text_file", WriteTextFileRequest.serializer(), WriteTextFileResponse.serializer())
public object TerminalCreate : AcpSessionRequestResponseMethod<CreateTerminalRequest, CreateTerminalResponse>("terminal/create", CreateTerminalRequest.serializer(), CreateTerminalResponse.serializer())
public object TerminalOutput : AcpSessionRequestResponseMethod<TerminalOutputRequest, TerminalOutputResponse>("terminal/output", TerminalOutputRequest.serializer(), TerminalOutputResponse.serializer())
public object TerminalRelease : AcpSessionRequestResponseMethod<ReleaseTerminalRequest, ReleaseTerminalResponse>("terminal/release", ReleaseTerminalRequest.serializer(), ReleaseTerminalResponse.serializer())
public object TerminalWaitForExit : AcpSessionRequestResponseMethod<WaitForTerminalExitRequest, WaitForTerminalExitResponse>("terminal/wait_for_exit", WaitForTerminalExitRequest.serializer(), WaitForTerminalExitResponse.serializer())
public object TerminalKill : AcpSessionRequestResponseMethod<KillTerminalCommandRequest, KillTerminalCommandResponse>("terminal/kill", KillTerminalCommandRequest.serializer(), KillTerminalCommandResponse.serializer())
public object TerminalRelease : AcpSessionRequestResponseNullableMethod<ReleaseTerminalRequest, ReleaseTerminalResponse>("terminal/release", ReleaseTerminalRequest.serializer(), ReleaseTerminalResponse.serializer())
public object TerminalWaitForExit : AcpSessionRequestResponseNullableMethod<WaitForTerminalExitRequest, WaitForTerminalExitResponse>("terminal/wait_for_exit", WaitForTerminalExitRequest.serializer(), WaitForTerminalExitResponse.serializer())
public object TerminalKill : AcpSessionRequestResponseNullableMethod<KillTerminalCommandRequest, KillTerminalCommandResponse>("terminal/kill", KillTerminalCommandRequest.serializer(), KillTerminalCommandResponse.serializer())
}


Expand Down
Loading
Loading