diff --git a/acp/api/acp.api b/acp/api/acp.api index 9c0539d..ac13e13 100644 --- a/acp/api/acp.api +++ b/acp/api/acp.api @@ -330,7 +330,3 @@ 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/CoroutinesUtilKt { - public static final fun catching (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - diff --git a/acp/src/commonMain/kotlin/com/agentclientprotocol/protocol/Protocol.kt b/acp/src/commonMain/kotlin/com/agentclientprotocol/protocol/Protocol.kt index 333acf6..b8be121 100644 --- a/acp/src/commonMain/kotlin/com/agentclientprotocol/protocol/Protocol.kt +++ b/acp/src/commonMain/kotlin/com/agentclientprotocol/protocol/Protocol.kt @@ -7,7 +7,7 @@ import com.agentclientprotocol.model.CancelRequestNotification import com.agentclientprotocol.rpc.* import com.agentclientprotocol.transport.Transport import com.agentclientprotocol.transport.asMessageChannel -import com.agentclientprotocol.util.catching +import com.agentclientprotocol.util.checkCancelled import io.github.oshai.kotlinlogging.KotlinLogging import kotlinx.atomicfu.* import kotlinx.collections.immutable.PersistentMap @@ -164,13 +164,11 @@ public class Protocol( // Start processing incoming messages scope.launch(CoroutineName("${Protocol::class.simpleName!!}.read-messages")) { - catching { + runCatching { for (message in transport.asMessageChannel()) { - catching { handleIncomingMessage(message) }.onFailure { logger.error(it) { - "Error processing incoming message: $message" } - } + handleIncomingMessage(message) } - }.onFailure { + }.checkCancelled().onFailure { logger.error(it) { "Error processing incoming messages" } } } @@ -365,8 +363,8 @@ public class Protocol( handleResponse(message) } } - }.onFailure { - logger.error(it) { "Failed to parse message: $message" } + }.checkCancelled().onFailure { + logger.error(it) { "Exception while processing incoming message: $message" } } } @@ -427,8 +425,12 @@ public class Protocol( if (handler != null) { runCatching { handler(notification) - }.onFailure { - logger.error(it) { "Error handling notification ${notification.method}" } + }.onFailure { t -> + if (t is CancellationException) { + logger.trace(t) { "Notification handler for '${notification.method}' cancelled" } + } else { + logger.error(t) { "Error handling notification ${notification.method}" } + } } } else { logger.debug { "No handler for notification: ${notification.method}" } diff --git a/acp/src/commonMain/kotlin/com/agentclientprotocol/transport/StdioTransport.kt b/acp/src/commonMain/kotlin/com/agentclientprotocol/transport/StdioTransport.kt index 67afd44..5ed59df 100644 --- a/acp/src/commonMain/kotlin/com/agentclientprotocol/transport/StdioTransport.kt +++ b/acp/src/commonMain/kotlin/com/agentclientprotocol/transport/StdioTransport.kt @@ -4,6 +4,7 @@ import com.agentclientprotocol.rpc.ACPJson import com.agentclientprotocol.rpc.JsonRpcMessage import com.agentclientprotocol.rpc.decodeJsonRpcMessage import com.agentclientprotocol.transport.Transport.State +import com.agentclientprotocol.util.checkCancelled import io.github.oshai.kotlinlogging.KotlinLogging import kotlinx.coroutines.* import kotlinx.coroutines.channels.Channel diff --git a/acp/src/commonMain/kotlin/com/agentclientprotocol/util/CoroutinesUtil.kt b/acp/src/commonMain/kotlin/com/agentclientprotocol/util/CoroutinesUtil.kt index 7f740bd..22e83ed 100644 --- a/acp/src/commonMain/kotlin/com/agentclientprotocol/util/CoroutinesUtil.kt +++ b/acp/src/commonMain/kotlin/com/agentclientprotocol/util/CoroutinesUtil.kt @@ -2,12 +2,11 @@ package com.agentclientprotocol.util import kotlin.coroutines.cancellation.CancellationException -/** Use instead of [runCatching] for KT-55480 fix. */ -public suspend fun catching(body: suspend () -> R): Result = - try { - Result.success(body()) - } catch (c: CancellationException) { - throw c - } catch (t: Throwable) { - Result.failure(t) - } \ No newline at end of file +/** + * Rethrows [CancellationException] if the [Result] execution was cancelled. Use on [runCatching] to avoid swallowing of [CancellationException] + */ +internal fun Result.checkCancelled(): Result { + val throwable = exceptionOrNull() + if (throwable is CancellationException) throw throwable + return this +} \ No newline at end of file