How do I create a composite aggregate in c#

I have been trying for days now to duplicate the following query in c#

POST /traces-apm*/_async_search
{
  "size": 0,
  "query": {
    "bool": {
      "must": [
        {
          "wildcard": {
            "url.original": "*.js"
          }
        },
        {
          "range": {
            "@timestamp": {
              "gte": "2024-03-11T00:00:00.000Z",
              "lte": "2024-03-11T23:59:59.999Z"
            }
          }
        }
      ]
    }
  },
  "aggs": {
    "unique_combinations": {
      "composite": {
        "sources": [
          {
            "site": {
              "terms": {
                "field": "labels.site"
              }
            }
          },
          {
            "url": {
              "terms": {
                "field": "url.original"
              }
            }
          }
        ],
        "size": 2 
      }
    }
  }
}

Nothing I have done seems to even come close. I'm pretty sure I want a composite aggregate but since there is very little documentation I'm playing a big guessing game. So far I have:

private static SearchRequestDescriptor<dynamic> GetSearchRequestDescriptorAggregateTransactions(string indexes,
    int size,
    string scrollTimeout, DateTime utcStartDate, DateTime utcEndDate)
{
    var searchRequestDescriptor = new SearchRequestDescriptor<dynamic>();
    searchRequestDescriptor.Index(indexes);
    searchRequestDescriptor.Size(size);
    searchRequestDescriptor.Scroll(scrollTimeout);
    searchRequestDescriptor.Query(q => q
        .Bool(b => b
            .Must(m => m
                .Range(r => r
                    .DateRange(d => d
                        .Field("@timestamp")
                        .Gt(utcStartDate)
                        .Lte(utcEndDate)
                    )
                )
                .Wildcard(w => w
                    .Field("url.original")
                    .Value("*.js"))
            )
        )
    );

    ICollection<IDictionary<string, CompositeAggregationSource>> sources =
        new List<IDictionary<string, CompositeAggregationSource>>();

    var siteSource = new CompositeAggregationSource
    {
        Terms = new TermsAggregation("labels.site")
    };

    var urlSource = new CompositeAggregationSource
    {
        Terms = new TermsAggregation("url.original")
    };

    sources.Add(new Dictionary<string, CompositeAggregationSource>
    {
        { "site", siteSource }
    });

    sources.Add(new Dictionary<string, CompositeAggregationSource>
    {
        { "url", urlSource }
    });

    var compAggDesc = new CompositeAggregationDescriptor<dynamic>();
    compAggDesc.Sources(sources);


    searchRequestDescriptor.Aggregations(a => a
        .Composite("composite", d => d.Sources(sources
            ).Size(2)
        )
    );

    searchRequestDescriptor.Aggregations(a => a
        .Composite("composite", d => d
            .Aggregations(aa => aa.Terms("unique", t => t
                .Field("labels.site")
                .Field("url.original")
                .Size(2)
                )
            )
            .Sources(sources)
        )
    );

    searchRequestDescriptor.Sort(s => s
        .Field("@timestamp")
    );

    return searchRequestDescriptor;
}

But this just produces the following error:
[composite] failed to parse field [sources]" CausedBy: "Type: x_content_parse_exception Reason: "[9:17] [terms] unknown field [terms]

As far as I can see I did not pass any filed named "terms"
Anyone know how to use the elastic.clients.Elasticsearch library?

So it looks like the real answer is to use the out-dated nest library. The lack of updates and and documentation to the elastic.clients.elasticsearch library seem to tell me that I need to start looking for something to replace elasticsearch in my tech stack. Elastic clearly doesn't see the .Net community as important to their long term strategies. If they did they'd be more aggressive in supporting .Net.