| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- syntax = "proto3";
- package chatto.api.v1;
- import "buf/validate/validate.proto";
- import "chatto/api/v1/message_types.proto";
- import "chatto/api/v1/room_timeline.proto";
- import "chatto/api/v1/rooms.proto";
- import "chatto/api/v1/threads.proto";
- import "google/protobuf/duration.proto";
- import "google/protobuf/timestamp.proto";
- // Ordering for message or grouped-thread search results.
- enum MessageSearchOrder {
- // Use relevance order.
- MESSAGE_SEARCH_ORDER_UNSPECIFIED = 0;
- // Highest message score first; grouped results use their best matching message.
- MESSAGE_SEARCH_ORDER_RELEVANCE = 1;
- // Newest matching message first, also when results are grouped.
- MESSAGE_SEARCH_ORDER_NEWEST = 2;
- // Return threads with the most recent activity first. Requires thread grouping.
- MESSAGE_SEARCH_ORDER_THREAD_ACTIVITY = 3;
- // Newest root-message creation first, with unknown dates last. Requires thread
- // grouping. Older servers can reject this order.
- MESSAGE_SEARCH_ORDER_THREAD_CREATED = 4;
- }
- // Candidate scope, intersected with the caller's current access and query filters.
- enum MessageSearchScope {
- // Search all accessible messages. This is the existing default.
- MESSAGE_SEARCH_SCOPE_UNSPECIFIED = 0;
- // Search roots and replies in followed threads, including direct messages.
- MESSAGE_SEARCH_SCOPE_FOLLOWED_THREADS = 1;
- }
- // Determines the result type and pagination unit.
- enum MessageSearchGroupBy {
- // Return individual matching messages.
- MESSAGE_SEARCH_GROUP_BY_UNSPECIFIED = 0;
- // Return distinct thread rows. A root without replies is also a thread.
- MESSAGE_SEARCH_GROUP_BY_THREAD = 1;
- }
- // Current availability of message search on this server.
- enum MessageSearchState {
- // The server did not report a meaningful state.
- MESSAGE_SEARCH_STATE_UNSPECIFIED = 0;
- // Search is disabled by the server operator.
- MESSAGE_SEARCH_STATE_DISABLED = 1;
- // Search is enabled but its provider has not established index state yet.
- MESSAGE_SEARCH_STATE_STARTING = 2;
- // The provider is rebuilding or catching up and cannot answer queries yet.
- MESSAGE_SEARCH_STATE_INDEXING = 3;
- // Search is ready to answer queries.
- MESSAGE_SEARCH_STATE_READY = 4;
- // Search can answer queries but has a known non-fatal limitation.
- MESSAGE_SEARCH_STATE_DEGRADED = 5;
- // Search is enabled but no provider can currently answer.
- MESSAGE_SEARCH_STATE_UNAVAILABLE = 6;
- }
- // Request to search current message bodies visible to the authenticated user.
- message SearchMessagesRequest {
- // Required query expression. Words are required terms, quoted text is an
- // exact phrase, and `AND` may separate terms. The query also accepts `in:`,
- // `from:`, `before:`, `after:`, and `has:attachment` filters; a recognized
- // filter may be used without a word or phrase.
- string query = 1 [(buf.validate.field).string = {
- min_len: 1
- max_bytes: 1024
- }];
- // Optional room-ID scope. The server intersects this room with rooms the
- // current user may read and with any `in:` filters in query.
- optional string room_id = 2 [(buf.validate.field).string = {
- min_len: 1
- max_bytes: 128
- }];
- // Optional author-ID scope. The server intersects this author with any
- // `from:` filters in query.
- optional string author_id = 3 [(buf.validate.field).string = {
- min_len: 1
- max_bytes: 128
- }];
- // Exclusive lower bound on message creation time. The stricter bound wins
- // when query also contains `after:`.
- google.protobuf.Timestamp created_after = 4;
- // Exclusive upper bound on message creation time. The stricter bound wins
- // when query also contains `before:`.
- google.protobuf.Timestamp created_before = 5;
- // When true, return only messages that currently have attachments.
- bool has_attachments = 6;
- // Defaults to relevance in both result modes. Thread activity order requires
- // thread grouping; newest order uses matching-message creation time.
- MessageSearchOrder order = 7 [(buf.validate.field).enum.defined_only = true];
- // Maximum results to return (messages or distinct threads). Zero uses 50; the
- // maximum is 100. Stale or no-longer-visible provider hits are omitted, so a
- // page may contain fewer messages than requested even when next_cursor is
- // present.
- uint32 page_size = 8 [(buf.validate.field).uint32.lte = 100];
- // Opaque cursor returned by the preceding response. It is bound to the
- // authenticated user and every other query field.
- string cursor = 9 [(buf.validate.field).string.max_bytes = 8192];
- // Candidate scope. Followed threads are selected before result pagination.
- MessageSearchScope scope = 10 [(buf.validate.field).enum.defined_only = true];
- // Result grouping. The server deduplicates threads before pagination.
- MessageSearchGroupBy group_by = 11 [(buf.validate.field).enum.defined_only = true];
- // Select root authors within FOLLOWED_THREADS before search and pagination.
- // Other scopes require UNSPECIFIED. This does not restrict reply authors;
- // author_id and from: still select the authors of matching messages.
- ThreadRootAuthorFilter root_author_filter = 12 [(buf.validate.field).enum.defined_only = true];
- }
- // One current, authorized match. With thread grouping, each result represents
- // one thread and message is its best match in the selected order.
- message MessageSearchResult {
- // Current renderable message that matched the query.
- Message message = 1;
- // Search-provider relevance score. Higher values are more relevant for the
- // same query. Clients may merge results from servers using compatible
- // search implementations by this value.
- double relevance_score = 2;
- // Present only with THREAD grouping. The matching message can be a reply;
- // the root and latest reply in this context need not match the query.
- ThreadSearchContext thread_context = 3;
- }
- // One ordered page of current, authorized message or thread results. Pagination reads a live
- // search index rather than a pinned snapshot, so results may move, repeat, or
- // disappear between page requests while the index advances.
- message SearchMessagesResponse {
- // Ordered matches. With THREAD grouping, one result per matching thread.
- // Otherwise each result is one message, without thread_context.
- repeated MessageSearchResult results = 1;
- // Opaque cursor for the next page in the selected result mode.
- // Empty means no more matches. Live activity can reorder thread pages.
- string next_cursor = 2;
- // Total distinct matching threads. Present only when group_by is THREAD.
- optional uint64 thread_total_count = 4;
- // Related entities for grouped results, avoiding per-row reads.
- RoomTimelineIncludes includes = 5;
- }
- // Current context for a grouped match. The viewer need not follow this thread.
- // Search evidence stays on the containing MessageSearchResult.
- message ThreadSearchContext {
- // Renderable root message, when still visible.
- Message root_message = 1;
- // Room containing this thread.
- RoomSummary room = 2;
- // Current thread metadata and viewer follow/read state.
- ThreadSummary thread = 3;
- // Most recent visible reply, when present; it need not match the query.
- Message latest_reply = 4;
- // Conversation-label participants for direct messages; empty for channels.
- repeated string direct_message_participant_user_ids = 5;
- }
- // Request for current message-search availability.
- message GetStatusRequest {}
- // Current message-search availability.
- message GetStatusResponse {
- reserved 2, 3;
- reserved "indexed_event_count", "target_event_count";
- // Current feature/provider state.
- MessageSearchState state = 1;
- // Suggested delay before checking again while search is not ready.
- google.protobuf.Duration retry_after = 4;
- }
- // Searches current message content visible to an authenticated user.
- service MessageSearchService {
- // Reports whether the operator enabled Search and whether its provider can
- // currently answer. This method remains available when Search is disabled.
- rpc GetStatus(GetStatusRequest) returns (GetStatusResponse);
- // Searches current message bodies in rooms where the caller is a member.
- // Scope and grouping are independent, including for direct messages. THREAD
- // grouping returns one row per matching root and its replies. Scope, grouping,
- // and ordering are part of the cursor scope. Unsupported combinations return
- // INVALID_ARGUMENT. Existing requests return individual messages by default.
- // Results also require message.read or a matching thread relationship with
- // message.read-interactions. Results are authorized and hydrated from current Chatto state
- // after provider matching. Returns FAILED_PRECONDITION when Search is
- // disabled and UNAVAILABLE when its provider is not ready.
- rpc SearchMessages(SearchMessagesRequest) returns (SearchMessagesResponse);
- }
|