// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

package google.cloud.aiplatform.v1beta1;

import "google/api/annotations.proto";
import "google/api/client.proto";
import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/cloud/aiplatform/v1beta1/entity_type.proto";
import "google/cloud/aiplatform/v1beta1/feature.proto";
import "google/cloud/aiplatform/v1beta1/feature_monitor.proto";
import "google/cloud/aiplatform/v1beta1/feature_selector.proto";
import "google/cloud/aiplatform/v1beta1/featurestore.proto";
import "google/cloud/aiplatform/v1beta1/io.proto";
import "google/cloud/aiplatform/v1beta1/operation.proto";
import "google/longrunning/operations.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/field_mask.proto";
import "google/protobuf/timestamp.proto";
import "google/type/interval.proto";

option csharp_namespace = "Google.Cloud.AIPlatform.V1Beta1";
option go_package = "cloud.google.com/go/aiplatform/apiv1beta1/aiplatformpb;aiplatformpb";
option java_multiple_files = true;
option java_outer_classname = "FeaturestoreServiceProto";
option java_package = "com.google.cloud.aiplatform.v1beta1";
option php_namespace = "Google\\Cloud\\AIPlatform\\V1beta1";
option ruby_package = "Google::Cloud::AIPlatform::V1beta1";

// The service that handles CRUD and List for resources for Featurestore.
service FeaturestoreService {
  option (google.api.default_host) = "aiplatform.googleapis.com";
  option (google.api.oauth_scopes) =
      "https://www.googleapis.com/auth/cloud-platform";

  // Creates a new Featurestore in a given project and location.
  rpc CreateFeaturestore(CreateFeaturestoreRequest)
      returns (google.longrunning.Operation) {
    option (google.api.http) = {
      post: "/v1beta1/{parent=projects/*/locations/*}/featurestores"
      body: "featurestore"
    };
    option (google.api.method_signature) = "parent,featurestore";
    option (google.api.method_signature) =
        "parent,featurestore,featurestore_id";
    option (google.longrunning.operation_info) = {
      response_type: "Featurestore"
      metadata_type: "CreateFeaturestoreOperationMetadata"
    };
  }

  // Gets details of a single Featurestore.
  rpc GetFeaturestore(GetFeaturestoreRequest) returns (Featurestore) {
    option (google.api.http) = {
      get: "/v1beta1/{name=projects/*/locations/*/featurestores/*}"
    };
    option (google.api.method_signature) = "name";
  }

  // Lists Featurestores in a given project and location.
  rpc ListFeaturestores(ListFeaturestoresRequest)
      returns (ListFeaturestoresResponse) {
    option (google.api.http) = {
      get: "/v1beta1/{parent=projects/*/locations/*}/featurestores"
    };
    option (google.api.method_signature) = "parent";
  }

  // Updates the parameters of a single Featurestore.
  rpc UpdateFeaturestore(UpdateFeaturestoreRequest)
      returns (google.longrunning.Operation) {
    option (google.api.http) = {
      patch: "/v1beta1/{featurestore.name=projects/*/locations/*/featurestores/*}"
      body: "featurestore"
    };
    option (google.api.method_signature) = "featurestore,update_mask";
    option (google.longrunning.operation_info) = {
      response_type: "Featurestore"
      metadata_type: "UpdateFeaturestoreOperationMetadata"
    };
  }

  // Deletes a single Featurestore. The Featurestore must not contain any
  // EntityTypes or `force` must be set to true for the request to succeed.
  rpc DeleteFeaturestore(DeleteFeaturestoreRequest)
      returns (google.longrunning.Operation) {
    option (google.api.http) = {
      delete: "/v1beta1/{name=projects/*/locations/*/featurestores/*}"
    };
    option (google.api.method_signature) = "name";
    option (google.api.method_signature) = "name,force";
    option (google.longrunning.operation_info) = {
      response_type: "google.protobuf.Empty"
      metadata_type: "DeleteOperationMetadata"
    };
  }

  // Creates a new EntityType in a given Featurestore.
  rpc CreateEntityType(CreateEntityTypeRequest)
      returns (google.longrunning.Operation) {
    option (google.api.http) = {
      post: "/v1beta1/{parent=projects/*/locations/*/featurestores/*}/entityTypes"
      body: "entity_type"
    };
    option (google.api.method_signature) = "parent,entity_type";
    option (google.api.method_signature) = "parent,entity_type,entity_type_id";
    option (google.longrunning.operation_info) = {
      response_type: "EntityType"
      metadata_type: "CreateEntityTypeOperationMetadata"
    };
  }

  // Gets details of a single EntityType.
  rpc GetEntityType(GetEntityTypeRequest) returns (EntityType) {
    option (google.api.http) = {
      get: "/v1beta1/{name=projects/*/locations/*/featurestores/*/entityTypes/*}"
    };
    option (google.api.method_signature) = "name";
  }

  // Lists EntityTypes in a given Featurestore.
  rpc ListEntityTypes(ListEntityTypesRequest)
      returns (ListEntityTypesResponse) {
    option (google.api.http) = {
      get: "/v1beta1/{parent=projects/*/locations/*/featurestores/*}/entityTypes"
    };
    option (google.api.method_signature) = "parent";
  }

  // Updates the parameters of a single EntityType.
  rpc UpdateEntityType(UpdateEntityTypeRequest) returns (EntityType) {
    option (google.api.http) = {
      patch: "/v1beta1/{entity_type.name=projects/*/locations/*/featurestores/*/entityTypes/*}"
      body: "entity_type"
    };
    option (google.api.method_signature) = "entity_type,update_mask";
  }

  // Deletes a single EntityType. The EntityType must not have any Features
  // or `force` must be set to true for the request to succeed.
  rpc DeleteEntityType(DeleteEntityTypeRequest)
      returns (google.longrunning.Operation) {
    option (google.api.http) = {
      delete: "/v1beta1/{name=projects/*/locations/*/featurestores/*/entityTypes/*}"
    };
    option (google.api.method_signature) = "name";
    option (google.api.method_signature) = "name,force";
    option (google.longrunning.operation_info) = {
      response_type: "google.protobuf.Empty"
      metadata_type: "DeleteOperationMetadata"
    };
  }

  // Creates a new Feature in a given EntityType.
  rpc CreateFeature(CreateFeatureRequest)
      returns (google.longrunning.Operation) {
    option (google.api.http) = {
      post: "/v1beta1/{parent=projects/*/locations/*/featurestores/*/entityTypes/*}/features"
      body: "feature"
    };
    option (google.api.method_signature) = "parent,feature";
    option (google.api.method_signature) = "parent,feature,feature_id";
    option (google.longrunning.operation_info) = {
      response_type: "Feature"
      metadata_type: "CreateFeatureOperationMetadata"
    };
  }

  // Creates a batch of Features in a given EntityType.
  rpc BatchCreateFeatures(BatchCreateFeaturesRequest)
      returns (google.longrunning.Operation) {
    option (google.api.http) = {
      post: "/v1beta1/{parent=projects/*/locations/*/featurestores/*/entityTypes/*}/features:batchCreate"
      body: "*"
    };
    option (google.api.method_signature) = "parent,requests";
    option (google.longrunning.operation_info) = {
      response_type: "BatchCreateFeaturesResponse"
      metadata_type: "BatchCreateFeaturesOperationMetadata"
    };
  }

  // Gets details of a single Feature.
  rpc GetFeature(GetFeatureRequest) returns (Feature) {
    option (google.api.http) = {
      get: "/v1beta1/{name=projects/*/locations/*/featurestores/*/entityTypes/*/features/*}"
    };
    option (google.api.method_signature) = "name";
  }

  // Lists Features in a given EntityType.
  rpc ListFeatures(ListFeaturesRequest) returns (ListFeaturesResponse) {
    option (google.api.http) = {
      get: "/v1beta1/{parent=projects/*/locations/*/featurestores/*/entityTypes/*}/features"
    };
    option (google.api.method_signature) = "parent";
  }

  // Updates the parameters of a single Feature.
  rpc UpdateFeature(UpdateFeatureRequest) returns (Feature) {
    option (google.api.http) = {
      patch: "/v1beta1/{feature.name=projects/*/locations/*/featurestores/*/entityTypes/*/features/*}"
      body: "feature"
    };
    option (google.api.method_signature) = "feature,update_mask";
  }

  // Deletes a single Feature.
  rpc DeleteFeature(DeleteFeatureRequest)
      returns (google.longrunning.Operation) {
    option (google.api.http) = {
      delete: "/v1beta1/{name=projects/*/locations/*/featurestores/*/entityTypes/*/features/*}"
    };
    option (google.api.method_signature) = "name";
    option (google.longrunning.operation_info) = {
      response_type: "google.protobuf.Empty"
      metadata_type: "DeleteOperationMetadata"
    };
  }

  // Imports Feature values into the Featurestore from a source storage.
  //
  // The progress of the import is tracked by the returned operation. The
  // imported features are guaranteed to be visible to subsequent read
  // operations after the operation is marked as successfully done.
  //
  // If an import operation fails, the Feature values returned from
  // reads and exports may be inconsistent. If consistency is
  // required, the caller must retry the same import request again and wait till
  // the new operation returned is marked as successfully done.
  //
  // There are also scenarios where the caller can cause inconsistency.
  //
  //  - Source data for import contains multiple distinct Feature values for
  //    the same entity ID and timestamp.
  //  - Source is modified during an import. This includes adding, updating, or
  //  removing source data and/or metadata. Examples of updating metadata
  //  include but are not limited to changing storage location, storage class,
  //  or retention policy.
  //  - Online serving cluster is under-provisioned.
  rpc ImportFeatureValues(ImportFeatureValuesRequest)
      returns (google.longrunning.Operation) {
    option (google.api.http) = {
      post: "/v1beta1/{entity_type=projects/*/locations/*/featurestores/*/entityTypes/*}:importFeatureValues"
      body: "*"
    };
    option (google.api.method_signature) = "entity_type";
    option (google.longrunning.operation_info) = {
      response_type: "ImportFeatureValuesResponse"
      metadata_type: "ImportFeatureValuesOperationMetadata"
    };
  }

  // Batch reads Feature values from a Featurestore.
  //
  // This API enables batch reading Feature values, where each read
  // instance in the batch may read Feature values of entities from one or
  // more EntityTypes. Point-in-time correctness is guaranteed for Feature
  // values of each read instance as of each instance's read timestamp.
  rpc BatchReadFeatureValues(BatchReadFeatureValuesRequest)
      returns (google.longrunning.Operation) {
    option (google.api.http) = {
      post: "/v1beta1/{featurestore=projects/*/locations/*/featurestores/*}:batchReadFeatureValues"
      body: "*"
    };
    option (google.api.method_signature) = "featurestore";
    option (google.longrunning.operation_info) = {
      response_type: "BatchReadFeatureValuesResponse"
      metadata_type: "BatchReadFeatureValuesOperationMetadata"
    };
  }

  // Exports Feature values from all the entities of a target EntityType.
  rpc ExportFeatureValues(ExportFeatureValuesRequest)
      returns (google.longrunning.Operation) {
    option (google.api.http) = {
      post: "/v1beta1/{entity_type=projects/*/locations/*/featurestores/*/entityTypes/*}:exportFeatureValues"
      body: "*"
    };
    option (google.api.method_signature) = "entity_type";
    option (google.longrunning.operation_info) = {
      response_type: "ExportFeatureValuesResponse"
      metadata_type: "ExportFeatureValuesOperationMetadata"
    };
  }

  // Delete Feature values from Featurestore.
  //
  // The progress of the deletion is tracked by the returned operation. The
  // deleted feature values are guaranteed to be invisible to subsequent read
  // operations after the operation is marked as successfully done.
  //
  // If a delete feature values operation fails, the feature values
  // returned from reads and exports may be inconsistent. If consistency is
  // required, the caller must retry the same delete request again and wait till
  // the new operation returned is marked as successfully done.
  rpc DeleteFeatureValues(DeleteFeatureValuesRequest)
      returns (google.longrunning.Operation) {
    option (google.api.http) = {
      post: "/v1beta1/{entity_type=projects/*/locations/*/featurestores/*/entityTypes/*}:deleteFeatureValues"
      body: "*"
    };
    option (google.api.method_signature) = "entity_type";
    option (google.longrunning.operation_info) = {
      response_type: "DeleteFeatureValuesResponse"
      metadata_type: "DeleteFeatureValuesOperationMetadata"
    };
  }

  // Searches Features matching a query in a given project.
  rpc SearchFeatures(SearchFeaturesRequest) returns (SearchFeaturesResponse) {
    option (google.api.http) = {
      get: "/v1beta1/{location=projects/*/locations/*}/featurestores:searchFeatures"
    };
    option (google.api.method_signature) = "location";
    option (google.api.method_signature) = "location,query";
  }
}

// Request message for
// [FeaturestoreService.CreateFeaturestore][google.cloud.aiplatform.v1beta1.FeaturestoreService.CreateFeaturestore].
message CreateFeaturestoreRequest {
  // Required. The resource name of the Location to create Featurestores.
  // Format:
  // `projects/{project}/locations/{location}`
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "aiplatform.googleapis.com/Featurestore"
    }
  ];

  // Required. The Featurestore to create.
  Featurestore featurestore = 2 [(google.api.field_behavior) = REQUIRED];

  // Required. The ID to use for this Featurestore, which will become the final
  // component of the Featurestore's resource name.
  //
  // This value may be up to 60 characters, and valid characters are
  // `[a-z0-9_]`. The first character cannot be a number.
  //
  // The value must be unique within the project and location.
  string featurestore_id = 3 [(google.api.field_behavior) = REQUIRED];
}

// Request message for
// [FeaturestoreService.GetFeaturestore][google.cloud.aiplatform.v1beta1.FeaturestoreService.GetFeaturestore].
message GetFeaturestoreRequest {
  // Required. The name of the Featurestore resource.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "aiplatform.googleapis.com/Featurestore"
    }
  ];
}

// Request message for
// [FeaturestoreService.ListFeaturestores][google.cloud.aiplatform.v1beta1.FeaturestoreService.ListFeaturestores].
message ListFeaturestoresRequest {
  // Required. The resource name of the Location to list Featurestores.
  // Format:
  // `projects/{project}/locations/{location}`
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "aiplatform.googleapis.com/Featurestore"
    }
  ];

  // Lists the featurestores that match the filter expression. The following
  // fields are supported:
  //
  // * `create_time`: Supports `=`, `!=`, `<`, `>`, `<=`, and `>=` comparisons.
  // Values must be
  //   in RFC 3339 format.
  // * `update_time`: Supports `=`, `!=`, `<`, `>`, `<=`, and `>=` comparisons.
  // Values must be
  //   in RFC 3339 format.
  // * `online_serving_config.fixed_node_count`: Supports `=`, `!=`, `<`, `>`,
  // `<=`, and `>=` comparisons.
  // * `labels`: Supports key-value equality and key presence.
  //
  // Examples:
  //
  // * `create_time > "2020-01-01" OR update_time > "2020-01-01"`
  //    Featurestores created or updated after 2020-01-01.
  // * `labels.env = "prod"`
  //    Featurestores with label "env" set to "prod".
  string filter = 2;

  // The maximum number of Featurestores to return. The service may return fewer
  // than this value. If unspecified, at most 100 Featurestores will be
  // returned. The maximum value is 100; any value greater than 100 will be
  // coerced to 100.
  int32 page_size = 3;

  // A page token, received from a previous
  // [FeaturestoreService.ListFeaturestores][google.cloud.aiplatform.v1beta1.FeaturestoreService.ListFeaturestores]
  // call. Provide this to retrieve the subsequent page.
  //
  // When paginating, all other parameters provided to
  // [FeaturestoreService.ListFeaturestores][google.cloud.aiplatform.v1beta1.FeaturestoreService.ListFeaturestores]
  // must match the call that provided the page token.
  string page_token = 4;

  // A comma-separated list of fields to order by, sorted in ascending order.
  // Use "desc" after a field name for descending.
  // Supported Fields:
  //
  //   * `create_time`
  //   * `update_time`
  //   * `online_serving_config.fixed_node_count`
  string order_by = 5;

  // Mask specifying which fields to read.
  google.protobuf.FieldMask read_mask = 6;
}

// Response message for
// [FeaturestoreService.ListFeaturestores][google.cloud.aiplatform.v1beta1.FeaturestoreService.ListFeaturestores].
message ListFeaturestoresResponse {
  // The Featurestores matching the request.
  repeated Featurestore featurestores = 1;

  // A token, which can be sent as
  // [ListFeaturestoresRequest.page_token][google.cloud.aiplatform.v1beta1.ListFeaturestoresRequest.page_token]
  // to retrieve the next page. If this field is omitted, there are no
  // subsequent pages.
  string next_page_token = 2;
}

// Request message for
// [FeaturestoreService.UpdateFeaturestore][google.cloud.aiplatform.v1beta1.FeaturestoreService.UpdateFeaturestore].
message UpdateFeaturestoreRequest {
  // Required. The Featurestore's `name` field is used to identify the
  // Featurestore to be updated. Format:
  // `projects/{project}/locations/{location}/featurestores/{featurestore}`
  Featurestore featurestore = 1 [(google.api.field_behavior) = REQUIRED];

  // Field mask is used to specify the fields to be overwritten in the
  // Featurestore resource by the update.
  // The fields specified in the update_mask are relative to the resource, not
  // the full request. A field will be overwritten if it is in the mask. If the
  // user does not provide a mask then only the non-empty fields present in the
  // request will be overwritten. Set the update_mask to `*` to override all
  // fields.
  //
  // Updatable fields:
  //
  //   * `labels`
  //   * `online_serving_config.fixed_node_count`
  //   * `online_serving_config.scaling`
  //   * `online_storage_ttl_days`
  google.protobuf.FieldMask update_mask = 2;
}

// Request message for
// [FeaturestoreService.DeleteFeaturestore][google.cloud.aiplatform.v1beta1.FeaturestoreService.DeleteFeaturestore].
message DeleteFeaturestoreRequest {
  // Required. The name of the Featurestore to be deleted.
  // Format:
  // `projects/{project}/locations/{location}/featurestores/{featurestore}`
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "aiplatform.googleapis.com/Featurestore"
    }
  ];

  // If set to true, any EntityTypes and Features for this Featurestore will
  // also be deleted. (Otherwise, the request will only work if the Featurestore
  // has no EntityTypes.)
  bool force = 2;
}

// Request message for
// [FeaturestoreService.ImportFeatureValues][google.cloud.aiplatform.v1beta1.FeaturestoreService.ImportFeatureValues].
message ImportFeatureValuesRequest {
  // Defines the Feature value(s) to import.
  message FeatureSpec {
    // Required. ID of the Feature to import values of. This Feature must exist
    // in the target EntityType, or the request will fail.
    string id = 1 [(google.api.field_behavior) = REQUIRED];

    // Source column to get the Feature values from. If not set, uses the column
    // with the same name as the Feature ID.
    string source_field = 2;
  }

  // Details about the source data, including the location of the storage and
  // the format.
  oneof source {
    AvroSource avro_source = 2;

    BigQuerySource bigquery_source = 3;

    CsvSource csv_source = 4;
  }

  // Source of Feature timestamp for all Feature values of each entity.
  // Timestamps must be millisecond-aligned.
  oneof feature_time_source {
    // Source column that holds the Feature timestamp for all Feature
    // values in each entity.
    string feature_time_field = 6;

    // Single Feature timestamp for all entities being imported. The
    // timestamp must not have higher than millisecond precision.
    google.protobuf.Timestamp feature_time = 7;
  }

  // Required. The resource name of the EntityType grouping the Features for
  // which values are being imported. Format:
  // `projects/{project}/locations/{location}/featurestores/{featurestore}/entityTypes/{entityType}`
  string entity_type = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "aiplatform.googleapis.com/EntityType"
    }
  ];

  // Source column that holds entity IDs. If not provided, entity IDs are
  // extracted from the column named entity_id.
  string entity_id_field = 5;

  // Required. Specifications defining which Feature values to import from the
  // entity. The request fails if no feature_specs are provided, and having
  // multiple feature_specs for one Feature is not allowed.
  repeated FeatureSpec feature_specs = 8
      [(google.api.field_behavior) = REQUIRED];

  // If set, data will not be imported for online serving. This
  // is typically used for backfilling, where Feature generation timestamps are
  // not in the timestamp range needed for online serving.
  bool disable_online_serving = 9;

  // Specifies the number of workers that are used to write data to the
  // Featurestore. Consider the online serving capacity that you require to
  // achieve the desired import throughput without interfering with online
  // serving. The value must be positive, and less than or equal to 100.
  // If not set, defaults to using 1 worker. The low count ensures minimal
  // impact on online serving performance.
  int32 worker_count = 11;

  // If true, API doesn't start ingestion analysis pipeline.
  bool disable_ingestion_analysis = 12;
}

// Response message for
// [FeaturestoreService.ImportFeatureValues][google.cloud.aiplatform.v1beta1.FeaturestoreService.ImportFeatureValues].
message ImportFeatureValuesResponse {
  // Number of entities that have been imported by the operation.
  int64 imported_entity_count = 1;

  // Number of Feature values that have been imported by the operation.
  int64 imported_feature_value_count = 2;

  // The number of rows in input source that weren't imported due to either
  // * Not having any featureValues.
  // * Having a null entityId.
  // * Having a null timestamp.
  // * Not being parsable (applicable for CSV sources).
  int64 invalid_row_count = 6;

  // The number rows that weren't ingested due to having feature timestamps
  // outside the retention boundary.
  int64 timestamp_outside_retention_rows_count = 4;
}

// Request message for
// [FeaturestoreService.BatchReadFeatureValues][google.cloud.aiplatform.v1beta1.FeaturestoreService.BatchReadFeatureValues].
message BatchReadFeatureValuesRequest {
  // Describe pass-through fields in read_instance source.
  message PassThroughField {
    // Required. The name of the field in the CSV header or the name of the
    // column in BigQuery table. The naming restriction is the same as
    // [Feature.name][google.cloud.aiplatform.v1beta1.Feature.name].
    string field_name = 1 [(google.api.field_behavior) = REQUIRED];
  }

  // Selects Features of an EntityType to read values of and specifies read
  // settings.
  message EntityTypeSpec {
    // Required. ID of the EntityType to select Features. The EntityType id is
    // the
    // [entity_type_id][google.cloud.aiplatform.v1beta1.CreateEntityTypeRequest.entity_type_id]
    // specified during EntityType creation.
    string entity_type_id = 1 [(google.api.field_behavior) = REQUIRED];

    // Required. Selectors choosing which Feature values to read from the
    // EntityType.
    FeatureSelector feature_selector = 2
        [(google.api.field_behavior) = REQUIRED];

    // Per-Feature settings for the batch read.
    repeated DestinationFeatureSetting settings = 3;
  }

  oneof read_option {
    // Each read instance consists of exactly one read timestamp and one or more
    // entity IDs identifying entities of the corresponding EntityTypes whose
    // Features are requested.
    //
    // Each output instance contains Feature values of requested entities
    // concatenated together as of the read time.
    //
    // An example read instance may be `foo_entity_id, bar_entity_id,
    // 2020-01-01T10:00:00.123Z`.
    //
    // An example output instance may be `foo_entity_id, bar_entity_id,
    // 2020-01-01T10:00:00.123Z, foo_entity_feature1_value,
    // bar_entity_feature2_value`.
    //
    // Timestamp in each read instance must be millisecond-aligned.
    //
    // `csv_read_instances` are read instances stored in a plain-text CSV file.
    // The header should be:
    //     [ENTITY_TYPE_ID1], [ENTITY_TYPE_ID2], ..., timestamp
    //
    // The columns can be in any order.
    //
    // Values in the timestamp column must use the RFC 3339 format, e.g.
    // `2012-07-30T10:43:17.123Z`.
    CsvSource csv_read_instances = 3;

    // Similar to csv_read_instances, but from BigQuery source.
    BigQuerySource bigquery_read_instances = 5;
  }

  // Required. The resource name of the Featurestore from which to query Feature
  // values. Format:
  // `projects/{project}/locations/{location}/featurestores/{featurestore}`
  string featurestore = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "aiplatform.googleapis.com/Featurestore"
    }
  ];

  // Required. Specifies output location and format.
  FeatureValueDestination destination = 4
      [(google.api.field_behavior) = REQUIRED];

  // When not empty, the specified fields in the *_read_instances source will be
  // joined as-is in the output, in addition to those fields from the
  // Featurestore Entity.
  //
  // For BigQuery source, the type of the pass-through values will be
  // automatically inferred. For CSV source, the pass-through values will be
  // passed as opaque bytes.
  repeated PassThroughField pass_through_fields = 8;

  // Required. Specifies EntityType grouping Features to read values of and
  // settings.
  repeated EntityTypeSpec entity_type_specs = 7
      [(google.api.field_behavior) = REQUIRED];

  // Optional. Excludes Feature values with feature generation timestamp before
  // this timestamp. If not set, retrieve oldest values kept in Feature Store.
  // Timestamp, if present, must not have higher than millisecond precision.
  google.protobuf.Timestamp start_time = 11
      [(google.api.field_behavior) = OPTIONAL];
}

// Request message for
// [FeaturestoreService.ExportFeatureValues][google.cloud.aiplatform.v1beta1.FeaturestoreService.ExportFeatureValues].
message ExportFeatureValuesRequest {
  // Describes exporting the latest Feature values of all entities of the
  // EntityType between [start_time, snapshot_time].
  message SnapshotExport {
    // Exports Feature values as of this timestamp. If not set,
    // retrieve values as of now. Timestamp, if present, must not have higher
    // than millisecond precision.
    google.protobuf.Timestamp snapshot_time = 1;

    // Excludes Feature values with feature generation timestamp before this
    // timestamp. If not set, retrieve oldest values kept in Feature Store.
    // Timestamp, if present, must not have higher than millisecond precision.
    google.protobuf.Timestamp start_time = 2;
  }

  // Describes exporting all historical Feature values of all entities of the
  // EntityType between [start_time, end_time].
  message FullExport {
    // Excludes Feature values with feature generation timestamp before this
    // timestamp. If not set, retrieve oldest values kept in Feature Store.
    // Timestamp, if present, must not have higher than millisecond precision.
    google.protobuf.Timestamp start_time = 2;

    // Exports Feature values as of this timestamp. If not set,
    // retrieve values as of now. Timestamp, if present, must not have higher
    // than millisecond precision.
    google.protobuf.Timestamp end_time = 1;
  }

  // Required. The mode in which Feature values are exported.
  oneof mode {
    // Exports the latest Feature values of all entities of the EntityType
    // within a time range.
    SnapshotExport snapshot_export = 3;

    // Exports all historical values of all entities of the EntityType within a
    // time range
    FullExport full_export = 7;
  }

  // Required. The resource name of the EntityType from which to export Feature
  // values. Format:
  // `projects/{project}/locations/{location}/featurestores/{featurestore}/entityTypes/{entity_type}`
  string entity_type = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "aiplatform.googleapis.com/EntityType"
    }
  ];

  // Required. Specifies destination location and format.
  FeatureValueDestination destination = 4
      [(google.api.field_behavior) = REQUIRED];

  // Required. Selects Features to export values of.
  FeatureSelector feature_selector = 5 [(google.api.field_behavior) = REQUIRED];

  // Per-Feature export settings.
  repeated DestinationFeatureSetting settings = 6;
}

message DestinationFeatureSetting {
  // Required. The ID of the Feature to apply the setting to.
  string feature_id = 1 [(google.api.field_behavior) = REQUIRED];

  // Specify the field name in the export destination. If not specified,
  // Feature ID is used.
  string destination_field = 2;
}

// A destination location for Feature values and format.
message FeatureValueDestination {
  oneof destination {
    // Output in BigQuery format.
    // [BigQueryDestination.output_uri][google.cloud.aiplatform.v1beta1.BigQueryDestination.output_uri]
    // in
    // [FeatureValueDestination.bigquery_destination][google.cloud.aiplatform.v1beta1.FeatureValueDestination.bigquery_destination]
    // must refer to a table.
    BigQueryDestination bigquery_destination = 1;

    // Output in TFRecord format.
    //
    // Below are the mapping from Feature value type
    // in Featurestore to Feature value type in TFRecord:
    //
    //     Value type in Featurestore                 | Value type in TFRecord
    //     DOUBLE, DOUBLE_ARRAY                       | FLOAT_LIST
    //     INT64, INT64_ARRAY                         | INT64_LIST
    //     STRING, STRING_ARRAY, BYTES                | BYTES_LIST
    //     true -> byte_string("true"), false -> byte_string("false")
    //     BOOL, BOOL_ARRAY (true, false)             | BYTES_LIST
    TFRecordDestination tfrecord_destination = 2;

    // Output in CSV format. Array Feature value types are not allowed in CSV
    // format.
    CsvDestination csv_destination = 3;
  }
}

// Response message for
// [FeaturestoreService.ExportFeatureValues][google.cloud.aiplatform.v1beta1.FeaturestoreService.ExportFeatureValues].
message ExportFeatureValuesResponse {}

// Response message for
// [FeaturestoreService.BatchReadFeatureValues][google.cloud.aiplatform.v1beta1.FeaturestoreService.BatchReadFeatureValues].
message BatchReadFeatureValuesResponse {}

// Request message for
// [FeaturestoreService.CreateEntityType][google.cloud.aiplatform.v1beta1.FeaturestoreService.CreateEntityType].
message CreateEntityTypeRequest {
  // Required. The resource name of the Featurestore to create EntityTypes.
  // Format:
  // `projects/{project}/locations/{location}/featurestores/{featurestore}`
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "aiplatform.googleapis.com/Featurestore"
    }
  ];

  // The EntityType to create.
  EntityType entity_type = 2;

  // Required. The ID to use for the EntityType, which will become the final
  // component of the EntityType's resource name.
  //
  // This value may be up to 60 characters, and valid characters are
  // `[a-z0-9_]`. The first character cannot be a number.
  //
  // The value must be unique within a featurestore.
  string entity_type_id = 3 [(google.api.field_behavior) = REQUIRED];
}

// Request message for
// [FeaturestoreService.GetEntityType][google.cloud.aiplatform.v1beta1.FeaturestoreService.GetEntityType].
message GetEntityTypeRequest {
  // Required. The name of the EntityType resource.
  // Format:
  // `projects/{project}/locations/{location}/featurestores/{featurestore}/entityTypes/{entity_type}`
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "aiplatform.googleapis.com/EntityType"
    }
  ];
}

// Request message for
// [FeaturestoreService.ListEntityTypes][google.cloud.aiplatform.v1beta1.FeaturestoreService.ListEntityTypes].
message ListEntityTypesRequest {
  // Required. The resource name of the Featurestore to list EntityTypes.
  // Format:
  // `projects/{project}/locations/{location}/featurestores/{featurestore}`
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "aiplatform.googleapis.com/EntityType"
    }
  ];

  // Lists the EntityTypes that match the filter expression. The following
  // filters are supported:
  //
  // * `create_time`: Supports `=`, `!=`, `<`, `>`, `>=`, and `<=` comparisons.
  // Values must be in RFC 3339 format.
  // * `update_time`: Supports `=`, `!=`, `<`, `>`, `>=`, and `<=` comparisons.
  // Values must be in RFC 3339 format.
  // * `labels`: Supports key-value equality as well as key presence.
  //
  // Examples:
  //
  // * `create_time > \"2020-01-31T15:30:00.000000Z\" OR
  //      update_time > \"2020-01-31T15:30:00.000000Z\"` --> EntityTypes created
  //      or updated after 2020-01-31T15:30:00.000000Z.
  // * `labels.active = yes AND labels.env = prod` --> EntityTypes having both
  //     (active: yes) and (env: prod) labels.
  // * `labels.env: *` --> Any EntityType which has a label with 'env' as the
  //   key.
  string filter = 2;

  // The maximum number of EntityTypes to return. The service may return fewer
  // than this value. If unspecified, at most 1000 EntityTypes will be returned.
  // The maximum value is 1000; any value greater than 1000 will be coerced to
  // 1000.
  int32 page_size = 3;

  // A page token, received from a previous
  // [FeaturestoreService.ListEntityTypes][google.cloud.aiplatform.v1beta1.FeaturestoreService.ListEntityTypes]
  // call. Provide this to retrieve the subsequent page.
  //
  // When paginating, all other parameters provided to
  // [FeaturestoreService.ListEntityTypes][google.cloud.aiplatform.v1beta1.FeaturestoreService.ListEntityTypes]
  // must match the call that provided the page token.
  string page_token = 4;

  // A comma-separated list of fields to order by, sorted in ascending order.
  // Use "desc" after a field name for descending.
  //
  // Supported fields:
  //
  //   * `entity_type_id`
  //   * `create_time`
  //   * `update_time`
  string order_by = 5;

  // Mask specifying which fields to read.
  google.protobuf.FieldMask read_mask = 6;
}

// Response message for
// [FeaturestoreService.ListEntityTypes][google.cloud.aiplatform.v1beta1.FeaturestoreService.ListEntityTypes].
message ListEntityTypesResponse {
  // The EntityTypes matching the request.
  repeated EntityType entity_types = 1;

  // A token, which can be sent as
  // [ListEntityTypesRequest.page_token][google.cloud.aiplatform.v1beta1.ListEntityTypesRequest.page_token]
  // to retrieve the next page. If this field is omitted, there are no
  // subsequent pages.
  string next_page_token = 2;
}

// Request message for
// [FeaturestoreService.UpdateEntityType][google.cloud.aiplatform.v1beta1.FeaturestoreService.UpdateEntityType].
message UpdateEntityTypeRequest {
  // Required. The EntityType's `name` field is used to identify the EntityType
  // to be updated. Format:
  // `projects/{project}/locations/{location}/featurestores/{featurestore}/entityTypes/{entity_type}`
  EntityType entity_type = 1 [(google.api.field_behavior) = REQUIRED];

  // Field mask is used to specify the fields to be overwritten in the
  // EntityType resource by the update.
  // The fields specified in the update_mask are relative to the resource, not
  // the full request. A field will be overwritten if it is in the mask. If the
  // user does not provide a mask then only the non-empty fields present in the
  // request will be overwritten. Set the update_mask to `*` to override all
  // fields.
  //
  // Updatable fields:
  //
  //   * `description`
  //   * `labels`
  //   * `monitoring_config.snapshot_analysis.disabled`
  //   * `monitoring_config.snapshot_analysis.monitoring_interval_days`
  //   * `monitoring_config.snapshot_analysis.staleness_days`
  //   * `monitoring_config.import_features_analysis.state`
  //   * `monitoring_config.import_features_analysis.anomaly_detection_baseline`
  //   * `monitoring_config.numerical_threshold_config.value`
  //   * `monitoring_config.categorical_threshold_config.value`
  //   * `offline_storage_ttl_days`
  google.protobuf.FieldMask update_mask = 2;
}

// Request message for [FeaturestoreService.DeleteEntityTypes][].
message DeleteEntityTypeRequest {
  // Required. The name of the EntityType to be deleted.
  // Format:
  // `projects/{project}/locations/{location}/featurestores/{featurestore}/entityTypes/{entity_type}`
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "aiplatform.googleapis.com/EntityType"
    }
  ];

  // If set to true, any Features for this EntityType will also be deleted.
  // (Otherwise, the request will only work if the EntityType has no Features.)
  bool force = 2;
}

// Request message for
// [FeaturestoreService.CreateFeature][google.cloud.aiplatform.v1beta1.FeaturestoreService.CreateFeature].
// Request message for
// [FeatureRegistryService.CreateFeature][google.cloud.aiplatform.v1beta1.FeatureRegistryService.CreateFeature].
message CreateFeatureRequest {
  // Required. The resource name of the EntityType or FeatureGroup to create a
  // Feature. Format for entity_type as parent:
  // `projects/{project}/locations/{location}/featurestores/{featurestore}/entityTypes/{entity_type}`
  // Format for feature_group as parent:
  // `projects/{project}/locations/{location}/featureGroups/{feature_group}`
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "aiplatform.googleapis.com/Feature"
    }
  ];

  // Required. The Feature to create.
  Feature feature = 2 [(google.api.field_behavior) = REQUIRED];

  // Required. The ID to use for the Feature, which will become the final
  // component of the Feature's resource name.
  //
  // This value may be up to 128 characters, and valid characters are
  // `[a-z0-9_]`. The first character cannot be a number.
  //
  // The value must be unique within an EntityType/FeatureGroup.
  string feature_id = 3 [(google.api.field_behavior) = REQUIRED];
}

// Request message for
// [FeaturestoreService.BatchCreateFeatures][google.cloud.aiplatform.v1beta1.FeaturestoreService.BatchCreateFeatures].
// Request message for
// [FeatureRegistryService.BatchCreateFeatures][google.cloud.aiplatform.v1beta1.FeatureRegistryService.BatchCreateFeatures].
message BatchCreateFeaturesRequest {
  // Required. The resource name of the EntityType/FeatureGroup to create the
  // batch of Features under. Format:
  // `projects/{project}/locations/{location}/featurestores/{featurestore}/entityTypes/{entity_type}`
  // `projects/{project}/locations/{location}/featureGroups/{feature_group}`
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "aiplatform.googleapis.com/Feature"
    }
  ];

  // Required. The request message specifying the Features to create. All
  // Features must be created under the same parent EntityType / FeatureGroup.
  // The `parent` field in each child request message can be omitted. If
  // `parent` is set in a child request, then the value must match the `parent`
  // value in this request message.
  repeated CreateFeatureRequest requests = 2
      [(google.api.field_behavior) = REQUIRED];
}

// Response message for
// [FeaturestoreService.BatchCreateFeatures][google.cloud.aiplatform.v1beta1.FeaturestoreService.BatchCreateFeatures].
message BatchCreateFeaturesResponse {
  // The Features created.
  repeated Feature features = 1;
}

// Request message for
// [FeaturestoreService.GetFeature][google.cloud.aiplatform.v1beta1.FeaturestoreService.GetFeature].
// Request message for
// [FeatureRegistryService.GetFeature][google.cloud.aiplatform.v1beta1.FeatureRegistryService.GetFeature].
message GetFeatureRequest {
  // Required. The name of the Feature resource.
  // Format for entity_type as parent:
  // `projects/{project}/locations/{location}/featurestores/{featurestore}/entityTypes/{entity_type}`
  // Format for feature_group as parent:
  // `projects/{project}/locations/{location}/featureGroups/{feature_group}`
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "aiplatform.googleapis.com/Feature"
    }
  ];

  // Optional. Only applicable for Vertex AI Feature Store.
  // If set, retrieves FeatureStatsAndAnomaly generated by FeatureMonitors based
  // on this spec.
  FeatureStatsAndAnomalySpec feature_stats_and_anomaly_spec = 3
      [(google.api.field_behavior) = OPTIONAL];
}

// Request message for
// [FeaturestoreService.ListFeatures][google.cloud.aiplatform.v1beta1.FeaturestoreService.ListFeatures].
// Request message for
// [FeatureRegistryService.ListFeatures][google.cloud.aiplatform.v1beta1.FeatureRegistryService.ListFeatures].
message ListFeaturesRequest {
  // Required. The resource name of the Location to list Features.
  // Format for entity_type as parent:
  // `projects/{project}/locations/{location}/featurestores/{featurestore}/entityTypes/{entity_type}`
  // Format for feature_group as parent:
  // `projects/{project}/locations/{location}/featureGroups/{feature_group}`
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "aiplatform.googleapis.com/Feature"
    }
  ];

  // Lists the Features that match the filter expression. The following
  // filters are supported:
  //
  // * `value_type`: Supports = and != comparisons.
  // * `create_time`: Supports =, !=, <, >, >=, and <= comparisons. Values must
  // be in RFC 3339 format.
  // * `update_time`: Supports =, !=, <, >, >=, and <= comparisons. Values must
  // be in RFC 3339 format.
  // * `labels`: Supports key-value equality as well as key presence.
  //
  // Examples:
  //
  // * `value_type = DOUBLE` --> Features whose type is DOUBLE.
  // * `create_time > \"2020-01-31T15:30:00.000000Z\" OR
  //      update_time > \"2020-01-31T15:30:00.000000Z\"` --> EntityTypes created
  //      or updated after 2020-01-31T15:30:00.000000Z.
  // * `labels.active = yes AND labels.env = prod` --> Features having both
  //     (active: yes) and (env: prod) labels.
  // * `labels.env: *` --> Any Feature which has a label with 'env' as the
  //   key.
  string filter = 2;

  // The maximum number of Features to return. The service may return fewer
  // than this value. If unspecified, at most 1000 Features will be returned.
  // The maximum value is 1000; any value greater than 1000 will be coerced to
  // 1000.
  int32 page_size = 3;

  // A page token, received from a previous
  // [FeaturestoreService.ListFeatures][google.cloud.aiplatform.v1beta1.FeaturestoreService.ListFeatures]
  // call or
  // [FeatureRegistryService.ListFeatures][google.cloud.aiplatform.v1beta1.FeatureRegistryService.ListFeatures]
  // call. Provide this to retrieve the subsequent page.
  //
  // When paginating, all other parameters provided to
  // [FeaturestoreService.ListFeatures][google.cloud.aiplatform.v1beta1.FeaturestoreService.ListFeatures]
  // or
  // [FeatureRegistryService.ListFeatures][google.cloud.aiplatform.v1beta1.FeatureRegistryService.ListFeatures]
  // must match the call that provided the page token.
  string page_token = 4;

  // A comma-separated list of fields to order by, sorted in ascending order.
  // Use "desc" after a field name for descending.
  // Supported fields:
  //
  //   * `feature_id`
  //   * `value_type` (Not supported for FeatureRegistry Feature)
  //   * `create_time`
  //   * `update_time`
  string order_by = 5;

  // Mask specifying which fields to read.
  google.protobuf.FieldMask read_mask = 6;

  // Only applicable for Vertex AI Feature Store (Legacy).
  // If set, return the most recent
  // [ListFeaturesRequest.latest_stats_count][google.cloud.aiplatform.v1beta1.ListFeaturesRequest.latest_stats_count]
  // of stats for each Feature in response. Valid value is [0, 10]. If number of
  // stats exists <
  // [ListFeaturesRequest.latest_stats_count][google.cloud.aiplatform.v1beta1.ListFeaturesRequest.latest_stats_count],
  // return all existing stats.
  int32 latest_stats_count = 7;
}

// Response message for
// [FeaturestoreService.ListFeatures][google.cloud.aiplatform.v1beta1.FeaturestoreService.ListFeatures].
// Response message for
// [FeatureRegistryService.ListFeatures][google.cloud.aiplatform.v1beta1.FeatureRegistryService.ListFeatures].
message ListFeaturesResponse {
  // The Features matching the request.
  repeated Feature features = 1;

  // A token, which can be sent as
  // [ListFeaturesRequest.page_token][google.cloud.aiplatform.v1beta1.ListFeaturesRequest.page_token]
  // to retrieve the next page. If this field is omitted, there are no
  // subsequent pages.
  string next_page_token = 2;
}

// Request message for
// [FeaturestoreService.SearchFeatures][google.cloud.aiplatform.v1beta1.FeaturestoreService.SearchFeatures].
message SearchFeaturesRequest {
  // Required. The resource name of the Location to search Features.
  // Format:
  // `projects/{project}/locations/{location}`
  string location = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "locations.googleapis.com/Location"
    }
  ];

  // Query string that is a conjunction of field-restricted queries and/or
  // field-restricted filters.  Field-restricted queries and filters can be
  // combined using `AND` to form a conjunction.
  //
  // A field query is in the form FIELD:QUERY. This implicitly checks if QUERY
  // exists as a substring within Feature's FIELD. The QUERY
  // and the FIELD are converted to a sequence of words (i.e. tokens) for
  // comparison. This is done by:
  //
  //   * Removing leading/trailing whitespace and tokenizing the search value.
  //   Characters that are not one of alphanumeric `[a-zA-Z0-9]`, underscore
  //   `_`, or asterisk `*` are treated as delimiters for tokens. `*` is treated
  //   as a wildcard that matches characters within a token.
  //   * Ignoring case.
  //   * Prepending an asterisk to the first and appending an asterisk to the
  //   last token in QUERY.
  //
  // A QUERY must be either a singular token or a phrase. A phrase is one or
  // multiple words enclosed in double quotation marks ("). With phrases, the
  // order of the words is important. Words in the phrase must be matching in
  // order and consecutively.
  //
  // Supported FIELDs for field-restricted queries:
  //
  // * `feature_id`
  // * `description`
  // * `entity_type_id`
  //
  // Examples:
  //
  // * `feature_id: foo` --> Matches a Feature with ID containing the substring
  // `foo` (eg. `foo`, `foofeature`, `barfoo`).
  // * `feature_id: foo*feature` --> Matches a Feature with ID containing the
  // substring `foo*feature` (eg. `foobarfeature`).
  // * `feature_id: foo AND description: bar` --> Matches a Feature with ID
  // containing the substring `foo` and description containing the substring
  // `bar`.
  //
  //
  // Besides field queries, the following exact-match filters are
  // supported. The exact-match filters do not support wildcards. Unlike
  // field-restricted queries, exact-match filters are case-sensitive.
  //
  // * `feature_id`: Supports = comparisons.
  // * `description`: Supports = comparisons. Multi-token filters should be
  // enclosed in quotes.
  // * `entity_type_id`: Supports = comparisons.
  // * `value_type`: Supports = and != comparisons.
  // * `labels`: Supports key-value equality as well as key presence.
  // * `featurestore_id`: Supports = comparisons.
  //
  // Examples:
  //
  // * `description = "foo bar"` --> Any Feature with description exactly equal
  // to `foo bar`
  // * `value_type = DOUBLE` --> Features whose type is DOUBLE.
  // * `labels.active = yes AND labels.env = prod` --> Features having both
  //     (active: yes) and (env: prod) labels.
  // * `labels.env: *` --> Any Feature which has a label with `env` as the
  //   key.
  string query = 3;

  // The maximum number of Features to return. The service may return fewer
  // than this value. If unspecified, at most 100 Features will be returned.
  // The maximum value is 100; any value greater than 100 will be coerced to
  // 100.
  int32 page_size = 4;

  // A page token, received from a previous
  // [FeaturestoreService.SearchFeatures][google.cloud.aiplatform.v1beta1.FeaturestoreService.SearchFeatures]
  // call. Provide this to retrieve the subsequent page.
  //
  // When paginating, all other parameters provided to
  // [FeaturestoreService.SearchFeatures][google.cloud.aiplatform.v1beta1.FeaturestoreService.SearchFeatures],
  // except `page_size`, must match the call that provided the page token.
  string page_token = 5;
}

// Response message for
// [FeaturestoreService.SearchFeatures][google.cloud.aiplatform.v1beta1.FeaturestoreService.SearchFeatures].
message SearchFeaturesResponse {
  // The Features matching the request.
  //
  // Fields returned:
  //
  //  * `name`
  //  * `description`
  //  * `labels`
  //  * `create_time`
  //  * `update_time`
  repeated Feature features = 1;

  // A token, which can be sent as
  // [SearchFeaturesRequest.page_token][google.cloud.aiplatform.v1beta1.SearchFeaturesRequest.page_token]
  // to retrieve the next page. If this field is omitted, there are no
  // subsequent pages.
  string next_page_token = 2;
}

// Request message for
// [FeaturestoreService.UpdateFeature][google.cloud.aiplatform.v1beta1.FeaturestoreService.UpdateFeature].
// Request message for
// [FeatureRegistryService.UpdateFeature][google.cloud.aiplatform.v1beta1.FeatureRegistryService.UpdateFeature].
message UpdateFeatureRequest {
  // Required. The Feature's `name` field is used to identify the Feature to be
  // updated.
  // Format:
  // `projects/{project}/locations/{location}/featurestores/{featurestore}/entityTypes/{entity_type}/features/{feature}`
  // `projects/{project}/locations/{location}/featureGroups/{feature_group}/features/{feature}`
  Feature feature = 1 [(google.api.field_behavior) = REQUIRED];

  // Field mask is used to specify the fields to be overwritten in the
  // Features resource by the update.
  // The fields specified in the update_mask are relative to the resource, not
  // the full request. A field will be overwritten if it is in the mask. If the
  // user does not provide a mask then only the non-empty fields present in the
  // request will be overwritten. Set the update_mask to `*` to override all
  // fields.
  //
  // Updatable fields:
  //
  //   * `description`
  //   * `labels`
  //   * `disable_monitoring` (Not supported for FeatureRegistryService Feature)
  //   * `point_of_contact` (Not supported for FeaturestoreService FeatureStore)
  google.protobuf.FieldMask update_mask = 2;
}

// Request message for
// [FeaturestoreService.DeleteFeature][google.cloud.aiplatform.v1beta1.FeaturestoreService.DeleteFeature].
// Request message for
// [FeatureRegistryService.DeleteFeature][google.cloud.aiplatform.v1beta1.FeatureRegistryService.DeleteFeature].
message DeleteFeatureRequest {
  // Required. The name of the Features to be deleted.
  // Format:
  // `projects/{project}/locations/{location}/featurestores/{featurestore}/entityTypes/{entity_type}/features/{feature}`
  // `projects/{project}/locations/{location}/featureGroups/{feature_group}/features/{feature}`
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "aiplatform.googleapis.com/Feature"
    }
  ];
}

// Details of operations that perform create Featurestore.
message CreateFeaturestoreOperationMetadata {
  // Operation metadata for Featurestore.
  GenericOperationMetadata generic_metadata = 1;
}

// Details of operations that perform update Featurestore.
message UpdateFeaturestoreOperationMetadata {
  // Operation metadata for Featurestore.
  GenericOperationMetadata generic_metadata = 1;
}

// Details of operations that perform import Feature values.
message ImportFeatureValuesOperationMetadata {
  // Operation metadata for Featurestore import Feature values.
  GenericOperationMetadata generic_metadata = 1;

  // Number of entities that have been imported by the operation.
  int64 imported_entity_count = 2;

  // Number of Feature values that have been imported by the operation.
  int64 imported_feature_value_count = 3;

  // The source URI from where Feature values are imported.
  repeated string source_uris = 4;

  // The number of rows in input source that weren't imported due to either
  // * Not having any featureValues.
  // * Having a null entityId.
  // * Having a null timestamp.
  // * Not being parsable (applicable for CSV sources).
  int64 invalid_row_count = 6;

  // The number rows that weren't ingested due to having timestamps outside the
  // retention boundary.
  int64 timestamp_outside_retention_rows_count = 7;

  // List of ImportFeatureValues operations running under a single EntityType
  // that are blocking this operation.
  repeated int64 blocking_operation_ids = 8;
}

// Details of operations that exports Features values.
message ExportFeatureValuesOperationMetadata {
  // Operation metadata for Featurestore export Feature values.
  GenericOperationMetadata generic_metadata = 1;
}

// Details of operations that batch reads Feature values.
message BatchReadFeatureValuesOperationMetadata {
  // Operation metadata for Featurestore batch read Features values.
  GenericOperationMetadata generic_metadata = 1;
}

// Details of operations that delete Feature values.
message DeleteFeatureValuesOperationMetadata {
  // Operation metadata for Featurestore delete Features values.
  GenericOperationMetadata generic_metadata = 1;
}

// Details of operations that perform create EntityType.
message CreateEntityTypeOperationMetadata {
  // Operation metadata for EntityType.
  GenericOperationMetadata generic_metadata = 1;
}

// Details of operations that perform create Feature.
message CreateFeatureOperationMetadata {
  // Operation metadata for Feature.
  GenericOperationMetadata generic_metadata = 1;
}

// Details of operations that perform batch create Features.
message BatchCreateFeaturesOperationMetadata {
  // Operation metadata for Feature.
  GenericOperationMetadata generic_metadata = 1;
}

// Request message for
// [FeaturestoreService.DeleteFeatureValues][google.cloud.aiplatform.v1beta1.FeaturestoreService.DeleteFeatureValues].
message DeleteFeatureValuesRequest {
  // Message to select entity.
  // If an entity id is selected, all the feature values corresponding to the
  // entity id will be deleted, including the entityId.
  message SelectEntity {
    // Required. Selectors choosing feature values of which entity id to be
    // deleted from the EntityType.
    EntityIdSelector entity_id_selector = 1
        [(google.api.field_behavior) = REQUIRED];
  }

  // Message to select time range and feature.
  // Values of the selected feature generated within an inclusive time range
  // will be deleted. Using this option permanently deletes the feature values
  // from the specified feature IDs within the specified time range.
  // This might include data from the online storage. If you want to retain
  // any deleted historical data in the online storage, you must re-ingest it.
  message SelectTimeRangeAndFeature {
    // Required. Select feature generated within a half-inclusive time range.
    // The time range is lower inclusive and upper exclusive.
    google.type.Interval time_range = 1
        [(google.api.field_behavior) = REQUIRED];

    // Required. Selectors choosing which feature values to be deleted from the
    // EntityType.
    FeatureSelector feature_selector = 2
        [(google.api.field_behavior) = REQUIRED];

    // If set, data will not be deleted from online storage.
    // When time range is older than the data in online storage, setting this to
    // be true will make the deletion have no impact on online serving.
    bool skip_online_storage_delete = 3;
  }

  // Defines options to select feature values to be deleted.
  oneof DeleteOption {
    // Select feature values to be deleted by specifying entities.
    SelectEntity select_entity = 2;

    // Select feature values to be deleted by specifying time range and
    // features.
    SelectTimeRangeAndFeature select_time_range_and_feature = 3;
  }

  // Required. The resource name of the EntityType grouping the Features for
  // which values are being deleted from. Format:
  // `projects/{project}/locations/{location}/featurestores/{featurestore}/entityTypes/{entityType}`
  string entity_type = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "aiplatform.googleapis.com/EntityType"
    }
  ];
}

// Response message for
// [FeaturestoreService.DeleteFeatureValues][google.cloud.aiplatform.v1beta1.FeaturestoreService.DeleteFeatureValues].
message DeleteFeatureValuesResponse {
  // Response message if the request uses the SelectEntity option.
  message SelectEntity {
    // The count of deleted entity rows in the offline storage.
    // Each row corresponds to the combination of an entity ID and a timestamp.
    // One entity ID can have multiple rows in the offline storage.
    int64 offline_storage_deleted_entity_row_count = 1;

    // The count of deleted entities in the online storage.
    // Each entity ID corresponds to one entity.
    int64 online_storage_deleted_entity_count = 2;
  }

  // Response message if the request uses the SelectTimeRangeAndFeature option.
  message SelectTimeRangeAndFeature {
    // The count of the features or columns impacted.
    // This is the same as the feature count in the request.
    int64 impacted_feature_count = 1;

    // The count of modified entity rows in the offline storage.
    // Each row corresponds to the combination of an entity ID and a timestamp.
    // One entity ID can have multiple rows in the offline storage.
    // Within each row, only the features specified in the request are
    // deleted.
    int64 offline_storage_modified_entity_row_count = 2;

    // The count of modified entities in the online storage.
    // Each entity ID corresponds to one entity.
    // Within each entity, only the features specified in the request are
    // deleted.
    int64 online_storage_modified_entity_count = 3;
  }

  // Response based on which delete option is specified in the
  // request
  oneof response {
    // Response for request specifying the entities to delete
    SelectEntity select_entity = 1;

    // Response for request specifying time range and feature
    SelectTimeRangeAndFeature select_time_range_and_feature = 2;
  }
}

// Selector for entityId. Getting ids from the given source.
message EntityIdSelector {
  // Details about the source data, including the location of the storage and
  // the format.
  oneof EntityIdsSource {
    // Source of Csv
    CsvSource csv_source = 3;
  }

  // Source column that holds entity IDs. If not provided, entity IDs are
  // extracted from the column named entity_id.
  string entity_id_field = 5;
}
