diff --git a/api/gen/proto/go/usageevents/v1/usageevents.pb.go b/api/gen/proto/go/usageevents/v1/usageevents.pb.go index 918d5d406125c..93fe996ea6527 100644 --- a/api/gen/proto/go/usageevents/v1/usageevents.pb.go +++ b/api/gen/proto/go/usageevents/v1/usageevents.pb.go @@ -2424,6 +2424,160 @@ func (m *AssistNewConversationEvent) GetCategory() string { return "" } +// AssistAccessRequest is an event that is emitted when a user requests access +// to a resource via Assist. +type AssistAccessRequest struct { + // ResourceType describes the type of resource the user is requesting access to, e.g. "node", "db", "k8s" or "role". + ResourceType string `protobuf:"bytes,1,opt,name=resource_type,json=resourceType,proto3" json:"resource_type,omitempty"` + // TotalTokens is the total amount of token used to generate the command summary + TotalTokens int64 `protobuf:"varint,2,opt,name=total_tokens,json=totalTokens,proto3" json:"total_tokens,omitempty"` + // PromptTokens is the amount of estimated tokens used by the prompt to generate the command summary + PromptTokens int64 `protobuf:"varint,3,opt,name=prompt_tokens,json=promptTokens,proto3" json:"prompt_tokens,omitempty"` + // CompletionTokens is the amount of tokens that the summary completion response consists of + CompletionTokens int64 `protobuf:"varint,4,opt,name=completion_tokens,json=completionTokens,proto3" json:"completion_tokens,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *AssistAccessRequest) Reset() { *m = AssistAccessRequest{} } +func (m *AssistAccessRequest) String() string { return proto.CompactTextString(m) } +func (*AssistAccessRequest) ProtoMessage() {} +func (*AssistAccessRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_94cf2ca1c69fd564, []int{35} +} +func (m *AssistAccessRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *AssistAccessRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_AssistAccessRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *AssistAccessRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_AssistAccessRequest.Merge(m, src) +} +func (m *AssistAccessRequest) XXX_Size() int { + return m.Size() +} +func (m *AssistAccessRequest) XXX_DiscardUnknown() { + xxx_messageInfo_AssistAccessRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_AssistAccessRequest proto.InternalMessageInfo + +func (m *AssistAccessRequest) GetResourceType() string { + if m != nil { + return m.ResourceType + } + return "" +} + +func (m *AssistAccessRequest) GetTotalTokens() int64 { + if m != nil { + return m.TotalTokens + } + return 0 +} + +func (m *AssistAccessRequest) GetPromptTokens() int64 { + if m != nil { + return m.PromptTokens + } + return 0 +} + +func (m *AssistAccessRequest) GetCompletionTokens() int64 { + if m != nil { + return m.CompletionTokens + } + return 0 +} + +// AssistAction is an event that is emitted when a user triggers an action (SSH command generation, output explain, etc.) +// via Assist. +type AssistAction struct { + // Action is the action that was triggered, e.g. "ssh-explain", "ssh-command-generate", etc. + Action string `protobuf:"bytes,1,opt,name=action,proto3" json:"action,omitempty"` + // TotalTokens is the total amount of token used to generate the command summary + TotalTokens int64 `protobuf:"varint,2,opt,name=total_tokens,json=totalTokens,proto3" json:"total_tokens,omitempty"` + // PromptTokens is the amount of estimated tokens used by the prompt to generate the command summary + PromptTokens int64 `protobuf:"varint,3,opt,name=prompt_tokens,json=promptTokens,proto3" json:"prompt_tokens,omitempty"` + // CompletionTokens is the amount of tokens that the summary completion response consists of + CompletionTokens int64 `protobuf:"varint,4,opt,name=completion_tokens,json=completionTokens,proto3" json:"completion_tokens,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *AssistAction) Reset() { *m = AssistAction{} } +func (m *AssistAction) String() string { return proto.CompactTextString(m) } +func (*AssistAction) ProtoMessage() {} +func (*AssistAction) Descriptor() ([]byte, []int) { + return fileDescriptor_94cf2ca1c69fd564, []int{36} +} +func (m *AssistAction) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *AssistAction) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_AssistAction.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *AssistAction) XXX_Merge(src proto.Message) { + xxx_messageInfo_AssistAction.Merge(m, src) +} +func (m *AssistAction) XXX_Size() int { + return m.Size() +} +func (m *AssistAction) XXX_DiscardUnknown() { + xxx_messageInfo_AssistAction.DiscardUnknown(m) +} + +var xxx_messageInfo_AssistAction proto.InternalMessageInfo + +func (m *AssistAction) GetAction() string { + if m != nil { + return m.Action + } + return "" +} + +func (m *AssistAction) GetTotalTokens() int64 { + if m != nil { + return m.TotalTokens + } + return 0 +} + +func (m *AssistAction) GetPromptTokens() int64 { + if m != nil { + return m.PromptTokens + } + return 0 +} + +func (m *AssistAction) GetCompletionTokens() int64 { + if m != nil { + return m.CompletionTokens + } + return 0 +} + // IntegrationEnrollMetadata contains common metadata // for Integration Enroll related events. type IntegrationEnrollMetadata struct { @@ -2443,7 +2597,7 @@ func (m *IntegrationEnrollMetadata) Reset() { *m = IntegrationEnrollMeta func (m *IntegrationEnrollMetadata) String() string { return proto.CompactTextString(m) } func (*IntegrationEnrollMetadata) ProtoMessage() {} func (*IntegrationEnrollMetadata) Descriptor() ([]byte, []int) { - return fileDescriptor_94cf2ca1c69fd564, []int{35} + return fileDescriptor_94cf2ca1c69fd564, []int{37} } func (m *IntegrationEnrollMetadata) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2506,7 +2660,7 @@ func (m *UIIntegrationEnrollStartEvent) Reset() { *m = UIIntegrationEnro func (m *UIIntegrationEnrollStartEvent) String() string { return proto.CompactTextString(m) } func (*UIIntegrationEnrollStartEvent) ProtoMessage() {} func (*UIIntegrationEnrollStartEvent) Descriptor() ([]byte, []int) { - return fileDescriptor_94cf2ca1c69fd564, []int{36} + return fileDescriptor_94cf2ca1c69fd564, []int{38} } func (m *UIIntegrationEnrollStartEvent) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2555,7 +2709,7 @@ func (m *UIIntegrationEnrollCompleteEvent) Reset() { *m = UIIntegrationE func (m *UIIntegrationEnrollCompleteEvent) String() string { return proto.CompactTextString(m) } func (*UIIntegrationEnrollCompleteEvent) ProtoMessage() {} func (*UIIntegrationEnrollCompleteEvent) Descriptor() ([]byte, []int) { - return fileDescriptor_94cf2ca1c69fd564, []int{37} + return fileDescriptor_94cf2ca1c69fd564, []int{39} } func (m *UIIntegrationEnrollCompleteEvent) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2630,6 +2784,8 @@ type UsageEventOneOf struct { // *UsageEventOneOf_UiOnboardQuestionnaireSubmit // *UsageEventOneOf_AssistExecution // *UsageEventOneOf_AssistNewConversation + // *UsageEventOneOf_AssistAccessRequest + // *UsageEventOneOf_AssistAction Event isUsageEventOneOf_Event `protobuf_oneof:"event"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -2640,7 +2796,7 @@ func (m *UsageEventOneOf) Reset() { *m = UsageEventOneOf{} } func (m *UsageEventOneOf) String() string { return proto.CompactTextString(m) } func (*UsageEventOneOf) ProtoMessage() {} func (*UsageEventOneOf) Descriptor() ([]byte, []int) { - return fileDescriptor_94cf2ca1c69fd564, []int{38} + return fileDescriptor_94cf2ca1c69fd564, []int{40} } func (m *UsageEventOneOf) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2777,6 +2933,12 @@ type UsageEventOneOf_AssistExecution struct { type UsageEventOneOf_AssistNewConversation struct { AssistNewConversation *AssistNewConversationEvent `protobuf:"bytes,35,opt,name=assist_new_conversation,json=assistNewConversation,proto3,oneof" json:"assist_new_conversation,omitempty"` } +type UsageEventOneOf_AssistAccessRequest struct { + AssistAccessRequest *AssistAccessRequest `protobuf:"bytes,38,opt,name=assist_access_request,json=assistAccessRequest,proto3,oneof" json:"assist_access_request,omitempty"` +} +type UsageEventOneOf_AssistAction struct { + AssistAction *AssistAction `protobuf:"bytes,39,opt,name=assist_action,json=assistAction,proto3,oneof" json:"assist_action,omitempty"` +} func (*UsageEventOneOf_UiBannerClick) isUsageEventOneOf_Event() {} func (*UsageEventOneOf_UiOnboardCompleteGoToDashboardClick) isUsageEventOneOf_Event() {} @@ -2812,6 +2974,8 @@ func (*UsageEventOneOf_UiIntegrationEnrollCompleteEvent) isUsageEventOneOf_Event func (*UsageEventOneOf_UiOnboardQuestionnaireSubmit) isUsageEventOneOf_Event() {} func (*UsageEventOneOf_AssistExecution) isUsageEventOneOf_Event() {} func (*UsageEventOneOf_AssistNewConversation) isUsageEventOneOf_Event() {} +func (*UsageEventOneOf_AssistAccessRequest) isUsageEventOneOf_Event() {} +func (*UsageEventOneOf_AssistAction) isUsageEventOneOf_Event() {} func (m *UsageEventOneOf) GetEvent() isUsageEventOneOf_Event { if m != nil { @@ -3058,6 +3222,20 @@ func (m *UsageEventOneOf) GetAssistNewConversation() *AssistNewConversationEvent return nil } +func (m *UsageEventOneOf) GetAssistAccessRequest() *AssistAccessRequest { + if x, ok := m.GetEvent().(*UsageEventOneOf_AssistAccessRequest); ok { + return x.AssistAccessRequest + } + return nil +} + +func (m *UsageEventOneOf) GetAssistAction() *AssistAction { + if x, ok := m.GetEvent().(*UsageEventOneOf_AssistAction); ok { + return x.AssistAction + } + return nil +} + // XXX_OneofWrappers is for the internal use of the proto package. func (*UsageEventOneOf) XXX_OneofWrappers() []interface{} { return []interface{}{ @@ -3095,6 +3273,8 @@ func (*UsageEventOneOf) XXX_OneofWrappers() []interface{} { (*UsageEventOneOf_UiOnboardQuestionnaireSubmit)(nil), (*UsageEventOneOf_AssistExecution)(nil), (*UsageEventOneOf_AssistNewConversation)(nil), + (*UsageEventOneOf_AssistAccessRequest)(nil), + (*UsageEventOneOf_AssistAction)(nil), } } @@ -3140,6 +3320,8 @@ func init() { proto.RegisterType((*AssistCompletionEvent)(nil), "teleport.usageevents.v1.AssistCompletionEvent") proto.RegisterType((*AssistExecutionEvent)(nil), "teleport.usageevents.v1.AssistExecutionEvent") proto.RegisterType((*AssistNewConversationEvent)(nil), "teleport.usageevents.v1.AssistNewConversationEvent") + proto.RegisterType((*AssistAccessRequest)(nil), "teleport.usageevents.v1.AssistAccessRequest") + proto.RegisterType((*AssistAction)(nil), "teleport.usageevents.v1.AssistAction") proto.RegisterType((*IntegrationEnrollMetadata)(nil), "teleport.usageevents.v1.IntegrationEnrollMetadata") proto.RegisterType((*UIIntegrationEnrollStartEvent)(nil), "teleport.usageevents.v1.UIIntegrationEnrollStartEvent") proto.RegisterType((*UIIntegrationEnrollCompleteEvent)(nil), "teleport.usageevents.v1.UIIntegrationEnrollCompleteEvent") @@ -3151,213 +3333,220 @@ func init() { } var fileDescriptor_94cf2ca1c69fd564 = []byte{ - // 3287 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x5b, 0xcb, 0x6f, 0x1c, 0x49, - 0x19, 0x9f, 0x1e, 0xdb, 0x89, 0x53, 0x49, 0xec, 0x4e, 0xe5, 0x35, 0x8e, 0xdf, 0xe3, 0x3c, 0x9d, - 0x5d, 0x7b, 0x93, 0xec, 0x23, 0x90, 0x85, 0xa5, 0xa7, 0xbb, 0xed, 0xee, 0x78, 0x66, 0x7a, 0x52, - 0xd5, 0x93, 0xe0, 0x48, 0xab, 0x52, 0x67, 0xa6, 0xe2, 0xb4, 0x32, 0xee, 0x1e, 0xba, 0x7b, 0xec, - 0xb5, 0x10, 0x5a, 0xf1, 0x14, 0xd2, 0x2e, 0x08, 0x0e, 0x48, 0x48, 0x48, 0x48, 0x08, 0x90, 0x38, - 0x70, 0x45, 0x7b, 0xe6, 0x04, 0x47, 0x24, 0xfe, 0x01, 0xb4, 0xff, 0x00, 0xe2, 0xc0, 0x05, 0x81, - 0x40, 0x5d, 0xfd, 0x98, 0x9e, 0x67, 0xf7, 0x06, 0xb8, 0x78, 0x6f, 0x9e, 0xaa, 0xdf, 0x57, 0xdf, - 0xaf, 0xea, 0xfb, 0xea, 0xf5, 0xab, 0x36, 0xb8, 0xe5, 0xd1, 0x16, 0x6d, 0xdb, 0x8e, 0xb7, 0xd9, - 0x71, 0x8d, 0x3d, 0x4a, 0x0f, 0xa8, 0xe5, 0xb9, 0x9b, 0x07, 0x77, 0x92, 0x3f, 0x37, 0xda, 0x8e, - 0xed, 0xd9, 0xf0, 0x72, 0x04, 0xdd, 0x48, 0xd6, 0x1d, 0xdc, 0x29, 0xae, 0x03, 0x58, 0x57, 0x4b, - 0x86, 0x65, 0x51, 0x47, 0x6c, 0x99, 0x8d, 0x97, 0xb2, 0x5f, 0x03, 0x2f, 0x80, 0x29, 0xa3, 0x45, - 0x1d, 0xaf, 0xc0, 0xad, 0x70, 0x37, 0x4f, 0xa1, 0xe0, 0x47, 0x71, 0x0b, 0xdc, 0xac, 0xab, 0x9a, - 0xf5, 0xcc, 0x36, 0x9c, 0xa6, 0x68, 0xef, 0xb7, 0x5b, 0xd4, 0xa3, 0xdb, 0xb6, 0x6e, 0x4b, 0x86, - 0xfb, 0x22, 0x28, 0xec, 0xb6, 0x70, 0x05, 0x4c, 0x77, 0x5c, 0xea, 0x58, 0xc6, 0x3e, 0x0d, 0x1b, - 0x89, 0x7f, 0x17, 0xaf, 0x81, 0xb5, 0xb8, 0x1d, 0xa1, 0xd9, 0xdc, 0x32, 0x1d, 0xd7, 0x43, 0xd4, - 0xb5, 0x3b, 0x4e, 0x83, 0x76, 0x9b, 0x28, 0xae, 0x27, 0xdc, 0xf5, 0xc3, 0xca, 0x86, 0x97, 0x24, - 0x5c, 0x7c, 0x0f, 0xac, 0xc6, 0x58, 0x4c, 0x3d, 0xd1, 0xa1, 0x4d, 0x6a, 0x79, 0xa6, 0xd1, 0xc2, - 0x9d, 0x67, 0xfb, 0xa6, 0x97, 0xce, 0x29, 0xd9, 0xc0, 0xa3, 0x0e, 0x75, 0x3d, 0xd3, 0xb6, 0x2c, - 0xc3, 0x74, 0x68, 0xd6, 0x06, 0xbe, 0x01, 0xae, 0xc5, 0x0d, 0x20, 0xba, 0x67, 0xba, 0x3e, 0xc1, - 0x17, 0x46, 0xab, 0x45, 0xad, 0xbd, 0xac, 0x8d, 0xc0, 0x39, 0x30, 0xbd, 0xff, 0xdc, 0x20, 0xde, - 0x51, 0x9b, 0x16, 0xf2, 0xac, 0xee, 0xe4, 0xfe, 0x73, 0x43, 0x3f, 0x6a, 0x53, 0xb8, 0x08, 0x40, - 0xcb, 0xde, 0x33, 0x2d, 0xf2, 0xbc, 0x65, 0x1f, 0x16, 0x26, 0x58, 0xe5, 0x29, 0x56, 0xb2, 0xd5, - 0xb2, 0x0f, 0x03, 0xfe, 0x88, 0x36, 0xec, 0x03, 0xea, 0x1c, 0x89, 0x76, 0x93, 0xba, 0xa2, 0x6d, - 0x79, 0xa6, 0xd5, 0xa1, 0x19, 0x83, 0xf2, 0x00, 0x2c, 0x0e, 0x34, 0xd0, 0x3e, 0xca, 0x68, 0xfc, - 0x2e, 0x58, 0xea, 0x33, 0xae, 0x39, 0xa6, 0xe5, 0x65, 0xb4, 0x2e, 0x02, 0x5e, 0x32, 0x5d, 0x66, - 0x5c, 0xa1, 0x9e, 0xd1, 0x34, 0x3c, 0x03, 0xce, 0x80, 0xbc, 0xd9, 0x0c, 0x91, 0x79, 0xb3, 0x59, - 0x34, 0x40, 0x21, 0xc2, 0x44, 0x39, 0x10, 0x63, 0x65, 0x30, 0xed, 0x84, 0x65, 0xcc, 0x62, 0xe6, - 0xee, 0xad, 0x8d, 0x11, 0xf9, 0xbe, 0xd1, 0xdf, 0x08, 0x8a, 0x4d, 0x8b, 0x2f, 0x01, 0x8c, 0x6a, - 0xb1, 0x47, 0xdb, 0xd8, 0x33, 0xbc, 0x8e, 0x0b, 0xdf, 0x03, 0x27, 0x5c, 0xf6, 0x57, 0xd8, 0xf4, - 0x8d, 0xd4, 0xa6, 0x03, 0x43, 0x14, 0x9a, 0xf9, 0x73, 0x89, 0x3a, 0x8e, 0xed, 0x84, 0x01, 0x0d, - 0x7e, 0x14, 0x7f, 0xc5, 0x81, 0x4b, 0x75, 0x35, 0x61, 0xe2, 0x78, 0xb4, 0x19, 0x0c, 0x95, 0x0c, - 0xa6, 0xf7, 0xc3, 0xae, 0x31, 0x9f, 0xa7, 0x33, 0x74, 0x27, 0x1a, 0x0b, 0x14, 0x9b, 0x42, 0x31, - 0x26, 0x9e, 0x67, 0x8d, 0xdc, 0xce, 0x40, 0x3c, 0xea, 0x75, 0x44, 0xbe, 0xf8, 0x2f, 0x0e, 0xac, - 0x74, 0x69, 0x46, 0x83, 0x86, 0x69, 0x8b, 0x36, 0xfc, 0x19, 0xf2, 0x3f, 0x25, 0x5c, 0x49, 0x84, - 0x31, 0xa0, 0x7c, 0x27, 0x73, 0x18, 0xbb, 0xcd, 0x45, 0x4d, 0x24, 0xfa, 0x3f, 0xf1, 0xea, 0xfd, - 0xff, 0x6e, 0xde, 0x5f, 0x84, 0x22, 0x80, 0x6a, 0x79, 0x74, 0xcf, 0x31, 0xfc, 0x9e, 0x0b, 0x4f, - 0xb0, 0xa6, 0x4a, 0xa2, 0x68, 0x5b, 0x16, 0x6d, 0x78, 0xc7, 0x7e, 0x1c, 0x3e, 0xc9, 0x27, 0xf3, - 0x40, 0x32, 0x3c, 0xe3, 0x99, 0xe1, 0x52, 0x24, 0x61, 0xd9, 0x72, 0xec, 0x56, 0xeb, 0xb8, 0xf7, - 0x1f, 0xde, 0x07, 0x05, 0x97, 0x25, 0x3d, 0x6d, 0x92, 0xa8, 0x65, 0x97, 0x34, 0xec, 0x8e, 0xe5, - 0x15, 0x26, 0x57, 0xb8, 0x9b, 0x13, 0xe8, 0x52, 0x54, 0x1f, 0x51, 0x71, 0x45, 0xbf, 0xb6, 0xf8, - 0x10, 0x14, 0xea, 0xaa, 0x68, 0xb4, 0x5a, 0xba, 0x2d, 0xb0, 0x39, 0x93, 0x58, 0x14, 0x37, 0xc0, - 0x44, 0x23, 0x1c, 0xab, 0x99, 0xbb, 0x0b, 0x23, 0x79, 0x89, 0xba, 0x80, 0x7c, 0x60, 0xf1, 0x07, - 0x53, 0x60, 0x21, 0x11, 0x05, 0xda, 0x6e, 0xd9, 0x47, 0x98, 0x3a, 0x07, 0x66, 0x83, 0x1e, 0xfb, - 0x08, 0xec, 0x81, 0xb3, 0x4d, 0xd6, 0x61, 0xb2, 0x4f, 0xbd, 0x17, 0x76, 0x93, 0x0d, 0xfb, 0xcc, - 0xdd, 0xd2, 0xc8, 0xb6, 0xc6, 0x0d, 0xd4, 0x46, 0x50, 0x54, 0x61, 0x2d, 0xa1, 0x33, 0xcd, 0xc4, - 0x2f, 0x68, 0x80, 0xd3, 0xa1, 0x23, 0xb6, 0x0d, 0x4f, 0x31, 0x37, 0x5f, 0xf9, 0x6f, 0xdc, 0xf8, - 0xfb, 0x37, 0x02, 0xcd, 0xf8, 0xef, 0x22, 0x01, 0x67, 0x92, 0x04, 0xe0, 0x22, 0x98, 0x93, 0xe4, - 0x5a, 0x59, 0xdb, 0x25, 0x15, 0x59, 0x57, 0x34, 0x89, 0xd4, 0xab, 0xb8, 0x26, 0x8b, 0xea, 0x96, - 0x2a, 0x4b, 0x7c, 0x0e, 0x5e, 0x02, 0xb0, 0xb7, 0x5a, 0xa8, 0xeb, 0x1a, 0xcf, 0xc1, 0x02, 0xb8, - 0xd0, 0x5b, 0x5e, 0x11, 0xaa, 0x75, 0xa1, 0xcc, 0xe7, 0x8b, 0x14, 0x80, 0xae, 0x6b, 0x38, 0x0f, - 0x2e, 0x87, 0x38, 0x7d, 0xb7, 0x26, 0xf7, 0x35, 0xbe, 0x04, 0xae, 0x24, 0x2b, 0xd5, 0x2a, 0xd6, - 0x85, 0x72, 0x99, 0x60, 0x11, 0xa9, 0x35, 0x9d, 0xe7, 0xe0, 0x15, 0x70, 0x29, 0x59, 0x2f, 0x54, - 0x84, 0xa7, 0x5a, 0x95, 0xc8, 0x22, 0xe6, 0xf3, 0xc5, 0x7f, 0x72, 0x60, 0x79, 0xc8, 0xaa, 0x10, - 0x9e, 0x7e, 0x8e, 0xfd, 0xa2, 0xf8, 0xcd, 0x3c, 0xb8, 0x3a, 0xd8, 0x7d, 0xd1, 0xb6, 0x9e, 0x9b, - 0x7b, 0x1d, 0x87, 0x56, 0xf4, 0x32, 0x3e, 0xf6, 0x63, 0xf0, 0xc3, 0x3c, 0xb8, 0x93, 0x9c, 0x02, - 0xee, 0x4b, 0xcf, 0x6e, 0xfb, 0x0b, 0xdd, 0x01, 0x95, 0x4c, 0x87, 0x36, 0x3c, 0xdb, 0x39, 0xd2, - 0x6d, 0xbb, 0xe5, 0xaa, 0x96, 0xeb, 0x19, 0xc7, 0x7f, 0xa7, 0x28, 0x7e, 0x94, 0x07, 0x1b, 0x69, - 0x03, 0x12, 0xa7, 0xc8, 0xb1, 0x1f, 0x8d, 0xdf, 0xe6, 0xc1, 0xf5, 0xee, 0x68, 0x08, 0x1d, 0xcf, - 0x8e, 0xfe, 0x4e, 0x6c, 0x94, 0xc7, 0x7e, 0xef, 0xba, 0x01, 0x66, 0x87, 0x1f, 0x1a, 0x66, 0x9c, - 0xde, 0xc3, 0xc2, 0xf7, 0xf2, 0xe0, 0xd6, 0x98, 0x15, 0x45, 0x15, 0x2a, 0x35, 0xbb, 0x65, 0x36, - 0x8e, 0x8e, 0x7d, 0xde, 0xfc, 0x9b, 0x03, 0xc5, 0xee, 0x40, 0xf8, 0x97, 0xc9, 0x86, 0xd9, 0x36, - 0x5a, 0xee, 0xe7, 0x67, 0xe6, 0xfc, 0x83, 0xf3, 0x2f, 0xe4, 0x11, 0x40, 0xa7, 0xae, 0x17, 0xde, - 0x35, 0x3e, 0x0f, 0xd7, 0xae, 0xbf, 0x73, 0xfe, 0xa9, 0x39, 0x02, 0x44, 0x5a, 0x53, 0xf3, 0xd8, - 0xf7, 0x7b, 0x1e, 0xcc, 0xd5, 0x55, 0xd1, 0xa1, 0x86, 0x47, 0xab, 0xf4, 0x10, 0xd9, 0xad, 0xa4, - 0x1e, 0xb6, 0xec, 0x27, 0x44, 0x4f, 0x25, 0x36, 0x0e, 0x92, 0x80, 0x55, 0xff, 0x34, 0xd6, 0x6b, - 0x6d, 0x58, 0x0d, 0xda, 0x4a, 0x40, 0x5e, 0x03, 0xeb, 0x7d, 0x90, 0xc7, 0x26, 0x3d, 0x94, 0xec, - 0x46, 0x67, 0x9f, 0x5a, 0x9e, 0xd1, 0x7b, 0x3f, 0x29, 0xfe, 0x8e, 0x03, 0x17, 0x05, 0xd7, 0x35, - 0xfd, 0xdc, 0x63, 0x21, 0x88, 0x73, 0xef, 0x06, 0x98, 0x6d, 0xd8, 0xd6, 0x01, 0x75, 0x5c, 0x66, - 0x43, 0x62, 0xad, 0x66, 0x26, 0x59, 0xac, 0x36, 0xe1, 0x2a, 0x38, 0xe3, 0xd9, 0x9e, 0xd1, 0x22, - 0x9e, 0xfd, 0x92, 0x5a, 0x81, 0x16, 0x31, 0x81, 0x4e, 0xb3, 0x32, 0x9d, 0x15, 0xc1, 0x35, 0x70, - 0xb6, 0xed, 0xd8, 0xfb, 0x6d, 0x2f, 0xc2, 0x4c, 0x30, 0xcc, 0x99, 0xa0, 0x30, 0x04, 0xdd, 0x06, - 0xe7, 0x1a, 0x31, 0x87, 0x08, 0x18, 0x2c, 0xa2, 0x7c, 0xb7, 0x22, 0x00, 0x17, 0xff, 0xcc, 0x81, - 0x0b, 0x01, 0x6f, 0xf9, 0x03, 0xda, 0xe8, 0xbc, 0x02, 0xed, 0x45, 0x00, 0x2c, 0xbb, 0x49, 0xc3, - 0xc5, 0x3a, 0x20, 0x7d, 0xca, 0x2f, 0x61, 0xeb, 0xf4, 0x40, 0xaf, 0x26, 0x32, 0xf4, 0x6a, 0x32, - 0x6b, 0xaf, 0xa6, 0x46, 0xf4, 0xea, 0x3e, 0xb8, 0x12, 0x74, 0xaa, 0x4a, 0x0f, 0xc5, 0x04, 0xdd, - 0x58, 0x60, 0x6b, 0x18, 0x1e, 0xdd, 0xb3, 0x9d, 0xa3, 0x48, 0x60, 0x8b, 0x7e, 0x17, 0x3f, 0xe6, - 0xc0, 0x5c, 0x42, 0xbb, 0x08, 0xee, 0xec, 0xa3, 0xa4, 0x36, 0x58, 0x02, 0x93, 0x2f, 0x4d, 0xab, - 0xc9, 0x7a, 0x3d, 0x73, 0x77, 0x63, 0x64, 0x1e, 0x0f, 0xb4, 0xb8, 0x63, 0x5a, 0x4d, 0xc4, 0x6c, - 0xe1, 0x3c, 0x38, 0xd5, 0x71, 0xa9, 0x43, 0x98, 0xde, 0x37, 0xd1, 0xd5, 0xfb, 0xaa, 0xc6, 0x3e, - 0x2d, 0xda, 0x7e, 0x22, 0x0f, 0x58, 0x33, 0x0d, 0x2c, 0xe8, 0x4b, 0x75, 0x60, 0x86, 0xdf, 0xcd, - 0xce, 0x62, 0x70, 0xaa, 0x17, 0x1d, 0xb0, 0x32, 0xc4, 0x61, 0xb4, 0xac, 0xfc, 0x7f, 0x7c, 0xfe, - 0xf5, 0x2a, 0x98, 0xad, 0xfb, 0x66, 0xac, 0x79, 0xcd, 0xa2, 0xda, 0x73, 0x58, 0x07, 0xb3, 0x1d, - 0x93, 0x3c, 0x63, 0x6a, 0x3b, 0x69, 0xf8, 0xf3, 0x2c, 0x74, 0x75, 0x7b, 0xcc, 0xf5, 0xb2, 0x5f, - 0x9c, 0x57, 0x72, 0xe8, 0x6c, 0xc7, 0x4c, 0x94, 0xc2, 0x9f, 0x71, 0xe0, 0x56, 0xc7, 0x24, 0x76, - 0x20, 0x3e, 0x93, 0x30, 0x71, 0x28, 0xd9, 0xb3, 0x89, 0x67, 0x93, 0x66, 0xa4, 0xce, 0x87, 0x1e, - 0x83, 0xe5, 0x49, 0x18, 0xe3, 0x31, 0x9b, 0xc4, 0xaf, 0xe4, 0xd0, 0x5a, 0xc7, 0x4c, 0xc5, 0xc2, - 0x8f, 0x38, 0xb0, 0x96, 0x60, 0x67, 0x34, 0x9b, 0xe4, 0xb9, 0xe9, 0xb8, 0x5e, 0xac, 0xa3, 0x84, - 0xbc, 0x26, 0x19, 0xaf, 0x77, 0xd3, 0x79, 0x8d, 0x7e, 0x32, 0x50, 0x72, 0x68, 0x29, 0xa6, 0x34, - 0x14, 0xd6, 0x3f, 0x56, 0x43, 0xd8, 0xb4, 0x0c, 0x2f, 0x8e, 0xce, 0x54, 0xd6, 0xb1, 0x4a, 0x79, - 0x9f, 0xe8, 0x19, 0xab, 0xd1, 0x58, 0xf8, 0x1d, 0x0e, 0xac, 0x24, 0xd8, 0xb9, 0xd4, 0x23, 0x8d, - 0xf8, 0x29, 0x83, 0xb8, 0xec, 0x15, 0xa1, 0x70, 0x82, 0x91, 0xfa, 0x62, 0x3a, 0xa9, 0x51, 0x0f, - 0x21, 0x4a, 0x0e, 0x2d, 0xc4, 0x6c, 0x86, 0x80, 0xe0, 0x8f, 0x38, 0x70, 0x35, 0x41, 0xc3, 0x09, - 0x2f, 0xf4, 0xa4, 0x11, 0xbd, 0x67, 0x44, 0x54, 0x4e, 0x32, 0x2a, 0x5f, 0x4e, 0xa7, 0x32, 0xee, - 0x45, 0x44, 0xc9, 0xa1, 0x95, 0x98, 0xce, 0x08, 0x60, 0x34, 0x32, 0x4e, 0xf8, 0xc6, 0x40, 0x1a, - 0x76, 0x93, 0x9d, 0xa5, 0x83, 0x37, 0x8e, 0x30, 0x5c, 0xd3, 0xa9, 0x23, 0x93, 0xf2, 0x42, 0x12, - 0x8c, 0xcc, 0x68, 0x10, 0xfc, 0x00, 0x2c, 0x0c, 0x63, 0xd1, 0x3e, 0x0a, 0x19, 0x9c, 0x62, 0x0c, - 0xde, 0xce, 0xce, 0x20, 0xf9, 0xc4, 0xa2, 0xe4, 0x50, 0x61, 0xc0, 0x7b, 0x08, 0x80, 0x5f, 0x07, - 0x8b, 0x83, 0x9e, 0xdb, 0x8e, 0x69, 0x79, 0xa1, 0x6b, 0xc0, 0x5c, 0xbf, 0x93, 0xd5, 0x75, 0xdf, - 0x03, 0x8d, 0x92, 0x43, 0x73, 0x7d, 0xbe, 0xbb, 0x08, 0xd8, 0x02, 0x73, 0x1d, 0x93, 0x34, 0xc3, - 0x83, 0x0b, 0x71, 0x83, 0xe7, 0x0a, 0xc2, 0x1a, 0x2f, 0x9c, 0x66, 0x8e, 0x37, 0x33, 0x28, 0x64, - 0xc9, 0x67, 0x0e, 0x25, 0x87, 0x2e, 0x75, 0xcc, 0xa1, 0x0f, 0x20, 0x1f, 0x05, 0xe9, 0x17, 0xbb, - 0x8b, 0xa7, 0xa6, 0x1b, 0xbd, 0x3b, 0x84, 0x9e, 0xcf, 0x30, 0xcf, 0x5f, 0xc8, 0xe0, 0x79, 0xf8, - 0xcb, 0x45, 0x90, 0x79, 0x29, 0xaf, 0x1b, 0x1f, 0xb2, 0xc4, 0x8b, 0xc9, 0x84, 0xda, 0xa0, 0x1b, - 0xc8, 0x7c, 0x21, 0x91, 0xb3, 0x8c, 0xc8, 0x5b, 0xaf, 0x24, 0x12, 0x06, 0x39, 0x37, 0x46, 0xd4, - 0xfd, 0x7e, 0xb0, 0x80, 0x76, 0x19, 0x84, 0xd7, 0xc2, 0xee, 0xbc, 0x0c, 0x48, 0xcc, 0x30, 0x12, - 0xf7, 0xb3, 0x90, 0x18, 0xa6, 0xd4, 0x29, 0x39, 0xb4, 0x9c, 0xe0, 0x31, 0x54, 0xcc, 0xfb, 0x69, - 0xb0, 0x7a, 0x0e, 0x52, 0x69, 0x44, 0xf7, 0x32, 0xb2, 0xef, 0xb5, 0xdc, 0x90, 0xd0, 0x2c, 0x23, - 0xf4, 0xa5, 0xcf, 0x40, 0x68, 0x50, 0x3b, 0x53, 0x72, 0xe8, 0xea, 0x20, 0xab, 0x2e, 0xce, 0x6b, - 0x85, 0xf2, 0xc1, 0xef, 0x39, 0x70, 0xbf, 0x37, 0x4e, 0x4c, 0x79, 0x21, 0x06, 0x93, 0x5e, 0x48, - 0x33, 0xd2, 0x5e, 0x88, 0x67, 0xdb, 0x2d, 0x97, 0x98, 0x81, 0x1c, 0x15, 0x32, 0xe5, 0x19, 0xd3, - 0x87, 0x99, 0xe2, 0x97, 0x49, 0xe1, 0x52, 0x72, 0xe8, 0x4e, 0x32, 0xa8, 0xd9, 0x64, 0xb1, 0x4f, - 0x38, 0xf0, 0x66, 0xa6, 0x3e, 0x74, 0x87, 0x3b, 0xe0, 0x7f, 0x8e, 0xf1, 0xdf, 0x7e, 0x65, 0xfe, - 0xbd, 0xd7, 0x6a, 0x25, 0x87, 0x36, 0xd2, 0xc8, 0xf7, 0x5d, 0xc4, 0x7f, 0xce, 0x81, 0xdb, 0x49, - 0xe6, 0x46, 0xc7, 0x3f, 0x79, 0xc4, 0x52, 0x4f, 0xe2, 0xcd, 0x24, 0x20, 0x0c, 0x19, 0xe1, 0xf7, - 0x32, 0x10, 0x1e, 0xa7, 0x19, 0x29, 0x39, 0x74, 0xbd, 0x4b, 0x74, 0xac, 0xba, 0xf4, 0x1b, 0x0e, - 0x6c, 0xa6, 0x64, 0xae, 0x69, 0xec, 0x93, 0x36, 0x93, 0x57, 0x42, 0x92, 0xe7, 0x19, 0xc9, 0xd2, - 0xab, 0xe4, 0x6f, 0xaf, 0x52, 0xa3, 0xe4, 0xd0, 0xad, 0x31, 0x49, 0xac, 0x1a, 0xfb, 0x49, 0x59, - 0xe7, 0xc7, 0x1c, 0xb8, 0x9e, 0xa4, 0xda, 0x8e, 0xd5, 0x8f, 0x81, 0xb8, 0x5f, 0x60, 0x0c, 0x1f, - 0x64, 0x60, 0x38, 0x4a, 0x42, 0x51, 0x72, 0xa8, 0xd8, 0xa5, 0x36, 0x52, 0x68, 0xf9, 0x16, 0x07, - 0x56, 0x93, 0x9c, 0x3c, 0xea, 0x7a, 0x3e, 0x1b, 0xab, 0x67, 0x3d, 0xbe, 0x98, 0xba, 0xfb, 0x8d, - 0xd1, 0x33, 0x94, 0x1c, 0x5a, 0xec, 0x32, 0x19, 0x26, 0x78, 0x38, 0x60, 0x3e, 0xc9, 0x21, 0x3a, - 0xe7, 0x46, 0xfb, 0xd0, 0xa5, 0x94, 0x4b, 0xfc, 0x28, 0x41, 0x21, 0xd8, 0x76, 0x47, 0x88, 0x0d, - 0x2d, 0x50, 0xe8, 0x98, 0xfe, 0x21, 0xcc, 0xf0, 0x28, 0xb1, 0xe8, 0x21, 0x71, 0xec, 0x56, 0x74, - 0xdc, 0xb8, 0x9c, 0x72, 0x4d, 0x18, 0x79, 0x95, 0x57, 0x72, 0xe8, 0x42, 0xc7, 0x1c, 0xac, 0x84, - 0x47, 0x6c, 0x93, 0xef, 0xf7, 0xe6, 0x1a, 0x07, 0x91, 0xcb, 0x42, 0xea, 0x08, 0x8f, 0x11, 0x08, - 0x82, 0x8e, 0x0e, 0x07, 0xc0, 0x0f, 0xc1, 0xf2, 0xb0, 0x8e, 0x32, 0x01, 0x21, 0x74, 0x3e, 0x97, - 0xba, 0xc1, 0x8c, 0x15, 0x1f, 0x94, 0x1c, 0xba, 0xd2, 0xdf, 0xeb, 0x2e, 0x04, 0xfe, 0x22, 0x58, - 0x42, 0xfa, 0x19, 0x1c, 0x98, 0xf4, 0x90, 0x34, 0x93, 0x02, 0x45, 0xc8, 0xe6, 0x0a, 0x63, 0x23, - 0x66, 0x65, 0x33, 0x46, 0xe7, 0x50, 0x72, 0xe8, 0x5a, 0x1f, 0xb1, 0xe1, 0x68, 0xf8, 0x6b, 0x0e, - 0x6c, 0x24, 0x53, 0xd0, 0xec, 0x5e, 0x04, 0x89, 0x71, 0xe8, 0x12, 0xdb, 0x6c, 0x36, 0xa2, 0x69, - 0x11, 0x66, 0xe5, 0x7c, 0xea, 0x15, 0x22, 0xdb, 0xd7, 0x05, 0x4a, 0x0e, 0xdd, 0xec, 0x66, 0x69, - 0x12, 0x7b, 0xe8, 0x6a, 0x66, 0xb3, 0xd1, 0xf3, 0x25, 0xc2, 0xc7, 0x1c, 0xb8, 0x36, 0xfc, 0xc8, - 0xd0, 0x74, 0x09, 0x65, 0x57, 0xd6, 0x90, 0xde, 0x42, 0xe6, 0x23, 0xd4, 0xf0, 0x47, 0xff, 0xde, - 0x23, 0x54, 0x8c, 0x69, 0xba, 0xc9, 0x0f, 0x03, 0xbc, 0x20, 0xad, 0xfd, 0xfd, 0xd6, 0xb3, 0xd9, - 0x6e, 0x16, 0x45, 0x31, 0x64, 0xb1, 0x98, 0x3a, 0x75, 0x87, 0xbf, 0xa0, 0x87, 0x19, 0x3d, 0xfc, - 0x75, 0xfd, 0x7d, 0x70, 0xce, 0x60, 0x7a, 0x09, 0xe9, 0x4a, 0x29, 0x85, 0x25, 0xe6, 0x69, 0xb4, - 0xa8, 0x31, 0x54, 0xee, 0x52, 0x72, 0x88, 0x37, 0xfa, 0x2a, 0xa2, 0x25, 0x31, 0x99, 0x02, 0xe1, - 0xc8, 0xb2, 0xe3, 0x71, 0xd8, 0xb3, 0xe5, 0xd4, 0x09, 0x3b, 0x46, 0x08, 0x09, 0x96, 0xc4, 0x71, - 0x4a, 0x49, 0x78, 0x54, 0x1e, 0x42, 0x22, 0x56, 0x01, 0x02, 0x1e, 0x2b, 0xa9, 0x71, 0x1e, 0xaf, - 0x8f, 0x04, 0x71, 0x4e, 0xd1, 0x50, 0xbe, 0xcd, 0xb1, 0x45, 0x24, 0xba, 0x37, 0x7e, 0x2d, 0xf9, - 0x1d, 0x5d, 0x74, 0x65, 0x5c, 0xcd, 0x7a, 0x7b, 0x1d, 0xf5, 0x15, 0x5e, 0xcf, 0xed, 0x75, 0x08, - 0x08, 0x3e, 0x05, 0x61, 0xb0, 0x08, 0x8d, 0xd4, 0xbf, 0x42, 0x91, 0x79, 0x7d, 0x3d, 0x25, 0xec, - 0xbd, 0x6a, 0xa1, 0x92, 0x43, 0xb3, 0x46, 0x6f, 0x39, 0xdc, 0x07, 0x97, 0xc3, 0xb6, 0xfd, 0x05, - 0x2a, 0x29, 0x1a, 0x16, 0xd6, 0x98, 0x8b, 0x7b, 0x29, 0x2e, 0x86, 0x69, 0x77, 0x4a, 0x0e, 0x5d, - 0x34, 0x86, 0xd5, 0x96, 0x4e, 0x82, 0x29, 0xd6, 0xc0, 0xc3, 0xc9, 0xe9, 0x3c, 0x3f, 0xe1, 0xf7, - 0x3b, 0x1e, 0xdc, 0x3d, 0xea, 0xc5, 0xf7, 0x30, 0x36, 0x95, 0xd6, 0x7f, 0x32, 0xd3, 0xfd, 0x8e, - 0x2e, 0x3a, 0xfd, 0xc0, 0x55, 0xb0, 0x28, 0xa9, 0x58, 0xd4, 0x1e, 0xcb, 0x88, 0x20, 0x19, 0x6b, - 0x75, 0x24, 0xf6, 0x7f, 0x01, 0xb0, 0x00, 0x0a, 0x83, 0x10, 0x2c, 0xa3, 0xc7, 0x32, 0xe2, 0x39, - 0xb8, 0x02, 0x16, 0x06, 0x6b, 0x77, 0xea, 0x25, 0x19, 0x55, 0x65, 0x5d, 0xc6, 0x7c, 0x1e, 0xde, - 0x03, 0x9b, 0x83, 0x08, 0x49, 0xd0, 0x85, 0x92, 0x80, 0x65, 0x52, 0xd3, 0xb0, 0xbe, 0x8d, 0x64, - 0x4c, 0xb0, 0x5c, 0xde, 0x22, 0x8a, 0x86, 0x75, 0x59, 0xe2, 0x27, 0xe0, 0x1b, 0xe0, 0xb5, 0x31, - 0x46, 0x95, 0x5d, 0xfc, 0xa8, 0xdc, 0x63, 0x31, 0x09, 0xef, 0x82, 0x8d, 0x71, 0x16, 0x5a, 0x75, - 0x5b, 0x93, 0x4a, 0x3d, 0x36, 0x53, 0xf0, 0x36, 0xb8, 0x91, 0x85, 0x1a, 0x92, 0x30, 0x7f, 0x02, - 0xde, 0x04, 0x57, 0x53, 0x29, 0xf9, 0xc8, 0x93, 0xf0, 0x3a, 0x28, 0x0e, 0x22, 0x85, 0x5a, 0xad, - 0xac, 0x8a, 0x82, 0xae, 0x6a, 0x55, 0xa2, 0xe8, 0x7a, 0x8d, 0x9f, 0x86, 0xd7, 0xc0, 0xea, 0x78, - 0x9c, 0x2e, 0xd6, 0xf8, 0x53, 0xc3, 0x61, 0x4f, 0xd4, 0xaa, 0xa4, 0x3d, 0xc1, 0x44, 0x92, 0xf1, - 0x8e, 0xae, 0xd5, 0x78, 0x00, 0x5f, 0x03, 0x37, 0xc7, 0xf0, 0xc3, 0x8f, 0xca, 0x41, 0xcc, 0x18, - 0xc7, 0xd3, 0x29, 0x03, 0xdc, 0xed, 0xba, 0x2c, 0x61, 0x45, 0xdd, 0xd2, 0xf9, 0x33, 0xf0, 0x4d, - 0xf0, 0x46, 0xa6, 0xf6, 0x93, 0x43, 0x7c, 0x36, 0xc5, 0x0f, 0x92, 0x25, 0xb5, 0x37, 0xf4, 0x33, - 0x59, 0x83, 0xb2, 0x2d, 0xd6, 0xf8, 0xd9, 0x4c, 0x41, 0xf1, 0x91, 0x7c, 0xe6, 0xe1, 0xf1, 0xd1, - 0xe7, 0xe0, 0x03, 0xf0, 0xce, 0x67, 0x19, 0x9e, 0x70, 0x3e, 0x94, 0x65, 0x8c, 0x79, 0x08, 0x5f, - 0x07, 0xb7, 0xb2, 0x18, 0x0b, 0x4f, 0xeb, 0x48, 0xe6, 0xcf, 0xc3, 0x1b, 0x60, 0x6d, 0x0c, 0x5c, - 0xda, 0xad, 0x0a, 0x15, 0x4d, 0x2a, 0xf1, 0x17, 0x52, 0x52, 0x5c, 0x14, 0x30, 0x16, 0xaa, 0x12, - 0x12, 0xc8, 0x8e, 0xbc, 0x8b, 0x6b, 0x82, 0x28, 0x63, 0xfe, 0x62, 0x4a, 0xd4, 0xba, 0x36, 0xc9, - 0x18, 0x5c, 0x82, 0xf7, 0xc1, 0x9b, 0x63, 0xac, 0xe4, 0xb2, 0x80, 0x75, 0x55, 0xc4, 0xb2, 0x80, - 0x44, 0xa5, 0xc7, 0xf2, 0x72, 0xa6, 0x78, 0x87, 0xf6, 0x82, 0xa8, 0xc8, 0x7c, 0x21, 0x65, 0xb4, - 0x02, 0x8b, 0x8a, 0x5c, 0xd1, 0xd0, 0xae, 0x54, 0xe2, 0xe7, 0x32, 0x39, 0x60, 0x23, 0x4b, 0x02, - 0x07, 0x57, 0x52, 0x3a, 0x13, 0x58, 0x88, 0xe5, 0x3a, 0xd6, 0xfb, 0x92, 0x77, 0x1e, 0xae, 0x83, - 0xeb, 0xa9, 0xd9, 0x15, 0x44, 0x71, 0x01, 0x6e, 0x80, 0xf5, 0x4c, 0xf9, 0x15, 0xe0, 0x17, 0x53, - 0x82, 0xd9, 0xc5, 0x57, 0x54, 0x11, 0x69, 0x58, 0xdb, 0xd2, 0xf9, 0x25, 0xf8, 0x36, 0xb8, 0x3b, - 0x2e, 0x98, 0x9a, 0xb8, 0x83, 0x34, 0x41, 0x54, 0xfa, 0xd6, 0xb9, 0xe5, 0x94, 0xdc, 0x8f, 0xd6, - 0x46, 0x41, 0x2f, 0x0b, 0x98, 0x5f, 0x49, 0x99, 0x53, 0xb8, 0xaa, 0x3d, 0xd9, 0x2a, 0x0b, 0x3b, - 0x32, 0xbf, 0x3a, 0xa2, 0x5d, 0x4d, 0x4c, 0x8c, 0xae, 0x84, 0x49, 0x0d, 0x69, 0x5f, 0xdd, 0xe5, - 0x8b, 0x23, 0x52, 0x31, 0x89, 0x56, 0xd4, 0x6d, 0x85, 0x08, 0x8f, 0x05, 0xb5, 0x2c, 0x94, 0xd4, - 0xb2, 0xaa, 0xef, 0xf2, 0x6b, 0xf0, 0x1d, 0x70, 0x2f, 0xc5, 0x8a, 0xcd, 0x10, 0x55, 0x24, 0x48, - 0xde, 0x56, 0xb1, 0x8e, 0xd8, 0xd2, 0xc9, 0x5f, 0x1d, 0xbe, 0x0a, 0x63, 0xa1, 0x52, 0x4e, 0x2e, - 0xb1, 0xfc, 0xb5, 0xf5, 0x5f, 0x72, 0x60, 0xa6, 0xf7, 0xdb, 0x6c, 0xb8, 0x0c, 0xe6, 0x63, 0x53, - 0xac, 0x0b, 0x7a, 0x1d, 0xf7, 0xed, 0x89, 0xf3, 0xe0, 0x72, 0x3f, 0x00, 0xd7, 0x45, 0xd1, 0x9f, - 0xfe, 0xdc, 0xd0, 0xca, 0x1d, 0xb5, 0x56, 0x93, 0x25, 0x3e, 0x0f, 0xe7, 0xc0, 0xc5, 0xfe, 0x4a, - 0x19, 0x21, 0x0d, 0xf1, 0x13, 0xc3, 0xec, 0x84, 0x92, 0x86, 0xd8, 0xf6, 0xb6, 0xfe, 0x07, 0x0e, - 0x4c, 0x88, 0xba, 0x00, 0xcf, 0x83, 0x59, 0x51, 0x17, 0x06, 0xbf, 0x00, 0xf4, 0x0b, 0x85, 0xba, - 0xae, 0x10, 0x51, 0xab, 0x56, 0x65, 0x51, 0xd7, 0xfc, 0xcd, 0xf9, 0x32, 0x38, 0xcf, 0xca, 0x45, - 0x5d, 0x7d, 0xec, 0xef, 0xd9, 0x18, 0xab, 0x5a, 0xd5, 0xdf, 0x93, 0xe3, 0x0a, 0x9f, 0x32, 0x41, - 0xf2, 0xa3, 0xba, 0x8c, 0x75, 0xcc, 0x4f, 0x44, 0x15, 0x35, 0x24, 0x57, 0xd4, 0x7a, 0x85, 0xe0, - 0x7a, 0xad, 0xa6, 0x21, 0x9d, 0x9f, 0x8c, 0x2a, 0x74, 0xe4, 0xcf, 0x13, 0x89, 0x48, 0xf2, 0x63, - 0xd5, 0x5f, 0x60, 0xa6, 0x22, 0xdf, 0xf5, 0xda, 0x36, 0x12, 0x24, 0x99, 0x94, 0x84, 0x6a, 0x55, - 0x46, 0xfc, 0x89, 0xc8, 0xa0, 0xa4, 0x96, 0xcb, 0x6a, 0x75, 0x9b, 0xe0, 0x7a, 0xa5, 0x22, 0xa0, - 0x5d, 0xfe, 0xe4, 0xfa, 0xdf, 0xa6, 0xc0, 0xc5, 0xa1, 0x6f, 0x83, 0xfe, 0x42, 0xa8, 0x56, 0x75, - 0x79, 0x3b, 0x08, 0x21, 0x91, 0xab, 0x48, 0x2b, 0x97, 0xc9, 0x8e, 0x5a, 0xed, 0xff, 0xe2, 0x71, - 0x15, 0x2c, 0x8e, 0x02, 0xe2, 0xb2, 0x20, 0xee, 0xf0, 0x1c, 0xbc, 0x0a, 0x56, 0x46, 0x41, 0x84, - 0x27, 0x98, 0xf8, 0xd7, 0x27, 0x3e, 0xef, 0x6f, 0xad, 0xa3, 0x50, 0x35, 0x61, 0x5b, 0x46, 0x52, - 0x5d, 0xdf, 0xe5, 0x27, 0xc6, 0xf9, 0x93, 0x2b, 0x82, 0x5a, 0xe6, 0x27, 0xfd, 0x73, 0xd0, 0x28, - 0xc8, 0x43, 0x15, 0x09, 0xfc, 0x14, 0x5c, 0x03, 0xcb, 0xa3, 0x10, 0x2c, 0xec, 0x48, 0xe2, 0x4f, - 0xf8, 0x49, 0x3b, 0x0a, 0x54, 0x11, 0x74, 0x5d, 0x46, 0x15, 0x0d, 0xeb, 0xfc, 0xc9, 0x71, 0xdd, - 0xab, 0x60, 0xa2, 0xcb, 0x42, 0x05, 0xf3, 0xd3, 0xe3, 0x50, 0x5a, 0x0d, 0x6f, 0xcb, 0x55, 0x55, - 0xe6, 0x4f, 0x8d, 0xa3, 0xae, 0xed, 0xe8, 0x02, 0x0f, 0xc6, 0x76, 0x4e, 0xa8, 0x6c, 0xf1, 0xa7, - 0xc7, 0xf3, 0x16, 0x15, 0xb5, 0x2a, 0x13, 0x55, 0xe2, 0xcf, 0xc0, 0xb7, 0xc0, 0x9d, 0x74, 0x1c, - 0xd9, 0x56, 0x75, 0xa5, 0x5e, 0x62, 0x79, 0xeb, 0xe7, 0xeb, 0x59, 0xb8, 0x09, 0x6e, 0x67, 0x30, - 0x13, 0x55, 0x24, 0x96, 0x65, 0x51, 0xe5, 0x67, 0xfc, 0x4d, 0x25, 0x9b, 0x9f, 0xb2, 0x50, 0xe2, - 0x67, 0xfd, 0xc5, 0x3b, 0x03, 0xfc, 0xa1, 0x5c, 0xdd, 0x51, 0xab, 0x98, 0xe7, 0x33, 0xe2, 0x85, - 0x2a, 0x56, 0x4b, 0x65, 0x99, 0x3f, 0x57, 0x7a, 0xff, 0x8f, 0x9f, 0x2e, 0x71, 0x7f, 0xfa, 0x74, - 0x89, 0xfb, 0xcb, 0xa7, 0x4b, 0xdc, 0x53, 0x6d, 0xcf, 0xf4, 0x5e, 0x74, 0x9e, 0x6d, 0x34, 0xec, - 0xfd, 0xcd, 0x3d, 0xc7, 0x38, 0x30, 0x03, 0x0d, 0xc1, 0x68, 0x6d, 0xc6, 0xff, 0xb1, 0x65, 0xb4, - 0xcd, 0xcd, 0x3d, 0x6a, 0x6d, 0xb2, 0x7f, 0xcf, 0xda, 0xdc, 0xb3, 0xfb, 0xfe, 0x85, 0xeb, 0x41, - 0xe2, 0xe7, 0xc1, 0x9d, 0x67, 0x27, 0x18, 0xec, 0xde, 0x7f, 0x02, 0x00, 0x00, 0xff, 0xff, 0x7c, - 0x2f, 0x37, 0x7a, 0xf2, 0x35, 0x00, 0x00, + // 3398 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x5b, 0xdd, 0x6f, 0xdb, 0xc8, + 0x76, 0x17, 0x65, 0x3b, 0x71, 0x4e, 0x1c, 0x9b, 0x99, 0x24, 0x8e, 0x1c, 0x7f, 0xcb, 0xf9, 0x74, + 0x72, 0xed, 0x9b, 0x64, 0xef, 0xdd, 0xb4, 0xb9, 0xed, 0x96, 0xa2, 0x68, 0x93, 0xb1, 0x24, 0x2a, + 0x43, 0x2a, 0xa9, 0x03, 0x5c, 0x0c, 0x18, 0x69, 0xe2, 0x10, 0x91, 0x49, 0x5d, 0x92, 0xb2, 0xaf, + 0x51, 0x14, 0x17, 0xfd, 0x44, 0x81, 0xdd, 0x16, 0xed, 0x43, 0x81, 0x02, 0x0b, 0x14, 0x58, 0xb4, + 0x05, 0xfa, 0x50, 0xa0, 0x4f, 0xc5, 0x3e, 0xf7, 0xa9, 0x7d, 0x2c, 0xd0, 0x7f, 0xa0, 0xd8, 0xff, + 0xa0, 0x0f, 0x7d, 0x29, 0x5a, 0xb4, 0xe0, 0xf0, 0x43, 0xd4, 0x27, 0xb9, 0x69, 0x2f, 0x16, 0xf0, + 0xbe, 0x89, 0x33, 0xe7, 0xcc, 0xf9, 0xcd, 0x9c, 0x33, 0x67, 0x66, 0x7e, 0x33, 0x82, 0x07, 0x1e, + 0x6d, 0xd3, 0x8e, 0xed, 0x78, 0xbb, 0x5d, 0xd7, 0x38, 0xa2, 0xf4, 0x84, 0x5a, 0x9e, 0xbb, 0x7b, + 0xf2, 0x38, 0xf9, 0xb9, 0xd3, 0x71, 0x6c, 0xcf, 0x46, 0x37, 0x23, 0xd1, 0x9d, 0x64, 0xdd, 0xc9, + 0xe3, 0xe2, 0x36, 0xa0, 0x86, 0x52, 0x32, 0x2c, 0x8b, 0x3a, 0x62, 0xdb, 0x6c, 0x7e, 0x90, 0xfc, + 0x1a, 0x74, 0x1d, 0x66, 0x8c, 0x36, 0x75, 0xbc, 0x02, 0xb7, 0xc1, 0xdd, 0xbf, 0x84, 0x83, 0x8f, + 0xe2, 0x1e, 0xdc, 0x6f, 0x28, 0xaa, 0xf5, 0xd6, 0x36, 0x9c, 0x96, 0x68, 0x1f, 0x77, 0xda, 0xd4, + 0xa3, 0xfb, 0xb6, 0x6e, 0x97, 0x0d, 0xf7, 0x7d, 0x50, 0xd8, 0x6b, 0xe1, 0x16, 0xcc, 0x76, 0x5d, + 0xea, 0x58, 0xc6, 0x31, 0x0d, 0x1b, 0x89, 0xbf, 0x8b, 0x77, 0x60, 0x2b, 0x6e, 0x47, 0x68, 0xb5, + 0xf6, 0x4c, 0xc7, 0xf5, 0x30, 0x75, 0xed, 0xae, 0xd3, 0xa4, 0xbd, 0x26, 0x8a, 0xdb, 0x09, 0x73, + 0x83, 0x62, 0x15, 0xc3, 0x4b, 0x02, 0x2e, 0x7e, 0x06, 0x9b, 0xb1, 0xac, 0x46, 0x3d, 0xd1, 0xa1, + 0x2d, 0x6a, 0x79, 0xa6, 0xd1, 0xd6, 0xba, 0x6f, 0x8f, 0x4d, 0x2f, 0x1d, 0x53, 0xb2, 0x81, 0x97, + 0x5d, 0xea, 0x7a, 0xa6, 0x6d, 0x59, 0x86, 0xe9, 0xd0, 0xac, 0x0d, 0xfc, 0x36, 0xdc, 0x89, 0x1b, + 0xc0, 0xf4, 0xc8, 0x74, 0x7d, 0x80, 0xef, 0x8d, 0x76, 0x9b, 0x5a, 0x47, 0x59, 0x1b, 0x41, 0x4b, + 0x30, 0x7b, 0xfc, 0xce, 0x20, 0xde, 0x59, 0x87, 0x16, 0xf2, 0xac, 0xee, 0xe2, 0xf1, 0x3b, 0x43, + 0x3f, 0xeb, 0x50, 0xb4, 0x0a, 0xd0, 0xb6, 0x8f, 0x4c, 0x8b, 0xbc, 0x6b, 0xdb, 0xa7, 0x85, 0x29, + 0x56, 0x79, 0x89, 0x95, 0xec, 0xb5, 0xed, 0xd3, 0x00, 0x3f, 0xa6, 0x4d, 0xfb, 0x84, 0x3a, 0x67, + 0xa2, 0xdd, 0xa2, 0xae, 0x68, 0x5b, 0x9e, 0x69, 0x75, 0x69, 0x46, 0xa7, 0x3c, 0x87, 0xd5, 0xa1, + 0x06, 0x3a, 0x67, 0x19, 0x95, 0x7f, 0x02, 0x6b, 0x03, 0xca, 0x75, 0xc7, 0xb4, 0xbc, 0x8c, 0xda, + 0x45, 0xe0, 0xcb, 0xa6, 0xcb, 0x94, 0xab, 0xd4, 0x33, 0x5a, 0x86, 0x67, 0xa0, 0x79, 0xc8, 0x9b, + 0xad, 0x50, 0x32, 0x6f, 0xb6, 0x8a, 0x06, 0x14, 0x22, 0x99, 0x28, 0x06, 0x62, 0x59, 0x09, 0x66, + 0x9d, 0xb0, 0x8c, 0x69, 0xcc, 0x3f, 0x79, 0xb0, 0x33, 0x26, 0xde, 0x77, 0x06, 0x1b, 0xc1, 0xb1, + 0x6a, 0xf1, 0x03, 0xa0, 0xa8, 0x56, 0xf3, 0x68, 0x47, 0xf3, 0x0c, 0xaf, 0xeb, 0xa2, 0xcf, 0xe0, + 0x82, 0xcb, 0x7e, 0x85, 0x4d, 0xdf, 0x4b, 0x6d, 0x3a, 0x50, 0xc4, 0xa1, 0x9a, 0x3f, 0x97, 0xa8, + 0xe3, 0xd8, 0x4e, 0xe8, 0xd0, 0xe0, 0xa3, 0xf8, 0xd7, 0x1c, 0x2c, 0x36, 0x94, 0x84, 0x8a, 0xe3, + 0xd1, 0x56, 0x30, 0x54, 0x12, 0xcc, 0x1e, 0x87, 0x5d, 0x63, 0x36, 0x2f, 0x67, 0xe8, 0x4e, 0x34, + 0x16, 0x38, 0x56, 0x45, 0x62, 0x0c, 0x3c, 0xcf, 0x1a, 0x79, 0x98, 0x01, 0x78, 0xd4, 0xeb, 0x08, + 0x7c, 0xf1, 0xbf, 0x39, 0xd8, 0xe8, 0xc1, 0x8c, 0x06, 0x4d, 0xa3, 0x6d, 0xda, 0xf4, 0x67, 0xc8, + 0xff, 0x2b, 0xe0, 0x6a, 0xc2, 0x8d, 0x01, 0xe4, 0xc7, 0x99, 0xdd, 0xd8, 0x6b, 0x2e, 0x6a, 0x22, + 0xd1, 0xff, 0xa9, 0x8f, 0xef, 0xff, 0x1f, 0xe4, 0xfd, 0x24, 0x14, 0x09, 0x28, 0x96, 0x47, 0x8f, + 0x1c, 0xc3, 0xef, 0xb9, 0xf0, 0x5a, 0x53, 0x95, 0xb2, 0x28, 0xda, 0x96, 0x45, 0x9b, 0xde, 0xb9, + 0x1f, 0x87, 0xaf, 0xf3, 0xc9, 0x38, 0x28, 0x1b, 0x9e, 0xf1, 0xd6, 0x70, 0x29, 0x2e, 0x6b, 0x92, + 0xe5, 0xd8, 0xed, 0xf6, 0x79, 0xef, 0x3f, 0x7a, 0x06, 0x05, 0x97, 0x05, 0x3d, 0x6d, 0x91, 0xa8, + 0x65, 0x97, 0x34, 0xed, 0xae, 0xe5, 0x15, 0xa6, 0x37, 0xb8, 0xfb, 0x53, 0x78, 0x31, 0xaa, 0x8f, + 0xa0, 0xb8, 0xa2, 0x5f, 0x5b, 0x7c, 0x01, 0x85, 0x86, 0x22, 0x1a, 0xed, 0xb6, 0x6e, 0x0b, 0x6c, + 0xce, 0x24, 0x92, 0xe2, 0x0e, 0x4c, 0x35, 0xc3, 0xb1, 0x9a, 0x7f, 0xb2, 0x32, 0x16, 0x97, 0xa8, + 0x0b, 0xd8, 0x17, 0x2c, 0xfe, 0xf1, 0x0c, 0xac, 0x24, 0xbc, 0x40, 0x3b, 0x6d, 0xfb, 0x4c, 0xa3, + 0xce, 0x89, 0xd9, 0xa4, 0xe7, 0xde, 0x03, 0x47, 0x70, 0xa5, 0xc5, 0x3a, 0x4c, 0x8e, 0xa9, 0xf7, + 0xde, 0x6e, 0xb1, 0x61, 0x9f, 0x7f, 0x52, 0x1a, 0xdb, 0xd6, 0xa4, 0x81, 0xda, 0x09, 0x8a, 0xaa, + 0xac, 0x25, 0x3c, 0xd7, 0x4a, 0x7c, 0x21, 0x03, 0x2e, 0x87, 0x86, 0xd8, 0x32, 0x3c, 0xc3, 0xcc, + 0xfc, 0xc6, 0xff, 0xc5, 0x8c, 0xbf, 0x7e, 0x63, 0x68, 0xc5, 0xbf, 0x8b, 0x04, 0xe6, 0x92, 0x00, + 0xd0, 0x2a, 0x2c, 0x95, 0xa5, 0x7a, 0x45, 0x3d, 0x24, 0x55, 0x49, 0x97, 0xd5, 0x32, 0x69, 0xd4, + 0xb4, 0xba, 0x24, 0x2a, 0x7b, 0x8a, 0x54, 0xe6, 0x73, 0x68, 0x11, 0x50, 0x7f, 0xb5, 0xd0, 0xd0, + 0x55, 0x9e, 0x43, 0x05, 0xb8, 0xde, 0x5f, 0x5e, 0x15, 0x6a, 0x0d, 0xa1, 0xc2, 0xe7, 0x8b, 0x14, + 0xa0, 0x67, 0x1a, 0x2d, 0xc3, 0xcd, 0x50, 0x4e, 0x3f, 0xac, 0x4b, 0x03, 0x8d, 0xaf, 0xc1, 0xad, + 0x64, 0xa5, 0x52, 0xd3, 0x74, 0xa1, 0x52, 0x21, 0x9a, 0x88, 0x95, 0xba, 0xce, 0x73, 0xe8, 0x16, + 0x2c, 0x26, 0xeb, 0x85, 0xaa, 0xf0, 0x46, 0xad, 0x11, 0x49, 0xd4, 0xf8, 0x7c, 0xf1, 0xbf, 0x38, + 0x58, 0x1f, 0x91, 0x15, 0xc2, 0xdd, 0xcf, 0xb9, 0x4f, 0x8a, 0xbf, 0x93, 0x87, 0xdb, 0xc3, 0xdd, + 0x17, 0x6d, 0xeb, 0x9d, 0x79, 0xd4, 0x75, 0x68, 0x55, 0xaf, 0x68, 0xe7, 0x7e, 0x0c, 0xfe, 0x24, + 0x0f, 0x8f, 0x93, 0x53, 0xc0, 0xfd, 0xe0, 0xd9, 0x1d, 0x3f, 0xd1, 0x9d, 0xd0, 0xb2, 0xe9, 0xd0, + 0xa6, 0x67, 0x3b, 0x67, 0xba, 0x6d, 0xb7, 0x5d, 0xc5, 0x72, 0x3d, 0xe3, 0xfc, 0xaf, 0x14, 0xc5, + 0xcf, 0xf3, 0xb0, 0x93, 0x36, 0x20, 0x71, 0x88, 0x9c, 0xfb, 0xd1, 0xf8, 0xbb, 0x3c, 0xdc, 0xed, + 0x8d, 0x86, 0xd0, 0xf5, 0xec, 0xe8, 0x77, 0x62, 0xa1, 0x3c, 0xf7, 0x6b, 0xd7, 0x3d, 0x58, 0x18, + 0xbd, 0x69, 0x98, 0x77, 0xfa, 0x37, 0x0b, 0x7f, 0x98, 0x87, 0x07, 0x13, 0x32, 0x8a, 0x22, 0x54, + 0xeb, 0x76, 0xdb, 0x6c, 0x9e, 0x9d, 0xfb, 0xb8, 0xf9, 0x1f, 0x0e, 0x8a, 0xbd, 0x81, 0xf0, 0x0f, + 0x93, 0x4d, 0xb3, 0x63, 0xb4, 0xdd, 0xef, 0xcf, 0xcc, 0xf9, 0x4f, 0xce, 0x3f, 0x90, 0x47, 0x02, + 0x3a, 0x75, 0xbd, 0xf0, 0xac, 0xf1, 0x7d, 0x38, 0x76, 0xfd, 0x07, 0xe7, 0xef, 0x9a, 0x23, 0x81, + 0x88, 0x6b, 0x6a, 0x9d, 0xfb, 0x7e, 0x2f, 0xc3, 0x52, 0x43, 0x11, 0x1d, 0x6a, 0x78, 0xb4, 0x46, + 0x4f, 0xb1, 0xdd, 0x4e, 0xf2, 0x61, 0xeb, 0x7e, 0x40, 0xf4, 0x55, 0x6a, 0xc6, 0x49, 0x52, 0x60, + 0xd3, 0xdf, 0x8d, 0xf5, 0x6b, 0x1b, 0x56, 0x93, 0xb6, 0x13, 0x22, 0x8f, 0x60, 0x7b, 0x40, 0xe4, + 0x95, 0x49, 0x4f, 0xcb, 0x76, 0xb3, 0x7b, 0x4c, 0x2d, 0xcf, 0xe8, 0x3f, 0x9f, 0x14, 0xff, 0x81, + 0x83, 0x1b, 0x82, 0xeb, 0x9a, 0x7e, 0xec, 0x31, 0x17, 0xc4, 0xb1, 0x77, 0x0f, 0x16, 0x9a, 0xb6, + 0x75, 0x42, 0x1d, 0x97, 0xe9, 0x90, 0x98, 0xab, 0x99, 0x4f, 0x16, 0x2b, 0x2d, 0xb4, 0x09, 0x73, + 0x9e, 0xed, 0x19, 0x6d, 0xe2, 0xd9, 0x1f, 0xa8, 0x15, 0x70, 0x11, 0x53, 0xf8, 0x32, 0x2b, 0xd3, + 0x59, 0x11, 0xda, 0x82, 0x2b, 0x1d, 0xc7, 0x3e, 0xee, 0x78, 0x91, 0xcc, 0x14, 0x93, 0x99, 0x0b, + 0x0a, 0x43, 0xa1, 0x87, 0x70, 0xb5, 0x19, 0x63, 0x88, 0x04, 0x83, 0x24, 0xca, 0xf7, 0x2a, 0x02, + 0xe1, 0xe2, 0xbf, 0x72, 0x70, 0x3d, 0xc0, 0x2d, 0xfd, 0x9c, 0x36, 0xbb, 0x1f, 0x01, 0x7b, 0x15, + 0xc0, 0xb2, 0x5b, 0x34, 0x4c, 0xd6, 0x01, 0xe8, 0x4b, 0x7e, 0x09, 0xcb, 0xd3, 0x43, 0xbd, 0x9a, + 0xca, 0xd0, 0xab, 0xe9, 0xac, 0xbd, 0x9a, 0x19, 0xd3, 0xab, 0x67, 0x70, 0x2b, 0xe8, 0x54, 0x8d, + 0x9e, 0x8a, 0x09, 0xb8, 0x31, 0xc1, 0xd6, 0x34, 0x3c, 0x7a, 0x64, 0x3b, 0x67, 0x11, 0xc1, 0x16, + 0x7d, 0x17, 0xff, 0x9e, 0x83, 0x6b, 0x81, 0xaa, 0xd0, 0x6c, 0x52, 0xd7, 0xc5, 0xf4, 0x67, 0x5d, + 0xea, 0x7a, 0x3e, 0xc6, 0x28, 0x7e, 0x83, 0xc3, 0x4e, 0xa0, 0x38, 0x17, 0x15, 0xb2, 0xd3, 0xc3, + 0x77, 0xe2, 0xc1, 0x2f, 0x39, 0x98, 0x8b, 0x10, 0xfb, 0xc5, 0x68, 0x11, 0x2e, 0x18, 0xec, 0x57, + 0x88, 0x31, 0xfc, 0xfa, 0x6e, 0xd0, 0x7d, 0xc1, 0xc1, 0x52, 0x82, 0x0b, 0x0a, 0x38, 0x90, 0x71, + 0xd4, 0x25, 0x2a, 0xc1, 0xf4, 0x07, 0xd3, 0x6a, 0x31, 0x68, 0xf3, 0x4f, 0x76, 0xc6, 0xe6, 0x85, + 0xa1, 0x16, 0x0f, 0x4c, 0xab, 0x85, 0x99, 0x2e, 0x5a, 0x86, 0x4b, 0x5d, 0x97, 0x3a, 0x84, 0xf1, + 0xa7, 0x53, 0x3d, 0xfe, 0xb4, 0x66, 0x1c, 0xd3, 0xa2, 0xed, 0x27, 0x86, 0x21, 0x6d, 0xc6, 0x29, + 0x06, 0xb1, 0x51, 0x1b, 0xca, 0x98, 0x4f, 0xb2, 0xa3, 0x18, 0x4e, 0x9d, 0x45, 0x07, 0x36, 0x46, + 0x18, 0x8c, 0xd2, 0xf4, 0x2f, 0xc7, 0xe6, 0x57, 0x77, 0x61, 0xa1, 0xe1, 0xab, 0xb1, 0xe6, 0x55, + 0x8b, 0xaa, 0xef, 0x50, 0x03, 0x16, 0xba, 0x26, 0x79, 0xcb, 0x6e, 0x2f, 0x48, 0xd3, 0xcf, 0x5b, + 0xa1, 0xa9, 0x87, 0x13, 0x8e, 0xeb, 0x83, 0x97, 0x1d, 0x72, 0x0e, 0x5f, 0xe9, 0x9a, 0x89, 0x52, + 0xf4, 0x25, 0x07, 0x0f, 0xba, 0x26, 0xb1, 0x03, 0x32, 0x9f, 0x84, 0xee, 0xa7, 0xe4, 0xc8, 0x26, + 0x9e, 0x4d, 0x5a, 0xd1, 0x6d, 0x47, 0x68, 0x31, 0x48, 0xf7, 0xc2, 0x04, 0x8b, 0xd9, 0xae, 0x4c, + 0xe4, 0x1c, 0xde, 0xea, 0x9a, 0xa9, 0xb2, 0xe8, 0x73, 0x0e, 0xb6, 0x12, 0xe8, 0x8c, 0x56, 0x8b, + 0xbc, 0x33, 0x1d, 0xd7, 0x8b, 0x79, 0xa9, 0x10, 0xd7, 0x34, 0xc3, 0xf5, 0x93, 0x74, 0x5c, 0xe3, + 0xaf, 0x60, 0xe4, 0x1c, 0x5e, 0x8b, 0x21, 0x8d, 0x14, 0x1b, 0x1c, 0xab, 0x11, 0x68, 0xda, 0x86, + 0x17, 0x7b, 0x67, 0x26, 0xeb, 0x58, 0xa5, 0xdc, 0xf7, 0xf4, 0x8d, 0xd5, 0x78, 0x59, 0xf4, 0xfb, + 0x1c, 0x6c, 0x24, 0xd0, 0xb9, 0xd4, 0x23, 0xcd, 0xf8, 0x6a, 0x88, 0xb8, 0xec, 0x56, 0xa6, 0x70, + 0x81, 0x81, 0xfa, 0xd5, 0x74, 0x50, 0xe3, 0x2e, 0x96, 0xe4, 0x1c, 0x5e, 0x89, 0xd1, 0x8c, 0x10, + 0x42, 0x7f, 0xca, 0xc1, 0xed, 0x04, 0x0c, 0x27, 0x24, 0x48, 0x48, 0x33, 0xba, 0x1f, 0x8a, 0xa0, + 0x5c, 0x64, 0x50, 0x7e, 0x3d, 0x1d, 0xca, 0xa4, 0x1b, 0x26, 0x39, 0x87, 0x37, 0x62, 0x38, 0x63, + 0x04, 0xa3, 0x91, 0x71, 0xc2, 0x3b, 0x1b, 0xd2, 0xb4, 0x5b, 0xec, 0x6c, 0x12, 0xdc, 0x19, 0x85, + 0xee, 0x9a, 0x4d, 0x1d, 0x99, 0x94, 0x1b, 0xa7, 0x60, 0x64, 0xc6, 0x0b, 0xa1, 0x9f, 0xc3, 0xca, + 0x28, 0x14, 0x9d, 0xb3, 0x10, 0xc1, 0x25, 0x86, 0xe0, 0xc7, 0xd9, 0x11, 0x24, 0xaf, 0xac, 0xe4, + 0x1c, 0x2e, 0x0c, 0x59, 0x0f, 0x05, 0xd0, 0x6f, 0xc1, 0xea, 0xb0, 0xe5, 0x8e, 0x63, 0x5a, 0x5e, + 0x68, 0x1a, 0x98, 0xe9, 0x4f, 0xb3, 0x9a, 0x1e, 0xb8, 0xf0, 0x92, 0x73, 0x78, 0x69, 0xc0, 0x76, + 0x4f, 0x02, 0xb5, 0x61, 0xa9, 0x6b, 0x92, 0x56, 0xb8, 0x11, 0x24, 0x6e, 0x70, 0xfd, 0x43, 0x58, + 0xe3, 0x85, 0xcb, 0xcc, 0xf0, 0x6e, 0x06, 0xc6, 0x31, 0x79, 0x6d, 0x24, 0xe7, 0xf0, 0x62, 0xd7, + 0x1c, 0x79, 0xa1, 0xf4, 0x79, 0x10, 0x7e, 0xb1, 0xb9, 0x78, 0x6a, 0xba, 0xd1, 0x3d, 0x4e, 0x68, + 0x79, 0x8e, 0x59, 0xfe, 0x95, 0x0c, 0x96, 0x47, 0xdf, 0x04, 0x05, 0x91, 0x97, 0x72, 0x5b, 0xf4, + 0x0b, 0x16, 0x78, 0x31, 0x98, 0x90, 0x6b, 0x75, 0x03, 0xda, 0x34, 0x04, 0x72, 0x85, 0x01, 0xf9, + 0xd1, 0x47, 0x91, 0xae, 0x41, 0xcc, 0x4d, 0x20, 0xc9, 0xff, 0x28, 0x48, 0xa0, 0x3d, 0x04, 0xe1, + 0x31, 0xbb, 0x37, 0x2f, 0x03, 0x10, 0xf3, 0x0c, 0xc4, 0xb3, 0x2c, 0x20, 0x46, 0x31, 0x9f, 0x72, + 0x0e, 0xaf, 0x27, 0x70, 0x8c, 0x24, 0x47, 0xff, 0x22, 0xc8, 0x9e, 0xc3, 0x50, 0x9a, 0xd1, 0x39, + 0x97, 0x1c, 0x7b, 0x6d, 0x37, 0x04, 0xb4, 0xc0, 0x00, 0xfd, 0xda, 0xb7, 0x00, 0x34, 0xcc, 0x45, + 0xca, 0x39, 0x7c, 0x7b, 0x18, 0x55, 0x4f, 0xce, 0x6b, 0x87, 0x74, 0xcc, 0x3f, 0x72, 0xf0, 0xac, + 0xdf, 0x4f, 0x8c, 0xc9, 0x22, 0x06, 0xa3, 0xb2, 0x48, 0x2b, 0xe2, 0xb2, 0x88, 0x67, 0xdb, 0x6d, + 0x97, 0x98, 0x01, 0xbd, 0x17, 0x22, 0xe5, 0x19, 0xd2, 0x17, 0x99, 0xfc, 0x97, 0x89, 0x31, 0x94, + 0x73, 0xf8, 0x71, 0xd2, 0xa9, 0xd9, 0x68, 0xc6, 0xaf, 0x39, 0xf8, 0x24, 0x53, 0x1f, 0x7a, 0xc3, + 0x1d, 0xe0, 0xbf, 0xca, 0xf0, 0xef, 0x7f, 0x34, 0xfe, 0x7e, 0x9a, 0x42, 0xce, 0xe1, 0x9d, 0x34, + 0xf0, 0x03, 0xc4, 0xc6, 0x5f, 0x72, 0xf0, 0x30, 0x89, 0xdc, 0xe8, 0xfa, 0x3b, 0x8f, 0x98, 0x3a, + 0x4b, 0xdc, 0x41, 0x05, 0x80, 0x11, 0x03, 0xfc, 0x59, 0x06, 0xc0, 0x93, 0x38, 0x38, 0x39, 0x87, + 0xef, 0xf6, 0x80, 0x4e, 0x64, 0xeb, 0xfe, 0x96, 0x83, 0xdd, 0x94, 0xc8, 0x35, 0x8d, 0x63, 0xd2, + 0x61, 0x74, 0x55, 0x08, 0xf2, 0x1a, 0x03, 0x59, 0xfa, 0x98, 0xf8, 0xed, 0x67, 0xbe, 0xe4, 0x1c, + 0x7e, 0x30, 0x21, 0x88, 0x15, 0xe3, 0x38, 0x49, 0x93, 0xfd, 0x19, 0x07, 0x77, 0x93, 0x50, 0x3b, + 0x31, 0x9b, 0x34, 0xe4, 0xf7, 0xeb, 0x0c, 0xe1, 0xf3, 0x0c, 0x08, 0xc7, 0x51, 0x52, 0x72, 0x0e, + 0x17, 0x7b, 0xd0, 0xc6, 0x12, 0x57, 0xbf, 0xcb, 0xc1, 0x66, 0x12, 0x93, 0x47, 0x5d, 0xcf, 0x47, + 0x63, 0xf5, 0xe5, 0xe3, 0x1b, 0xa9, 0xab, 0xdf, 0x04, 0x7e, 0x48, 0xce, 0xe1, 0xd5, 0x1e, 0x92, + 0x51, 0x04, 0x92, 0x03, 0xcb, 0x49, 0x0c, 0xd1, 0x3e, 0x37, 0x5a, 0x87, 0x16, 0x53, 0x48, 0x91, + 0x71, 0x04, 0x4d, 0xb0, 0xec, 0x8e, 0x21, 0x6f, 0xda, 0x50, 0xe8, 0x9a, 0xfe, 0x26, 0xcc, 0xf0, + 0x28, 0xb1, 0xe8, 0x29, 0x71, 0xec, 0x76, 0xb4, 0xdd, 0xb8, 0x99, 0x72, 0x4c, 0x18, 0x4b, 0x8d, + 0xc8, 0x39, 0x7c, 0xbd, 0x6b, 0x0e, 0x57, 0xa2, 0x33, 0xb6, 0xc8, 0x0f, 0x5a, 0x73, 0x8d, 0x93, + 0xc8, 0x64, 0x21, 0x75, 0x84, 0x27, 0x10, 0x2e, 0x41, 0x47, 0x47, 0x0b, 0xa0, 0x5f, 0xc0, 0xfa, + 0xa8, 0x8e, 0x32, 0x42, 0x26, 0x34, 0xbe, 0x94, 0xba, 0xc0, 0x4c, 0x24, 0x73, 0xe4, 0x1c, 0xbe, + 0x35, 0xd8, 0xeb, 0x9e, 0x08, 0xfa, 0x2a, 0x48, 0x21, 0x83, 0x08, 0x4e, 0x4c, 0x7a, 0x4a, 0x5a, + 0x49, 0xc2, 0x27, 0x44, 0x73, 0x8b, 0xa1, 0x11, 0xb3, 0xa2, 0x99, 0xc0, 0x1b, 0xc9, 0x39, 0x7c, + 0x67, 0x00, 0xd8, 0x68, 0x69, 0xf4, 0x37, 0x1c, 0xec, 0x24, 0x43, 0xd0, 0xec, 0x1d, 0x04, 0x89, + 0x71, 0xea, 0x12, 0xdb, 0x6c, 0x35, 0xa3, 0x69, 0x11, 0x46, 0xe5, 0x72, 0xea, 0x11, 0x22, 0xdb, + 0x6b, 0x0d, 0x39, 0x87, 0xef, 0xf7, 0xa2, 0x34, 0x29, 0x7b, 0xea, 0xaa, 0x66, 0xab, 0xd9, 0xf7, + 0xb2, 0xe3, 0x0b, 0x0e, 0xee, 0x8c, 0xde, 0x32, 0xb4, 0x5c, 0x42, 0xd9, 0x91, 0x35, 0x84, 0xb7, + 0x92, 0x79, 0x0b, 0x35, 0xfa, 0x11, 0x45, 0xff, 0x16, 0x2a, 0x96, 0x69, 0xb9, 0xc9, 0x87, 0x16, + 0x5e, 0x10, 0xd6, 0xfe, 0x7a, 0xeb, 0xd9, 0x24, 0x60, 0x42, 0x02, 0x2f, 0x86, 0x28, 0x56, 0x53, + 0xa7, 0xee, 0xe8, 0x17, 0x09, 0x61, 0x44, 0x8f, 0x7e, 0xad, 0xf0, 0x53, 0xb8, 0x6a, 0x30, 0x4a, + 0x86, 0xf4, 0x08, 0x91, 0xc2, 0x1a, 0xb3, 0x34, 0x9e, 0xd4, 0x18, 0x49, 0x1f, 0xca, 0x39, 0xcc, + 0x1b, 0x03, 0x15, 0x51, 0x4a, 0x4c, 0x86, 0x40, 0x38, 0xb2, 0x6c, 0x7b, 0x1c, 0xf6, 0x6c, 0x3d, + 0x75, 0xc2, 0x4e, 0x20, 0x42, 0x82, 0x94, 0x38, 0x89, 0x29, 0x09, 0xb7, 0xca, 0x23, 0x40, 0xc4, + 0x2c, 0x40, 0x80, 0x63, 0x23, 0xd5, 0xcf, 0x93, 0xf9, 0x91, 0xc0, 0xcf, 0x29, 0x1c, 0xca, 0xef, + 0x71, 0x2c, 0x89, 0x44, 0xe7, 0xc6, 0x9f, 0x25, 0xdf, 0x25, 0x46, 0x47, 0xc6, 0xcd, 0xac, 0xa7, + 0xd7, 0x71, 0xaf, 0x1a, 0xfb, 0x4e, 0xaf, 0x23, 0x84, 0xd0, 0x1b, 0x08, 0x9d, 0x45, 0x68, 0xc4, + 0xa6, 0x16, 0x8a, 0xcc, 0xea, 0x0f, 0x52, 0xdc, 0xde, 0xcf, 0xbe, 0xca, 0x39, 0xbc, 0x60, 0xf4, + 0x97, 0xa3, 0x63, 0xb8, 0x19, 0xb6, 0xed, 0x27, 0xa8, 0x24, 0x09, 0x5b, 0xd8, 0x62, 0x26, 0x9e, + 0xa6, 0x98, 0x18, 0xc5, 0x85, 0xca, 0x39, 0x7c, 0xc3, 0x18, 0x55, 0x8b, 0xde, 0x42, 0x58, 0x41, + 0x0c, 0x46, 0x84, 0x12, 0x27, 0x60, 0x42, 0x0b, 0x77, 0x99, 0xb1, 0x47, 0x29, 0xc6, 0xfa, 0xd8, + 0x53, 0x39, 0x87, 0xaf, 0x19, 0x23, 0x48, 0xd5, 0x0a, 0x5c, 0x89, 0x6d, 0xb0, 0x8e, 0xdc, 0x63, + 0x6d, 0xdf, 0x49, 0x6d, 0xdb, 0x17, 0x96, 0x73, 0x78, 0xce, 0x48, 0x7c, 0x97, 0x2e, 0xc2, 0x0c, + 0x93, 0x7c, 0x31, 0x3d, 0x9b, 0xe7, 0xa7, 0x7c, 0x4f, 0xc5, 0xe1, 0x70, 0x44, 0xbd, 0xf8, 0xe4, + 0xc8, 0x26, 0xff, 0xf6, 0x9f, 0xcf, 0xf7, 0x5e, 0x52, 0x46, 0xfb, 0x35, 0xb4, 0x09, 0xab, 0x65, + 0x45, 0x13, 0xd5, 0x57, 0x12, 0x26, 0x58, 0xd2, 0xd4, 0x06, 0x16, 0x07, 0xdf, 0x80, 0xac, 0x40, + 0x61, 0x58, 0x44, 0x93, 0xf0, 0x2b, 0x09, 0xf3, 0x1c, 0xda, 0x80, 0x95, 0xe1, 0xda, 0x83, 0x46, + 0x49, 0xc2, 0x35, 0x49, 0x97, 0x34, 0x3e, 0x8f, 0x9e, 0xc2, 0xee, 0xb0, 0x44, 0x59, 0xd0, 0x85, + 0x92, 0xa0, 0x49, 0xa4, 0xae, 0x6a, 0xfa, 0x3e, 0x96, 0x34, 0xa2, 0x49, 0x95, 0x3d, 0x22, 0xab, + 0x9a, 0x2e, 0x95, 0xf9, 0x29, 0xf4, 0x43, 0x78, 0x34, 0x41, 0xa9, 0x7a, 0xa8, 0xbd, 0xac, 0xf4, + 0x69, 0x4c, 0xa3, 0x27, 0xb0, 0x33, 0x49, 0x43, 0xad, 0xed, 0xab, 0xe5, 0x52, 0x9f, 0xce, 0x0c, + 0x7a, 0x08, 0xf7, 0xb2, 0x40, 0xc3, 0x65, 0x8d, 0xbf, 0x80, 0xee, 0xc3, 0xed, 0x54, 0x48, 0xbe, + 0xe4, 0x45, 0x74, 0x17, 0x8a, 0xc3, 0x92, 0x42, 0xbd, 0x5e, 0x51, 0x44, 0x41, 0x57, 0xd4, 0x1a, + 0x91, 0x75, 0xbd, 0xce, 0xcf, 0xa2, 0x3b, 0xb0, 0x39, 0x59, 0x4e, 0x17, 0xeb, 0xfc, 0xa5, 0xd1, + 0x62, 0xaf, 0x95, 0x5a, 0x59, 0x7d, 0xad, 0x91, 0xb2, 0xa4, 0x1d, 0xe8, 0x6a, 0x9d, 0x07, 0xf4, + 0x08, 0xee, 0x4f, 0xc0, 0xa7, 0xbd, 0xac, 0x04, 0x3e, 0x63, 0x18, 0x2f, 0xa7, 0x0c, 0x70, 0xaf, + 0xeb, 0x52, 0x59, 0x93, 0x95, 0x3d, 0x9d, 0x9f, 0x43, 0x9f, 0xc0, 0x0f, 0x33, 0xb5, 0x9f, 0x1c, + 0xe2, 0x2b, 0x29, 0x76, 0xb0, 0x54, 0x56, 0xfa, 0x5d, 0x3f, 0x9f, 0xd5, 0x29, 0xfb, 0x62, 0x9d, + 0x5f, 0xc8, 0xe4, 0x14, 0x5f, 0x92, 0xcf, 0x3c, 0x3c, 0xbe, 0xf4, 0x55, 0xf4, 0x1c, 0x3e, 0xfd, + 0x36, 0xc3, 0x13, 0xce, 0x87, 0x8a, 0xa4, 0x69, 0x3c, 0x42, 0x3f, 0x80, 0x07, 0x59, 0x94, 0x85, + 0x37, 0x0d, 0x2c, 0xf1, 0xd7, 0xd0, 0x3d, 0xd8, 0x9a, 0x20, 0x5e, 0x3e, 0xac, 0x09, 0x55, 0xb5, + 0x5c, 0xe2, 0xaf, 0xa7, 0x84, 0xb8, 0x28, 0x68, 0x9a, 0x50, 0x2b, 0x63, 0x81, 0x1c, 0x48, 0x87, + 0x5a, 0x5d, 0x10, 0x25, 0x8d, 0xbf, 0x91, 0xe2, 0xb5, 0x9e, 0x4e, 0xd2, 0x07, 0x8b, 0xe8, 0x19, + 0x7c, 0x32, 0x41, 0x4b, 0xaa, 0x08, 0x9a, 0xae, 0x88, 0x9a, 0x24, 0x60, 0x51, 0xee, 0xd3, 0xbc, + 0x99, 0xc9, 0xdf, 0xa1, 0xbe, 0x20, 0xca, 0x12, 0x5f, 0x48, 0x19, 0xad, 0x40, 0xa3, 0x2a, 0x55, + 0x55, 0x7c, 0x58, 0x2e, 0xf1, 0x4b, 0x99, 0x0c, 0xb0, 0x91, 0x25, 0x81, 0x81, 0x5b, 0x29, 0x9d, + 0x09, 0x34, 0xc4, 0x4a, 0x43, 0xd3, 0x07, 0x82, 0x77, 0x19, 0x6d, 0xc3, 0xdd, 0xd4, 0xe8, 0x0a, + 0xbc, 0xb8, 0x82, 0x76, 0x60, 0x3b, 0x53, 0x7c, 0x05, 0xf2, 0xab, 0x29, 0xce, 0xec, 0xc9, 0x57, + 0x15, 0x11, 0xab, 0x9a, 0xba, 0xa7, 0xf3, 0x6b, 0xe8, 0xc7, 0xf0, 0x64, 0x92, 0x33, 0x55, 0xf1, + 0x00, 0xab, 0x82, 0x28, 0x0f, 0xe4, 0xb9, 0xf5, 0x94, 0xd8, 0x8f, 0x72, 0xa3, 0xa0, 0x57, 0x04, + 0x8d, 0xdf, 0x48, 0x99, 0x53, 0x5a, 0x4d, 0x7d, 0xbd, 0x57, 0x11, 0x0e, 0x24, 0x7e, 0x73, 0x4c, + 0xbb, 0xaa, 0x98, 0x18, 0xdd, 0xb2, 0x46, 0xea, 0x58, 0xfd, 0xcd, 0x43, 0xbe, 0x38, 0x26, 0x14, + 0x93, 0xd2, 0xb2, 0xb2, 0x2f, 0x13, 0xe1, 0x95, 0xa0, 0x54, 0x84, 0x92, 0x52, 0x51, 0xf4, 0x43, + 0x7e, 0x0b, 0x7d, 0x0a, 0x4f, 0x53, 0xb4, 0xd8, 0x0c, 0x51, 0x44, 0x82, 0xa5, 0x7d, 0x45, 0xd3, + 0x31, 0x4b, 0x9d, 0xfc, 0xed, 0xd1, 0x59, 0x58, 0x13, 0xaa, 0x95, 0x64, 0x8a, 0xe5, 0xef, 0x6c, + 0xff, 0x15, 0x07, 0xf3, 0xfd, 0xaf, 0xf3, 0xd1, 0x3a, 0x2c, 0xc7, 0xaa, 0x9a, 0x2e, 0xe8, 0x0d, + 0x6d, 0x60, 0x4d, 0x5c, 0x86, 0x9b, 0x83, 0x02, 0x5a, 0x43, 0x14, 0xfd, 0xe9, 0xcf, 0x8d, 0xac, + 0x3c, 0x50, 0xea, 0x75, 0xa9, 0xcc, 0xe7, 0xd1, 0x12, 0xdc, 0x18, 0xac, 0x94, 0x30, 0x56, 0x31, + 0x3f, 0x35, 0x4a, 0x4f, 0x28, 0xa9, 0x98, 0x2d, 0x6f, 0xdb, 0xff, 0xc4, 0xc1, 0x94, 0xa8, 0x0b, + 0xe8, 0x1a, 0x2c, 0x88, 0xba, 0x30, 0xfc, 0x06, 0xd4, 0x2f, 0x14, 0x1a, 0xba, 0x4c, 0x44, 0xb5, + 0x56, 0x93, 0x44, 0x5d, 0xf5, 0x17, 0xe7, 0x9b, 0x70, 0x8d, 0x95, 0x8b, 0xba, 0xf2, 0xca, 0x5f, + 0xb3, 0x35, 0x4d, 0x51, 0x6b, 0xfe, 0x9a, 0x1c, 0x57, 0xf8, 0x90, 0x09, 0x96, 0x5e, 0x36, 0x24, + 0x4d, 0xd7, 0xf8, 0xa9, 0xa8, 0xa2, 0x8e, 0xa5, 0xaa, 0xd2, 0xa8, 0x12, 0xad, 0x51, 0xaf, 0xab, + 0x58, 0xe7, 0xa7, 0xa3, 0x0a, 0x1d, 0xfb, 0xf3, 0xa4, 0x4c, 0xca, 0xd2, 0x2b, 0xc5, 0x4f, 0x30, + 0x33, 0x91, 0xed, 0x46, 0x7d, 0x1f, 0x0b, 0x65, 0x89, 0x94, 0x84, 0x5a, 0x4d, 0xc2, 0xfc, 0x85, + 0x48, 0xa1, 0xa4, 0x54, 0x2a, 0x4a, 0x6d, 0x9f, 0x68, 0x8d, 0x6a, 0x55, 0xc0, 0x87, 0xfc, 0xc5, + 0xed, 0x7f, 0x9f, 0x81, 0x1b, 0x23, 0x6f, 0x33, 0xfd, 0x44, 0xa8, 0xd4, 0x74, 0x69, 0x3f, 0x70, + 0x21, 0x91, 0x6a, 0x58, 0xad, 0x54, 0xc8, 0x81, 0x52, 0x1b, 0x7c, 0xf3, 0xba, 0x09, 0xab, 0xe3, + 0x04, 0xb5, 0x8a, 0x20, 0x1e, 0xf0, 0x1c, 0xba, 0x0d, 0x1b, 0xe3, 0x44, 0x84, 0xd7, 0x1a, 0xf1, + 0x0f, 0x7c, 0x7c, 0xde, 0x5f, 0x5a, 0xc7, 0x49, 0xd5, 0x85, 0x7d, 0x09, 0x97, 0x1b, 0xfa, 0x21, + 0x3f, 0x35, 0xc9, 0x9e, 0x54, 0x15, 0x94, 0x0a, 0x3f, 0xed, 0xef, 0x83, 0xc6, 0x89, 0xbc, 0x50, + 0xb0, 0xc0, 0xcf, 0xa0, 0x2d, 0x58, 0x1f, 0x27, 0xc1, 0xdc, 0x8e, 0xcb, 0xfc, 0x05, 0x3f, 0x68, + 0xc7, 0x09, 0x55, 0x05, 0x5d, 0x97, 0x70, 0x55, 0xd5, 0x74, 0xfe, 0xe2, 0xa4, 0xee, 0x55, 0x35, + 0xa2, 0x4b, 0x42, 0x55, 0xe3, 0x67, 0x27, 0x49, 0xa9, 0x75, 0x6d, 0x5f, 0xaa, 0x29, 0x12, 0x7f, + 0x69, 0x12, 0x74, 0xf5, 0x40, 0x17, 0x78, 0x98, 0xd8, 0x39, 0xa1, 0xba, 0xc7, 0x5f, 0x9e, 0x8c, + 0x5b, 0x94, 0x95, 0x9a, 0x44, 0x94, 0x32, 0x3f, 0x87, 0x7e, 0x04, 0x8f, 0xd3, 0xe5, 0xc8, 0xbe, + 0xa2, 0xcb, 0x8d, 0x12, 0x8b, 0x5b, 0x3f, 0x5e, 0xaf, 0xa0, 0x5d, 0x78, 0x98, 0x41, 0x4d, 0x54, + 0xb0, 0x58, 0x91, 0x44, 0x85, 0x9f, 0xf7, 0x17, 0x95, 0x6c, 0x76, 0x2a, 0x42, 0x89, 0x5f, 0xf0, + 0x93, 0x77, 0x06, 0xf1, 0x17, 0x52, 0xed, 0x40, 0xa9, 0x69, 0x3c, 0x9f, 0x51, 0x5e, 0xa8, 0x69, + 0x4a, 0xa9, 0x22, 0xf1, 0x57, 0x4b, 0x3f, 0xfd, 0xe7, 0x6f, 0xd6, 0xb8, 0x7f, 0xf9, 0x66, 0x8d, + 0xfb, 0xb7, 0x6f, 0xd6, 0xb8, 0x37, 0xea, 0x91, 0xe9, 0xbd, 0xef, 0xbe, 0xdd, 0x69, 0xda, 0xc7, + 0xbb, 0x47, 0x8e, 0x71, 0x62, 0x06, 0xac, 0x87, 0xd1, 0xde, 0x8d, 0xff, 0xb3, 0x67, 0x74, 0xcc, + 0xdd, 0x23, 0x6a, 0xed, 0xb2, 0x3f, 0xe8, 0xed, 0x1e, 0xd9, 0x03, 0x7f, 0xe2, 0x7b, 0x9e, 0xf8, + 0x3c, 0x79, 0xfc, 0xf6, 0x02, 0x13, 0x7b, 0xfa, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x6e, 0xc7, + 0xc1, 0x45, 0xf4, 0x37, 0x00, 0x00, } func (m *UIBannerClickEvent) Marshal() (dAtA []byte, err error) { @@ -4972,6 +5161,104 @@ func (m *AssistNewConversationEvent) MarshalToSizedBuffer(dAtA []byte) (int, err return len(dAtA) - i, nil } +func (m *AssistAccessRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *AssistAccessRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *AssistAccessRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.XXX_unrecognized != nil { + i -= len(m.XXX_unrecognized) + copy(dAtA[i:], m.XXX_unrecognized) + } + if m.CompletionTokens != 0 { + i = encodeVarintUsageevents(dAtA, i, uint64(m.CompletionTokens)) + i-- + dAtA[i] = 0x20 + } + if m.PromptTokens != 0 { + i = encodeVarintUsageevents(dAtA, i, uint64(m.PromptTokens)) + i-- + dAtA[i] = 0x18 + } + if m.TotalTokens != 0 { + i = encodeVarintUsageevents(dAtA, i, uint64(m.TotalTokens)) + i-- + dAtA[i] = 0x10 + } + if len(m.ResourceType) > 0 { + i -= len(m.ResourceType) + copy(dAtA[i:], m.ResourceType) + i = encodeVarintUsageevents(dAtA, i, uint64(len(m.ResourceType))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *AssistAction) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *AssistAction) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *AssistAction) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.XXX_unrecognized != nil { + i -= len(m.XXX_unrecognized) + copy(dAtA[i:], m.XXX_unrecognized) + } + if m.CompletionTokens != 0 { + i = encodeVarintUsageevents(dAtA, i, uint64(m.CompletionTokens)) + i-- + dAtA[i] = 0x20 + } + if m.PromptTokens != 0 { + i = encodeVarintUsageevents(dAtA, i, uint64(m.PromptTokens)) + i-- + dAtA[i] = 0x18 + } + if m.TotalTokens != 0 { + i = encodeVarintUsageevents(dAtA, i, uint64(m.TotalTokens)) + i-- + dAtA[i] = 0x10 + } + if len(m.Action) > 0 { + i -= len(m.Action) + copy(dAtA[i:], m.Action) + i = encodeVarintUsageevents(dAtA, i, uint64(len(m.Action))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func (m *IntegrationEnrollMetadata) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -5886,6 +6173,52 @@ func (m *UsageEventOneOf_AssistNewConversation) MarshalToSizedBuffer(dAtA []byte } return len(dAtA) - i, nil } +func (m *UsageEventOneOf_AssistAccessRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *UsageEventOneOf_AssistAccessRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.AssistAccessRequest != nil { + { + size, err := m.AssistAccessRequest.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintUsageevents(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2 + i-- + dAtA[i] = 0xb2 + } + return len(dAtA) - i, nil +} +func (m *UsageEventOneOf_AssistAction) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *UsageEventOneOf_AssistAction) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.AssistAction != nil { + { + size, err := m.AssistAction.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintUsageevents(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2 + i-- + dAtA[i] = 0xba + } + return len(dAtA) - i, nil +} func encodeVarintUsageevents(dAtA []byte, offset int, v uint64) int { offset -= sovUsageevents(v) base := offset @@ -6583,22 +6916,24 @@ func (m *AssistNewConversationEvent) Size() (n int) { return n } -func (m *IntegrationEnrollMetadata) Size() (n int) { +func (m *AssistAccessRequest) Size() (n int) { if m == nil { return 0 } var l int _ = l - l = len(m.Id) + l = len(m.ResourceType) if l > 0 { n += 1 + l + sovUsageevents(uint64(l)) } - if m.Kind != 0 { - n += 1 + sovUsageevents(uint64(m.Kind)) + if m.TotalTokens != 0 { + n += 1 + sovUsageevents(uint64(m.TotalTokens)) } - l = len(m.UserName) - if l > 0 { - n += 1 + l + sovUsageevents(uint64(l)) + if m.PromptTokens != 0 { + n += 1 + sovUsageevents(uint64(m.PromptTokens)) + } + if m.CompletionTokens != 0 { + n += 1 + sovUsageevents(uint64(m.CompletionTokens)) } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) @@ -6606,13 +6941,61 @@ func (m *IntegrationEnrollMetadata) Size() (n int) { return n } -func (m *UIIntegrationEnrollStartEvent) Size() (n int) { +func (m *AssistAction) Size() (n int) { if m == nil { return 0 } var l int _ = l - if m.Metadata != nil { + l = len(m.Action) + if l > 0 { + n += 1 + l + sovUsageevents(uint64(l)) + } + if m.TotalTokens != 0 { + n += 1 + sovUsageevents(uint64(m.TotalTokens)) + } + if m.PromptTokens != 0 { + n += 1 + sovUsageevents(uint64(m.PromptTokens)) + } + if m.CompletionTokens != 0 { + n += 1 + sovUsageevents(uint64(m.CompletionTokens)) + } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } + return n +} + +func (m *IntegrationEnrollMetadata) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Id) + if l > 0 { + n += 1 + l + sovUsageevents(uint64(l)) + } + if m.Kind != 0 { + n += 1 + sovUsageevents(uint64(m.Kind)) + } + l = len(m.UserName) + if l > 0 { + n += 1 + l + sovUsageevents(uint64(l)) + } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } + return n +} + +func (m *UIIntegrationEnrollStartEvent) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Metadata != nil { l = m.Metadata.Size() n += 1 + l + sovUsageevents(uint64(l)) } @@ -7061,6 +7444,30 @@ func (m *UsageEventOneOf_AssistNewConversation) Size() (n int) { } return n } +func (m *UsageEventOneOf_AssistAccessRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.AssistAccessRequest != nil { + l = m.AssistAccessRequest.Size() + n += 2 + l + sovUsageevents(uint64(l)) + } + return n +} +func (m *UsageEventOneOf_AssistAction) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.AssistAction != nil { + l = m.AssistAction.Size() + n += 2 + l + sovUsageevents(uint64(l)) + } + return n +} func sovUsageevents(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 @@ -11075,6 +11482,286 @@ func (m *AssistNewConversationEvent) Unmarshal(dAtA []byte) error { } return nil } +func (m *AssistAccessRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowUsageevents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: AssistAccessRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: AssistAccessRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ResourceType", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowUsageevents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthUsageevents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthUsageevents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ResourceType = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TotalTokens", wireType) + } + m.TotalTokens = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowUsageevents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TotalTokens |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PromptTokens", wireType) + } + m.PromptTokens = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowUsageevents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PromptTokens |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field CompletionTokens", wireType) + } + m.CompletionTokens = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowUsageevents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.CompletionTokens |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipUsageevents(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthUsageevents + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *AssistAction) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowUsageevents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: AssistAction: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: AssistAction: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Action", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowUsageevents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthUsageevents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthUsageevents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Action = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TotalTokens", wireType) + } + m.TotalTokens = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowUsageevents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TotalTokens |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PromptTokens", wireType) + } + m.PromptTokens = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowUsageevents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PromptTokens |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field CompletionTokens", wireType) + } + m.CompletionTokens = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowUsageevents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.CompletionTokens |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipUsageevents(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthUsageevents + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *IntegrationEnrollMetadata) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -12602,6 +13289,76 @@ func (m *UsageEventOneOf) Unmarshal(dAtA []byte) error { } m.Event = &UsageEventOneOf_AssistNewConversation{v} iNdEx = postIndex + case 38: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AssistAccessRequest", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowUsageevents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthUsageevents + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthUsageevents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &AssistAccessRequest{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Event = &UsageEventOneOf_AssistAccessRequest{v} + iNdEx = postIndex + case 39: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AssistAction", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowUsageevents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthUsageevents + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthUsageevents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &AssistAction{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Event = &UsageEventOneOf_AssistAction{v} + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipUsageevents(dAtA[iNdEx:]) diff --git a/api/proto/teleport/usageevents/v1/usageevents.proto b/api/proto/teleport/usageevents/v1/usageevents.proto index 36e83d857de0a..ebb8f29bd3b98 100644 --- a/api/proto/teleport/usageevents/v1/usageevents.proto +++ b/api/proto/teleport/usageevents/v1/usageevents.proto @@ -377,6 +377,32 @@ message AssistNewConversationEvent { string category = 1; } +// AssistAccessRequest is an event that is emitted when a user requests access +// to a resource via Assist. +message AssistAccessRequest { + // ResourceType describes the type of resource the user is requesting access to, e.g. "node", "db", "k8s" or "role". + string resource_type = 1; + // TotalTokens is the total amount of token used to generate the command summary + int64 total_tokens = 2; + // PromptTokens is the amount of estimated tokens used by the prompt to generate the command summary + int64 prompt_tokens = 3; + // CompletionTokens is the amount of tokens that the summary completion response consists of + int64 completion_tokens = 4; +} + +// AssistAction is an event that is emitted when a user triggers an action (SSH command generation, output explain, etc.) +// via Assist. +message AssistAction { + // Action is the action that was triggered, e.g. "ssh-explain", "ssh-command-generate", etc. + string action = 1; + // TotalTokens is the total amount of token used to generate the command summary + int64 total_tokens = 2; + // PromptTokens is the amount of estimated tokens used by the prompt to generate the command summary + int64 prompt_tokens = 3; + // CompletionTokens is the amount of tokens that the summary completion response consists of + int64 completion_tokens = 4; +} + // IntegrationEnrollKind represents the types of integration that // can be enrolled. enum IntegrationEnrollKind { @@ -462,6 +488,8 @@ message UsageEventOneOf { UIOnboardQuestionnaireSubmitEvent ui_onboard_questionnaire_submit = 33; AssistExecutionEvent assist_execution = 34; AssistNewConversationEvent assist_new_conversation = 35; + AssistAccessRequest assist_access_request = 38; + AssistAction assist_action = 39; } reserved 2; //UIOnboardGetStartedClickEvent reserved "ui_onboard_get_started_click"; diff --git a/gen/proto/go/prehog/v1alpha/teleport.pb.go b/gen/proto/go/prehog/v1alpha/teleport.pb.go index dad38fe9a2c8d..5f2eeebaf6656 100644 --- a/gen/proto/go/prehog/v1alpha/teleport.pb.go +++ b/gen/proto/go/prehog/v1alpha/teleport.pb.go @@ -3777,6 +3777,178 @@ func (x *AssistNewConversationEvent) GetCategory() string { return "" } +// AssistAccessRequest is an event that is emitted when a user requests access +// to a resource via Assist. +type AssistAccessRequestEvent struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // UserName is anonymized user name + UserName string `protobuf:"bytes,1,opt,name=user_name,json=userName,proto3" json:"user_name,omitempty"` + // ResourceType describes the type of resource the user is requesting access to, e.g. "node", "db", "k8s" or "role". + ResourceType string `protobuf:"bytes,2,opt,name=resource_type,json=resourceType,proto3" json:"resource_type,omitempty"` + // TotalTokens is the total amount of token used to generate the command summary + TotalTokens int64 `protobuf:"varint,4,opt,name=total_tokens,json=totalTokens,proto3" json:"total_tokens,omitempty"` + // PromptTokens is the amount of estimated tokens used by the prompt to generate the command summary + PromptTokens int64 `protobuf:"varint,5,opt,name=prompt_tokens,json=promptTokens,proto3" json:"prompt_tokens,omitempty"` + // CompletionTokens is the amount of tokens that the summary completion response consists of + CompletionTokens int64 `protobuf:"varint,6,opt,name=completion_tokens,json=completionTokens,proto3" json:"completion_tokens,omitempty"` +} + +func (x *AssistAccessRequestEvent) Reset() { + *x = AssistAccessRequestEvent{} + if protoimpl.UnsafeEnabled { + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[48] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AssistAccessRequestEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AssistAccessRequestEvent) ProtoMessage() {} + +func (x *AssistAccessRequestEvent) ProtoReflect() protoreflect.Message { + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[48] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AssistAccessRequestEvent.ProtoReflect.Descriptor instead. +func (*AssistAccessRequestEvent) Descriptor() ([]byte, []int) { + return file_prehog_v1alpha_teleport_proto_rawDescGZIP(), []int{48} +} + +func (x *AssistAccessRequestEvent) GetUserName() string { + if x != nil { + return x.UserName + } + return "" +} + +func (x *AssistAccessRequestEvent) GetResourceType() string { + if x != nil { + return x.ResourceType + } + return "" +} + +func (x *AssistAccessRequestEvent) GetTotalTokens() int64 { + if x != nil { + return x.TotalTokens + } + return 0 +} + +func (x *AssistAccessRequestEvent) GetPromptTokens() int64 { + if x != nil { + return x.PromptTokens + } + return 0 +} + +func (x *AssistAccessRequestEvent) GetCompletionTokens() int64 { + if x != nil { + return x.CompletionTokens + } + return 0 +} + +// AssistAction is an event that is emitted when a user triggers an action (SSH command generation, output explain, etc.) +// via Assist. +type AssistActionEvent struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // UserName is anonymized user name + UserName string `protobuf:"bytes,1,opt,name=user_name,json=userName,proto3" json:"user_name,omitempty"` + // Action is the action that was triggered, e.g. "ssh-explain", "ssh-command-generate", etc. + Action string `protobuf:"bytes,2,opt,name=action,proto3" json:"action,omitempty"` + // TotalTokens is the total amount of token used to generate the command summary + TotalTokens int64 `protobuf:"varint,4,opt,name=total_tokens,json=totalTokens,proto3" json:"total_tokens,omitempty"` + // PromptTokens is the amount of estimated tokens used by the prompt to generate the command summary + PromptTokens int64 `protobuf:"varint,5,opt,name=prompt_tokens,json=promptTokens,proto3" json:"prompt_tokens,omitempty"` + // CompletionTokens is the amount of tokens that the summary completion response consists of + CompletionTokens int64 `protobuf:"varint,6,opt,name=completion_tokens,json=completionTokens,proto3" json:"completion_tokens,omitempty"` +} + +func (x *AssistActionEvent) Reset() { + *x = AssistActionEvent{} + if protoimpl.UnsafeEnabled { + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[49] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AssistActionEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AssistActionEvent) ProtoMessage() {} + +func (x *AssistActionEvent) ProtoReflect() protoreflect.Message { + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[49] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AssistActionEvent.ProtoReflect.Descriptor instead. +func (*AssistActionEvent) Descriptor() ([]byte, []int) { + return file_prehog_v1alpha_teleport_proto_rawDescGZIP(), []int{49} +} + +func (x *AssistActionEvent) GetUserName() string { + if x != nil { + return x.UserName + } + return "" +} + +func (x *AssistActionEvent) GetAction() string { + if x != nil { + return x.Action + } + return "" +} + +func (x *AssistActionEvent) GetTotalTokens() int64 { + if x != nil { + return x.TotalTokens + } + return 0 +} + +func (x *AssistActionEvent) GetPromptTokens() int64 { + if x != nil { + return x.PromptTokens + } + return 0 +} + +func (x *AssistActionEvent) GetCompletionTokens() int64 { + if x != nil { + return x.CompletionTokens + } + return 0 +} + // IntegrationEnrollMetadata contains common metadata // for Integration Enroll related events. type IntegrationEnrollMetadata struct { @@ -3796,7 +3968,7 @@ type IntegrationEnrollMetadata struct { func (x *IntegrationEnrollMetadata) Reset() { *x = IntegrationEnrollMetadata{} if protoimpl.UnsafeEnabled { - mi := &file_prehog_v1alpha_teleport_proto_msgTypes[48] + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[50] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3809,7 +3981,7 @@ func (x *IntegrationEnrollMetadata) String() string { func (*IntegrationEnrollMetadata) ProtoMessage() {} func (x *IntegrationEnrollMetadata) ProtoReflect() protoreflect.Message { - mi := &file_prehog_v1alpha_teleport_proto_msgTypes[48] + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[50] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3822,7 +3994,7 @@ func (x *IntegrationEnrollMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use IntegrationEnrollMetadata.ProtoReflect.Descriptor instead. func (*IntegrationEnrollMetadata) Descriptor() ([]byte, []int) { - return file_prehog_v1alpha_teleport_proto_rawDescGZIP(), []int{48} + return file_prehog_v1alpha_teleport_proto_rawDescGZIP(), []int{50} } func (x *IntegrationEnrollMetadata) GetId() string { @@ -3859,7 +4031,7 @@ type UIIntegrationEnrollStartEvent struct { func (x *UIIntegrationEnrollStartEvent) Reset() { *x = UIIntegrationEnrollStartEvent{} if protoimpl.UnsafeEnabled { - mi := &file_prehog_v1alpha_teleport_proto_msgTypes[49] + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[51] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3872,7 +4044,7 @@ func (x *UIIntegrationEnrollStartEvent) String() string { func (*UIIntegrationEnrollStartEvent) ProtoMessage() {} func (x *UIIntegrationEnrollStartEvent) ProtoReflect() protoreflect.Message { - mi := &file_prehog_v1alpha_teleport_proto_msgTypes[49] + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[51] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3885,7 +4057,7 @@ func (x *UIIntegrationEnrollStartEvent) ProtoReflect() protoreflect.Message { // Deprecated: Use UIIntegrationEnrollStartEvent.ProtoReflect.Descriptor instead. func (*UIIntegrationEnrollStartEvent) Descriptor() ([]byte, []int) { - return file_prehog_v1alpha_teleport_proto_rawDescGZIP(), []int{49} + return file_prehog_v1alpha_teleport_proto_rawDescGZIP(), []int{51} } func (x *UIIntegrationEnrollStartEvent) GetMetadata() *IntegrationEnrollMetadata { @@ -3908,7 +4080,7 @@ type UIIntegrationEnrollCompleteEvent struct { func (x *UIIntegrationEnrollCompleteEvent) Reset() { *x = UIIntegrationEnrollCompleteEvent{} if protoimpl.UnsafeEnabled { - mi := &file_prehog_v1alpha_teleport_proto_msgTypes[50] + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[52] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3921,7 +4093,7 @@ func (x *UIIntegrationEnrollCompleteEvent) String() string { func (*UIIntegrationEnrollCompleteEvent) ProtoMessage() {} func (x *UIIntegrationEnrollCompleteEvent) ProtoReflect() protoreflect.Message { - mi := &file_prehog_v1alpha_teleport_proto_msgTypes[50] + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[52] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3934,7 +4106,7 @@ func (x *UIIntegrationEnrollCompleteEvent) ProtoReflect() protoreflect.Message { // Deprecated: Use UIIntegrationEnrollCompleteEvent.ProtoReflect.Descriptor instead. func (*UIIntegrationEnrollCompleteEvent) Descriptor() ([]byte, []int) { - return file_prehog_v1alpha_teleport_proto_rawDescGZIP(), []int{50} + return file_prehog_v1alpha_teleport_proto_rawDescGZIP(), []int{52} } func (x *UIIntegrationEnrollCompleteEvent) GetMetadata() *IntegrationEnrollMetadata { @@ -3959,7 +4131,7 @@ type EditorChangeEvent struct { func (x *EditorChangeEvent) Reset() { *x = EditorChangeEvent{} if protoimpl.UnsafeEnabled { - mi := &file_prehog_v1alpha_teleport_proto_msgTypes[51] + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[53] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3972,7 +4144,7 @@ func (x *EditorChangeEvent) String() string { func (*EditorChangeEvent) ProtoMessage() {} func (x *EditorChangeEvent) ProtoReflect() protoreflect.Message { - mi := &file_prehog_v1alpha_teleport_proto_msgTypes[51] + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[53] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3985,7 +4157,7 @@ func (x *EditorChangeEvent) ProtoReflect() protoreflect.Message { // Deprecated: Use EditorChangeEvent.ProtoReflect.Descriptor instead. func (*EditorChangeEvent) Descriptor() ([]byte, []int) { - return file_prehog_v1alpha_teleport_proto_rawDescGZIP(), []int{51} + return file_prehog_v1alpha_teleport_proto_rawDescGZIP(), []int{53} } func (x *EditorChangeEvent) GetUserName() string { @@ -4025,7 +4197,7 @@ type DeviceAuthenticateEvent struct { func (x *DeviceAuthenticateEvent) Reset() { *x = DeviceAuthenticateEvent{} if protoimpl.UnsafeEnabled { - mi := &file_prehog_v1alpha_teleport_proto_msgTypes[52] + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[54] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4038,7 +4210,7 @@ func (x *DeviceAuthenticateEvent) String() string { func (*DeviceAuthenticateEvent) ProtoMessage() {} func (x *DeviceAuthenticateEvent) ProtoReflect() protoreflect.Message { - mi := &file_prehog_v1alpha_teleport_proto_msgTypes[52] + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[54] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4051,7 +4223,7 @@ func (x *DeviceAuthenticateEvent) ProtoReflect() protoreflect.Message { // Deprecated: Use DeviceAuthenticateEvent.ProtoReflect.Descriptor instead. func (*DeviceAuthenticateEvent) Descriptor() ([]byte, []int) { - return file_prehog_v1alpha_teleport_proto_rawDescGZIP(), []int{52} + return file_prehog_v1alpha_teleport_proto_rawDescGZIP(), []int{54} } func (x *DeviceAuthenticateEvent) GetDeviceId() string { @@ -4141,13 +4313,15 @@ type SubmitEventRequest struct { // *SubmitEventRequest_AssistExecution // *SubmitEventRequest_AssistNewConversation // *SubmitEventRequest_DeviceAuthenticateEvent + // *SubmitEventRequest_AssistAccessRequest + // *SubmitEventRequest_AssistAction Event isSubmitEventRequest_Event `protobuf_oneof:"event"` } func (x *SubmitEventRequest) Reset() { *x = SubmitEventRequest{} if protoimpl.UnsafeEnabled { - mi := &file_prehog_v1alpha_teleport_proto_msgTypes[53] + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[55] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4160,7 +4334,7 @@ func (x *SubmitEventRequest) String() string { func (*SubmitEventRequest) ProtoMessage() {} func (x *SubmitEventRequest) ProtoReflect() protoreflect.Message { - mi := &file_prehog_v1alpha_teleport_proto_msgTypes[53] + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[55] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4173,7 +4347,7 @@ func (x *SubmitEventRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SubmitEventRequest.ProtoReflect.Descriptor instead. func (*SubmitEventRequest) Descriptor() ([]byte, []int) { - return file_prehog_v1alpha_teleport_proto_rawDescGZIP(), []int{53} + return file_prehog_v1alpha_teleport_proto_rawDescGZIP(), []int{55} } func (x *SubmitEventRequest) GetClusterName() string { @@ -4540,6 +4714,20 @@ func (x *SubmitEventRequest) GetDeviceAuthenticateEvent() *DeviceAuthenticateEve return nil } +func (x *SubmitEventRequest) GetAssistAccessRequest() *AssistAccessRequestEvent { + if x, ok := x.GetEvent().(*SubmitEventRequest_AssistAccessRequest); ok { + return x.AssistAccessRequest + } + return nil +} + +func (x *SubmitEventRequest) GetAssistAction() *AssistActionEvent { + if x, ok := x.GetEvent().(*SubmitEventRequest_AssistAction); ok { + return x.AssistAction + } + return nil +} + type isSubmitEventRequest_Event interface { isSubmitEventRequest_Event() } @@ -4745,6 +4933,14 @@ type SubmitEventRequest_DeviceAuthenticateEvent struct { DeviceAuthenticateEvent *DeviceAuthenticateEvent `protobuf:"bytes,52,opt,name=device_authenticate_event,json=deviceAuthenticateEvent,proto3,oneof"` } +type SubmitEventRequest_AssistAccessRequest struct { + AssistAccessRequest *AssistAccessRequestEvent `protobuf:"bytes,54,opt,name=assist_access_request,json=assistAccessRequest,proto3,oneof"` +} + +type SubmitEventRequest_AssistAction struct { + AssistAction *AssistActionEvent `protobuf:"bytes,55,opt,name=assist_action,json=assistAction,proto3,oneof"` +} + func (*SubmitEventRequest_UserLogin) isSubmitEventRequest_Event() {} func (*SubmitEventRequest_SsoCreate) isSubmitEventRequest_Event() {} @@ -4845,6 +5041,10 @@ func (*SubmitEventRequest_AssistNewConversation) isSubmitEventRequest_Event() {} func (*SubmitEventRequest_DeviceAuthenticateEvent) isSubmitEventRequest_Event() {} +func (*SubmitEventRequest_AssistAccessRequest) isSubmitEventRequest_Event() {} + +func (*SubmitEventRequest_AssistAction) isSubmitEventRequest_Event() {} + type SubmitEventResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -4854,7 +5054,7 @@ type SubmitEventResponse struct { func (x *SubmitEventResponse) Reset() { *x = SubmitEventResponse{} if protoimpl.UnsafeEnabled { - mi := &file_prehog_v1alpha_teleport_proto_msgTypes[54] + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[56] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4867,7 +5067,7 @@ func (x *SubmitEventResponse) String() string { func (*SubmitEventResponse) ProtoMessage() {} func (x *SubmitEventResponse) ProtoReflect() protoreflect.Message { - mi := &file_prehog_v1alpha_teleport_proto_msgTypes[54] + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[56] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4880,7 +5080,7 @@ func (x *SubmitEventResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SubmitEventResponse.ProtoReflect.Descriptor instead. func (*SubmitEventResponse) Descriptor() ([]byte, []int) { - return file_prehog_v1alpha_teleport_proto_rawDescGZIP(), []int{54} + return file_prehog_v1alpha_teleport_proto_rawDescGZIP(), []int{56} } type SubmitEventsRequest struct { @@ -4895,7 +5095,7 @@ type SubmitEventsRequest struct { func (x *SubmitEventsRequest) Reset() { *x = SubmitEventsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_prehog_v1alpha_teleport_proto_msgTypes[55] + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[57] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4908,7 +5108,7 @@ func (x *SubmitEventsRequest) String() string { func (*SubmitEventsRequest) ProtoMessage() {} func (x *SubmitEventsRequest) ProtoReflect() protoreflect.Message { - mi := &file_prehog_v1alpha_teleport_proto_msgTypes[55] + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[57] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4921,7 +5121,7 @@ func (x *SubmitEventsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SubmitEventsRequest.ProtoReflect.Descriptor instead. func (*SubmitEventsRequest) Descriptor() ([]byte, []int) { - return file_prehog_v1alpha_teleport_proto_rawDescGZIP(), []int{55} + return file_prehog_v1alpha_teleport_proto_rawDescGZIP(), []int{57} } func (x *SubmitEventsRequest) GetEvents() []*SubmitEventRequest { @@ -4940,7 +5140,7 @@ type SubmitEventsResponse struct { func (x *SubmitEventsResponse) Reset() { *x = SubmitEventsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_prehog_v1alpha_teleport_proto_msgTypes[56] + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[58] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4953,7 +5153,7 @@ func (x *SubmitEventsResponse) String() string { func (*SubmitEventsResponse) ProtoMessage() {} func (x *SubmitEventsResponse) ProtoReflect() protoreflect.Message { - mi := &file_prehog_v1alpha_teleport_proto_msgTypes[56] + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[58] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4966,7 +5166,7 @@ func (x *SubmitEventsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SubmitEventsResponse.ProtoReflect.Descriptor instead. func (*SubmitEventsResponse) Descriptor() ([]byte, []int) { - return file_prehog_v1alpha_teleport_proto_rawDescGZIP(), []int{56} + return file_prehog_v1alpha_teleport_proto_rawDescGZIP(), []int{58} } type HelloTeleportRequest struct { @@ -4978,7 +5178,7 @@ type HelloTeleportRequest struct { func (x *HelloTeleportRequest) Reset() { *x = HelloTeleportRequest{} if protoimpl.UnsafeEnabled { - mi := &file_prehog_v1alpha_teleport_proto_msgTypes[57] + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[59] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4991,7 +5191,7 @@ func (x *HelloTeleportRequest) String() string { func (*HelloTeleportRequest) ProtoMessage() {} func (x *HelloTeleportRequest) ProtoReflect() protoreflect.Message { - mi := &file_prehog_v1alpha_teleport_proto_msgTypes[57] + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[59] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5004,7 +5204,7 @@ func (x *HelloTeleportRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use HelloTeleportRequest.ProtoReflect.Descriptor instead. func (*HelloTeleportRequest) Descriptor() ([]byte, []int) { - return file_prehog_v1alpha_teleport_proto_rawDescGZIP(), []int{57} + return file_prehog_v1alpha_teleport_proto_rawDescGZIP(), []int{59} } type HelloTeleportResponse struct { @@ -5016,7 +5216,7 @@ type HelloTeleportResponse struct { func (x *HelloTeleportResponse) Reset() { *x = HelloTeleportResponse{} if protoimpl.UnsafeEnabled { - mi := &file_prehog_v1alpha_teleport_proto_msgTypes[58] + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[60] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5029,7 +5229,7 @@ func (x *HelloTeleportResponse) String() string { func (*HelloTeleportResponse) ProtoMessage() {} func (x *HelloTeleportResponse) ProtoReflect() protoreflect.Message { - mi := &file_prehog_v1alpha_teleport_proto_msgTypes[58] + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[60] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5042,7 +5242,7 @@ func (x *HelloTeleportResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use HelloTeleportResponse.ProtoReflect.Descriptor instead. func (*HelloTeleportResponse) Descriptor() ([]byte, []int) { - return file_prehog_v1alpha_teleport_proto_rawDescGZIP(), []int{58} + return file_prehog_v1alpha_teleport_proto_rawDescGZIP(), []int{60} } var File_prehog_v1alpha_teleport_proto protoreflect.FileDescriptor @@ -5522,647 +5722,683 @@ var file_prehog_v1alpha_teleport_proto_rawDesc = []byte{ 0x1b, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x22, 0x83, 0x01, 0x0a, 0x19, 0x49, 0x6e, 0x74, - 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x39, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x04, 0x6b, 0x69, 0x6e, - 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x66, - 0x0a, 0x1d, 0x55, 0x49, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, - 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x53, 0x74, 0x61, 0x72, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, - 0x45, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, - 0x72, 0x6f, 0x6c, 0x6c, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x69, 0x0a, 0x20, 0x55, 0x49, 0x49, 0x6e, 0x74, 0x65, - 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x43, 0x6f, 0x6d, - 0x70, 0x6c, 0x65, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x45, 0x0a, 0x08, 0x6d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, - 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x49, 0x6e, - 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x22, 0x6c, 0x0a, 0x11, 0x45, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x43, 0x68, 0x61, 0x6e, 0x67, - 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x4e, - 0x61, 0x6d, 0x65, 0x12, 0x3a, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x45, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x43, 0x68, 0x61, 0x6e, 0x67, - 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, - 0x79, 0x0a, 0x17, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, - 0x69, 0x63, 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x72, 0x5f, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, - 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x6f, - 0x73, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x4f, 0x73, 0x54, 0x79, 0x70, 0x65, 0x22, 0x98, 0x2c, 0x0a, 0x12, 0x53, - 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x3f, - 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x48, 0x00, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, - 0x3f, 0x0a, 0x0a, 0x73, 0x73, 0x6f, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x53, 0x53, 0x4f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x09, 0x73, 0x73, 0x6f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x12, 0x4e, 0x0a, 0x0f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x72, 0x65, 0x68, - 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, - 0x52, 0x0e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x12, 0x48, 0x0a, 0x0d, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x72, - 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x53, 0x74, 0x61, 0x72, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0c, 0x73, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x4c, 0x0a, 0x0f, 0x75, 0x69, - 0x5f, 0x62, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x43, 0x6c, 0x69, - 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0d, 0x75, 0x69, 0x42, 0x61, 0x6e, - 0x6e, 0x65, 0x72, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x12, 0x92, 0x01, 0x0a, 0x29, 0x75, 0x69, 0x5f, - 0x6f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, - 0x5f, 0x67, 0x6f, 0x5f, 0x74, 0x6f, 0x5f, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, - 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x70, - 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, + 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x22, 0xd1, 0x01, 0x0a, 0x18, 0x41, 0x73, 0x73, + 0x69, 0x73, 0x74, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x4e, 0x61, + 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x6f, 0x74, 0x61, 0x6c, + 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x74, + 0x6f, 0x74, 0x61, 0x6c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, + 0x6f, 0x6d, 0x70, 0x74, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, + 0x2b, 0x0a, 0x11, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x6f, + 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x63, 0x6f, 0x6d, 0x70, + 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x22, 0xbd, 0x01, 0x0a, + 0x11, 0x41, 0x73, 0x73, 0x69, 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, + 0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x6f, 0x74, 0x61, 0x6c, + 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x74, + 0x6f, 0x74, 0x61, 0x6c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, + 0x6f, 0x6d, 0x70, 0x74, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, + 0x2b, 0x0a, 0x11, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x6f, + 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x63, 0x6f, 0x6d, 0x70, + 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x22, 0x83, 0x01, 0x0a, + 0x19, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x72, 0x6f, + 0x6c, 0x6c, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x39, 0x0a, 0x04, 0x6b, 0x69, + 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, + 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x4b, 0x69, 0x6e, 0x64, 0x52, + 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x4e, 0x61, + 0x6d, 0x65, 0x22, 0x66, 0x0a, 0x1d, 0x55, 0x49, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x53, 0x74, 0x61, 0x72, 0x74, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x12, 0x45, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x69, 0x0a, 0x20, 0x55, 0x49, + 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, + 0x6c, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x45, + 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x29, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x72, + 0x6f, 0x6c, 0x6c, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x6c, 0x0a, 0x11, 0x45, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x43, + 0x68, 0x61, 0x6e, 0x67, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x75, 0x73, + 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, + 0x73, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x3a, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x45, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x43, + 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x22, 0x79, 0x0a, 0x17, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x41, 0x75, 0x74, + 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1b, + 0x0a, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x75, + 0x73, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x75, 0x73, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x5f, 0x6f, 0x73, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0c, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4f, 0x73, 0x54, 0x79, 0x70, 0x65, 0x22, 0xc2, + 0x2d, 0x0a, 0x12, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x12, 0x3f, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6c, 0x6f, 0x67, 0x69, 0x6e, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x69, + 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x4c, 0x6f, + 0x67, 0x69, 0x6e, 0x12, 0x3f, 0x0a, 0x0a, 0x73, 0x73, 0x6f, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x53, 0x53, 0x4f, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x09, 0x73, 0x73, 0x6f, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x12, 0x4e, 0x0a, 0x0f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, + 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x12, 0x48, 0x0a, 0x0d, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, + 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x72, + 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x53, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, + 0x52, 0x0c, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x4c, + 0x0a, 0x0f, 0x75, 0x69, 0x5f, 0x62, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x5f, 0x63, 0x6c, 0x69, 0x63, + 0x6b, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x42, 0x61, 0x6e, 0x6e, 0x65, + 0x72, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0d, 0x75, + 0x69, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x12, 0x92, 0x01, 0x0a, + 0x29, 0x75, 0x69, 0x5f, 0x6f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5f, 0x63, 0x6f, 0x6d, 0x70, + 0x6c, 0x65, 0x74, 0x65, 0x5f, 0x67, 0x6f, 0x5f, 0x74, 0x6f, 0x5f, 0x64, 0x61, 0x73, 0x68, 0x62, + 0x6f, 0x61, 0x72, 0x64, 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x38, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x2e, 0x55, 0x49, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6d, 0x70, 0x6c, + 0x65, 0x74, 0x65, 0x47, 0x6f, 0x54, 0x6f, 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, + 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x23, 0x75, 0x69, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x47, 0x6f, 0x54, 0x6f, 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x43, 0x6c, 0x69, 0x63, - 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x23, 0x75, 0x69, 0x4f, 0x6e, 0x62, 0x6f, - 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x47, 0x6f, 0x54, 0x6f, 0x44, - 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x12, 0x82, 0x01, - 0x0a, 0x23, 0x75, 0x69, 0x5f, 0x6f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5f, 0x61, 0x64, 0x64, - 0x5f, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, - 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x70, 0x72, - 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x4f, - 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x41, 0x64, 0x64, 0x46, 0x69, 0x72, 0x73, 0x74, 0x52, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x48, 0x00, 0x52, 0x1e, 0x75, 0x69, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x41, 0x64, 0x64, - 0x46, 0x69, 0x72, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6c, 0x69, - 0x63, 0x6b, 0x12, 0x92, 0x01, 0x0a, 0x29, 0x75, 0x69, 0x5f, 0x6f, 0x6e, 0x62, 0x6f, 0x61, 0x72, - 0x64, 0x5f, 0x61, 0x64, 0x64, 0x5f, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, - 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, + 0x6b, 0x12, 0x82, 0x01, 0x0a, 0x23, 0x75, 0x69, 0x5f, 0x6f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, + 0x5f, 0x61, 0x64, 0x64, 0x5f, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x33, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x2e, 0x55, 0x49, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x41, 0x64, 0x64, 0x46, 0x69, 0x72, + 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1e, 0x75, 0x69, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x41, 0x64, 0x64, 0x46, 0x69, 0x72, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x4c, 0x61, 0x74, 0x65, 0x72, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x48, 0x00, 0x52, 0x23, 0x75, 0x69, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x41, 0x64, 0x64, - 0x46, 0x69, 0x72, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4c, 0x61, 0x74, - 0x65, 0x72, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x12, 0x7b, 0x0a, 0x20, 0x75, 0x69, 0x5f, 0x6f, 0x6e, - 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, - 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x31, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x2e, 0x55, 0x49, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x53, 0x65, 0x74, 0x43, - 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1c, 0x75, 0x69, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, - 0x64, 0x53, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x53, 0x75, - 0x62, 0x6d, 0x69, 0x74, 0x12, 0x87, 0x01, 0x0a, 0x24, 0x75, 0x69, 0x5f, 0x6f, 0x6e, 0x62, 0x6f, - 0x61, 0x72, 0x64, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x63, 0x68, 0x61, - 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x5f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x18, 0x0d, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x52, 0x65, - 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x53, - 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x20, 0x75, 0x69, - 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, - 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x12, 0x7b, - 0x0a, 0x20, 0x75, 0x69, 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x5f, 0x63, 0x6f, - 0x64, 0x65, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x65, 0x5f, 0x63, 0x6c, 0x69, - 0x63, 0x6b, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, - 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x52, 0x65, 0x63, 0x6f, - 0x76, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, - 0x65, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1c, 0x75, - 0x69, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x43, 0x6f, - 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x65, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x12, 0x6f, 0x0a, 0x1c, 0x75, - 0x69, 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x73, - 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x18, 0x0f, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x2d, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x2e, 0x55, 0x49, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x64, - 0x65, 0x73, 0x43, 0x6f, 0x70, 0x79, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x48, 0x00, 0x52, 0x18, 0x75, 0x69, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x43, 0x6f, - 0x64, 0x65, 0x73, 0x43, 0x6f, 0x70, 0x79, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x12, 0x72, 0x0a, 0x1d, - 0x75, 0x69, 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, - 0x73, 0x5f, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x18, 0x10, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x43, - 0x6f, 0x64, 0x65, 0x73, 0x50, 0x72, 0x69, 0x6e, 0x74, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x19, 0x75, 0x69, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, - 0x79, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x50, 0x72, 0x69, 0x6e, 0x74, 0x43, 0x6c, 0x69, 0x63, 0x6b, - 0x12, 0x63, 0x0a, 0x19, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, - 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x11, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x53, - 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x16, 0x75, - 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x82, 0x01, 0x0a, 0x24, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, - 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x73, - 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x12, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, - 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x20, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, - 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x6c, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x6f, 0x0a, 0x1d, 0x75, 0x73, - 0x65, 0x72, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x69, - 0x73, 0x73, 0x75, 0x65, 0x64, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x13, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x2a, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, - 0x74, 0x65, 0x49, 0x73, 0x73, 0x75, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, - 0x1a, 0x75, 0x73, 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, - 0x49, 0x73, 0x73, 0x75, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x4d, 0x0a, 0x10, 0x73, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x76, 0x32, 0x18, - 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, - 0x61, 0x72, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0e, 0x73, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x56, 0x32, 0x12, 0x76, 0x0a, 0x20, 0x75, 0x69, - 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, - 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x15, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, - 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1c, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, - 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x12, 0x7f, 0x0a, 0x23, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, - 0x72, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x73, - 0x74, 0x65, 0x72, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x16, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x2f, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x62, - 0x61, 0x73, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x48, 0x00, 0x52, 0x1f, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x61, - 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x12, 0x8f, 0x01, 0x0a, 0x29, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, - 0x76, 0x65, 0x72, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x5f, 0x6d, 0x74, 0x6c, 0x73, 0x5f, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x18, 0x17, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, + 0x65, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x12, 0x92, 0x01, 0x0a, 0x29, 0x75, 0x69, 0x5f, 0x6f, 0x6e, + 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5f, 0x61, 0x64, 0x64, 0x5f, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x5f, 0x63, + 0x6c, 0x69, 0x63, 0x6b, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x70, 0x72, 0x65, + 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x4f, 0x6e, + 0x62, 0x6f, 0x61, 0x72, 0x64, 0x41, 0x64, 0x64, 0x46, 0x69, 0x72, 0x73, 0x74, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4c, 0x61, 0x74, 0x65, 0x72, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x23, 0x75, 0x69, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, + 0x64, 0x41, 0x64, 0x64, 0x46, 0x69, 0x72, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x4c, 0x61, 0x74, 0x65, 0x72, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x12, 0x7b, 0x0a, 0x20, 0x75, + 0x69, 0x5f, 0x6f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x63, 0x72, + 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x18, + 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, + 0x53, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x53, 0x75, 0x62, + 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1c, 0x75, 0x69, 0x4f, 0x6e, + 0x62, 0x6f, 0x61, 0x72, 0x64, 0x53, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, + 0x61, 0x6c, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x12, 0x87, 0x01, 0x0a, 0x24, 0x75, 0x69, 0x5f, + 0x6f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, + 0x5f, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x5f, 0x73, 0x75, 0x62, 0x6d, 0x69, + 0x74, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x4f, 0x6e, 0x62, 0x6f, 0x61, + 0x72, 0x64, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, + 0x6e, 0x67, 0x65, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, + 0x52, 0x20, 0x75, 0x69, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x52, 0x65, 0x67, 0x69, 0x73, + 0x74, 0x65, 0x72, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x53, 0x75, 0x62, 0x6d, + 0x69, 0x74, 0x12, 0x7b, 0x0a, 0x20, 0x75, 0x69, 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, + 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x65, + 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x70, + 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, + 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x43, 0x6f, 0x6e, + 0x74, 0x69, 0x6e, 0x75, 0x65, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, + 0x00, 0x52, 0x1c, 0x75, 0x69, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x64, + 0x65, 0x73, 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x65, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x12, + 0x6f, 0x0a, 0x1c, 0x75, 0x69, 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x5f, 0x63, + 0x6f, 0x64, 0x65, 0x73, 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x18, + 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, + 0x79, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x43, 0x6f, 0x70, 0x79, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x18, 0x75, 0x69, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, + 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x43, 0x6f, 0x70, 0x79, 0x43, 0x6c, 0x69, 0x63, 0x6b, + 0x12, 0x72, 0x0a, 0x1d, 0x75, 0x69, 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x5f, + 0x63, 0x6f, 0x64, 0x65, 0x73, 0x5f, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x5f, 0x63, 0x6c, 0x69, 0x63, + 0x6b, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x52, 0x65, 0x63, 0x6f, 0x76, + 0x65, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x50, 0x72, 0x69, 0x6e, 0x74, 0x43, 0x6c, 0x69, + 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x19, 0x75, 0x69, 0x52, 0x65, 0x63, + 0x6f, 0x76, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x50, 0x72, 0x69, 0x6e, 0x74, 0x43, + 0x6c, 0x69, 0x63, 0x6b, 0x12, 0x63, 0x0a, 0x19, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, + 0x76, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, - 0x76, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x75, 0x72, 0x65, 0x4d, 0x54, 0x4c, 0x53, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, - 0x24, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x62, - 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x4d, 0x74, 0x6c, 0x73, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0xb8, 0x01, 0x0a, 0x38, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, - 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x63, - 0x74, 0x69, 0x76, 0x65, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x74, - 0x6f, 0x6f, 0x6c, 0x73, 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x5f, 0x65, 0x76, 0x65, - 0x6e, 0x74, 0x18, 0x18, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, + 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, + 0x00, 0x52, 0x16, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, + 0x72, 0x74, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x82, 0x01, 0x0a, 0x24, 0x75, 0x69, + 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x76, 0x65, + 0x6e, 0x74, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, - 0x6f, 0x76, 0x65, 0x72, 0x44, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x41, 0x63, 0x74, 0x69, 0x76, - 0x65, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x54, 0x6f, 0x6f, 0x6c, 0x73, 0x49, - 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x31, 0x75, - 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, - 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x54, - 0x6f, 0x6f, 0x6c, 0x73, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x12, 0xae, 0x01, 0x0a, 0x34, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, - 0x5f, 0x64, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, - 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x75, 0x72, 0x65, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x19, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x3e, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x65, 0x73, 0x6b, 0x74, - 0x6f, 0x70, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, - 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, - 0x00, 0x52, 0x2e, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x65, 0x73, - 0x6b, 0x74, 0x6f, 0x70, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, - 0x6f, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x12, 0x95, 0x01, 0x0a, 0x2b, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, - 0x72, 0x5f, 0x61, 0x75, 0x74, 0x6f, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, - 0x64, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x5f, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, - 0x76, 0x65, 0x72, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, - 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, - 0x00, 0x52, 0x26, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x41, 0x75, 0x74, - 0x6f, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x9f, 0x01, 0x0a, 0x2f, 0x75, 0x69, - 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, - 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x5f, 0x69, 0x61, 0x6d, - 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x1b, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, + 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x6c, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x20, 0x75, 0x69, + 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x6f, + 0x0a, 0x1d, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x65, 0x5f, 0x69, 0x73, 0x73, 0x75, 0x65, 0x64, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, + 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x49, 0x73, 0x73, 0x75, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x48, 0x00, 0x52, 0x1a, 0x75, 0x73, 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x49, 0x73, 0x73, 0x75, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, + 0x4d, 0x0a, 0x10, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, + 0x5f, 0x76, 0x32, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x72, 0x65, 0x68, + 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0e, + 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x56, 0x32, 0x12, 0x76, + 0x0a, 0x20, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x65, + 0x70, 0x6c, 0x6f, 0x79, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x65, 0x76, 0x65, + 0x6e, 0x74, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, + 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, + 0x6f, 0x76, 0x65, 0x72, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1c, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, + 0x6f, 0x76, 0x65, 0x72, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x7f, 0x0a, 0x23, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, + 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x72, + 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x16, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, + 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1f, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, + 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, + 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x8f, 0x01, 0x0a, 0x29, 0x75, 0x69, 0x5f, 0x64, + 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, + 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x5f, 0x6d, 0x74, 0x6c, 0x73, 0x5f, + 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x17, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x70, 0x72, + 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, + 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x4d, 0x54, 0x4c, 0x53, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x48, 0x00, 0x52, 0x24, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, - 0x49, 0x41, 0x4d, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, - 0x52, 0x29, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, - 0x62, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x49, 0x61, 0x6d, - 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x88, 0x01, 0x0a, 0x26, - 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x70, 0x72, 0x69, 0x6e, - 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, - 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x70, + 0x4d, 0x74, 0x6c, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0xb8, 0x01, 0x0a, 0x38, 0x75, 0x69, + 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x73, 0x6b, 0x74, 0x6f, + 0x70, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, + 0x72, 0x79, 0x5f, 0x74, 0x6f, 0x6f, 0x6c, 0x73, 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, + 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x18, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, - 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, - 0x6c, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x48, 0x00, 0x52, 0x22, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x50, 0x72, - 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, - 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x79, 0x0a, 0x21, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, - 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x1d, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x2d, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x54, 0x65, 0x73, - 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x48, 0x00, 0x52, 0x1d, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x54, 0x65, - 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x12, 0x69, 0x0a, 0x1b, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, - 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, - 0x18, 0x1e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, + 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x41, + 0x63, 0x74, 0x69, 0x76, 0x65, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x54, 0x6f, + 0x6f, 0x6c, 0x73, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, + 0x00, 0x52, 0x31, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x65, 0x73, + 0x6b, 0x74, 0x6f, 0x70, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, + 0x6f, 0x72, 0x79, 0x54, 0x6f, 0x6f, 0x6c, 0x73, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x12, 0xae, 0x01, 0x0a, 0x34, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, + 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x63, 0x74, + 0x69, 0x76, 0x65, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x19, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, + 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x44, 0x69, 0x72, 0x65, + 0x63, 0x74, 0x6f, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x2e, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, + 0x72, 0x44, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x44, 0x69, + 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x95, 0x01, 0x0a, 0x2b, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, + 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x61, 0x75, 0x74, 0x6f, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, + 0x76, 0x65, 0x72, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x5f, + 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x70, 0x72, + 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, + 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x69, 0x73, 0x63, 0x6f, + 0x76, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x26, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, + 0x72, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x9f, 0x01, + 0x0a, 0x2f, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x61, + 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, + 0x5f, 0x69, 0x61, 0x6d, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, + 0x76, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x75, 0x72, 0x65, 0x49, 0x41, 0x4d, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x48, 0x00, 0x52, 0x29, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, + 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, + 0x65, 0x49, 0x61, 0x6d, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, + 0x88, 0x01, 0x0a, 0x26, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, + 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x75, 0x72, 0x65, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x32, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x50, 0x72, 0x69, 0x6e, + 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x22, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, + 0x65, 0x72, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x75, 0x72, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x79, 0x0a, 0x21, 0x75, 0x69, + 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, + 0x1d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, + 0x72, 0x54, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1d, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, + 0x65, 0x72, 0x54, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x69, 0x0a, 0x1b, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, + 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x65, + 0x76, 0x65, 0x6e, 0x74, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x70, 0x72, 0x65, + 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, + 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x18, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x48, 0x00, 0x52, 0x18, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x43, 0x6f, - 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x42, 0x0a, 0x0b, - 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x18, 0x1f, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0a, 0x72, 0x6f, 0x6c, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x12, 0x63, 0x0a, 0x18, 0x75, 0x69, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x6e, 0x65, - 0x77, 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x18, 0x20, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x65, 0x77, 0x52, - 0x6f, 0x6c, 0x65, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, - 0x14, 0x75, 0x69, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x65, 0x77, 0x52, 0x6f, 0x6c, 0x65, - 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x12, 0x70, 0x0a, 0x1d, 0x75, 0x69, 0x5f, 0x63, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x5f, 0x6e, 0x65, 0x77, 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x73, 0x61, 0x76, 0x65, - 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x18, 0x21, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x70, - 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x65, 0x77, 0x52, 0x6f, 0x6c, 0x65, 0x53, 0x61, 0x76, - 0x65, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x18, 0x75, - 0x69, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x65, 0x77, 0x52, 0x6f, 0x6c, 0x65, 0x53, 0x61, - 0x76, 0x65, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x12, 0x76, 0x0a, 0x1f, 0x75, 0x69, 0x5f, 0x63, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x5f, 0x6e, 0x65, 0x77, 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x63, 0x61, - 0x6e, 0x63, 0x65, 0x6c, 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x18, 0x22, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x2f, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x12, 0x42, 0x0a, 0x0b, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x18, + 0x1f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0a, 0x72, 0x6f, 0x6c, 0x65, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x12, 0x63, 0x0a, 0x18, 0x75, 0x69, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x5f, 0x6e, 0x65, 0x77, 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, + 0x18, 0x20, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x4e, 0x65, 0x77, 0x52, 0x6f, 0x6c, 0x65, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x48, 0x00, 0x52, 0x14, 0x75, 0x69, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x65, 0x77, + 0x52, 0x6f, 0x6c, 0x65, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x12, 0x70, 0x0a, 0x1d, 0x75, 0x69, 0x5f, + 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x6e, 0x65, 0x77, 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x5f, + 0x73, 0x61, 0x76, 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x18, 0x21, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x2d, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x65, 0x77, 0x52, 0x6f, 0x6c, - 0x65, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x48, 0x00, 0x52, 0x1a, 0x75, 0x69, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x65, 0x77, - 0x52, 0x6f, 0x6c, 0x65, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x12, - 0x98, 0x01, 0x0a, 0x2b, 0x75, 0x69, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x6e, 0x65, - 0x77, 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x5f, 0x64, 0x6f, 0x63, 0x75, - 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x18, - 0x23, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, - 0x65, 0x77, 0x52, 0x6f, 0x6c, 0x65, 0x56, 0x69, 0x65, 0x77, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, - 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x48, 0x00, 0x52, 0x25, 0x75, 0x69, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x65, 0x77, - 0x52, 0x6f, 0x6c, 0x65, 0x56, 0x69, 0x65, 0x77, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x12, 0x45, 0x0a, 0x0c, 0x6b, 0x75, - 0x62, 0x65, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x24, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x20, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x2e, 0x4b, 0x75, 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0b, 0x6b, 0x75, 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x2f, 0x0a, 0x04, 0x73, 0x66, 0x74, 0x70, 0x18, 0x25, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x19, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x2e, 0x53, 0x46, 0x54, 0x50, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x04, 0x73, 0x66, - 0x74, 0x70, 0x12, 0x56, 0x0a, 0x14, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x26, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x22, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x12, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x57, 0x0a, 0x12, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, - 0x18, 0x27, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, - 0x52, 0x11, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, - 0x65, 0x61, 0x74, 0x12, 0x9c, 0x01, 0x0a, 0x2e, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, - 0x76, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, - 0x61, 0x77, 0x73, 0x5f, 0x6f, 0x69, 0x64, 0x63, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, - 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x28, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x70, - 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, + 0x65, 0x53, 0x61, 0x76, 0x65, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, + 0x00, 0x52, 0x18, 0x75, 0x69, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x65, 0x77, 0x52, 0x6f, + 0x6c, 0x65, 0x53, 0x61, 0x76, 0x65, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x12, 0x76, 0x0a, 0x1f, 0x75, + 0x69, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x6e, 0x65, 0x77, 0x5f, 0x72, 0x6f, 0x6c, + 0x65, 0x5f, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x18, 0x22, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x65, + 0x77, 0x52, 0x6f, 0x6c, 0x65, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x43, 0x6c, 0x69, 0x63, 0x6b, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1a, 0x75, 0x69, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x4e, 0x65, 0x77, 0x52, 0x6f, 0x6c, 0x65, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x43, 0x6c, + 0x69, 0x63, 0x6b, 0x12, 0x98, 0x01, 0x0a, 0x2b, 0x75, 0x69, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x5f, 0x6e, 0x65, 0x77, 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x5f, + 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6c, + 0x69, 0x63, 0x6b, 0x18, 0x23, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x70, 0x72, 0x65, 0x68, + 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x4e, 0x65, 0x77, 0x52, 0x6f, 0x6c, 0x65, 0x56, 0x69, 0x65, 0x77, 0x44, 0x6f, + 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x69, 0x63, 0x6b, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x25, 0x75, 0x69, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x4e, 0x65, 0x77, 0x52, 0x6f, 0x6c, 0x65, 0x56, 0x69, 0x65, 0x77, 0x44, 0x6f, 0x63, 0x75, + 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x12, 0x45, + 0x0a, 0x0c, 0x6b, 0x75, 0x62, 0x65, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x24, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4b, 0x75, 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0b, 0x6b, 0x75, 0x62, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x04, 0x73, 0x66, 0x74, 0x70, 0x18, 0x25, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x53, 0x46, 0x54, 0x50, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, + 0x52, 0x04, 0x73, 0x66, 0x74, 0x70, 0x12, 0x56, 0x0a, 0x14, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, + 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x26, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x12, 0x61, 0x67, 0x65, 0x6e, + 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x57, + 0x0a, 0x12, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x72, 0x74, + 0x62, 0x65, 0x61, 0x74, 0x18, 0x27, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x72, 0x65, + 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x48, 0x00, 0x52, 0x11, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x48, 0x65, + 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x12, 0x9c, 0x01, 0x0a, 0x2e, 0x75, 0x69, 0x5f, 0x64, + 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x77, 0x73, 0x5f, 0x6f, 0x69, 0x64, 0x63, 0x5f, 0x63, 0x6f, 0x6e, + 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x28, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x38, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x49, 0x6e, 0x74, 0x65, + 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x57, 0x53, 0x4f, 0x49, 0x44, 0x43, 0x43, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x28, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x41, 0x57, 0x53, 0x4f, 0x49, 0x44, 0x43, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x28, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, - 0x6f, 0x76, 0x65, 0x72, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, - 0x77, 0x73, 0x4f, 0x69, 0x64, 0x63, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x12, 0x83, 0x01, 0x0a, 0x25, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, - 0x65, 0x72, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x72, 0x64, 0x73, 0x5f, - 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x29, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x61, - 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x52, 0x44, 0x53, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x20, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, - 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x52, 0x64, 0x73, 0x45, 0x6e, 0x72, - 0x6f, 0x6c, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x6b, 0x0a, 0x1d, 0x75, 0x69, 0x5f, 0x63, - 0x61, 0x6c, 0x6c, 0x5f, 0x74, 0x6f, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6c, - 0x69, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x2a, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x28, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x2e, 0x55, 0x49, 0x43, 0x61, 0x6c, 0x6c, 0x54, 0x6f, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, - 0x6c, 0x69, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x18, 0x75, 0x69, 0x43, - 0x61, 0x6c, 0x6c, 0x54, 0x6f, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x69, 0x63, 0x6b, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x54, 0x0a, 0x11, 0x61, 0x73, 0x73, 0x69, 0x73, 0x74, 0x5f, - 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x2b, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x25, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x69, - 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x10, 0x61, 0x73, 0x73, 0x69, 0x73, - 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x79, 0x0a, 0x21, 0x75, + 0x69, 0x6f, 0x6e, 0x41, 0x77, 0x73, 0x4f, 0x69, 0x64, 0x63, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, + 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x83, 0x01, 0x0a, 0x25, 0x75, 0x69, 0x5f, 0x64, 0x69, + 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x5f, + 0x72, 0x64, 0x73, 0x5f, 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, + 0x18, 0x29, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, + 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x52, 0x44, 0x53, 0x45, 0x6e, 0x72, + 0x6f, 0x6c, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x20, 0x75, 0x69, 0x44, 0x69, + 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x52, 0x64, + 0x73, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x6b, 0x0a, 0x1d, + 0x75, 0x69, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x5f, 0x74, 0x6f, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x2a, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x43, 0x61, 0x6c, 0x6c, 0x54, 0x6f, 0x41, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, + 0x18, 0x75, 0x69, 0x43, 0x61, 0x6c, 0x6c, 0x54, 0x6f, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, + 0x6c, 0x69, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x54, 0x0a, 0x11, 0x61, 0x73, 0x73, + 0x69, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x2b, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x70, + 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x10, 0x61, + 0x73, 0x73, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x79, 0x0a, 0x21, 0x75, 0x69, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x65, + 0x76, 0x65, 0x6e, 0x74, 0x18, 0x2c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x70, 0x72, 0x65, + 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x49, 0x6e, + 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x53, + 0x74, 0x61, 0x72, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1d, 0x75, 0x69, 0x49, + 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, + 0x53, 0x74, 0x61, 0x72, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x82, 0x01, 0x0a, 0x24, 0x75, 0x69, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x6e, - 0x72, 0x6f, 0x6c, 0x6c, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, - 0x18, 0x2c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x53, 0x74, 0x61, 0x72, 0x74, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1d, 0x75, 0x69, 0x49, 0x6e, 0x74, 0x65, 0x67, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x53, 0x74, 0x61, 0x72, - 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x82, 0x01, 0x0a, 0x24, 0x75, 0x69, 0x5f, 0x69, 0x6e, - 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, - 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, - 0x2d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, - 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x20, 0x75, 0x69, 0x49, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x6c, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x5f, 0x65, 0x76, + 0x65, 0x6e, 0x74, 0x18, 0x2d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x70, 0x72, 0x65, 0x68, + 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x43, 0x6f, - 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x53, 0x0a, 0x13, 0x65, - 0x64, 0x69, 0x74, 0x6f, 0x72, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x65, 0x76, 0x65, - 0x6e, 0x74, 0x18, 0x2e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, - 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x45, 0x64, 0x69, 0x74, 0x6f, 0x72, - 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x11, 0x65, - 0x64, 0x69, 0x74, 0x6f, 0x72, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x12, 0x3f, 0x0a, 0x0a, 0x62, 0x6f, 0x74, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x18, 0x2f, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x42, 0x6f, 0x74, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x09, 0x62, 0x6f, 0x74, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x12, 0x7a, 0x0a, 0x1f, 0x75, 0x69, 0x5f, 0x6f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5f, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x6e, 0x61, 0x69, 0x72, 0x65, 0x5f, 0x73, 0x75, - 0x62, 0x6d, 0x69, 0x74, 0x18, 0x30, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x70, 0x72, 0x65, - 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x4f, 0x6e, - 0x62, 0x6f, 0x61, 0x72, 0x64, 0x51, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x6e, 0x61, 0x69, - 0x72, 0x65, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, - 0x1c, 0x75, 0x69, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x51, 0x75, 0x65, 0x73, 0x74, 0x69, - 0x6f, 0x6e, 0x6e, 0x61, 0x69, 0x72, 0x65, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x12, 0x39, 0x0a, - 0x08, 0x62, 0x6f, 0x74, 0x5f, 0x6a, 0x6f, 0x69, 0x6e, 0x18, 0x31, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1c, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x2e, 0x42, 0x6f, 0x74, 0x4a, 0x6f, 0x69, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, - 0x07, 0x62, 0x6f, 0x74, 0x4a, 0x6f, 0x69, 0x6e, 0x12, 0x51, 0x0a, 0x10, 0x61, 0x73, 0x73, 0x69, - 0x73, 0x74, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x32, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x73, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, - 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0f, 0x61, 0x73, 0x73, 0x69, - 0x73, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x64, 0x0a, 0x17, 0x61, - 0x73, 0x73, 0x69, 0x73, 0x74, 0x5f, 0x6e, 0x65, 0x77, 0x5f, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, - 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x33, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x70, - 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x41, 0x73, - 0x73, 0x69, 0x73, 0x74, 0x4e, 0x65, 0x77, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x15, 0x61, 0x73, 0x73, 0x69, - 0x73, 0x74, 0x4e, 0x65, 0x77, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x65, 0x0a, 0x19, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x61, 0x75, 0x74, 0x68, - 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x34, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x41, 0x75, 0x74, 0x68, - 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, - 0x17, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, - 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x42, 0x07, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x4a, 0x04, 0x08, 0x08, 0x10, 0x09, 0x52, 0x1c, 0x75, 0x69, 0x5f, 0x6f, 0x6e, 0x62, 0x6f, - 0x61, 0x72, 0x64, 0x5f, 0x67, 0x65, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x5f, - 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x22, 0x15, 0x0a, 0x13, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x51, 0x0a, 0x13, - 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x3a, 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x22, - 0x16, 0x0a, 0x14, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x0a, 0x14, 0x48, 0x65, 0x6c, 0x6c, 0x6f, - 0x54, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, - 0x17, 0x0a, 0x15, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x54, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2a, 0xe2, 0x01, 0x0a, 0x0c, 0x52, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x1d, 0x0a, 0x19, 0x52, 0x45, 0x53, - 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, - 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x52, 0x45, 0x53, 0x4f, - 0x55, 0x52, 0x43, 0x45, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4e, 0x4f, 0x44, 0x45, 0x10, 0x01, - 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x4b, 0x49, 0x4e, - 0x44, 0x5f, 0x41, 0x50, 0x50, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x10, 0x02, 0x12, 0x1d, - 0x0a, 0x19, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, - 0x4b, 0x55, 0x42, 0x45, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x10, 0x03, 0x12, 0x1b, 0x0a, - 0x17, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x44, - 0x42, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x10, 0x04, 0x12, 0x21, 0x0a, 0x1d, 0x52, 0x45, - 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x57, 0x49, 0x4e, 0x44, - 0x4f, 0x57, 0x53, 0x5f, 0x44, 0x45, 0x53, 0x4b, 0x54, 0x4f, 0x50, 0x10, 0x05, 0x12, 0x1e, 0x0a, - 0x1a, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4e, - 0x4f, 0x44, 0x45, 0x5f, 0x4f, 0x50, 0x45, 0x4e, 0x53, 0x53, 0x48, 0x10, 0x06, 0x2a, 0x95, 0x0e, - 0x0a, 0x10, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x12, 0x21, 0x0a, 0x1d, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, - 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, - 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, - 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x45, - 0x52, 0x10, 0x01, 0x12, 0x20, 0x0a, 0x1c, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, - 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x4b, 0x55, 0x42, 0x45, 0x52, 0x4e, 0x45, - 0x54, 0x45, 0x53, 0x10, 0x02, 0x12, 0x33, 0x0a, 0x2f, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, - 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, - 0x41, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x53, 0x54, 0x47, 0x52, 0x45, 0x53, 0x5f, 0x53, 0x45, 0x4c, - 0x46, 0x5f, 0x48, 0x4f, 0x53, 0x54, 0x45, 0x44, 0x10, 0x03, 0x12, 0x30, 0x0a, 0x2c, 0x44, 0x49, + 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x20, 0x75, + 0x69, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x72, 0x6f, + 0x6c, 0x6c, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, + 0x53, 0x0a, 0x13, 0x65, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x2e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, + 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x45, 0x64, + 0x69, 0x74, 0x6f, 0x72, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, + 0x00, 0x52, 0x11, 0x65, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x12, 0x3f, 0x0a, 0x0a, 0x62, 0x6f, 0x74, 0x5f, 0x63, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x18, 0x2f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, + 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x42, 0x6f, 0x74, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x09, 0x62, 0x6f, 0x74, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x7a, 0x0a, 0x1f, 0x75, 0x69, 0x5f, 0x6f, 0x6e, 0x62, 0x6f, + 0x61, 0x72, 0x64, 0x5f, 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x6e, 0x61, 0x69, 0x72, + 0x65, 0x5f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x18, 0x30, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, + 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, + 0x55, 0x49, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x51, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, + 0x6e, 0x6e, 0x61, 0x69, 0x72, 0x65, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x48, 0x00, 0x52, 0x1c, 0x75, 0x69, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x51, 0x75, + 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x6e, 0x61, 0x69, 0x72, 0x65, 0x53, 0x75, 0x62, 0x6d, 0x69, + 0x74, 0x12, 0x39, 0x0a, 0x08, 0x62, 0x6f, 0x74, 0x5f, 0x6a, 0x6f, 0x69, 0x6e, 0x18, 0x31, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x42, 0x6f, 0x74, 0x4a, 0x6f, 0x69, 0x6e, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x48, 0x00, 0x52, 0x07, 0x62, 0x6f, 0x74, 0x4a, 0x6f, 0x69, 0x6e, 0x12, 0x51, 0x0a, 0x10, + 0x61, 0x73, 0x73, 0x69, 0x73, 0x74, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x32, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x73, 0x74, 0x45, 0x78, + 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0f, + 0x61, 0x73, 0x73, 0x69, 0x73, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x64, 0x0a, 0x17, 0x61, 0x73, 0x73, 0x69, 0x73, 0x74, 0x5f, 0x6e, 0x65, 0x77, 0x5f, 0x63, 0x6f, + 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x33, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x2a, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x73, 0x74, 0x4e, 0x65, 0x77, 0x43, 0x6f, 0x6e, 0x76, 0x65, + 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x15, + 0x61, 0x73, 0x73, 0x69, 0x73, 0x74, 0x4e, 0x65, 0x77, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x65, 0x0a, 0x19, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, + 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x76, 0x65, + 0x6e, 0x74, 0x18, 0x34, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, + 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x48, 0x00, 0x52, 0x17, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x41, 0x75, 0x74, 0x68, 0x65, + 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x5e, 0x0a, 0x15, + 0x61, 0x73, 0x73, 0x69, 0x73, 0x74, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x72, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x36, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x70, 0x72, + 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x41, 0x73, 0x73, + 0x69, 0x73, 0x74, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x13, 0x61, 0x73, 0x73, 0x69, 0x73, 0x74, 0x41, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x48, 0x0a, 0x0d, + 0x61, 0x73, 0x73, 0x69, 0x73, 0x74, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x37, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0c, 0x61, 0x73, 0x73, 0x69, 0x73, 0x74, + 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x07, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4a, + 0x04, 0x08, 0x08, 0x10, 0x09, 0x52, 0x1c, 0x75, 0x69, 0x5f, 0x6f, 0x6e, 0x62, 0x6f, 0x61, 0x72, + 0x64, 0x5f, 0x67, 0x65, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x6c, + 0x69, 0x63, 0x6b, 0x22, 0x15, 0x0a, 0x13, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x51, 0x0a, 0x13, 0x53, 0x75, + 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x3a, 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x16, 0x0a, + 0x14, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x0a, 0x14, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x54, 0x65, + 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x17, 0x0a, + 0x15, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x54, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2a, 0xe2, 0x01, 0x0a, 0x0c, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x1d, 0x0a, 0x19, 0x52, 0x45, 0x53, 0x4f, 0x55, + 0x52, 0x43, 0x45, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, + 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, + 0x43, 0x45, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4e, 0x4f, 0x44, 0x45, 0x10, 0x01, 0x12, 0x1c, + 0x0a, 0x18, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, + 0x41, 0x50, 0x50, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x10, 0x02, 0x12, 0x1d, 0x0a, 0x19, + 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4b, 0x55, + 0x42, 0x45, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x10, 0x03, 0x12, 0x1b, 0x0a, 0x17, 0x52, + 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x44, 0x42, 0x5f, + 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x10, 0x04, 0x12, 0x21, 0x0a, 0x1d, 0x52, 0x45, 0x53, 0x4f, + 0x55, 0x52, 0x43, 0x45, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x57, 0x49, 0x4e, 0x44, 0x4f, 0x57, + 0x53, 0x5f, 0x44, 0x45, 0x53, 0x4b, 0x54, 0x4f, 0x50, 0x10, 0x05, 0x12, 0x1e, 0x0a, 0x1a, 0x52, + 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4e, 0x4f, 0x44, + 0x45, 0x5f, 0x4f, 0x50, 0x45, 0x4e, 0x53, 0x53, 0x48, 0x10, 0x06, 0x2a, 0x95, 0x0e, 0x0a, 0x10, + 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x12, 0x21, 0x0a, 0x1d, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, + 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, + 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, + 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x10, + 0x01, 0x12, 0x20, 0x0a, 0x1c, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, + 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x4b, 0x55, 0x42, 0x45, 0x52, 0x4e, 0x45, 0x54, 0x45, + 0x53, 0x10, 0x02, 0x12, 0x33, 0x0a, 0x2f, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, + 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, + 0x45, 0x5f, 0x50, 0x4f, 0x53, 0x54, 0x47, 0x52, 0x45, 0x53, 0x5f, 0x53, 0x45, 0x4c, 0x46, 0x5f, + 0x48, 0x4f, 0x53, 0x54, 0x45, 0x44, 0x10, 0x03, 0x12, 0x30, 0x0a, 0x2c, 0x44, 0x49, 0x53, 0x43, + 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, + 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x4d, 0x59, 0x53, 0x51, 0x4c, 0x5f, 0x53, 0x45, 0x4c, + 0x46, 0x5f, 0x48, 0x4f, 0x53, 0x54, 0x45, 0x44, 0x10, 0x04, 0x12, 0x32, 0x0a, 0x2e, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, - 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x4d, 0x59, 0x53, 0x51, 0x4c, 0x5f, 0x53, - 0x45, 0x4c, 0x46, 0x5f, 0x48, 0x4f, 0x53, 0x54, 0x45, 0x44, 0x10, 0x04, 0x12, 0x32, 0x0a, 0x2e, - 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, - 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x4d, 0x4f, 0x4e, 0x47, 0x4f, - 0x44, 0x42, 0x5f, 0x53, 0x45, 0x4c, 0x46, 0x5f, 0x48, 0x4f, 0x53, 0x54, 0x45, 0x44, 0x10, 0x05, - 0x12, 0x2b, 0x0a, 0x27, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, - 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x50, - 0x4f, 0x53, 0x54, 0x47, 0x52, 0x45, 0x53, 0x5f, 0x52, 0x44, 0x53, 0x10, 0x06, 0x12, 0x28, 0x0a, - 0x24, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, - 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x4d, 0x59, 0x53, 0x51, - 0x4c, 0x5f, 0x52, 0x44, 0x53, 0x10, 0x07, 0x12, 0x26, 0x0a, 0x22, 0x44, 0x49, 0x53, 0x43, 0x4f, - 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x41, 0x50, 0x50, - 0x4c, 0x49, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x48, 0x54, 0x54, 0x50, 0x10, 0x08, 0x12, - 0x25, 0x0a, 0x21, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, - 0x55, 0x52, 0x43, 0x45, 0x5f, 0x41, 0x50, 0x50, 0x4c, 0x49, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, - 0x5f, 0x54, 0x43, 0x50, 0x10, 0x09, 0x12, 0x25, 0x0a, 0x21, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, - 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x57, 0x49, 0x4e, 0x44, - 0x4f, 0x57, 0x53, 0x5f, 0x44, 0x45, 0x53, 0x4b, 0x54, 0x4f, 0x50, 0x10, 0x0a, 0x12, 0x2c, 0x0a, - 0x28, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, - 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x53, 0x51, 0x4c, 0x53, - 0x45, 0x52, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x44, 0x53, 0x10, 0x0b, 0x12, 0x30, 0x0a, 0x2c, 0x44, + 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x4d, 0x4f, 0x4e, 0x47, 0x4f, 0x44, 0x42, + 0x5f, 0x53, 0x45, 0x4c, 0x46, 0x5f, 0x48, 0x4f, 0x53, 0x54, 0x45, 0x44, 0x10, 0x05, 0x12, 0x2b, + 0x0a, 0x27, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, + 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x53, + 0x54, 0x47, 0x52, 0x45, 0x53, 0x5f, 0x52, 0x44, 0x53, 0x10, 0x06, 0x12, 0x28, 0x0a, 0x24, 0x44, + 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, + 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x4d, 0x59, 0x53, 0x51, 0x4c, 0x5f, + 0x52, 0x44, 0x53, 0x10, 0x07, 0x12, 0x26, 0x0a, 0x22, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, + 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x41, 0x50, 0x50, 0x4c, 0x49, + 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x48, 0x54, 0x54, 0x50, 0x10, 0x08, 0x12, 0x25, 0x0a, + 0x21, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, + 0x43, 0x45, 0x5f, 0x41, 0x50, 0x50, 0x4c, 0x49, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, + 0x43, 0x50, 0x10, 0x09, 0x12, 0x25, 0x0a, 0x21, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, + 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x57, 0x49, 0x4e, 0x44, 0x4f, 0x57, + 0x53, 0x5f, 0x44, 0x45, 0x53, 0x4b, 0x54, 0x4f, 0x50, 0x10, 0x0a, 0x12, 0x2c, 0x0a, 0x28, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, - 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x53, 0x54, 0x47, 0x52, - 0x45, 0x53, 0x5f, 0x52, 0x45, 0x44, 0x53, 0x48, 0x49, 0x46, 0x54, 0x10, 0x0c, 0x12, 0x34, 0x0a, - 0x30, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, - 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x53, 0x51, 0x4c, 0x53, - 0x45, 0x52, 0x56, 0x45, 0x52, 0x5f, 0x53, 0x45, 0x4c, 0x46, 0x5f, 0x48, 0x4f, 0x53, 0x54, 0x45, - 0x44, 0x10, 0x0d, 0x12, 0x30, 0x0a, 0x2c, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, + 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x53, 0x51, 0x4c, 0x53, 0x45, 0x52, + 0x56, 0x45, 0x52, 0x5f, 0x52, 0x44, 0x53, 0x10, 0x0b, 0x12, 0x30, 0x0a, 0x2c, 0x44, 0x49, 0x53, + 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, + 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x53, 0x54, 0x47, 0x52, 0x45, 0x53, + 0x5f, 0x52, 0x45, 0x44, 0x53, 0x48, 0x49, 0x46, 0x54, 0x10, 0x0c, 0x12, 0x34, 0x0a, 0x30, 0x44, + 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, + 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x53, 0x51, 0x4c, 0x53, 0x45, 0x52, + 0x56, 0x45, 0x52, 0x5f, 0x53, 0x45, 0x4c, 0x46, 0x5f, 0x48, 0x4f, 0x53, 0x54, 0x45, 0x44, 0x10, + 0x0d, 0x12, 0x30, 0x0a, 0x2c, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, + 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, + 0x52, 0x45, 0x44, 0x49, 0x53, 0x5f, 0x53, 0x45, 0x4c, 0x46, 0x5f, 0x48, 0x4f, 0x53, 0x54, 0x45, + 0x44, 0x10, 0x0e, 0x12, 0x2b, 0x0a, 0x27, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, - 0x45, 0x5f, 0x52, 0x45, 0x44, 0x49, 0x53, 0x5f, 0x53, 0x45, 0x4c, 0x46, 0x5f, 0x48, 0x4f, 0x53, - 0x54, 0x45, 0x44, 0x10, 0x0e, 0x12, 0x2b, 0x0a, 0x27, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, - 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, - 0x41, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x53, 0x54, 0x47, 0x52, 0x45, 0x53, 0x5f, 0x47, 0x43, 0x50, - 0x10, 0x0f, 0x12, 0x28, 0x0a, 0x24, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, - 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, - 0x5f, 0x4d, 0x59, 0x53, 0x51, 0x4c, 0x5f, 0x47, 0x43, 0x50, 0x10, 0x10, 0x12, 0x2c, 0x0a, 0x28, - 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, - 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x53, 0x51, 0x4c, 0x53, 0x45, - 0x52, 0x56, 0x45, 0x52, 0x5f, 0x47, 0x43, 0x50, 0x10, 0x11, 0x12, 0x3b, 0x0a, 0x37, 0x44, 0x49, + 0x45, 0x5f, 0x50, 0x4f, 0x53, 0x54, 0x47, 0x52, 0x45, 0x53, 0x5f, 0x47, 0x43, 0x50, 0x10, 0x0f, + 0x12, 0x28, 0x0a, 0x24, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, + 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x4d, + 0x59, 0x53, 0x51, 0x4c, 0x5f, 0x47, 0x43, 0x50, 0x10, 0x10, 0x12, 0x2c, 0x0a, 0x28, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, - 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x53, 0x54, 0x47, 0x52, 0x45, - 0x53, 0x5f, 0x52, 0x45, 0x44, 0x53, 0x48, 0x49, 0x46, 0x54, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x45, - 0x52, 0x4c, 0x45, 0x53, 0x53, 0x10, 0x12, 0x12, 0x2d, 0x0a, 0x29, 0x44, 0x49, 0x53, 0x43, 0x4f, + 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x53, 0x51, 0x4c, 0x53, 0x45, 0x52, 0x56, + 0x45, 0x52, 0x5f, 0x47, 0x43, 0x50, 0x10, 0x11, 0x12, 0x3b, 0x0a, 0x37, 0x44, 0x49, 0x53, 0x43, + 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, + 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x53, 0x54, 0x47, 0x52, 0x45, 0x53, 0x5f, + 0x52, 0x45, 0x44, 0x53, 0x48, 0x49, 0x46, 0x54, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x4c, + 0x45, 0x53, 0x53, 0x10, 0x12, 0x12, 0x2d, 0x0a, 0x29, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, + 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, + 0x41, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x53, 0x54, 0x47, 0x52, 0x45, 0x53, 0x5f, 0x41, 0x5a, 0x55, + 0x52, 0x45, 0x10, 0x13, 0x12, 0x27, 0x0a, 0x23, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, + 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, + 0x53, 0x45, 0x5f, 0x44, 0x59, 0x4e, 0x41, 0x4d, 0x4f, 0x44, 0x42, 0x10, 0x14, 0x12, 0x32, 0x0a, + 0x2e, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, + 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x43, 0x41, 0x53, 0x53, + 0x41, 0x4e, 0x44, 0x52, 0x41, 0x5f, 0x4b, 0x45, 0x59, 0x53, 0x50, 0x41, 0x43, 0x45, 0x53, 0x10, + 0x15, 0x12, 0x34, 0x0a, 0x30, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, + 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, + 0x43, 0x41, 0x53, 0x53, 0x41, 0x4e, 0x44, 0x52, 0x41, 0x5f, 0x53, 0x45, 0x4c, 0x46, 0x5f, 0x48, + 0x4f, 0x53, 0x54, 0x45, 0x44, 0x10, 0x16, 0x12, 0x38, 0x0a, 0x34, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, - 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x53, 0x54, 0x47, 0x52, 0x45, 0x53, 0x5f, 0x41, - 0x5a, 0x55, 0x52, 0x45, 0x10, 0x13, 0x12, 0x27, 0x0a, 0x23, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, - 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, - 0x42, 0x41, 0x53, 0x45, 0x5f, 0x44, 0x59, 0x4e, 0x41, 0x4d, 0x4f, 0x44, 0x42, 0x10, 0x14, 0x12, - 0x32, 0x0a, 0x2e, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, - 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x43, 0x41, - 0x53, 0x53, 0x41, 0x4e, 0x44, 0x52, 0x41, 0x5f, 0x4b, 0x45, 0x59, 0x53, 0x50, 0x41, 0x43, 0x45, - 0x53, 0x10, 0x15, 0x12, 0x34, 0x0a, 0x30, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, + 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x45, 0x4c, 0x41, 0x53, 0x54, 0x49, 0x43, 0x53, 0x45, 0x41, + 0x52, 0x43, 0x48, 0x5f, 0x53, 0x45, 0x4c, 0x46, 0x5f, 0x48, 0x4f, 0x53, 0x54, 0x45, 0x44, 0x10, + 0x17, 0x12, 0x30, 0x0a, 0x2c, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, + 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, + 0x52, 0x45, 0x44, 0x49, 0x53, 0x5f, 0x45, 0x4c, 0x41, 0x53, 0x54, 0x49, 0x43, 0x41, 0x43, 0x48, + 0x45, 0x10, 0x18, 0x12, 0x2d, 0x0a, 0x29, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, - 0x45, 0x5f, 0x43, 0x41, 0x53, 0x53, 0x41, 0x4e, 0x44, 0x52, 0x41, 0x5f, 0x53, 0x45, 0x4c, 0x46, - 0x5f, 0x48, 0x4f, 0x53, 0x54, 0x45, 0x44, 0x10, 0x16, 0x12, 0x38, 0x0a, 0x34, 0x44, 0x49, 0x53, - 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, - 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x45, 0x4c, 0x41, 0x53, 0x54, 0x49, 0x43, 0x53, - 0x45, 0x41, 0x52, 0x43, 0x48, 0x5f, 0x53, 0x45, 0x4c, 0x46, 0x5f, 0x48, 0x4f, 0x53, 0x54, 0x45, - 0x44, 0x10, 0x17, 0x12, 0x30, 0x0a, 0x2c, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, - 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, - 0x45, 0x5f, 0x52, 0x45, 0x44, 0x49, 0x53, 0x5f, 0x45, 0x4c, 0x41, 0x53, 0x54, 0x49, 0x43, 0x41, - 0x43, 0x48, 0x45, 0x10, 0x18, 0x12, 0x2d, 0x0a, 0x29, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, - 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, - 0x41, 0x53, 0x45, 0x5f, 0x52, 0x45, 0x44, 0x49, 0x53, 0x5f, 0x4d, 0x45, 0x4d, 0x4f, 0x52, 0x59, - 0x44, 0x42, 0x10, 0x19, 0x12, 0x30, 0x0a, 0x2c, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, + 0x45, 0x5f, 0x52, 0x45, 0x44, 0x49, 0x53, 0x5f, 0x4d, 0x45, 0x4d, 0x4f, 0x52, 0x59, 0x44, 0x42, + 0x10, 0x19, 0x12, 0x30, 0x0a, 0x2c, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, + 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, + 0x5f, 0x52, 0x45, 0x44, 0x49, 0x53, 0x5f, 0x41, 0x5a, 0x55, 0x52, 0x45, 0x5f, 0x43, 0x41, 0x43, + 0x48, 0x45, 0x10, 0x1a, 0x12, 0x38, 0x0a, 0x34, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, - 0x53, 0x45, 0x5f, 0x52, 0x45, 0x44, 0x49, 0x53, 0x5f, 0x41, 0x5a, 0x55, 0x52, 0x45, 0x5f, 0x43, - 0x41, 0x43, 0x48, 0x45, 0x10, 0x1a, 0x12, 0x38, 0x0a, 0x34, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, - 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, - 0x42, 0x41, 0x53, 0x45, 0x5f, 0x52, 0x45, 0x44, 0x49, 0x53, 0x5f, 0x43, 0x4c, 0x55, 0x53, 0x54, - 0x45, 0x52, 0x5f, 0x53, 0x45, 0x4c, 0x46, 0x5f, 0x48, 0x4f, 0x53, 0x54, 0x45, 0x44, 0x10, 0x1b, - 0x12, 0x2a, 0x0a, 0x26, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, - 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x4d, - 0x59, 0x53, 0x51, 0x4c, 0x5f, 0x41, 0x5a, 0x55, 0x52, 0x45, 0x10, 0x1c, 0x12, 0x2e, 0x0a, 0x2a, - 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, - 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x53, 0x51, 0x4c, 0x53, 0x45, - 0x52, 0x56, 0x45, 0x52, 0x5f, 0x41, 0x5a, 0x55, 0x52, 0x45, 0x10, 0x1d, 0x12, 0x32, 0x0a, 0x2e, - 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, - 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x53, 0x51, 0x4c, 0x53, 0x45, - 0x52, 0x56, 0x45, 0x52, 0x5f, 0x4d, 0x49, 0x43, 0x52, 0x4f, 0x53, 0x4f, 0x46, 0x54, 0x10, 0x1e, - 0x12, 0x36, 0x0a, 0x32, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, - 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x43, - 0x4f, 0x43, 0x4b, 0x52, 0x4f, 0x41, 0x43, 0x48, 0x44, 0x42, 0x5f, 0x53, 0x45, 0x4c, 0x46, 0x5f, - 0x48, 0x4f, 0x53, 0x54, 0x45, 0x44, 0x10, 0x1f, 0x12, 0x2c, 0x0a, 0x28, 0x44, 0x49, 0x53, 0x43, - 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, - 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x4d, 0x4f, 0x4e, 0x47, 0x4f, 0x44, 0x42, 0x5f, 0x41, - 0x54, 0x4c, 0x41, 0x53, 0x10, 0x20, 0x12, 0x28, 0x0a, 0x24, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, + 0x53, 0x45, 0x5f, 0x52, 0x45, 0x44, 0x49, 0x53, 0x5f, 0x43, 0x4c, 0x55, 0x53, 0x54, 0x45, 0x52, + 0x5f, 0x53, 0x45, 0x4c, 0x46, 0x5f, 0x48, 0x4f, 0x53, 0x54, 0x45, 0x44, 0x10, 0x1b, 0x12, 0x2a, + 0x0a, 0x26, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, + 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x4d, 0x59, 0x53, + 0x51, 0x4c, 0x5f, 0x41, 0x5a, 0x55, 0x52, 0x45, 0x10, 0x1c, 0x12, 0x2e, 0x0a, 0x2a, 0x44, 0x49, + 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, + 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x53, 0x51, 0x4c, 0x53, 0x45, 0x52, 0x56, + 0x45, 0x52, 0x5f, 0x41, 0x5a, 0x55, 0x52, 0x45, 0x10, 0x1d, 0x12, 0x32, 0x0a, 0x2e, 0x44, 0x49, + 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, + 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x53, 0x51, 0x4c, 0x53, 0x45, 0x52, 0x56, + 0x45, 0x52, 0x5f, 0x4d, 0x49, 0x43, 0x52, 0x4f, 0x53, 0x4f, 0x46, 0x54, 0x10, 0x1e, 0x12, 0x36, + 0x0a, 0x32, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, + 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x43, 0x4f, 0x43, + 0x4b, 0x52, 0x4f, 0x41, 0x43, 0x48, 0x44, 0x42, 0x5f, 0x53, 0x45, 0x4c, 0x46, 0x5f, 0x48, 0x4f, + 0x53, 0x54, 0x45, 0x44, 0x10, 0x1f, 0x12, 0x2c, 0x0a, 0x28, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, - 0x42, 0x41, 0x53, 0x45, 0x5f, 0x53, 0x4e, 0x4f, 0x57, 0x46, 0x4c, 0x41, 0x4b, 0x45, 0x10, 0x21, - 0x12, 0x2c, 0x0a, 0x28, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, - 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x4f, 0x43, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, - 0x53, 0x45, 0x5f, 0x52, 0x44, 0x53, 0x5f, 0x50, 0x52, 0x4f, 0x58, 0x59, 0x10, 0x22, 0x12, 0x34, - 0x0a, 0x30, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, + 0x42, 0x41, 0x53, 0x45, 0x5f, 0x4d, 0x4f, 0x4e, 0x47, 0x4f, 0x44, 0x42, 0x5f, 0x41, 0x54, 0x4c, + 0x41, 0x53, 0x10, 0x20, 0x12, 0x28, 0x0a, 0x24, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, + 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, + 0x53, 0x45, 0x5f, 0x53, 0x4e, 0x4f, 0x57, 0x46, 0x4c, 0x41, 0x4b, 0x45, 0x10, 0x21, 0x12, 0x2c, + 0x0a, 0x28, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x4f, 0x43, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, - 0x5f, 0x48, 0x49, 0x47, 0x48, 0x5f, 0x41, 0x56, 0x41, 0x49, 0x4c, 0x41, 0x42, 0x49, 0x4c, 0x49, - 0x54, 0x59, 0x10, 0x23, 0x12, 0x37, 0x0a, 0x33, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, - 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x4f, 0x43, 0x5f, 0x44, 0x41, - 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x44, 0x59, 0x4e, 0x41, 0x4d, 0x49, 0x43, 0x5f, 0x52, - 0x45, 0x47, 0x49, 0x53, 0x54, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x24, 0x12, 0x26, 0x0a, - 0x22, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, - 0x43, 0x45, 0x5f, 0x53, 0x41, 0x4d, 0x4c, 0x5f, 0x41, 0x50, 0x50, 0x4c, 0x49, 0x43, 0x41, 0x54, - 0x49, 0x4f, 0x4e, 0x10, 0x25, 0x2a, 0xa3, 0x01, 0x0a, 0x0e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, - 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x0a, 0x1b, 0x44, 0x49, 0x53, 0x43, - 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, - 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x44, 0x49, 0x53, - 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x53, 0x55, 0x43, - 0x43, 0x45, 0x53, 0x53, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, - 0x45, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x53, 0x4b, 0x49, 0x50, 0x50, 0x45, - 0x44, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, - 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x12, 0x1b, - 0x0a, 0x17, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, - 0x53, 0x5f, 0x41, 0x42, 0x4f, 0x52, 0x54, 0x45, 0x44, 0x10, 0x04, 0x2a, 0xc7, 0x01, 0x0a, 0x03, - 0x43, 0x54, 0x41, 0x12, 0x13, 0x0a, 0x0f, 0x43, 0x54, 0x41, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, - 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x43, 0x54, 0x41, 0x5f, - 0x41, 0x55, 0x54, 0x48, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x4f, 0x52, 0x10, 0x01, - 0x12, 0x17, 0x0a, 0x13, 0x43, 0x54, 0x41, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5f, 0x53, - 0x45, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x53, 0x10, 0x02, 0x12, 0x17, 0x0a, 0x13, 0x43, 0x54, 0x41, - 0x5f, 0x41, 0x43, 0x43, 0x45, 0x53, 0x53, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x53, - 0x10, 0x03, 0x12, 0x17, 0x0a, 0x13, 0x43, 0x54, 0x41, 0x5f, 0x50, 0x52, 0x45, 0x4d, 0x49, 0x55, - 0x4d, 0x5f, 0x53, 0x55, 0x50, 0x50, 0x4f, 0x52, 0x54, 0x10, 0x04, 0x12, 0x17, 0x0a, 0x13, 0x43, - 0x54, 0x41, 0x5f, 0x54, 0x52, 0x55, 0x53, 0x54, 0x45, 0x44, 0x5f, 0x44, 0x45, 0x56, 0x49, 0x43, - 0x45, 0x53, 0x10, 0x05, 0x12, 0x16, 0x0a, 0x12, 0x43, 0x54, 0x41, 0x5f, 0x55, 0x50, 0x47, 0x52, - 0x41, 0x44, 0x45, 0x5f, 0x42, 0x41, 0x4e, 0x4e, 0x45, 0x52, 0x10, 0x06, 0x12, 0x17, 0x0a, 0x13, - 0x43, 0x54, 0x41, 0x5f, 0x42, 0x49, 0x4c, 0x4c, 0x49, 0x4e, 0x47, 0x5f, 0x53, 0x55, 0x4d, 0x4d, - 0x41, 0x52, 0x59, 0x10, 0x07, 0x2a, 0xf1, 0x05, 0x0a, 0x15, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x4b, 0x69, 0x6e, 0x64, 0x12, - 0x27, 0x0a, 0x23, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, - 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, - 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x21, 0x0a, 0x1d, 0x49, 0x4e, 0x54, 0x45, - 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, - 0x49, 0x4e, 0x44, 0x5f, 0x53, 0x4c, 0x41, 0x43, 0x4b, 0x10, 0x01, 0x12, 0x24, 0x0a, 0x20, 0x49, + 0x5f, 0x52, 0x44, 0x53, 0x5f, 0x50, 0x52, 0x4f, 0x58, 0x59, 0x10, 0x22, 0x12, 0x34, 0x0a, 0x30, + 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, + 0x45, 0x5f, 0x44, 0x4f, 0x43, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x48, + 0x49, 0x47, 0x48, 0x5f, 0x41, 0x56, 0x41, 0x49, 0x4c, 0x41, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, + 0x10, 0x23, 0x12, 0x37, 0x0a, 0x33, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, + 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x4f, 0x43, 0x5f, 0x44, 0x41, 0x54, 0x41, + 0x42, 0x41, 0x53, 0x45, 0x5f, 0x44, 0x59, 0x4e, 0x41, 0x4d, 0x49, 0x43, 0x5f, 0x52, 0x45, 0x47, + 0x49, 0x53, 0x54, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x24, 0x12, 0x26, 0x0a, 0x22, 0x44, + 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, + 0x5f, 0x53, 0x41, 0x4d, 0x4c, 0x5f, 0x41, 0x50, 0x50, 0x4c, 0x49, 0x43, 0x41, 0x54, 0x49, 0x4f, + 0x4e, 0x10, 0x25, 0x2a, 0xa3, 0x01, 0x0a, 0x0e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x0a, 0x1b, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, + 0x45, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, + 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x44, 0x49, 0x53, 0x43, 0x4f, + 0x56, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, + 0x53, 0x53, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, + 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x53, 0x4b, 0x49, 0x50, 0x50, 0x45, 0x44, 0x10, + 0x02, 0x12, 0x19, 0x0a, 0x15, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x53, 0x54, + 0x41, 0x54, 0x55, 0x53, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x12, 0x1b, 0x0a, 0x17, + 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, + 0x41, 0x42, 0x4f, 0x52, 0x54, 0x45, 0x44, 0x10, 0x04, 0x2a, 0xc7, 0x01, 0x0a, 0x03, 0x43, 0x54, + 0x41, 0x12, 0x13, 0x0a, 0x0f, 0x43, 0x54, 0x41, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, + 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x43, 0x54, 0x41, 0x5f, 0x41, 0x55, + 0x54, 0x48, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x4f, 0x52, 0x10, 0x01, 0x12, 0x17, + 0x0a, 0x13, 0x43, 0x54, 0x41, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5f, 0x53, 0x45, 0x53, + 0x53, 0x49, 0x4f, 0x4e, 0x53, 0x10, 0x02, 0x12, 0x17, 0x0a, 0x13, 0x43, 0x54, 0x41, 0x5f, 0x41, + 0x43, 0x43, 0x45, 0x53, 0x53, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x53, 0x10, 0x03, + 0x12, 0x17, 0x0a, 0x13, 0x43, 0x54, 0x41, 0x5f, 0x50, 0x52, 0x45, 0x4d, 0x49, 0x55, 0x4d, 0x5f, + 0x53, 0x55, 0x50, 0x50, 0x4f, 0x52, 0x54, 0x10, 0x04, 0x12, 0x17, 0x0a, 0x13, 0x43, 0x54, 0x41, + 0x5f, 0x54, 0x52, 0x55, 0x53, 0x54, 0x45, 0x44, 0x5f, 0x44, 0x45, 0x56, 0x49, 0x43, 0x45, 0x53, + 0x10, 0x05, 0x12, 0x16, 0x0a, 0x12, 0x43, 0x54, 0x41, 0x5f, 0x55, 0x50, 0x47, 0x52, 0x41, 0x44, + 0x45, 0x5f, 0x42, 0x41, 0x4e, 0x4e, 0x45, 0x52, 0x10, 0x06, 0x12, 0x17, 0x0a, 0x13, 0x43, 0x54, + 0x41, 0x5f, 0x42, 0x49, 0x4c, 0x4c, 0x49, 0x4e, 0x47, 0x5f, 0x53, 0x55, 0x4d, 0x4d, 0x41, 0x52, + 0x59, 0x10, 0x07, 0x2a, 0xf1, 0x05, 0x0a, 0x15, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x27, 0x0a, + 0x23, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, + 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, + 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x21, 0x0a, 0x1d, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, + 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, + 0x44, 0x5f, 0x53, 0x4c, 0x41, 0x43, 0x4b, 0x10, 0x01, 0x12, 0x24, 0x0a, 0x20, 0x49, 0x4e, 0x54, + 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, + 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x41, 0x57, 0x53, 0x5f, 0x4f, 0x49, 0x44, 0x43, 0x10, 0x02, 0x12, + 0x25, 0x0a, 0x21, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, + 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x52, + 0x44, 0x55, 0x54, 0x59, 0x10, 0x03, 0x12, 0x21, 0x0a, 0x1d, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, + 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, + 0x44, 0x5f, 0x45, 0x4d, 0x41, 0x49, 0x4c, 0x10, 0x04, 0x12, 0x20, 0x0a, 0x1c, 0x49, 0x4e, 0x54, + 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, + 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4a, 0x49, 0x52, 0x41, 0x10, 0x05, 0x12, 0x23, 0x0a, 0x1f, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, - 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x41, 0x57, 0x53, 0x5f, 0x4f, 0x49, 0x44, 0x43, 0x10, - 0x02, 0x12, 0x25, 0x0a, 0x21, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, - 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x50, 0x41, 0x47, - 0x45, 0x52, 0x44, 0x55, 0x54, 0x59, 0x10, 0x03, 0x12, 0x21, 0x0a, 0x1d, 0x49, 0x4e, 0x54, 0x45, + 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x52, 0x44, 0x10, 0x06, + 0x12, 0x26, 0x0a, 0x22, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, + 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4d, 0x41, 0x54, 0x54, + 0x45, 0x52, 0x4d, 0x4f, 0x53, 0x54, 0x10, 0x07, 0x12, 0x24, 0x0a, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, - 0x49, 0x4e, 0x44, 0x5f, 0x45, 0x4d, 0x41, 0x49, 0x4c, 0x10, 0x04, 0x12, 0x20, 0x0a, 0x1c, 0x49, - 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, - 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4a, 0x49, 0x52, 0x41, 0x10, 0x05, 0x12, 0x23, 0x0a, - 0x1f, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, - 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x52, 0x44, - 0x10, 0x06, 0x12, 0x26, 0x0a, 0x22, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, - 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4d, 0x41, - 0x54, 0x54, 0x45, 0x52, 0x4d, 0x4f, 0x53, 0x54, 0x10, 0x07, 0x12, 0x24, 0x0a, 0x20, 0x49, 0x4e, - 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, - 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4d, 0x53, 0x5f, 0x54, 0x45, 0x41, 0x4d, 0x53, 0x10, 0x08, - 0x12, 0x24, 0x0a, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, - 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4f, 0x50, 0x53, 0x47, - 0x45, 0x4e, 0x49, 0x45, 0x10, 0x09, 0x12, 0x20, 0x0a, 0x1c, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, + 0x49, 0x4e, 0x44, 0x5f, 0x4d, 0x53, 0x5f, 0x54, 0x45, 0x41, 0x4d, 0x53, 0x10, 0x08, 0x12, 0x24, + 0x0a, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, + 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4f, 0x50, 0x53, 0x47, 0x45, 0x4e, + 0x49, 0x45, 0x10, 0x09, 0x12, 0x20, 0x0a, 0x1c, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, + 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, + 0x4f, 0x4b, 0x54, 0x41, 0x10, 0x0a, 0x12, 0x20, 0x0a, 0x1c, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, - 0x44, 0x5f, 0x4f, 0x4b, 0x54, 0x41, 0x10, 0x0a, 0x12, 0x20, 0x0a, 0x1c, 0x49, 0x4e, 0x54, 0x45, + 0x44, 0x5f, 0x4a, 0x41, 0x4d, 0x46, 0x10, 0x0b, 0x12, 0x26, 0x0a, 0x22, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, - 0x49, 0x4e, 0x44, 0x5f, 0x4a, 0x41, 0x4d, 0x46, 0x10, 0x0b, 0x12, 0x26, 0x0a, 0x22, 0x49, 0x4e, - 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, - 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4d, 0x41, 0x43, 0x48, 0x49, 0x4e, 0x45, 0x5f, 0x49, 0x44, - 0x10, 0x0c, 0x12, 0x35, 0x0a, 0x31, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, - 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4d, 0x41, - 0x43, 0x48, 0x49, 0x4e, 0x45, 0x5f, 0x49, 0x44, 0x5f, 0x47, 0x49, 0x54, 0x48, 0x55, 0x42, 0x5f, - 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x10, 0x0d, 0x12, 0x2f, 0x0a, 0x2b, 0x49, 0x4e, 0x54, - 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, - 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4d, 0x41, 0x43, 0x48, 0x49, 0x4e, 0x45, 0x5f, 0x49, 0x44, 0x5f, - 0x43, 0x49, 0x52, 0x43, 0x4c, 0x45, 0x43, 0x49, 0x10, 0x0e, 0x12, 0x2d, 0x0a, 0x29, 0x49, 0x4e, - 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, - 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4d, 0x41, 0x43, 0x48, 0x49, 0x4e, 0x45, 0x5f, 0x49, 0x44, - 0x5f, 0x47, 0x49, 0x54, 0x4c, 0x41, 0x42, 0x10, 0x0f, 0x12, 0x2e, 0x0a, 0x2a, 0x49, 0x4e, 0x54, - 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, - 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4d, 0x41, 0x43, 0x48, 0x49, 0x4e, 0x45, 0x5f, 0x49, 0x44, 0x5f, - 0x4a, 0x45, 0x4e, 0x4b, 0x49, 0x4e, 0x53, 0x10, 0x10, 0x12, 0x2e, 0x0a, 0x2a, 0x49, 0x4e, 0x54, - 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, - 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4d, 0x41, 0x43, 0x48, 0x49, 0x4e, 0x45, 0x5f, 0x49, 0x44, 0x5f, - 0x41, 0x4e, 0x53, 0x49, 0x42, 0x4c, 0x45, 0x10, 0x11, 0x2a, 0x88, 0x01, 0x0a, 0x12, 0x45, 0x64, - 0x69, 0x74, 0x6f, 0x72, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x12, 0x24, 0x0a, 0x20, 0x45, 0x44, 0x49, 0x54, 0x4f, 0x52, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, - 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, - 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x25, 0x0a, 0x21, 0x45, 0x44, 0x49, 0x54, 0x4f, 0x52, - 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x52, - 0x4f, 0x4c, 0x45, 0x5f, 0x47, 0x52, 0x41, 0x4e, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x25, 0x0a, - 0x21, 0x45, 0x44, 0x49, 0x54, 0x4f, 0x52, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x53, - 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x52, 0x4f, 0x4c, 0x45, 0x5f, 0x52, 0x45, 0x4d, 0x4f, 0x56, - 0x45, 0x44, 0x10, 0x02, 0x32, 0xb4, 0x02, 0x0a, 0x18, 0x54, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x12, 0x5b, 0x0a, 0x0b, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x12, 0x22, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x88, 0x02, 0x01, 0x12, 0x5b, - 0x0a, 0x0c, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x23, + 0x49, 0x4e, 0x44, 0x5f, 0x4d, 0x41, 0x43, 0x48, 0x49, 0x4e, 0x45, 0x5f, 0x49, 0x44, 0x10, 0x0c, + 0x12, 0x35, 0x0a, 0x31, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, + 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4d, 0x41, 0x43, 0x48, + 0x49, 0x4e, 0x45, 0x5f, 0x49, 0x44, 0x5f, 0x47, 0x49, 0x54, 0x48, 0x55, 0x42, 0x5f, 0x41, 0x43, + 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x10, 0x0d, 0x12, 0x2f, 0x0a, 0x2b, 0x49, 0x4e, 0x54, 0x45, 0x47, + 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, + 0x4e, 0x44, 0x5f, 0x4d, 0x41, 0x43, 0x48, 0x49, 0x4e, 0x45, 0x5f, 0x49, 0x44, 0x5f, 0x43, 0x49, + 0x52, 0x43, 0x4c, 0x45, 0x43, 0x49, 0x10, 0x0e, 0x12, 0x2d, 0x0a, 0x29, 0x49, 0x4e, 0x54, 0x45, + 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, + 0x49, 0x4e, 0x44, 0x5f, 0x4d, 0x41, 0x43, 0x48, 0x49, 0x4e, 0x45, 0x5f, 0x49, 0x44, 0x5f, 0x47, + 0x49, 0x54, 0x4c, 0x41, 0x42, 0x10, 0x0f, 0x12, 0x2e, 0x0a, 0x2a, 0x49, 0x4e, 0x54, 0x45, 0x47, + 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, + 0x4e, 0x44, 0x5f, 0x4d, 0x41, 0x43, 0x48, 0x49, 0x4e, 0x45, 0x5f, 0x49, 0x44, 0x5f, 0x4a, 0x45, + 0x4e, 0x4b, 0x49, 0x4e, 0x53, 0x10, 0x10, 0x12, 0x2e, 0x0a, 0x2a, 0x49, 0x4e, 0x54, 0x45, 0x47, + 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, + 0x4e, 0x44, 0x5f, 0x4d, 0x41, 0x43, 0x48, 0x49, 0x4e, 0x45, 0x5f, 0x49, 0x44, 0x5f, 0x41, 0x4e, + 0x53, 0x49, 0x42, 0x4c, 0x45, 0x10, 0x11, 0x2a, 0x88, 0x01, 0x0a, 0x12, 0x45, 0x64, 0x69, 0x74, + 0x6f, 0x72, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x24, + 0x0a, 0x20, 0x45, 0x44, 0x49, 0x54, 0x4f, 0x52, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, + 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, + 0x45, 0x44, 0x10, 0x00, 0x12, 0x25, 0x0a, 0x21, 0x45, 0x44, 0x49, 0x54, 0x4f, 0x52, 0x5f, 0x43, + 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x52, 0x4f, 0x4c, + 0x45, 0x5f, 0x47, 0x52, 0x41, 0x4e, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x25, 0x0a, 0x21, 0x45, + 0x44, 0x49, 0x54, 0x4f, 0x52, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x53, 0x54, 0x41, + 0x54, 0x55, 0x53, 0x5f, 0x52, 0x4f, 0x4c, 0x45, 0x5f, 0x52, 0x45, 0x4d, 0x4f, 0x56, 0x45, 0x44, + 0x10, 0x02, 0x32, 0xb4, 0x02, 0x0a, 0x18, 0x54, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, + 0x5b, 0x0a, 0x0b, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x22, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, - 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5e, 0x0a, 0x0d, 0x48, - 0x65, 0x6c, 0x6c, 0x6f, 0x54, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x24, 0x2e, 0x70, - 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x48, 0x65, - 0x6c, 0x6c, 0x6f, 0x54, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x54, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0xc9, 0x01, 0x0a, 0x12, - 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x42, 0x0d, 0x54, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x50, 0x01, 0x5a, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x67, 0x72, 0x61, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, - 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x3b, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0xa2, 0x02, 0x03, 0x50, 0x58, 0x58, 0xaa, 0x02, 0x0e, 0x50, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, - 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0xca, 0x02, 0x0e, 0x50, 0x72, 0x65, 0x68, 0x6f, 0x67, - 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0xe2, 0x02, 0x1a, 0x50, 0x72, 0x65, 0x68, 0x6f, - 0x67, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0f, 0x50, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x3a, 0x3a, - 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x88, 0x02, 0x01, 0x12, 0x5b, 0x0a, 0x0c, + 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x23, 0x2e, 0x70, + 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x53, 0x75, + 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x24, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5e, 0x0a, 0x0d, 0x48, 0x65, 0x6c, + 0x6c, 0x6f, 0x54, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x24, 0x2e, 0x70, 0x72, 0x65, + 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x48, 0x65, 0x6c, 0x6c, + 0x6f, 0x54, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x25, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x54, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0xc9, 0x01, 0x0a, 0x12, 0x63, 0x6f, + 0x6d, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x42, 0x0d, 0x54, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, + 0x01, 0x5a, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, + 0x61, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x6c, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, + 0x6f, 0x2f, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x3b, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0xa2, 0x02, + 0x03, 0x50, 0x58, 0x58, 0xaa, 0x02, 0x0e, 0x50, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x56, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0xca, 0x02, 0x0e, 0x50, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x5c, 0x56, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0xe2, 0x02, 0x1a, 0x50, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x5c, + 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0xea, 0x02, 0x0f, 0x50, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x3a, 0x3a, 0x56, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -6178,7 +6414,7 @@ func file_prehog_v1alpha_teleport_proto_rawDescGZIP() []byte { } var file_prehog_v1alpha_teleport_proto_enumTypes = make([]protoimpl.EnumInfo, 8) -var file_prehog_v1alpha_teleport_proto_msgTypes = make([]protoimpl.MessageInfo, 59) +var file_prehog_v1alpha_teleport_proto_msgTypes = make([]protoimpl.MessageInfo, 61) var file_prehog_v1alpha_teleport_proto_goTypes = []interface{}{ (ResourceKind)(0), // 0: prehog.v1alpha.ResourceKind (DiscoverResource)(0), // 1: prehog.v1alpha.DiscoverResource @@ -6236,24 +6472,26 @@ var file_prehog_v1alpha_teleport_proto_goTypes = []interface{}{ (*AssistCompletionEvent)(nil), // 53: prehog.v1alpha.AssistCompletionEvent (*AssistExecutionEvent)(nil), // 54: prehog.v1alpha.AssistExecutionEvent (*AssistNewConversationEvent)(nil), // 55: prehog.v1alpha.AssistNewConversationEvent - (*IntegrationEnrollMetadata)(nil), // 56: prehog.v1alpha.IntegrationEnrollMetadata - (*UIIntegrationEnrollStartEvent)(nil), // 57: prehog.v1alpha.UIIntegrationEnrollStartEvent - (*UIIntegrationEnrollCompleteEvent)(nil), // 58: prehog.v1alpha.UIIntegrationEnrollCompleteEvent - (*EditorChangeEvent)(nil), // 59: prehog.v1alpha.EditorChangeEvent - (*DeviceAuthenticateEvent)(nil), // 60: prehog.v1alpha.DeviceAuthenticateEvent - (*SubmitEventRequest)(nil), // 61: prehog.v1alpha.SubmitEventRequest - (*SubmitEventResponse)(nil), // 62: prehog.v1alpha.SubmitEventResponse - (*SubmitEventsRequest)(nil), // 63: prehog.v1alpha.SubmitEventsRequest - (*SubmitEventsResponse)(nil), // 64: prehog.v1alpha.SubmitEventsResponse - (*HelloTeleportRequest)(nil), // 65: prehog.v1alpha.HelloTeleportRequest - (*HelloTeleportResponse)(nil), // 66: prehog.v1alpha.HelloTeleportResponse - (*durationpb.Duration)(nil), // 67: google.protobuf.Duration - (*timestamppb.Timestamp)(nil), // 68: google.protobuf.Timestamp + (*AssistAccessRequestEvent)(nil), // 56: prehog.v1alpha.AssistAccessRequestEvent + (*AssistActionEvent)(nil), // 57: prehog.v1alpha.AssistActionEvent + (*IntegrationEnrollMetadata)(nil), // 58: prehog.v1alpha.IntegrationEnrollMetadata + (*UIIntegrationEnrollStartEvent)(nil), // 59: prehog.v1alpha.UIIntegrationEnrollStartEvent + (*UIIntegrationEnrollCompleteEvent)(nil), // 60: prehog.v1alpha.UIIntegrationEnrollCompleteEvent + (*EditorChangeEvent)(nil), // 61: prehog.v1alpha.EditorChangeEvent + (*DeviceAuthenticateEvent)(nil), // 62: prehog.v1alpha.DeviceAuthenticateEvent + (*SubmitEventRequest)(nil), // 63: prehog.v1alpha.SubmitEventRequest + (*SubmitEventResponse)(nil), // 64: prehog.v1alpha.SubmitEventResponse + (*SubmitEventsRequest)(nil), // 65: prehog.v1alpha.SubmitEventsRequest + (*SubmitEventsResponse)(nil), // 66: prehog.v1alpha.SubmitEventsResponse + (*HelloTeleportRequest)(nil), // 67: prehog.v1alpha.HelloTeleportRequest + (*HelloTeleportResponse)(nil), // 68: prehog.v1alpha.HelloTeleportResponse + (*durationpb.Duration)(nil), // 69: google.protobuf.Duration + (*timestamppb.Timestamp)(nil), // 70: google.protobuf.Timestamp } var file_prehog_v1alpha_teleport_proto_depIdxs = []int32{ 0, // 0: prehog.v1alpha.ResourceHeartbeatEvent.resource_kind:type_name -> prehog.v1alpha.ResourceKind 13, // 1: prehog.v1alpha.SessionStartEvent.database:type_name -> prehog.v1alpha.SessionStartDatabaseMetadata - 67, // 2: prehog.v1alpha.UserCertificateIssuedEvent.ttl:type_name -> google.protobuf.Duration + 69, // 2: prehog.v1alpha.UserCertificateIssuedEvent.ttl:type_name -> google.protobuf.Duration 1, // 3: prehog.v1alpha.DiscoverResourceMetadata.resource:type_name -> prehog.v1alpha.DiscoverResource 2, // 4: prehog.v1alpha.DiscoverStepStatus.status:type_name -> prehog.v1alpha.DiscoverStatus 25, // 5: prehog.v1alpha.UIDiscoverStartedEvent.metadata:type_name -> prehog.v1alpha.DiscoverMetadata @@ -6301,10 +6539,10 @@ var file_prehog_v1alpha_teleport_proto_depIdxs = []int32{ 27, // 47: prehog.v1alpha.UIDiscoverCompletedEvent.status:type_name -> prehog.v1alpha.DiscoverStepStatus 3, // 48: prehog.v1alpha.UICallToActionClickEvent.cta:type_name -> prehog.v1alpha.CTA 4, // 49: prehog.v1alpha.IntegrationEnrollMetadata.kind:type_name -> prehog.v1alpha.IntegrationEnrollKind - 56, // 50: prehog.v1alpha.UIIntegrationEnrollStartEvent.metadata:type_name -> prehog.v1alpha.IntegrationEnrollMetadata - 56, // 51: prehog.v1alpha.UIIntegrationEnrollCompleteEvent.metadata:type_name -> prehog.v1alpha.IntegrationEnrollMetadata + 58, // 50: prehog.v1alpha.UIIntegrationEnrollStartEvent.metadata:type_name -> prehog.v1alpha.IntegrationEnrollMetadata + 58, // 51: prehog.v1alpha.UIIntegrationEnrollCompleteEvent.metadata:type_name -> prehog.v1alpha.IntegrationEnrollMetadata 5, // 52: prehog.v1alpha.EditorChangeEvent.status:type_name -> prehog.v1alpha.EditorChangeStatus - 68, // 53: prehog.v1alpha.SubmitEventRequest.timestamp:type_name -> google.protobuf.Timestamp + 70, // 53: prehog.v1alpha.SubmitEventRequest.timestamp:type_name -> google.protobuf.Timestamp 8, // 54: prehog.v1alpha.SubmitEventRequest.user_login:type_name -> prehog.v1alpha.UserLoginEvent 9, // 55: prehog.v1alpha.SubmitEventRequest.sso_create:type_name -> prehog.v1alpha.SSOCreateEvent 10, // 56: prehog.v1alpha.SubmitEventRequest.resource_create:type_name -> prehog.v1alpha.ResourceCreateEvent @@ -6345,27 +6583,29 @@ var file_prehog_v1alpha_teleport_proto_depIdxs = []int32{ 31, // 91: prehog.v1alpha.SubmitEventRequest.ui_discover_database_rds_enroll_event:type_name -> prehog.v1alpha.UIDiscoverDatabaseRDSEnrollEvent 49, // 92: prehog.v1alpha.SubmitEventRequest.ui_call_to_action_click_event:type_name -> prehog.v1alpha.UICallToActionClickEvent 53, // 93: prehog.v1alpha.SubmitEventRequest.assist_completion:type_name -> prehog.v1alpha.AssistCompletionEvent - 57, // 94: prehog.v1alpha.SubmitEventRequest.ui_integration_enroll_start_event:type_name -> prehog.v1alpha.UIIntegrationEnrollStartEvent - 58, // 95: prehog.v1alpha.SubmitEventRequest.ui_integration_enroll_complete_event:type_name -> prehog.v1alpha.UIIntegrationEnrollCompleteEvent - 59, // 96: prehog.v1alpha.SubmitEventRequest.editor_change_event:type_name -> prehog.v1alpha.EditorChangeEvent + 59, // 94: prehog.v1alpha.SubmitEventRequest.ui_integration_enroll_start_event:type_name -> prehog.v1alpha.UIIntegrationEnrollStartEvent + 60, // 95: prehog.v1alpha.SubmitEventRequest.ui_integration_enroll_complete_event:type_name -> prehog.v1alpha.UIIntegrationEnrollCompleteEvent + 61, // 96: prehog.v1alpha.SubmitEventRequest.editor_change_event:type_name -> prehog.v1alpha.EditorChangeEvent 43, // 97: prehog.v1alpha.SubmitEventRequest.bot_create:type_name -> prehog.v1alpha.BotCreateEvent 21, // 98: prehog.v1alpha.SubmitEventRequest.ui_onboard_questionnaire_submit:type_name -> prehog.v1alpha.UIOnboardQuestionnaireSubmitEvent 44, // 99: prehog.v1alpha.SubmitEventRequest.bot_join:type_name -> prehog.v1alpha.BotJoinEvent 54, // 100: prehog.v1alpha.SubmitEventRequest.assist_execution:type_name -> prehog.v1alpha.AssistExecutionEvent 55, // 101: prehog.v1alpha.SubmitEventRequest.assist_new_conversation:type_name -> prehog.v1alpha.AssistNewConversationEvent - 60, // 102: prehog.v1alpha.SubmitEventRequest.device_authenticate_event:type_name -> prehog.v1alpha.DeviceAuthenticateEvent - 61, // 103: prehog.v1alpha.SubmitEventsRequest.events:type_name -> prehog.v1alpha.SubmitEventRequest - 61, // 104: prehog.v1alpha.TeleportReportingService.SubmitEvent:input_type -> prehog.v1alpha.SubmitEventRequest - 63, // 105: prehog.v1alpha.TeleportReportingService.SubmitEvents:input_type -> prehog.v1alpha.SubmitEventsRequest - 65, // 106: prehog.v1alpha.TeleportReportingService.HelloTeleport:input_type -> prehog.v1alpha.HelloTeleportRequest - 62, // 107: prehog.v1alpha.TeleportReportingService.SubmitEvent:output_type -> prehog.v1alpha.SubmitEventResponse - 64, // 108: prehog.v1alpha.TeleportReportingService.SubmitEvents:output_type -> prehog.v1alpha.SubmitEventsResponse - 66, // 109: prehog.v1alpha.TeleportReportingService.HelloTeleport:output_type -> prehog.v1alpha.HelloTeleportResponse - 107, // [107:110] is the sub-list for method output_type - 104, // [104:107] is the sub-list for method input_type - 104, // [104:104] is the sub-list for extension type_name - 104, // [104:104] is the sub-list for extension extendee - 0, // [0:104] is the sub-list for field type_name + 62, // 102: prehog.v1alpha.SubmitEventRequest.device_authenticate_event:type_name -> prehog.v1alpha.DeviceAuthenticateEvent + 56, // 103: prehog.v1alpha.SubmitEventRequest.assist_access_request:type_name -> prehog.v1alpha.AssistAccessRequestEvent + 57, // 104: prehog.v1alpha.SubmitEventRequest.assist_action:type_name -> prehog.v1alpha.AssistActionEvent + 63, // 105: prehog.v1alpha.SubmitEventsRequest.events:type_name -> prehog.v1alpha.SubmitEventRequest + 63, // 106: prehog.v1alpha.TeleportReportingService.SubmitEvent:input_type -> prehog.v1alpha.SubmitEventRequest + 65, // 107: prehog.v1alpha.TeleportReportingService.SubmitEvents:input_type -> prehog.v1alpha.SubmitEventsRequest + 67, // 108: prehog.v1alpha.TeleportReportingService.HelloTeleport:input_type -> prehog.v1alpha.HelloTeleportRequest + 64, // 109: prehog.v1alpha.TeleportReportingService.SubmitEvent:output_type -> prehog.v1alpha.SubmitEventResponse + 66, // 110: prehog.v1alpha.TeleportReportingService.SubmitEvents:output_type -> prehog.v1alpha.SubmitEventsResponse + 68, // 111: prehog.v1alpha.TeleportReportingService.HelloTeleport:output_type -> prehog.v1alpha.HelloTeleportResponse + 109, // [109:112] is the sub-list for method output_type + 106, // [106:109] is the sub-list for method input_type + 106, // [106:106] is the sub-list for extension type_name + 106, // [106:106] is the sub-list for extension extendee + 0, // [0:106] is the sub-list for field type_name } func init() { file_prehog_v1alpha_teleport_proto_init() } @@ -6951,7 +7191,7 @@ func file_prehog_v1alpha_teleport_proto_init() { } } file_prehog_v1alpha_teleport_proto_msgTypes[48].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*IntegrationEnrollMetadata); i { + switch v := v.(*AssistAccessRequestEvent); i { case 0: return &v.state case 1: @@ -6963,7 +7203,7 @@ func file_prehog_v1alpha_teleport_proto_init() { } } file_prehog_v1alpha_teleport_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UIIntegrationEnrollStartEvent); i { + switch v := v.(*AssistActionEvent); i { case 0: return &v.state case 1: @@ -6975,7 +7215,7 @@ func file_prehog_v1alpha_teleport_proto_init() { } } file_prehog_v1alpha_teleport_proto_msgTypes[50].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UIIntegrationEnrollCompleteEvent); i { + switch v := v.(*IntegrationEnrollMetadata); i { case 0: return &v.state case 1: @@ -6987,7 +7227,7 @@ func file_prehog_v1alpha_teleport_proto_init() { } } file_prehog_v1alpha_teleport_proto_msgTypes[51].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EditorChangeEvent); i { + switch v := v.(*UIIntegrationEnrollStartEvent); i { case 0: return &v.state case 1: @@ -6999,7 +7239,7 @@ func file_prehog_v1alpha_teleport_proto_init() { } } file_prehog_v1alpha_teleport_proto_msgTypes[52].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DeviceAuthenticateEvent); i { + switch v := v.(*UIIntegrationEnrollCompleteEvent); i { case 0: return &v.state case 1: @@ -7011,7 +7251,7 @@ func file_prehog_v1alpha_teleport_proto_init() { } } file_prehog_v1alpha_teleport_proto_msgTypes[53].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SubmitEventRequest); i { + switch v := v.(*EditorChangeEvent); i { case 0: return &v.state case 1: @@ -7023,7 +7263,7 @@ func file_prehog_v1alpha_teleport_proto_init() { } } file_prehog_v1alpha_teleport_proto_msgTypes[54].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SubmitEventResponse); i { + switch v := v.(*DeviceAuthenticateEvent); i { case 0: return &v.state case 1: @@ -7035,7 +7275,7 @@ func file_prehog_v1alpha_teleport_proto_init() { } } file_prehog_v1alpha_teleport_proto_msgTypes[55].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SubmitEventsRequest); i { + switch v := v.(*SubmitEventRequest); i { case 0: return &v.state case 1: @@ -7047,7 +7287,7 @@ func file_prehog_v1alpha_teleport_proto_init() { } } file_prehog_v1alpha_teleport_proto_msgTypes[56].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SubmitEventsResponse); i { + switch v := v.(*SubmitEventResponse); i { case 0: return &v.state case 1: @@ -7059,7 +7299,7 @@ func file_prehog_v1alpha_teleport_proto_init() { } } file_prehog_v1alpha_teleport_proto_msgTypes[57].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HelloTeleportRequest); i { + switch v := v.(*SubmitEventsRequest); i { case 0: return &v.state case 1: @@ -7071,6 +7311,30 @@ func file_prehog_v1alpha_teleport_proto_init() { } } file_prehog_v1alpha_teleport_proto_msgTypes[58].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SubmitEventsResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_prehog_v1alpha_teleport_proto_msgTypes[59].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HelloTeleportRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_prehog_v1alpha_teleport_proto_msgTypes[60].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HelloTeleportResponse); i { case 0: return &v.state @@ -7083,7 +7347,7 @@ func file_prehog_v1alpha_teleport_proto_init() { } } } - file_prehog_v1alpha_teleport_proto_msgTypes[53].OneofWrappers = []interface{}{ + file_prehog_v1alpha_teleport_proto_msgTypes[55].OneofWrappers = []interface{}{ (*SubmitEventRequest_UserLogin)(nil), (*SubmitEventRequest_SsoCreate)(nil), (*SubmitEventRequest_ResourceCreate)(nil), @@ -7133,6 +7397,8 @@ func file_prehog_v1alpha_teleport_proto_init() { (*SubmitEventRequest_AssistExecution)(nil), (*SubmitEventRequest_AssistNewConversation)(nil), (*SubmitEventRequest_DeviceAuthenticateEvent)(nil), + (*SubmitEventRequest_AssistAccessRequest)(nil), + (*SubmitEventRequest_AssistAction)(nil), } type x struct{} out := protoimpl.TypeBuilder{ @@ -7140,7 +7406,7 @@ func file_prehog_v1alpha_teleport_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_prehog_v1alpha_teleport_proto_rawDesc, NumEnums: 8, - NumMessages: 59, + NumMessages: 61, NumExtensions: 0, NumServices: 1, }, diff --git a/gen/proto/js/prehog/v1alpha/teleport_pb.d.ts b/gen/proto/js/prehog/v1alpha/teleport_pb.d.ts index 6532e505fade4..2df5c0246d12f 100644 --- a/gen/proto/js/prehog/v1alpha/teleport_pb.d.ts +++ b/gen/proto/js/prehog/v1alpha/teleport_pb.d.ts @@ -1492,6 +1492,80 @@ export namespace AssistNewConversationEvent { } } +export class AssistAccessRequestEvent extends jspb.Message { + getUserName(): string; + setUserName(value: string): AssistAccessRequestEvent; + + getResourceType(): string; + setResourceType(value: string): AssistAccessRequestEvent; + + getTotalTokens(): number; + setTotalTokens(value: number): AssistAccessRequestEvent; + + getPromptTokens(): number; + setPromptTokens(value: number): AssistAccessRequestEvent; + + getCompletionTokens(): number; + setCompletionTokens(value: number): AssistAccessRequestEvent; + + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): AssistAccessRequestEvent.AsObject; + static toObject(includeInstance: boolean, msg: AssistAccessRequestEvent): AssistAccessRequestEvent.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: AssistAccessRequestEvent, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): AssistAccessRequestEvent; + static deserializeBinaryFromReader(message: AssistAccessRequestEvent, reader: jspb.BinaryReader): AssistAccessRequestEvent; +} + +export namespace AssistAccessRequestEvent { + export type AsObject = { + userName: string, + resourceType: string, + totalTokens: number, + promptTokens: number, + completionTokens: number, + } +} + +export class AssistActionEvent extends jspb.Message { + getUserName(): string; + setUserName(value: string): AssistActionEvent; + + getAction(): string; + setAction(value: string): AssistActionEvent; + + getTotalTokens(): number; + setTotalTokens(value: number): AssistActionEvent; + + getPromptTokens(): number; + setPromptTokens(value: number): AssistActionEvent; + + getCompletionTokens(): number; + setCompletionTokens(value: number): AssistActionEvent; + + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): AssistActionEvent.AsObject; + static toObject(includeInstance: boolean, msg: AssistActionEvent): AssistActionEvent.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: AssistActionEvent, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): AssistActionEvent; + static deserializeBinaryFromReader(message: AssistActionEvent, reader: jspb.BinaryReader): AssistActionEvent; +} + +export namespace AssistActionEvent { + export type AsObject = { + userName: string, + action: string, + totalTokens: number, + promptTokens: number, + completionTokens: number, + } +} + export class IntegrationEnrollMetadata extends jspb.Message { getId(): string; setId(value: string): IntegrationEnrollMetadata; @@ -1928,6 +2002,18 @@ export class SubmitEventRequest extends jspb.Message { setDeviceAuthenticateEvent(value?: DeviceAuthenticateEvent): SubmitEventRequest; + hasAssistAccessRequest(): boolean; + clearAssistAccessRequest(): void; + getAssistAccessRequest(): AssistAccessRequestEvent | undefined; + setAssistAccessRequest(value?: AssistAccessRequestEvent): SubmitEventRequest; + + + hasAssistAction(): boolean; + clearAssistAction(): void; + getAssistAction(): AssistActionEvent | undefined; + setAssistAction(value?: AssistActionEvent): SubmitEventRequest; + + getEventCase(): SubmitEventRequest.EventCase; serializeBinary(): Uint8Array; @@ -1993,6 +2079,8 @@ export namespace SubmitEventRequest { assistExecution?: AssistExecutionEvent.AsObject, assistNewConversation?: AssistNewConversationEvent.AsObject, deviceAuthenticateEvent?: DeviceAuthenticateEvent.AsObject, + assistAccessRequest?: AssistAccessRequestEvent.AsObject, + assistAction?: AssistActionEvent.AsObject, } export enum EventCase { @@ -2096,6 +2184,10 @@ export namespace SubmitEventRequest { DEVICE_AUTHENTICATE_EVENT = 52, + ASSIST_ACCESS_REQUEST = 54, + + ASSIST_ACTION = 55, + } } diff --git a/gen/proto/js/prehog/v1alpha/teleport_pb.js b/gen/proto/js/prehog/v1alpha/teleport_pb.js index d779c1b9b3e9a..55dee60e841fd 100644 --- a/gen/proto/js/prehog/v1alpha/teleport_pb.js +++ b/gen/proto/js/prehog/v1alpha/teleport_pb.js @@ -20,6 +20,8 @@ goog.object.extend(proto, google_protobuf_duration_pb); var google_protobuf_timestamp_pb = require('google-protobuf/google/protobuf/timestamp_pb.js'); goog.object.extend(proto, google_protobuf_timestamp_pb); goog.exportSymbol('proto.prehog.v1alpha.AgentMetadataEvent', null, global); +goog.exportSymbol('proto.prehog.v1alpha.AssistAccessRequestEvent', null, global); +goog.exportSymbol('proto.prehog.v1alpha.AssistActionEvent', null, global); goog.exportSymbol('proto.prehog.v1alpha.AssistCompletionEvent', null, global); goog.exportSymbol('proto.prehog.v1alpha.AssistExecutionEvent', null, global); goog.exportSymbol('proto.prehog.v1alpha.AssistNewConversationEvent', null, global); @@ -1095,6 +1097,48 @@ if (goog.DEBUG && !COMPILED) { */ proto.prehog.v1alpha.AssistNewConversationEvent.displayName = 'proto.prehog.v1alpha.AssistNewConversationEvent'; } +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.prehog.v1alpha.AssistAccessRequestEvent = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.prehog.v1alpha.AssistAccessRequestEvent, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.prehog.v1alpha.AssistAccessRequestEvent.displayName = 'proto.prehog.v1alpha.AssistAccessRequestEvent'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.prehog.v1alpha.AssistActionEvent = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.prehog.v1alpha.AssistActionEvent, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.prehog.v1alpha.AssistActionEvent.displayName = 'proto.prehog.v1alpha.AssistActionEvent'; +} /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a @@ -11032,8 +11076,8 @@ if (jspb.Message.GENERATE_TO_OBJECT) { * http://goto/soy-param-migration * @return {!Object} */ -proto.prehog.v1alpha.IntegrationEnrollMetadata.prototype.toObject = function(opt_includeInstance) { - return proto.prehog.v1alpha.IntegrationEnrollMetadata.toObject(opt_includeInstance, this); +proto.prehog.v1alpha.AssistAccessRequestEvent.prototype.toObject = function(opt_includeInstance) { + return proto.prehog.v1alpha.AssistAccessRequestEvent.toObject(opt_includeInstance, this); }; @@ -11042,15 +11086,17 @@ proto.prehog.v1alpha.IntegrationEnrollMetadata.prototype.toObject = function(opt * @param {boolean|undefined} includeInstance Deprecated. Whether to include * the JSPB instance for transitional soy proto support: * http://goto/soy-param-migration - * @param {!proto.prehog.v1alpha.IntegrationEnrollMetadata} msg The msg instance to transform. + * @param {!proto.prehog.v1alpha.AssistAccessRequestEvent} msg The msg instance to transform. * @return {!Object} * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.prehog.v1alpha.IntegrationEnrollMetadata.toObject = function(includeInstance, msg) { +proto.prehog.v1alpha.AssistAccessRequestEvent.toObject = function(includeInstance, msg) { var f, obj = { - id: jspb.Message.getFieldWithDefault(msg, 1, ""), - kind: jspb.Message.getFieldWithDefault(msg, 2, 0), - userName: jspb.Message.getFieldWithDefault(msg, 3, "") + userName: jspb.Message.getFieldWithDefault(msg, 1, ""), + resourceType: jspb.Message.getFieldWithDefault(msg, 2, ""), + totalTokens: jspb.Message.getFieldWithDefault(msg, 4, 0), + promptTokens: jspb.Message.getFieldWithDefault(msg, 5, 0), + completionTokens: jspb.Message.getFieldWithDefault(msg, 6, 0) }; if (includeInstance) { @@ -11064,23 +11110,23 @@ proto.prehog.v1alpha.IntegrationEnrollMetadata.toObject = function(includeInstan /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.prehog.v1alpha.IntegrationEnrollMetadata} + * @return {!proto.prehog.v1alpha.AssistAccessRequestEvent} */ -proto.prehog.v1alpha.IntegrationEnrollMetadata.deserializeBinary = function(bytes) { +proto.prehog.v1alpha.AssistAccessRequestEvent.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); - var msg = new proto.prehog.v1alpha.IntegrationEnrollMetadata; - return proto.prehog.v1alpha.IntegrationEnrollMetadata.deserializeBinaryFromReader(msg, reader); + var msg = new proto.prehog.v1alpha.AssistAccessRequestEvent; + return proto.prehog.v1alpha.AssistAccessRequestEvent.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. - * @param {!proto.prehog.v1alpha.IntegrationEnrollMetadata} msg The message object to deserialize into. + * @param {!proto.prehog.v1alpha.AssistAccessRequestEvent} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.prehog.v1alpha.IntegrationEnrollMetadata} + * @return {!proto.prehog.v1alpha.AssistAccessRequestEvent} */ -proto.prehog.v1alpha.IntegrationEnrollMetadata.deserializeBinaryFromReader = function(msg, reader) { +proto.prehog.v1alpha.AssistAccessRequestEvent.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; @@ -11089,15 +11135,23 @@ proto.prehog.v1alpha.IntegrationEnrollMetadata.deserializeBinaryFromReader = fun switch (field) { case 1: var value = /** @type {string} */ (reader.readString()); - msg.setId(value); + msg.setUserName(value); break; case 2: - var value = /** @type {!proto.prehog.v1alpha.IntegrationEnrollKind} */ (reader.readEnum()); - msg.setKind(value); - break; - case 3: var value = /** @type {string} */ (reader.readString()); - msg.setUserName(value); + msg.setResourceType(value); + break; + case 4: + var value = /** @type {number} */ (reader.readInt64()); + msg.setTotalTokens(value); + break; + case 5: + var value = /** @type {number} */ (reader.readInt64()); + msg.setPromptTokens(value); + break; + case 6: + var value = /** @type {number} */ (reader.readInt64()); + msg.setCompletionTokens(value); break; default: reader.skipField(); @@ -11112,9 +11166,9 @@ proto.prehog.v1alpha.IntegrationEnrollMetadata.deserializeBinaryFromReader = fun * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ -proto.prehog.v1alpha.IntegrationEnrollMetadata.prototype.serializeBinary = function() { +proto.prehog.v1alpha.AssistAccessRequestEvent.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); - proto.prehog.v1alpha.IntegrationEnrollMetadata.serializeBinaryToWriter(this, writer); + proto.prehog.v1alpha.AssistAccessRequestEvent.serializeBinaryToWriter(this, writer); return writer.getResultBuffer(); }; @@ -11122,30 +11176,44 @@ proto.prehog.v1alpha.IntegrationEnrollMetadata.prototype.serializeBinary = funct /** * Serializes the given message to binary data (in protobuf wire * format), writing to the given BinaryWriter. - * @param {!proto.prehog.v1alpha.IntegrationEnrollMetadata} message + * @param {!proto.prehog.v1alpha.AssistAccessRequestEvent} message * @param {!jspb.BinaryWriter} writer * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.prehog.v1alpha.IntegrationEnrollMetadata.serializeBinaryToWriter = function(message, writer) { +proto.prehog.v1alpha.AssistAccessRequestEvent.serializeBinaryToWriter = function(message, writer) { var f = undefined; - f = message.getId(); + f = message.getUserName(); if (f.length > 0) { writer.writeString( 1, f ); } - f = message.getKind(); - if (f !== 0.0) { - writer.writeEnum( + f = message.getResourceType(); + if (f.length > 0) { + writer.writeString( 2, f ); } - f = message.getUserName(); - if (f.length > 0) { - writer.writeString( - 3, + f = message.getTotalTokens(); + if (f !== 0) { + writer.writeInt64( + 4, + f + ); + } + f = message.getPromptTokens(); + if (f !== 0) { + writer.writeInt64( + 5, + f + ); + } + f = message.getCompletionTokens(); + if (f !== 0) { + writer.writeInt64( + 6, f ); } @@ -11153,56 +11221,92 @@ proto.prehog.v1alpha.IntegrationEnrollMetadata.serializeBinaryToWriter = functio /** - * optional string id = 1; + * optional string user_name = 1; * @return {string} */ -proto.prehog.v1alpha.IntegrationEnrollMetadata.prototype.getId = function() { +proto.prehog.v1alpha.AssistAccessRequestEvent.prototype.getUserName = function() { return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); }; /** * @param {string} value - * @return {!proto.prehog.v1alpha.IntegrationEnrollMetadata} returns this + * @return {!proto.prehog.v1alpha.AssistAccessRequestEvent} returns this */ -proto.prehog.v1alpha.IntegrationEnrollMetadata.prototype.setId = function(value) { +proto.prehog.v1alpha.AssistAccessRequestEvent.prototype.setUserName = function(value) { return jspb.Message.setProto3StringField(this, 1, value); }; /** - * optional IntegrationEnrollKind kind = 2; - * @return {!proto.prehog.v1alpha.IntegrationEnrollKind} + * optional string resource_type = 2; + * @return {string} */ -proto.prehog.v1alpha.IntegrationEnrollMetadata.prototype.getKind = function() { - return /** @type {!proto.prehog.v1alpha.IntegrationEnrollKind} */ (jspb.Message.getFieldWithDefault(this, 2, 0)); +proto.prehog.v1alpha.AssistAccessRequestEvent.prototype.getResourceType = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); }; /** - * @param {!proto.prehog.v1alpha.IntegrationEnrollKind} value - * @return {!proto.prehog.v1alpha.IntegrationEnrollMetadata} returns this + * @param {string} value + * @return {!proto.prehog.v1alpha.AssistAccessRequestEvent} returns this */ -proto.prehog.v1alpha.IntegrationEnrollMetadata.prototype.setKind = function(value) { - return jspb.Message.setProto3EnumField(this, 2, value); +proto.prehog.v1alpha.AssistAccessRequestEvent.prototype.setResourceType = function(value) { + return jspb.Message.setProto3StringField(this, 2, value); }; /** - * optional string user_name = 3; - * @return {string} + * optional int64 total_tokens = 4; + * @return {number} */ -proto.prehog.v1alpha.IntegrationEnrollMetadata.prototype.getUserName = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); +proto.prehog.v1alpha.AssistAccessRequestEvent.prototype.getTotalTokens = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 4, 0)); }; /** - * @param {string} value - * @return {!proto.prehog.v1alpha.IntegrationEnrollMetadata} returns this + * @param {number} value + * @return {!proto.prehog.v1alpha.AssistAccessRequestEvent} returns this */ -proto.prehog.v1alpha.IntegrationEnrollMetadata.prototype.setUserName = function(value) { - return jspb.Message.setProto3StringField(this, 3, value); +proto.prehog.v1alpha.AssistAccessRequestEvent.prototype.setTotalTokens = function(value) { + return jspb.Message.setProto3IntField(this, 4, value); +}; + + +/** + * optional int64 prompt_tokens = 5; + * @return {number} + */ +proto.prehog.v1alpha.AssistAccessRequestEvent.prototype.getPromptTokens = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 5, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.prehog.v1alpha.AssistAccessRequestEvent} returns this + */ +proto.prehog.v1alpha.AssistAccessRequestEvent.prototype.setPromptTokens = function(value) { + return jspb.Message.setProto3IntField(this, 5, value); +}; + + +/** + * optional int64 completion_tokens = 6; + * @return {number} + */ +proto.prehog.v1alpha.AssistAccessRequestEvent.prototype.getCompletionTokens = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 6, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.prehog.v1alpha.AssistAccessRequestEvent} returns this + */ +proto.prehog.v1alpha.AssistAccessRequestEvent.prototype.setCompletionTokens = function(value) { + return jspb.Message.setProto3IntField(this, 6, value); }; @@ -11222,8 +11326,8 @@ if (jspb.Message.GENERATE_TO_OBJECT) { * http://goto/soy-param-migration * @return {!Object} */ -proto.prehog.v1alpha.UIIntegrationEnrollStartEvent.prototype.toObject = function(opt_includeInstance) { - return proto.prehog.v1alpha.UIIntegrationEnrollStartEvent.toObject(opt_includeInstance, this); +proto.prehog.v1alpha.AssistActionEvent.prototype.toObject = function(opt_includeInstance) { + return proto.prehog.v1alpha.AssistActionEvent.toObject(opt_includeInstance, this); }; @@ -11232,13 +11336,17 @@ proto.prehog.v1alpha.UIIntegrationEnrollStartEvent.prototype.toObject = function * @param {boolean|undefined} includeInstance Deprecated. Whether to include * the JSPB instance for transitional soy proto support: * http://goto/soy-param-migration - * @param {!proto.prehog.v1alpha.UIIntegrationEnrollStartEvent} msg The msg instance to transform. + * @param {!proto.prehog.v1alpha.AssistActionEvent} msg The msg instance to transform. * @return {!Object} * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.prehog.v1alpha.UIIntegrationEnrollStartEvent.toObject = function(includeInstance, msg) { +proto.prehog.v1alpha.AssistActionEvent.toObject = function(includeInstance, msg) { var f, obj = { - metadata: (f = msg.getMetadata()) && proto.prehog.v1alpha.IntegrationEnrollMetadata.toObject(includeInstance, f) + userName: jspb.Message.getFieldWithDefault(msg, 1, ""), + action: jspb.Message.getFieldWithDefault(msg, 2, ""), + totalTokens: jspb.Message.getFieldWithDefault(msg, 4, 0), + promptTokens: jspb.Message.getFieldWithDefault(msg, 5, 0), + completionTokens: jspb.Message.getFieldWithDefault(msg, 6, 0) }; if (includeInstance) { @@ -11252,23 +11360,23 @@ proto.prehog.v1alpha.UIIntegrationEnrollStartEvent.toObject = function(includeIn /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.prehog.v1alpha.UIIntegrationEnrollStartEvent} + * @return {!proto.prehog.v1alpha.AssistActionEvent} */ -proto.prehog.v1alpha.UIIntegrationEnrollStartEvent.deserializeBinary = function(bytes) { +proto.prehog.v1alpha.AssistActionEvent.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); - var msg = new proto.prehog.v1alpha.UIIntegrationEnrollStartEvent; - return proto.prehog.v1alpha.UIIntegrationEnrollStartEvent.deserializeBinaryFromReader(msg, reader); + var msg = new proto.prehog.v1alpha.AssistActionEvent; + return proto.prehog.v1alpha.AssistActionEvent.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. - * @param {!proto.prehog.v1alpha.UIIntegrationEnrollStartEvent} msg The message object to deserialize into. + * @param {!proto.prehog.v1alpha.AssistActionEvent} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.prehog.v1alpha.UIIntegrationEnrollStartEvent} + * @return {!proto.prehog.v1alpha.AssistActionEvent} */ -proto.prehog.v1alpha.UIIntegrationEnrollStartEvent.deserializeBinaryFromReader = function(msg, reader) { +proto.prehog.v1alpha.AssistActionEvent.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; @@ -11276,9 +11384,24 @@ proto.prehog.v1alpha.UIIntegrationEnrollStartEvent.deserializeBinaryFromReader = var field = reader.getFieldNumber(); switch (field) { case 1: - var value = new proto.prehog.v1alpha.IntegrationEnrollMetadata; - reader.readMessage(value,proto.prehog.v1alpha.IntegrationEnrollMetadata.deserializeBinaryFromReader); - msg.setMetadata(value); + var value = /** @type {string} */ (reader.readString()); + msg.setUserName(value); + break; + case 2: + var value = /** @type {string} */ (reader.readString()); + msg.setAction(value); + break; + case 4: + var value = /** @type {number} */ (reader.readInt64()); + msg.setTotalTokens(value); + break; + case 5: + var value = /** @type {number} */ (reader.readInt64()); + msg.setPromptTokens(value); + break; + case 6: + var value = /** @type {number} */ (reader.readInt64()); + msg.setCompletionTokens(value); break; default: reader.skipField(); @@ -11293,9 +11416,9 @@ proto.prehog.v1alpha.UIIntegrationEnrollStartEvent.deserializeBinaryFromReader = * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ -proto.prehog.v1alpha.UIIntegrationEnrollStartEvent.prototype.serializeBinary = function() { +proto.prehog.v1alpha.AssistActionEvent.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); - proto.prehog.v1alpha.UIIntegrationEnrollStartEvent.serializeBinaryToWriter(this, writer); + proto.prehog.v1alpha.AssistActionEvent.serializeBinaryToWriter(this, writer); return writer.getResultBuffer(); }; @@ -11303,36 +11426,457 @@ proto.prehog.v1alpha.UIIntegrationEnrollStartEvent.prototype.serializeBinary = f /** * Serializes the given message to binary data (in protobuf wire * format), writing to the given BinaryWriter. - * @param {!proto.prehog.v1alpha.UIIntegrationEnrollStartEvent} message + * @param {!proto.prehog.v1alpha.AssistActionEvent} message * @param {!jspb.BinaryWriter} writer * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.prehog.v1alpha.UIIntegrationEnrollStartEvent.serializeBinaryToWriter = function(message, writer) { +proto.prehog.v1alpha.AssistActionEvent.serializeBinaryToWriter = function(message, writer) { var f = undefined; - f = message.getMetadata(); - if (f != null) { - writer.writeMessage( + f = message.getUserName(); + if (f.length > 0) { + writer.writeString( 1, - f, - proto.prehog.v1alpha.IntegrationEnrollMetadata.serializeBinaryToWriter + f + ); + } + f = message.getAction(); + if (f.length > 0) { + writer.writeString( + 2, + f + ); + } + f = message.getTotalTokens(); + if (f !== 0) { + writer.writeInt64( + 4, + f + ); + } + f = message.getPromptTokens(); + if (f !== 0) { + writer.writeInt64( + 5, + f + ); + } + f = message.getCompletionTokens(); + if (f !== 0) { + writer.writeInt64( + 6, + f ); } }; /** - * optional IntegrationEnrollMetadata metadata = 1; - * @return {?proto.prehog.v1alpha.IntegrationEnrollMetadata} + * optional string user_name = 1; + * @return {string} */ -proto.prehog.v1alpha.UIIntegrationEnrollStartEvent.prototype.getMetadata = function() { - return /** @type{?proto.prehog.v1alpha.IntegrationEnrollMetadata} */ ( - jspb.Message.getWrapperField(this, proto.prehog.v1alpha.IntegrationEnrollMetadata, 1)); +proto.prehog.v1alpha.AssistActionEvent.prototype.getUserName = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); }; /** - * @param {?proto.prehog.v1alpha.IntegrationEnrollMetadata|undefined} value - * @return {!proto.prehog.v1alpha.UIIntegrationEnrollStartEvent} returns this + * @param {string} value + * @return {!proto.prehog.v1alpha.AssistActionEvent} returns this + */ +proto.prehog.v1alpha.AssistActionEvent.prototype.setUserName = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; + + +/** + * optional string action = 2; + * @return {string} + */ +proto.prehog.v1alpha.AssistActionEvent.prototype.getAction = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** + * @param {string} value + * @return {!proto.prehog.v1alpha.AssistActionEvent} returns this + */ +proto.prehog.v1alpha.AssistActionEvent.prototype.setAction = function(value) { + return jspb.Message.setProto3StringField(this, 2, value); +}; + + +/** + * optional int64 total_tokens = 4; + * @return {number} + */ +proto.prehog.v1alpha.AssistActionEvent.prototype.getTotalTokens = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 4, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.prehog.v1alpha.AssistActionEvent} returns this + */ +proto.prehog.v1alpha.AssistActionEvent.prototype.setTotalTokens = function(value) { + return jspb.Message.setProto3IntField(this, 4, value); +}; + + +/** + * optional int64 prompt_tokens = 5; + * @return {number} + */ +proto.prehog.v1alpha.AssistActionEvent.prototype.getPromptTokens = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 5, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.prehog.v1alpha.AssistActionEvent} returns this + */ +proto.prehog.v1alpha.AssistActionEvent.prototype.setPromptTokens = function(value) { + return jspb.Message.setProto3IntField(this, 5, value); +}; + + +/** + * optional int64 completion_tokens = 6; + * @return {number} + */ +proto.prehog.v1alpha.AssistActionEvent.prototype.getCompletionTokens = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 6, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.prehog.v1alpha.AssistActionEvent} returns this + */ +proto.prehog.v1alpha.AssistActionEvent.prototype.setCompletionTokens = function(value) { + return jspb.Message.setProto3IntField(this, 6, value); +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.prehog.v1alpha.IntegrationEnrollMetadata.prototype.toObject = function(opt_includeInstance) { + return proto.prehog.v1alpha.IntegrationEnrollMetadata.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.prehog.v1alpha.IntegrationEnrollMetadata} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.prehog.v1alpha.IntegrationEnrollMetadata.toObject = function(includeInstance, msg) { + var f, obj = { + id: jspb.Message.getFieldWithDefault(msg, 1, ""), + kind: jspb.Message.getFieldWithDefault(msg, 2, 0), + userName: jspb.Message.getFieldWithDefault(msg, 3, "") + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.prehog.v1alpha.IntegrationEnrollMetadata} + */ +proto.prehog.v1alpha.IntegrationEnrollMetadata.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.prehog.v1alpha.IntegrationEnrollMetadata; + return proto.prehog.v1alpha.IntegrationEnrollMetadata.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.prehog.v1alpha.IntegrationEnrollMetadata} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.prehog.v1alpha.IntegrationEnrollMetadata} + */ +proto.prehog.v1alpha.IntegrationEnrollMetadata.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setId(value); + break; + case 2: + var value = /** @type {!proto.prehog.v1alpha.IntegrationEnrollKind} */ (reader.readEnum()); + msg.setKind(value); + break; + case 3: + var value = /** @type {string} */ (reader.readString()); + msg.setUserName(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.prehog.v1alpha.IntegrationEnrollMetadata.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.prehog.v1alpha.IntegrationEnrollMetadata.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.prehog.v1alpha.IntegrationEnrollMetadata} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.prehog.v1alpha.IntegrationEnrollMetadata.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getId(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } + f = message.getKind(); + if (f !== 0.0) { + writer.writeEnum( + 2, + f + ); + } + f = message.getUserName(); + if (f.length > 0) { + writer.writeString( + 3, + f + ); + } +}; + + +/** + * optional string id = 1; + * @return {string} + */ +proto.prehog.v1alpha.IntegrationEnrollMetadata.prototype.getId = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * @param {string} value + * @return {!proto.prehog.v1alpha.IntegrationEnrollMetadata} returns this + */ +proto.prehog.v1alpha.IntegrationEnrollMetadata.prototype.setId = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; + + +/** + * optional IntegrationEnrollKind kind = 2; + * @return {!proto.prehog.v1alpha.IntegrationEnrollKind} + */ +proto.prehog.v1alpha.IntegrationEnrollMetadata.prototype.getKind = function() { + return /** @type {!proto.prehog.v1alpha.IntegrationEnrollKind} */ (jspb.Message.getFieldWithDefault(this, 2, 0)); +}; + + +/** + * @param {!proto.prehog.v1alpha.IntegrationEnrollKind} value + * @return {!proto.prehog.v1alpha.IntegrationEnrollMetadata} returns this + */ +proto.prehog.v1alpha.IntegrationEnrollMetadata.prototype.setKind = function(value) { + return jspb.Message.setProto3EnumField(this, 2, value); +}; + + +/** + * optional string user_name = 3; + * @return {string} + */ +proto.prehog.v1alpha.IntegrationEnrollMetadata.prototype.getUserName = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); +}; + + +/** + * @param {string} value + * @return {!proto.prehog.v1alpha.IntegrationEnrollMetadata} returns this + */ +proto.prehog.v1alpha.IntegrationEnrollMetadata.prototype.setUserName = function(value) { + return jspb.Message.setProto3StringField(this, 3, value); +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.prehog.v1alpha.UIIntegrationEnrollStartEvent.prototype.toObject = function(opt_includeInstance) { + return proto.prehog.v1alpha.UIIntegrationEnrollStartEvent.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.prehog.v1alpha.UIIntegrationEnrollStartEvent} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.prehog.v1alpha.UIIntegrationEnrollStartEvent.toObject = function(includeInstance, msg) { + var f, obj = { + metadata: (f = msg.getMetadata()) && proto.prehog.v1alpha.IntegrationEnrollMetadata.toObject(includeInstance, f) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.prehog.v1alpha.UIIntegrationEnrollStartEvent} + */ +proto.prehog.v1alpha.UIIntegrationEnrollStartEvent.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.prehog.v1alpha.UIIntegrationEnrollStartEvent; + return proto.prehog.v1alpha.UIIntegrationEnrollStartEvent.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.prehog.v1alpha.UIIntegrationEnrollStartEvent} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.prehog.v1alpha.UIIntegrationEnrollStartEvent} + */ +proto.prehog.v1alpha.UIIntegrationEnrollStartEvent.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = new proto.prehog.v1alpha.IntegrationEnrollMetadata; + reader.readMessage(value,proto.prehog.v1alpha.IntegrationEnrollMetadata.deserializeBinaryFromReader); + msg.setMetadata(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.prehog.v1alpha.UIIntegrationEnrollStartEvent.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.prehog.v1alpha.UIIntegrationEnrollStartEvent.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.prehog.v1alpha.UIIntegrationEnrollStartEvent} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.prehog.v1alpha.UIIntegrationEnrollStartEvent.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getMetadata(); + if (f != null) { + writer.writeMessage( + 1, + f, + proto.prehog.v1alpha.IntegrationEnrollMetadata.serializeBinaryToWriter + ); + } +}; + + +/** + * optional IntegrationEnrollMetadata metadata = 1; + * @return {?proto.prehog.v1alpha.IntegrationEnrollMetadata} + */ +proto.prehog.v1alpha.UIIntegrationEnrollStartEvent.prototype.getMetadata = function() { + return /** @type{?proto.prehog.v1alpha.IntegrationEnrollMetadata} */ ( + jspb.Message.getWrapperField(this, proto.prehog.v1alpha.IntegrationEnrollMetadata, 1)); +}; + + +/** + * @param {?proto.prehog.v1alpha.IntegrationEnrollMetadata|undefined} value + * @return {!proto.prehog.v1alpha.UIIntegrationEnrollStartEvent} returns this */ proto.prehog.v1alpha.UIIntegrationEnrollStartEvent.prototype.setMetadata = function(value) { return jspb.Message.setWrapperField(this, 1, value); @@ -11867,7 +12411,7 @@ proto.prehog.v1alpha.DeviceAuthenticateEvent.prototype.setDeviceOsType = functio * @private {!Array>} * @const */ -proto.prehog.v1alpha.SubmitEventRequest.oneofGroups_ = [[3,4,5,6,7,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52]]; +proto.prehog.v1alpha.SubmitEventRequest.oneofGroups_ = [[3,4,5,6,7,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,54,55]]; /** * @enum {number} @@ -11922,7 +12466,9 @@ proto.prehog.v1alpha.SubmitEventRequest.EventCase = { BOT_JOIN: 49, ASSIST_EXECUTION: 50, ASSIST_NEW_CONVERSATION: 51, - DEVICE_AUTHENTICATE_EVENT: 52 + DEVICE_AUTHENTICATE_EVENT: 52, + ASSIST_ACCESS_REQUEST: 54, + ASSIST_ACTION: 55 }; /** @@ -12013,7 +12559,9 @@ proto.prehog.v1alpha.SubmitEventRequest.toObject = function(includeInstance, msg botJoin: (f = msg.getBotJoin()) && proto.prehog.v1alpha.BotJoinEvent.toObject(includeInstance, f), assistExecution: (f = msg.getAssistExecution()) && proto.prehog.v1alpha.AssistExecutionEvent.toObject(includeInstance, f), assistNewConversation: (f = msg.getAssistNewConversation()) && proto.prehog.v1alpha.AssistNewConversationEvent.toObject(includeInstance, f), - deviceAuthenticateEvent: (f = msg.getDeviceAuthenticateEvent()) && proto.prehog.v1alpha.DeviceAuthenticateEvent.toObject(includeInstance, f) + deviceAuthenticateEvent: (f = msg.getDeviceAuthenticateEvent()) && proto.prehog.v1alpha.DeviceAuthenticateEvent.toObject(includeInstance, f), + assistAccessRequest: (f = msg.getAssistAccessRequest()) && proto.prehog.v1alpha.AssistAccessRequestEvent.toObject(includeInstance, f), + assistAction: (f = msg.getAssistAction()) && proto.prehog.v1alpha.AssistActionEvent.toObject(includeInstance, f) }; if (includeInstance) { @@ -12304,6 +12852,16 @@ proto.prehog.v1alpha.SubmitEventRequest.deserializeBinaryFromReader = function(m reader.readMessage(value,proto.prehog.v1alpha.DeviceAuthenticateEvent.deserializeBinaryFromReader); msg.setDeviceAuthenticateEvent(value); break; + case 54: + var value = new proto.prehog.v1alpha.AssistAccessRequestEvent; + reader.readMessage(value,proto.prehog.v1alpha.AssistAccessRequestEvent.deserializeBinaryFromReader); + msg.setAssistAccessRequest(value); + break; + case 55: + var value = new proto.prehog.v1alpha.AssistActionEvent; + reader.readMessage(value,proto.prehog.v1alpha.AssistActionEvent.deserializeBinaryFromReader); + msg.setAssistAction(value); + break; default: reader.skipField(); break; @@ -12740,6 +13298,22 @@ proto.prehog.v1alpha.SubmitEventRequest.serializeBinaryToWriter = function(messa proto.prehog.v1alpha.DeviceAuthenticateEvent.serializeBinaryToWriter ); } + f = message.getAssistAccessRequest(); + if (f != null) { + writer.writeMessage( + 54, + f, + proto.prehog.v1alpha.AssistAccessRequestEvent.serializeBinaryToWriter + ); + } + f = message.getAssistAction(); + if (f != null) { + writer.writeMessage( + 55, + f, + proto.prehog.v1alpha.AssistActionEvent.serializeBinaryToWriter + ); + } }; @@ -14611,6 +15185,80 @@ proto.prehog.v1alpha.SubmitEventRequest.prototype.hasDeviceAuthenticateEvent = f }; +/** + * optional AssistAccessRequestEvent assist_access_request = 54; + * @return {?proto.prehog.v1alpha.AssistAccessRequestEvent} + */ +proto.prehog.v1alpha.SubmitEventRequest.prototype.getAssistAccessRequest = function() { + return /** @type{?proto.prehog.v1alpha.AssistAccessRequestEvent} */ ( + jspb.Message.getWrapperField(this, proto.prehog.v1alpha.AssistAccessRequestEvent, 54)); +}; + + +/** + * @param {?proto.prehog.v1alpha.AssistAccessRequestEvent|undefined} value + * @return {!proto.prehog.v1alpha.SubmitEventRequest} returns this +*/ +proto.prehog.v1alpha.SubmitEventRequest.prototype.setAssistAccessRequest = function(value) { + return jspb.Message.setOneofWrapperField(this, 54, proto.prehog.v1alpha.SubmitEventRequest.oneofGroups_[0], value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.prehog.v1alpha.SubmitEventRequest} returns this + */ +proto.prehog.v1alpha.SubmitEventRequest.prototype.clearAssistAccessRequest = function() { + return this.setAssistAccessRequest(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.prehog.v1alpha.SubmitEventRequest.prototype.hasAssistAccessRequest = function() { + return jspb.Message.getField(this, 54) != null; +}; + + +/** + * optional AssistActionEvent assist_action = 55; + * @return {?proto.prehog.v1alpha.AssistActionEvent} + */ +proto.prehog.v1alpha.SubmitEventRequest.prototype.getAssistAction = function() { + return /** @type{?proto.prehog.v1alpha.AssistActionEvent} */ ( + jspb.Message.getWrapperField(this, proto.prehog.v1alpha.AssistActionEvent, 55)); +}; + + +/** + * @param {?proto.prehog.v1alpha.AssistActionEvent|undefined} value + * @return {!proto.prehog.v1alpha.SubmitEventRequest} returns this +*/ +proto.prehog.v1alpha.SubmitEventRequest.prototype.setAssistAction = function(value) { + return jspb.Message.setOneofWrapperField(this, 55, proto.prehog.v1alpha.SubmitEventRequest.oneofGroups_[0], value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.prehog.v1alpha.SubmitEventRequest} returns this + */ +proto.prehog.v1alpha.SubmitEventRequest.prototype.clearAssistAction = function() { + return this.setAssistAction(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.prehog.v1alpha.SubmitEventRequest.prototype.hasAssistAction = function() { + return jspb.Message.getField(this, 55) != null; +}; + + diff --git a/lib/ai/chat.go b/lib/ai/chat.go index 986880c00f244..6094f44d4ebfc 100644 --- a/lib/ai/chat.go +++ b/lib/ai/chat.go @@ -65,6 +65,11 @@ func (chat *Chat) Complete(ctx context.Context, userInput string, progressUpdate }, model.NewTokenCount(), nil } + return chat.Reply(ctx, userInput, progressUpdates) +} + +// Reply replies to the user input with a message from the assistant based on the current context. +func (chat *Chat) Reply(ctx context.Context, userInput string, progressUpdates func(*model.AgentAction)) (any, *model.TokenCount, error) { userMessage := openai.ChatCompletionMessage{ Role: openai.ChatMessageRoleUser, Content: userInput, diff --git a/lib/ai/chat_test.go b/lib/ai/chat_test.go index a969f669f8bf3..ee21f3e3ffefc 100644 --- a/lib/ai/chat_test.go +++ b/lib/ai/chat_test.go @@ -51,7 +51,7 @@ func TestChat_PromptTokens(t *testing.T) { Content: "Hello", }, }, - want: 721, + want: 610, }, { name: "system and user messages", @@ -65,7 +65,7 @@ func TestChat_PromptTokens(t *testing.T) { Content: "Hi LLM.", }, }, - want: 729, + want: 618, }, { name: "tokenize our prompt", @@ -79,7 +79,7 @@ func TestChat_PromptTokens(t *testing.T) { Content: "Show me free disk space on localhost node.", }, }, - want: 932, + want: 821, }, } @@ -108,7 +108,10 @@ func TestChat_PromptTokens(t *testing.T) { cfg.BaseURL = server.URL + "/v1" client := NewClientFromConfig(cfg) - chat := client.NewChat(nil, "Bob") + + toolsConfig := model.ToolsConfig{DisableEmbeddingsTool: true} + chat, err := client.NewChat("Bob", toolsConfig) + require.NoError(t, err) for _, message := range tt.messages { chat.Insert(message.Role, message.Content) @@ -149,10 +152,12 @@ func TestChat_Complete(t *testing.T) { cfg.BaseURL = server.URL + "/v1" client := NewClientFromConfig(cfg) - chat := client.NewChat(nil, "Bob") + toolsConfig := model.ToolsConfig{DisableEmbeddingsTool: true} + chat, err := client.NewChat("Bob", toolsConfig) + require.NoError(t, err) ctx := context.Background() - _, _, err := chat.Complete(ctx, "Hello", func(aa *model.AgentAction) {}) + _, _, err = chat.Complete(ctx, "Hello", func(aa *model.AgentAction) {}) require.NoError(t, err) chat.Insert(openai.ChatMessageRoleUser, "Show me free disk space on localhost node.") diff --git a/lib/ai/client.go b/lib/ai/client.go index 056fd471fef98..9ae56effbbb2c 100644 --- a/lib/ai/client.go +++ b/lib/ai/client.go @@ -23,10 +23,14 @@ import ( "github.com/sashabaranov/go-openai" "github.com/tiktoken-go/tokenizer/codec" - "github.com/gravitational/teleport/api/gen/proto/go/assist/v1" + "github.com/gravitational/teleport/lib/ai/embedding" "github.com/gravitational/teleport/lib/ai/model" ) +const ( + maxOpenAIEmbeddingsPerRequest = 1000 +) + // Client is a client for OpenAI API. type Client struct { svc *openai.Client @@ -44,8 +48,20 @@ func NewClientFromConfig(config openai.ClientConfig) *Client { // NewChat creates a new chat. The username is set in the conversation context, // so that the AI can use it to personalize the conversation. -// embeddingServiceClient is used to get the embeddings from the Auth Server. -func (client *Client) NewChat(embeddingServiceClient assist.AssistEmbeddingServiceClient, username string) *Chat { +// toolsConfig contains all required clients and configuration for agent tools +// to interact with Teleport. +func (client *Client) NewChat(username string, toolsConfig model.ToolsConfig) (*Chat, error) { + tools := []model.Tool{ + model.NewExecutionTool(), + } + if !toolsConfig.DisableEmbeddingsTool { + tools = append(tools, model.NewRetrievalTool(toolsConfig.EmbeddingsClient, toolsConfig.NodeClient, + toolsConfig.AccessChecker, username)) + } + agent, err := model.NewAgent(tools...) + if err != nil { + return nil, trace.Wrap(err) + } return &Chat{ client: client, messages: []openai.ChatCompletionMessage{ @@ -57,8 +73,28 @@ func (client *Client) NewChat(embeddingServiceClient assist.AssistEmbeddingServi // Initialize a tokenizer for prompt token accounting. // Cl100k is used by GPT-3 and GPT-4. tokenizer: codec.NewCl100kBase(), - agent: model.NewAgent(embeddingServiceClient, username), + agent: agent, + }, nil +} + +func (client *Client) NewCommand(username string) (*Chat, error) { + agent, err := model.NewAgent(model.NewGenerateTool()) + if err != nil { + return nil, trace.Wrap(err) } + return &Chat{ + client: client, + messages: []openai.ChatCompletionMessage{ + { + Role: openai.ChatMessageRoleSystem, + Content: model.PromptCharacter(username), + }, + }, + // Initialize a tokenizer for prompt token accounting. + // Cl100k is used by GPT-3 and GPT-4. + tokenizer: codec.NewCl100kBase(), + agent: agent, + }, nil } // Summary creates a short summary for the given input. @@ -112,7 +148,7 @@ func (client *Client) CommandSummary(ctx context.Context, messages []openai.Chat return completion, tc, trace.Wrap(err) } -// ClassifyMessage takes a user message, a list of categories, and uses the AI mode as a zero shot classifier. +// ClassifyMessage takes a user message, a list of categories, and uses the AI mode as a zero-shot classifier. func (client *Client) ClassifyMessage(ctx context.Context, message string, classes map[string]string) (string, error) { resp, err := client.svc.CreateChatCompletion( ctx, @@ -131,3 +167,52 @@ func (client *Client) ClassifyMessage(ctx context.Context, message string, class return resp.Choices[0].Message.Content, nil } + +// ComputeEmbeddings takes a map of nodes and calls openAI to generate +// embeddings for those nodes. ComputeEmbeddings is responsible for +// implementing a retry mechanism if the embedding computation is flaky. +func (client *Client) ComputeEmbeddings(ctx context.Context, input []string) ([]embedding.Vector64, error) { + var results []embedding.Vector64 + for i := 0; maxOpenAIEmbeddingsPerRequest*i < len(input); i++ { + result, err := client.computeEmbeddings(ctx, paginateInput(input, i, maxOpenAIEmbeddingsPerRequest)) + if err != nil { + return nil, trace.Wrap(err) + } + for _, vector := range result { + results = append(results, embedding.Vector32to64(vector)) + } + } + return results, nil +} + +func paginateInput(input []string, page, pageSize int) []string { + begin := page * pageSize + var end int + if len(input) < (page+1)*pageSize { + end = len(input) + } else { + end = (page + 1) * pageSize + } + return input[begin:end] +} + +// computeEmbeddings calls the openAI embedding model with the provided input. +// This function should not be called directly, use ComputeEmbeddings instead +// to ensure input is properly batched. +func (client *Client) computeEmbeddings(ctx context.Context, input []string) ([]embedding.Vector32, error) { + req := openai.EmbeddingRequest{ + Input: input, + Model: openai.AdaEmbeddingV2, + } + + // Execute the query + resp, err := client.svc.CreateEmbeddings(ctx, req) + if err != nil { + return nil, trace.Wrap(err) + } + result := make([]embedding.Vector32, len(input)) + for i, item := range resp.Data { + result[i] = item.Embedding + } + return result, nil +} diff --git a/lib/ai/embedding.go b/lib/ai/embedding/embedding.go similarity index 56% rename from lib/ai/embedding.go rename to lib/ai/embedding/embedding.go index c145024256593..8abe1f24359bd 100644 --- a/lib/ai/embedding.go +++ b/lib/ai/embedding/embedding.go @@ -1,34 +1,29 @@ -// Copyright 2023 Gravitational, Inc -// -// 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. - -package ai +/* + * Copyright 2023 Gravitational, Inc. + * + * 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. + */ + +package embedding import ( "context" "crypto/sha256" - "github.com/gravitational/trace" - "github.com/sashabaranov/go-openai" - embeddingpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/embedding/v1" "github.com/gravitational/teleport/lib/backend" ) -const ( - maxOpenAIEmbeddingsPerRequest = 1000 -) - // EmbeddingHash is the hash function that should be used to compute embedding // hashes. var EmbeddingHash = sha256.Sum256 @@ -48,6 +43,16 @@ type Vector32 = []float32 // requiring 64-bit floats. type Vector64 = []float64 +// Embedder is implemented for batch text embedding. Embedding can happen in +// place (with an embedding model, for example) or be done by a remote embedding +// service like OpenAI. +type Embedder interface { + // ComputeEmbeddings computes the embeddings of multiple strings. + // The embedding list follows the input order (e.g., result[i] is the + // embedding of input[i]). + ComputeEmbeddings(ctx context.Context, input []string) ([]Vector64, error) +} + // Embedding contains a Teleport resource embedding. Embeddings are small semantic // representations of larger and more complex data. Embeddings can be compared, // the smaller the distance between two vectors, the closer the concepts are. @@ -77,6 +82,18 @@ func (e *Embedding) GetVector() Vector64 { return e.Vector } +// Dimensions returns the number of dimensions of the embedding +// Implements kdtree.Point interface +func (e *Embedding) Dimensions() int { + return len(e.Vector) +} + +// Dimension returns the value of the i-th dimension +// Implements kdtree.Point interface +func (e *Embedding) Dimension(i int) float64 { + return e.Vector[i] +} + // NewEmbedding is an Embedding constructor. func NewEmbedding(kind, id string, vector Vector64, hash Sha256Hash) *Embedding { return &Embedding{ @@ -87,69 +104,10 @@ func NewEmbedding(kind, id string, vector Vector64, hash Sha256Hash) *Embedding } } -// Embedder is implemented for batch text embedding. Embedding can happen in -// place (with an embedding model, for example) or be done by a remote embedding -// service like OpenAI. -type Embedder interface { - // ComputeEmbeddings computes the embeddings of multiple strings. - // The embedding list follows the input order (e.g., result[i] is the - // embedding of input[i]). - ComputeEmbeddings(ctx context.Context, input []string) ([]Vector64, error) -} - -// ComputeEmbeddings taxes a map of nodes and calls openAI to generate -// embeddings for those nodes. ComputeEmbeddings is responsible for -// implementing a retry mechanism if the embedding computation is flaky. -func (client *Client) ComputeEmbeddings(ctx context.Context, input []string) ([]Vector64, error) { - var results []Vector64 - for i := 0; maxOpenAIEmbeddingsPerRequest*i < len(input); i++ { - result, err := client.computeEmbeddings(ctx, paginateInput(input, i, maxOpenAIEmbeddingsPerRequest)) - if err != nil { - return nil, trace.Wrap(err) - } - for _, vector := range result { - results = append(results, vector32to64(vector)) - } - } - return results, nil -} - -func paginateInput(input []string, page, pageSize int) []string { - begin := page * pageSize - var end int - if len(input) < (page+1)*pageSize { - end = len(input) - } else { - end = (page + 1) * pageSize - } - return input[begin:end] -} - -func vector32to64(vector32 Vector32) Vector64 { +func Vector32to64(vector32 Vector32) Vector64 { vector64 := make(Vector64, len(vector32)) for i, dimension := range vector32 { vector64[i] = float64(dimension) } return vector64 } - -// computeEmbeddings calls the openAI embedding model with the provided input. -// This function should not be called directly, use ComputeEmbeddings instead -// to ensure input is properly batched. -func (client *Client) computeEmbeddings(ctx context.Context, input []string) ([]Vector32, error) { - req := openai.EmbeddingRequest{ - Input: input, - Model: openai.AdaEmbeddingV2, - } - - // Execute the query - resp, err := client.svc.CreateEmbeddings(ctx, req) - if err != nil { - return nil, trace.Wrap(err) - } - result := make([]Vector32, len(input)) - for i, item := range resp.Data { - result[i] = item.Embedding - } - return result, nil -} diff --git a/lib/ai/embedding/serialization.go b/lib/ai/embedding/serialization.go new file mode 100644 index 0000000000000..ecf33ed7cf472 --- /dev/null +++ b/lib/ai/embedding/serialization.go @@ -0,0 +1,44 @@ +/* + * Copyright 2023 Gravitational, Inc. + * + * 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. + */ + +package embedding + +import ( + "github.com/gravitational/trace" + "gopkg.in/yaml.v3" + + "github.com/gravitational/teleport/api/types" +) + +// SerializeNode converts a type.Server into text ready to be fed to an +// embedding model. The YAML serialization function was chosen over JSON and +// CSV as it provided better results. +func SerializeNode(node types.Server) ([]byte, error) { + a := struct { + Name string `yaml:"name"` + Kind string `yaml:"kind"` + SubKind string `yaml:"subkind"` + Labels map[string]string `yaml:"labels"` + }{ + // Create artificial Name file for the node "name". Using node.GetName() as Name seems to confuse the model. + Name: node.GetHostname(), + Kind: types.KindNode, + SubKind: node.GetSubKind(), + Labels: node.GetAllLabels(), + } + text, err := yaml.Marshal(&a) + return text, trace.Wrap(err) +} diff --git a/lib/ai/embeddings.go b/lib/ai/embeddingprocessor.go similarity index 84% rename from lib/ai/embeddings.go rename to lib/ai/embeddingprocessor.go index 62cd55590819a..e02da4d7f93f4 100644 --- a/lib/ai/embeddings.go +++ b/lib/ai/embeddingprocessor.go @@ -24,13 +24,13 @@ import ( "github.com/gravitational/trace" "github.com/sirupsen/logrus" "google.golang.org/protobuf/proto" - "gopkg.in/yaml.v3" "github.com/gravitational/teleport/api/defaults" embeddingpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/embedding/v1" "github.com/gravitational/teleport/api/internalutils/stream" "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/api/utils/retryutils" + embeddinglib "github.com/gravitational/teleport/lib/ai/embedding" streamutils "github.com/gravitational/teleport/lib/utils/stream" ) @@ -40,9 +40,9 @@ const maxEmbeddingAPISize = 1000 // Embeddings implements the minimal interface used by the Embedding processor. type Embeddings interface { // GetEmbeddings returns all embeddings for a given kind. - GetEmbeddings(ctx context.Context, kind string) stream.Stream[*Embedding] + GetEmbeddings(ctx context.Context, kind string) stream.Stream[*embeddinglib.Embedding] // UpsertEmbedding creates or update a single ai.Embedding in the backend. - UpsertEmbedding(ctx context.Context, embedding *Embedding) (*Embedding, error) + UpsertEmbedding(ctx context.Context, embedding *embeddinglib.Embedding) (*embeddinglib.Embedding, error) } // NodesStreamGetter is a service that gets nodes. @@ -52,7 +52,7 @@ type NodesStreamGetter interface { } // MarshalEmbedding marshals the ai.Embedding resource to binary ProtoBuf. -func MarshalEmbedding(embedding *Embedding) ([]byte, error) { +func MarshalEmbedding(embedding *embeddinglib.Embedding) ([]byte, error) { data, err := proto.Marshal((*embeddingpb.Embedding)(embedding)) if err != nil { return nil, trace.Wrap(err) @@ -61,7 +61,7 @@ func MarshalEmbedding(embedding *Embedding) ([]byte, error) { } // UnmarshalEmbedding unmarshals binary ProtoBuf into an ai.Embedding resource. -func UnmarshalEmbedding(bytes []byte) (*Embedding, error) { +func UnmarshalEmbedding(bytes []byte) (*embeddinglib.Embedding, error) { if len(bytes) == 0 { return nil, trace.BadParameter("missing embedding data") } @@ -71,37 +71,17 @@ func UnmarshalEmbedding(bytes []byte) (*Embedding, error) { return nil, trace.Wrap(err) } - return (*Embedding)(&embedding), nil + return (*embeddinglib.Embedding)(&embedding), nil } // EmbeddingHashMatches returns true if the hash of the embedding matches the // given hash. -func EmbeddingHashMatches(embedding *Embedding, hash Sha256Hash) bool { +func EmbeddingHashMatches(embedding *embeddinglib.Embedding, hash embeddinglib.Sha256Hash) bool { if len(embedding.EmbeddedHash) != 32 { return false } - return *(*Sha256Hash)(embedding.EmbeddedHash) == hash -} - -// SerializeNode converts a type.Server into text ready to be fed to an -// embedding model. The YAML serialization function was chosen over JSON and -// CSV as it provided better results. -func SerializeNode(node types.Server) ([]byte, error) { - a := struct { - Name string `yaml:"name"` - Kind string `yaml:"kind"` - SubKind string `yaml:"subkind"` - Labels map[string]string `yaml:"labels"` - }{ - // Create artificial Name file for the node "name". Using node.GetName() as Name seems to confuse the model. - Name: node.GetHostname(), - Kind: types.KindNode, - SubKind: node.GetSubKind(), - Labels: node.GetAllLabels(), - } - text, err := yaml.Marshal(&a) - return text, trace.Wrap(err) + return *(*embeddinglib.Sha256Hash)(embedding.EmbeddedHash) == hash } // BatchReducer is a helper that processes data in batches. @@ -149,7 +129,7 @@ func (b *BatchReducer[T, V]) Finalize(ctx context.Context) (V, error) { // EmbeddingProcessorConfig is the configuration for EmbeddingProcessor. type EmbeddingProcessorConfig struct { - AIClient Embedder + AIClient embeddinglib.Embedder EmbeddingSrv Embeddings EmbeddingsRetriever *SimpleRetriever NodeSrv NodesStreamGetter @@ -160,7 +140,7 @@ type EmbeddingProcessorConfig struct { // EmbeddingProcessor is responsible for processing nodes, generating embeddings // and storing their embeddings in the backend. type EmbeddingProcessor struct { - aiClient Embedder + aiClient embeddinglib.Embedder embeddingSrv Embeddings embeddingsRetriever *SimpleRetriever nodeSrv NodesStreamGetter @@ -188,7 +168,7 @@ type nodeStringPair struct { // mapProcessFn is a helper function that maps a slice of nodeStringPair, // compute embeddings and return them as a slice of ai.Embedding. -func (e *EmbeddingProcessor) mapProcessFn(ctx context.Context, data []*nodeStringPair) ([]*Embedding, error) { +func (e *EmbeddingProcessor) mapProcessFn(ctx context.Context, data []*nodeStringPair) ([]*embeddinglib.Embedding, error) { dataBatch := make([]string, 0, len(data)) for _, pair := range data { dataBatch = append(dataBatch, pair.data) @@ -199,11 +179,11 @@ func (e *EmbeddingProcessor) mapProcessFn(ctx context.Context, data []*nodeStrin return nil, trace.Wrap(err) } - results := make([]*Embedding, 0, len(embeddings)) + results := make([]*embeddinglib.Embedding, 0, len(embeddings)) for i, embedding := range embeddings { - emb := NewEmbedding(types.KindNode, + emb := embeddinglib.NewEmbedding(types.KindNode, data[i].node.GetName(), embedding, - EmbeddingHash([]byte(data[i].data)), + embeddinglib.EmbeddingHash([]byte(data[i].data)), ) results = append(results, emb) } @@ -245,7 +225,7 @@ func (e *EmbeddingProcessor) process(ctx context.Context) { embeddingsStream, // On new node callback. Add the node to the batch. func(node types.Server) error { - nodeData, err := SerializeNode(node) + nodeData, err := embeddinglib.SerializeNode(node) if err != nil { return trace.Wrap(err) } @@ -261,12 +241,12 @@ func (e *EmbeddingProcessor) process(ctx context.Context) { }, // On equal node callback. Check if the node's embedding hash matches // the one in the backend. If not, add the node to the batch. - func(node types.Server, embedding *Embedding) error { - nodeData, err := SerializeNode(node) + func(node types.Server, embedding *embeddinglib.Embedding) error { + nodeData, err := embeddinglib.SerializeNode(node) if err != nil { return trace.Wrap(err) } - nodeHash := EmbeddingHash(nodeData) + nodeHash := embeddinglib.EmbeddingHash(nodeData) if !EmbeddingHashMatches(embedding, nodeHash) { vectors, err := batch.Add(ctx, &nodeStringPair{node, string(nodeData)}) @@ -280,7 +260,7 @@ func (e *EmbeddingProcessor) process(ctx context.Context) { return nil }, // On compare keys callback. Compare the keys for iteration. - func(node types.Server, embeddings *Embedding) int { + func(node types.Server, embeddings *embeddinglib.Embedding) int { return strings.Compare(node.GetName(), embeddings.GetEmbeddedID()) }, ) @@ -330,7 +310,7 @@ func (e *EmbeddingProcessor) updateMemIndex(ctx context.Context) error { } // upsertEmbeddings is a helper function that upserts the embeddings into the backend. -func (e *EmbeddingProcessor) upsertEmbeddings(ctx context.Context, rawEmbeddings []*Embedding) error { +func (e *EmbeddingProcessor) upsertEmbeddings(ctx context.Context, rawEmbeddings []*embeddinglib.Embedding) error { // Store the new embeddings into the backend for _, embedding := range rawEmbeddings { _, err := e.embeddingSrv.UpsertEmbedding(ctx, embedding) diff --git a/lib/ai/embeddings_test.go b/lib/ai/embeddingprocessor_test.go similarity index 95% rename from lib/ai/embeddings_test.go rename to lib/ai/embeddingprocessor_test.go index 7cedaba69c59c..227e90c2f45c4 100644 --- a/lib/ai/embeddings_test.go +++ b/lib/ai/embeddingprocessor_test.go @@ -35,6 +35,7 @@ import ( "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/api/utils/retryutils" "github.com/gravitational/teleport/lib/ai" + "github.com/gravitational/teleport/lib/ai/embedding" "github.com/gravitational/teleport/lib/backend/memory" "github.com/gravitational/teleport/lib/services/local" "github.com/gravitational/teleport/lib/utils" @@ -47,13 +48,13 @@ type MockEmbedder struct { timesCalled map[string]int } -func (m MockEmbedder) ComputeEmbeddings(_ context.Context, input []string) ([]ai.Vector64, error) { - result := make([]ai.Vector64, len(input)) +func (m MockEmbedder) ComputeEmbeddings(_ context.Context, input []string) ([]embedding.Vector64, error) { + result := make([]embedding.Vector64, len(input)) for i, text := range input { name := strings.Split(text, "\n")[0] m.timesCalled[name]++ hash := sha256.Sum256([]byte(text)) - vector := make(ai.Vector64, len(hash)) + vector := make(embedding.Vector64, len(hash)) for j, x := range hash { vector[j] = 1 / float64(int(x)+1) } @@ -183,7 +184,7 @@ func TestNodeEmbeddingGeneration(t *testing.T) { func TestMarshallUnmarshallEmbedding(t *testing.T) { // We test that float precision is above six digits - initial := ai.NewEmbedding(types.KindNode, "foo", ai.Vector64{0.1234567, 1, 1}, sha256.Sum256([]byte("test"))) + initial := embedding.NewEmbedding(types.KindNode, "foo", embedding.Vector64{0.1234567, 1, 1}, sha256.Sum256([]byte("test"))) marshaled, err := ai.MarshalEmbedding(initial) require.NoError(t, err) @@ -209,7 +210,7 @@ func makeNode(num int) types.Server { return node } -func validateEmbeddings(t *testing.T, nodesStream stream.Stream[types.Server], embeddingsStream stream.Stream[*ai.Embedding]) { +func validateEmbeddings(t *testing.T, nodesStream stream.Stream[types.Server], embeddingsStream stream.Stream[*embedding.Embedding]) { t.Helper() nodes, err := stream.Collect(nodesStream) diff --git a/lib/ai/knnretriever.go b/lib/ai/knnretriever.go index e427510994f3f..ca948e9339d9c 100644 --- a/lib/ai/knnretriever.go +++ b/lib/ai/knnretriever.go @@ -19,30 +19,20 @@ package ai import ( "github.com/gravitational/trace" "github.com/kyroy/kdtree" + + "github.com/gravitational/teleport/lib/ai/embedding" ) // Document is a embedding enriched with similarity score type Document struct { - *Embedding + *embedding.Embedding SimilarityScore float64 } -// Dimensions returns the number of dimensions of the embedding -// Implements kdtree.Point interface -func (e *Embedding) Dimensions() int { - return len(e.Vector) -} - -// Dimension returns the value of the i-th dimension -// Implements kdtree.Point interface -func (e *Embedding) Dimension(i int) float64 { - return e.Vector[i] -} - // KNNRetriever is a retriever that uses KNN to find relevant documents. type KNNRetriever struct { tree *kdtree.KDTree - mapping map[string]*Embedding + mapping map[string]*embedding.Embedding // vectorsDimension is the dimension of the vectors. // All vectors must have the same dimension. vectorsDimension int @@ -50,13 +40,13 @@ type KNNRetriever struct { // NewKNNRetriever returns a new KNNRetriever. It expects that all points // have the same dimension and all vectors are normalized. -func NewKNNRetriever(points []*Embedding) (*KNNRetriever, error) { +func NewKNNRetriever(points []*embedding.Embedding) (*KNNRetriever, error) { if len(points) == 0 { return nil, trace.BadParameter("no points provided") } expectedDimension := points[0].Dimensions() kpoints := make([]kdtree.Point, len(points)) - mapping := make(map[string]*Embedding, len(points)) + mapping := make(map[string]*embedding.Embedding, len(points)) for i, point := range points { // Make sure that all points have the same dimension if point.Dimensions() != expectedDimension { @@ -74,11 +64,11 @@ func NewKNNRetriever(points []*Embedding) (*KNNRetriever, error) { } // GetRelevant returns the k most relevant documents to the query -func (r *KNNRetriever) GetRelevant(query *Embedding, k int) []*Document { +func (r *KNNRetriever) GetRelevant(query *embedding.Embedding, k int) []*Document { result := r.tree.KNN(query, k) relevant := make([]*Document, len(result)) for i, item := range result { - embedding := item.(*Embedding) + embedding := item.(*embedding.Embedding) // Ignore error. We've already checked that all points have the same dimension similarity, _ := calculateSimilarity(query.Vector, embedding.Vector) @@ -91,7 +81,7 @@ func (r *KNNRetriever) GetRelevant(query *Embedding, k int) []*Document { } // Insert inserts a new point into the retriever -func (r *KNNRetriever) Insert(point *Embedding) error { +func (r *KNNRetriever) Insert(point *embedding.Embedding) error { if point.Dimensions() != r.vectorsDimension { return trace.BadParameter("point has wrong dimension") } diff --git a/lib/ai/knnretriever_test.go b/lib/ai/knnretriever_test.go index 20c0d52774b26..007fd72d0229b 100644 --- a/lib/ai/knnretriever_test.go +++ b/lib/ai/knnretriever_test.go @@ -27,6 +27,7 @@ import ( "github.com/stretchr/testify/require" "github.com/gravitational/teleport/api/types" + "github.com/gravitational/teleport/lib/ai/embedding" ) func TestKNNRetriever_GetRelevant(t *testing.T) { @@ -35,11 +36,11 @@ func TestKNNRetriever_GetRelevant(t *testing.T) { // Generate random vector. The seed is fixed, so the results are deterministic. randGen := rand.New(rand.NewSource(42)) - generateVector := func() Vector64 { + generateVector := func() embedding.Vector64 { const testVectorDimension = 100 // generate random vector // reduce the dimensionality to 100 - vec := make(Vector64, testVectorDimension) + vec := make(embedding.Vector64, testVectorDimension) for i := 0; i < testVectorDimension; i++ { vec[i] = randGen.Float64() } @@ -49,13 +50,13 @@ func TestKNNRetriever_GetRelevant(t *testing.T) { } const testEmbeddingsSize = 100 - points := make([]*Embedding, testEmbeddingsSize) + points := make([]*embedding.Embedding, testEmbeddingsSize) for i := 0; i < testEmbeddingsSize; i++ { - points[i] = NewEmbedding(types.KindNode, strconv.Itoa(i), generateVector(), sha256.Sum256([]byte{byte(i)})) + points[i] = embedding.NewEmbedding(types.KindNode, strconv.Itoa(i), generateVector(), sha256.Sum256([]byte{byte(i)})) } // Create a query. - query := NewEmbedding(types.KindNode, "1", generateVector(), sha256.Sum256([]byte("1"))) + query := embedding.NewEmbedding(types.KindNode, "1", generateVector(), sha256.Sum256([]byte("1"))) retriever, err := NewKNNRetriever(points) require.NoError(t, err) @@ -79,15 +80,15 @@ func TestKNNRetriever_GetRelevant(t *testing.T) { func TestKNNRetriever_Insert(t *testing.T) { t.Parallel() - points := []*Embedding{ - NewEmbedding(types.KindNode, "1", Vector64{1, 2, 3}, sha256.Sum256([]byte("1"))), - NewEmbedding(types.KindNode, "2", Vector64{4, 5, 6}, sha256.Sum256([]byte("2"))), + points := []*embedding.Embedding{ + embedding.NewEmbedding(types.KindNode, "1", embedding.Vector64{1, 2, 3}, sha256.Sum256([]byte("1"))), + embedding.NewEmbedding(types.KindNode, "2", embedding.Vector64{4, 5, 6}, sha256.Sum256([]byte("2"))), } retriever, err := NewKNNRetriever(points) require.NoError(t, err) - newEmbedding := NewEmbedding(types.KindNode, "3", Vector64{7, 8, 9}, sha256.Sum256([]byte("3"))) + newEmbedding := embedding.NewEmbedding(types.KindNode, "3", embedding.Vector64{7, 8, 9}, sha256.Sum256([]byte("3"))) docs1 := retriever.GetRelevant(newEmbedding, 10) require.Len(t, docs1, 2) @@ -101,16 +102,16 @@ func TestKNNRetriever_Insert(t *testing.T) { func TestKNNRetriever_Remove(t *testing.T) { t.Parallel() - points := []*Embedding{ - NewEmbedding(types.KindNode, "1", Vector64{1, 2, 3}, sha256.Sum256([]byte("1"))), - NewEmbedding(types.KindNode, "2", Vector64{4, 5, 6}, sha256.Sum256([]byte("2"))), - NewEmbedding(types.KindNode, "3", Vector64{7, 8, 9}, sha256.Sum256([]byte("3"))), + points := []*embedding.Embedding{ + embedding.NewEmbedding(types.KindNode, "1", embedding.Vector64{1, 2, 3}, sha256.Sum256([]byte("1"))), + embedding.NewEmbedding(types.KindNode, "2", embedding.Vector64{4, 5, 6}, sha256.Sum256([]byte("2"))), + embedding.NewEmbedding(types.KindNode, "3", embedding.Vector64{7, 8, 9}, sha256.Sum256([]byte("3"))), } retriever, err := NewKNNRetriever(points) require.NoError(t, err) - query := NewEmbedding(types.KindNode, "3", Vector64{7, 8, 9}, sha256.Sum256([]byte("3"))) + query := embedding.NewEmbedding(types.KindNode, "3", embedding.Vector64{7, 8, 9}, sha256.Sum256([]byte("3"))) docs1 := retriever.GetRelevant(query, 10) require.Len(t, docs1, 3) @@ -132,9 +133,9 @@ func L2norm(v []float64) float64 { } // Function to normalize vector using L2 norm -func normalize(v Vector64) Vector64 { +func normalize(v embedding.Vector64) embedding.Vector64 { norm := L2norm(v) - result := make(Vector64, len(v)) + result := make(embedding.Vector64, len(v)) for i, value := range v { result[i] = value / norm } diff --git a/lib/ai/model/agent.go b/lib/ai/model/agent.go index 55d9ee7884370..3db8f7d07f856 100644 --- a/lib/ai/model/agent.go +++ b/lib/ai/model/agent.go @@ -30,6 +30,7 @@ import ( log "github.com/sirupsen/logrus" "github.com/gravitational/teleport/api/gen/proto/go/assist/v1" + "github.com/gravitational/teleport/lib/services" ) const ( @@ -46,17 +47,68 @@ const ( finalResponseHeader = "" ) +// NewExecutionTool creates a new execution tool. The execution tool is responsible for executing commands. +func NewExecutionTool() Tool { + return &commandExecutionTool{} +} + +// NewGenerateTool creates a new generation tool. The generation tool is responsible for generating Bash commands. +func NewGenerateTool() Tool { + return &commandGenerationTool{} +} + +// NewRetrievalTool creates a new retrieval tool. The retrieval tool is responsible for retrieving embeddings. +func NewRetrievalTool(assistClient assist.AssistEmbeddingServiceClient, + nodeClient NodeGetter, + userAccessChecker services.AccessChecker, + currentUser string, +) Tool { + return &embeddingRetrievalTool{ + assistClient: assistClient, + currentUser: currentUser, + nodeClient: nodeClient, + userAccessChecker: userAccessChecker, + } +} + // NewAgent creates a new agent. The Assist agent which defines the model responsible for the Assist feature. -func NewAgent(assistClient assist.AssistEmbeddingServiceClient, username string) *Agent { +func NewAgent(tools ...Tool) (*Agent, error) { + if len(tools) == 0 { + return nil, trace.BadParameter("at least one tool is required") + } + return &Agent{ - tools: []Tool{ - &commandExecutionTool{}, - &embeddingRetrievalTool{ - assistClient: assistClient, - currentUser: username, - }, - }, + tools: tools, + }, nil +} + +// ToolsConfig contains all the tool configuration and clients the tools +// can potentially leverage to interact with Teleport. Such clients can be used +// to list resources or check RBAC rules for example. +type ToolsConfig struct { + // DisableEmbeddingsTool disables the embedding retrieval tool, useful in tests. + DisableEmbeddingsTool bool + // EmbeddingsClient is required when the embeddings tool is enabled. + EmbeddingsClient assist.AssistEmbeddingServiceClient + // AccessChecker is required when NodeClient is set + AccessChecker services.AccessChecker + // NodeClient is optional, when set, the tools might attempt to search for + // nodes directly from cache on small clusters. + NodeClient *services.NodeWatcher +} + +// CheckAndSetDefaults checks if the ToolsConfig is valid and sets defaults +// when needed. +func (a *ToolsConfig) CheckAndSetDefaults() error { + if !a.DisableEmbeddingsTool { + if a.EmbeddingsClient == nil { + return trace.BadParameter("Embeddings client is mandatory when embedding tool is enabled") + } + if a.NodeClient != nil && a.AccessChecker == nil { + return trace.BadParameter("AccessChecker is required when NodeClient is set") + } } + return nil } // Agent is a model storing static state which defines some properties of the chat model. @@ -223,6 +275,25 @@ func (a *Agent) takeNextStep(ctx context.Context, state *executionState, progres return stepOutput{finish: &agentFinish{output: completion}}, nil } + if tool, ok := tool.(*commandGenerationTool); ok { + input, err := tool.parseInput(action.Input) + if err != nil { + action := &AgentAction{ + Action: actionException, + Input: observationPrefix + "Invalid or incomplete response", + Log: thoughtPrefix + err.Error(), + } + + return stepOutput{action: action, observation: action.Input}, nil + } + completion := &GeneratedCommand{ + Command: input.Command, + } + + log.Tracef("agent decided on command generation, let's translate to an agentFinish") + return stepOutput{finish: &agentFinish{output: completion}}, nil + } + runOut, err := tool.Run(ctx, action.Input) if err != nil { return stepOutput{}, trace.Wrap(err) diff --git a/lib/ai/model/generationtool.go b/lib/ai/model/generationtool.go new file mode 100644 index 0000000000000..1d83940b13899 --- /dev/null +++ b/lib/ai/model/generationtool.go @@ -0,0 +1,80 @@ +/* + * Copyright 2023 Gravitational, Inc. + * + * 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. + */ + +package model + +import ( + "context" + "fmt" + + "github.com/gravitational/trace" +) + +type commandGenerationTool struct{} + +type commandGenerationToolInput struct { + // Command is a unix command to execute. + Command string `json:"command"` +} + +func (c *commandGenerationTool) Name() string { + return "Command Generation" +} + +func (c *commandGenerationTool) Description() string { + // acknowledgement field is used to convince the LLM to return the JSON. + // Base on my testing LLM ignores the JSON when the schema has only one field. + // Adding additional "pseudo-fields" to the schema makes the LLM return the JSON. + return fmt.Sprintf(`Generate a Bash command. +The input must be a JSON object with the following schema: +%vjson +{ + "command": string, \\ The generated command + "acknowledgement": boolean \\ Set to true to ackowledge that you understand the formatting +} +%v +`, "```", "```") +} + +func (c *commandGenerationTool) Run(_ context.Context, _ string) (string, error) { + // This is stubbed because commandGenerationTool is handled specially. + // This is because execution of this tool breaks the loop and returns a command suggestion to the user. + // It is still handled as a tool because testing has shown that the LLM behaves better when it is treated as a tool. + // + // In addition, treating it as a Tool interface item simplifies the display and prompt assembly logic significantly. + return "", trace.NotImplemented("not implemented") +} + +// parseInput is called in a special case if the planned tool is commandExecutionTool. +// This is because commandExecutionTool is handled differently from most other tools and forcibly terminates the thought loop. +func (*commandGenerationTool) parseInput(input string) (*commandGenerationToolInput, error) { + output, err := parseJSONFromModel[commandGenerationToolInput](input) + if err != nil { + return nil, err + } + + if output.Command == "" { + return nil, &invalidOutputError{ + coarse: "command generation: missing command", + detail: "command must be non-empty", + } + } + + // Ignore the acknowledgement field. + // We do not care about the value. Having the command it enough. + + return &output, nil +} diff --git a/lib/ai/model/messages.go b/lib/ai/model/messages.go index 7774afad27946..687314ba85331 100644 --- a/lib/ai/model/messages.go +++ b/lib/ai/model/messages.go @@ -50,3 +50,8 @@ type CompletionCommand struct { Nodes []string `json:"nodes,omitempty"` Labels []Label `json:"labels,omitempty"` } + +// GeneratedCommand represents a Bash command generated by LLM. +type GeneratedCommand struct { + Command string `json:"command"` +} diff --git a/lib/ai/model/prompt.go b/lib/ai/model/prompt.go index fd940c6c72773..54ceef1f66adf 100644 --- a/lib/ai/model/prompt.go +++ b/lib/ai/model/prompt.go @@ -111,7 +111,8 @@ func ConversationCommandResult(result map[string][]byte) string { message.WriteString(string(output)) message.WriteString("\n") } - message.WriteString("Based on the chat history, extract relevant information out of the command output and write a summary.") + message.WriteString("Based on the chat history, extract relevant information out of the command output and write a summary. " + + "For error messages suggest a solution if possible. The solution can contain a Linux command or a description.") return message.String() } diff --git a/lib/ai/model/tool.go b/lib/ai/model/tool.go index 73a492b1a4adb..daec42dfef3a7 100644 --- a/lib/ai/model/tool.go +++ b/lib/ai/model/tool.go @@ -26,6 +26,15 @@ import ( "github.com/gravitational/teleport/api/gen/proto/go/assist/v1" "github.com/gravitational/teleport/api/types" + embeddinglib "github.com/gravitational/teleport/lib/ai/embedding" + "github.com/gravitational/teleport/lib/services" +) + +const ( + // proxyLookupClusterMaxSize is max the number of nodes in the cluster to attempt an opportunistic node lookup + // in the proxy cache. We always do embedding lookups if the cluster is larger than this number. + proxyLookupClusterMaxSize = 100 + maxEmbeddingsPerLookup = 10 ) // Tool is an interface that allows the agent to interact with the outside world. @@ -100,15 +109,48 @@ func (*commandExecutionTool) parseInput(input string) (*commandExecutionToolInpu return &output, nil } +type NodeGetter interface { + GetNodes(ctx context.Context, fn func(n services.Node) bool) []types.Server + NodeCount() int +} + type embeddingRetrievalTool struct { - assistClient assist.AssistEmbeddingServiceClient - currentUser string + assistClient assist.AssistEmbeddingServiceClient + nodeClient NodeGetter + userAccessChecker services.AccessChecker + currentUser string } type embeddingRetrievalToolInput struct { Question string `json:"question"` } +// tryNodeLookupFromProxyCache checks how many nodes the user has access to by +// hitting the proxy cache. If the user has access to less than +// maxEmbeddingsPerLookup, the returned boolean indicates the lookup is +// successful and the result can be used. If the boolean is false, the caller +// must not use the returned result and perform a Node lookup via other means +// (embeddings lookup). +func (e *embeddingRetrievalTool) tryNodeLookupFromProxyCache(ctx context.Context) (bool, string, error) { + nodes := e.nodeClient.GetNodes(ctx, func(node services.Node) bool { + err := e.userAccessChecker.CheckAccess(node, services.AccessState{MFAVerified: true}) + return err == nil + }) + if len(nodes) == 0 || len(nodes) > maxEmbeddingsPerLookup { + return false, "", nil + } + sb := strings.Builder{} + for _, node := range nodes { + data, err := embeddinglib.SerializeNode(node) + if err != nil { + return false, "", trace.Wrap(err) + } + sb.Write(data) + sb.WriteString("\n") + } + return true, sb.String(), nil +} + func (e *embeddingRetrievalTool) Run(ctx context.Context, input string) (string, error) { inputCmd, outErr := e.parseInput(input) if outErr == nil { @@ -119,10 +161,21 @@ func (e *embeddingRetrievalTool) Run(ctx context.Context, input string) (string, } log.Tracef("embedding retrieval input: %v", input) + // Threshold to avoid looping over all nodes on large clusters + if e.nodeClient != nil && e.nodeClient.NodeCount() < proxyLookupClusterMaxSize { + ok, result, err := e.tryNodeLookupFromProxyCache(ctx) + if err != nil { + return "", trace.Wrap(err) + } + if ok { + return result, nil + } + } + resp, err := e.assistClient.GetAssistantEmbeddings(ctx, &assist.GetAssistantEmbeddingsRequest{ Username: e.currentUser, Kind: types.KindNode, // currently only node embeddings are supported - Limit: 10, + Limit: maxEmbeddingsPerLookup, Query: input, }) if err != nil { diff --git a/lib/ai/model/tool_test.go b/lib/ai/model/tool_test.go new file mode 100644 index 0000000000000..4a15d246bd82b --- /dev/null +++ b/lib/ai/model/tool_test.go @@ -0,0 +1,137 @@ +/* + * Copyright 2023 Gravitational, Inc. + * + * 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. + */ + +package model + +import ( + "context" + "fmt" + "testing" + + "github.com/gravitational/trace" + "github.com/stretchr/testify/require" + + "github.com/gravitational/teleport/api/types" + "github.com/gravitational/teleport/lib/services" +) + +const testUser = "username" + +// mockAccessChecker implements the services.AccessChecker and always validate +// or reject access based on its allowAccess field. +type mockAccessChecker struct { + allowAccess bool + services.AccessChecker +} + +func (ac *mockAccessChecker) CheckAccess(_ services.AccessCheckable, _ services.AccessState, _ ...services.RoleMatcher) error { + if ac.allowAccess { + return nil + } + return trace.AccessDenied("user does not have access") +} + +// mockNodeGetter returns a static list of nodes +type mockNodeGetter struct { + nodes []types.Server +} + +func (ng *mockNodeGetter) NodeCount() int { + return len(ng.nodes) +} + +func (ng *mockNodeGetter) GetNodes(_ context.Context, fn func(n services.Node) bool) []types.Server { + var result []types.Server + for _, node := range ng.nodes { + if fn(node) { + result = append(result, node) + } + } + return result +} + +func Test_embeddingRetrievalTool_tryNodeLookupFromProxyCache(t *testing.T) { + ctx := context.Background() + tests := []struct { + name string + nodeCount int + hasAccess bool + assertLookupSuccessful require.BoolAssertionFunc + expectedOutput string + }{ + { + name: "No nodes", + nodeCount: 0, + hasAccess: true, + assertLookupSuccessful: require.False, + }, + { + name: "Few nodes", + nodeCount: 2, + hasAccess: true, + assertLookupSuccessful: require.True, + expectedOutput: `name: node-0 +kind: node +subkind: teleport +labels: + foo: bar + +name: node-1 +kind: node +subkind: teleport +labels: + foo: bar + +`, + }, + { + name: "Few nodes without access", + nodeCount: 2, + hasAccess: false, + assertLookupSuccessful: require.False, + }, + { + name: "Too many nodes", + nodeCount: maxEmbeddingsPerLookup + 1, + hasAccess: true, + assertLookupSuccessful: require.False, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Test setup + var err error + nodes := make([]types.Server, tt.nodeCount) + for i := 0; i < tt.nodeCount; i++ { + nodeName := fmt.Sprintf("node-%d", i) + nodes[i], err = types.NewServerWithLabels(nodeName, types.KindNode, types.ServerSpecV2{Hostname: nodeName}, map[string]string{"foo": "bar"}) + require.NoError(t, err) + } + + e := &embeddingRetrievalTool{ + nodeClient: &mockNodeGetter{nodes: nodes}, + userAccessChecker: &mockAccessChecker{allowAccess: tt.hasAccess}, + currentUser: testUser, + } + + // Doing the real test + ok, output, err := e.tryNodeLookupFromProxyCache(ctx) + require.NoError(t, err) + tt.assertLookupSuccessful(t, ok) + require.Equal(t, tt.expectedOutput, output) + }) + } +} diff --git a/lib/ai/simpleretriever.go b/lib/ai/simpleretriever.go index 16745f82579fd..94f32b10314d7 100644 --- a/lib/ai/simpleretriever.go +++ b/lib/ai/simpleretriever.go @@ -19,27 +19,29 @@ package ai import ( "sort" "sync" + + "github.com/gravitational/teleport/lib/ai/embedding" ) // SimpleRetriever is a simple implementation of embeddings retriever. // It stores all the embeddings in memory and retrieves the k nearest neighbors // by iterating over all the embeddings. Do not use for large datasets. type SimpleRetriever struct { - embeddings map[string]*Embedding + embeddings map[string]*embedding.Embedding maxSize int mtx sync.Mutex } func NewSimpleRetriever() *SimpleRetriever { return &SimpleRetriever{ - embeddings: make(map[string]*Embedding), + embeddings: make(map[string]*embedding.Embedding), maxSize: 1_000, // keep the number low to avoid OOM } } // Insert adds the embedding to the retriever. If the retriever is full, the // embedding is not added and false is returned. -func (r *SimpleRetriever) Insert(id string, embedding *Embedding) bool { +func (r *SimpleRetriever) Insert(id string, embedding *embedding.Embedding) bool { r.mtx.Lock() defer r.mtx.Unlock() if len(r.embeddings) >= r.maxSize { @@ -68,11 +70,11 @@ func (r *SimpleRetriever) Swap(s *SimpleRetriever) { // FilterFn is a function that filters out embeddings. // If the function returns false, the embedding is filtered out. -type FilterFn func(id string, embedding *Embedding) bool +type FilterFn func(id string, embedding *embedding.Embedding) bool // GetRelevant returns the k nearest neighbors to the query embedding. // If a filter is provided, only the embeddings that pass the filter are considered. -func (r *SimpleRetriever) GetRelevant(query *Embedding, k int, filter FilterFn) []*Document { +func (r *SimpleRetriever) GetRelevant(query *embedding.Embedding, k int, filter FilterFn) []*Document { // Replace with priority queue if k is large. results := make([]*Document, 0, k) diff --git a/lib/ai/simpleretriever_test.go b/lib/ai/simpleretriever_test.go index 37030da39f40a..d5d8904d420b4 100644 --- a/lib/ai/simpleretriever_test.go +++ b/lib/ai/simpleretriever_test.go @@ -25,6 +25,7 @@ import ( "github.com/stretchr/testify/require" "github.com/gravitational/teleport/api/types" + "github.com/gravitational/teleport/lib/ai/embedding" ) func TestSimpleRetriever_GetRelevant(t *testing.T) { @@ -33,11 +34,11 @@ func TestSimpleRetriever_GetRelevant(t *testing.T) { // Generate random vector. The seed is fixed, so the results are deterministic. randGen := rand.New(rand.NewSource(42)) - generateVector := func() Vector64 { + generateVector := func() embedding.Vector64 { const testVectorDimension = 100 // generate random vector // reduce the dimensionality to 100 - vec := make(Vector64, testVectorDimension) + vec := make(embedding.Vector64, testVectorDimension) for i := 0; i < testVectorDimension; i++ { vec[i] = randGen.Float64() } @@ -47,13 +48,13 @@ func TestSimpleRetriever_GetRelevant(t *testing.T) { } const testEmbeddingsSize = 100 - points := make([]*Embedding, testEmbeddingsSize) + points := make([]*embedding.Embedding, testEmbeddingsSize) for i := 0; i < testEmbeddingsSize; i++ { - points[i] = NewEmbedding(types.KindNode, strconv.Itoa(i), generateVector(), [32]byte{}) + points[i] = embedding.NewEmbedding(types.KindNode, strconv.Itoa(i), generateVector(), [32]byte{}) } // Create a query. - query := NewEmbedding(types.KindNode, "1", generateVector(), [32]byte{}) + query := embedding.NewEmbedding(types.KindNode, "1", generateVector(), [32]byte{}) retriever := NewSimpleRetriever() @@ -62,7 +63,7 @@ func TestSimpleRetriever_GetRelevant(t *testing.T) { } // Get the top 10 most similar documents. - docs := retriever.GetRelevant(query, 10, func(id string, embedding *Embedding) bool { + docs := retriever.GetRelevant(query, 10, func(id string, embedding *embedding.Embedding) bool { return true }) require.Len(t, docs, 10) diff --git a/lib/assist/assist.go b/lib/assist/assist.go index 3e4e00a29113c..62633d7c03d62 100644 --- a/lib/assist/assist.go +++ b/lib/assist/assist.go @@ -121,10 +121,12 @@ type Chat struct { // NewChat creates a new Assist chat. func (a *Assist) NewChat(ctx context.Context, assistService MessageService, - embeddingServiceClient assist.AssistEmbeddingServiceClient, - conversationID, username string, + conversationID, username string, toolsConfig model.ToolsConfig, ) (*Chat, error) { - aichat := a.client.NewChat(embeddingServiceClient, username) + aichat, err := a.client.NewChat(username, toolsConfig) + if err != nil { + return nil, trace.Wrap(err) + } chat := &Chat{ assist: a, @@ -142,6 +144,31 @@ func (a *Assist) NewChat(ctx context.Context, assistService MessageService, return chat, nil } +// LightweightChat is a Teleport Assist chat that doesn't store the history +// of the conversation. +type LightweightChat struct { + assist *Assist + chat *ai.Chat +} + +// NewLightweightChat creates a new Assist chat what doesn't store the history +// of the conversation. +func (a *Assist) NewLightweightChat(username string) (*LightweightChat, error) { + aichat, err := a.client.NewCommand(username) // TODO(jakule): fix this after all in-flight PRs are merged + if err != nil { + return nil, trace.Wrap(err) + } + + return &LightweightChat{ + assist: a, + chat: aichat, + }, nil +} + +func (a *Assist) NewSSHCommand(username string) (*ai.Chat, error) { + return a.client.NewCommand(username) +} + // GenerateSummary generates a summary for the given message. func (a *Assist) GenerateSummary(ctx context.Context, message string) (string, error) { return a.client.Summary(ctx, message) @@ -177,7 +204,7 @@ func (c *Chat) reloadMessages(ctx context.Context) error { } // ClassifyMessage takes a user message, a list of categories, and uses the AI -// mode as a zero shot classifier. It returns an error if the classification +// mode as a zero-shot classifier. It returns an error if the classification // result is not a valid class. func (a *Assist) ClassifyMessage(ctx context.Context, message string, classes map[string]string) (string, error) { category, err := a.client.ClassifyMessage(ctx, message, classes) @@ -404,6 +431,63 @@ func (c *Chat) ProcessComplete(ctx context.Context, onMessage onMessageFunc, use return tokenCount, nil } +// ProcessComplete processes a user message and returns the assistant's response. +func (c *LightweightChat) ProcessComplete(ctx context.Context, onMessage onMessageFunc, userInput string, +) (*model.TokenCount, error) { + progressUpdates := func(update *model.AgentAction) { + payload, err := json.Marshal(update) + if err != nil { + log.WithError(err).Debugf("Failed to marshal progress update: %v", update) + return + } + + if err := onMessage(MessageKindProgressUpdate, payload, c.assist.clock.Now().UTC()); err != nil { + log.WithError(err).Debugf("Failed to send progress update: %v", update) + return + } + } + + message, tokenCount, err := c.chat.Reply(ctx, userInput, progressUpdates) + if err != nil { + return nil, trace.Wrap(err) + } + + c.chat.Insert(openai.ChatMessageRoleUser, userInput) + + switch message := message.(type) { + case *model.Message: + c.chat.Insert(openai.ChatMessageRoleAssistant, message.Content) + if err := onMessage(MessageKindAssistantMessage, []byte(message.Content), c.assist.clock.Now().UTC()); err != nil { + return nil, trace.Wrap(err) + } + case *model.GeneratedCommand: + c.chat.Insert(openai.ChatMessageRoleAssistant, message.Command) + if err := onMessage(MessageKindCommand, []byte(message.Command), c.assist.clock.Now().UTC()); err != nil { + return nil, trace.Wrap(err) + } + case *model.StreamingMessage: + if err := func() error { + var text strings.Builder + defer onMessage(MessageKindAssistantPartialFinalize, nil, c.assist.clock.Now().UTC()) + for part := range message.Parts { + text.WriteString(part) + + if err := onMessage(MessageKindAssistantPartialMessage, []byte(part), c.assist.clock.Now().UTC()); err != nil { + return trace.Wrap(err) + } + } + c.chat.Insert(openai.ChatMessageRoleAssistant, text.String()) + return nil + }(); err != nil { + return nil, trace.Wrap(err) + } + default: + return nil, trace.Errorf("Unexpected message type: %T", message) + } + + return tokenCount, nil +} + func getOpenAITokenFromDefaultPlugin(ctx context.Context, proxyClient PluginGetter) (string, error) { // Try retrieving credentials from the plugin resource first openaiPlugin, err := proxyClient.PluginsClient().GetPlugin(ctx, &pluginsv1.GetPluginRequest{ diff --git a/lib/assist/assist_test.go b/lib/assist/assist_test.go index 495383fb2ef38..1420cee23de71 100644 --- a/lib/assist/assist_test.go +++ b/lib/assist/assist_test.go @@ -32,6 +32,7 @@ import ( "github.com/gravitational/teleport/api/gen/proto/go/assist/v1" pluginsv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/plugins/v1" "github.com/gravitational/teleport/api/types" + "github.com/gravitational/teleport/lib/ai/model" aitest "github.com/gravitational/teleport/lib/ai/testutils" "github.com/gravitational/teleport/lib/auth" ) @@ -71,7 +72,10 @@ func TestChatComplete(t *testing.T) { require.NoError(t, err) // When a chat is created. - chat, err := client.NewChat(ctx, authSrv.AuthServer, nil, conversationResp.Id, testUser) + toolsConfig := model.ToolsConfig{ + DisableEmbeddingsTool: true, + } + chat, err := client.NewChat(ctx, authSrv.AuthServer, conversationResp.Id, testUser, toolsConfig) require.NoError(t, err) t.Run("new conversation is new", func(t *testing.T) { diff --git a/lib/auth/assist/assistv1/service.go b/lib/auth/assist/assistv1/service.go index fd5a5b0efb940..6fcd880674411 100644 --- a/lib/auth/assist/assistv1/service.go +++ b/lib/auth/assist/assistv1/service.go @@ -29,6 +29,7 @@ import ( "github.com/gravitational/teleport/api/gen/proto/go/assist/v1" "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/lib/ai" + embeddinglib "github.com/gravitational/teleport/lib/ai/embedding" "github.com/gravitational/teleport/lib/authz" "github.com/gravitational/teleport/lib/services" ) @@ -38,7 +39,7 @@ import ( type ServiceConfig struct { Backend services.Assistant Embeddings *ai.SimpleRetriever - Embedder ai.Embedder + Embedder embeddinglib.Embedder Authorizer authz.Authorizer Logger *logrus.Entry ResourceGetter ResourceGetter @@ -59,7 +60,7 @@ type Service struct { embeddings *ai.SimpleRetriever // embedder is used to embed text into a vector. // It can be nil if the OpenAI API key is not set. - embedder ai.Embedder + embedder embeddinglib.Embedder authorizer authz.Authorizer log *logrus.Entry resourceGetter ResourceGetter @@ -239,8 +240,8 @@ func (a *Service) GetAssistantEmbeddings(ctx context.Context, msg *assist.GetAss } // Use default values for the id and content, as we only care about the embeddings. - queryEmbeddings := ai.NewEmbedding(msg.Kind, "", embeddings[0], [32]byte{}) - documents := a.embeddings.GetRelevant(queryEmbeddings, int(msg.Limit), func(id string, embedding *ai.Embedding) bool { + queryEmbeddings := embeddinglib.NewEmbedding(msg.Kind, "", embeddings[0], [32]byte{}) + documents := a.embeddings.GetRelevant(queryEmbeddings, int(msg.Limit), func(id string, embedding *embeddinglib.Embedding) bool { // Run RBAC check on the embedded resource. node, err := a.resourceGetter.GetNode(ctx, defaults.Namespace, embedding.GetEmbeddedID()) if err != nil { @@ -257,7 +258,7 @@ func (a *Service) GetAssistantEmbeddings(ctx context.Context, msg *assist.GetAss return nil, trace.Wrap(err) } - content, err := ai.SerializeNode(node) + content, err := embeddinglib.SerializeNode(node) if err != nil { return nil, trace.Wrap(err) } diff --git a/lib/auth/auth.go b/lib/auth/auth.go index c98cef46c77c3..4231d7eeb120c 100644 --- a/lib/auth/auth.go +++ b/lib/auth/auth.go @@ -70,6 +70,7 @@ import ( "github.com/gravitational/teleport/api/utils/retryutils" apisshutils "github.com/gravitational/teleport/api/utils/sshutils" "github.com/gravitational/teleport/lib/ai" + "github.com/gravitational/teleport/lib/ai/embedding" "github.com/gravitational/teleport/lib/auth/keystore" "github.com/gravitational/teleport/lib/auth/native" "github.com/gravitational/teleport/lib/auth/userloginstate" @@ -716,7 +717,7 @@ type Server struct { embeddingsRetriever *ai.SimpleRetriever // embedder is an embedder client used to generate embeddings. - embedder ai.Embedder + embedder embedding.Embedder } // SetSAMLService registers svc as the SAMLService that provides the SAML diff --git a/lib/auth/helpers.go b/lib/auth/helpers.go index 102b323ca642f..73e59499399d4 100644 --- a/lib/auth/helpers.go +++ b/lib/auth/helpers.go @@ -36,6 +36,7 @@ import ( "github.com/gravitational/teleport/api/types" apiutils "github.com/gravitational/teleport/api/utils" "github.com/gravitational/teleport/lib/ai" + "github.com/gravitational/teleport/lib/ai/embedding" "github.com/gravitational/teleport/lib/auth/keystore" "github.com/gravitational/teleport/lib/auth/native" authority "github.com/gravitational/teleport/lib/auth/testauthority" @@ -78,7 +79,7 @@ type TestAuthServerConfig struct { // AuthPreferenceSpec is custom initial AuthPreference spec for the test. AuthPreferenceSpec *types.AuthPreferenceSpecV2 // Embedder is required to enable the assist in the auth server. - Embedder ai.Embedder + Embedder embedding.Embedder } // CheckAndSetDefaults checks and sets defaults @@ -194,7 +195,7 @@ func WithClock(clock clockwork.Clock) ServerOption { } // WithEmbedder is a functional server option that sets the server's embedder. -func WithEmbedder(embedder ai.Embedder) ServerOption { +func WithEmbedder(embedder embedding.Embedder) ServerOption { return func(s *Server) error { s.embedder = embedder return nil @@ -1193,6 +1194,6 @@ func CreateUserAndRoleWithoutRoles(clt clt, username string, allowedLogins []str // noopEmbedder is a no op implementation of the Embedder interface. type noopEmbedder struct{} -func (n noopEmbedder) ComputeEmbeddings(_ context.Context, _ []string) ([]ai.Vector64, error) { - return []ai.Vector64{}, nil +func (n noopEmbedder) ComputeEmbeddings(_ context.Context, _ []string) ([]embedding.Vector64, error) { + return []embedding.Vector64{}, nil } diff --git a/lib/auth/init.go b/lib/auth/init.go index 9ef84fe5ec420..336ffe88d5498 100644 --- a/lib/auth/init.go +++ b/lib/auth/init.go @@ -44,6 +44,7 @@ import ( apisshutils "github.com/gravitational/teleport/api/utils/sshutils" "github.com/gravitational/teleport/lib" "github.com/gravitational/teleport/lib/ai" + "github.com/gravitational/teleport/lib/ai/embedding" "github.com/gravitational/teleport/lib/auth/keystore" "github.com/gravitational/teleport/lib/auth/native" "github.com/gravitational/teleport/lib/backend" @@ -251,7 +252,7 @@ type InitConfig struct { EmbeddingRetriever *ai.SimpleRetriever // EmbeddingClient is a client that allows generating embeddings. - EmbeddingClient ai.Embedder + EmbeddingClient embedding.Embedder // Tracer used to create spans. Tracer oteltrace.Tracer diff --git a/lib/service/service.go b/lib/service/service.go index d58eb0ebcc3e8..492e822546cba 100644 --- a/lib/service/service.go +++ b/lib/service/service.go @@ -71,6 +71,7 @@ import ( "github.com/gravitational/teleport/lib" "github.com/gravitational/teleport/lib/agentless" "github.com/gravitational/teleport/lib/ai" + "github.com/gravitational/teleport/lib/ai/embedding" "github.com/gravitational/teleport/lib/auditd" "github.com/gravitational/teleport/lib/auth" "github.com/gravitational/teleport/lib/auth/keygen" @@ -1663,7 +1664,7 @@ func (process *TeleportProcess) initAuthService() error { traceClt = clt } - var embedderClient ai.Embedder + var embedderClient embedding.Embedder if cfg.Auth.AssistAPIKey != "" { // cfg.OpenAIConfig is set in tests to change the OpenAI API endpoint // Like for proxy, if a custom OpenAIConfig is passed, the token from @@ -3897,6 +3898,7 @@ func (process *TeleportProcess) initProxyEndpoint(conn *Connector) error { SessionControl: sessionController, PROXYSigner: proxySigner, OpenAIConfig: cfg.OpenAIConfig, + NodeWatcher: nodeWatcher, } webHandler, err := web.NewHandler(webConfig) if err != nil { diff --git a/lib/services/embeddings.go b/lib/services/embeddings.go index 1149213bf69cb..f4b8bf0dbaf93 100644 --- a/lib/services/embeddings.go +++ b/lib/services/embeddings.go @@ -20,7 +20,7 @@ import ( "context" "github.com/gravitational/teleport/api/internalutils/stream" - "github.com/gravitational/teleport/lib/ai" + "github.com/gravitational/teleport/lib/ai/embedding" ) // Embeddings service is responsible for storing and retrieving embeddings in @@ -28,9 +28,9 @@ import ( // re-generated by an ai.Embedder. type Embeddings interface { // GetEmbedding looks up a single embedding by its name in the backend. - GetEmbedding(ctx context.Context, kind, resourceID string) (*ai.Embedding, error) + GetEmbedding(ctx context.Context, kind, resourceID string) (*embedding.Embedding, error) // GetEmbeddings returns all embeddings for a given kind. - GetEmbeddings(ctx context.Context, kind string) stream.Stream[*ai.Embedding] + GetEmbeddings(ctx context.Context, kind string) stream.Stream[*embedding.Embedding] // UpsertEmbedding creates or updates a single ai.Embedding in the backend. - UpsertEmbedding(ctx context.Context, embedding *ai.Embedding) (*ai.Embedding, error) + UpsertEmbedding(ctx context.Context, embedding *embedding.Embedding) (*embedding.Embedding, error) } diff --git a/lib/services/local/embeddings.go b/lib/services/local/embeddings.go index d782e1448b573..613c99fbb0891 100644 --- a/lib/services/local/embeddings.go +++ b/lib/services/local/embeddings.go @@ -25,6 +25,7 @@ import ( "github.com/gravitational/teleport/api/internalutils/stream" "github.com/gravitational/teleport/api/utils/retryutils" "github.com/gravitational/teleport/lib/ai" + "github.com/gravitational/teleport/lib/ai/embedding" "github.com/gravitational/teleport/lib/backend" ) @@ -42,7 +43,7 @@ const ( ) // GetEmbedding looks up a single embedding by its name in the backend. -func (e EmbeddingsService) GetEmbedding(ctx context.Context, kind, resourceID string) (*ai.Embedding, error) { +func (e EmbeddingsService) GetEmbedding(ctx context.Context, kind, resourceID string) (*embedding.Embedding, error) { result, err := e.Get(ctx, backend.Key(embeddingsPrefix, kind, resourceID)) if err != nil { return nil, trace.Wrap(err) @@ -51,10 +52,10 @@ func (e EmbeddingsService) GetEmbedding(ctx context.Context, kind, resourceID st } // GetEmbeddings returns a stream of embeddings for a given kind. -func (e EmbeddingsService) GetEmbeddings(ctx context.Context, kind string) stream.Stream[*ai.Embedding] { +func (e EmbeddingsService) GetEmbeddings(ctx context.Context, kind string) stream.Stream[*embedding.Embedding] { startKey := backend.ExactKey(embeddingsPrefix, kind) items := backend.StreamRange(ctx, e, startKey, backend.RangeEnd(startKey), 50) - return stream.FilterMap(items, func(item backend.Item) (*ai.Embedding, bool) { + return stream.FilterMap(items, func(item backend.Item) (*embedding.Embedding, bool) { embedding, err := ai.UnmarshalEmbedding(item.Value) if err != nil { e.log.Warnf("Skipping embedding at %s, failed to unmarshal: %v", item.Key, err) @@ -65,7 +66,7 @@ func (e EmbeddingsService) GetEmbeddings(ctx context.Context, kind string) strea } // UpsertEmbedding creates or update a single ai.Embedding in the backend. -func (e EmbeddingsService) UpsertEmbedding(ctx context.Context, embedding *ai.Embedding) (*ai.Embedding, error) { +func (e EmbeddingsService) UpsertEmbedding(ctx context.Context, embedding *embedding.Embedding) (*embedding.Embedding, error) { value, err := ai.MarshalEmbedding(embedding) if err != nil { return nil, trace.Wrap(err) @@ -92,6 +93,6 @@ func NewEmbeddingsService(b backend.Backend) *EmbeddingsService { } // embeddingItemKey builds the backend item key for a given ai.Embedding. -func embeddingItemKey(embedding *ai.Embedding) []byte { +func embeddingItemKey(embedding *embedding.Embedding) []byte { return backend.Key(embeddingsPrefix, embedding.GetName()) } diff --git a/lib/services/local/embeddings_test.go b/lib/services/local/embeddings_test.go index f9eaa3e16b272..30a242f8574b0 100644 --- a/lib/services/local/embeddings_test.go +++ b/lib/services/local/embeddings_test.go @@ -26,14 +26,14 @@ import ( "github.com/gravitational/teleport/api/internalutils/stream" "github.com/gravitational/teleport/api/types" - "github.com/gravitational/teleport/lib/ai" + embeddinglib "github.com/gravitational/teleport/lib/ai/embedding" "github.com/gravitational/teleport/lib/backend/memory" ) var ( - embedding1 = ai.NewEmbedding(types.KindNode, "foo", ai.Vector64{0, 0}, sha256.Sum256([]byte("test1"))) - embedding2 = ai.NewEmbedding(types.KindNode, "bar", ai.Vector64{1, 1, 1}, sha256.Sum256([]byte("test2"))) - embedding3 = ai.NewEmbedding(types.KindDatabase, "bar", ai.Vector64{2}, sha256.Sum256([]byte("test3"))) + embedding1 = embeddinglib.NewEmbedding(types.KindNode, "foo", embeddinglib.Vector64{0, 0}, sha256.Sum256([]byte("test1"))) + embedding2 = embeddinglib.NewEmbedding(types.KindNode, "bar", embeddinglib.Vector64{1, 1, 1}, sha256.Sum256([]byte("test2"))) + embedding3 = embeddinglib.NewEmbedding(types.KindDatabase, "bar", embeddinglib.Vector64{2}, sha256.Sum256([]byte("test3"))) ) func errorIsNotFound(t require.TestingT, err error, msgAndArgs ...interface{}) { @@ -45,7 +45,7 @@ func TestGetEmbedding(t *testing.T) { // Test setup: create the backend, the service, and load all fixtures ctx := context.Background() - fixtures := []*ai.Embedding{embedding1, embedding2, embedding3} + fixtures := []*embeddinglib.Embedding{embedding1, embedding2, embedding3} backend, err := memory.New(memory.Config{ Context: ctx, @@ -66,7 +66,7 @@ func TestGetEmbedding(t *testing.T) { kind string id string assertErr require.ErrorAssertionFunc - expected *ai.Embedding + expected *embeddinglib.Embedding }{ { name: "Simple get", @@ -107,7 +107,7 @@ func TestGetEmbeddings(t *testing.T) { // Test setup: create the backend, the service, and load all fixtures ctx := context.Background() - fixtures := []*ai.Embedding{embedding1, embedding2, embedding3} + fixtures := []*embeddinglib.Embedding{embedding1, embedding2, embedding3} backend, err := memory.New(memory.Config{ Context: ctx, @@ -184,7 +184,7 @@ func TestUpsertEmbedding(t *testing.T) { errorIsNotFound(t, err) // Test: add an element in the backend and check if we can retrieve it - embedding := ai.NewEmbedding(types.KindNode, "foo", ai.Vector64{0, 0}, sha256.Sum256([]byte("test"))) + embedding := embeddinglib.NewEmbedding(types.KindNode, "foo", embeddinglib.Vector64{0, 0}, sha256.Sum256([]byte("test"))) embedding, err = service.UpsertEmbedding(ctx, embedding) require.NoError(t, err) result, err := service.GetEmbedding(ctx, types.KindNode, "foo") @@ -192,7 +192,7 @@ func TestUpsertEmbedding(t *testing.T) { requireEmbeddingsEqual(t, embedding, result) // Test: update the embedding and check we now retrieve the new version - embedding = ai.NewEmbedding(types.KindNode, "foo", ai.Vector64{1, 1, 1, 1, 1}, sha256.Sum256([]byte("test2"))) + embedding = embeddinglib.NewEmbedding(types.KindNode, "foo", embeddinglib.Vector64{1, 1, 1, 1, 1}, sha256.Sum256([]byte("test2"))) embedding, err = service.UpsertEmbedding(ctx, embedding) require.NoError(t, err) result, err = service.GetEmbedding(ctx, types.KindNode, "foo") @@ -200,9 +200,9 @@ func TestUpsertEmbedding(t *testing.T) { requireEmbeddingsEqual(t, embedding, result) } -// sortableEmbeddings is an ai.Embedding list that can be sorted. This is used +// sortableEmbeddings is an embedding.Embedding list that can be sorted. This is used // in tests to compare two lists and their content. -type sortableEmbeddings []*ai.Embedding +type sortableEmbeddings []*embeddinglib.Embedding func (s sortableEmbeddings) Len() int { return len(s) @@ -220,7 +220,7 @@ func (s sortableEmbeddings) Swap(i, j int) { // This is required because equivalent ai.Embedding might differ depending on // how they have been created (marshaling/unmarshalling protobuf messages set // some internal fields that a freshly created ai.Embedding doesn't have). -func requireEmbeddingsEqual(t require.TestingT, expected, actual *ai.Embedding) { +func requireEmbeddingsEqual(t require.TestingT, expected, actual *embeddinglib.Embedding) { if expected == nil { require.Nil(t, actual) return diff --git a/lib/usagereporter/teleport/types.go b/lib/usagereporter/teleport/types.go index 0809f893f5594..977cde665cb9e 100644 --- a/lib/usagereporter/teleport/types.go +++ b/lib/usagereporter/teleport/types.go @@ -609,6 +609,40 @@ func (e *AssistNewConversationEvent) Anonymize(a utils.Anonymizer) prehogv1a.Sub } } +type AssistAccessRequestEvent prehogv1a.AssistAccessRequestEvent + +// Anonymize anonymizes the event. +func (e *AssistAccessRequestEvent) Anonymize(a utils.Anonymizer) prehogv1a.SubmitEventRequest { + return prehogv1a.SubmitEventRequest{ + Event: &prehogv1a.SubmitEventRequest_AssistAccessRequest{ + AssistAccessRequest: &prehogv1a.AssistAccessRequestEvent{ + UserName: a.AnonymizeString(e.UserName), + ResourceType: e.ResourceType, + TotalTokens: e.TotalTokens, + PromptTokens: e.PromptTokens, + CompletionTokens: e.CompletionTokens, + }, + }, + } +} + +type AssistActionEvent prehogv1a.AssistActionEvent + +// Anonymize anonymizes the event. +func (e *AssistActionEvent) Anonymize(a utils.Anonymizer) prehogv1a.SubmitEventRequest { + return prehogv1a.SubmitEventRequest{ + Event: &prehogv1a.SubmitEventRequest_AssistAction{ + AssistAction: &prehogv1a.AssistActionEvent{ + UserName: a.AnonymizeString(e.UserName), + Action: e.Action, + TotalTokens: e.TotalTokens, + PromptTokens: e.PromptTokens, + CompletionTokens: e.CompletionTokens, + }, + }, + } +} + // UserMetadata contains user metadata information which is used to contextualize events with user information. type UserMetadata struct { // Username contains the user's name. @@ -617,7 +651,7 @@ type UserMetadata struct { IsSSO bool } -// DeviceAuthenticateEvent event is emitted after successful device authentication ceremony. +// DeviceAuthenticateEvent event is emitted after a successful device authentication ceremony. type DeviceAuthenticateEvent prehogv1a.DeviceAuthenticateEvent func (d *DeviceAuthenticateEvent) Anonymize(a utils.Anonymizer) prehogv1a.SubmitEventRequest { @@ -907,6 +941,24 @@ func ConvertUsageEvent(event *usageeventsv1.UsageEventOneOf, userMD UserMetadata Category: e.AssistNewConversation.Category, } return ret, nil + case *usageeventsv1.UsageEventOneOf_AssistAccessRequest: + ret := &AssistAccessRequestEvent{ + UserName: userMD.Username, + ResourceType: e.AssistAccessRequest.ResourceType, + TotalTokens: e.AssistAccessRequest.TotalTokens, + PromptTokens: e.AssistAccessRequest.PromptTokens, + CompletionTokens: e.AssistAccessRequest.CompletionTokens, + } + return ret, nil + case *usageeventsv1.UsageEventOneOf_AssistAction: + ret := &AssistActionEvent{ + UserName: userMD.Username, + Action: e.AssistAction.Action, + TotalTokens: e.AssistAction.TotalTokens, + PromptTokens: e.AssistAction.PromptTokens, + CompletionTokens: e.AssistAction.CompletionTokens, + } + return ret, nil default: return nil, trace.BadParameter("invalid usage event type %T", event.GetEvent()) } diff --git a/lib/web/apiserver.go b/lib/web/apiserver.go index eee6fe00e464d..b4bf8e6626a05 100644 --- a/lib/web/apiserver.go +++ b/lib/web/apiserver.go @@ -136,6 +136,10 @@ type Handler struct { // ClusterFeatures contain flags for supported and unsupported features. ClusterFeatures proto.Features + + // nodeWatcher is a services.NodeWatcher used by Assist to lookup nodes from + // the proxy's cache and get nodes in real time. + nodeWatcher *services.NodeWatcher } // HandlerOption is a functional argument - an option that can be passed @@ -258,6 +262,10 @@ type Config struct { // OpenAIConfig provides config options for the OpenAI integration. OpenAIConfig *openai.ClientConfig + + // NodeWatcher is a services.NodeWatcher used by Assist to lookup nodes from + // the proxy's cache and get nodes in real time. + NodeWatcher *services.NodeWatcher } type APIHandler struct { @@ -409,6 +417,10 @@ func NewHandler(cfg Config, opts ...HandlerOption) (*APIHandler, error) { h.Handle("GET", "/web/config.js", httplib.MakeHandler(h.getWebConfig)) } + if cfg.NodeWatcher != nil { + h.nodeWatcher = cfg.NodeWatcher + } + routingHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // ensure security headers are set for all responses httplib.SetDefaultSecurityHeaders(w.Header()) diff --git a/lib/web/assistant.go b/lib/web/assistant.go index 363a0c9e7a8e5..b23887664317f 100644 --- a/lib/web/assistant.go +++ b/lib/web/assistant.go @@ -31,6 +31,7 @@ import ( "google.golang.org/protobuf/types/known/timestamppb" "github.com/gravitational/teleport/api/client/proto" + clientproto "github.com/gravitational/teleport/api/client/proto" assistpb "github.com/gravitational/teleport/api/gen/proto/go/assist/v1" usageeventsv1 "github.com/gravitational/teleport/api/gen/proto/go/usageevents/v1" "github.com/gravitational/teleport/lib/ai/model" @@ -41,6 +42,17 @@ import ( "github.com/gravitational/teleport/lib/reversetunnel" ) +// We can not know how many tokens we will consume in advance. +// Try to consume a small number of tokens first. +const lookaheadTokens = 100 + +const ( + // actionSSHGenerateCommand is a name of the action for generating SSH commands. + actionSSHGenerateCommand = "ssh-cmdgen" + // actionSSHExplainCommand is a name of the action for explaining terminal output in SSH session. + actionSSHExplainCommand = "ssh-explain" +) + // createAssistantConversationResponse is a response for POST /webapi/assistant/conversations. type createdAssistantConversationResponse struct { // ID is a conversation ID. @@ -315,6 +327,9 @@ func (h *Handler) generateAssistantTitle(_ http.ResponseWriter, r *http.Request, return conversationInfo, nil } +// assistant is a handler for GET /webapi/sites/:site/assistant. +// This handler covers the main chat conversation as well as the +// SSH completition (SSH command generation and output explanation). func (h *Handler) assistant(w http.ResponseWriter, r *http.Request, _ httprouter.Params, sctx *SessionContext, site reversetunnel.RemoteSite, ) (any, error) { @@ -327,6 +342,7 @@ func (h *Handler) assistant(w http.ResponseWriter, r *http.Request, _ httprouter } func (h *Handler) reportTokenUsage(usedTokens *model.TokenCount, lookaheadTokens int, conversationID string, authClient auth.ClientI) { + // Create a new context to not be bounded by the request timeout. ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() @@ -375,8 +391,9 @@ func runAssistant(h *Handler, w http.ResponseWriter, r *http.Request, ) (err error) { q := r.URL.Query() conversationID := q.Get("conversation_id") - if conversationID == "" { - return trace.BadParameter("conversation ID is required") + actionParam := r.URL.Query().Get("action") + if conversationID == "" && actionParam == "" { + return trace.BadParameter("conversation ID or action is required") } authClient, err := sctx.GetClient() @@ -459,8 +476,7 @@ func runAssistant(h *Handler, w http.ResponseWriter, r *http.Request, // Update the read deadline upon receiving a pong message. ws.SetPongHandler(func(_ string) error { - ws.SetReadDeadline(deadlineForInterval(keepAliveInterval)) - return nil + return trace.Wrap(ws.SetReadDeadline(deadlineForInterval(keepAliveInterval))) }) ws.SetCloseHandler(func(code int, text string) error { @@ -476,25 +492,140 @@ func runAssistant(h *Handler, w http.ResponseWriter, r *http.Request, return trace.Wrap(err) } - chat, err := assistClient.NewChat(ctx, authClient, authClient.EmbeddingClient(), conversationID, sctx.GetUser()) + switch r.URL.Query().Get("action") { + case actionSSHGenerateCommand: + err = h.assistGenSSHCommandLoop(ctx, assistClient, ws, sctx.GetUser(), authClient) + case actionSSHExplainCommand: + err = h.assistSSHExplainOutputLoop(ctx, assistClient, ws, authClient) + default: + err = h.assistChatLoop(ctx, assistClient, authClient, conversationID, sctx, ws) + } + + return trace.Wrap(err) +} + +type usageReporter interface { + SubmitUsageEvent(ctx context.Context, req *proto.SubmitUsageEventRequest) error +} + +// assistSSHExplainOutputLoop reads the user's input and generates a command summary. +func (h *Handler) assistSSHExplainOutputLoop(ctx context.Context, assistClient *assist.Assist, ws *websocket.Conn, usageRep usageReporter) error { + _, payload, err := ws.ReadMessage() + if err != nil { + if wsIsClosed(err) { + return nil + } + return trace.Wrap(err) + } + + modelMessages := []*assistpb.AssistantMessage{ + { + Type: string(assist.MessageKindUserMessage), + Payload: string(payload), + }, + } + + summary, tokenCount, err := assistClient.GenerateCommandSummary(ctx, modelMessages, map[string][]byte{}) + if err != nil { + return trace.Wrap(err) + } + + if err := onMessageFn(ws, assist.MessageKindAssistantMessage, []byte(summary), h.clock.Now().UTC()); err != nil { + return trace.Wrap(err) + } + + prompt, completion := model.CountTokens(tokenCount) + + usageEventReq := &clientproto.SubmitUsageEventRequest{ + Event: &usageeventsv1.UsageEventOneOf{ + Event: &usageeventsv1.UsageEventOneOf_AssistAction{ + AssistAction: &usageeventsv1.AssistAction{ + Action: actionSSHExplainCommand, + TotalTokens: int64(completion + prompt), + PromptTokens: int64(prompt), + CompletionTokens: int64(completion), + }, + }, + }, + } + if err := usageRep.SubmitUsageEvent(ctx, usageEventReq); err != nil { + h.log.WithError(err).Warn("Failed to emit usage event") + } + + return nil +} + +// assistSSHCommandLoop reads the user's input and generates a Linux command. +func (h *Handler) assistGenSSHCommandLoop(ctx context.Context, assistClient *assist.Assist, ws *websocket.Conn, username string, usageRep usageReporter) error { + chat, err := assistClient.NewLightweightChat(username) if err != nil { return trace.Wrap(err) } - // onMessageFn is called when a message is received from the OpenAI API. - onMessageFn := func(kind assist.MessageType, payload []byte, createdTime time.Time) error { - msg := &assistantMessage{ - Type: kind, - Payload: string(payload), - CreatedTime: createdTime.Format(time.RFC3339), + for { + _, payload, err := ws.ReadMessage() + if err != nil { + if wsIsClosed(err) { + break + } + return trace.Wrap(err) + } + + tokenCount, err := chat.ProcessComplete(ctx, func(kind assist.MessageType, payload []byte, createdTime time.Time) error { + return onMessageFn(ws, kind, payload, createdTime) + }, string(payload)) + if err != nil { + return trace.Wrap(err) + } + + prompt, completion := model.CountTokens(tokenCount) + + usageEventReq := &clientproto.SubmitUsageEventRequest{ + Event: &usageeventsv1.UsageEventOneOf{ + Event: &usageeventsv1.UsageEventOneOf_AssistAction{ + AssistAction: &usageeventsv1.AssistAction{ + Action: actionSSHGenerateCommand, + TotalTokens: int64(completion + prompt), + PromptTokens: int64(prompt), + CompletionTokens: int64(completion), + }, + }, + }, + } + if err := usageRep.SubmitUsageEvent(ctx, usageEventReq); err != nil { + h.log.WithError(err).Warn("Failed to emit usage event") } + } + return nil +} + +// assistChatLoop is the main chat loop for the assistant. +// It reads the user's input from provided WS and generates a response. +func (h *Handler) assistChatLoop(ctx context.Context, assistClient *assist.Assist, authClient auth.ClientI, + conversationID string, sctx *SessionContext, ws *websocket.Conn, +) error { + ac, err := sctx.GetUserAccessChecker() + if err != nil { + return trace.Wrap(err) + } + + toolsConfig := model.ToolsConfig{ + EmbeddingsClient: authClient.EmbeddingClient(), + AccessChecker: ac, + NodeClient: h.nodeWatcher, + } + chat, err := assistClient.NewChat(ctx, authClient, conversationID, sctx.GetUser(), toolsConfig) + if err != nil { + return trace.Wrap(err) + } - return trace.Wrap(ws.WriteJSON(msg)) + onMessage := func(kind assist.MessageType, payload []byte, createdTime time.Time) error { + return trace.Wrap(onMessageFn(ws, kind, payload, createdTime)) } if chat.IsNewConversation() { // new conversation, generate a hello message - if _, err := chat.ProcessComplete(ctx, onMessageFn, ""); err != nil { + if _, err := chat.ProcessComplete(ctx, onMessage, ""); err != nil { return trace.Wrap(err) } } @@ -502,8 +633,7 @@ func runAssistant(h *Handler, w http.ResponseWriter, r *http.Request, for { _, payload, err := ws.ReadMessage() if err != nil { - if err == io.EOF || websocket.IsCloseError(err, websocket.CloseAbnormalClosure, - websocket.CloseGoingAway, websocket.CloseNormalClosure) { + if wsIsClosed(err) { break } return trace.Wrap(err) @@ -514,11 +644,8 @@ func runAssistant(h *Handler, w http.ResponseWriter, r *http.Request, return trace.Wrap(err) } - // We can not know how many tokens we will consume in advance. - // Try to consume a small amount of tokens first. - const lookaheadTokens = 100 - if !h.assistantLimiter.AllowN(time.Now(), lookaheadTokens) { - err := onMessageFn(assist.MessageKindError, []byte("You have reached the rate limit. Please try again later."), h.clock.Now().UTC()) + if !h.assistantLimiter.AllowN(h.clock.Now(), lookaheadTokens) { + err := onMessageFn(ws, assist.MessageKindError, []byte("You have reached the rate limit. Please try again later."), h.clock.Now().UTC()) if err != nil { return trace.Wrap(err) } @@ -526,7 +653,7 @@ func runAssistant(h *Handler, w http.ResponseWriter, r *http.Request, } //TODO(jakule): Should we sanitize the payload? - usedTokens, err := chat.ProcessComplete(ctx, onMessageFn, wsIncoming.Payload) + usedTokens, err := chat.ProcessComplete(ctx, onMessage, wsIncoming.Payload) if err != nil { return trace.Wrap(err) } @@ -539,3 +666,20 @@ func runAssistant(h *Handler, w http.ResponseWriter, r *http.Request, h.log.Debug("end assistant conversation loop") return nil } + +// wsIsClosed returns true if the error is caused by a closed websocket. +func wsIsClosed(err error) bool { + return err == io.EOF || websocket.IsCloseError(err, websocket.CloseAbnormalClosure, + websocket.CloseGoingAway, websocket.CloseNormalClosure) +} + +// onMessageFn is called when a message is received from the OpenAI API. +func onMessageFn(ws *websocket.Conn, kind assist.MessageType, payload []byte, createdTime time.Time) error { + msg := &assistantMessage{ + Type: kind, + Payload: string(payload), + CreatedTime: createdTime.Format(time.RFC3339), + } + + return trace.Wrap(ws.WriteJSON(msg)) +} diff --git a/lib/web/assistant_test.go b/lib/web/assistant_test.go index 55c7dd1b96122..8632d07a7ab5f 100644 --- a/lib/web/assistant_test.go +++ b/lib/web/assistant_test.go @@ -151,16 +151,7 @@ func Test_runAssistant(t *testing.T) { if tc.setup != nil { tc.setup(t, s) } - - assistRole, err := types.NewRole("assist-access", types.RoleSpecV6{ - Allow: types.RoleConditions{ - Rules: []types.Rule{ - types.NewRule(types.KindAssistant, services.RW()), - }, - }, - }) - require.NoError(t, err) - require.NoError(t, s.server.Auth().UpsertRole(s.ctx, assistRole)) + assistRole := allowAssistAccess(t, s) ctx := context.Background() authPack := s.authPack(t, "foo", assistRole.GetName()) @@ -168,7 +159,7 @@ func Test_runAssistant(t *testing.T) { conversationID := s.makeAssistConversation(t, ctx, authPack) // Make WS client and start the conversation - ws, err := s.makeAssistant(t, authPack, conversationID) + ws, err := s.makeAssistant(t, authPack, conversationID, "") require.NoError(t, err) t.Cleanup(func() { require.NoError(t, ws.Close()) }) @@ -211,7 +202,7 @@ func Test_runAssistError(t *testing.T) { require.NoError(t, err) _, payload, err := ws.ReadMessage() - require.NoError(t, err) + require.NoError(t, err, "expected error message, payload: %s", payload) var msg assistantMessage err = json.Unmarshal(payload, &msg) @@ -250,24 +241,15 @@ func Test_runAssistError(t *testing.T) { openaiCfg.BaseURL = server.URL s := newWebSuiteWithConfig(t, webSuiteConfig{OpenAIConfig: &openaiCfg}) - ctx := context.Background() - - assistRole, err := types.NewRole("assist-access", types.RoleSpecV6{ - Allow: types.RoleConditions{ - Rules: []types.Rule{ - types.NewRule(types.KindAssistant, services.RW()), - }, - }, - }) - require.NoError(t, err) - require.NoError(t, s.server.Auth().UpsertRole(s.ctx, assistRole)) - + assistRole := allowAssistAccess(t, s) authPack := s.authPack(t, "foo", assistRole.GetName()) + + ctx := context.Background() // Create the conversation conversationID := s.makeAssistConversation(t, ctx, authPack) // Make WS client and start the conversation - ws, err := s.makeAssistant(t, authPack, conversationID) + ws, err := s.makeAssistant(t, authPack, conversationID, "") require.NoError(t, err) t.Cleanup(func() { // The TLS connection might or might not be closed, this is an implementation detail. @@ -287,59 +269,88 @@ func Test_runAssistError(t *testing.T) { require.Equal(t, websocket.CloseInternalServerErr, closeErr.Code, "Expected abnormal closure") } -// makeAssistConversation creates a new assist conversation and returns its ID -func (s *WebSuite) makeAssistConversation(t *testing.T, ctx context.Context, authPack *authPack) string { - clt := authPack.clt +func Test_SSHCommandGeneration(t *testing.T) { + t.Parallel() - resp, err := clt.PostJSON(ctx, clt.Endpoint("webapi", "assistant", "conversations"), nil) + assertGenCommand := func(ws *websocket.Conn) { + _, payload, err := ws.ReadMessage() + require.NoError(t, err) + + var msg assistantMessage + err = json.Unmarshal(payload, &msg) + require.NoError(t, err) + + // Expect "hello" message + require.Equal(t, assist.MessageKindProgressUpdate, msg.Type) + require.Contains(t, msg.Payload, "openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes -subj") + } + + responses := []string{generateCommandResponse()} + server := httptest.NewServer(aitest.GetTestHandlerFn(t, responses)) + t.Cleanup(server.Close) + + openaiCfg := openai.DefaultConfig("test-token") + openaiCfg.BaseURL = server.URL + s := newWebSuiteWithConfig(t, webSuiteConfig{OpenAIConfig: &openaiCfg}) + + assistRole := allowAssistAccess(t, s) + authPack := s.authPack(t, "foo", assistRole.GetName()) + + // Make WS client and start the conversation + ws, err := s.makeAssistant(t, authPack, "", "ssh-cmdgen") require.NoError(t, err) + t.Cleanup(func() { + err := ws.Close() + require.NoError(t, err) + }) - convResp := struct { - ConversationID string `json:"id"` - }{} - err = json.Unmarshal(resp.Bytes(), &convResp) + err = ws.WriteMessage(websocket.TextMessage, []byte(`{"input:" "My cert expired!!! What is x509?"}`)) require.NoError(t, err) - return convResp.ConversationID + // verify responses + assertGenCommand(ws) } -// makeAssistant creates a new assistant websocket connection. -func (s *WebSuite) makeAssistant(t *testing.T, pack *authPack, conversationID string) (*websocket.Conn, error) { - u := url.URL{ - Host: s.url().Host, - Scheme: client.WSS, - Path: fmt.Sprintf("/v1/webapi/sites/%s/assistant", currentSiteShortcut), - } +func Test_SSHCommandExplain(t *testing.T) { + t.Parallel() - q := u.Query() - q.Set("conversation_id", conversationID) - q.Set(roundtrip.AccessTokenQueryParam, pack.session.Token) - u.RawQuery = q.Encode() + assertResponse := func(ws *websocket.Conn) { + _, payload, err := ws.ReadMessage() + require.NoError(t, err) - dialer := websocket.Dialer{} - dialer.TLSClientConfig = &tls.Config{ - InsecureSkipVerify: true, - } + var msg assistantMessage + err = json.Unmarshal(payload, &msg) + require.NoError(t, err) - header := http.Header{} - header.Add("Origin", "http://localhost") - for _, cookie := range pack.cookies { - header.Add("Cookie", cookie.String()) + // Expect "hello" message + require.Equal(t, assist.MessageKindAssistantMessage, msg.Type) + require.Contains(t, msg.Payload, "The application has failed to connect to the database. The database is not running.") } - ws, resp, err := dialer.Dial(u.String(), header) - if err != nil { - res, err2 := io.ReadAll(resp.Body) - t.Log("response body:", string(res), err2) - return nil, trace.Wrap(err) - } + responses := []string{commandSummaryResponse()} + server := httptest.NewServer(aitest.GetTestHandlerFn(t, responses)) + t.Cleanup(server.Close) - err = resp.Body.Close() - if err != nil { - return nil, trace.Wrap(err) - } + openaiCfg := openai.DefaultConfig("test-token") + openaiCfg.BaseURL = server.URL + s := newWebSuiteWithConfig(t, webSuiteConfig{OpenAIConfig: &openaiCfg}) - return ws, nil + assistRole := allowAssistAccess(t, s) + authPack := s.authPack(t, "foo", assistRole.GetName()) + + // Make WS client and start the conversation + ws, err := s.makeAssistant(t, authPack, "", "ssh-explain") + require.NoError(t, err) + t.Cleanup(func() { + err := ws.Close() + require.NoError(t, err) + }) + + err = ws.WriteMessage(websocket.TextMessage, []byte(`{"input:" "listen tcp 0.0.0.0:5432: bind: address already in use"}`)) + require.NoError(t, err) + + // verify responses + assertResponse(ws) } func Test_generateAssistantTitle(t *testing.T) { @@ -360,14 +371,7 @@ func Test_generateAssistantTitle(t *testing.T) { OpenAIConfig: &openaiCfg, }) - assistRole, err := types.NewRole("assist-access", types.RoleSpecV6{ - Allow: types.RoleConditions{ - Rules: []types.Rule{ - types.NewRule(types.KindAssistant, services.RW()), - }, - }, - }) - require.NoError(t, err) + assistRole := allowAssistAccess(t, s) require.NoError(t, s.server.Auth().UpsertRole(s.ctx, assistRole)) pack := s.authPack(t, "foo", assistRole.GetName()) @@ -388,7 +392,98 @@ func Test_generateAssistantTitle(t *testing.T) { require.NotEmpty(t, info.Title) } +func allowAssistAccess(t *testing.T, s *WebSuite) types.Role { + assistRole, err := types.NewRole("assist-access", types.RoleSpecV6{ + Allow: types.RoleConditions{ + Rules: []types.Rule{ + types.NewRule(types.KindAssistant, services.RW()), + }, + }, + }) + require.NoError(t, err) + require.NoError(t, s.server.Auth().UpsertRole(s.ctx, assistRole)) + + return assistRole +} + +// makeAssistConversation creates a new assist conversation and returns its ID +func (s *WebSuite) makeAssistConversation(t *testing.T, ctx context.Context, authPack *authPack) string { + clt := authPack.clt + + resp, err := clt.PostJSON(ctx, clt.Endpoint("webapi", "assistant", "conversations"), nil) + require.NoError(t, err) + + convResp := struct { + ConversationID string `json:"id"` + }{} + err = json.Unmarshal(resp.Bytes(), &convResp) + require.NoError(t, err) + + return convResp.ConversationID +} + +// makeAssistant creates a new assistant websocket connection. +func (s *WebSuite) makeAssistant(_ *testing.T, pack *authPack, conversationID, action string) (*websocket.Conn, error) { + if action == "" && conversationID == "" { + return nil, trace.BadParameter("must specify either conversation_id or action") + } + + u := url.URL{ + Host: s.url().Host, + Scheme: client.WSS, + Path: fmt.Sprintf("/v1/webapi/sites/%s/assistant", currentSiteShortcut), + } + + q := u.Query() + if conversationID != "" { + q.Set("conversation_id", conversationID) + } + + if action != "" { + q.Set("action", action) + } + + q.Set(roundtrip.AccessTokenQueryParam, pack.session.Token) + u.RawQuery = q.Encode() + + dialer := websocket.Dialer{} + dialer.TLSClientConfig = &tls.Config{ + InsecureSkipVerify: true, + } + + header := http.Header{} + header.Add("Origin", "http://localhost") + for _, cookie := range pack.cookies { + header.Add("Cookie", cookie.String()) + } + + ws, resp, err := dialer.Dial(u.String(), header) + if err != nil { + return nil, trace.Wrap(err) + } + + err = resp.Body.Close() + if err != nil { + return nil, trace.Wrap(err) + } + + return ws, nil +} + // generateTextResponse generates a response for a text completion func generateTextResponse() string { return "\nWhich node do you want to use?" } + +func generateCommandResponse() string { + return "```" + `json + { + "action": "Command Generation", + "action_input": "{\"command\":\"openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes -subj\"}" + } + ` + "```" +} + +func commandSummaryResponse() string { + return "The application has failed to connect to the database. The database is not running." +} diff --git a/proto/prehog/v1alpha/teleport.proto b/proto/prehog/v1alpha/teleport.proto index da8a5bbeb231d..0941ed84073e4 100644 --- a/proto/prehog/v1alpha/teleport.proto +++ b/proto/prehog/v1alpha/teleport.proto @@ -651,6 +651,36 @@ message AssistNewConversationEvent { string category = 2; } +// AssistAccessRequest is an event that is emitted when a user requests access +// to a resource via Assist. +message AssistAccessRequestEvent { + // UserName is anonymized user name + string user_name = 1; + // ResourceType describes the type of resource the user is requesting access to, e.g. "node", "db", "k8s" or "role". + string resource_type = 2; + // TotalTokens is the total amount of token used to generate the command summary + int64 total_tokens = 4; + // PromptTokens is the amount of estimated tokens used by the prompt to generate the command summary + int64 prompt_tokens = 5; + // CompletionTokens is the amount of tokens that the summary completion response consists of + int64 completion_tokens = 6; +} + +// AssistAction is an event that is emitted when a user triggers an action (SSH command generation, output explain, etc.) +// via Assist. +message AssistActionEvent { + // UserName is anonymized user name + string user_name = 1; + // Action is the action that was triggered, e.g. "ssh-explain", "ssh-command-generate", etc. + string action = 2; + // TotalTokens is the total amount of token used to generate the command summary + int64 total_tokens = 4; + // PromptTokens is the amount of estimated tokens used by the prompt to generate the command summary + int64 prompt_tokens = 5; + // CompletionTokens is the amount of tokens that the summary completion response consists of + int64 completion_tokens = 6; +} + // IntegrationEnrollKind represents the types of integration that // can be enrolled. enum IntegrationEnrollKind { @@ -819,6 +849,9 @@ message SubmitEventRequest { AssistNewConversationEvent assist_new_conversation = 51; DeviceAuthenticateEvent device_authenticate_event = 52; + + AssistAccessRequestEvent assist_access_request = 54; + AssistActionEvent assist_action = 55; } reserved 8; // UIOnboardGetStartedClickEvent diff --git a/web/packages/teleport/src/Console/DocumentSsh/DocumentSsh.tsx b/web/packages/teleport/src/Console/DocumentSsh/DocumentSsh.tsx index 959c9ad778c3c..8aafcb8b37424 100644 --- a/web/packages/teleport/src/Console/DocumentSsh/DocumentSsh.tsx +++ b/web/packages/teleport/src/Console/DocumentSsh/DocumentSsh.tsx @@ -31,6 +31,12 @@ import * as stores from 'teleport/Console/stores'; import AuthnDialog from 'teleport/components/AuthnDialog'; import useWebAuthn from 'teleport/lib/useWebAuthn'; +import { TerminalAssistContextProvider } from 'teleport/Console/DocumentSsh/TerminalAssist/TerminalAssistContext'; + +import { useTeleport } from 'teleport'; + +import { useConsoleContext } from 'teleport/Console/consoleContextProvider'; + import Document from '../Document'; import { Terminal, TerminalRef } from './Terminal'; @@ -46,6 +52,12 @@ export default function DocumentSshWrapper(props: PropTypes) { } function DocumentSsh({ doc, visible }: PropTypes) { + const ctx = useTeleport(); + const consoleCtx = useConsoleContext(); + + const assistEnabled = + consoleCtx.storeUser.getAssistantAccess().list && ctx.assistEnabled; + const terminalRef = useRef(); const { tty, status, closeDocument, session } = useSshSession(doc); const webauthn = useWebAuthn(tty); @@ -70,6 +82,16 @@ function DocumentSsh({ doc, visible }: PropTypes) { terminalRef.current?.focus(); }, [visible, webauthn.requested]); + const terminal = ( + + ); + return ( @@ -85,14 +107,14 @@ function DocumentSsh({ doc, visible }: PropTypes) { errorText={webauthn.errorText} /> )} - {status === 'initialized' && ( - - )} + {status === 'initialized' && + (assistEnabled ? ( + + {terminal} + + ) : ( + terminal + ))} ((props, ref) => { const termCtrlRef = useRef(); const elementRef = useRef(); + const assist = useTerminalAssist(); + + const [actionBarState, setActionBarState] = useState({ + top: 0, + left: 0, + visible: false, + }); + useImperativeHandle( ref, () => ({ @@ -74,24 +94,102 @@ export const Terminal = forwardRef((props, ref) => { } }); + if (props.assistEnabled) { + termCtrl.term.onSelectionChange(() => { + const term = termCtrl.term; + + const position = term.getSelectionPosition(); + const selection = term.getSelection().trim(); + + if (position && selection) { + const charWidth = Math.ceil(term.element.offsetWidth / term.cols); + const charHeight = Math.ceil(term.element.offsetHeight / term.rows); + + const left = Math.round( + ((position.start.x + position.end.x) / 2) * charWidth + ); + const top = Math.round((position.end.y + 2) * charHeight) + 15; + + setActionBarState({ + visible: true, + left, + top, + }); + + return; + } + + setActionBarState(position => ({ + ...position, + visible: false, + })); + }); + } + return () => termCtrl.destroy(); // do not re-initialize xterm when theme changes, use specialized handlers. // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + }, [props.assistEnabled]); + + function handleUseCommand(command: string) { + termCtrlRef.current.term.paste(command); + } + + function handleAssistClose() { + termCtrlRef.current.term.focus(); + } + + function handleAskAssist() { + assist.explainSelection(termCtrlRef.current.term.getSelection()); + } + + function handleActionBarClose() { + setActionBarState(position => ({ + ...position, + visible: false, + })); + } + + function handleActionBarCopy() { + const selection = termCtrlRef.current.term.getSelection(); + + if (selection) { + void navigator.clipboard.writeText(selection); + } + } useEffect(() => { termCtrlRef.current?.updateTheme(props.theme); }, [props.theme]); return ( - - - + <> + + + + + {props.assistEnabled && ( + <> + + + + + )} + ); }); diff --git a/web/packages/teleport/src/Console/DocumentSsh/TerminalAssist/ActionBar.tsx b/web/packages/teleport/src/Console/DocumentSsh/TerminalAssist/ActionBar.tsx new file mode 100644 index 0000000000000..6bacadbb05bd7 --- /dev/null +++ b/web/packages/teleport/src/Console/DocumentSsh/TerminalAssist/ActionBar.tsx @@ -0,0 +1,104 @@ +/** + * Copyright 2023 Gravitational, Inc. + * + * 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. + */ + +import React from 'react'; +import styled from 'styled-components'; + +import { Copy, Cross } from 'design/Icon'; +import { BrainIcon } from 'design/SVGIcon'; + +interface Position { + top: number; + left: number; +} + +interface ActionBarProps { + position: Position; + visible: boolean; + onAskAssist: () => void; + onClose: () => void; + onCopy: () => void; +} + +const Container = styled.div` + position: absolute; + background: ${p => p.theme.colors.levels.popout}; + border: 1px solid ${p => p.theme.colors.spotBackground[1]}; + box-shadow: 0 0 10px ${p => p.theme.colors.spotBackground[1]}; + border-radius: 10px; + line-height: 1; + z-index: 100; + transform: translate(-50%, 0); + display: flex; + overflow: hidden; + padding: ${p => p.theme.space[1] / 2}px; + transition: opacity 0.2s ease-in-out; + opacity: ${p => (p.visible ? 1 : 0)}; + pointer-events: ${p => (p.visible ? 'auto' : 'none')}; +`; + +const Button = styled.div` + font-size: 13px; + display: flex; + align-items: center; + gap: ${p => p.theme.space[2]}px; + padding: ${p => p.theme.space[1]}px ${p => p.theme.space[2]}px; + border-radius: 5px; + cursor: pointer; + + &:hover { + background: ${p => p.theme.colors.spotBackground[0]}; + } +`; + +const CloseButton = styled(Button)` + padding: ${p => p.theme.space[2]}px; +`; + +export function ActionBar(props: ActionBarProps) { + const left = Math.max(props.position.left, 110); // make sure the bar is not off the edge of the screen + + function handleAskAssist() { + props.onClose(); + props.onAskAssist(); + } + + function handleCopy() { + props.onClose(); + props.onCopy(); + } + + return ( + + + + + + + + + + ); +} diff --git a/web/packages/teleport/src/Console/DocumentSsh/TerminalAssist/MessageBox.tsx b/web/packages/teleport/src/Console/DocumentSsh/TerminalAssist/MessageBox.tsx new file mode 100644 index 0000000000000..f53de57c02843 --- /dev/null +++ b/web/packages/teleport/src/Console/DocumentSsh/TerminalAssist/MessageBox.tsx @@ -0,0 +1,111 @@ +/** + * Copyright 2023 Gravitational, Inc. + * + * 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. + */ + +import React, { ChangeEvent, useEffect, useRef, useState } from 'react'; +import styled from 'styled-components'; + +import { useTerminalAssist } from 'teleport/Console/DocumentSsh/TerminalAssist/TerminalAssistContext'; + +interface MessageBoxProps { + onUseCommand: (command: string) => void; +} + +const Container = styled.div` + padding: 0 ${p => p.theme.space[2]}px + ${p => p.theme.space[2] + p.theme.space[1]}px ${p => p.theme.space[2]}px; +`; + +const Input = styled.input` + width: 100%; + background: ${props => props.theme.colors.levels.popout}; + color: ${props => props.theme.colors.text.main}; + border: 2px solid ${props => props.theme.colors.spotBackground[1]}; + border-radius: 18px; + resize: none; + padding: ${p => p.theme.space[3]}px; + font-size: 14px; + line-height: 1; + box-sizing: border-box; + overflow-y: hidden; + + &:focus { + outline: none; + border-color: ${props => props.theme.colors.spotBackground[2]}; + } + + ::placeholder { + color: ${props => props.theme.colors.text.muted}; + } +`; + +export function MessageBox(props: MessageBoxProps) { + const { close, getLastSuggestedCommand, loading, send, visible } = + useTerminalAssist(); + + const ref = useRef(null); + + const [value, setValue] = useState(''); + + function handleChange(event: ChangeEvent) { + setValue(event.target.value); + } + + function handleKeyDown(event: React.KeyboardEvent) { + if (!visible || event.key !== 'Enter') { + return; + } + + if (event.metaKey) { + const lastCommand = getLastSuggestedCommand(); + + if (lastCommand) { + close(); + + props.onUseCommand(lastCommand); + } + + return; + } + + if (loading || !value) { + return; + } + + event.preventDefault(); + event.stopPropagation(); + + send(value); + setValue(''); + } + + useEffect(() => { + if (visible) { + ref.current.focus(); + } + }, [visible]); + + return ( + + + + ); +} diff --git a/web/packages/teleport/src/Console/DocumentSsh/TerminalAssist/MessageItem.tsx b/web/packages/teleport/src/Console/DocumentSsh/TerminalAssist/MessageItem.tsx new file mode 100644 index 0000000000000..2f291244a6082 --- /dev/null +++ b/web/packages/teleport/src/Console/DocumentSsh/TerminalAssist/MessageItem.tsx @@ -0,0 +1,187 @@ +/** + * Copyright 2023 Gravitational, Inc. + * + * 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. + */ + +import React from 'react'; +import styled from 'styled-components'; + +import { + Message, + MessageType, +} from 'teleport/Console/DocumentSsh/TerminalAssist/types'; +import { + Key, + KeyShortcut, +} from 'teleport/Console/DocumentSsh/TerminalAssist/Shared'; +import { getMetaKeySymbol } from 'teleport/Console/DocumentSsh/TerminalAssist/utils'; + +interface MessageItemProps { + message: Message; + onUseCommand: (command: string) => void; + lastMessage?: boolean; +} + +const UserMessage = styled.div` + padding: ${p => p.theme.space[2]}px ${p => p.theme.space[3]}px; + border: 1px solid ${p => p.theme.colors.spotBackground[0]}; + box-shadow: 0 0 3px ${p => p.theme.colors.spotBackground[0]}; + border-radius: 7px; +`; + +const MessageContainer = styled.div` + display: flex; + width: 100%; +`; + +const UserMessageContainer = styled(MessageContainer)` + justify-content: flex-end; +`; + +const Explanation = styled.div` + background: ${props => props.theme.colors.spotBackground[0]}; + border-radius: 15px; + padding: ${p => p.theme.space[3]}px; + overflow: hidden; +`; + +const Reasoning = styled.div` + font-size: 14px; + border-left: 2px solid ${p => p.theme.colors.spotBackground[1]}; + padding: ${p => p.theme.space[1]}px 0 ${p => p.theme.space[1]}px + ${p => p.theme.space[2]}px; + margin: ${p => p.theme.space[1]}px 0; +`; + +const SuggestedCommand = styled.div` + background: ${props => props.theme.colors.spotBackground[0]}; + border-radius: 15px; + padding: ${p => p.theme.space[3]}px; + overflow: hidden; +`; + +const SuggestedCommandTitle = styled.div` + font-weight: 700; + color: ${props => props.theme.colors.text.slightlyMuted}; +`; + +const Command = styled.pre.attrs({ + 'data-scrollbar': 'default', +})` + margin: 0 -${p => p.theme.space[2]}px -${p => p.theme.space[2]}px; + padding: ${p => p.theme.space[2]}px; + font-family: ${p => p.theme.fonts.mono}; + overflow-x: auto; + font-size: 13px; +`; + +const SuggestedCommandButtons = styled.div` + display: flex; + gap: ${p => p.theme.space[2]}px; + margin-top: ${p => p.theme.space[3]}px; +`; + +const SuggestedCommandButton = styled.div` + display: flex; + align-items: center; + gap: ${p => p.theme.space[2]}px; + font-size: 14px; + padding: ${p => p.theme.space[2]}px ${p => p.theme.space[3]}px; + border: 1px solid ${p => p.theme.colors.spotBackground[1]}; + border-radius: 7px; + line-height: 1; + font-weight: bold; + cursor: pointer; + + ${KeyShortcut} { + background: ${p => p.theme.colors.spotBackground[0]}; + border-color: ${p => p.theme.colors.spotBackground[0]}; + color: ${p => p.theme.colors.text.main}; + opacity: 0.7; + + span { + opacity: 0.5; + } + } +`; + +const UseCommandButton = styled(SuggestedCommandButton)` + background: ${p => p.theme.colors.buttons.primary.default}; + color: ${p => p.theme.colors.buttons.primary.text}; + + ${KeyShortcut} { + background: ${p => p.theme.colors.buttons.primary.default}; + border-color: ${p => p.theme.colors.buttons.primary.default}; + } + + ${Key} { + color: ${p => p.theme.colors.buttons.primary.text}; + } +`; + +export function MessageItem(props: MessageItemProps) { + function handleUseCommand() { + if (props.message.type !== MessageType.SuggestedCommand) { + return; + } + + props.onUseCommand(props.message.command); + } + + if (props.message.type === MessageType.User) { + return ( + + {props.message.value} + + ); + } + + if (props.message.type === MessageType.SuggestedCommand) { + return ( + + + Suggested command + + {props.message.reasoning} + + {props.message.command} + + + + Use + {props.lastMessage && ( + + + {getMetaKeySymbol()} + +⏎ + + + )} + + + + + ); + } + + if (props.message.type === MessageType.Explanation) { + return ( + + {props.message.value} + + ); + } + + return null; +} diff --git a/web/packages/teleport/src/Console/DocumentSsh/TerminalAssist/Shared.tsx b/web/packages/teleport/src/Console/DocumentSsh/TerminalAssist/Shared.tsx new file mode 100644 index 0000000000000..e4ffa6c97b28c --- /dev/null +++ b/web/packages/teleport/src/Console/DocumentSsh/TerminalAssist/Shared.tsx @@ -0,0 +1,38 @@ +/** + * Copyright 2023 Gravitational, Inc. + * + * 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. + */ + +import styled from 'styled-components'; + +export const Key = styled.div` + line-height: 1; + background: ${p => p.theme.colors.spotBackground[1]}; + padding: 2px; + border: 1px solid ${p => p.theme.colors.spotBackground[1]}; + border-radius: ${p => p.theme.space[1]}px; + font-weight: 700; + color: ${p => p.theme.colors.text.muted}; +`; + +export const KeyShortcut = styled.div` + display: flex; + align-items: center; + gap: ${p => p.theme.space[1]}px; + opacity: 0.5; + font-size: 12px; + pointer-events: none; + user-select: none; + transition: opacity 0.2s ease-in-out; +`; diff --git a/web/packages/teleport/src/Console/DocumentSsh/TerminalAssist/TerminalAssist.tsx b/web/packages/teleport/src/Console/DocumentSsh/TerminalAssist/TerminalAssist.tsx new file mode 100644 index 0000000000000..b869a3de6765f --- /dev/null +++ b/web/packages/teleport/src/Console/DocumentSsh/TerminalAssist/TerminalAssist.tsx @@ -0,0 +1,205 @@ +/** + * Copyright 2023 Gravitational, Inc. + * + * 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. + */ + +import React, { useEffect } from 'react'; +import styled from 'styled-components'; + +import { BrainIcon, CloseIcon } from 'design/SVGIcon'; + +import { HeaderIcon, Tooltip } from 'teleport/Assist/shared'; +import { + TypingContainer, + TypingDot, +} from 'teleport/Assist/Conversation/Typing'; +import { useTerminalAssist } from 'teleport/Console/DocumentSsh/TerminalAssist/TerminalAssistContext'; +import { + Key, + KeyShortcut, +} from 'teleport/Console/DocumentSsh/TerminalAssist/Shared'; +import { MessageItem } from 'teleport/Console/DocumentSsh/TerminalAssist/MessageItem'; +import { getMetaKeySymbol } from 'teleport/Console/DocumentSsh/TerminalAssist/utils'; +import { MessageBox } from 'teleport/Console/DocumentSsh/TerminalAssist/MessageBox'; + +interface TerminalAssistProps { + onUseCommand: (command: string) => void; + onClose: () => void; +} + +const Container = styled.div` + position: fixed; + bottom: 10px; + right: 20px; + display: flex; + flex-direction: column; + gap: ${p => p.theme.space[2]}px; + z-index: 1000; +`; + +const Button = styled.div` + display: flex; + align-items: center; + justify-content: center; + transition: opacity 0.2s ease-in-out; + cursor: pointer; + width: 50px; + height: 50px; + position: relative; + z-index: 2; + + svg path { + fill: white; + } +`; + +const Background = styled.div` + position: absolute; + bottom: 32px; + right: 2px; + border-radius: ${p => (p.visible ? '25px' : '25px')}; + background: ${p => (p.visible ? p.theme.colors.levels.popout : '#311c79')}; + width: ${p => (p.visible ? '500px' : '50px')}; + height: ${p => (p.visible ? '600px' : '50px')}; + transition: all + ${p => + p.visible + ? '0.5s cubic-bezier(0.33, 1.2, 0.68, 1)' + : '0.3s cubic-bezier(0.33, 1, 0.68, 1)'}; + transform-origin: bottom right; + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.4); +`; + +const ChatContainer = styled.div` + position: absolute; + bottom: 30px; + right: 2px; + width: 500px; + height: 600px; + display: flex; + flex-direction: column; + justify-content: flex-end; + opacity: ${p => (p.visible ? 1 : 0)}; + transition: ${p => (p.visible ? 'opacity 0.5s ease-in-out' : 'none')}; + transition-delay: 0.2s; + box-sizing: border-box; +`; + +const Header = styled.header` + display: flex; + align-items: center; + justify-content: space-between; + padding: ${p => p.theme.space[2]}px ${p => p.theme.space[3]}px + ${p => p.theme.space[2]}px ${p => p.theme.space[2] + p.theme.space[3]}px; + border-bottom: 1px solid ${p => p.theme.colors.spotBackground[0]}; + user-select: none; + box-sizing: border-box; +`; + +const ScrollArea = styled.div.attrs({ + 'data-scrollbar': 'default', +})` + flex: 1; + overflow-y: auto; + display: flex; + flex-direction: column-reverse; + padding: 0 ${p => p.theme.space[2]}px ${p => p.theme.space[2]}px + ${p => p.theme.space[2]}px; + gap: ${p => p.theme.space[2]}px; +`; + +const Title = styled.h2` + margin: 0; + font-size: 16px; +`; + +export function TerminalAssist(props: TerminalAssistProps) { + const { close, loading, messages, open, visible } = useTerminalAssist(); + + useEffect(() => { + function keyDownHandler(e: KeyboardEvent) { + if (e.metaKey && e.key === '/') { + e.preventDefault(); + e.stopPropagation(); + + visible ? close() : open(); + } + } + + window.addEventListener('keydown', keyDownHandler); + + return () => { + window.removeEventListener('keydown', keyDownHandler); + }; + }, [visible]); + + function handleUseCommand(command: string) { + props.onUseCommand(command); + close(); + } + + return ( + + + + +
+ Assist + + + + + Hide Assist + +
+ + + {loading && ( + + + + + + )} + + {messages.map((m, i) => ( + + ))} + + + +
+ + + + + {getMetaKeySymbol()}+ + / + +
+ ); +} diff --git a/web/packages/teleport/src/Console/DocumentSsh/TerminalAssist/TerminalAssistContext.tsx b/web/packages/teleport/src/Console/DocumentSsh/TerminalAssist/TerminalAssistContext.tsx new file mode 100644 index 0000000000000..9af1886c7a1a9 --- /dev/null +++ b/web/packages/teleport/src/Console/DocumentSsh/TerminalAssist/TerminalAssistContext.tsx @@ -0,0 +1,185 @@ +/** + * Copyright 2023 Gravitational, Inc. + * + * 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. + */ + +import React, { + createContext, + PropsWithChildren, + useContext, + useEffect, + useRef, + useState, +} from 'react'; + +import { Author, ServerMessage } from 'teleport/Assist/types'; +import { getAccessToken, getHostName } from 'teleport/services/api'; +import useStickyClusterId from 'teleport/useStickyClusterId'; +import cfg from 'teleport/config'; +import { + ExplanationMessage, + Message, + MessageType, + SuggestedCommandMessage, + UserMessage, +} from 'teleport/Console/DocumentSsh/TerminalAssist/types'; + +interface TerminalAssistContextValue { + close: () => void; + explainSelection: (selection: string) => void; + getLastSuggestedCommand: () => string; + loading: boolean; + messages: Message[]; + open: () => void; + send: (message: string) => void; + visible: boolean; +} + +const TerminalAssistContext = createContext(null); + +export function TerminalAssistContextProvider( + props: PropsWithChildren +) { + const { clusterId } = useStickyClusterId(); + + const [visible, setVisible] = useState(false); + + const socketRef = useRef(null); + const socketUrl = cfg.getAssistActionWebSocketUrl( + getHostName(), + clusterId, + getAccessToken(), + 'ssh-cmdgen' + ); + + const [loading, setLoading] = useState(false); + + // note: we store messages in reverse order so that we can use flex-direction: column-reverse + // to automatically scroll to the bottom of the list + const [messages, setMessages] = useState([]); + + useEffect(() => { + socketRef.current = new WebSocket(socketUrl); + + socketRef.current.onmessage = e => { + const data = JSON.parse(e.data) as ServerMessage; + const payload = JSON.parse(data.payload) as { + action: string; + input: string; + reasoning: string; + }; + const input = JSON.parse(payload.input) as { + command: string; + }; + + const message: SuggestedCommandMessage = { + author: Author.Teleport, + type: MessageType.SuggestedCommand, + command: input.command, + reasoning: payload.reasoning, + }; + + setLoading(false); + setMessages(m => [message, ...m]); + }; + }, []); + + function close() { + setVisible(false); + } + + function open() { + setVisible(true); + } + + function explainSelection(selection: string) { + if (!visible) { + setVisible(true); + } + + setLoading(true); + + const encodedOutput = btoa(selection); + + const socketUrl = cfg.getAssistActionWebSocketUrl( + getHostName(), + clusterId, + getAccessToken(), + 'ssh-explain' + ); + + const ws = new WebSocket(socketUrl); + + ws.onopen = () => { + ws.send(encodedOutput); + }; + + ws.onmessage = event => { + const message = event.data; + const msg = JSON.parse(message) as ServerMessage; + + const explanation: ExplanationMessage = { + author: Author.Teleport, + type: MessageType.Explanation, + value: msg.payload, + }; + + setMessages(m => [explanation, ...m]); + setLoading(false); + + ws.close(); + }; + } + + function send(message: string) { + setLoading(true); + + const userMessage: UserMessage = { + author: Author.User, + type: MessageType.User, + value: message, + }; + + socketRef.current.send(message); + + setMessages(m => [userMessage, ...m]); + } + + function getLastSuggestedCommand() { + if (messages[0] && messages[0].type === MessageType.SuggestedCommand) { + return (messages[0] as SuggestedCommandMessage).command; + } + } + + return ( + + {props.children} + + ); +} + +export function useTerminalAssist() { + return useContext(TerminalAssistContext); +} diff --git a/web/packages/teleport/src/Console/DocumentSsh/TerminalAssist/index.ts b/web/packages/teleport/src/Console/DocumentSsh/TerminalAssist/index.ts new file mode 100644 index 0000000000000..bf9dc29d740e4 --- /dev/null +++ b/web/packages/teleport/src/Console/DocumentSsh/TerminalAssist/index.ts @@ -0,0 +1,17 @@ +/** + * Copyright 2023 Gravitational, Inc. + * + * 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. + */ + +export { TerminalAssist } from './TerminalAssist'; diff --git a/web/packages/teleport/src/Console/DocumentSsh/TerminalAssist/types.ts b/web/packages/teleport/src/Console/DocumentSsh/TerminalAssist/types.ts new file mode 100644 index 0000000000000..79b1797dccac7 --- /dev/null +++ b/web/packages/teleport/src/Console/DocumentSsh/TerminalAssist/types.ts @@ -0,0 +1,47 @@ +/** + * Copyright 2023 Gravitational, Inc. + * + * 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. + */ + +import { Author } from 'teleport/Assist/types'; + +export enum MessageType { + User, + SuggestedCommand, + Explanation, +} + +export interface UserMessage { + author: Author.User; + type: MessageType.User; + value: string; +} + +export interface SuggestedCommandMessage { + author: Author.Teleport; + type: MessageType.SuggestedCommand; + command: string; + reasoning: string; +} + +export interface ExplanationMessage { + author: Author.Teleport; + type: MessageType.Explanation; + value: string; +} + +export type Message = + | UserMessage + | SuggestedCommandMessage + | ExplanationMessage; diff --git a/web/packages/teleport/src/Console/DocumentSsh/TerminalAssist/utils.ts b/web/packages/teleport/src/Console/DocumentSsh/TerminalAssist/utils.ts new file mode 100644 index 0000000000000..375656864f2ce --- /dev/null +++ b/web/packages/teleport/src/Console/DocumentSsh/TerminalAssist/utils.ts @@ -0,0 +1,27 @@ +/** + * Copyright 2023 Gravitational, Inc. + * + * 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. + */ + +import { getPlatform } from 'design/theme/utils'; + +export function getMetaKeySymbol() { + const platform = getPlatform(); + + if (platform.isMac) { + return '⌘'; + } + + return '⊞'; +} diff --git a/web/packages/teleport/src/config.ts b/web/packages/teleport/src/config.ts index 0adf91b5b730c..ce651fb9b3f07 100644 --- a/web/packages/teleport/src/config.ts +++ b/web/packages/teleport/src/config.ts @@ -731,6 +731,25 @@ const cfg = { ); }, + getAssistActionWebSocketUrl( + hostname: string, + clusterId: string, + accessToken: string, + action: string + ) { + const searchParams = new URLSearchParams(); + + searchParams.set('access_token', accessToken); + searchParams.set('action', action); + + return ( + generatePath(cfg.api.assistConversationWebSocketPath, { + hostname, + clusterId, + }) + `?${searchParams.toString()}` + ); + }, + getAssistConversationHistoryUrl(conversationId: string) { return generatePath(cfg.api.assistConversationHistoryPath, { conversationId,