protected fun parseJSONRPCRequest()

in a2a/a2a-transport/a2a-transport-core-jsonrpc/src/commonMain/kotlin/ai/koog/a2a/transport/jsonrpc/JSONRPCServerTransport.kt [50:103]


    protected fun parseJSONRPCRequest(raw: String): Pair<JSONRPCRequest, A2AMethod> {
        val jsonBody = try {
            JSONRPCJson.decodeFromString<JsonObject>(raw)
        } catch (e: SerializationException) {
            throw A2AParseException("Cannot parse request body to JSON:\n${e.message}")
        }

        // According to A2A TCK, need to parse id early to reply with provided id in error messages
        val id = jsonBody["id"]?.let {
            try {
                JSONRPCJson.decodeFromJsonElement<RequestId>(it)
            } catch (e: SerializationException) {
                throw A2AInvalidRequestException("Cannot parse request id to JSON-RPC id:\n${e.message}")
            }
        }

        val a2aMethod = (jsonBody["method"] as? JsonPrimitive)
            ?.content
            ?.let {
                A2AMethod.entries.find { m -> m.value == it }
                    ?: throw A2AMethodNotFoundException("Method not found: $it", id)
            }
            ?: throw A2AInvalidRequestException("No method parameter", id)

        val params = jsonBody["params"]
            ?.let {
                try {
                    JSONRPCJson
                        .decodeFromJsonElement<JsonObject>(it)
                        .also {
                            // According to A2A TCK, empty parameter names are not allowed
                            if (it.keys.any { it.isEmpty() }) {
                                throw A2AInvalidParamsException("Empty parameter names are not allowed", id)
                            }
                        }
                } catch (e: SerializationException) {
                    throw A2AInvalidParamsException("Cannot parse request params to JSON:\n${e.message}", id)
                }
            }

        val jsonrpc = jsonBody["jsonrpc"]
            ?.jsonPrimitive?.content
            ?.takeIf { it == JSONRPC_VERSION }
            ?: throw A2AInvalidRequestException("Unsupported JSON-RPC version", id)

        val jsonrpcBody = JSONRPCRequest(
            id = id ?: throw A2AInvalidRequestException("No id parameter"),
            method = a2aMethod.value,
            params = params ?: JsonNull,
            jsonrpc = jsonrpc,
        )

        return jsonrpcBody to a2aMethod
    }