zed.proto

  1syntax = "proto3";
  2package zed.messages;
  3
  4message Envelope {
  5    uint32 id = 1;
  6    optional uint32 responding_to = 2;
  7    optional uint32 original_sender_id = 3;
  8    oneof payload {
  9        Ack ack = 4;
 10        Error error = 5;
 11        Ping ping = 6;
 12        Test test = 7;
 13
 14        RegisterProject register_project = 8;
 15        RegisterProjectResponse register_project_response = 9;
 16        UnregisterProject unregister_project = 10;
 17        RequestJoinProject request_join_project = 11;
 18        RespondToJoinProjectRequest respond_to_join_project_request = 12;
 19        JoinProjectRequestCancelled join_project_request_cancelled = 13;
 20        JoinProject join_project = 14;
 21        JoinProjectResponse join_project_response = 15;
 22        LeaveProject leave_project = 16;
 23        AddProjectCollaborator add_project_collaborator = 17;
 24        RemoveProjectCollaborator remove_project_collaborator = 18;
 25        ProjectUnshared project_unshared = 19;
 26
 27        GetDefinition get_definition = 20;
 28        GetDefinitionResponse get_definition_response = 21;
 29        GetReferences get_references = 22;
 30        GetReferencesResponse get_references_response = 23;
 31        GetDocumentHighlights get_document_highlights = 24;
 32        GetDocumentHighlightsResponse get_document_highlights_response = 25;
 33        GetProjectSymbols get_project_symbols = 26;
 34        GetProjectSymbolsResponse get_project_symbols_response = 27;
 35        OpenBufferForSymbol open_buffer_for_symbol = 28;
 36        OpenBufferForSymbolResponse open_buffer_for_symbol_response = 29;
 37
 38        UpdateProject update_project = 30;
 39        RegisterProjectActivity register_project_activity = 31;
 40        UpdateWorktree update_worktree = 32;
 41
 42        CreateProjectEntry create_project_entry = 33;
 43        RenameProjectEntry rename_project_entry = 34;
 44        CopyProjectEntry copy_project_entry = 35;
 45        DeleteProjectEntry delete_project_entry = 36;
 46        ProjectEntryResponse project_entry_response = 37;
 47
 48        UpdateDiagnosticSummary update_diagnostic_summary = 38;
 49        StartLanguageServer start_language_server = 39;
 50        UpdateLanguageServer update_language_server = 40;
 51
 52        OpenBufferById open_buffer_by_id = 41;
 53        OpenBufferByPath open_buffer_by_path = 42;
 54        OpenBufferResponse open_buffer_response = 43;
 55        UpdateBuffer update_buffer = 44;
 56        UpdateBufferFile update_buffer_file = 45;
 57        SaveBuffer save_buffer = 46;
 58        BufferSaved buffer_saved = 47;
 59        BufferReloaded buffer_reloaded = 48;
 60        ReloadBuffers reload_buffers = 49;
 61        ReloadBuffersResponse reload_buffers_response = 50;
 62        FormatBuffers format_buffers = 51;
 63        FormatBuffersResponse format_buffers_response = 52;
 64        GetCompletions get_completions = 53;
 65        GetCompletionsResponse get_completions_response = 54;
 66        ApplyCompletionAdditionalEdits apply_completion_additional_edits = 55;
 67        ApplyCompletionAdditionalEditsResponse apply_completion_additional_edits_response = 56;
 68        GetCodeActions get_code_actions = 57;
 69        GetCodeActionsResponse get_code_actions_response = 58;
 70        GetHover get_hover = 59;
 71        GetHoverResponse get_hover_response = 60;
 72        ApplyCodeAction apply_code_action = 61;
 73        ApplyCodeActionResponse apply_code_action_response = 62;
 74        PrepareRename prepare_rename = 63;
 75        PrepareRenameResponse prepare_rename_response = 64;
 76        PerformRename perform_rename = 65;
 77        PerformRenameResponse perform_rename_response = 66;
 78        SearchProject search_project = 67;
 79        SearchProjectResponse search_project_response = 68;
 80
 81        GetChannels get_channels = 69;
 82        GetChannelsResponse get_channels_response = 70;
 83        JoinChannel join_channel = 71;
 84        JoinChannelResponse join_channel_response = 72;
 85        LeaveChannel leave_channel = 73;
 86        SendChannelMessage send_channel_message = 74;
 87        SendChannelMessageResponse send_channel_message_response = 75;
 88        ChannelMessageSent channel_message_sent = 76;
 89        GetChannelMessages get_channel_messages = 77;
 90        GetChannelMessagesResponse get_channel_messages_response = 78;
 91
 92        UpdateContacts update_contacts = 79;
 93        UpdateInviteInfo update_invite_info = 80;
 94        ShowContacts show_contacts = 81;
 95
 96        GetUsers get_users = 82;
 97        FuzzySearchUsers fuzzy_search_users = 83;
 98        UsersResponse users_response = 84;
 99        RequestContact request_contact = 85;
100        RespondToContactRequest respond_to_contact_request = 86;
101        RemoveContact remove_contact = 87;
102
103        Follow follow = 88;
104        FollowResponse follow_response = 89;
105        UpdateFollowers update_followers = 90;
106        Unfollow unfollow = 91;
107    }
108}
109
110// Messages
111
112message Ping {}
113
114message Ack {}
115
116message Error {
117    string message = 1;
118}
119
120message Test {
121    uint64 id = 1;
122}
123
124message RegisterProject {}
125
126message RegisterProjectResponse {
127    uint64 project_id = 1;
128}
129
130message UnregisterProject {
131    uint64 project_id = 1;
132}
133
134message UpdateProject {
135    uint64 project_id = 1;
136    repeated WorktreeMetadata worktrees = 2;
137}
138
139message RegisterProjectActivity {
140    uint64 project_id = 1;
141}
142
143message RequestJoinProject {
144    uint64 requester_id = 1;
145    uint64 project_id = 2;
146}
147
148message RespondToJoinProjectRequest {
149    uint64 requester_id = 1;
150    uint64 project_id = 2;
151    bool allow = 3;
152}
153
154message JoinProjectRequestCancelled {
155    uint64 requester_id = 1;
156    uint64 project_id = 2;
157}
158
159message JoinProject {
160    uint64 project_id = 1;
161}
162
163message JoinProjectResponse {
164    oneof variant {
165        Accept accept = 1;
166        Decline decline = 2;
167    }
168
169    message Accept {
170        uint32 replica_id = 1;
171        repeated Worktree worktrees = 2;
172        repeated Collaborator collaborators = 3;
173        repeated LanguageServer language_servers = 4;        
174    }
175    
176    message Decline {
177        Reason reason = 1;
178
179        enum Reason {
180            Declined = 0;
181            Closed = 1;
182            WentOffline = 2;
183        }
184    }
185}
186
187message LeaveProject {
188    uint64 project_id = 1;
189}
190
191message UpdateWorktree {
192    uint64 project_id = 1;
193    uint64 worktree_id = 2;
194    string root_name = 3;
195    repeated Entry updated_entries = 4;
196    repeated uint64 removed_entries = 5;
197    uint64 scan_id = 6;
198}
199
200message CreateProjectEntry {
201    uint64 project_id = 1;
202    uint64 worktree_id = 2;
203    bytes path = 3;
204    bool is_directory = 4;
205}
206
207message RenameProjectEntry {
208    uint64 project_id = 1;
209    uint64 entry_id = 2;
210    bytes new_path = 3;
211}
212
213message CopyProjectEntry {
214    uint64 project_id = 1;
215    uint64 entry_id = 2;
216    bytes new_path = 3;
217}
218
219message DeleteProjectEntry {
220    uint64 project_id = 1;
221    uint64 entry_id = 2;
222}
223
224message ProjectEntryResponse {
225    Entry entry = 1;
226    uint64 worktree_scan_id = 2;
227}
228
229message AddProjectCollaborator {
230    uint64 project_id = 1;
231    Collaborator collaborator = 2;
232}
233
234message RemoveProjectCollaborator {
235    uint64 project_id = 1;
236    uint32 peer_id = 2;
237}
238
239message ProjectUnshared {
240    uint64 project_id = 1;
241}
242
243message GetDefinition {
244     uint64 project_id = 1;
245     uint64 buffer_id = 2;
246     Anchor position = 3;
247     repeated VectorClockEntry version = 4;
248 }
249
250message GetDefinitionResponse {
251    repeated Location locations = 1;
252}
253
254message GetReferences {
255     uint64 project_id = 1;
256     uint64 buffer_id = 2;
257     Anchor position = 3;
258     repeated VectorClockEntry version = 4;
259 }
260
261message GetReferencesResponse {
262    repeated Location locations = 1;
263}
264
265message GetDocumentHighlights {
266     uint64 project_id = 1;
267     uint64 buffer_id = 2;
268     Anchor position = 3;
269     repeated VectorClockEntry version = 4;
270 }
271
272message GetDocumentHighlightsResponse {
273    repeated DocumentHighlight highlights = 1;
274}
275
276message Location {
277    Buffer buffer = 1;
278    Anchor start = 2;
279    Anchor end = 3;
280}
281
282message DocumentHighlight {
283    Kind kind = 1;
284    Anchor start = 2;
285    Anchor end = 3;
286
287    enum Kind {
288        Text = 0;
289        Read = 1;
290        Write = 2;
291    }
292}
293
294message GetProjectSymbols {
295    uint64 project_id = 1;
296    string query = 2;
297}
298
299message GetProjectSymbolsResponse {
300    repeated Symbol symbols = 4;
301}
302
303message Symbol {
304    uint64 source_worktree_id = 1;
305    uint64 worktree_id = 2;
306    string language_server_name = 3;
307    string name = 4;
308    int32 kind = 5;
309    string path = 6;
310    Point start = 7;
311    Point end = 8;
312    bytes signature = 9;
313}
314
315message OpenBufferForSymbol {
316    uint64 project_id = 1;
317    Symbol symbol = 2;
318}
319
320message OpenBufferForSymbolResponse {
321    Buffer buffer = 1;
322}
323
324message OpenBufferByPath {
325    uint64 project_id = 1;
326    uint64 worktree_id = 2;
327    string path = 3;
328}
329
330message OpenBufferById {
331    uint64 project_id = 1;
332    uint64 id = 2;
333}
334
335message OpenBufferResponse {
336    Buffer buffer = 1;
337}
338
339message CloseBuffer {
340    uint64 project_id = 1;
341    uint64 buffer_id = 2;
342}
343
344message UpdateBuffer {
345    uint64 project_id = 1;
346    uint64 buffer_id = 2;
347    repeated Operation operations = 3;
348}
349
350message UpdateBufferFile {
351    uint64 project_id = 1;
352    uint64 buffer_id = 2;
353    File file = 3;
354}
355
356message SaveBuffer {
357    uint64 project_id = 1;
358    uint64 buffer_id = 2;
359    repeated VectorClockEntry version = 3;
360}
361
362message BufferSaved {
363    uint64 project_id = 1;
364    uint64 buffer_id = 2;
365    repeated VectorClockEntry version = 3;
366    Timestamp mtime = 4;
367    string fingerprint = 5;
368}
369
370message BufferReloaded {
371    uint64 project_id = 1;
372    uint64 buffer_id = 2;
373    repeated VectorClockEntry version = 3;
374    Timestamp mtime = 4;
375    string fingerprint = 5;
376}
377
378message ReloadBuffers {
379    uint64 project_id = 1;
380    repeated uint64 buffer_ids = 2;
381}
382
383message ReloadBuffersResponse {
384    ProjectTransaction transaction = 1;
385}
386
387message FormatBuffers {
388    uint64 project_id = 1;
389    repeated uint64 buffer_ids = 2;
390}
391
392message FormatBuffersResponse {
393    ProjectTransaction transaction = 1;
394}
395
396message GetCompletions {
397    uint64 project_id = 1;
398    uint64 buffer_id = 2;
399    Anchor position = 3;
400    repeated VectorClockEntry version = 4;
401}
402
403message GetCompletionsResponse {
404    repeated Completion completions = 1;
405    repeated VectorClockEntry version = 2;
406}
407
408message ApplyCompletionAdditionalEdits {
409    uint64 project_id = 1;
410    uint64 buffer_id = 2;
411    Completion completion = 3;
412}
413
414message ApplyCompletionAdditionalEditsResponse {
415    Transaction transaction = 1;
416}
417
418message Completion {
419    Anchor old_start = 1;
420    Anchor old_end = 2;
421    string new_text = 3;
422    bytes lsp_completion = 4;
423}
424
425message GetCodeActions {
426    uint64 project_id = 1;
427    uint64 buffer_id = 2;
428    Anchor start = 3;
429    Anchor end = 4;
430    repeated VectorClockEntry version = 5;
431}
432
433message GetCodeActionsResponse {
434    repeated CodeAction actions = 1;
435    repeated VectorClockEntry version = 2;
436}
437
438message GetHover {
439    uint64 project_id = 1;
440    uint64 buffer_id = 2;
441    Anchor position = 3;
442    repeated VectorClockEntry version = 5;
443}
444
445message GetHoverResponse {
446    optional Anchor start = 1;
447    optional Anchor end = 2;
448    repeated HoverBlock contents = 3;
449}
450
451message HoverBlock {
452    string text = 1;
453    optional string language = 2;
454}
455
456message ApplyCodeAction {
457    uint64 project_id = 1;
458    uint64 buffer_id = 2;
459    CodeAction action = 3;
460}
461
462message ApplyCodeActionResponse {
463    ProjectTransaction transaction = 1;
464}
465
466message PrepareRename {
467    uint64 project_id = 1;
468    uint64 buffer_id = 2;
469    Anchor position = 3;
470    repeated VectorClockEntry version = 4;
471}
472
473message PrepareRenameResponse {
474    bool can_rename = 1;
475    Anchor start = 2;
476    Anchor end = 3;
477    repeated VectorClockEntry version = 4;
478}
479
480message PerformRename {
481    uint64 project_id = 1;
482    uint64 buffer_id = 2;
483    Anchor position = 3;
484    string new_name = 4;
485    repeated VectorClockEntry version = 5;
486}
487
488message PerformRenameResponse {
489    ProjectTransaction transaction = 2;
490}
491
492message SearchProject {
493    uint64 project_id = 1;
494    string query = 2;
495    bool regex = 3;
496    bool whole_word = 4;
497    bool case_sensitive = 5;
498}
499
500message SearchProjectResponse {
501    repeated Location locations = 1;
502}
503
504message CodeAction {
505    Anchor start = 1;
506    Anchor end = 2;
507    bytes lsp_action = 3;
508}
509
510message ProjectTransaction {
511    repeated Buffer buffers = 1;
512    repeated Transaction transactions = 2;
513}
514
515message Transaction {
516    LocalTimestamp id = 1;
517    repeated LocalTimestamp edit_ids = 2;
518    repeated VectorClockEntry start = 3;
519    repeated VectorClockEntry end = 4;
520    repeated Range ranges = 5;
521}
522
523message LocalTimestamp {
524    uint32 replica_id = 1;
525    uint32 value = 2;
526}
527
528message LanguageServer {
529    uint64 id = 1;
530    string name = 2;
531}
532
533message StartLanguageServer {
534    uint64 project_id = 1;
535    LanguageServer server = 2;
536}
537
538message UpdateDiagnosticSummary {
539    uint64 project_id = 1;
540    uint64 worktree_id = 2;
541    DiagnosticSummary summary = 3;
542}
543
544message DiagnosticSummary {
545    string path = 1;
546    uint64 language_server_id = 2;
547    uint32 error_count = 3;
548    uint32 warning_count = 4;
549}
550
551message UpdateLanguageServer {
552    uint64 project_id = 1;
553    uint64 language_server_id = 2;
554    oneof variant {
555        LspWorkStart work_start = 3;
556        LspWorkProgress work_progress = 4;
557        LspWorkEnd work_end = 5;
558        LspDiskBasedDiagnosticsUpdating disk_based_diagnostics_updating = 6;
559        LspDiskBasedDiagnosticsUpdated disk_based_diagnostics_updated = 7;
560    }
561}
562
563message LspWorkStart {
564    string token = 1;
565    optional string message = 2;
566    optional uint32 percentage = 3;
567}
568
569message LspWorkProgress {
570    string token = 1;
571    optional string message = 2;
572    optional uint32 percentage = 3;
573}
574
575message LspWorkEnd {
576    string token = 1;
577}
578
579message LspDiskBasedDiagnosticsUpdating {}
580
581message LspDiskBasedDiagnosticsUpdated {}
582
583message GetChannels {}
584
585message GetChannelsResponse {
586    repeated Channel channels = 1;
587}
588
589message JoinChannel {
590    uint64 channel_id = 1;
591}
592
593message JoinChannelResponse {
594    repeated ChannelMessage messages = 1;
595    bool done = 2;
596}
597
598message LeaveChannel {
599    uint64 channel_id = 1;
600}
601
602message GetUsers {
603    repeated uint64 user_ids = 1;
604}
605
606message FuzzySearchUsers {
607    string query = 1;
608}
609
610message UsersResponse {
611    repeated User users = 1;
612}
613
614message RequestContact {
615    uint64 responder_id = 1;
616}
617
618message RemoveContact {
619    uint64 user_id = 1;
620}
621
622message RespondToContactRequest {
623    uint64 requester_id = 1;
624    ContactRequestResponse response = 2;
625}
626
627enum ContactRequestResponse {
628    Accept = 0;
629    Decline = 1;
630    Block = 2;
631    Dismiss = 3;
632}
633
634message SendChannelMessage {
635    uint64 channel_id = 1;
636    string body = 2;
637    Nonce nonce = 3;
638}
639
640message SendChannelMessageResponse {
641    ChannelMessage message = 1;
642}
643
644message ChannelMessageSent {
645    uint64 channel_id = 1;
646    ChannelMessage message = 2;
647}
648
649message GetChannelMessages {
650    uint64 channel_id = 1;
651    uint64 before_message_id = 2;
652}
653
654message GetChannelMessagesResponse {
655    repeated ChannelMessage messages = 1;
656    bool done = 2;
657}
658
659message UpdateContacts {
660    repeated Contact contacts = 1;
661    repeated uint64 remove_contacts = 2;
662    repeated IncomingContactRequest incoming_requests = 3;
663    repeated uint64 remove_incoming_requests = 4;
664    repeated uint64 outgoing_requests = 5;
665    repeated uint64 remove_outgoing_requests = 6;
666}
667
668message UpdateInviteInfo {
669    string url = 1;
670    uint32 count = 2;
671}
672
673message ShowContacts {}
674
675message IncomingContactRequest {
676    uint64 requester_id = 1;
677    bool should_notify = 2;
678}
679
680message UpdateDiagnostics {
681    uint32 replica_id = 1;
682    uint32 lamport_timestamp = 2;
683    repeated Diagnostic diagnostics = 3;
684}
685
686message Follow {
687    uint64 project_id = 1;
688    uint32 leader_id = 2;
689}
690
691message FollowResponse {
692    optional uint64 active_view_id = 1;
693    repeated View views = 2;
694}
695
696message UpdateFollowers {
697    uint64 project_id = 1;
698    repeated uint32 follower_ids = 2;
699    oneof variant {
700        UpdateActiveView update_active_view = 3;
701        View create_view = 4;
702        UpdateView update_view = 5;
703    }
704}
705
706message Unfollow {
707    uint64 project_id = 1;
708    uint32 leader_id = 2;
709}
710
711// Entities
712
713message UpdateActiveView {
714    optional uint64 id = 1;
715    optional uint32 leader_id = 2;
716}
717
718message UpdateView {
719    uint64 id = 1;
720    optional uint32 leader_id = 2;
721
722    oneof variant {
723        Editor editor = 3;
724    }
725
726    message Editor {
727        repeated Selection selections = 1;
728        Anchor scroll_top_anchor = 2;
729        float scroll_x = 3;
730        float scroll_y = 4;
731    }
732}
733
734message View {
735    uint64 id = 1;
736    optional uint32 leader_id = 2;
737
738    oneof variant {
739        Editor editor = 3;
740    }
741
742    message Editor {
743        uint64 buffer_id = 1;
744        repeated Selection selections = 2;
745        Anchor scroll_top_anchor = 3;
746        float scroll_x = 4;
747        float scroll_y = 5;
748    }
749}
750
751message Collaborator {
752    uint32 peer_id = 1;
753    uint32 replica_id = 2;
754    uint64 user_id = 3;
755}
756
757message User {
758    uint64 id = 1;
759    string github_login = 2;
760    string avatar_url = 3;
761}
762
763message Worktree {
764    uint64 id = 1;
765    string root_name = 2;
766    repeated Entry entries = 3;
767    repeated DiagnosticSummary diagnostic_summaries = 4;
768    bool visible = 5;
769    uint64 scan_id = 6;
770}
771
772message File {
773    uint64 worktree_id = 1;
774    optional uint64 entry_id = 2;
775    string path = 3;
776    Timestamp mtime = 4;
777}
778
779message Entry {
780    uint64 id = 1;
781    bool is_dir = 2;
782    bytes path = 3;
783    uint64 inode = 4;
784    Timestamp mtime = 5;
785    bool is_symlink = 6;
786    bool is_ignored = 7;
787}
788
789message Buffer {
790    oneof variant {
791        uint64 id = 1;
792        BufferState state = 2;
793    }
794}
795
796message BufferState {
797    uint64 id = 1;
798    optional File file = 2;
799    string base_text = 3;
800    repeated Operation operations = 4;
801    repeated SelectionSet selections = 5;
802    repeated Diagnostic diagnostics = 6;
803    uint32 diagnostics_timestamp = 7;
804    repeated string completion_triggers = 8;
805}
806
807message SelectionSet {
808    uint32 replica_id = 1;
809    repeated Selection selections = 2;
810    uint32 lamport_timestamp = 3;
811    bool line_mode = 4;
812}
813
814message Selection {
815    uint64 id = 1;
816    Anchor start = 2;
817    Anchor end = 3;
818    bool reversed = 4;
819}
820
821message Anchor {
822    uint32 replica_id = 1;
823    uint32 local_timestamp = 2;
824    uint64 offset = 3;
825    Bias bias = 4;
826    optional uint64 buffer_id = 5;
827}
828
829enum Bias {
830    Left = 0;
831    Right = 1;
832}
833
834message Diagnostic {
835    Anchor start = 1;
836    Anchor end = 2;
837    Severity severity = 3;
838    string message = 4;
839    optional string code = 5;
840    uint64 group_id = 6;
841    bool is_primary = 7;
842    bool is_valid = 8;
843    bool is_disk_based = 9;
844    bool is_unnecessary = 10;
845
846    enum Severity {
847        None = 0;
848        Error = 1;
849        Warning = 2;
850        Information = 3;
851        Hint = 4;
852    }
853}
854
855message Operation {
856    oneof variant {
857        Edit edit = 1;
858        Undo undo = 2;
859        UpdateSelections update_selections = 3;
860        UpdateDiagnostics update_diagnostics = 4;
861        UpdateCompletionTriggers update_completion_triggers = 5;
862    }
863
864    message Edit {
865        uint32 replica_id = 1;
866        uint32 local_timestamp = 2;
867        uint32 lamport_timestamp = 3;
868        repeated VectorClockEntry version = 4;
869        repeated Range ranges = 5;
870        repeated string new_text = 6;
871    }
872
873    message Undo {
874        uint32 replica_id = 1;
875        uint32 local_timestamp = 2;
876        uint32 lamport_timestamp = 3;
877        repeated VectorClockEntry version = 4;
878        repeated Range transaction_ranges = 5;
879        repeated VectorClockEntry transaction_version = 6;
880        repeated UndoCount counts = 7;
881    }
882
883    message UpdateSelections {
884        uint32 replica_id = 1;
885        uint32 lamport_timestamp = 2;
886        repeated Selection selections = 3;
887        bool line_mode = 4;
888    }
889
890    message UpdateCompletionTriggers {
891        uint32 replica_id = 1;
892        uint32 lamport_timestamp = 2;
893        repeated string triggers = 3;
894    }
895}
896
897message UndoMapEntry {
898    uint32 replica_id = 1;
899    uint32 local_timestamp = 2;
900    repeated UndoCount counts = 3;
901}
902
903message UndoCount {
904    uint32 replica_id = 1;
905    uint32 local_timestamp = 2;
906    uint32 count = 3;
907}
908
909message VectorClockEntry {
910    uint32 replica_id = 1;
911    uint32 timestamp = 2;
912}
913
914message Timestamp {
915    uint64 seconds = 1;
916    uint32 nanos = 2;
917}
918
919message Range {
920    uint64 start = 1;
921    uint64 end = 2;
922}
923
924message Point {
925    uint32 row = 1;
926    uint32 column = 2;
927}
928
929message Nonce {
930    uint64 upper_half = 1;
931    uint64 lower_half = 2;
932}
933
934message Channel {
935    uint64 id = 1;
936    string name = 2;
937}
938
939message ChannelMessage {
940    uint64 id = 1;
941    string body = 2;
942    uint64 timestamp = 3;
943    uint64 sender_id = 4;
944    Nonce nonce = 5;
945}
946
947message Contact {
948    uint64 user_id = 1;
949    repeated ProjectMetadata projects = 2;
950    bool online = 3;
951    bool should_notify = 4;
952}
953
954message ProjectMetadata {
955    uint64 id = 1;
956    repeated string visible_worktree_root_names = 3;
957    repeated uint64 guests = 4;
958}
959
960message WorktreeMetadata {
961    uint64 id = 1;
962    string root_name = 2;
963    bool visible = 3;
964}