Repository: microsoft/onnxruntime
File: onnxruntime/core/session/plugin_ep/ep_plugin_provider_interfaces.cc (C++)

Code before:
  std::unique_ptr<EpGraph> ep_graph = nullptr;
  if (Status status = EpGraph::Create(graph_viewer, ep_graph); !status.IsOK()) {
    LOGS(logger, ERROR) << "Failed to create OrtGraph for " << Type() << ": " << status.ToString();
    return {};
  }

  OrtEpGraphSupportInfo api_graph_support_info(*ep_graph);
  Status status = ToStatusAndRelease(ort_ep_->GetCapability(ort_ep_.get(), ep_graph->ToExternal(), &api_graph_support_info));

  if (!status.IsOK()) {
    LOGS(logger, ERROR) << "OrtEp::GetCapability() for " << Type() << " failed with error: " << status.ToString();
    return {};
  }

  std::vector<std::unique_ptr<ComputeCapability>> result;
  result.reserve(api_graph_support_info.node_groupings.size());
  if (api_graph_support_info.node_groupings.empty()) {
    return {};
  }

  ModelMetadefIdGenerator generator;

  // Create ComputeCapability instances from OrtEpGraphSupportInfo::NodeGrouping instances.
  for (const OrtEpGraphSupportInfo::NodeGrouping& node_grouping : api_graph_support_info.node_groupings) {
    if (node_grouping.kind == OrtEpGraphSupportInfo::NodeGroupingKind::kSingleAssignedNode) {
      if (node_grouping.nodes.empty()) {
        // The EpGraphSupportInfo_AddSingleNode() C API should already return an error if the EP tries to provide
        // an invalid node. However, we check here too just in case this changes.
        LOGS(logger, ERROR) << "OrtEp::GetCapability() for " << Type() << " did not specify a valid node "
                            << "when specifying a supported node.";
        return {};
      }

      auto indexed_sub_graph = std::make_unique<IndexedSubGraph>();

      indexed_sub_graph->nodes.push_back(node_grouping.nodes[0]->GetInternalNode().Index());
      result.push_back(std::make_unique<ComputeCapability>(std::move(indexed_sub_graph)));
    } else if (node_grouping.kind == OrtEpGraphSupportInfo::NodeGroupingKind::kFusedNode) {
      if (node_grouping.nodes.empty()) {
        // The EpGraphSupportInfo_AddNodesToFuse() C API should already return an error if the EP tries to provide
        // an empty array of nodes from OrtEp::GetCapability(). However, we check here too just in case this changes.
        LOGS(logger, WARNING) << "OrtEp::GetCapability() for " << Type() << " set an empty array of nodes "
                              << "when specifying supported nodes.";
        return {};
      }

      std::unordered_set<const Node*> node_set;
      node_set.reserve(node_grouping.nodes.size());

      for (const EpNode* ep_node : node_grouping.nodes) {
        node_set.insert(&ep_node->GetInternalNode());

Review comment (suggestion):
hm, it _seems_ safe to assume that calling `EpGraphSupportInfo_AddSingleNode` will add one node. if we do want to check, checking for `node_grouping.nodes.size() == 1` would be more exact.

however, perhaps we also want to check that the EP didn't provide a node that was already assigned to another EP here.

Code after:
  if (api_graph_support_info.node_groupings.empty()) {
    return {};
  }

  ModelMetadefIdGenerator generator;

  // Create ComputeCapability instances from OrtEpGraphSupportInfo::NodeGrouping instances.
  for (const OrtEpGraphSupportInfo::NodeGrouping& node_grouping : api_graph_support_info.node_groupings) {
    // Skip this node grouping if any node has already been assigned to another EP.
    if (const Node* node_for_other_ep = FindFirstNodeAssignedToOtherEP(Type(), node_grouping.nodes);
        node_for_other_ep != nullptr) {
      LOGS(logger, WARNING) << "OrtEp::GetCapability() specified nodes that cannot be assigned to " << Type() << ". "
                            << "Found one or more nodes that were already assigned to a different EP named '"
                            << node_for_other_ep->GetExecutionProviderType() << "'. Ex: "
                            << node_for_other_ep->OpType() << " node with name '"
                            << node_for_other_ep->Name() << "'.";
      continue;
    }

    if (node_grouping.kind == OrtEpGraphSupportInfo::NodeGroupingKind::kSingleAssignedNode) {
      if (node_grouping.nodes.size() != 1) {
        // The EpGraphSupportInfo_AddSingleNode() C API should already return an error if the EP tries to provide
        // an invalid node. However, we check here too just in case this changes.
        LOGS(logger, ERROR) << "OrtEp::GetCapability() for " << Type() << " did not specify exactly one valid node "
                            << "when calling EpGraphSupportInfo_AddSingleNode().";
        return {};
      }

      auto indexed_sub_graph = std::make_unique<IndexedSubGraph>();

      indexed_sub_graph->nodes.push_back(node_grouping.nodes[0]->GetInternalNode().Index());
      result.push_back(std::make_unique<ComputeCapability>(std::move(indexed_sub_graph)));
    } else if (node_grouping.kind == OrtEpGraphSupportInfo::NodeGroupingKind::kFusedNode) {
      if (node_grouping.nodes.empty()) {
        // The EpGraphSupportInfo_AddNodesToFuse() C API should already return an error if the EP tries to provide
        // an empty array of nodes from OrtEp::GetCapability(). However, we check here too just in case this changes.
        LOGS(logger, ERROR) << "OrtEp::GetCapability() for " << Type() << " set an empty array of nodes "
                            << "when specifying supported nodes.";
        return {};
      }

      std::unordered_set<const Node*> node_set;
      node_set.reserve(node_grouping.nodes.size());

      for (const EpNode* ep_node : node_grouping.nodes) {
        node_set.insert(&ep_node->GetInternalNode());
      }

      // We now require the OrtEp to only provide individual groups of supported nodes that each maps to exactly
      // one ComputeCapability. Calling utils::CreateSupportedPartitions() may create multiple ComputeCapability
      // instances, and if so, log an error and return.