// Copyright 2026 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.discoveryengine.v1beta;

import "google/api/annotations.proto";
import "google/api/client.proto";
import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/cloud/discoveryengine/v1beta/assist_answer.proto";
import "google/cloud/discoveryengine/v1beta/assistant.proto";
import "google/cloud/discoveryengine/v1beta/search_service.proto";
import "google/cloud/discoveryengine/v1beta/session.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/field_mask.proto";

option csharp_namespace = "Google.Cloud.DiscoveryEngine.V1Beta";
option go_package = "cloud.google.com/go/discoveryengine/apiv1beta/discoveryenginepb;discoveryenginepb";
option java_multiple_files = true;
option java_outer_classname = "AssistantServiceProto";
option java_package = "com.google.cloud.discoveryengine.v1beta";
option objc_class_prefix = "DISCOVERYENGINE";
option php_namespace = "Google\\Cloud\\DiscoveryEngine\\V1beta";
option ruby_package = "Google::Cloud::DiscoveryEngine::V1beta";

// Service for managing Assistant configuration and assisting users.
service AssistantService {
  option (google.api.default_host) = "discoveryengine.googleapis.com";
  option (google.api.oauth_scopes) =
      "https://www.googleapis.com/auth/cloud-platform,"
      "https://www.googleapis.com/auth/discoveryengine.assist.readwrite,"
      "https://www.googleapis.com/auth/discoveryengine.readwrite,"
      "https://www.googleapis.com/auth/discoveryengine.serving.readwrite";

  // Assists the user with a query in a streaming fashion.
  rpc StreamAssist(StreamAssistRequest) returns (stream StreamAssistResponse) {
    option (google.api.http) = {
      post: "/v1beta/{name=projects/*/locations/*/collections/*/engines/*/assistants/*}:streamAssist"
      body: "*"
    };
  }

  // Creates an [Assistant][google.cloud.discoveryengine.v1beta.Assistant].
  rpc CreateAssistant(CreateAssistantRequest) returns (Assistant) {
    option (google.api.http) = {
      post: "/v1beta/{parent=projects/*/locations/*/collections/*/engines/*}/assistants"
      body: "assistant"
    };
  }

  // Deletes an [Assistant][google.cloud.discoveryengine.v1beta.Assistant].
  rpc DeleteAssistant(DeleteAssistantRequest) returns (google.protobuf.Empty) {
    option (google.api.http) = {
      delete: "/v1beta/{name=projects/*/locations/*/collections/*/engines/*/assistants/*}"
    };
    option (google.api.method_signature) = "name";
  }

  // Updates an [Assistant][google.cloud.discoveryengine.v1beta.Assistant]
  rpc UpdateAssistant(UpdateAssistantRequest) returns (Assistant) {
    option (google.api.http) = {
      patch: "/v1beta/{assistant.name=projects/*/locations/*/collections/*/engines/*/assistants/*}"
      body: "assistant"
    };
    option (google.api.method_signature) = "assistant,update_mask";
  }

  // Gets an [Assistant][google.cloud.discoveryengine.v1beta.Assistant].
  rpc GetAssistant(GetAssistantRequest) returns (Assistant) {
    option (google.api.http) = {
      get: "/v1beta/{name=projects/*/locations/*/collections/*/engines/*/assistants/*}"
    };
    option (google.api.method_signature) = "name";
  }

  // Lists all [Assistant][google.cloud.discoveryengine.v1beta.Assistant]s under
  // an [Engine][google.cloud.discoveryengine.v1beta.Engine].
  rpc ListAssistants(ListAssistantsRequest) returns (ListAssistantsResponse) {
    option (google.api.http) = {
      get: "/v1beta/{parent=projects/*/locations/*/collections/*/engines/*}/assistants"
    };
    option (google.api.method_signature) = "parent";
  }
}

// User metadata of the request.
message AssistUserMetadata {
  // Optional. IANA time zone, e.g. Europe/Budapest.
  string time_zone = 1 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Preferred language to be used for answering if language detection
  // fails. Also used as the language of error messages created by actions,
  // regardless of language detection results.
  string preferred_language_code = 2 [(google.api.field_behavior) = OPTIONAL];
}

// Request for the
// [AssistantService.StreamAssist][google.cloud.discoveryengine.v1beta.AssistantService.StreamAssist]
// method.
message StreamAssistRequest {
  // Specification of tools that are used to serve the request.
  message ToolsSpec {
    // Specification of the Vertex AI Search tool.
    message VertexAiSearchSpec {
      // Optional. Specs defining
      // [DataStore][google.cloud.discoveryengine.v1beta.DataStore]s to filter
      // on in a search call and configurations for those data stores. This is
      // only considered for
      // [Engine][google.cloud.discoveryengine.v1beta.Engine]s with multiple
      // data stores.
      repeated SearchRequest.DataStoreSpec data_store_specs = 2
          [(google.api.field_behavior) = OPTIONAL];

      // Optional. The filter syntax consists of an expression language for
      // constructing a predicate from one or more fields of the documents being
      // filtered. Filter expression is case-sensitive.
      //
      // If this field is unrecognizable, an  `INVALID_ARGUMENT`  is returned.
      //
      // Filtering in Vertex AI Search is done by mapping the LHS filter key to
      // a key property defined in the Vertex AI Search backend -- this mapping
      // is defined by the customer in their schema. For example a media
      // customer might have a field 'name' in their schema. In this case the
      // filter would look like this: filter --> name:'ANY("king kong")'
      //
      // For more information about filtering including syntax and filter
      // operators, see
      // [Filter](https://cloud.google.com/generative-ai-app-builder/docs/filter-search-metadata)
      string filter = 4 [(google.api.field_behavior) = OPTIONAL];
    }

    // Specification of the web grounding tool.
    message WebGroundingSpec {}

    // Specification of the image generation tool.
    message ImageGenerationSpec {}

    // Specification of the video generation tool.
    message VideoGenerationSpec {}

    // Optional. Specification of the Vertex AI Search tool.
    VertexAiSearchSpec vertex_ai_search_spec = 1
        [(google.api.field_behavior) = OPTIONAL];

    // Optional. Specification of the web grounding tool.
    // If field is present, enables grounding with web search. Works only if
    // [Assistant.web_grounding_type][google.cloud.discoveryengine.v1beta.Assistant.web_grounding_type]
    // is
    // [WEB_GROUNDING_TYPE_GOOGLE_SEARCH][google.cloud.discoveryengine.v1beta.Assistant.WebGroundingType.WEB_GROUNDING_TYPE_GOOGLE_SEARCH]
    // or
    // [WEB_GROUNDING_TYPE_ENTERPRISE_WEB_SEARCH][google.cloud.discoveryengine.v1beta.Assistant.WebGroundingType.WEB_GROUNDING_TYPE_ENTERPRISE_WEB_SEARCH].
    WebGroundingSpec web_grounding_spec = 2
        [(google.api.field_behavior) = OPTIONAL];

    // Optional. Specification of the image generation tool.
    ImageGenerationSpec image_generation_spec = 3
        [(google.api.field_behavior) = OPTIONAL];

    // Optional. Specification of the video generation tool.
    VideoGenerationSpec video_generation_spec = 4
        [(google.api.field_behavior) = OPTIONAL];
  }

  // Assistant generation specification for the request.
  // This allows to override the default generation configuration at the engine
  // level.
  message GenerationSpec {
    // Optional. The Vertex AI model_id used for the generative model. If not
    // set, the default Assistant model will be used.
    string model_id = 1 [(google.api.field_behavior) = OPTIONAL];
  }

  // Required. The resource name of the
  // [Assistant][google.cloud.discoveryengine.v1beta.Assistant]. Format:
  // `projects/{project}/locations/{location}/collections/{collection}/engines/{engine}/assistants/{assistant}`
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "discoveryengine.googleapis.com/Assistant"
    }
  ];

  // Optional. Current user query.
  //
  // Empty query is only supported if `file_ids` are provided. In this case, the
  // answer will be generated based on those context files.
  Query query = 2 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The session to use for the request. If specified, the assistant
  // has access to the session history, and the query and the answer are stored
  // there.
  //
  // If `-` is specified as the session ID, or it is left empty, then a new
  // session is created with an automatically generated ID.
  //
  // Format:
  // `projects/{project}/locations/{location}/collections/{collection}/engines/{engine}/sessions/{session}`
  string session = 3 [
    (google.api.field_behavior) = OPTIONAL,
    (google.api.resource_reference) = {
      type: "discoveryengine.googleapis.com/Session"
    }
  ];

  // Optional. Information about the user initiating the query.
  AssistUserMetadata user_metadata = 6 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Specification of tools that are used to serve the request.
  ToolsSpec tools_spec = 18 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Specification of the generation configuration for the request.
  GenerationSpec generation_spec = 19 [(google.api.field_behavior) = OPTIONAL];
}

// Response for the
// [AssistantService.StreamAssist][google.cloud.discoveryengine.v1beta.AssistantService.StreamAssist]
// method.
message StreamAssistResponse {
  // Information about the session.
  message SessionInfo {
    // Name of the newly generated or continued session.
    //
    // Format:
    // `projects/{project}/locations/{location}/collections/{collection}/engines/{engine}/sessions/{session}`.
    string session = 1 [(google.api.resource_reference) = {
      type: "discoveryengine.googleapis.com/Session"
    }];
  }

  // Represents a skill used during the assist call.
  message InvokedSkill {
    // The resource name of the skill.
    string name = 1;

    // The display name of the skill.
    string display_name = 2;
  }

  // Assist answer resource object containing parts of the assistant's final
  // answer for the user's query.
  //
  // Not present if the current response doesn't add anything to previously
  // sent
  // [AssistAnswer.replies][google.cloud.discoveryengine.v1beta.AssistAnswer.replies].
  //
  // Observe
  // [AssistAnswer.state][google.cloud.discoveryengine.v1beta.AssistAnswer.state]
  // to see if more parts are to be expected. While the state is `IN_PROGRESS`,
  // the
  // [AssistAnswer.replies][google.cloud.discoveryengine.v1beta.AssistAnswer.replies]
  // field in each response will contain replies (reply fragments) to be
  // appended to the ones received in previous responses.
  // [AssistAnswer.name][google.cloud.discoveryengine.v1beta.AssistAnswer.name]
  // won't be filled.
  //
  // If the state is `SUCCEEDED`, `FAILED` or `SKIPPED`, the response
  // is the last response and
  // [AssistAnswer.name][google.cloud.discoveryengine.v1beta.AssistAnswer.name]
  // will have a value.
  AssistAnswer answer = 1;

  // Session information. Only included in the final StreamAssistResponse of the
  // response stream.
  SessionInfo session_info = 2;

  // A global unique ID that identifies the current pair of request and stream
  // of responses. Used for feedback and support.
  string assist_token = 4;

  // The tool names of the tools that were invoked.
  repeated string invocation_tools = 8;

  // The skills executed during the turn.
  repeated InvokedSkill invoked_skills = 10;
}

// Request for the
// [AssistantService.CreateAssistant][google.cloud.discoveryengine.v1beta.AssistantService.CreateAssistant]
// method.
message CreateAssistantRequest {
  // Required. The parent resource name.
  // Format:
  // `projects/{project}/locations/{location}/collections/{collection}/engines/{engine}`
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "discoveryengine.googleapis.com/Engine"
    }
  ];

  // Required. The [Assistant][google.cloud.discoveryengine.v1beta.Assistant] to
  // create.
  Assistant assistant = 2 [(google.api.field_behavior) = REQUIRED];

  // Required. The ID to use for the
  // [Assistant][google.cloud.discoveryengine.v1beta.Assistant], which will
  // become the final component of the
  // [Assistant][google.cloud.discoveryengine.v1beta.Assistant]'s resource name.
  //
  // This field must conform to [RFC-1034](https://tools.ietf.org/html/rfc1034)
  // with a length limit of 63 characters.
  string assistant_id = 3 [(google.api.field_behavior) = REQUIRED];
}

// Request message for the
// [AssistantService.DeleteAssistant][google.cloud.discoveryengine.v1beta.AssistantService.DeleteAssistant]
// method.
message DeleteAssistantRequest {
  // Required. Resource name of
  // [Assistant][google.cloud.discoveryengine.v1beta.Assistant]. Format:
  // `projects/{project}/locations/{location}/collections/{collection}/engines/{engine}/assistants/{assistant}`
  //
  // If the caller does not have permission to delete the
  // [Assistant][google.cloud.discoveryengine.v1beta.Assistant], regardless of
  // whether or not it exists, a PERMISSION_DENIED error is returned.
  //
  // If the [Assistant][google.cloud.discoveryengine.v1beta.Assistant] to delete
  // does not exist, a NOT_FOUND error is returned.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "discoveryengine.googleapis.com/Assistant"
    }
  ];
}

// Request message for the
// [AssistantService.GetAssistant][google.cloud.discoveryengine.v1beta.AssistantService.GetAssistant]
// method.
message GetAssistantRequest {
  // Required. Resource name of
  // [Assistant][google.cloud.discoveryengine.v1beta.Assistant]. Format:
  // `projects/{project}/locations/{location}/collections/{collection}/engines/{engine}/assistants/{assistant}`
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "discoveryengine.googleapis.com/Assistant"
    }
  ];
}

// Request message for the
// [AssistantService.ListAssistants][google.cloud.discoveryengine.v1beta.AssistantService.ListAssistants]
// method.
message ListAssistantsRequest {
  // Required. The parent resource name.
  // Format:
  // `projects/{project}/locations/{location}/collections/{collection}/engines/{engine}`
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "discoveryengine.googleapis.com/Engine"
    }
  ];

  // Maximum number of
  // [Assistant][google.cloud.discoveryengine.v1beta.Assistant]s to return. If
  // unspecified, defaults to 100. The maximum allowed value is 1000; anything
  // above that will be coerced down to 1000.
  int32 page_size = 2;

  // A page token
  // [ListAssistantsResponse.next_page_token][google.cloud.discoveryengine.v1beta.ListAssistantsResponse.next_page_token],
  // received from a previous
  // [AssistantService.ListAssistants][google.cloud.discoveryengine.v1beta.AssistantService.ListAssistants]
  // call. Provide this to retrieve the subsequent page.
  //
  // When paginating, all other parameters provided to
  // [ListAssistants][google.cloud.discoveryengine.v1beta.AssistantService.ListAssistants]
  // must match the call that provided the page token.
  string page_token = 3;
}

// Response message for the
// [AssistantService.ListAssistants][google.cloud.discoveryengine.v1beta.AssistantService.ListAssistants]
// method.
message ListAssistantsResponse {
  // All the customer's
  // [Assistant][google.cloud.discoveryengine.v1beta.Assistant]s.
  repeated Assistant assistants = 1;

  // A token that can be sent as
  // [ListAssistantsRequest.page_token][google.cloud.discoveryengine.v1beta.ListAssistantsRequest.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 the
// [AssistantService.UpdateAssistant][google.cloud.discoveryengine.v1beta.AssistantService.UpdateAssistant]
// method.
message UpdateAssistantRequest {
  // Required. The [Assistant][google.cloud.discoveryengine.v1beta.Assistant] to
  // update.
  //
  // The [Assistant][google.cloud.discoveryengine.v1beta.Assistant]'s `name`
  // field is used to identify the
  // [Assistant][google.cloud.discoveryengine.v1beta.Assistant] to update.
  // Format:
  // `projects/{project}/locations/{location}/collections/{collection}/engines/{engine}/assistants/{assistant}`
  //
  // If the caller does not have permission to update the
  // [Assistant][google.cloud.discoveryengine.v1beta.Assistant], regardless of
  // whether or not it exists, a PERMISSION_DENIED error is returned.
  //
  // If the [Assistant][google.cloud.discoveryengine.v1beta.Assistant] to update
  // does not exist, a NOT_FOUND error is returned.
  Assistant assistant = 1 [(google.api.field_behavior) = REQUIRED];

  // The list of fields to update.
  google.protobuf.FieldMask update_mask = 2;
}
