diff --git a/proto/gen/rill/runtime/v1/api.pb.go b/proto/gen/rill/runtime/v1/api.pb.go index da659abb968..e1673bfc575 100644 --- a/proto/gen/rill/runtime/v1/api.pb.go +++ b/proto/gen/rill/runtime/v1/api.pb.go @@ -238,7 +238,7 @@ func (x ConnectorDriver_Property_Type) Number() protoreflect.EnumNumber { // Deprecated: Use ConnectorDriver_Property_Type.Descriptor instead. func (ConnectorDriver_Property_Type) EnumDescriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{67, 0, 0} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{76, 0, 0} } // Request message for RuntimeService.Ping @@ -3109,6 +3109,644 @@ func (x *GenerateCanvasFileResponse) GetAiSucceeded() bool { return false } +type GenerateTemplateRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + InstanceId string `protobuf:"bytes,1,opt,name=instance_id,json=instanceId,proto3" json:"instance_id,omitempty"` + ResourceType string `protobuf:"bytes,2,opt,name=resource_type,json=resourceType,proto3" json:"resource_type,omitempty"` + Driver string `protobuf:"bytes,3,opt,name=driver,proto3" json:"driver,omitempty"` + Properties *structpb.Struct `protobuf:"bytes,4,opt,name=properties,proto3" json:"properties,omitempty"` + ConnectorName string `protobuf:"bytes,5,opt,name=connector_name,json=connectorName,proto3" json:"connector_name,omitempty"` +} + +func (x *GenerateTemplateRequest) Reset() { + *x = GenerateTemplateRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_rill_runtime_v1_api_proto_msgTypes[47] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GenerateTemplateRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GenerateTemplateRequest) ProtoMessage() {} + +func (x *GenerateTemplateRequest) ProtoReflect() protoreflect.Message { + mi := &file_rill_runtime_v1_api_proto_msgTypes[47] + 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 GenerateTemplateRequest.ProtoReflect.Descriptor instead. +func (*GenerateTemplateRequest) Descriptor() ([]byte, []int) { + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{47} +} + +func (x *GenerateTemplateRequest) GetInstanceId() string { + if x != nil { + return x.InstanceId + } + return "" +} + +func (x *GenerateTemplateRequest) GetResourceType() string { + if x != nil { + return x.ResourceType + } + return "" +} + +func (x *GenerateTemplateRequest) GetDriver() string { + if x != nil { + return x.Driver + } + return "" +} + +func (x *GenerateTemplateRequest) GetProperties() *structpb.Struct { + if x != nil { + return x.Properties + } + return nil +} + +func (x *GenerateTemplateRequest) GetConnectorName() string { + if x != nil { + return x.ConnectorName + } + return "" +} + +type GenerateTemplateResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Blob string `protobuf:"bytes,1,opt,name=blob,proto3" json:"blob,omitempty"` + EnvVars map[string]string `protobuf:"bytes,2,rep,name=env_vars,json=envVars,proto3" json:"env_vars,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + // Actual resource type used; may differ from request when driver is rewritten + ResourceType string `protobuf:"bytes,3,opt,name=resource_type,json=resourceType,proto3" json:"resource_type,omitempty"` + // Actual driver used; may differ from request when rewritten to duckdb + Driver string `protobuf:"bytes,4,opt,name=driver,proto3" json:"driver,omitempty"` +} + +func (x *GenerateTemplateResponse) Reset() { + *x = GenerateTemplateResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_rill_runtime_v1_api_proto_msgTypes[48] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GenerateTemplateResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GenerateTemplateResponse) ProtoMessage() {} + +func (x *GenerateTemplateResponse) ProtoReflect() protoreflect.Message { + mi := &file_rill_runtime_v1_api_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 GenerateTemplateResponse.ProtoReflect.Descriptor instead. +func (*GenerateTemplateResponse) Descriptor() ([]byte, []int) { + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{48} +} + +func (x *GenerateTemplateResponse) GetBlob() string { + if x != nil { + return x.Blob + } + return "" +} + +func (x *GenerateTemplateResponse) GetEnvVars() map[string]string { + if x != nil { + return x.EnvVars + } + return nil +} + +func (x *GenerateTemplateResponse) GetResourceType() string { + if x != nil { + return x.ResourceType + } + return "" +} + +func (x *GenerateTemplateResponse) GetDriver() string { + if x != nil { + return x.Driver + } + return "" +} + +// Template describes a declarative template for generating project files. +type Template struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + DisplayName string `protobuf:"bytes,2,opt,name=display_name,json=displayName,proto3" json:"display_name,omitempty"` + Driver string `protobuf:"bytes,3,opt,name=driver,proto3" json:"driver,omitempty"` + Olap string `protobuf:"bytes,4,opt,name=olap,proto3" json:"olap,omitempty"` + Tags []string `protobuf:"bytes,5,rep,name=tags,proto3" json:"tags,omitempty"` + Files []*TemplateFile `protobuf:"bytes,6,rep,name=files,proto3" json:"files,omitempty"` + // JSON Schema for form generation and property metadata. + JsonSchema *structpb.Struct `protobuf:"bytes,7,opt,name=json_schema,json=jsonSchema,proto3" json:"json_schema,omitempty"` + // Short description of the template. + Description string `protobuf:"bytes,8,opt,name=description,proto3" json:"description,omitempty"` + // Link to documentation. + DocsUrl string `protobuf:"bytes,9,opt,name=docs_url,json=docsUrl,proto3" json:"docs_url,omitempty"` + // Icon component name for full-size display. + Icon string `protobuf:"bytes,10,opt,name=icon,proto3" json:"icon,omitempty"` + // Icon component name for small display. + SmallIcon string `protobuf:"bytes,11,opt,name=small_icon,json=smallIcon,proto3" json:"small_icon,omitempty"` +} + +func (x *Template) Reset() { + *x = Template{} + if protoimpl.UnsafeEnabled { + mi := &file_rill_runtime_v1_api_proto_msgTypes[49] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Template) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Template) ProtoMessage() {} + +func (x *Template) ProtoReflect() protoreflect.Message { + mi := &file_rill_runtime_v1_api_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 Template.ProtoReflect.Descriptor instead. +func (*Template) Descriptor() ([]byte, []int) { + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{49} +} + +func (x *Template) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Template) GetDisplayName() string { + if x != nil { + return x.DisplayName + } + return "" +} + +func (x *Template) GetDriver() string { + if x != nil { + return x.Driver + } + return "" +} + +func (x *Template) GetOlap() string { + if x != nil { + return x.Olap + } + return "" +} + +func (x *Template) GetTags() []string { + if x != nil { + return x.Tags + } + return nil +} + +func (x *Template) GetFiles() []*TemplateFile { + if x != nil { + return x.Files + } + return nil +} + +func (x *Template) GetJsonSchema() *structpb.Struct { + if x != nil { + return x.JsonSchema + } + return nil +} + +func (x *Template) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *Template) GetDocsUrl() string { + if x != nil { + return x.DocsUrl + } + return "" +} + +func (x *Template) GetIcon() string { + if x != nil { + return x.Icon + } + return "" +} + +func (x *Template) GetSmallIcon() string { + if x != nil { + return x.SmallIcon + } + return "" +} + +// TemplateFile describes a single output file within a template. +type TemplateFile struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + PathPattern string `protobuf:"bytes,2,opt,name=path_pattern,json=pathPattern,proto3" json:"path_pattern,omitempty"` +} + +func (x *TemplateFile) Reset() { + *x = TemplateFile{} + if protoimpl.UnsafeEnabled { + mi := &file_rill_runtime_v1_api_proto_msgTypes[50] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TemplateFile) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TemplateFile) ProtoMessage() {} + +func (x *TemplateFile) ProtoReflect() protoreflect.Message { + mi := &file_rill_runtime_v1_api_proto_msgTypes[50] + 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 TemplateFile.ProtoReflect.Descriptor instead. +func (*TemplateFile) Descriptor() ([]byte, []int) { + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{50} +} + +func (x *TemplateFile) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *TemplateFile) GetPathPattern() string { + if x != nil { + return x.PathPattern + } + return "" +} + +type ListTemplatesRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Optional tag filter; only templates matching ALL tags are returned. + Tags []string `protobuf:"bytes,1,rep,name=tags,proto3" json:"tags,omitempty"` +} + +func (x *ListTemplatesRequest) Reset() { + *x = ListTemplatesRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_rill_runtime_v1_api_proto_msgTypes[51] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListTemplatesRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListTemplatesRequest) ProtoMessage() {} + +func (x *ListTemplatesRequest) ProtoReflect() protoreflect.Message { + mi := &file_rill_runtime_v1_api_proto_msgTypes[51] + 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 ListTemplatesRequest.ProtoReflect.Descriptor instead. +func (*ListTemplatesRequest) Descriptor() ([]byte, []int) { + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{51} +} + +func (x *ListTemplatesRequest) GetTags() []string { + if x != nil { + return x.Tags + } + return nil +} + +type ListTemplatesResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Templates []*Template `protobuf:"bytes,1,rep,name=templates,proto3" json:"templates,omitempty"` +} + +func (x *ListTemplatesResponse) Reset() { + *x = ListTemplatesResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_rill_runtime_v1_api_proto_msgTypes[52] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListTemplatesResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListTemplatesResponse) ProtoMessage() {} + +func (x *ListTemplatesResponse) ProtoReflect() protoreflect.Message { + mi := &file_rill_runtime_v1_api_proto_msgTypes[52] + 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 ListTemplatesResponse.ProtoReflect.Descriptor instead. +func (*ListTemplatesResponse) Descriptor() ([]byte, []int) { + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{52} +} + +func (x *ListTemplatesResponse) GetTemplates() []*Template { + if x != nil { + return x.Templates + } + return nil +} + +type GenerateFileRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + InstanceId string `protobuf:"bytes,1,opt,name=instance_id,json=instanceId,proto3" json:"instance_id,omitempty"` + // Template name (e.g. "s3", "s3-duckdb", "iceberg-duckdb") + TemplateName string `protobuf:"bytes,2,opt,name=template_name,json=templateName,proto3" json:"template_name,omitempty"` + // Output filter: "connector", "model", or empty for all files + Output string `protobuf:"bytes,3,opt,name=output,proto3" json:"output,omitempty"` + Properties *structpb.Struct `protobuf:"bytes,4,opt,name=properties,proto3" json:"properties,omitempty"` + // Connector name reference (for model outputs that reference a connector) + ConnectorName string `protobuf:"bytes,5,opt,name=connector_name,json=connectorName,proto3" json:"connector_name,omitempty"` + // If true, render without writing files (for YAML preview) + Preview bool `protobuf:"varint,6,opt,name=preview,proto3" json:"preview,omitempty"` +} + +func (x *GenerateFileRequest) Reset() { + *x = GenerateFileRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_rill_runtime_v1_api_proto_msgTypes[53] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GenerateFileRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GenerateFileRequest) ProtoMessage() {} + +func (x *GenerateFileRequest) ProtoReflect() protoreflect.Message { + mi := &file_rill_runtime_v1_api_proto_msgTypes[53] + 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 GenerateFileRequest.ProtoReflect.Descriptor instead. +func (*GenerateFileRequest) Descriptor() ([]byte, []int) { + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{53} +} + +func (x *GenerateFileRequest) GetInstanceId() string { + if x != nil { + return x.InstanceId + } + return "" +} + +func (x *GenerateFileRequest) GetTemplateName() string { + if x != nil { + return x.TemplateName + } + return "" +} + +func (x *GenerateFileRequest) GetOutput() string { + if x != nil { + return x.Output + } + return "" +} + +func (x *GenerateFileRequest) GetProperties() *structpb.Struct { + if x != nil { + return x.Properties + } + return nil +} + +func (x *GenerateFileRequest) GetConnectorName() string { + if x != nil { + return x.ConnectorName + } + return "" +} + +func (x *GenerateFileRequest) GetPreview() bool { + if x != nil { + return x.Preview + } + return false +} + +type GenerateFileResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Files []*GeneratedFile `protobuf:"bytes,1,rep,name=files,proto3" json:"files,omitempty"` + EnvVars map[string]string `protobuf:"bytes,2,rep,name=env_vars,json=envVars,proto3" json:"env_vars,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` +} + +func (x *GenerateFileResponse) Reset() { + *x = GenerateFileResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_rill_runtime_v1_api_proto_msgTypes[54] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GenerateFileResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GenerateFileResponse) ProtoMessage() {} + +func (x *GenerateFileResponse) ProtoReflect() protoreflect.Message { + mi := &file_rill_runtime_v1_api_proto_msgTypes[54] + 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 GenerateFileResponse.ProtoReflect.Descriptor instead. +func (*GenerateFileResponse) Descriptor() ([]byte, []int) { + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{54} +} + +func (x *GenerateFileResponse) GetFiles() []*GeneratedFile { + if x != nil { + return x.Files + } + return nil +} + +func (x *GenerateFileResponse) GetEnvVars() map[string]string { + if x != nil { + return x.EnvVars + } + return nil +} + +// GeneratedFile is a single rendered output file. +type GeneratedFile struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` + Blob string `protobuf:"bytes,2,opt,name=blob,proto3" json:"blob,omitempty"` +} + +func (x *GeneratedFile) Reset() { + *x = GeneratedFile{} + if protoimpl.UnsafeEnabled { + mi := &file_rill_runtime_v1_api_proto_msgTypes[55] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GeneratedFile) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GeneratedFile) ProtoMessage() {} + +func (x *GeneratedFile) ProtoReflect() protoreflect.Message { + mi := &file_rill_runtime_v1_api_proto_msgTypes[55] + 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 GeneratedFile.ProtoReflect.Descriptor instead. +func (*GeneratedFile) Descriptor() ([]byte, []int) { + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{55} +} + +func (x *GeneratedFile) GetPath() string { + if x != nil { + return x.Path + } + return "" +} + +func (x *GeneratedFile) GetBlob() string { + if x != nil { + return x.Blob + } + return "" +} + type QueryResolverRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -3124,7 +3762,7 @@ type QueryResolverRequest struct { func (x *QueryResolverRequest) Reset() { *x = QueryResolverRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[47] + mi := &file_rill_runtime_v1_api_proto_msgTypes[56] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3137,7 +3775,7 @@ func (x *QueryResolverRequest) String() string { func (*QueryResolverRequest) ProtoMessage() {} func (x *QueryResolverRequest) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[47] + mi := &file_rill_runtime_v1_api_proto_msgTypes[56] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3150,7 +3788,7 @@ func (x *QueryResolverRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryResolverRequest.ProtoReflect.Descriptor instead. func (*QueryResolverRequest) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{47} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{56} } func (x *QueryResolverRequest) GetInstanceId() string { @@ -3201,7 +3839,7 @@ type QueryResolverResponse struct { func (x *QueryResolverResponse) Reset() { *x = QueryResolverResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[48] + mi := &file_rill_runtime_v1_api_proto_msgTypes[57] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3214,7 +3852,7 @@ func (x *QueryResolverResponse) String() string { func (*QueryResolverResponse) ProtoMessage() {} func (x *QueryResolverResponse) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[48] + mi := &file_rill_runtime_v1_api_proto_msgTypes[57] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3227,7 +3865,7 @@ func (x *QueryResolverResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryResolverResponse.ProtoReflect.Descriptor instead. func (*QueryResolverResponse) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{48} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{57} } func (x *QueryResolverResponse) GetMeta() *structpb.Struct { @@ -3265,7 +3903,7 @@ type Log struct { func (x *Log) Reset() { *x = Log{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[49] + mi := &file_rill_runtime_v1_api_proto_msgTypes[58] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3278,7 +3916,7 @@ func (x *Log) String() string { func (*Log) ProtoMessage() {} func (x *Log) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[49] + mi := &file_rill_runtime_v1_api_proto_msgTypes[58] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3291,7 +3929,7 @@ func (x *Log) ProtoReflect() protoreflect.Message { // Deprecated: Use Log.ProtoReflect.Descriptor instead. func (*Log) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{49} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{58} } func (x *Log) GetLevel() LogLevel { @@ -3338,7 +3976,7 @@ type ModelPartition struct { func (x *ModelPartition) Reset() { *x = ModelPartition{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[50] + mi := &file_rill_runtime_v1_api_proto_msgTypes[59] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3351,7 +3989,7 @@ func (x *ModelPartition) String() string { func (*ModelPartition) ProtoMessage() {} func (x *ModelPartition) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[50] + mi := &file_rill_runtime_v1_api_proto_msgTypes[59] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3364,7 +4002,7 @@ func (x *ModelPartition) ProtoReflect() protoreflect.Message { // Deprecated: Use ModelPartition.ProtoReflect.Descriptor instead. func (*ModelPartition) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{50} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{59} } func (x *ModelPartition) GetKey() string { @@ -3423,7 +4061,7 @@ type GetLogsRequest struct { func (x *GetLogsRequest) Reset() { *x = GetLogsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[51] + mi := &file_rill_runtime_v1_api_proto_msgTypes[60] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3436,7 +4074,7 @@ func (x *GetLogsRequest) String() string { func (*GetLogsRequest) ProtoMessage() {} func (x *GetLogsRequest) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[51] + mi := &file_rill_runtime_v1_api_proto_msgTypes[60] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3449,7 +4087,7 @@ func (x *GetLogsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetLogsRequest.ProtoReflect.Descriptor instead. func (*GetLogsRequest) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{51} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{60} } func (x *GetLogsRequest) GetInstanceId() string { @@ -3491,7 +4129,7 @@ type GetLogsResponse struct { func (x *GetLogsResponse) Reset() { *x = GetLogsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[52] + mi := &file_rill_runtime_v1_api_proto_msgTypes[61] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3504,7 +4142,7 @@ func (x *GetLogsResponse) String() string { func (*GetLogsResponse) ProtoMessage() {} func (x *GetLogsResponse) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[52] + mi := &file_rill_runtime_v1_api_proto_msgTypes[61] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3517,7 +4155,7 @@ func (x *GetLogsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetLogsResponse.ProtoReflect.Descriptor instead. func (*GetLogsResponse) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{52} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{61} } func (x *GetLogsResponse) GetLogs() []*Log { @@ -3541,7 +4179,7 @@ type WatchLogsRequest struct { func (x *WatchLogsRequest) Reset() { *x = WatchLogsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[53] + mi := &file_rill_runtime_v1_api_proto_msgTypes[62] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3554,7 +4192,7 @@ func (x *WatchLogsRequest) String() string { func (*WatchLogsRequest) ProtoMessage() {} func (x *WatchLogsRequest) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[53] + mi := &file_rill_runtime_v1_api_proto_msgTypes[62] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3567,7 +4205,7 @@ func (x *WatchLogsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use WatchLogsRequest.ProtoReflect.Descriptor instead. func (*WatchLogsRequest) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{53} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{62} } func (x *WatchLogsRequest) GetInstanceId() string { @@ -3609,7 +4247,7 @@ type WatchLogsResponse struct { func (x *WatchLogsResponse) Reset() { *x = WatchLogsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[54] + mi := &file_rill_runtime_v1_api_proto_msgTypes[63] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3622,7 +4260,7 @@ func (x *WatchLogsResponse) String() string { func (*WatchLogsResponse) ProtoMessage() {} func (x *WatchLogsResponse) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[54] + mi := &file_rill_runtime_v1_api_proto_msgTypes[63] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3635,7 +4273,7 @@ func (x *WatchLogsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use WatchLogsResponse.ProtoReflect.Descriptor instead. func (*WatchLogsResponse) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{54} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{63} } func (x *WatchLogsResponse) GetLog() *Log { @@ -3663,7 +4301,7 @@ type ListResourcesRequest struct { func (x *ListResourcesRequest) Reset() { *x = ListResourcesRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[55] + mi := &file_rill_runtime_v1_api_proto_msgTypes[64] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3676,7 +4314,7 @@ func (x *ListResourcesRequest) String() string { func (*ListResourcesRequest) ProtoMessage() {} func (x *ListResourcesRequest) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[55] + mi := &file_rill_runtime_v1_api_proto_msgTypes[64] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3689,7 +4327,7 @@ func (x *ListResourcesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListResourcesRequest.ProtoReflect.Descriptor instead. func (*ListResourcesRequest) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{55} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{64} } func (x *ListResourcesRequest) GetInstanceId() string { @@ -3731,7 +4369,7 @@ type ListResourcesResponse struct { func (x *ListResourcesResponse) Reset() { *x = ListResourcesResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[56] + mi := &file_rill_runtime_v1_api_proto_msgTypes[65] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3744,7 +4382,7 @@ func (x *ListResourcesResponse) String() string { func (*ListResourcesResponse) ProtoMessage() {} func (x *ListResourcesResponse) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[56] + mi := &file_rill_runtime_v1_api_proto_msgTypes[65] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3757,7 +4395,7 @@ func (x *ListResourcesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListResourcesResponse.ProtoReflect.Descriptor instead. func (*ListResourcesResponse) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{56} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{65} } func (x *ListResourcesResponse) GetResources() []*Resource { @@ -3780,7 +4418,7 @@ type WatchResourcesRequest struct { func (x *WatchResourcesRequest) Reset() { *x = WatchResourcesRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[57] + mi := &file_rill_runtime_v1_api_proto_msgTypes[66] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3793,7 +4431,7 @@ func (x *WatchResourcesRequest) String() string { func (*WatchResourcesRequest) ProtoMessage() {} func (x *WatchResourcesRequest) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[57] + mi := &file_rill_runtime_v1_api_proto_msgTypes[66] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3806,7 +4444,7 @@ func (x *WatchResourcesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use WatchResourcesRequest.ProtoReflect.Descriptor instead. func (*WatchResourcesRequest) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{57} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{66} } func (x *WatchResourcesRequest) GetInstanceId() string { @@ -3843,7 +4481,7 @@ type WatchResourcesResponse struct { func (x *WatchResourcesResponse) Reset() { *x = WatchResourcesResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[58] + mi := &file_rill_runtime_v1_api_proto_msgTypes[67] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3856,7 +4494,7 @@ func (x *WatchResourcesResponse) String() string { func (*WatchResourcesResponse) ProtoMessage() {} func (x *WatchResourcesResponse) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[58] + mi := &file_rill_runtime_v1_api_proto_msgTypes[67] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3869,7 +4507,7 @@ func (x *WatchResourcesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use WatchResourcesResponse.ProtoReflect.Descriptor instead. func (*WatchResourcesResponse) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{58} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{67} } func (x *WatchResourcesResponse) GetEvent() ResourceEvent { @@ -3906,7 +4544,7 @@ type GetResourceRequest struct { func (x *GetResourceRequest) Reset() { *x = GetResourceRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[59] + mi := &file_rill_runtime_v1_api_proto_msgTypes[68] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3919,7 +4557,7 @@ func (x *GetResourceRequest) String() string { func (*GetResourceRequest) ProtoMessage() {} func (x *GetResourceRequest) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[59] + mi := &file_rill_runtime_v1_api_proto_msgTypes[68] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3932,7 +4570,7 @@ func (x *GetResourceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetResourceRequest.ProtoReflect.Descriptor instead. func (*GetResourceRequest) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{59} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{68} } func (x *GetResourceRequest) GetInstanceId() string { @@ -3967,7 +4605,7 @@ type GetResourceResponse struct { func (x *GetResourceResponse) Reset() { *x = GetResourceResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[60] + mi := &file_rill_runtime_v1_api_proto_msgTypes[69] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3980,7 +4618,7 @@ func (x *GetResourceResponse) String() string { func (*GetResourceResponse) ProtoMessage() {} func (x *GetResourceResponse) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[60] + mi := &file_rill_runtime_v1_api_proto_msgTypes[69] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3993,7 +4631,7 @@ func (x *GetResourceResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetResourceResponse.ProtoReflect.Descriptor instead. func (*GetResourceResponse) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{60} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{69} } func (x *GetResourceResponse) GetResource() *Resource { @@ -4015,7 +4653,7 @@ type GetExploreRequest struct { func (x *GetExploreRequest) Reset() { *x = GetExploreRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[61] + mi := &file_rill_runtime_v1_api_proto_msgTypes[70] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4028,7 +4666,7 @@ func (x *GetExploreRequest) String() string { func (*GetExploreRequest) ProtoMessage() {} func (x *GetExploreRequest) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[61] + mi := &file_rill_runtime_v1_api_proto_msgTypes[70] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4041,7 +4679,7 @@ func (x *GetExploreRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetExploreRequest.ProtoReflect.Descriptor instead. func (*GetExploreRequest) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{61} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{70} } func (x *GetExploreRequest) GetInstanceId() string { @@ -4070,7 +4708,7 @@ type GetExploreResponse struct { func (x *GetExploreResponse) Reset() { *x = GetExploreResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[62] + mi := &file_rill_runtime_v1_api_proto_msgTypes[71] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4083,7 +4721,7 @@ func (x *GetExploreResponse) String() string { func (*GetExploreResponse) ProtoMessage() {} func (x *GetExploreResponse) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[62] + mi := &file_rill_runtime_v1_api_proto_msgTypes[71] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4096,7 +4734,7 @@ func (x *GetExploreResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetExploreResponse.ProtoReflect.Descriptor instead. func (*GetExploreResponse) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{62} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{71} } func (x *GetExploreResponse) GetExplore() *Resource { @@ -4129,7 +4767,7 @@ type GetModelPartitionsRequest struct { func (x *GetModelPartitionsRequest) Reset() { *x = GetModelPartitionsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[63] + mi := &file_rill_runtime_v1_api_proto_msgTypes[72] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4142,7 +4780,7 @@ func (x *GetModelPartitionsRequest) String() string { func (*GetModelPartitionsRequest) ProtoMessage() {} func (x *GetModelPartitionsRequest) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[63] + mi := &file_rill_runtime_v1_api_proto_msgTypes[72] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4155,7 +4793,7 @@ func (x *GetModelPartitionsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetModelPartitionsRequest.ProtoReflect.Descriptor instead. func (*GetModelPartitionsRequest) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{63} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{72} } func (x *GetModelPartitionsRequest) GetInstanceId() string { @@ -4212,7 +4850,7 @@ type GetModelPartitionsResponse struct { func (x *GetModelPartitionsResponse) Reset() { *x = GetModelPartitionsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[64] + mi := &file_rill_runtime_v1_api_proto_msgTypes[73] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4225,7 +4863,7 @@ func (x *GetModelPartitionsResponse) String() string { func (*GetModelPartitionsResponse) ProtoMessage() {} func (x *GetModelPartitionsResponse) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[64] + mi := &file_rill_runtime_v1_api_proto_msgTypes[73] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4238,7 +4876,7 @@ func (x *GetModelPartitionsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetModelPartitionsResponse.ProtoReflect.Descriptor instead. func (*GetModelPartitionsResponse) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{64} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{73} } func (x *GetModelPartitionsResponse) GetPartitions() []*ModelPartition { @@ -4281,7 +4919,7 @@ type CreateTriggerRequest struct { func (x *CreateTriggerRequest) Reset() { *x = CreateTriggerRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[65] + mi := &file_rill_runtime_v1_api_proto_msgTypes[74] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4294,7 +4932,7 @@ func (x *CreateTriggerRequest) String() string { func (*CreateTriggerRequest) ProtoMessage() {} func (x *CreateTriggerRequest) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[65] + mi := &file_rill_runtime_v1_api_proto_msgTypes[74] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4307,7 +4945,7 @@ func (x *CreateTriggerRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateTriggerRequest.ProtoReflect.Descriptor instead. func (*CreateTriggerRequest) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{65} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{74} } func (x *CreateTriggerRequest) GetInstanceId() string { @@ -4361,7 +4999,7 @@ type CreateTriggerResponse struct { func (x *CreateTriggerResponse) Reset() { *x = CreateTriggerResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[66] + mi := &file_rill_runtime_v1_api_proto_msgTypes[75] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4374,7 +5012,7 @@ func (x *CreateTriggerResponse) String() string { func (*CreateTriggerResponse) ProtoMessage() {} func (x *CreateTriggerResponse) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[66] + mi := &file_rill_runtime_v1_api_proto_msgTypes[75] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4387,7 +5025,7 @@ func (x *CreateTriggerResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateTriggerResponse.ProtoReflect.Descriptor instead. func (*CreateTriggerResponse) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{66} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{75} } // ConnectorDriver represents a connector driver available in the runtime. @@ -4425,7 +5063,7 @@ type ConnectorDriver struct { func (x *ConnectorDriver) Reset() { *x = ConnectorDriver{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[67] + mi := &file_rill_runtime_v1_api_proto_msgTypes[76] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4438,7 +5076,7 @@ func (x *ConnectorDriver) String() string { func (*ConnectorDriver) ProtoMessage() {} func (x *ConnectorDriver) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[67] + mi := &file_rill_runtime_v1_api_proto_msgTypes[76] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4451,7 +5089,7 @@ func (x *ConnectorDriver) ProtoReflect() protoreflect.Message { // Deprecated: Use ConnectorDriver.ProtoReflect.Descriptor instead. func (*ConnectorDriver) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{67} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{76} } func (x *ConnectorDriver) GetName() string { @@ -4606,7 +5244,7 @@ type AnalyzedConnector struct { func (x *AnalyzedConnector) Reset() { *x = AnalyzedConnector{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[68] + mi := &file_rill_runtime_v1_api_proto_msgTypes[77] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4619,7 +5257,7 @@ func (x *AnalyzedConnector) String() string { func (*AnalyzedConnector) ProtoMessage() {} func (x *AnalyzedConnector) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[68] + mi := &file_rill_runtime_v1_api_proto_msgTypes[77] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4632,7 +5270,7 @@ func (x *AnalyzedConnector) ProtoReflect() protoreflect.Message { // Deprecated: Use AnalyzedConnector.ProtoReflect.Descriptor instead. func (*AnalyzedConnector) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{68} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{77} } func (x *AnalyzedConnector) GetName() string { @@ -4722,7 +5360,7 @@ type ListConnectorDriversRequest struct { func (x *ListConnectorDriversRequest) Reset() { *x = ListConnectorDriversRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[69] + mi := &file_rill_runtime_v1_api_proto_msgTypes[78] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4735,7 +5373,7 @@ func (x *ListConnectorDriversRequest) String() string { func (*ListConnectorDriversRequest) ProtoMessage() {} func (x *ListConnectorDriversRequest) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[69] + mi := &file_rill_runtime_v1_api_proto_msgTypes[78] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4748,7 +5386,7 @@ func (x *ListConnectorDriversRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListConnectorDriversRequest.ProtoReflect.Descriptor instead. func (*ListConnectorDriversRequest) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{69} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{78} } // Response message for RuntimeService.ListConnectorDrivers @@ -4763,7 +5401,7 @@ type ListConnectorDriversResponse struct { func (x *ListConnectorDriversResponse) Reset() { *x = ListConnectorDriversResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[70] + mi := &file_rill_runtime_v1_api_proto_msgTypes[79] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4776,7 +5414,7 @@ func (x *ListConnectorDriversResponse) String() string { func (*ListConnectorDriversResponse) ProtoMessage() {} func (x *ListConnectorDriversResponse) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[70] + mi := &file_rill_runtime_v1_api_proto_msgTypes[79] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4789,7 +5427,7 @@ func (x *ListConnectorDriversResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListConnectorDriversResponse.ProtoReflect.Descriptor instead. func (*ListConnectorDriversResponse) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{70} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{79} } func (x *ListConnectorDriversResponse) GetConnectors() []*ConnectorDriver { @@ -4811,7 +5449,7 @@ type AnalyzeConnectorsRequest struct { func (x *AnalyzeConnectorsRequest) Reset() { *x = AnalyzeConnectorsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[71] + mi := &file_rill_runtime_v1_api_proto_msgTypes[80] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4824,7 +5462,7 @@ func (x *AnalyzeConnectorsRequest) String() string { func (*AnalyzeConnectorsRequest) ProtoMessage() {} func (x *AnalyzeConnectorsRequest) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[71] + mi := &file_rill_runtime_v1_api_proto_msgTypes[80] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4837,7 +5475,7 @@ func (x *AnalyzeConnectorsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use AnalyzeConnectorsRequest.ProtoReflect.Descriptor instead. func (*AnalyzeConnectorsRequest) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{71} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{80} } func (x *AnalyzeConnectorsRequest) GetInstanceId() string { @@ -4859,7 +5497,7 @@ type AnalyzeConnectorsResponse struct { func (x *AnalyzeConnectorsResponse) Reset() { *x = AnalyzeConnectorsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[72] + mi := &file_rill_runtime_v1_api_proto_msgTypes[81] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4872,7 +5510,7 @@ func (x *AnalyzeConnectorsResponse) String() string { func (*AnalyzeConnectorsResponse) ProtoMessage() {} func (x *AnalyzeConnectorsResponse) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[72] + mi := &file_rill_runtime_v1_api_proto_msgTypes[81] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4885,7 +5523,7 @@ func (x *AnalyzeConnectorsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use AnalyzeConnectorsResponse.ProtoReflect.Descriptor instead. func (*AnalyzeConnectorsResponse) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{72} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{81} } func (x *AnalyzeConnectorsResponse) GetConnectors() []*AnalyzedConnector { @@ -4907,7 +5545,7 @@ type ListNotifierConnectorsRequest struct { func (x *ListNotifierConnectorsRequest) Reset() { *x = ListNotifierConnectorsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[73] + mi := &file_rill_runtime_v1_api_proto_msgTypes[82] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4920,7 +5558,7 @@ func (x *ListNotifierConnectorsRequest) String() string { func (*ListNotifierConnectorsRequest) ProtoMessage() {} func (x *ListNotifierConnectorsRequest) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[73] + mi := &file_rill_runtime_v1_api_proto_msgTypes[82] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4933,7 +5571,7 @@ func (x *ListNotifierConnectorsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListNotifierConnectorsRequest.ProtoReflect.Descriptor instead. func (*ListNotifierConnectorsRequest) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{73} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{82} } func (x *ListNotifierConnectorsRequest) GetInstanceId() string { @@ -4956,7 +5594,7 @@ type ListNotifierConnectorsResponse struct { func (x *ListNotifierConnectorsResponse) Reset() { *x = ListNotifierConnectorsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[74] + mi := &file_rill_runtime_v1_api_proto_msgTypes[83] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4969,7 +5607,7 @@ func (x *ListNotifierConnectorsResponse) String() string { func (*ListNotifierConnectorsResponse) ProtoMessage() {} func (x *ListNotifierConnectorsResponse) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[74] + mi := &file_rill_runtime_v1_api_proto_msgTypes[83] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4982,7 +5620,7 @@ func (x *ListNotifierConnectorsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListNotifierConnectorsResponse.ProtoReflect.Descriptor instead. func (*ListNotifierConnectorsResponse) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{74} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{83} } func (x *ListNotifierConnectorsResponse) GetConnectors() []*Connector { @@ -5010,7 +5648,7 @@ type Conversation struct { func (x *Conversation) Reset() { *x = Conversation{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[75] + mi := &file_rill_runtime_v1_api_proto_msgTypes[84] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5023,7 +5661,7 @@ func (x *Conversation) String() string { func (*Conversation) ProtoMessage() {} func (x *Conversation) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[75] + mi := &file_rill_runtime_v1_api_proto_msgTypes[84] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5036,7 +5674,7 @@ func (x *Conversation) ProtoReflect() protoreflect.Message { // Deprecated: Use Conversation.ProtoReflect.Descriptor instead. func (*Conversation) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{75} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{84} } func (x *Conversation) GetId() string { @@ -5110,7 +5748,7 @@ type Message struct { func (x *Message) Reset() { *x = Message{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[76] + mi := &file_rill_runtime_v1_api_proto_msgTypes[85] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5123,7 +5761,7 @@ func (x *Message) String() string { func (*Message) ProtoMessage() {} func (x *Message) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[76] + mi := &file_rill_runtime_v1_api_proto_msgTypes[85] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5136,7 +5774,7 @@ func (x *Message) ProtoReflect() protoreflect.Message { // Deprecated: Use Message.ProtoReflect.Descriptor instead. func (*Message) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{76} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{85} } func (x *Message) GetId() string { @@ -5247,7 +5885,7 @@ type AnalystAgentContext struct { func (x *AnalystAgentContext) Reset() { *x = AnalystAgentContext{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[77] + mi := &file_rill_runtime_v1_api_proto_msgTypes[86] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5260,7 +5898,7 @@ func (x *AnalystAgentContext) String() string { func (*AnalystAgentContext) ProtoMessage() {} func (x *AnalystAgentContext) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[77] + mi := &file_rill_runtime_v1_api_proto_msgTypes[86] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5273,7 +5911,7 @@ func (x *AnalystAgentContext) ProtoReflect() protoreflect.Message { // Deprecated: Use AnalystAgentContext.ProtoReflect.Descriptor instead. func (*AnalystAgentContext) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{77} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{86} } func (x *AnalystAgentContext) GetExplore() string { @@ -5356,7 +5994,7 @@ type DeveloperAgentContext struct { func (x *DeveloperAgentContext) Reset() { *x = DeveloperAgentContext{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[78] + mi := &file_rill_runtime_v1_api_proto_msgTypes[87] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5369,7 +6007,7 @@ func (x *DeveloperAgentContext) String() string { func (*DeveloperAgentContext) ProtoMessage() {} func (x *DeveloperAgentContext) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[78] + mi := &file_rill_runtime_v1_api_proto_msgTypes[87] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5382,7 +6020,7 @@ func (x *DeveloperAgentContext) ProtoReflect() protoreflect.Message { // Deprecated: Use DeveloperAgentContext.ProtoReflect.Descriptor instead. func (*DeveloperAgentContext) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{78} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{87} } func (x *DeveloperAgentContext) GetInitProject() bool { @@ -5419,7 +6057,7 @@ type FeedbackAgentContext struct { func (x *FeedbackAgentContext) Reset() { *x = FeedbackAgentContext{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[79] + mi := &file_rill_runtime_v1_api_proto_msgTypes[88] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5432,7 +6070,7 @@ func (x *FeedbackAgentContext) String() string { func (*FeedbackAgentContext) ProtoMessage() {} func (x *FeedbackAgentContext) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[79] + mi := &file_rill_runtime_v1_api_proto_msgTypes[88] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5445,7 +6083,7 @@ func (x *FeedbackAgentContext) ProtoReflect() protoreflect.Message { // Deprecated: Use FeedbackAgentContext.ProtoReflect.Descriptor instead. func (*FeedbackAgentContext) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{79} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{88} } func (x *FeedbackAgentContext) GetTargetMessageId() string { @@ -5490,7 +6128,7 @@ type ListConversationsRequest struct { func (x *ListConversationsRequest) Reset() { *x = ListConversationsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[80] + mi := &file_rill_runtime_v1_api_proto_msgTypes[89] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5503,7 +6141,7 @@ func (x *ListConversationsRequest) String() string { func (*ListConversationsRequest) ProtoMessage() {} func (x *ListConversationsRequest) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[80] + mi := &file_rill_runtime_v1_api_proto_msgTypes[89] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5516,7 +6154,7 @@ func (x *ListConversationsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListConversationsRequest.ProtoReflect.Descriptor instead. func (*ListConversationsRequest) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{80} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{89} } func (x *ListConversationsRequest) GetInstanceId() string { @@ -5545,7 +6183,7 @@ type ListConversationsResponse struct { func (x *ListConversationsResponse) Reset() { *x = ListConversationsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[81] + mi := &file_rill_runtime_v1_api_proto_msgTypes[90] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5558,7 +6196,7 @@ func (x *ListConversationsResponse) String() string { func (*ListConversationsResponse) ProtoMessage() {} func (x *ListConversationsResponse) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[81] + mi := &file_rill_runtime_v1_api_proto_msgTypes[90] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5571,7 +6209,7 @@ func (x *ListConversationsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListConversationsResponse.ProtoReflect.Descriptor instead. func (*ListConversationsResponse) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{81} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{90} } func (x *ListConversationsResponse) GetConversations() []*Conversation { @@ -5594,7 +6232,7 @@ type GetConversationRequest struct { func (x *GetConversationRequest) Reset() { *x = GetConversationRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[82] + mi := &file_rill_runtime_v1_api_proto_msgTypes[91] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5607,7 +6245,7 @@ func (x *GetConversationRequest) String() string { func (*GetConversationRequest) ProtoMessage() {} func (x *GetConversationRequest) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[82] + mi := &file_rill_runtime_v1_api_proto_msgTypes[91] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5620,7 +6258,7 @@ func (x *GetConversationRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetConversationRequest.ProtoReflect.Descriptor instead. func (*GetConversationRequest) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{82} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{91} } func (x *GetConversationRequest) GetInstanceId() string { @@ -5651,7 +6289,7 @@ type GetConversationResponse struct { func (x *GetConversationResponse) Reset() { *x = GetConversationResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[83] + mi := &file_rill_runtime_v1_api_proto_msgTypes[92] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5664,7 +6302,7 @@ func (x *GetConversationResponse) String() string { func (*GetConversationResponse) ProtoMessage() {} func (x *GetConversationResponse) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[83] + mi := &file_rill_runtime_v1_api_proto_msgTypes[92] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5677,7 +6315,7 @@ func (x *GetConversationResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetConversationResponse.ProtoReflect.Descriptor instead. func (*GetConversationResponse) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{83} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{92} } func (x *GetConversationResponse) GetConversation() *Conversation { @@ -5718,7 +6356,7 @@ type ShareConversationRequest struct { func (x *ShareConversationRequest) Reset() { *x = ShareConversationRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[84] + mi := &file_rill_runtime_v1_api_proto_msgTypes[93] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5731,7 +6369,7 @@ func (x *ShareConversationRequest) String() string { func (*ShareConversationRequest) ProtoMessage() {} func (x *ShareConversationRequest) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[84] + mi := &file_rill_runtime_v1_api_proto_msgTypes[93] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5744,7 +6382,7 @@ func (x *ShareConversationRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ShareConversationRequest.ProtoReflect.Descriptor instead. func (*ShareConversationRequest) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{84} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{93} } func (x *ShareConversationRequest) GetInstanceId() string { @@ -5778,7 +6416,7 @@ type ShareConversationResponse struct { func (x *ShareConversationResponse) Reset() { *x = ShareConversationResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[85] + mi := &file_rill_runtime_v1_api_proto_msgTypes[94] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5791,7 +6429,7 @@ func (x *ShareConversationResponse) String() string { func (*ShareConversationResponse) ProtoMessage() {} func (x *ShareConversationResponse) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[85] + mi := &file_rill_runtime_v1_api_proto_msgTypes[94] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5804,7 +6442,7 @@ func (x *ShareConversationResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ShareConversationResponse.ProtoReflect.Descriptor instead. func (*ShareConversationResponse) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{85} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{94} } // Request message for RuntimeService.ForkConversation @@ -5820,7 +6458,7 @@ type ForkConversationRequest struct { func (x *ForkConversationRequest) Reset() { *x = ForkConversationRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[86] + mi := &file_rill_runtime_v1_api_proto_msgTypes[95] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5833,7 +6471,7 @@ func (x *ForkConversationRequest) String() string { func (*ForkConversationRequest) ProtoMessage() {} func (x *ForkConversationRequest) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[86] + mi := &file_rill_runtime_v1_api_proto_msgTypes[95] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5846,7 +6484,7 @@ func (x *ForkConversationRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ForkConversationRequest.ProtoReflect.Descriptor instead. func (*ForkConversationRequest) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{86} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{95} } func (x *ForkConversationRequest) GetInstanceId() string { @@ -5875,7 +6513,7 @@ type ForkConversationResponse struct { func (x *ForkConversationResponse) Reset() { *x = ForkConversationResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[87] + mi := &file_rill_runtime_v1_api_proto_msgTypes[96] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5888,7 +6526,7 @@ func (x *ForkConversationResponse) String() string { func (*ForkConversationResponse) ProtoMessage() {} func (x *ForkConversationResponse) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[87] + mi := &file_rill_runtime_v1_api_proto_msgTypes[96] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5901,7 +6539,7 @@ func (x *ForkConversationResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ForkConversationResponse.ProtoReflect.Descriptor instead. func (*ForkConversationResponse) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{87} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{96} } func (x *ForkConversationResponse) GetConversationId() string { @@ -5923,7 +6561,7 @@ type ListToolsRequest struct { func (x *ListToolsRequest) Reset() { *x = ListToolsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[88] + mi := &file_rill_runtime_v1_api_proto_msgTypes[97] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5936,7 +6574,7 @@ func (x *ListToolsRequest) String() string { func (*ListToolsRequest) ProtoMessage() {} func (x *ListToolsRequest) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[88] + mi := &file_rill_runtime_v1_api_proto_msgTypes[97] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5949,7 +6587,7 @@ func (x *ListToolsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListToolsRequest.ProtoReflect.Descriptor instead. func (*ListToolsRequest) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{88} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{97} } func (x *ListToolsRequest) GetInstanceId() string { @@ -5971,7 +6609,7 @@ type ListToolsResponse struct { func (x *ListToolsResponse) Reset() { *x = ListToolsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[89] + mi := &file_rill_runtime_v1_api_proto_msgTypes[98] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5984,7 +6622,7 @@ func (x *ListToolsResponse) String() string { func (*ListToolsResponse) ProtoMessage() {} func (x *ListToolsResponse) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[89] + mi := &file_rill_runtime_v1_api_proto_msgTypes[98] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5997,7 +6635,7 @@ func (x *ListToolsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListToolsResponse.ProtoReflect.Descriptor instead. func (*ListToolsResponse) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{89} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{98} } func (x *ListToolsResponse) GetTools() []*v1.Tool { @@ -6036,7 +6674,7 @@ type CompleteRequest struct { func (x *CompleteRequest) Reset() { *x = CompleteRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[90] + mi := &file_rill_runtime_v1_api_proto_msgTypes[99] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6049,7 +6687,7 @@ func (x *CompleteRequest) String() string { func (*CompleteRequest) ProtoMessage() {} func (x *CompleteRequest) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[90] + mi := &file_rill_runtime_v1_api_proto_msgTypes[99] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6062,7 +6700,7 @@ func (x *CompleteRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CompleteRequest.ProtoReflect.Descriptor instead. func (*CompleteRequest) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{90} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{99} } func (x *CompleteRequest) GetInstanceId() string { @@ -6127,7 +6765,7 @@ type CompleteResponse struct { func (x *CompleteResponse) Reset() { *x = CompleteResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[91] + mi := &file_rill_runtime_v1_api_proto_msgTypes[100] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6140,7 +6778,7 @@ func (x *CompleteResponse) String() string { func (*CompleteResponse) ProtoMessage() {} func (x *CompleteResponse) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[91] + mi := &file_rill_runtime_v1_api_proto_msgTypes[100] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6153,7 +6791,7 @@ func (x *CompleteResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CompleteResponse.ProtoReflect.Descriptor instead. func (*CompleteResponse) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{91} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{100} } func (x *CompleteResponse) GetConversationId() string { @@ -6199,7 +6837,7 @@ type CompleteStreamingRequest struct { func (x *CompleteStreamingRequest) Reset() { *x = CompleteStreamingRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[92] + mi := &file_rill_runtime_v1_api_proto_msgTypes[101] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6212,7 +6850,7 @@ func (x *CompleteStreamingRequest) String() string { func (*CompleteStreamingRequest) ProtoMessage() {} func (x *CompleteStreamingRequest) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[92] + mi := &file_rill_runtime_v1_api_proto_msgTypes[101] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6225,7 +6863,7 @@ func (x *CompleteStreamingRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CompleteStreamingRequest.ProtoReflect.Descriptor instead. func (*CompleteStreamingRequest) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{92} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{101} } func (x *CompleteStreamingRequest) GetInstanceId() string { @@ -6290,7 +6928,7 @@ type CompleteStreamingResponse struct { func (x *CompleteStreamingResponse) Reset() { *x = CompleteStreamingResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[93] + mi := &file_rill_runtime_v1_api_proto_msgTypes[102] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6303,7 +6941,7 @@ func (x *CompleteStreamingResponse) String() string { func (*CompleteStreamingResponse) ProtoMessage() {} func (x *CompleteStreamingResponse) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[93] + mi := &file_rill_runtime_v1_api_proto_msgTypes[102] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6316,7 +6954,7 @@ func (x *CompleteStreamingResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CompleteStreamingResponse.ProtoReflect.Descriptor instead. func (*CompleteStreamingResponse) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{93} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{102} } func (x *CompleteStreamingResponse) GetConversationId() string { @@ -6347,7 +6985,7 @@ type GetAIMessageRequest struct { func (x *GetAIMessageRequest) Reset() { *x = GetAIMessageRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[94] + mi := &file_rill_runtime_v1_api_proto_msgTypes[103] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6360,7 +6998,7 @@ func (x *GetAIMessageRequest) String() string { func (*GetAIMessageRequest) ProtoMessage() {} func (x *GetAIMessageRequest) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[94] + mi := &file_rill_runtime_v1_api_proto_msgTypes[103] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6373,7 +7011,7 @@ func (x *GetAIMessageRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetAIMessageRequest.ProtoReflect.Descriptor instead. func (*GetAIMessageRequest) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{94} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{103} } func (x *GetAIMessageRequest) GetInstanceId() string { @@ -6409,7 +7047,7 @@ type GetAIMessageResponse struct { func (x *GetAIMessageResponse) Reset() { *x = GetAIMessageResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[95] + mi := &file_rill_runtime_v1_api_proto_msgTypes[104] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6422,7 +7060,7 @@ func (x *GetAIMessageResponse) String() string { func (*GetAIMessageResponse) ProtoMessage() {} func (x *GetAIMessageResponse) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[95] + mi := &file_rill_runtime_v1_api_proto_msgTypes[104] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6435,7 +7073,7 @@ func (x *GetAIMessageResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetAIMessageResponse.ProtoReflect.Descriptor instead. func (*GetAIMessageResponse) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{95} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{104} } func (x *GetAIMessageResponse) GetMessage() *Message { @@ -6463,7 +7101,7 @@ type IssueDevJWTRequest struct { func (x *IssueDevJWTRequest) Reset() { *x = IssueDevJWTRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[96] + mi := &file_rill_runtime_v1_api_proto_msgTypes[105] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6476,7 +7114,7 @@ func (x *IssueDevJWTRequest) String() string { func (*IssueDevJWTRequest) ProtoMessage() {} func (x *IssueDevJWTRequest) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[96] + mi := &file_rill_runtime_v1_api_proto_msgTypes[105] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6489,7 +7127,7 @@ func (x *IssueDevJWTRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use IssueDevJWTRequest.ProtoReflect.Descriptor instead. func (*IssueDevJWTRequest) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{96} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{105} } func (x *IssueDevJWTRequest) GetName() string { @@ -6539,7 +7177,7 @@ type IssueDevJWTResponse struct { func (x *IssueDevJWTResponse) Reset() { *x = IssueDevJWTResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[97] + mi := &file_rill_runtime_v1_api_proto_msgTypes[106] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6552,7 +7190,7 @@ func (x *IssueDevJWTResponse) String() string { func (*IssueDevJWTResponse) ProtoMessage() {} func (x *IssueDevJWTResponse) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[97] + mi := &file_rill_runtime_v1_api_proto_msgTypes[106] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6565,7 +7203,7 @@ func (x *IssueDevJWTResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use IssueDevJWTResponse.ProtoReflect.Descriptor instead. func (*IssueDevJWTResponse) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{97} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{106} } func (x *IssueDevJWTResponse) GetJwt() string { @@ -6587,7 +7225,7 @@ type AnalyzeVariablesRequest struct { func (x *AnalyzeVariablesRequest) Reset() { *x = AnalyzeVariablesRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[98] + mi := &file_rill_runtime_v1_api_proto_msgTypes[107] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6600,7 +7238,7 @@ func (x *AnalyzeVariablesRequest) String() string { func (*AnalyzeVariablesRequest) ProtoMessage() {} func (x *AnalyzeVariablesRequest) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[98] + mi := &file_rill_runtime_v1_api_proto_msgTypes[107] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6613,7 +7251,7 @@ func (x *AnalyzeVariablesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use AnalyzeVariablesRequest.ProtoReflect.Descriptor instead. func (*AnalyzeVariablesRequest) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{98} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{107} } func (x *AnalyzeVariablesRequest) GetInstanceId() string { @@ -6635,7 +7273,7 @@ type AnalyzeVariablesResponse struct { func (x *AnalyzeVariablesResponse) Reset() { *x = AnalyzeVariablesResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[99] + mi := &file_rill_runtime_v1_api_proto_msgTypes[108] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6648,7 +7286,7 @@ func (x *AnalyzeVariablesResponse) String() string { func (*AnalyzeVariablesResponse) ProtoMessage() {} func (x *AnalyzeVariablesResponse) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[99] + mi := &file_rill_runtime_v1_api_proto_msgTypes[108] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6661,7 +7299,7 @@ func (x *AnalyzeVariablesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use AnalyzeVariablesResponse.ProtoReflect.Descriptor instead. func (*AnalyzeVariablesResponse) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{99} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{108} } func (x *AnalyzeVariablesResponse) GetVariables() []*AnalyzedVariable { @@ -6687,7 +7325,7 @@ type AnalyzedVariable struct { func (x *AnalyzedVariable) Reset() { *x = AnalyzedVariable{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[100] + mi := &file_rill_runtime_v1_api_proto_msgTypes[109] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6700,7 +7338,7 @@ func (x *AnalyzedVariable) String() string { func (*AnalyzedVariable) ProtoMessage() {} func (x *AnalyzedVariable) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[100] + mi := &file_rill_runtime_v1_api_proto_msgTypes[109] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6713,7 +7351,7 @@ func (x *AnalyzedVariable) ProtoReflect() protoreflect.Message { // Deprecated: Use AnalyzedVariable.ProtoReflect.Descriptor instead. func (*AnalyzedVariable) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{100} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{109} } func (x *AnalyzedVariable) GetName() string { @@ -6750,7 +7388,7 @@ type ListGitCommitsRequest struct { func (x *ListGitCommitsRequest) Reset() { *x = ListGitCommitsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[101] + mi := &file_rill_runtime_v1_api_proto_msgTypes[110] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6763,7 +7401,7 @@ func (x *ListGitCommitsRequest) String() string { func (*ListGitCommitsRequest) ProtoMessage() {} func (x *ListGitCommitsRequest) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[101] + mi := &file_rill_runtime_v1_api_proto_msgTypes[110] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6776,7 +7414,7 @@ func (x *ListGitCommitsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListGitCommitsRequest.ProtoReflect.Descriptor instead. func (*ListGitCommitsRequest) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{101} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{110} } func (x *ListGitCommitsRequest) GetInstanceId() string { @@ -6812,7 +7450,7 @@ type ListGitCommitsResponse struct { func (x *ListGitCommitsResponse) Reset() { *x = ListGitCommitsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[102] + mi := &file_rill_runtime_v1_api_proto_msgTypes[111] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6825,7 +7463,7 @@ func (x *ListGitCommitsResponse) String() string { func (*ListGitCommitsResponse) ProtoMessage() {} func (x *ListGitCommitsResponse) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[102] + mi := &file_rill_runtime_v1_api_proto_msgTypes[111] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6838,7 +7476,7 @@ func (x *ListGitCommitsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListGitCommitsResponse.ProtoReflect.Descriptor instead. func (*ListGitCommitsResponse) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{102} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{111} } func (x *ListGitCommitsResponse) GetCommits() []*GitCommit { @@ -6870,7 +7508,7 @@ type GitCommit struct { func (x *GitCommit) Reset() { *x = GitCommit{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[103] + mi := &file_rill_runtime_v1_api_proto_msgTypes[112] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6883,7 +7521,7 @@ func (x *GitCommit) String() string { func (*GitCommit) ProtoMessage() {} func (x *GitCommit) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[103] + mi := &file_rill_runtime_v1_api_proto_msgTypes[112] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6896,7 +7534,7 @@ func (x *GitCommit) ProtoReflect() protoreflect.Message { // Deprecated: Use GitCommit.ProtoReflect.Descriptor instead. func (*GitCommit) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{103} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{112} } func (x *GitCommit) GetCommitSha() string { @@ -6945,7 +7583,7 @@ type GitStatusRequest struct { func (x *GitStatusRequest) Reset() { *x = GitStatusRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[104] + mi := &file_rill_runtime_v1_api_proto_msgTypes[113] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6958,7 +7596,7 @@ func (x *GitStatusRequest) String() string { func (*GitStatusRequest) ProtoMessage() {} func (x *GitStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[104] + mi := &file_rill_runtime_v1_api_proto_msgTypes[113] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6971,7 +7609,7 @@ func (x *GitStatusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GitStatusRequest.ProtoReflect.Descriptor instead. func (*GitStatusRequest) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{104} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{113} } func (x *GitStatusRequest) GetInstanceId() string { @@ -7003,7 +7641,7 @@ type GitStatusResponse struct { func (x *GitStatusResponse) Reset() { *x = GitStatusResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[105] + mi := &file_rill_runtime_v1_api_proto_msgTypes[114] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7016,7 +7654,7 @@ func (x *GitStatusResponse) String() string { func (*GitStatusResponse) ProtoMessage() {} func (x *GitStatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[105] + mi := &file_rill_runtime_v1_api_proto_msgTypes[114] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7029,7 +7667,7 @@ func (x *GitStatusResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GitStatusResponse.ProtoReflect.Descriptor instead. func (*GitStatusResponse) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{105} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{114} } func (x *GitStatusResponse) GetBranch() string { @@ -7085,7 +7723,7 @@ type ListGitBranchesRequest struct { func (x *ListGitBranchesRequest) Reset() { *x = ListGitBranchesRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[106] + mi := &file_rill_runtime_v1_api_proto_msgTypes[115] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7098,7 +7736,7 @@ func (x *ListGitBranchesRequest) String() string { func (*ListGitBranchesRequest) ProtoMessage() {} func (x *ListGitBranchesRequest) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[106] + mi := &file_rill_runtime_v1_api_proto_msgTypes[115] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7111,7 +7749,7 @@ func (x *ListGitBranchesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListGitBranchesRequest.ProtoReflect.Descriptor instead. func (*ListGitBranchesRequest) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{106} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{115} } func (x *ListGitBranchesRequest) GetInstanceId() string { @@ -7133,7 +7771,7 @@ type ListGitBranchesResponse struct { func (x *ListGitBranchesResponse) Reset() { *x = ListGitBranchesResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[107] + mi := &file_rill_runtime_v1_api_proto_msgTypes[116] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7146,7 +7784,7 @@ func (x *ListGitBranchesResponse) String() string { func (*ListGitBranchesResponse) ProtoMessage() {} func (x *ListGitBranchesResponse) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[107] + mi := &file_rill_runtime_v1_api_proto_msgTypes[116] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7159,7 +7797,7 @@ func (x *ListGitBranchesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListGitBranchesResponse.ProtoReflect.Descriptor instead. func (*ListGitBranchesResponse) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{107} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{116} } func (x *ListGitBranchesResponse) GetCurrentBranch() string { @@ -7189,7 +7827,7 @@ type GitBranch struct { func (x *GitBranch) Reset() { *x = GitBranch{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[108] + mi := &file_rill_runtime_v1_api_proto_msgTypes[117] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7202,7 +7840,7 @@ func (x *GitBranch) String() string { func (*GitBranch) ProtoMessage() {} func (x *GitBranch) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[108] + mi := &file_rill_runtime_v1_api_proto_msgTypes[117] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7215,7 +7853,7 @@ func (x *GitBranch) ProtoReflect() protoreflect.Message { // Deprecated: Use GitBranch.ProtoReflect.Descriptor instead. func (*GitBranch) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{108} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{117} } func (x *GitBranch) GetName() string { @@ -7251,7 +7889,7 @@ type GitCommitRequest struct { func (x *GitCommitRequest) Reset() { *x = GitCommitRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[109] + mi := &file_rill_runtime_v1_api_proto_msgTypes[118] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7264,7 +7902,7 @@ func (x *GitCommitRequest) String() string { func (*GitCommitRequest) ProtoMessage() {} func (x *GitCommitRequest) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[109] + mi := &file_rill_runtime_v1_api_proto_msgTypes[118] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7277,7 +7915,7 @@ func (x *GitCommitRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GitCommitRequest.ProtoReflect.Descriptor instead. func (*GitCommitRequest) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{109} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{118} } func (x *GitCommitRequest) GetInstanceId() string { @@ -7305,7 +7943,7 @@ type GitCommitResponse struct { func (x *GitCommitResponse) Reset() { *x = GitCommitResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[110] + mi := &file_rill_runtime_v1_api_proto_msgTypes[119] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7318,7 +7956,7 @@ func (x *GitCommitResponse) String() string { func (*GitCommitResponse) ProtoMessage() {} func (x *GitCommitResponse) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[110] + mi := &file_rill_runtime_v1_api_proto_msgTypes[119] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7331,7 +7969,7 @@ func (x *GitCommitResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GitCommitResponse.ProtoReflect.Descriptor instead. func (*GitCommitResponse) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{110} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{119} } func (x *GitCommitResponse) GetCommitSha() string { @@ -7354,7 +7992,7 @@ type RestoreGitCommitRequest struct { func (x *RestoreGitCommitRequest) Reset() { *x = RestoreGitCommitRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[111] + mi := &file_rill_runtime_v1_api_proto_msgTypes[120] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7367,7 +8005,7 @@ func (x *RestoreGitCommitRequest) String() string { func (*RestoreGitCommitRequest) ProtoMessage() {} func (x *RestoreGitCommitRequest) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[111] + mi := &file_rill_runtime_v1_api_proto_msgTypes[120] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7380,7 +8018,7 @@ func (x *RestoreGitCommitRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RestoreGitCommitRequest.ProtoReflect.Descriptor instead. func (*RestoreGitCommitRequest) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{111} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{120} } func (x *RestoreGitCommitRequest) GetInstanceId() string { @@ -7409,7 +8047,7 @@ type RestoreGitCommitResponse struct { func (x *RestoreGitCommitResponse) Reset() { *x = RestoreGitCommitResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[112] + mi := &file_rill_runtime_v1_api_proto_msgTypes[121] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7422,7 +8060,7 @@ func (x *RestoreGitCommitResponse) String() string { func (*RestoreGitCommitResponse) ProtoMessage() {} func (x *RestoreGitCommitResponse) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[112] + mi := &file_rill_runtime_v1_api_proto_msgTypes[121] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7435,7 +8073,7 @@ func (x *RestoreGitCommitResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RestoreGitCommitResponse.ProtoReflect.Descriptor instead. func (*RestoreGitCommitResponse) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{112} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{121} } func (x *RestoreGitCommitResponse) GetNewCommitSha() string { @@ -7459,7 +8097,7 @@ type GitMergeToBranchRequest struct { func (x *GitMergeToBranchRequest) Reset() { *x = GitMergeToBranchRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[113] + mi := &file_rill_runtime_v1_api_proto_msgTypes[122] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7472,7 +8110,7 @@ func (x *GitMergeToBranchRequest) String() string { func (*GitMergeToBranchRequest) ProtoMessage() {} func (x *GitMergeToBranchRequest) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[113] + mi := &file_rill_runtime_v1_api_proto_msgTypes[122] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7485,7 +8123,7 @@ func (x *GitMergeToBranchRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GitMergeToBranchRequest.ProtoReflect.Descriptor instead. func (*GitMergeToBranchRequest) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{113} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{122} } func (x *GitMergeToBranchRequest) GetInstanceId() string { @@ -7521,7 +8159,7 @@ type GitMergeToBranchResponse struct { func (x *GitMergeToBranchResponse) Reset() { *x = GitMergeToBranchResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[114] + mi := &file_rill_runtime_v1_api_proto_msgTypes[123] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7534,7 +8172,7 @@ func (x *GitMergeToBranchResponse) String() string { func (*GitMergeToBranchResponse) ProtoMessage() {} func (x *GitMergeToBranchResponse) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[114] + mi := &file_rill_runtime_v1_api_proto_msgTypes[123] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7547,7 +8185,7 @@ func (x *GitMergeToBranchResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GitMergeToBranchResponse.ProtoReflect.Descriptor instead. func (*GitMergeToBranchResponse) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{114} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{123} } func (x *GitMergeToBranchResponse) GetOutput() string { @@ -7571,7 +8209,7 @@ type GitSwitchBranchRequest struct { func (x *GitSwitchBranchRequest) Reset() { *x = GitSwitchBranchRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[115] + mi := &file_rill_runtime_v1_api_proto_msgTypes[124] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7584,7 +8222,7 @@ func (x *GitSwitchBranchRequest) String() string { func (*GitSwitchBranchRequest) ProtoMessage() {} func (x *GitSwitchBranchRequest) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[115] + mi := &file_rill_runtime_v1_api_proto_msgTypes[124] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7597,7 +8235,7 @@ func (x *GitSwitchBranchRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GitSwitchBranchRequest.ProtoReflect.Descriptor instead. func (*GitSwitchBranchRequest) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{115} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{124} } func (x *GitSwitchBranchRequest) GetInstanceId() string { @@ -7637,7 +8275,7 @@ type GitSwitchBranchResponse struct { func (x *GitSwitchBranchResponse) Reset() { *x = GitSwitchBranchResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[116] + mi := &file_rill_runtime_v1_api_proto_msgTypes[125] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7650,7 +8288,7 @@ func (x *GitSwitchBranchResponse) String() string { func (*GitSwitchBranchResponse) ProtoMessage() {} func (x *GitSwitchBranchResponse) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[116] + mi := &file_rill_runtime_v1_api_proto_msgTypes[125] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7663,7 +8301,7 @@ func (x *GitSwitchBranchResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GitSwitchBranchResponse.ProtoReflect.Descriptor instead. func (*GitSwitchBranchResponse) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{116} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{125} } type GitPullRequest struct { @@ -7678,7 +8316,7 @@ type GitPullRequest struct { func (x *GitPullRequest) Reset() { *x = GitPullRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[117] + mi := &file_rill_runtime_v1_api_proto_msgTypes[126] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7691,7 +8329,7 @@ func (x *GitPullRequest) String() string { func (*GitPullRequest) ProtoMessage() {} func (x *GitPullRequest) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[117] + mi := &file_rill_runtime_v1_api_proto_msgTypes[126] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7704,7 +8342,7 @@ func (x *GitPullRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GitPullRequest.ProtoReflect.Descriptor instead. func (*GitPullRequest) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{117} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{126} } func (x *GitPullRequest) GetInstanceId() string { @@ -7733,7 +8371,7 @@ type GitPullResponse struct { func (x *GitPullResponse) Reset() { *x = GitPullResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[118] + mi := &file_rill_runtime_v1_api_proto_msgTypes[127] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7746,7 +8384,7 @@ func (x *GitPullResponse) String() string { func (*GitPullResponse) ProtoMessage() {} func (x *GitPullResponse) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[118] + mi := &file_rill_runtime_v1_api_proto_msgTypes[127] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7759,7 +8397,7 @@ func (x *GitPullResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GitPullResponse.ProtoReflect.Descriptor instead. func (*GitPullResponse) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{118} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{127} } func (x *GitPullResponse) GetOutput() string { @@ -7782,7 +8420,7 @@ type GitPushRequest struct { func (x *GitPushRequest) Reset() { *x = GitPushRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[119] + mi := &file_rill_runtime_v1_api_proto_msgTypes[128] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7795,7 +8433,7 @@ func (x *GitPushRequest) String() string { func (*GitPushRequest) ProtoMessage() {} func (x *GitPushRequest) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[119] + mi := &file_rill_runtime_v1_api_proto_msgTypes[128] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7808,7 +8446,7 @@ func (x *GitPushRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GitPushRequest.ProtoReflect.Descriptor instead. func (*GitPushRequest) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{119} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{128} } func (x *GitPushRequest) GetInstanceId() string { @@ -7841,7 +8479,7 @@ type GitPushResponse struct { func (x *GitPushResponse) Reset() { *x = GitPushResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[120] + mi := &file_rill_runtime_v1_api_proto_msgTypes[129] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7854,7 +8492,7 @@ func (x *GitPushResponse) String() string { func (*GitPushResponse) ProtoMessage() {} func (x *GitPushResponse) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[120] + mi := &file_rill_runtime_v1_api_proto_msgTypes[129] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7867,7 +8505,7 @@ func (x *GitPushResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GitPushResponse.ProtoReflect.Descriptor instead. func (*GitPushResponse) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{120} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{129} } // Property represents the spec of one of the driver's config properties @@ -7903,7 +8541,7 @@ type ConnectorDriver_Property struct { func (x *ConnectorDriver_Property) Reset() { *x = ConnectorDriver_Property{} if protoimpl.UnsafeEnabled { - mi := &file_rill_runtime_v1_api_proto_msgTypes[129] + mi := &file_rill_runtime_v1_api_proto_msgTypes[140] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7916,7 +8554,7 @@ func (x *ConnectorDriver_Property) String() string { func (*ConnectorDriver_Property) ProtoMessage() {} func (x *ConnectorDriver_Property) ProtoReflect() protoreflect.Message { - mi := &file_rill_runtime_v1_api_proto_msgTypes[129] + mi := &file_rill_runtime_v1_api_proto_msgTypes[140] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7929,7 +8567,7 @@ func (x *ConnectorDriver_Property) ProtoReflect() protoreflect.Message { // Deprecated: Use ConnectorDriver_Property.ProtoReflect.Descriptor instead. func (*ConnectorDriver_Property) Descriptor() ([]byte, []int) { - return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{67, 0} + return file_rill_runtime_v1_api_proto_rawDescGZIP(), []int{76, 0} } func (x *ConnectorDriver_Property) GetKey() string { @@ -8465,1265 +9103,1395 @@ var file_rill_runtime_v1_api_proto_rawDesc = []byte{ 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x69, 0x5f, 0x73, 0x75, 0x63, 0x63, 0x65, 0x65, 0x64, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x61, 0x69, 0x53, 0x75, 0x63, 0x63, 0x65, 0x65, 0x64, 0x65, 0x64, 0x22, - 0xf1, 0x01, 0x0a, 0x14, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, - 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, - 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, - 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, - 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x73, - 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x12, 0x48, 0x0a, 0x13, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, - 0x72, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x12, 0x72, 0x65, 0x73, - 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x12, - 0x3c, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x5f, 0x61, 0x72, 0x67, 0x73, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, - 0x0c, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x41, 0x72, 0x67, 0x73, 0x12, 0x14, 0x0a, - 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x69, - 0x6d, 0x69, 0x74, 0x22, 0xa6, 0x01, 0x0a, 0x15, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, - 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2b, 0x0a, - 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, - 0x72, 0x75, 0x63, 0x74, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x33, 0x0a, 0x06, 0x73, 0x63, - 0x68, 0x65, 0x6d, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x72, 0x69, 0x6c, - 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x72, - 0x75, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, - 0x2b, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, + 0xa4, 0x02, 0x0a, 0x17, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x54, 0x65, 0x6d, 0x70, + 0x6c, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x0b, 0x69, + 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x18, 0xfa, 0x42, 0x15, 0x72, 0x13, 0x32, 0x11, 0x5e, 0x5b, 0x5f, 0x5c, 0x2d, 0x61, 0x2d, + 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x2b, 0x24, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, + 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x3c, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x17, 0xfa, + 0x42, 0x14, 0x72, 0x12, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, + 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x30, 0x0a, 0x06, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xfa, 0x42, 0x15, 0x72, 0x13, 0x32, 0x11, 0x5e, 0x5b, 0x61, + 0x2d, 0x7a, 0x5d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5f, 0x5d, 0x2a, 0x24, 0x52, 0x06, + 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x12, 0x37, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, + 0x74, 0x69, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, + 0x75, 0x63, 0x74, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x12, + 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, + 0x6f, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xfa, 0x01, 0x0a, 0x18, 0x47, 0x65, 0x6e, 0x65, 0x72, + 0x61, 0x74, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6c, 0x6f, 0x62, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x62, 0x6c, 0x6f, 0x62, 0x12, 0x51, 0x0a, 0x08, 0x65, 0x6e, 0x76, 0x5f, 0x76, + 0x61, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x72, 0x69, 0x6c, 0x6c, + 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x65, + 0x72, 0x61, 0x74, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x45, 0x6e, 0x76, 0x56, 0x61, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x52, 0x07, 0x65, 0x6e, 0x76, 0x56, 0x61, 0x72, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, + 0x16, 0x0a, 0x06, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x1a, 0x3a, 0x0a, 0x0c, 0x45, 0x6e, 0x76, 0x56, 0x61, + 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, + 0x02, 0x38, 0x01, 0x22, 0xe0, 0x02, 0x0a, 0x08, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, + 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, + 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x72, 0x69, 0x76, 0x65, + 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x12, + 0x12, 0x0a, 0x04, 0x6f, 0x6c, 0x61, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6f, + 0x6c, 0x61, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x33, 0x0a, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, + 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, + 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, + 0x65, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x38, 0x0a, 0x0b, + 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x0a, 0x6a, 0x73, 0x6f, 0x6e, + 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x64, 0x6f, 0x63, 0x73, + 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x6f, 0x63, 0x73, + 0x55, 0x72, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x63, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x69, 0x63, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x6d, 0x61, 0x6c, 0x6c, + 0x5f, 0x69, 0x63, 0x6f, 0x6e, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x6d, 0x61, + 0x6c, 0x6c, 0x49, 0x63, 0x6f, 0x6e, 0x22, 0x45, 0x0a, 0x0c, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, + 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, + 0x74, 0x68, 0x5f, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x70, 0x61, 0x74, 0x68, 0x50, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x22, 0x2a, 0x0a, + 0x14, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x22, 0x50, 0x0a, 0x15, 0x4c, 0x69, 0x73, + 0x74, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x37, 0x0a, 0x09, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, + 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, + 0x52, 0x09, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x22, 0x90, 0x02, 0x0a, 0x13, + 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xfa, 0x42, 0x15, 0x72, 0x13, 0x32, + 0x11, 0x5e, 0x5b, 0x5f, 0x5c, 0x2d, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, + 0x2b, 0x24, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x2c, + 0x0a, 0x0d, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0c, + 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, + 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x75, + 0x74, 0x70, 0x75, 0x74, 0x12, 0x37, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, + 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, + 0x74, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x12, 0x25, 0x0a, + 0x0e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, + 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x70, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x22, 0xd7, + 0x01, 0x0a, 0x14, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, + 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, + 0x65, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x4d, 0x0a, + 0x08, 0x65, 0x6e, 0x76, 0x5f, 0x76, 0x61, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x32, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x45, 0x6e, 0x76, 0x56, 0x61, 0x72, 0x73, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x07, 0x65, 0x6e, 0x76, 0x56, 0x61, 0x72, 0x73, 0x1a, 0x3a, 0x0a, 0x0c, + 0x45, 0x6e, 0x76, 0x56, 0x61, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, + 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x37, 0x0a, 0x0d, 0x47, 0x65, 0x6e, 0x65, + 0x72, 0x61, 0x74, 0x65, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, + 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, + 0x04, 0x62, 0x6c, 0x6f, 0x62, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x62, 0x6c, 0x6f, + 0x62, 0x22, 0xf1, 0x01, 0x0a, 0x14, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x6f, 0x6c, + 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, + 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x72, + 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, + 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x12, 0x48, 0x0a, 0x13, 0x72, 0x65, 0x73, 0x6f, 0x6c, + 0x76, 0x65, 0x72, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x12, 0x72, + 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, + 0x73, 0x12, 0x3c, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x5f, 0x61, 0x72, + 0x67, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, + 0x74, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x41, 0x72, 0x67, 0x73, 0x12, + 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, + 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x22, 0xa6, 0x01, 0x0a, 0x15, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, + 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x2b, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0xa3, 0x01, 0x0a, - 0x03, 0x4c, 0x6f, 0x67, 0x12, 0x2f, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, - 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x05, - 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x2e, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 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, - 0x04, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, - 0x21, 0x0a, 0x0c, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6a, 0x73, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, - 0x61, 0x64, 0x22, 0xfb, 0x01, 0x0a, 0x0e, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x50, 0x61, 0x72, 0x74, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2b, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x04, - 0x64, 0x61, 0x74, 0x61, 0x12, 0x38, 0x0a, 0x09, 0x77, 0x61, 0x74, 0x65, 0x72, 0x6d, 0x61, 0x72, - 0x6b, 0x18, 0x03, 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, 0x77, 0x61, 0x74, 0x65, 0x72, 0x6d, 0x61, 0x72, 0x6b, 0x12, 0x3b, - 0x0a, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x6e, 0x18, 0x04, 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, - 0x0a, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x64, 0x4f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x65, - 0x72, 0x72, 0x6f, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, - 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x5f, 0x6d, 0x73, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x65, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x4d, 0x73, - 0x22, 0xa8, 0x01, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, - 0x63, 0x65, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x73, 0x63, 0x65, 0x6e, 0x64, 0x69, 0x6e, - 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x61, 0x73, 0x63, 0x65, 0x6e, 0x64, 0x69, - 0x6e, 0x67, 0x12, 0x26, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x05, 0x42, 0x10, 0xfa, 0x42, 0x0d, 0x1a, 0x0b, 0x28, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x01, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x2f, 0x0a, 0x05, 0x6c, 0x65, - 0x76, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x72, 0x69, 0x6c, 0x6c, - 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x4c, - 0x65, 0x76, 0x65, 0x6c, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0x3b, 0x0a, 0x0f, 0x47, - 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x28, - 0x0a, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x72, - 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, - 0x6f, 0x67, 0x52, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x22, 0xb1, 0x01, 0x0a, 0x10, 0x57, 0x61, 0x74, - 0x63, 0x68, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, - 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x16, - 0x0a, 0x06, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, - 0x72, 0x65, 0x70, 0x6c, 0x61, 0x79, 0x12, 0x33, 0x0a, 0x0c, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x79, - 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x42, 0x10, 0xfa, 0x42, - 0x0d, 0x1a, 0x0b, 0x28, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x52, 0x0b, - 0x72, 0x65, 0x70, 0x6c, 0x61, 0x79, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x2f, 0x0a, 0x05, 0x6c, - 0x65, 0x76, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x72, 0x69, 0x6c, - 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, - 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0x3b, 0x0a, 0x11, - 0x57, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x26, 0x0a, 0x03, 0x6c, 0x6f, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, + 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x33, 0x0a, 0x06, + 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x72, + 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, + 0x74, 0x72, 0x75, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, + 0x61, 0x12, 0x2b, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0xa3, + 0x01, 0x0a, 0x03, 0x4c, 0x6f, 0x67, 0x12, 0x2f, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, + 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, + 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x2e, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 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, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, + 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6a, 0x73, 0x6f, 0x6e, 0x50, 0x61, 0x79, + 0x6c, 0x6f, 0x61, 0x64, 0x22, 0xfb, 0x01, 0x0a, 0x0e, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x50, 0x61, + 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2b, 0x0a, 0x04, 0x64, 0x61, 0x74, + 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, + 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x38, 0x0a, 0x09, 0x77, 0x61, 0x74, 0x65, 0x72, 0x6d, + 0x61, 0x72, 0x6b, 0x18, 0x03, 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, 0x77, 0x61, 0x74, 0x65, 0x72, 0x6d, 0x61, 0x72, 0x6b, + 0x12, 0x3b, 0x0a, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x6e, 0x18, + 0x04, 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, 0x0a, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x64, 0x4f, 0x6e, 0x12, 0x14, 0x0a, + 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, + 0x72, 0x6f, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x5f, 0x6d, + 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x65, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, + 0x4d, 0x73, 0x22, 0xa8, 0x01, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, + 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, + 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x73, 0x63, 0x65, 0x6e, 0x64, + 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x61, 0x73, 0x63, 0x65, 0x6e, + 0x64, 0x69, 0x6e, 0x67, 0x12, 0x26, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x05, 0x42, 0x10, 0xfa, 0x42, 0x0d, 0x1a, 0x0b, 0x28, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x01, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x2f, 0x0a, 0x05, + 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x72, 0x69, + 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, + 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0x3b, 0x0a, + 0x0f, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x28, 0x0a, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x4c, 0x6f, 0x67, 0x52, 0x03, 0x6c, 0x6f, 0x67, 0x22, 0x91, 0x01, 0x0a, 0x14, 0x4c, 0x69, - 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, - 0x65, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x30, 0x0a, 0x14, 0x73, - 0x6b, 0x69, 0x70, 0x5f, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x63, 0x68, 0x65, - 0x63, 0x6b, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x73, 0x6b, 0x69, 0x70, 0x53, - 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x22, 0x50, 0x0a, - 0x15, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x72, 0x69, 0x6c, 0x6c, - 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x22, - 0x64, 0x0a, 0x15, 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, - 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, - 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, - 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x16, 0x0a, - 0x06, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x72, - 0x65, 0x70, 0x6c, 0x61, 0x79, 0x22, 0xb8, 0x01, 0x0a, 0x16, 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x34, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x1e, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, - 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x31, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, - 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4e, - 0x61, 0x6d, 0x65, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x35, 0x0a, 0x08, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x72, 0x69, + 0x2e, 0x4c, 0x6f, 0x67, 0x52, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x22, 0xb1, 0x01, 0x0a, 0x10, 0x57, + 0x61, 0x74, 0x63, 0x68, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, + 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x06, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x79, 0x12, 0x33, 0x0a, 0x0c, 0x72, 0x65, 0x70, 0x6c, + 0x61, 0x79, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x42, 0x10, + 0xfa, 0x42, 0x0d, 0x1a, 0x0b, 0x28, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, + 0x52, 0x0b, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x79, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x2f, 0x0a, + 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x72, + 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, + 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0x3b, + 0x0a, 0x11, 0x57, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x03, 0x6c, 0x6f, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x14, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x52, 0x03, 0x6c, 0x6f, 0x67, 0x22, 0x91, 0x01, 0x0a, 0x14, + 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, + 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, + 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x30, 0x0a, + 0x14, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x63, + 0x68, 0x65, 0x63, 0x6b, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x73, 0x6b, 0x69, + 0x70, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x22, + 0x50, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x22, 0x9a, 0x01, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, - 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, - 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x31, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x73, 0x22, 0x64, 0x0a, 0x15, 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, + 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6b, + 0x69, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, + 0x16, 0x0a, 0x06, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x06, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x79, 0x22, 0xb8, 0x01, 0x0a, 0x16, 0x57, 0x61, 0x74, 0x63, + 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x34, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x1e, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x52, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x31, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x30, 0x0a, 0x14, 0x73, - 0x6b, 0x69, 0x70, 0x5f, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x63, 0x68, 0x65, - 0x63, 0x6b, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x73, 0x6b, 0x69, 0x70, 0x53, - 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x22, 0x4c, 0x0a, - 0x13, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, - 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0x48, 0x0a, 0x11, 0x47, - 0x65, 0x74, 0x45, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, - 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x87, 0x01, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x45, 0x78, 0x70, - 0x6c, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x07, - 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, + 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x35, 0x0a, 0x08, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x07, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, - 0x65, 0x12, 0x3c, 0x0a, 0x0c, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x76, 0x69, 0x65, - 0x77, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x22, 0x9a, 0x01, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x73, + 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, + 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x31, 0x0a, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, + 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x30, 0x0a, + 0x14, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x63, + 0x68, 0x65, 0x63, 0x6b, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x73, 0x6b, 0x69, + 0x70, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x22, + 0x4c, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, + 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0x48, 0x0a, + 0x11, 0x47, 0x65, 0x74, 0x45, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, + 0x65, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x87, 0x01, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x45, + 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, + 0x0a, 0x07, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x19, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x07, 0x65, 0x78, 0x70, 0x6c, + 0x6f, 0x72, 0x65, 0x12, 0x3c, 0x0a, 0x0c, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x76, + 0x69, 0x65, 0x77, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x72, 0x69, 0x6c, 0x6c, + 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x52, 0x0b, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x56, 0x69, 0x65, + 0x77, 0x22, 0xce, 0x01, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x50, 0x61, + 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, + 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, + 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, + 0x12, 0x18, 0x0a, 0x07, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x07, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x65, 0x64, 0x12, 0x27, 0x0a, 0x09, 0x70, 0x61, + 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x42, 0x0a, 0xfa, + 0x42, 0x07, 0x2a, 0x05, 0x18, 0x90, 0x4e, 0x40, 0x01, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, + 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, + 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, + 0x65, 0x6e, 0x22, 0x85, 0x01, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x50, + 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x3f, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, + 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x50, 0x61, 0x72, + 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, + 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, + 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0xf7, 0x01, 0x0a, 0x14, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, + 0x63, 0x65, 0x49, 0x64, 0x12, 0x3b, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x52, 0x0b, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x56, 0x69, 0x65, 0x77, 0x22, - 0xce, 0x01, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x50, 0x61, 0x72, 0x74, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, - 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x14, - 0x0a, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, - 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x18, - 0x0a, 0x07, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x07, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x65, 0x64, 0x12, 0x27, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, - 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x42, 0x0a, 0xfa, 0x42, 0x07, - 0x2a, 0x05, 0x18, 0x90, 0x4e, 0x40, 0x01, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, - 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, - 0x22, 0x85, 0x01, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x50, 0x61, 0x72, - 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x3f, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, - 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x50, 0x61, 0x72, 0x74, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, - 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, - 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0xf7, 0x01, 0x0a, 0x14, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, - 0x49, 0x64, 0x12, 0x3b, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, - 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, - 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, - 0x3c, 0x0a, 0x06, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x24, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x54, 0x72, - 0x69, 0x67, 0x67, 0x65, 0x72, 0x52, 0x06, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x12, 0x16, 0x0a, - 0x06, 0x70, 0x61, 0x72, 0x73, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x70, - 0x61, 0x72, 0x73, 0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x6c, 0x6c, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x03, 0x61, 0x6c, 0x6c, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x6c, 0x6c, 0x5f, 0x66, - 0x75, 0x6c, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x61, 0x6c, 0x6c, 0x46, 0x75, - 0x6c, 0x6c, 0x22, 0x17, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x72, 0x69, 0x67, - 0x67, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x96, 0x0a, 0x0a, 0x0f, - 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x12, - 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x12, 0x56, 0x0a, 0x11, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72, - 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, - 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, - 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x52, 0x10, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x12, 0x56, 0x0a, 0x11, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, - 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, + 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x73, 0x12, 0x3c, 0x0a, 0x06, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x24, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x4d, 0x6f, 0x64, 0x65, 0x6c, + 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x52, 0x06, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x12, + 0x16, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x73, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x06, 0x70, 0x61, 0x72, 0x73, 0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x6c, 0x6c, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x61, 0x6c, 0x6c, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x6c, 0x6c, + 0x5f, 0x66, 0x75, 0x6c, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x61, 0x6c, 0x6c, + 0x46, 0x75, 0x6c, 0x6c, 0x22, 0x17, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x72, + 0x69, 0x67, 0x67, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x96, 0x0a, + 0x0a, 0x0f, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x44, 0x72, 0x69, 0x76, 0x65, + 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x56, 0x0a, 0x11, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, + 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x29, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x44, 0x72, 0x69, 0x76, + 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x52, 0x10, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x12, 0x56, 0x0a, + 0x11, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, + 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, + 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x6f, 0x72, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x65, + 0x72, 0x74, 0x79, 0x52, 0x10, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x70, 0x65, + 0x72, 0x74, 0x69, 0x65, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, + 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, + 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x64, 0x6f, + 0x63, 0x73, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x6f, + 0x63, 0x73, 0x55, 0x72, 0x6c, 0x12, 0x2f, 0x0a, 0x13, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, + 0x6e, 0x74, 0x73, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x18, 0x0a, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x12, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, + 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x12, 0x2d, 0x0a, 0x12, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, + 0x65, 0x6e, 0x74, 0x73, 0x5f, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x18, 0x0b, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x11, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x43, 0x61, + 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, + 0x6e, 0x74, 0x73, 0x5f, 0x72, 0x65, 0x70, 0x6f, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, + 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x70, 0x6f, 0x12, 0x29, + 0x0a, 0x10, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x5f, 0x61, 0x64, 0x6d, + 0x69, 0x6e, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, + 0x65, 0x6e, 0x74, 0x73, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x6d, 0x70, + 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x5f, 0x61, 0x69, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0c, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x41, 0x69, 0x12, 0x30, + 0x0a, 0x14, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x5f, 0x73, 0x71, 0x6c, + 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x69, 0x6d, + 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x53, 0x71, 0x6c, 0x53, 0x74, 0x6f, 0x72, 0x65, + 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x5f, 0x6f, + 0x6c, 0x61, 0x70, 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x69, 0x6d, 0x70, 0x6c, 0x65, + 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x4f, 0x6c, 0x61, 0x70, 0x12, 0x36, 0x0a, 0x17, 0x69, 0x6d, 0x70, + 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x73, + 0x74, 0x6f, 0x72, 0x65, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x69, 0x6d, 0x70, 0x6c, + 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x74, 0x6f, 0x72, + 0x65, 0x12, 0x32, 0x0a, 0x15, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x5f, + 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x13, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x46, 0x69, 0x6c, 0x65, + 0x53, 0x74, 0x6f, 0x72, 0x65, 0x12, 0x2f, 0x0a, 0x13, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, + 0x6e, 0x74, 0x73, 0x5f, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x13, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x12, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x4e, 0x6f, + 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x31, 0x0a, 0x14, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, + 0x65, 0x6e, 0x74, 0x73, 0x5f, 0x77, 0x61, 0x72, 0x65, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x18, 0x14, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, + 0x57, 0x61, 0x72, 0x65, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x1a, 0xda, 0x03, 0x0a, 0x08, 0x50, 0x72, + 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x42, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2e, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, - 0x79, 0x52, 0x10, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, - 0x69, 0x65, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, - 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x64, 0x6f, 0x63, 0x73, - 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x6f, 0x63, 0x73, - 0x55, 0x72, 0x6c, 0x12, 0x2f, 0x0a, 0x13, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, - 0x73, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x12, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x67, 0x69, - 0x73, 0x74, 0x72, 0x79, 0x12, 0x2d, 0x0a, 0x12, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, - 0x74, 0x73, 0x5f, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x11, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x43, 0x61, 0x74, 0x61, - 0x6c, 0x6f, 0x67, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, - 0x73, 0x5f, 0x72, 0x65, 0x70, 0x6f, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x69, 0x6d, - 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x70, 0x6f, 0x12, 0x29, 0x0a, 0x10, - 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, - 0x18, 0x0d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, - 0x74, 0x73, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x6d, 0x70, 0x6c, 0x65, - 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x5f, 0x61, 0x69, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, - 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x41, 0x69, 0x12, 0x30, 0x0a, 0x14, - 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x5f, 0x73, 0x71, 0x6c, 0x5f, 0x73, - 0x74, 0x6f, 0x72, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x69, 0x6d, 0x70, 0x6c, - 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x53, 0x71, 0x6c, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x12, 0x27, - 0x0a, 0x0f, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x5f, 0x6f, 0x6c, 0x61, - 0x70, 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, - 0x6e, 0x74, 0x73, 0x4f, 0x6c, 0x61, 0x70, 0x12, 0x36, 0x0a, 0x17, 0x69, 0x6d, 0x70, 0x6c, 0x65, - 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x73, 0x74, 0x6f, - 0x72, 0x65, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, - 0x65, 0x6e, 0x74, 0x73, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x12, - 0x32, 0x0a, 0x15, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x5f, 0x66, 0x69, - 0x6c, 0x65, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, - 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x74, - 0x6f, 0x72, 0x65, 0x12, 0x2f, 0x0a, 0x13, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, - 0x73, 0x5f, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x13, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x12, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x4e, 0x6f, 0x74, 0x69, - 0x66, 0x69, 0x65, 0x72, 0x12, 0x31, 0x0a, 0x14, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, - 0x74, 0x73, 0x5f, 0x77, 0x61, 0x72, 0x65, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x18, 0x14, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x13, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x57, 0x61, - 0x72, 0x65, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x1a, 0xda, 0x03, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x70, - 0x65, 0x72, 0x74, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x42, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2e, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, - 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, - 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x2e, - 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, - 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, - 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, - 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, - 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, - 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x64, - 0x6f, 0x63, 0x73, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, - 0x6f, 0x63, 0x73, 0x55, 0x72, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x69, 0x6e, 0x74, 0x18, 0x07, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x69, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, - 0x66, 0x61, 0x75, 0x6c, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x65, 0x66, - 0x61, 0x75, 0x6c, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, - 0x64, 0x65, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x6c, 0x61, 0x63, 0x65, - 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, - 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x1b, - 0x0a, 0x09, 0x6e, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x08, 0x6e, 0x6f, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x22, 0x77, 0x0a, 0x04, 0x54, - 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, - 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, - 0x45, 0x5f, 0x4e, 0x55, 0x4d, 0x42, 0x45, 0x52, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, - 0x50, 0x45, 0x5f, 0x42, 0x4f, 0x4f, 0x4c, 0x45, 0x41, 0x4e, 0x10, 0x02, 0x12, 0x0f, 0x0a, 0x0b, - 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x03, 0x12, 0x0d, 0x0a, - 0x09, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x04, 0x12, 0x16, 0x0a, 0x12, - 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x46, 0x4f, 0x52, 0x4d, 0x41, 0x54, 0x49, 0x4f, 0x4e, - 0x41, 0x4c, 0x10, 0x05, 0x22, 0x8d, 0x05, 0x0a, 0x11, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x7a, 0x65, - 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x38, - 0x0a, 0x06, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, - 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, - 0x52, 0x06, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x12, 0x2f, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, - 0x74, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3c, 0x0a, 0x0d, 0x70, 0x72, 0x65, - 0x73, 0x65, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x0c, 0x70, 0x72, 0x65, 0x73, 0x65, - 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3e, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x6a, 0x65, - 0x63, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, - 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x50, 0x0a, 0x0a, 0x65, 0x6e, 0x76, 0x5f, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x72, 0x69, - 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6e, - 0x61, 0x6c, 0x79, 0x7a, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x2e, - 0x45, 0x6e, 0x76, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, - 0x65, 0x6e, 0x76, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x72, 0x6f, - 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x70, 0x72, - 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x76, 0x69, - 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, - 0x69, 0x6f, 0x6e, 0x41, 0x72, 0x67, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x68, 0x61, 0x73, 0x5f, 0x61, - 0x6e, 0x6f, 0x6e, 0x79, 0x6d, 0x6f, 0x75, 0x73, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x68, 0x61, 0x73, 0x41, 0x6e, 0x6f, 0x6e, 0x79, 0x6d, - 0x6f, 0x75, 0x73, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x36, 0x0a, 0x07, 0x75, 0x73, 0x65, - 0x64, 0x5f, 0x62, 0x79, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x69, 0x6c, - 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x06, 0x75, 0x73, 0x65, 0x64, 0x42, - 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x3c, 0x0a, 0x0e, 0x45, 0x6e, 0x76, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x3a, 0x02, 0x38, 0x01, 0x22, 0x1d, 0x0a, 0x1b, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0x6f, 0x72, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x22, 0x60, 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x6f, 0x72, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, - 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x6f, 0x72, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x6f, 0x72, 0x73, 0x22, 0x3b, 0x0a, 0x18, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x7a, 0x65, - 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, - 0x49, 0x64, 0x22, 0x5f, 0x0a, 0x19, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x7a, 0x65, 0x43, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x42, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, - 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x7a, 0x65, 0x64, 0x43, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, - 0x6f, 0x72, 0x73, 0x22, 0x40, 0x0a, 0x1d, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x6f, 0x74, 0x69, 0x66, - 0x69, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, - 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, - 0x6e, 0x63, 0x65, 0x49, 0x64, 0x22, 0x5c, 0x0a, 0x1e, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x6f, 0x74, + 0x79, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, + 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, + 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, + 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, + 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, + 0x08, 0x64, 0x6f, 0x63, 0x73, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x64, 0x6f, 0x63, 0x73, 0x55, 0x72, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x69, 0x6e, 0x74, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x69, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, + 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, + 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x68, + 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x6c, 0x61, + 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x63, 0x72, + 0x65, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, + 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x18, 0x0b, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x08, 0x6e, 0x6f, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x22, 0x77, 0x0a, + 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, + 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x54, + 0x59, 0x50, 0x45, 0x5f, 0x4e, 0x55, 0x4d, 0x42, 0x45, 0x52, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, + 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x4f, 0x4f, 0x4c, 0x45, 0x41, 0x4e, 0x10, 0x02, 0x12, 0x0f, + 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x03, 0x12, + 0x0d, 0x0a, 0x09, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x04, 0x12, 0x16, + 0x0a, 0x12, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x46, 0x4f, 0x52, 0x4d, 0x41, 0x54, 0x49, + 0x4f, 0x4e, 0x41, 0x4c, 0x10, 0x05, 0x22, 0x8d, 0x05, 0x0a, 0x11, 0x41, 0x6e, 0x61, 0x6c, 0x79, + 0x7a, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x12, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x12, 0x38, 0x0a, 0x06, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x20, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x44, 0x72, 0x69, 0x76, + 0x65, 0x72, 0x52, 0x06, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x12, 0x2f, 0x0a, 0x06, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, + 0x75, 0x63, 0x74, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3c, 0x0a, 0x0d, 0x70, + 0x72, 0x65, 0x73, 0x65, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x0c, 0x70, 0x72, 0x65, + 0x73, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3e, 0x0a, 0x0e, 0x70, 0x72, 0x6f, + 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x6a, + 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x50, 0x0a, 0x0a, 0x65, 0x6e, 0x76, + 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, + 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x7a, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, + 0x72, 0x2e, 0x45, 0x6e, 0x76, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x09, 0x65, 0x6e, 0x76, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1c, 0x0a, 0x09, 0x70, + 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, + 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x0e, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x76, + 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x41, 0x72, 0x67, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x68, 0x61, 0x73, + 0x5f, 0x61, 0x6e, 0x6f, 0x6e, 0x79, 0x6d, 0x6f, 0x75, 0x73, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x68, 0x61, 0x73, 0x41, 0x6e, 0x6f, 0x6e, + 0x79, 0x6d, 0x6f, 0x75, 0x73, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x36, 0x0a, 0x07, 0x75, + 0x73, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, + 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x06, 0x75, 0x73, 0x65, + 0x64, 0x42, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, + 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x3c, 0x0a, 0x0e, 0x45, 0x6e, 0x76, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x1d, 0x0a, 0x1b, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x60, 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, + 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, + 0x6f, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x69, 0x6c, 0x6c, + 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, + 0x65, 0x63, 0x74, 0x6f, 0x72, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x52, 0x0a, 0x63, 0x6f, 0x6e, + 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x22, 0x3b, 0x0a, 0x18, 0x41, 0x6e, 0x61, 0x6c, 0x79, + 0x7a, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, + 0x63, 0x65, 0x49, 0x64, 0x22, 0x5f, 0x0a, 0x19, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x7a, 0x65, 0x43, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x42, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, + 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x7a, 0x65, 0x64, + 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x6f, 0x72, 0x73, 0x22, 0x40, 0x0a, 0x1d, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x72, 0x69, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, + 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x73, + 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x22, 0x5c, 0x0a, 0x1e, 0x4c, 0x69, 0x73, 0x74, 0x4e, + 0x6f, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, + 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, + 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x6f, 0x72, 0x73, 0x22, 0x9a, 0x02, 0x0a, 0x0c, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, + 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, + 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, + 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, + 0x61, 0x67, 0x65, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x75, 0x73, 0x65, + 0x72, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x64, 0x5f, 0x6f, 0x6e, 0x18, 0x04, 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, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x4f, + 0x6e, 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x6e, 0x18, + 0x05, 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, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x4f, 0x6e, 0x12, 0x34, 0x0a, 0x08, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, + 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x08, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x73, 0x22, 0xf8, 0x02, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x0e, + 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1b, + 0x0a, 0x09, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x39, 0x0a, 0x0a, 0x63, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x6e, 0x18, 0x03, 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, 0x63, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x64, 0x4f, 0x6e, 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x64, 0x5f, 0x6f, 0x6e, 0x18, 0x04, 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, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x4f, + 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, + 0x12, 0x0a, 0x04, 0x74, 0x6f, 0x6f, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, + 0x6f, 0x6f, 0x6c, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x44, 0x61, 0x74, 0x61, 0x12, 0x32, 0x0a, 0x07, 0x63, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x72, 0x69, 0x6c, + 0x6c, 0x2e, 0x61, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x42, + 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, 0xac, 0x04, + 0x0a, 0x13, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, + 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x12, + 0x16, 0x0a, 0x06, 0x63, 0x61, 0x6e, 0x76, 0x61, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x63, 0x61, 0x6e, 0x76, 0x61, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x61, 0x6e, 0x76, 0x61, + 0x73, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0f, 0x63, 0x61, 0x6e, 0x76, 0x61, 0x73, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, + 0x6e, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, + 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, + 0x6e, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x73, 0x18, 0x06, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x6d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x73, 0x12, 0x31, + 0x0a, 0x05, 0x77, 0x68, 0x65, 0x72, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, + 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x45, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x77, 0x68, 0x65, 0x72, + 0x65, 0x12, 0x72, 0x0a, 0x16, 0x77, 0x68, 0x65, 0x72, 0x65, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x6d, + 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x18, 0x0c, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x3d, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x74, + 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x2e, 0x57, 0x68, 0x65, 0x72, 0x65, 0x50, 0x65, 0x72, + 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x56, 0x69, 0x65, 0x77, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x13, 0x77, 0x68, 0x65, 0x72, 0x65, 0x50, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, + 0x73, 0x56, 0x69, 0x65, 0x77, 0x12, 0x39, 0x0a, 0x0a, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x73, 0x74, + 0x61, 0x72, 0x74, 0x18, 0x08, 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, 0x53, 0x74, 0x61, 0x72, 0x74, + 0x12, 0x35, 0x0a, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x65, 0x6e, 0x64, 0x18, 0x09, 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, 0x07, + 0x74, 0x69, 0x6d, 0x65, 0x45, 0x6e, 0x64, 0x1a, 0x63, 0x0a, 0x18, 0x57, 0x68, 0x65, 0x72, 0x65, + 0x50, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x56, 0x69, 0x65, 0x77, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x31, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, + 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x66, 0x0a, 0x15, + 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, + 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x69, 0x74, 0x5f, 0x70, 0x72, + 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x6e, 0x69, + 0x74, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x2a, 0x0a, 0x11, 0x63, 0x75, 0x72, 0x72, + 0x65, 0x6e, 0x74, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x46, 0x69, 0x6c, 0x65, + 0x50, 0x61, 0x74, 0x68, 0x22, 0x9a, 0x01, 0x0a, 0x14, 0x46, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, + 0x6b, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x2a, 0x0a, + 0x11, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x65, 0x6e, + 0x74, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, + 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x61, 0x74, 0x65, 0x67, + 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x61, 0x74, + 0x65, 0x67, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, + 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, + 0x74, 0x22, 0x83, 0x01, 0x0a, 0x18, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, + 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x39, + 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x18, 0xfa, 0x42, 0x15, 0x72, 0x13, 0x32, 0x11, 0x5e, 0x5b, 0x5f, 0x5c, + 0x2d, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x2b, 0x24, 0x52, 0x0a, 0x69, + 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x2c, 0x0a, 0x12, 0x75, 0x73, 0x65, + 0x72, 0x5f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x75, 0x73, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x74, + 0x50, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x22, 0x60, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x43, + 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, - 0x6f, 0x72, 0x73, 0x22, 0x9a, 0x02, 0x0a, 0x0c, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x02, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, - 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x61, 0x67, - 0x65, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x41, - 0x67, 0x65, 0x6e, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, - 0x6f, 0x6e, 0x18, 0x04, 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, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x4f, 0x6e, 0x12, - 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x6e, 0x18, 0x05, 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, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x4f, 0x6e, 0x12, 0x34, 0x0a, 0x08, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x72, - 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x08, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, - 0x22, 0xf8, 0x02, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x0e, 0x0a, 0x02, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1b, 0x0a, 0x09, - 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x6e, 0x18, 0x03, 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, 0x63, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x64, 0x4f, 0x6e, 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, - 0x6f, 0x6e, 0x18, 0x04, 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, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x4f, 0x6e, 0x12, - 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, - 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, - 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, - 0x04, 0x74, 0x6f, 0x6f, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x6f, 0x6f, - 0x6c, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, - 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x54, 0x79, 0x70, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x5f, - 0x64, 0x61, 0x74, 0x61, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x44, 0x61, 0x74, 0x61, 0x12, 0x32, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, - 0x6e, 0x74, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, - 0x61, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, 0xac, 0x04, 0x0a, 0x13, - 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x74, - 0x65, 0x78, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x12, 0x16, 0x0a, - 0x06, 0x63, 0x61, 0x6e, 0x76, 0x61, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, - 0x61, 0x6e, 0x76, 0x61, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x61, 0x6e, 0x76, 0x61, 0x73, 0x5f, - 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0f, 0x63, 0x61, 0x6e, 0x76, 0x61, 0x73, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, - 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x05, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, - 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x08, 0x6d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x73, 0x12, 0x31, 0x0a, 0x05, - 0x77, 0x68, 0x65, 0x72, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x72, 0x69, - 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, - 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x77, 0x68, 0x65, 0x72, 0x65, 0x12, - 0x72, 0x0a, 0x16, 0x77, 0x68, 0x65, 0x72, 0x65, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x6d, 0x65, 0x74, - 0x72, 0x69, 0x63, 0x73, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x3d, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, - 0x6e, 0x74, 0x65, 0x78, 0x74, 0x2e, 0x57, 0x68, 0x65, 0x72, 0x65, 0x50, 0x65, 0x72, 0x4d, 0x65, - 0x74, 0x72, 0x69, 0x63, 0x73, 0x56, 0x69, 0x65, 0x77, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x13, - 0x77, 0x68, 0x65, 0x72, 0x65, 0x50, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x56, - 0x69, 0x65, 0x77, 0x12, 0x39, 0x0a, 0x0a, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x72, - 0x74, 0x18, 0x08, 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, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x35, - 0x0a, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x65, 0x6e, 0x64, 0x18, 0x09, 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, 0x07, 0x74, 0x69, - 0x6d, 0x65, 0x45, 0x6e, 0x64, 0x1a, 0x63, 0x0a, 0x18, 0x57, 0x68, 0x65, 0x72, 0x65, 0x50, 0x65, - 0x72, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x56, 0x69, 0x65, 0x77, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x6b, 0x65, 0x79, 0x12, 0x31, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x66, 0x0a, 0x15, 0x44, 0x65, - 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x74, - 0x65, 0x78, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x69, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x6a, - 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x6e, 0x69, 0x74, 0x50, - 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x2a, 0x0a, 0x11, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, - 0x74, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x50, 0x61, - 0x74, 0x68, 0x22, 0x9a, 0x01, 0x0a, 0x14, 0x46, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, 0x41, - 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x2a, 0x0a, 0x11, 0x74, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x65, 0x6e, 0x74, 0x69, - 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x6e, 0x74, - 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, - 0x69, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x61, 0x74, 0x65, 0x67, - 0x6f, 0x72, 0x69, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x22, - 0x83, 0x01, 0x0a, 0x18, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x0b, - 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x42, 0x18, 0xfa, 0x42, 0x15, 0x72, 0x13, 0x32, 0x11, 0x5e, 0x5b, 0x5f, 0x5c, 0x2d, 0x61, - 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x2b, 0x24, 0x52, 0x0a, 0x69, 0x6e, 0x73, - 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x2c, 0x0a, 0x12, 0x75, 0x73, 0x65, 0x72, 0x5f, - 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x10, 0x75, 0x73, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x50, 0x61, - 0x74, 0x74, 0x65, 0x72, 0x6e, 0x22, 0x60, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, - 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x43, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x69, 0x6c, 0x6c, + 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x76, + 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x7c, 0x0a, 0x16, 0x47, 0x65, 0x74, + 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xfa, 0x42, 0x15, 0x72, 0x13, 0x32, + 0x11, 0x5e, 0x5b, 0x5f, 0x5c, 0x2d, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, + 0x2b, 0x24, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x27, + 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0xad, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x43, + 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x76, - 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, - 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x7c, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x43, 0x6f, - 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x39, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xfa, 0x42, 0x15, 0x72, 0x13, 0x32, 0x11, 0x5e, - 0x5b, 0x5f, 0x5c, 0x2d, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x2b, 0x24, - 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, - 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0xad, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, - 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x41, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, - 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, - 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x34, 0x0a, 0x08, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, - 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, - 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x52, 0x08, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x73, - 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x69, 0x73, - 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x22, 0xb1, 0x01, 0x0a, 0x18, 0x53, 0x68, 0x61, 0x72, 0x65, 0x43, - 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x39, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xfa, 0x42, 0x15, 0x72, 0x13, 0x32, 0x11, - 0x5e, 0x5b, 0x5f, 0x5c, 0x2d, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x2b, - 0x24, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x30, 0x0a, - 0x0f, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, - 0x0e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, - 0x28, 0x0a, 0x10, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x75, 0x6e, 0x74, 0x69, 0x6c, - 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x22, 0x1b, 0x0a, 0x19, 0x53, 0x68, 0x61, - 0x72, 0x65, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x86, 0x01, 0x0a, 0x17, 0x46, 0x6f, 0x72, 0x6b, 0x43, - 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x39, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xfa, 0x42, 0x15, 0x72, 0x13, 0x32, 0x11, - 0x5e, 0x5b, 0x5f, 0x5c, 0x2d, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x2b, - 0x24, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x30, 0x0a, - 0x0f, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, - 0x0e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, - 0x43, 0x0a, 0x18, 0x46, 0x6f, 0x72, 0x6b, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x63, - 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x33, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x6f, 0x6f, 0x6c, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, - 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, - 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x22, 0x3b, 0x0a, 0x11, 0x4c, 0x69, 0x73, - 0x74, 0x54, 0x6f, 0x6f, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, - 0x0a, 0x05, 0x74, 0x6f, 0x6f, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, - 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x61, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x6f, 0x6f, 0x6c, 0x52, - 0x05, 0x74, 0x6f, 0x6f, 0x6c, 0x73, 0x22, 0xf4, 0x03, 0x0a, 0x0f, 0x43, 0x6f, 0x6d, 0x70, 0x6c, - 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x0b, 0x69, 0x6e, - 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, - 0x18, 0xfa, 0x42, 0x15, 0x72, 0x13, 0x32, 0x11, 0x5e, 0x5b, 0x5f, 0x5c, 0x2d, 0x61, 0x2d, 0x7a, - 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x2b, 0x24, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, - 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, - 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x16, - 0x0a, 0x06, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x12, 0x4e, 0x0a, 0x05, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x18, - 0x0a, 0x20, 0x01, 0x28, 0x09, 0x42, 0x38, 0xfa, 0x42, 0x35, 0x72, 0x33, 0x52, 0x0d, 0x61, 0x6e, - 0x61, 0x6c, 0x79, 0x73, 0x74, 0x5f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x0f, 0x64, 0x65, 0x76, - 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x72, 0x5f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x0e, 0x66, 0x65, - 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0xd0, 0x01, 0x01, 0x52, - 0x05, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x12, 0x58, 0x0a, 0x15, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, - 0x74, 0x5f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, - 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, - 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x74, 0x41, - 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x13, 0x61, 0x6e, 0x61, - 0x6c, 0x79, 0x73, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, - 0x12, 0x5e, 0x0a, 0x17, 0x64, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x72, 0x5f, 0x61, 0x67, - 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x26, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x72, 0x41, 0x67, 0x65, - 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x15, 0x64, 0x65, 0x76, 0x65, 0x6c, - 0x6f, 0x70, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, - 0x12, 0x5b, 0x0a, 0x16, 0x66, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x61, 0x67, 0x65, - 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x25, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x46, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, 0x41, 0x67, 0x65, 0x6e, 0x74, - 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x14, 0x66, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, - 0x6b, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x71, 0x0a, - 0x10, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x76, - 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x34, 0x0a, 0x08, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x72, - 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x08, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, - 0x22, 0xfd, 0x03, 0x0a, 0x18, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x74, 0x72, - 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, - 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x42, 0x18, 0xfa, 0x42, 0x15, 0x72, 0x13, 0x32, 0x11, 0x5e, 0x5b, 0x5f, 0x5c, 0x2d, - 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x2b, 0x24, 0x52, 0x0a, 0x69, 0x6e, - 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x76, - 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, - 0x64, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x06, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x12, 0x4e, 0x0a, 0x05, 0x61, 0x67, 0x65, - 0x6e, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x42, 0x38, 0xfa, 0x42, 0x35, 0x72, 0x33, 0x52, - 0x0d, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x74, 0x5f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x0f, - 0x64, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x72, 0x5f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x52, - 0x0e, 0x66, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0xd0, - 0x01, 0x01, 0x52, 0x05, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x12, 0x58, 0x0a, 0x15, 0x61, 0x6e, 0x61, - 0x6c, 0x79, 0x73, 0x74, 0x5f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, - 0x78, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, - 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6e, 0x61, 0x6c, 0x79, - 0x73, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x13, - 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x74, - 0x65, 0x78, 0x74, 0x12, 0x5e, 0x0a, 0x17, 0x64, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x72, - 0x5f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x0c, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, - 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x72, - 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x15, 0x64, 0x65, - 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x74, - 0x65, 0x78, 0x74, 0x12, 0x5b, 0x0a, 0x16, 0x66, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, 0x5f, - 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x0d, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, - 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, 0x41, 0x67, - 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x14, 0x66, 0x65, 0x65, 0x64, - 0x62, 0x61, 0x63, 0x6b, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, - 0x22, 0x78, 0x0a, 0x19, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x74, 0x72, 0x65, - 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, + 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, + 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x34, 0x0a, 0x08, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, + 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x52, 0x08, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x12, 0x19, 0x0a, 0x08, + 0x69, 0x73, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, + 0x69, 0x73, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x22, 0xb1, 0x01, 0x0a, 0x18, 0x53, 0x68, 0x61, 0x72, + 0x65, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xfa, 0x42, 0x15, 0x72, 0x13, + 0x32, 0x11, 0x5e, 0x5b, 0x5f, 0x5c, 0x2d, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, + 0x5d, 0x2b, 0x24, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, + 0x30, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, + 0x01, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, + 0x64, 0x12, 0x28, 0x0a, 0x10, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x75, 0x6e, 0x74, + 0x69, 0x6c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x22, 0x1b, 0x0a, 0x19, 0x53, + 0x68, 0x61, 0x72, 0x65, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x86, 0x01, 0x0a, 0x17, 0x46, 0x6f, 0x72, + 0x6b, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xfa, 0x42, 0x15, 0x72, 0x13, + 0x32, 0x11, 0x5e, 0x5b, 0x5f, 0x5c, 0x2d, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, + 0x5d, 0x2b, 0x24, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, + 0x30, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, + 0x01, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, + 0x64, 0x22, 0x43, 0x0a, 0x18, 0x46, 0x6f, 0x72, 0x6b, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x32, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, - 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x7e, 0x0a, 0x13, 0x47, 0x65, - 0x74, 0x41, 0x49, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, - 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x6f, 0x6e, - 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x22, 0x4a, 0x0a, 0x14, 0x47, 0x65, - 0x74, 0x41, 0x49, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x32, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, - 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x07, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xb7, 0x01, 0x0a, 0x12, 0x49, 0x73, 0x73, 0x75, 0x65, - 0x44, 0x65, 0x76, 0x4a, 0x57, 0x54, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, - 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x05, 0x65, 0x6d, - 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, - 0x10, 0x01, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x67, 0x72, 0x6f, - 0x75, 0x70, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x67, 0x72, 0x6f, 0x75, 0x70, - 0x73, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x12, 0x37, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, - 0x72, 0x75, 0x63, 0x74, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, - 0x22, 0x27, 0x0a, 0x13, 0x49, 0x73, 0x73, 0x75, 0x65, 0x44, 0x65, 0x76, 0x4a, 0x57, 0x54, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6a, 0x77, 0x74, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6a, 0x77, 0x74, 0x22, 0x3a, 0x0a, 0x17, 0x41, 0x6e, 0x61, - 0x6c, 0x79, 0x7a, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, - 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, - 0x6e, 0x63, 0x65, 0x49, 0x64, 0x22, 0x5b, 0x0a, 0x18, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x7a, 0x65, - 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x3f, 0x0a, 0x09, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, - 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x7a, 0x65, 0x64, 0x56, - 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x09, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, - 0x65, 0x73, 0x22, 0x83, 0x01, 0x0a, 0x10, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x7a, 0x65, 0x64, 0x56, - 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x64, - 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0c, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x12, 0x36, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x18, 0x08, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, - 0x52, 0x06, 0x75, 0x73, 0x65, 0x64, 0x42, 0x79, 0x22, 0x8e, 0x01, 0x0a, 0x15, 0x4c, 0x69, 0x73, - 0x74, 0x47, 0x69, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x39, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xfa, 0x42, 0x15, 0x72, 0x13, 0x32, 0x11, - 0x5e, 0x5b, 0x5f, 0x5c, 0x2d, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x2b, - 0x24, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x1b, 0x0a, - 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, - 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, - 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x76, 0x0a, 0x16, 0x4c, 0x69, 0x73, - 0x74, 0x47, 0x69, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, - 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, - 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, - 0x6e, 0x22, 0xc7, 0x01, 0x0a, 0x09, 0x47, 0x69, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, - 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x73, 0x68, 0x61, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x53, 0x68, 0x61, 0x12, 0x1f, - 0x0a, 0x0b, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, - 0x21, 0x0a, 0x0c, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x45, 0x6d, 0x61, - 0x69, 0x6c, 0x12, 0x3d, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x5f, - 0x6f, 0x6e, 0x18, 0x04, 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, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x4f, - 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x4d, 0x0a, 0x10, 0x47, - 0x69, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x33, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x6f, + 0x6f, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, + 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x22, 0x3b, 0x0a, 0x11, 0x4c, + 0x69, 0x73, 0x74, 0x54, 0x6f, 0x6f, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x26, 0x0a, 0x05, 0x74, 0x6f, 0x6f, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x10, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x61, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x6f, 0x6f, + 0x6c, 0x52, 0x05, 0x74, 0x6f, 0x6f, 0x6c, 0x73, 0x22, 0xf4, 0x03, 0x0a, 0x0f, 0x43, 0x6f, 0x6d, + 0x70, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x0b, + 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x42, 0x18, 0xfa, 0x42, 0x15, 0x72, 0x13, 0x32, 0x11, 0x5e, 0x5b, 0x5f, 0x5c, 0x2d, 0x61, + 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x2b, 0x24, 0x52, 0x0a, 0x69, 0x6e, 0x73, + 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x76, 0x65, + 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, + 0x12, 0x16, 0x0a, 0x06, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x12, 0x4e, 0x0a, 0x05, 0x61, 0x67, 0x65, 0x6e, + 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x42, 0x38, 0xfa, 0x42, 0x35, 0x72, 0x33, 0x52, 0x0d, + 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x74, 0x5f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x0f, 0x64, + 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x72, 0x5f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x0e, + 0x66, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0xd0, 0x01, + 0x01, 0x52, 0x05, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x12, 0x58, 0x0a, 0x15, 0x61, 0x6e, 0x61, 0x6c, + 0x79, 0x73, 0x74, 0x5f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, + 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, + 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x73, + 0x74, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x13, 0x61, + 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, + 0x78, 0x74, 0x12, 0x5e, 0x0a, 0x17, 0x64, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x72, 0x5f, + 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x0c, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, + 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x72, 0x41, + 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x15, 0x64, 0x65, 0x76, + 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, + 0x78, 0x74, 0x12, 0x5b, 0x0a, 0x16, 0x66, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x61, + 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x0d, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, 0x41, 0x67, 0x65, + 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x14, 0x66, 0x65, 0x65, 0x64, 0x62, + 0x61, 0x63, 0x6b, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, + 0x71, 0x0a, 0x10, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x6f, + 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x34, 0x0a, 0x08, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, + 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x08, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x73, 0x22, 0xfd, 0x03, 0x0a, 0x18, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x53, + 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xfa, 0x42, 0x15, 0x72, 0x13, 0x32, 0x11, 0x5e, 0x5b, 0x5f, 0x5c, 0x2d, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x2b, 0x24, 0x52, 0x0a, - 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x22, 0xdc, 0x01, 0x0a, 0x11, 0x47, - 0x69, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x16, 0x0a, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x1d, 0x0a, 0x0a, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x55, 0x72, 0x6c, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x61, 0x6e, 0x61, 0x67, - 0x65, 0x64, 0x5f, 0x67, 0x69, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x6d, 0x61, - 0x6e, 0x61, 0x67, 0x65, 0x64, 0x47, 0x69, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x6c, 0x6f, 0x63, 0x61, - 0x6c, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x0c, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x23, 0x0a, - 0x0d, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x73, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x43, 0x6f, 0x6d, 0x6d, 0x69, - 0x74, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x63, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x72, 0x65, 0x6d, 0x6f, - 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x73, 0x22, 0x53, 0x0a, 0x16, 0x4c, 0x69, 0x73, - 0x74, 0x47, 0x69, 0x74, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xfa, 0x42, 0x15, 0x72, 0x13, 0x32, - 0x11, 0x5e, 0x5b, 0x5f, 0x5c, 0x2d, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, - 0x2b, 0x24, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x22, 0x78, - 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x69, 0x74, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x65, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x75, 0x72, - 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, - 0x12, 0x36, 0x0a, 0x08, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, 0x74, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x08, - 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x22, 0x77, 0x0a, 0x09, 0x47, 0x69, 0x74, 0x42, - 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x68, 0x61, 0x73, - 0x5f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x0d, 0x68, 0x61, 0x73, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, - 0x12, 0x2f, 0x0a, 0x13, 0x65, 0x64, 0x69, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x64, 0x65, 0x70, - 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x65, - 0x64, 0x69, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, - 0x74, 0x22, 0x74, 0x0a, 0x10, 0x47, 0x69, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52, 0x65, + 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x6f, + 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x12, 0x4e, 0x0a, 0x05, 0x61, + 0x67, 0x65, 0x6e, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x42, 0x38, 0xfa, 0x42, 0x35, 0x72, + 0x33, 0x52, 0x0d, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x74, 0x5f, 0x61, 0x67, 0x65, 0x6e, 0x74, + 0x52, 0x0f, 0x64, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x72, 0x5f, 0x61, 0x67, 0x65, 0x6e, + 0x74, 0x52, 0x0e, 0x66, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x61, 0x67, 0x65, 0x6e, + 0x74, 0xd0, 0x01, 0x01, 0x52, 0x05, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x12, 0x58, 0x0a, 0x15, 0x61, + 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x74, 0x5f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x6e, + 0x74, 0x65, 0x78, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x72, 0x69, 0x6c, + 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6e, 0x61, + 0x6c, 0x79, 0x73, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, + 0x52, 0x13, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, + 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x5e, 0x0a, 0x17, 0x64, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, + 0x65, 0x72, 0x5f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, + 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, + 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, + 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x15, + 0x64, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, + 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x5b, 0x0a, 0x16, 0x66, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, + 0x6b, 0x5f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, + 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, + 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, + 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x14, 0x66, 0x65, + 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, + 0x78, 0x74, 0x22, 0x78, 0x0a, 0x19, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x74, + 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x27, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, + 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x32, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x72, 0x69, 0x6c, 0x6c, + 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x7e, 0x0a, 0x13, + 0x47, 0x65, 0x74, 0x41, 0x49, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, + 0x63, 0x65, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, + 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, + 0x0a, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x22, 0x4a, 0x0a, 0x14, + 0x47, 0x65, 0x74, 0x41, 0x49, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, + 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, + 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xb7, 0x01, 0x0a, 0x12, 0x49, 0x73, 0x73, + 0x75, 0x65, 0x44, 0x65, 0x76, 0x4a, 0x57, 0x54, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, + 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x05, + 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, + 0x72, 0x02, 0x10, 0x01, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x67, + 0x72, 0x6f, 0x75, 0x70, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x67, 0x72, 0x6f, + 0x75, 0x70, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x12, 0x37, 0x0a, 0x0a, 0x61, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x73, 0x22, 0x27, 0x0a, 0x13, 0x49, 0x73, 0x73, 0x75, 0x65, 0x44, 0x65, 0x76, 0x4a, 0x57, + 0x54, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6a, 0x77, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6a, 0x77, 0x74, 0x22, 0x3a, 0x0a, 0x17, 0x41, + 0x6e, 0x61, 0x6c, 0x79, 0x7a, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, + 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x73, + 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x22, 0x5b, 0x0a, 0x18, 0x41, 0x6e, 0x61, 0x6c, 0x79, + 0x7a, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x09, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, + 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x7a, 0x65, + 0x64, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x09, 0x76, 0x61, 0x72, 0x69, 0x61, + 0x62, 0x6c, 0x65, 0x73, 0x22, 0x83, 0x01, 0x0a, 0x10, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x7a, 0x65, + 0x64, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, + 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x12, 0x36, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x18, 0x08, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, + 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4e, 0x61, + 0x6d, 0x65, 0x52, 0x06, 0x75, 0x73, 0x65, 0x64, 0x42, 0x79, 0x22, 0x8e, 0x01, 0x0a, 0x15, 0x4c, + 0x69, 0x73, 0x74, 0x47, 0x69, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xfa, 0x42, 0x15, 0x72, 0x13, + 0x32, 0x11, 0x5e, 0x5b, 0x5f, 0x5c, 0x2d, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, + 0x5d, 0x2b, 0x24, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, + 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, + 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x76, 0x0a, 0x16, 0x4c, + 0x69, 0x73, 0x74, 0x47, 0x69, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, + 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, 0x74, 0x43, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, + 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, + 0x6b, 0x65, 0x6e, 0x22, 0xc7, 0x01, 0x0a, 0x09, 0x47, 0x69, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x73, 0x68, 0x61, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x53, 0x68, 0x61, + 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x4e, 0x61, 0x6d, + 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x5f, 0x65, 0x6d, 0x61, 0x69, + 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x45, + 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x3d, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, + 0x64, 0x5f, 0x6f, 0x6e, 0x18, 0x04, 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, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, + 0x64, 0x4f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x4d, 0x0a, + 0x10, 0x47, 0x69, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x39, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xfa, 0x42, 0x15, 0x72, 0x13, 0x32, 0x11, 0x5e, + 0x5b, 0x5f, 0x5c, 0x2d, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x2b, 0x24, + 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x22, 0xdc, 0x01, 0x0a, + 0x11, 0x47, 0x69, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x1d, 0x0a, 0x0a, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x55, 0x72, 0x6c, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x61, 0x6e, + 0x61, 0x67, 0x65, 0x64, 0x5f, 0x67, 0x69, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, + 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x64, 0x47, 0x69, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x0c, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, + 0x23, 0x0a, 0x0d, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x73, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x43, 0x6f, 0x6d, + 0x6d, 0x69, 0x74, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x63, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x72, 0x65, + 0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x73, 0x22, 0x53, 0x0a, 0x16, 0x4c, + 0x69, 0x73, 0x74, 0x47, 0x69, 0x74, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xfa, 0x42, 0x15, 0x72, 0x13, 0x32, 0x11, 0x5e, 0x5b, 0x5f, 0x5c, 0x2d, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x2b, 0x24, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, - 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x32, 0x0a, 0x11, 0x47, 0x69, 0x74, 0x43, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, - 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x73, 0x68, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x53, 0x68, 0x61, 0x22, 0x7c, 0x0a, 0x17, 0x52, - 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x47, 0x69, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, - 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xfa, 0x42, 0x15, - 0x72, 0x13, 0x32, 0x11, 0x5e, 0x5b, 0x5f, 0x5c, 0x2d, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, - 0x2d, 0x39, 0x5d, 0x2b, 0x24, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, - 0x64, 0x12, 0x26, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x73, 0x68, 0x61, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x09, - 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x53, 0x68, 0x61, 0x22, 0x40, 0x0a, 0x18, 0x52, 0x65, 0x73, - 0x74, 0x6f, 0x72, 0x65, 0x47, 0x69, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x6e, 0x65, 0x77, 0x5f, 0x63, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x5f, 0x73, 0x68, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6e, - 0x65, 0x77, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x53, 0x68, 0x61, 0x22, 0x82, 0x01, 0x0a, 0x17, - 0x47, 0x69, 0x74, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x54, 0x6f, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, + 0x22, 0x78, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x69, 0x74, 0x42, 0x72, 0x61, 0x6e, 0x63, + 0x68, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x63, + 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x72, 0x61, 0x6e, + 0x63, 0x68, 0x12, 0x36, 0x0a, 0x08, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x18, 0x02, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, + 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, 0x74, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, + 0x52, 0x08, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x22, 0x77, 0x0a, 0x09, 0x47, 0x69, + 0x74, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x68, + 0x61, 0x73, 0x5f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x0d, 0x68, 0x61, 0x73, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, + 0x6e, 0x74, 0x12, 0x2f, 0x0a, 0x13, 0x65, 0x64, 0x69, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x64, + 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x12, 0x65, 0x64, 0x69, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, + 0x65, 0x6e, 0x74, 0x22, 0x74, 0x0a, 0x10, 0x47, 0x69, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xfa, 0x42, 0x15, 0x72, 0x13, 0x32, 0x11, 0x5e, 0x5b, 0x5f, 0x5c, 0x2d, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x2b, 0x24, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, - 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, - 0x72, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, - 0x22, 0x32, 0x0a, 0x18, 0x47, 0x69, 0x74, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x54, 0x6f, 0x42, 0x72, - 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, - 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x75, - 0x74, 0x70, 0x75, 0x74, 0x22, 0xb5, 0x01, 0x0a, 0x16, 0x47, 0x69, 0x74, 0x53, 0x77, 0x69, 0x74, - 0x63, 0x68, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x39, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xfa, 0x42, 0x15, 0x72, 0x13, 0x32, 0x11, 0x5e, 0x5b, 0x5f, - 0x5c, 0x2d, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x2b, 0x24, 0x52, 0x0a, - 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x72, - 0x61, 0x6e, 0x63, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x62, 0x72, 0x61, 0x6e, - 0x63, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x06, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x30, 0x0a, 0x14, 0x69, 0x67, - 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, - 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, - 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x22, 0x19, 0x0a, 0x17, - 0x47, 0x69, 0x74, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x70, 0x0a, 0x0e, 0x47, 0x69, 0x74, 0x50, 0x75, - 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x0b, 0x69, 0x6e, 0x73, + 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x32, 0x0a, 0x11, 0x47, 0x69, 0x74, + 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, + 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x73, 0x68, 0x61, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x53, 0x68, 0x61, 0x22, 0x7c, 0x0a, + 0x17, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x47, 0x69, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, + 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xfa, + 0x42, 0x15, 0x72, 0x13, 0x32, 0x11, 0x5e, 0x5b, 0x5f, 0x5c, 0x2d, 0x61, 0x2d, 0x7a, 0x41, 0x2d, + 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x2b, 0x24, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, + 0x65, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x73, 0x68, + 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, + 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x53, 0x68, 0x61, 0x22, 0x40, 0x0a, 0x18, 0x52, + 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x47, 0x69, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x6e, 0x65, 0x77, 0x5f, 0x63, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x73, 0x68, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0c, 0x6e, 0x65, 0x77, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x53, 0x68, 0x61, 0x22, 0x82, 0x01, + 0x0a, 0x17, 0x47, 0x69, 0x74, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x54, 0x6f, 0x42, 0x72, 0x61, 0x6e, + 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xfa, 0x42, 0x15, 0x72, 0x13, 0x32, 0x11, 0x5e, 0x5b, 0x5f, 0x5c, 0x2d, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x2b, 0x24, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, - 0x63, 0x65, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x5f, - 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x64, 0x69, 0x73, - 0x63, 0x61, 0x72, 0x64, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x22, 0x29, 0x0a, 0x0f, 0x47, 0x69, 0x74, - 0x50, 0x75, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, - 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x75, - 0x74, 0x70, 0x75, 0x74, 0x22, 0x88, 0x01, 0x0a, 0x0e, 0x47, 0x69, 0x74, 0x50, 0x75, 0x73, 0x68, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, - 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xfa, 0x42, - 0x15, 0x72, 0x13, 0x32, 0x11, 0x5e, 0x5b, 0x5f, 0x5c, 0x2d, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, - 0x30, 0x2d, 0x39, 0x5d, 0x2b, 0x24, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, - 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x6d, 0x6d, - 0x69, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, - 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x22, - 0x11, 0x0a, 0x0f, 0x47, 0x69, 0x74, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x2a, 0x54, 0x0a, 0x09, 0x46, 0x69, 0x6c, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, - 0x1a, 0x0a, 0x16, 0x46, 0x49, 0x4c, 0x45, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x55, 0x4e, - 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x46, - 0x49, 0x4c, 0x45, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x57, 0x52, 0x49, 0x54, 0x45, 0x10, - 0x01, 0x12, 0x15, 0x0a, 0x11, 0x46, 0x49, 0x4c, 0x45, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, - 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x02, 0x2a, 0x8c, 0x01, 0x0a, 0x08, 0x4c, 0x6f, 0x67, - 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x19, 0x0a, 0x15, 0x4c, 0x4f, 0x47, 0x5f, 0x4c, 0x45, 0x56, - 0x45, 0x4c, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, - 0x12, 0x13, 0x0a, 0x0f, 0x4c, 0x4f, 0x47, 0x5f, 0x4c, 0x45, 0x56, 0x45, 0x4c, 0x5f, 0x44, 0x45, - 0x42, 0x55, 0x47, 0x10, 0x04, 0x12, 0x12, 0x0a, 0x0e, 0x4c, 0x4f, 0x47, 0x5f, 0x4c, 0x45, 0x56, - 0x45, 0x4c, 0x5f, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x08, 0x12, 0x12, 0x0a, 0x0e, 0x4c, 0x4f, 0x47, - 0x5f, 0x4c, 0x45, 0x56, 0x45, 0x4c, 0x5f, 0x57, 0x41, 0x52, 0x4e, 0x10, 0x0c, 0x12, 0x13, 0x0a, - 0x0f, 0x4c, 0x4f, 0x47, 0x5f, 0x4c, 0x45, 0x56, 0x45, 0x4c, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, - 0x10, 0x10, 0x12, 0x13, 0x0a, 0x0f, 0x4c, 0x4f, 0x47, 0x5f, 0x4c, 0x45, 0x56, 0x45, 0x4c, 0x5f, - 0x46, 0x41, 0x54, 0x41, 0x4c, 0x10, 0x14, 0x2a, 0x64, 0x0a, 0x0d, 0x52, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1e, 0x0a, 0x1a, 0x52, 0x45, 0x53, 0x4f, - 0x55, 0x52, 0x43, 0x45, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, - 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x52, 0x45, 0x53, 0x4f, - 0x55, 0x52, 0x43, 0x45, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x57, 0x52, 0x49, 0x54, 0x45, - 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x45, - 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x02, 0x32, 0xbb, 0x3b, - 0x0a, 0x0e, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x12, 0x55, 0x0a, 0x04, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x1c, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, + 0x63, 0x65, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x14, 0x0a, 0x05, + 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, + 0x63, 0x65, 0x22, 0x32, 0x0a, 0x18, 0x47, 0x69, 0x74, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x54, 0x6f, + 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, + 0x0a, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x22, 0xb5, 0x01, 0x0a, 0x16, 0x47, 0x69, 0x74, 0x53, 0x77, + 0x69, 0x74, 0x63, 0x68, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x39, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xfa, 0x42, 0x15, 0x72, 0x13, 0x32, 0x11, 0x5e, + 0x5b, 0x5f, 0x5c, 0x2d, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x2b, 0x24, + 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, + 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x62, 0x72, + 0x61, 0x6e, 0x63, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x30, 0x0a, 0x14, + 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x63, 0x68, 0x61, + 0x6e, 0x67, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x69, 0x67, 0x6e, 0x6f, + 0x72, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x22, 0x19, + 0x0a, 0x17, 0x47, 0x69, 0x74, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x42, 0x72, 0x61, 0x6e, 0x63, + 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x70, 0x0a, 0x0e, 0x47, 0x69, 0x74, + 0x50, 0x75, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x0b, 0x69, + 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x18, 0xfa, 0x42, 0x15, 0x72, 0x13, 0x32, 0x11, 0x5e, 0x5b, 0x5f, 0x5c, 0x2d, 0x61, 0x2d, + 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x2b, 0x24, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, + 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, + 0x64, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x64, + 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x22, 0x29, 0x0a, 0x0f, 0x47, + 0x69, 0x74, 0x50, 0x75, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, + 0x0a, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x22, 0x88, 0x01, 0x0a, 0x0e, 0x47, 0x69, 0x74, 0x50, 0x75, + 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x0b, 0x69, 0x6e, 0x73, + 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, + 0xfa, 0x42, 0x15, 0x72, 0x13, 0x32, 0x11, 0x5e, 0x5b, 0x5f, 0x5c, 0x2d, 0x61, 0x2d, 0x7a, 0x41, + 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x2b, 0x24, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, + 0x63, 0x65, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6f, + 0x6d, 0x6d, 0x69, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x66, + 0x6f, 0x72, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, + 0x65, 0x22, 0x11, 0x0a, 0x0f, 0x47, 0x69, 0x74, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x2a, 0x54, 0x0a, 0x09, 0x46, 0x69, 0x6c, 0x65, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x12, 0x1a, 0x0a, 0x16, 0x46, 0x49, 0x4c, 0x45, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, + 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a, + 0x10, 0x46, 0x49, 0x4c, 0x45, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x57, 0x52, 0x49, 0x54, + 0x45, 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x46, 0x49, 0x4c, 0x45, 0x5f, 0x45, 0x56, 0x45, 0x4e, + 0x54, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x02, 0x2a, 0x8c, 0x01, 0x0a, 0x08, 0x4c, + 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x19, 0x0a, 0x15, 0x4c, 0x4f, 0x47, 0x5f, 0x4c, + 0x45, 0x56, 0x45, 0x4c, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, + 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x4c, 0x4f, 0x47, 0x5f, 0x4c, 0x45, 0x56, 0x45, 0x4c, 0x5f, + 0x44, 0x45, 0x42, 0x55, 0x47, 0x10, 0x04, 0x12, 0x12, 0x0a, 0x0e, 0x4c, 0x4f, 0x47, 0x5f, 0x4c, + 0x45, 0x56, 0x45, 0x4c, 0x5f, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x08, 0x12, 0x12, 0x0a, 0x0e, 0x4c, + 0x4f, 0x47, 0x5f, 0x4c, 0x45, 0x56, 0x45, 0x4c, 0x5f, 0x57, 0x41, 0x52, 0x4e, 0x10, 0x0c, 0x12, + 0x13, 0x0a, 0x0f, 0x4c, 0x4f, 0x47, 0x5f, 0x4c, 0x45, 0x56, 0x45, 0x4c, 0x5f, 0x45, 0x52, 0x52, + 0x4f, 0x52, 0x10, 0x10, 0x12, 0x13, 0x0a, 0x0f, 0x4c, 0x4f, 0x47, 0x5f, 0x4c, 0x45, 0x56, 0x45, + 0x4c, 0x5f, 0x46, 0x41, 0x54, 0x41, 0x4c, 0x10, 0x14, 0x2a, 0x64, 0x0a, 0x0d, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1e, 0x0a, 0x1a, 0x52, 0x45, + 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x55, 0x4e, 0x53, + 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x52, 0x45, + 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x57, 0x52, 0x49, + 0x54, 0x45, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, + 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x02, 0x32, + 0xea, 0x3e, 0x0a, 0x0e, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x12, 0x55, 0x0a, 0x04, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x1c, 0x2e, 0x72, 0x69, 0x6c, + 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x69, 0x6e, + 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, - 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x10, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0a, 0x12, 0x08, 0x2f, - 0x76, 0x31, 0x2f, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x5d, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x6c, 0x74, - 0x68, 0x12, 0x1e, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1f, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x12, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0c, 0x12, 0x0a, 0x2f, 0x76, 0x31, 0x2f, - 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x12, 0x8d, 0x01, 0x0a, 0x0e, 0x49, 0x6e, 0x73, 0x74, 0x61, - 0x6e, 0x63, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x12, 0x26, 0x2e, 0x72, 0x69, 0x6c, 0x6c, - 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, - 0x61, 0x6e, 0x63, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x27, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x48, 0x65, 0x61, 0x6c, - 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x24, 0x12, 0x22, 0x2f, 0x76, 0x31, 0x2f, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x2f, 0x69, - 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, - 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x75, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, - 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x25, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, - 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, - 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, - 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x15, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0f, 0x12, 0x0d, - 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x7d, 0x0a, - 0x0b, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x23, 0x2e, 0x72, - 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, - 0x65, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x24, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, - 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, - 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x7b, 0x0a, 0x0e, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x26, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x10, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0a, 0x12, + 0x08, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x5d, 0x0a, 0x06, 0x48, 0x65, 0x61, + 0x6c, 0x74, 0x68, 0x12, 0x1e, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, + 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, + 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x12, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0c, 0x12, 0x0a, 0x2f, 0x76, + 0x31, 0x2f, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x12, 0x8d, 0x01, 0x0a, 0x0e, 0x49, 0x6e, 0x73, + 0x74, 0x61, 0x6e, 0x63, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x12, 0x26, 0x2e, 0x72, 0x69, + 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, + 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, + 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x48, 0x65, + 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x24, 0x12, 0x22, 0x2f, 0x76, 0x31, 0x2f, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, + 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, + 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x75, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, + 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x25, 0x2e, 0x72, 0x69, 0x6c, 0x6c, + 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x26, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x15, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0f, + 0x12, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, + 0x7d, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x23, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, - 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, - 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x3a, 0x01, 0x2a, 0x22, 0x0d, 0x2f, 0x76, 0x31, 0x2f, - 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x83, 0x01, 0x0a, 0x0c, 0x45, 0x64, - 0x69, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x24, 0x2e, 0x72, 0x69, 0x6c, - 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x64, 0x69, - 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x25, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x45, 0x64, 0x69, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x3a, - 0x01, 0x2a, 0x32, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, - 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x12, - 0x89, 0x01, 0x0a, 0x0e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, - 0x63, 0x65, 0x12, 0x26, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x49, 0x6e, 0x73, 0x74, 0x61, - 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x72, 0x69, 0x6c, - 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, - 0x65, 0x74, 0x65, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x3a, 0x01, 0x2a, 0x22, 0x1b, - 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, - 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x91, 0x01, 0x0a, 0x0c, - 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x24, 0x2e, 0x72, - 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, - 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, + 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x1d, 0x12, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, + 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x7b, + 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, + 0x12, 0x26, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, + 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x3a, 0x01, 0x2a, 0x22, 0x0d, 0x2f, 0x76, + 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x83, 0x01, 0x0a, 0x0c, + 0x45, 0x64, 0x69, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x24, 0x2e, 0x72, + 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, + 0x64, 0x69, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x34, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x2e, 0x3a, 0x01, 0x2a, 0x22, 0x29, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x64, 0x69, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x20, 0x3a, 0x01, 0x2a, 0x32, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, - 0x7d, 0x2f, 0x72, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x2d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, - 0x7d, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x21, 0x2e, 0x72, - 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x22, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x29, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x23, 0x12, 0x21, 0x2f, 0x76, 0x31, - 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, - 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x88, - 0x01, 0x0a, 0x0a, 0x57, 0x61, 0x74, 0x63, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x22, 0x2e, - 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x57, 0x61, 0x74, 0x63, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x23, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x29, 0x12, 0x27, - 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, - 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x66, 0x69, 0x6c, 0x65, - 0x73, 0x2f, 0x77, 0x61, 0x74, 0x63, 0x68, 0x30, 0x01, 0x12, 0x7d, 0x0a, 0x07, 0x47, 0x65, 0x74, - 0x46, 0x69, 0x6c, 0x65, 0x12, 0x1f, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, - 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, - 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x29, 0x12, - 0x27, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, - 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x66, 0x69, 0x6c, - 0x65, 0x73, 0x2f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x80, 0x01, 0x0a, 0x07, 0x50, 0x75, 0x74, - 0x46, 0x69, 0x6c, 0x65, 0x12, 0x1f, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, - 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, - 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x32, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2c, 0x3a, - 0x01, 0x2a, 0x22, 0x27, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, - 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, - 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x96, 0x01, 0x0a, 0x0f, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x12, - 0x27, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, - 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, - 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x30, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2a, 0x3a, 0x01, 0x2a, 0x22, 0x25, 0x2f, + 0x7d, 0x12, 0x89, 0x01, 0x0a, 0x0e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x49, 0x6e, 0x73, 0x74, + 0x61, 0x6e, 0x63, 0x65, 0x12, 0x26, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, + 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x49, 0x6e, 0x73, + 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x72, + 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, + 0x65, 0x6c, 0x65, 0x74, 0x65, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x3a, 0x01, 0x2a, + 0x22, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, + 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x91, 0x01, + 0x0a, 0x0c, 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x24, + 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, + 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x34, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x2e, 0x3a, 0x01, 0x2a, 0x22, 0x29, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, + 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, + 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x2d, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x12, 0x7d, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x21, + 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x22, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x29, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x23, 0x12, 0x21, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x73, - 0x2f, 0x64, 0x69, 0x72, 0x12, 0x86, 0x01, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x46, - 0x69, 0x6c, 0x65, 0x12, 0x22, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, - 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, - 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, - 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2f, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x29, 0x2a, 0x27, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, - 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, - 0x7d, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x8a, 0x01, - 0x0a, 0x0a, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x22, 0x2e, 0x72, - 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, - 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x23, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x33, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2d, 0x3a, 0x01, 0x2a, - 0x22, 0x28, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, + 0x12, 0x88, 0x01, 0x0a, 0x0a, 0x57, 0x61, 0x74, 0x63, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, + 0x22, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, + 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x29, + 0x12, 0x27, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x66, 0x69, - 0x6c, 0x65, 0x73, 0x2f, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x71, 0x0a, 0x0c, 0x4c, 0x69, - 0x73, 0x74, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x12, 0x24, 0x2e, 0x72, 0x69, 0x6c, - 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x25, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x14, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0e, 0x12, - 0x0c, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x12, 0x9b, 0x01, - 0x0a, 0x0d, 0x55, 0x6e, 0x70, 0x61, 0x63, 0x6b, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x12, - 0x25, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x55, 0x6e, 0x70, 0x61, 0x63, 0x6b, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, - 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x70, 0x61, 0x63, 0x6b, 0x45, - 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3b, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x35, 0x3a, 0x01, 0x2a, 0x22, 0x30, 0x2f, 0x76, 0x31, 0x2f, 0x69, - 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, - 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2f, 0x75, 0x6e, 0x70, - 0x61, 0x63, 0x6b, 0x2d, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x12, 0x93, 0x01, 0x0a, 0x0b, - 0x55, 0x6e, 0x70, 0x61, 0x63, 0x6b, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x23, 0x2e, 0x72, 0x69, - 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, - 0x70, 0x61, 0x63, 0x6b, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x24, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x70, 0x61, 0x63, 0x6b, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x39, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x33, 0x3a, 0x01, - 0x2a, 0x22, 0x2e, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, + 0x6c, 0x65, 0x73, 0x2f, 0x77, 0x61, 0x74, 0x63, 0x68, 0x30, 0x01, 0x12, 0x7d, 0x0a, 0x07, 0x47, + 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x1f, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, + 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, + 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2f, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x29, 0x12, 0x27, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x66, - 0x69, 0x6c, 0x65, 0x73, 0x2f, 0x75, 0x6e, 0x70, 0x61, 0x63, 0x6b, 0x2d, 0x65, 0x6d, 0x70, 0x74, - 0x79, 0x12, 0xc0, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x4d, 0x65, - 0x74, 0x72, 0x69, 0x63, 0x73, 0x56, 0x69, 0x65, 0x77, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x2f, 0x2e, - 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x56, - 0x69, 0x65, 0x77, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, - 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, - 0x56, 0x69, 0x65, 0x77, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x42, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3c, 0x3a, 0x01, 0x2a, 0x22, 0x37, 0x2f, 0x76, 0x31, - 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, - 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2f, 0x67, - 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x2d, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2d, - 0x76, 0x69, 0x65, 0x77, 0x12, 0xab, 0x01, 0x0a, 0x12, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, - 0x65, 0x43, 0x61, 0x6e, 0x76, 0x61, 0x73, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x2a, 0x2e, 0x72, 0x69, - 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, - 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x43, 0x61, 0x6e, 0x76, 0x61, 0x73, 0x46, 0x69, 0x6c, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, - 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, - 0x74, 0x65, 0x43, 0x61, 0x6e, 0x76, 0x61, 0x73, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x36, 0x3a, 0x01, 0x2a, 0x22, - 0x31, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, + 0x69, 0x6c, 0x65, 0x73, 0x2f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x80, 0x01, 0x0a, 0x07, 0x50, + 0x75, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x1f, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, + 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75, 0x74, 0x46, 0x69, 0x6c, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, + 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75, 0x74, 0x46, 0x69, 0x6c, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x32, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x2c, 0x3a, 0x01, 0x2a, 0x22, 0x27, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, + 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, + 0x7d, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x96, 0x01, + 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, + 0x79, 0x12, 0x27, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, + 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x72, 0x69, 0x6c, + 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x30, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2a, 0x3a, 0x01, 0x2a, 0x22, + 0x25, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x66, 0x69, 0x6c, - 0x65, 0x73, 0x2f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x2d, 0x63, 0x61, 0x6e, 0x76, - 0x61, 0x73, 0x12, 0x95, 0x01, 0x0a, 0x0d, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x6f, - 0x6c, 0x76, 0x65, 0x72, 0x12, 0x25, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, - 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x6f, - 0x6c, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x72, 0x69, - 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, - 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x35, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2f, 0x3a, 0x01, 0x2a, 0x22, 0x2a, - 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, - 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x71, 0x75, 0x65, 0x72, - 0x79, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x12, 0x76, 0x0a, 0x07, 0x47, 0x65, - 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x1f, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, - 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, - 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, - 0x12, 0x20, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, - 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x6c, 0x6f, - 0x67, 0x73, 0x12, 0x84, 0x01, 0x0a, 0x09, 0x57, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x6f, 0x67, 0x73, - 0x12, 0x21, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, - 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x6f, 0x67, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x28, 0x12, - 0x26, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, - 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x6c, 0x6f, 0x67, - 0x73, 0x2f, 0x77, 0x61, 0x74, 0x63, 0x68, 0x30, 0x01, 0x12, 0x8d, 0x01, 0x0a, 0x0d, 0x4c, 0x69, - 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x25, 0x2e, 0x72, 0x69, - 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2d, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x27, 0x12, 0x25, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, - 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x9a, 0x01, 0x0a, 0x0e, 0x57, 0x61, - 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x26, 0x2e, 0x72, - 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, - 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, - 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x35, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x2f, 0x12, 0x2d, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, - 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, - 0x64, 0x7d, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x2d, 0x2f, 0x77, - 0x61, 0x74, 0x63, 0x68, 0x30, 0x01, 0x12, 0x86, 0x01, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x52, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x23, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, - 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x72, 0x69, - 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, - 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x2c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x26, 0x12, 0x24, 0x2f, 0x76, 0x31, 0x2f, 0x69, - 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, - 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, - 0x8c, 0x01, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x45, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x12, 0x22, + 0x65, 0x73, 0x2f, 0x64, 0x69, 0x72, 0x12, 0x86, 0x01, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x22, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, + 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x46, 0x69, + 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x72, 0x69, 0x6c, 0x6c, + 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2f, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x29, 0x2a, 0x27, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, + 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, + 0x69, 0x64, 0x7d, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x8a, 0x01, 0x0a, 0x0a, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x22, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x2e, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x35, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2f, 0x12, - 0x2d, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, - 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x12, 0xac, - 0x01, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x50, 0x61, 0x72, 0x74, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2a, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, - 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x6c, - 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x2b, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x50, 0x61, 0x72, 0x74, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3d, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x37, 0x12, 0x35, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, - 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, - 0x69, 0x64, 0x7d, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2f, 0x7b, 0x6d, 0x6f, 0x64, 0x65, - 0x6c, 0x7d, 0x2f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x8e, 0x01, - 0x0a, 0x0d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x12, - 0x25, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, - 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, - 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2e, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x28, 0x3a, 0x01, 0x2a, 0x22, 0x23, 0x2f, 0x76, 0x31, 0x2f, 0x69, - 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, - 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x12, 0x90, - 0x01, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, - 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x73, 0x12, 0x2c, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, - 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, - 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0x6f, 0x72, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x76, - 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x6d, 0x65, 0x74, - 0x61, 0x12, 0xa2, 0x01, 0x0a, 0x11, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x7a, 0x65, 0x43, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x29, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, - 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x7a, - 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x7a, 0x65, 0x43, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x36, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x30, 0x12, 0x2e, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, - 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, - 0x69, 0x64, 0x7d, 0x2f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x61, - 0x6e, 0x61, 0x6c, 0x79, 0x7a, 0x65, 0x12, 0xb3, 0x01, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x4e, - 0x6f, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, - 0x73, 0x12, 0x2e, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, - 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x2f, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, - 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x38, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x32, 0x12, 0x30, 0x2f, 0x76, 0x31, 0x2f, - 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, - 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, - 0x72, 0x73, 0x2f, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x12, 0xa0, 0x01, 0x0a, - 0x11, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x12, 0x29, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x33, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2d, 0x3a, + 0x01, 0x2a, 0x22, 0x28, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, + 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, + 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2f, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x71, 0x0a, 0x0c, + 0x4c, 0x69, 0x73, 0x74, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x12, 0x24, 0x2e, 0x72, + 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x14, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x0e, 0x12, 0x0c, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x12, + 0x9b, 0x01, 0x0a, 0x0d, 0x55, 0x6e, 0x70, 0x61, 0x63, 0x6b, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, + 0x65, 0x12, 0x25, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x70, 0x61, 0x63, 0x6b, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, + 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x70, 0x61, 0x63, + 0x6b, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x3b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x35, 0x3a, 0x01, 0x2a, 0x22, 0x30, 0x2f, 0x76, 0x31, + 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, + 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2f, 0x75, + 0x6e, 0x70, 0x61, 0x63, 0x6b, 0x2d, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x12, 0x93, 0x01, + 0x0a, 0x0b, 0x55, 0x6e, 0x70, 0x61, 0x63, 0x6b, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x23, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x34, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x2e, 0x12, 0x2c, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, - 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x61, - 0x69, 0x2f, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, - 0xac, 0x01, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, - 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x72, - 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, - 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x46, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x40, 0x12, 0x3e, - 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, - 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x61, 0x69, 0x2f, 0x63, - 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x7b, 0x63, 0x6f, - 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0xbb, - 0x01, 0x0a, 0x11, 0x53, 0x68, 0x61, 0x72, 0x65, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x29, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, - 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x65, 0x43, 0x6f, 0x6e, 0x76, - 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x2a, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x65, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4f, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x49, 0x3a, 0x01, 0x2a, 0x22, 0x44, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, - 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, - 0x69, 0x64, 0x7d, 0x2f, 0x61, 0x69, 0x2f, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x7b, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x73, 0x68, 0x61, 0x72, 0x65, 0x12, 0xb7, 0x01, 0x0a, - 0x10, 0x46, 0x6f, 0x72, 0x6b, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x28, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x6f, 0x72, 0x6b, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x72, 0x69, - 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x6f, - 0x72, 0x6b, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x48, 0x3a, 0x01, - 0x2a, 0x22, 0x43, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, - 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x61, - 0x69, 0x2f, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, - 0x7b, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, - 0x7d, 0x2f, 0x66, 0x6f, 0x72, 0x6b, 0x12, 0x80, 0x01, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x54, - 0x6f, 0x6f, 0x6c, 0x73, 0x12, 0x21, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, - 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x6f, 0x6f, 0x6c, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, - 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x6f, - 0x6f, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2c, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x26, 0x12, 0x24, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, + 0x55, 0x6e, 0x70, 0x61, 0x63, 0x6b, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x70, 0x61, 0x63, 0x6b, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x39, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x33, + 0x3a, 0x01, 0x2a, 0x22, 0x2e, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, - 0x2f, 0x61, 0x69, 0x2f, 0x74, 0x6f, 0x6f, 0x6c, 0x73, 0x12, 0x83, 0x01, 0x0a, 0x08, 0x43, 0x6f, - 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x20, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, - 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, - 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, - 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x32, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x2c, 0x3a, 0x01, 0x2a, 0x22, 0x27, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, + 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2f, 0x75, 0x6e, 0x70, 0x61, 0x63, 0x6b, 0x2d, 0x65, 0x6d, + 0x70, 0x74, 0x79, 0x12, 0xc0, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, + 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x56, 0x69, 0x65, 0x77, 0x46, 0x69, 0x6c, 0x65, 0x12, + 0x2f, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, + 0x73, 0x56, 0x69, 0x65, 0x77, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x30, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, + 0x63, 0x73, 0x56, 0x69, 0x65, 0x77, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x42, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3c, 0x3a, 0x01, 0x2a, 0x22, 0x37, 0x2f, + 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, + 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x73, + 0x2f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x2d, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, + 0x73, 0x2d, 0x76, 0x69, 0x65, 0x77, 0x12, 0xab, 0x01, 0x0a, 0x12, 0x47, 0x65, 0x6e, 0x65, 0x72, + 0x61, 0x74, 0x65, 0x43, 0x61, 0x6e, 0x76, 0x61, 0x73, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x2a, 0x2e, + 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x43, 0x61, 0x6e, 0x76, 0x61, 0x73, 0x46, 0x69, + 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x72, 0x69, 0x6c, 0x6c, + 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x65, + 0x72, 0x61, 0x74, 0x65, 0x43, 0x61, 0x6e, 0x76, 0x61, 0x73, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x36, 0x3a, 0x01, + 0x2a, 0x22, 0x31, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, + 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x66, + 0x69, 0x6c, 0x65, 0x73, 0x2f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x2d, 0x63, 0x61, + 0x6e, 0x76, 0x61, 0x73, 0x12, 0xa1, 0x01, 0x0a, 0x10, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, + 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0x28, 0x2e, 0x72, 0x69, 0x6c, 0x6c, + 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x65, + 0x72, 0x61, 0x74, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, + 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x54, 0x65, + 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x38, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x32, 0x3a, 0x01, 0x2a, 0x22, 0x2d, 0x2f, 0x76, 0x31, 0x2f, 0x69, + 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, + 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x2f, + 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0x75, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, + 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x12, 0x25, 0x2e, 0x72, 0x69, 0x6c, 0x6c, + 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x26, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x15, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0f, + 0x12, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x12, + 0x91, 0x01, 0x0a, 0x0c, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, + 0x12, 0x24, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, + 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, + 0x65, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x34, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x2e, 0x3a, 0x01, 0x2a, 0x22, 0x29, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, + 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, + 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x2f, 0x66, + 0x69, 0x6c, 0x65, 0x12, 0x95, 0x01, 0x0a, 0x0d, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, + 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x12, 0x25, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, + 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, + 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x72, + 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x51, + 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x35, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2f, 0x3a, 0x01, 0x2a, 0x22, + 0x2a, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, + 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x71, 0x75, 0x65, + 0x72, 0x79, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x12, 0x76, 0x0a, 0x07, 0x47, + 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x1f, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, + 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, + 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x67, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x22, 0x12, 0x20, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, + 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x6c, + 0x6f, 0x67, 0x73, 0x12, 0x84, 0x01, 0x0a, 0x09, 0x57, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x6f, 0x67, + 0x73, 0x12, 0x21, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, + 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x6f, 0x67, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x28, + 0x12, 0x26, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, + 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x6c, 0x6f, + 0x67, 0x73, 0x2f, 0x77, 0x61, 0x74, 0x63, 0x68, 0x30, 0x01, 0x12, 0x8d, 0x01, 0x0a, 0x0d, 0x4c, + 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x25, 0x2e, 0x72, + 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, + 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2d, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x27, 0x12, 0x25, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, + 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, + 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x9a, 0x01, 0x0a, 0x0e, 0x57, + 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x26, 0x2e, + 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, + 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x35, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2f, 0x12, 0x2d, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, - 0x69, 0x64, 0x7d, 0x2f, 0x61, 0x69, 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, - 0xa7, 0x01, 0x0a, 0x11, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x74, 0x72, 0x65, - 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x12, 0x29, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, - 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, - 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x2a, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, - 0x6d, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x39, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x33, 0x3a, 0x01, 0x2a, 0x22, 0x2e, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, + 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x2d, 0x2f, + 0x77, 0x61, 0x74, 0x63, 0x68, 0x30, 0x01, 0x12, 0x86, 0x01, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x23, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, + 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x72, + 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, + 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x2c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x26, 0x12, 0x24, 0x2f, 0x76, 0x31, 0x2f, + 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, + 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x12, 0x8c, 0x01, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x45, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x12, + 0x22, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, + 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x35, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2f, + 0x12, 0x2d, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, + 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x12, + 0xac, 0x01, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x50, 0x61, 0x72, 0x74, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2a, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, + 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x65, + 0x6c, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x50, 0x61, 0x72, + 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x3d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x37, 0x12, 0x35, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, - 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x61, 0x69, 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, - 0x2f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x30, 0x01, 0x12, 0xb9, 0x01, 0x0a, 0x0c, 0x47, 0x65, - 0x74, 0x41, 0x49, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x24, 0x2e, 0x72, 0x69, 0x6c, - 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, - 0x41, 0x49, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x25, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x49, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x5c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x56, 0x12, - 0x54, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, + 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2f, 0x7b, 0x6d, 0x6f, 0x64, + 0x65, 0x6c, 0x7d, 0x2f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x8e, + 0x01, 0x0a, 0x0d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, + 0x12, 0x25, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, + 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x28, 0x3a, 0x01, 0x2a, 0x22, 0x23, 0x2f, 0x76, 0x31, 0x2f, + 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, + 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x12, + 0x90, 0x01, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, + 0x72, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x73, 0x12, 0x2c, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, + 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, + 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, + 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, + 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x6d, 0x65, + 0x74, 0x61, 0x12, 0xa2, 0x01, 0x0a, 0x11, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x7a, 0x65, 0x43, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x29, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, + 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6e, 0x61, 0x6c, 0x79, + 0x7a, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, + 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x7a, 0x65, 0x43, 0x6f, 0x6e, + 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x36, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x30, 0x12, 0x2e, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, + 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, + 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x2f, + 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x7a, 0x65, 0x12, 0xb3, 0x01, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, + 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, + 0x72, 0x73, 0x12, 0x2e, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x65, + 0x72, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x65, + 0x72, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x38, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x32, 0x12, 0x30, 0x2f, 0x76, 0x31, + 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, + 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, + 0x6f, 0x72, 0x73, 0x2f, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x12, 0xa0, 0x01, + 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x12, 0x29, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, + 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, + 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, + 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x34, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x2e, 0x12, 0x2c, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, + 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, + 0x61, 0x69, 0x2f, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x12, 0xac, 0x01, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, + 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, + 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, + 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x46, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x40, 0x12, + 0x3e, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x61, 0x69, 0x2f, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x7b, 0x63, - 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x7d, 0x2f, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2f, 0x7b, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x70, 0x0a, 0x0b, 0x49, 0x73, 0x73, 0x75, 0x65, 0x44, 0x65, - 0x76, 0x4a, 0x57, 0x54, 0x12, 0x23, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, - 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x73, 0x73, 0x75, 0x65, 0x44, 0x65, 0x76, 0x4a, - 0x57, 0x54, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x72, 0x69, 0x6c, 0x6c, - 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x73, 0x73, 0x75, - 0x65, 0x44, 0x65, 0x76, 0x4a, 0x57, 0x54, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x16, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x3a, 0x01, 0x2a, 0x22, 0x0b, 0x2f, 0x76, 0x31, 0x2f, - 0x64, 0x65, 0x76, 0x2d, 0x6a, 0x77, 0x74, 0x12, 0x9e, 0x01, 0x0a, 0x10, 0x41, 0x6e, 0x61, 0x6c, - 0x79, 0x7a, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x28, 0x2e, 0x72, - 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, - 0x6e, 0x61, 0x6c, 0x79, 0x7a, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, - 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x7a, 0x65, - 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x35, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2f, 0x12, 0x2d, 0x2f, 0x76, 0x31, 0x2f, 0x69, - 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, - 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, - 0x2f, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x7a, 0x65, 0x12, 0x92, 0x01, 0x0a, 0x0e, 0x4c, 0x69, 0x73, - 0x74, 0x47, 0x69, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x26, 0x2e, 0x72, 0x69, - 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x47, 0x69, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, - 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x69, 0x74, 0x43, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2f, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x29, 0x12, 0x27, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, + 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x7d, 0x12, + 0xbb, 0x01, 0x0a, 0x11, 0x53, 0x68, 0x61, 0x72, 0x65, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x29, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, + 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x65, 0x43, 0x6f, 0x6e, + 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x2a, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x65, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4f, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x49, 0x3a, 0x01, 0x2a, 0x22, 0x44, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, + 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, + 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x61, 0x69, 0x2f, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x7b, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x73, 0x68, 0x61, 0x72, 0x65, 0x12, 0xb7, 0x01, + 0x0a, 0x10, 0x46, 0x6f, 0x72, 0x6b, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x28, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x6f, 0x72, 0x6b, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x72, + 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x46, + 0x6f, 0x72, 0x6b, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x48, 0x3a, + 0x01, 0x2a, 0x22, 0x43, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, + 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, + 0x61, 0x69, 0x2f, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x2f, 0x7b, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, + 0x64, 0x7d, 0x2f, 0x66, 0x6f, 0x72, 0x6b, 0x12, 0x80, 0x01, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, + 0x54, 0x6f, 0x6f, 0x6c, 0x73, 0x12, 0x21, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, + 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x6f, 0x6f, 0x6c, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, + 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, + 0x6f, 0x6f, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2c, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x26, 0x12, 0x24, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, - 0x7d, 0x2f, 0x67, 0x69, 0x74, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x82, 0x01, - 0x0a, 0x09, 0x47, 0x69, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x21, 0x2e, 0x72, 0x69, - 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, - 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, - 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x47, 0x69, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x28, 0x12, 0x26, 0x2f, 0x76, 0x31, 0x2f, + 0x7d, 0x2f, 0x61, 0x69, 0x2f, 0x74, 0x6f, 0x6f, 0x6c, 0x73, 0x12, 0x83, 0x01, 0x0a, 0x08, 0x43, + 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x20, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, + 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, + 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x72, 0x69, 0x6c, 0x6c, + 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, + 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x32, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x2c, 0x3a, 0x01, 0x2a, 0x22, 0x27, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, + 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, + 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x61, 0x69, 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, + 0x12, 0xa7, 0x01, 0x0a, 0x11, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x74, 0x72, + 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x12, 0x29, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, + 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, + 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x2a, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x74, 0x72, 0x65, + 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x39, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x33, 0x3a, 0x01, 0x2a, 0x22, 0x2e, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, + 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, + 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x61, 0x69, 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, + 0x65, 0x2f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x30, 0x01, 0x12, 0xb9, 0x01, 0x0a, 0x0c, 0x47, + 0x65, 0x74, 0x41, 0x49, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x24, 0x2e, 0x72, 0x69, + 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, + 0x74, 0x41, 0x49, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x25, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x49, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x5c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x56, + 0x12, 0x54, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, + 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x61, 0x69, + 0x2f, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x7b, + 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x7d, + 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2f, 0x7b, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x70, 0x0a, 0x0b, 0x49, 0x73, 0x73, 0x75, 0x65, 0x44, + 0x65, 0x76, 0x4a, 0x57, 0x54, 0x12, 0x23, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, + 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x73, 0x73, 0x75, 0x65, 0x44, 0x65, 0x76, + 0x4a, 0x57, 0x54, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x72, 0x69, 0x6c, + 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x73, 0x73, + 0x75, 0x65, 0x44, 0x65, 0x76, 0x4a, 0x57, 0x54, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x16, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x3a, 0x01, 0x2a, 0x22, 0x0b, 0x2f, 0x76, 0x31, + 0x2f, 0x64, 0x65, 0x76, 0x2d, 0x6a, 0x77, 0x74, 0x12, 0x9e, 0x01, 0x0a, 0x10, 0x41, 0x6e, 0x61, + 0x6c, 0x79, 0x7a, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x28, 0x2e, + 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x7a, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, + 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x7a, + 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x35, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2f, 0x12, 0x2d, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, - 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x67, 0x69, 0x74, 0x2f, 0x73, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x12, 0x96, 0x01, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x69, 0x74, 0x42, 0x72, - 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x12, 0x27, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, - 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x69, 0x74, - 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x28, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x69, 0x74, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x65, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x30, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x2a, 0x12, 0x28, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, - 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x67, - 0x69, 0x74, 0x2f, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x12, 0x85, 0x01, 0x0a, 0x09, - 0x47, 0x69, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x21, 0x2e, 0x72, 0x69, 0x6c, 0x6c, - 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, 0x74, 0x43, - 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x72, + 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, + 0x73, 0x2f, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x7a, 0x65, 0x12, 0x92, 0x01, 0x0a, 0x0e, 0x4c, 0x69, + 0x73, 0x74, 0x47, 0x69, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x26, 0x2e, 0x72, + 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x47, 0x69, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, + 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x69, 0x74, 0x43, 0x6f, + 0x6d, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2f, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x29, 0x12, 0x27, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, + 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, + 0x64, 0x7d, 0x2f, 0x67, 0x69, 0x74, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x82, + 0x01, 0x0a, 0x09, 0x47, 0x69, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x21, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, - 0x69, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x3a, 0x01, 0x2a, 0x22, 0x26, 0x2f, 0x76, 0x31, + 0x69, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x22, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x47, 0x69, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x28, 0x12, 0x26, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, - 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x67, 0x69, 0x74, 0x2f, 0x63, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x12, 0xa8, 0x01, 0x0a, 0x10, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x47, - 0x69, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x28, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, - 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x6f, - 0x72, 0x65, 0x47, 0x69, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x47, 0x69, 0x74, 0x43, - 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3f, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x39, 0x3a, 0x01, 0x2a, 0x22, 0x34, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, - 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, - 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x67, 0x69, 0x74, 0x2f, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x72, - 0x65, 0x2f, 0x7b, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x73, 0x68, 0x61, 0x7d, 0x12, 0x99, - 0x01, 0x0a, 0x10, 0x47, 0x69, 0x74, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x54, 0x6f, 0x42, 0x72, 0x61, - 0x6e, 0x63, 0x68, 0x12, 0x28, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, - 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, 0x74, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x54, 0x6f, - 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, + 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x67, 0x69, 0x74, 0x2f, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x12, 0x96, 0x01, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x69, 0x74, 0x42, + 0x72, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x12, 0x27, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, + 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x69, + 0x74, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x28, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x69, 0x74, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, + 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x30, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x2a, 0x12, 0x28, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, + 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, + 0x67, 0x69, 0x74, 0x2f, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x12, 0x85, 0x01, 0x0a, + 0x09, 0x47, 0x69, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x21, 0x2e, 0x72, 0x69, 0x6c, + 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, 0x74, + 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x47, 0x69, 0x74, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x54, 0x6f, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x30, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2a, - 0x3a, 0x01, 0x2a, 0x22, 0x25, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, - 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, - 0x2f, 0x67, 0x69, 0x74, 0x2f, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x12, 0xa0, 0x01, 0x0a, 0x0f, 0x47, - 0x69, 0x74, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x27, - 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x47, 0x69, 0x74, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, - 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, 0x74, 0x53, 0x77, 0x69, - 0x74, 0x63, 0x68, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x3a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x34, 0x3a, 0x01, 0x2a, 0x22, 0x2f, 0x2f, 0x76, + 0x47, 0x69, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x3a, 0x01, 0x2a, 0x22, 0x26, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, - 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x67, 0x69, 0x74, 0x2f, 0x62, 0x72, - 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x2f, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x12, 0x7d, 0x0a, - 0x07, 0x47, 0x69, 0x74, 0x50, 0x75, 0x6c, 0x6c, 0x12, 0x1f, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, + 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x67, 0x69, 0x74, 0x2f, 0x63, 0x6f, + 0x6d, 0x6d, 0x69, 0x74, 0x12, 0xa8, 0x01, 0x0a, 0x10, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, + 0x47, 0x69, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x28, 0x2e, 0x72, 0x69, 0x6c, 0x6c, + 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x74, + 0x6f, 0x72, 0x65, 0x47, 0x69, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, + 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x47, 0x69, 0x74, + 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3f, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x39, 0x3a, 0x01, 0x2a, 0x22, 0x34, 0x2f, 0x76, 0x31, 0x2f, 0x69, + 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, + 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x67, 0x69, 0x74, 0x2f, 0x72, 0x65, 0x73, 0x74, 0x6f, + 0x72, 0x65, 0x2f, 0x7b, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x73, 0x68, 0x61, 0x7d, 0x12, + 0x99, 0x01, 0x0a, 0x10, 0x47, 0x69, 0x74, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x54, 0x6f, 0x42, 0x72, + 0x61, 0x6e, 0x63, 0x68, 0x12, 0x28, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, + 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, 0x74, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x54, + 0x6f, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, + 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x47, 0x69, 0x74, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x54, 0x6f, 0x42, 0x72, 0x61, 0x6e, 0x63, + 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x30, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x2a, 0x3a, 0x01, 0x2a, 0x22, 0x25, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, + 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, + 0x7d, 0x2f, 0x67, 0x69, 0x74, 0x2f, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x12, 0xa0, 0x01, 0x0a, 0x0f, + 0x47, 0x69, 0x74, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, + 0x27, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x47, 0x69, 0x74, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x42, 0x72, 0x61, 0x6e, 0x63, + 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, + 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, 0x74, 0x53, 0x77, + 0x69, 0x74, 0x63, 0x68, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x3a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x34, 0x3a, 0x01, 0x2a, 0x22, 0x2f, 0x2f, + 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, + 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x67, 0x69, 0x74, 0x2f, 0x62, + 0x72, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x2f, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x12, 0x7d, + 0x0a, 0x07, 0x47, 0x69, 0x74, 0x50, 0x75, 0x6c, 0x6c, 0x12, 0x1f, 0x2e, 0x72, 0x69, 0x6c, 0x6c, + 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, 0x74, 0x50, + 0x75, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x72, 0x69, 0x6c, + 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, 0x74, + 0x50, 0x75, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2f, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x29, 0x3a, 0x01, 0x2a, 0x22, 0x24, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, + 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, + 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x67, 0x69, 0x74, 0x2f, 0x70, 0x75, 0x6c, 0x6c, 0x12, 0x7d, 0x0a, + 0x07, 0x47, 0x69, 0x74, 0x50, 0x75, 0x73, 0x68, 0x12, 0x1f, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, 0x74, 0x50, 0x75, - 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x72, 0x69, 0x6c, 0x6c, + 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, 0x74, 0x50, - 0x75, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2f, 0x82, 0xd3, 0xe4, + 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x29, 0x3a, 0x01, 0x2a, 0x22, 0x24, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, - 0x69, 0x64, 0x7d, 0x2f, 0x67, 0x69, 0x74, 0x2f, 0x70, 0x75, 0x6c, 0x6c, 0x12, 0x7d, 0x0a, 0x07, - 0x47, 0x69, 0x74, 0x50, 0x75, 0x73, 0x68, 0x12, 0x1f, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, - 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, 0x74, 0x50, 0x75, 0x73, - 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, - 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, 0x74, 0x50, 0x75, - 0x73, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2f, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x29, 0x3a, 0x01, 0x2a, 0x22, 0x24, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, - 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, - 0x64, 0x7d, 0x2f, 0x67, 0x69, 0x74, 0x2f, 0x70, 0x75, 0x73, 0x68, 0x42, 0xbb, 0x01, 0x0a, 0x13, - 0x63, 0x6f, 0x6d, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, - 0x2e, 0x76, 0x31, 0x42, 0x08, 0x41, 0x70, 0x69, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, - 0x3c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x69, 0x6c, 0x6c, - 0x64, 0x61, 0x74, 0x61, 0x2f, 0x72, 0x69, 0x6c, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, - 0x67, 0x65, 0x6e, 0x2f, 0x72, 0x69, 0x6c, 0x6c, 0x2f, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, - 0x2f, 0x76, 0x31, 0x3b, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x76, 0x31, 0xa2, 0x02, 0x03, - 0x52, 0x52, 0x58, 0xaa, 0x02, 0x0f, 0x52, 0x69, 0x6c, 0x6c, 0x2e, 0x52, 0x75, 0x6e, 0x74, 0x69, - 0x6d, 0x65, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0f, 0x52, 0x69, 0x6c, 0x6c, 0x5c, 0x52, 0x75, 0x6e, - 0x74, 0x69, 0x6d, 0x65, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x1b, 0x52, 0x69, 0x6c, 0x6c, 0x5c, 0x52, - 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x11, 0x52, 0x69, 0x6c, 0x6c, 0x3a, 0x3a, 0x52, 0x75, - 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x69, 0x64, 0x7d, 0x2f, 0x67, 0x69, 0x74, 0x2f, 0x70, 0x75, 0x73, 0x68, 0x42, 0xbb, 0x01, 0x0a, + 0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x72, 0x69, 0x6c, 0x6c, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, + 0x65, 0x2e, 0x76, 0x31, 0x42, 0x08, 0x41, 0x70, 0x69, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, + 0x5a, 0x3c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x69, 0x6c, + 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2f, 0x72, 0x69, 0x6c, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x72, 0x69, 0x6c, 0x6c, 0x2f, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, + 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x76, 0x31, 0xa2, 0x02, + 0x03, 0x52, 0x52, 0x58, 0xaa, 0x02, 0x0f, 0x52, 0x69, 0x6c, 0x6c, 0x2e, 0x52, 0x75, 0x6e, 0x74, + 0x69, 0x6d, 0x65, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0f, 0x52, 0x69, 0x6c, 0x6c, 0x5c, 0x52, 0x75, + 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x1b, 0x52, 0x69, 0x6c, 0x6c, 0x5c, + 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x11, 0x52, 0x69, 0x6c, 0x6c, 0x3a, 0x3a, 0x52, + 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( @@ -9739,7 +10507,7 @@ func file_rill_runtime_v1_api_proto_rawDescGZIP() []byte { } var file_rill_runtime_v1_api_proto_enumTypes = make([]protoimpl.EnumInfo, 4) -var file_rill_runtime_v1_api_proto_msgTypes = make([]protoimpl.MessageInfo, 132) +var file_rill_runtime_v1_api_proto_msgTypes = make([]protoimpl.MessageInfo, 143) var file_rill_runtime_v1_api_proto_goTypes = []any{ (FileEvent)(0), // 0: rill.runtime.v1.FileEvent (LogLevel)(0), // 1: rill.runtime.v1.LogLevel @@ -9792,306 +10560,331 @@ var file_rill_runtime_v1_api_proto_goTypes = []any{ (*GenerateMetricsViewFileResponse)(nil), // 48: rill.runtime.v1.GenerateMetricsViewFileResponse (*GenerateCanvasFileRequest)(nil), // 49: rill.runtime.v1.GenerateCanvasFileRequest (*GenerateCanvasFileResponse)(nil), // 50: rill.runtime.v1.GenerateCanvasFileResponse - (*QueryResolverRequest)(nil), // 51: rill.runtime.v1.QueryResolverRequest - (*QueryResolverResponse)(nil), // 52: rill.runtime.v1.QueryResolverResponse - (*Log)(nil), // 53: rill.runtime.v1.Log - (*ModelPartition)(nil), // 54: rill.runtime.v1.ModelPartition - (*GetLogsRequest)(nil), // 55: rill.runtime.v1.GetLogsRequest - (*GetLogsResponse)(nil), // 56: rill.runtime.v1.GetLogsResponse - (*WatchLogsRequest)(nil), // 57: rill.runtime.v1.WatchLogsRequest - (*WatchLogsResponse)(nil), // 58: rill.runtime.v1.WatchLogsResponse - (*ListResourcesRequest)(nil), // 59: rill.runtime.v1.ListResourcesRequest - (*ListResourcesResponse)(nil), // 60: rill.runtime.v1.ListResourcesResponse - (*WatchResourcesRequest)(nil), // 61: rill.runtime.v1.WatchResourcesRequest - (*WatchResourcesResponse)(nil), // 62: rill.runtime.v1.WatchResourcesResponse - (*GetResourceRequest)(nil), // 63: rill.runtime.v1.GetResourceRequest - (*GetResourceResponse)(nil), // 64: rill.runtime.v1.GetResourceResponse - (*GetExploreRequest)(nil), // 65: rill.runtime.v1.GetExploreRequest - (*GetExploreResponse)(nil), // 66: rill.runtime.v1.GetExploreResponse - (*GetModelPartitionsRequest)(nil), // 67: rill.runtime.v1.GetModelPartitionsRequest - (*GetModelPartitionsResponse)(nil), // 68: rill.runtime.v1.GetModelPartitionsResponse - (*CreateTriggerRequest)(nil), // 69: rill.runtime.v1.CreateTriggerRequest - (*CreateTriggerResponse)(nil), // 70: rill.runtime.v1.CreateTriggerResponse - (*ConnectorDriver)(nil), // 71: rill.runtime.v1.ConnectorDriver - (*AnalyzedConnector)(nil), // 72: rill.runtime.v1.AnalyzedConnector - (*ListConnectorDriversRequest)(nil), // 73: rill.runtime.v1.ListConnectorDriversRequest - (*ListConnectorDriversResponse)(nil), // 74: rill.runtime.v1.ListConnectorDriversResponse - (*AnalyzeConnectorsRequest)(nil), // 75: rill.runtime.v1.AnalyzeConnectorsRequest - (*AnalyzeConnectorsResponse)(nil), // 76: rill.runtime.v1.AnalyzeConnectorsResponse - (*ListNotifierConnectorsRequest)(nil), // 77: rill.runtime.v1.ListNotifierConnectorsRequest - (*ListNotifierConnectorsResponse)(nil), // 78: rill.runtime.v1.ListNotifierConnectorsResponse - (*Conversation)(nil), // 79: rill.runtime.v1.Conversation - (*Message)(nil), // 80: rill.runtime.v1.Message - (*AnalystAgentContext)(nil), // 81: rill.runtime.v1.AnalystAgentContext - (*DeveloperAgentContext)(nil), // 82: rill.runtime.v1.DeveloperAgentContext - (*FeedbackAgentContext)(nil), // 83: rill.runtime.v1.FeedbackAgentContext - (*ListConversationsRequest)(nil), // 84: rill.runtime.v1.ListConversationsRequest - (*ListConversationsResponse)(nil), // 85: rill.runtime.v1.ListConversationsResponse - (*GetConversationRequest)(nil), // 86: rill.runtime.v1.GetConversationRequest - (*GetConversationResponse)(nil), // 87: rill.runtime.v1.GetConversationResponse - (*ShareConversationRequest)(nil), // 88: rill.runtime.v1.ShareConversationRequest - (*ShareConversationResponse)(nil), // 89: rill.runtime.v1.ShareConversationResponse - (*ForkConversationRequest)(nil), // 90: rill.runtime.v1.ForkConversationRequest - (*ForkConversationResponse)(nil), // 91: rill.runtime.v1.ForkConversationResponse - (*ListToolsRequest)(nil), // 92: rill.runtime.v1.ListToolsRequest - (*ListToolsResponse)(nil), // 93: rill.runtime.v1.ListToolsResponse - (*CompleteRequest)(nil), // 94: rill.runtime.v1.CompleteRequest - (*CompleteResponse)(nil), // 95: rill.runtime.v1.CompleteResponse - (*CompleteStreamingRequest)(nil), // 96: rill.runtime.v1.CompleteStreamingRequest - (*CompleteStreamingResponse)(nil), // 97: rill.runtime.v1.CompleteStreamingResponse - (*GetAIMessageRequest)(nil), // 98: rill.runtime.v1.GetAIMessageRequest - (*GetAIMessageResponse)(nil), // 99: rill.runtime.v1.GetAIMessageResponse - (*IssueDevJWTRequest)(nil), // 100: rill.runtime.v1.IssueDevJWTRequest - (*IssueDevJWTResponse)(nil), // 101: rill.runtime.v1.IssueDevJWTResponse - (*AnalyzeVariablesRequest)(nil), // 102: rill.runtime.v1.AnalyzeVariablesRequest - (*AnalyzeVariablesResponse)(nil), // 103: rill.runtime.v1.AnalyzeVariablesResponse - (*AnalyzedVariable)(nil), // 104: rill.runtime.v1.AnalyzedVariable - (*ListGitCommitsRequest)(nil), // 105: rill.runtime.v1.ListGitCommitsRequest - (*ListGitCommitsResponse)(nil), // 106: rill.runtime.v1.ListGitCommitsResponse - (*GitCommit)(nil), // 107: rill.runtime.v1.GitCommit - (*GitStatusRequest)(nil), // 108: rill.runtime.v1.GitStatusRequest - (*GitStatusResponse)(nil), // 109: rill.runtime.v1.GitStatusResponse - (*ListGitBranchesRequest)(nil), // 110: rill.runtime.v1.ListGitBranchesRequest - (*ListGitBranchesResponse)(nil), // 111: rill.runtime.v1.ListGitBranchesResponse - (*GitBranch)(nil), // 112: rill.runtime.v1.GitBranch - (*GitCommitRequest)(nil), // 113: rill.runtime.v1.GitCommitRequest - (*GitCommitResponse)(nil), // 114: rill.runtime.v1.GitCommitResponse - (*RestoreGitCommitRequest)(nil), // 115: rill.runtime.v1.RestoreGitCommitRequest - (*RestoreGitCommitResponse)(nil), // 116: rill.runtime.v1.RestoreGitCommitResponse - (*GitMergeToBranchRequest)(nil), // 117: rill.runtime.v1.GitMergeToBranchRequest - (*GitMergeToBranchResponse)(nil), // 118: rill.runtime.v1.GitMergeToBranchResponse - (*GitSwitchBranchRequest)(nil), // 119: rill.runtime.v1.GitSwitchBranchRequest - (*GitSwitchBranchResponse)(nil), // 120: rill.runtime.v1.GitSwitchBranchResponse - (*GitPullRequest)(nil), // 121: rill.runtime.v1.GitPullRequest - (*GitPullResponse)(nil), // 122: rill.runtime.v1.GitPullResponse - (*GitPushRequest)(nil), // 123: rill.runtime.v1.GitPushRequest - (*GitPushResponse)(nil), // 124: rill.runtime.v1.GitPushResponse - nil, // 125: rill.runtime.v1.HealthResponse.InstancesHealthEntry - nil, // 126: rill.runtime.v1.InstanceHealth.MetricsViewErrorsEntry - nil, // 127: rill.runtime.v1.Instance.VariablesEntry - nil, // 128: rill.runtime.v1.Instance.ProjectVariablesEntry - nil, // 129: rill.runtime.v1.Instance.FeatureFlagsEntry - nil, // 130: rill.runtime.v1.Instance.AnnotationsEntry - nil, // 131: rill.runtime.v1.CreateInstanceRequest.VariablesEntry - nil, // 132: rill.runtime.v1.CreateInstanceRequest.AnnotationsEntry - (*ConnectorDriver_Property)(nil), // 133: rill.runtime.v1.ConnectorDriver.Property - nil, // 134: rill.runtime.v1.AnalyzedConnector.EnvConfigEntry - nil, // 135: rill.runtime.v1.AnalystAgentContext.WherePerMetricsViewEntry - (*timestamppb.Timestamp)(nil), // 136: google.protobuf.Timestamp - (*structpb.Struct)(nil), // 137: google.protobuf.Struct - (*StructType)(nil), // 138: rill.runtime.v1.StructType - (*Resource)(nil), // 139: rill.runtime.v1.Resource - (*ResourceName)(nil), // 140: rill.runtime.v1.ResourceName - (*RefreshModelTrigger)(nil), // 141: rill.runtime.v1.RefreshModelTrigger - (*v1.ContentBlock)(nil), // 142: rill.ai.v1.ContentBlock - (*Expression)(nil), // 143: rill.runtime.v1.Expression - (*v1.Tool)(nil), // 144: rill.ai.v1.Tool + (*GenerateTemplateRequest)(nil), // 51: rill.runtime.v1.GenerateTemplateRequest + (*GenerateTemplateResponse)(nil), // 52: rill.runtime.v1.GenerateTemplateResponse + (*Template)(nil), // 53: rill.runtime.v1.Template + (*TemplateFile)(nil), // 54: rill.runtime.v1.TemplateFile + (*ListTemplatesRequest)(nil), // 55: rill.runtime.v1.ListTemplatesRequest + (*ListTemplatesResponse)(nil), // 56: rill.runtime.v1.ListTemplatesResponse + (*GenerateFileRequest)(nil), // 57: rill.runtime.v1.GenerateFileRequest + (*GenerateFileResponse)(nil), // 58: rill.runtime.v1.GenerateFileResponse + (*GeneratedFile)(nil), // 59: rill.runtime.v1.GeneratedFile + (*QueryResolverRequest)(nil), // 60: rill.runtime.v1.QueryResolverRequest + (*QueryResolverResponse)(nil), // 61: rill.runtime.v1.QueryResolverResponse + (*Log)(nil), // 62: rill.runtime.v1.Log + (*ModelPartition)(nil), // 63: rill.runtime.v1.ModelPartition + (*GetLogsRequest)(nil), // 64: rill.runtime.v1.GetLogsRequest + (*GetLogsResponse)(nil), // 65: rill.runtime.v1.GetLogsResponse + (*WatchLogsRequest)(nil), // 66: rill.runtime.v1.WatchLogsRequest + (*WatchLogsResponse)(nil), // 67: rill.runtime.v1.WatchLogsResponse + (*ListResourcesRequest)(nil), // 68: rill.runtime.v1.ListResourcesRequest + (*ListResourcesResponse)(nil), // 69: rill.runtime.v1.ListResourcesResponse + (*WatchResourcesRequest)(nil), // 70: rill.runtime.v1.WatchResourcesRequest + (*WatchResourcesResponse)(nil), // 71: rill.runtime.v1.WatchResourcesResponse + (*GetResourceRequest)(nil), // 72: rill.runtime.v1.GetResourceRequest + (*GetResourceResponse)(nil), // 73: rill.runtime.v1.GetResourceResponse + (*GetExploreRequest)(nil), // 74: rill.runtime.v1.GetExploreRequest + (*GetExploreResponse)(nil), // 75: rill.runtime.v1.GetExploreResponse + (*GetModelPartitionsRequest)(nil), // 76: rill.runtime.v1.GetModelPartitionsRequest + (*GetModelPartitionsResponse)(nil), // 77: rill.runtime.v1.GetModelPartitionsResponse + (*CreateTriggerRequest)(nil), // 78: rill.runtime.v1.CreateTriggerRequest + (*CreateTriggerResponse)(nil), // 79: rill.runtime.v1.CreateTriggerResponse + (*ConnectorDriver)(nil), // 80: rill.runtime.v1.ConnectorDriver + (*AnalyzedConnector)(nil), // 81: rill.runtime.v1.AnalyzedConnector + (*ListConnectorDriversRequest)(nil), // 82: rill.runtime.v1.ListConnectorDriversRequest + (*ListConnectorDriversResponse)(nil), // 83: rill.runtime.v1.ListConnectorDriversResponse + (*AnalyzeConnectorsRequest)(nil), // 84: rill.runtime.v1.AnalyzeConnectorsRequest + (*AnalyzeConnectorsResponse)(nil), // 85: rill.runtime.v1.AnalyzeConnectorsResponse + (*ListNotifierConnectorsRequest)(nil), // 86: rill.runtime.v1.ListNotifierConnectorsRequest + (*ListNotifierConnectorsResponse)(nil), // 87: rill.runtime.v1.ListNotifierConnectorsResponse + (*Conversation)(nil), // 88: rill.runtime.v1.Conversation + (*Message)(nil), // 89: rill.runtime.v1.Message + (*AnalystAgentContext)(nil), // 90: rill.runtime.v1.AnalystAgentContext + (*DeveloperAgentContext)(nil), // 91: rill.runtime.v1.DeveloperAgentContext + (*FeedbackAgentContext)(nil), // 92: rill.runtime.v1.FeedbackAgentContext + (*ListConversationsRequest)(nil), // 93: rill.runtime.v1.ListConversationsRequest + (*ListConversationsResponse)(nil), // 94: rill.runtime.v1.ListConversationsResponse + (*GetConversationRequest)(nil), // 95: rill.runtime.v1.GetConversationRequest + (*GetConversationResponse)(nil), // 96: rill.runtime.v1.GetConversationResponse + (*ShareConversationRequest)(nil), // 97: rill.runtime.v1.ShareConversationRequest + (*ShareConversationResponse)(nil), // 98: rill.runtime.v1.ShareConversationResponse + (*ForkConversationRequest)(nil), // 99: rill.runtime.v1.ForkConversationRequest + (*ForkConversationResponse)(nil), // 100: rill.runtime.v1.ForkConversationResponse + (*ListToolsRequest)(nil), // 101: rill.runtime.v1.ListToolsRequest + (*ListToolsResponse)(nil), // 102: rill.runtime.v1.ListToolsResponse + (*CompleteRequest)(nil), // 103: rill.runtime.v1.CompleteRequest + (*CompleteResponse)(nil), // 104: rill.runtime.v1.CompleteResponse + (*CompleteStreamingRequest)(nil), // 105: rill.runtime.v1.CompleteStreamingRequest + (*CompleteStreamingResponse)(nil), // 106: rill.runtime.v1.CompleteStreamingResponse + (*GetAIMessageRequest)(nil), // 107: rill.runtime.v1.GetAIMessageRequest + (*GetAIMessageResponse)(nil), // 108: rill.runtime.v1.GetAIMessageResponse + (*IssueDevJWTRequest)(nil), // 109: rill.runtime.v1.IssueDevJWTRequest + (*IssueDevJWTResponse)(nil), // 110: rill.runtime.v1.IssueDevJWTResponse + (*AnalyzeVariablesRequest)(nil), // 111: rill.runtime.v1.AnalyzeVariablesRequest + (*AnalyzeVariablesResponse)(nil), // 112: rill.runtime.v1.AnalyzeVariablesResponse + (*AnalyzedVariable)(nil), // 113: rill.runtime.v1.AnalyzedVariable + (*ListGitCommitsRequest)(nil), // 114: rill.runtime.v1.ListGitCommitsRequest + (*ListGitCommitsResponse)(nil), // 115: rill.runtime.v1.ListGitCommitsResponse + (*GitCommit)(nil), // 116: rill.runtime.v1.GitCommit + (*GitStatusRequest)(nil), // 117: rill.runtime.v1.GitStatusRequest + (*GitStatusResponse)(nil), // 118: rill.runtime.v1.GitStatusResponse + (*ListGitBranchesRequest)(nil), // 119: rill.runtime.v1.ListGitBranchesRequest + (*ListGitBranchesResponse)(nil), // 120: rill.runtime.v1.ListGitBranchesResponse + (*GitBranch)(nil), // 121: rill.runtime.v1.GitBranch + (*GitCommitRequest)(nil), // 122: rill.runtime.v1.GitCommitRequest + (*GitCommitResponse)(nil), // 123: rill.runtime.v1.GitCommitResponse + (*RestoreGitCommitRequest)(nil), // 124: rill.runtime.v1.RestoreGitCommitRequest + (*RestoreGitCommitResponse)(nil), // 125: rill.runtime.v1.RestoreGitCommitResponse + (*GitMergeToBranchRequest)(nil), // 126: rill.runtime.v1.GitMergeToBranchRequest + (*GitMergeToBranchResponse)(nil), // 127: rill.runtime.v1.GitMergeToBranchResponse + (*GitSwitchBranchRequest)(nil), // 128: rill.runtime.v1.GitSwitchBranchRequest + (*GitSwitchBranchResponse)(nil), // 129: rill.runtime.v1.GitSwitchBranchResponse + (*GitPullRequest)(nil), // 130: rill.runtime.v1.GitPullRequest + (*GitPullResponse)(nil), // 131: rill.runtime.v1.GitPullResponse + (*GitPushRequest)(nil), // 132: rill.runtime.v1.GitPushRequest + (*GitPushResponse)(nil), // 133: rill.runtime.v1.GitPushResponse + nil, // 134: rill.runtime.v1.HealthResponse.InstancesHealthEntry + nil, // 135: rill.runtime.v1.InstanceHealth.MetricsViewErrorsEntry + nil, // 136: rill.runtime.v1.Instance.VariablesEntry + nil, // 137: rill.runtime.v1.Instance.ProjectVariablesEntry + nil, // 138: rill.runtime.v1.Instance.FeatureFlagsEntry + nil, // 139: rill.runtime.v1.Instance.AnnotationsEntry + nil, // 140: rill.runtime.v1.CreateInstanceRequest.VariablesEntry + nil, // 141: rill.runtime.v1.CreateInstanceRequest.AnnotationsEntry + nil, // 142: rill.runtime.v1.GenerateTemplateResponse.EnvVarsEntry + nil, // 143: rill.runtime.v1.GenerateFileResponse.EnvVarsEntry + (*ConnectorDriver_Property)(nil), // 144: rill.runtime.v1.ConnectorDriver.Property + nil, // 145: rill.runtime.v1.AnalyzedConnector.EnvConfigEntry + nil, // 146: rill.runtime.v1.AnalystAgentContext.WherePerMetricsViewEntry + (*timestamppb.Timestamp)(nil), // 147: google.protobuf.Timestamp + (*structpb.Struct)(nil), // 148: google.protobuf.Struct + (*StructType)(nil), // 149: rill.runtime.v1.StructType + (*Resource)(nil), // 150: rill.runtime.v1.Resource + (*ResourceName)(nil), // 151: rill.runtime.v1.ResourceName + (*RefreshModelTrigger)(nil), // 152: rill.runtime.v1.RefreshModelTrigger + (*v1.ContentBlock)(nil), // 153: rill.ai.v1.ContentBlock + (*Expression)(nil), // 154: rill.runtime.v1.Expression + (*v1.Tool)(nil), // 155: rill.ai.v1.Tool } var file_rill_runtime_v1_api_proto_depIdxs = []int32{ - 136, // 0: rill.runtime.v1.PingResponse.time:type_name -> google.protobuf.Timestamp - 125, // 1: rill.runtime.v1.HealthResponse.instances_health:type_name -> rill.runtime.v1.HealthResponse.InstancesHealthEntry + 147, // 0: rill.runtime.v1.PingResponse.time:type_name -> google.protobuf.Timestamp + 134, // 1: rill.runtime.v1.HealthResponse.instances_health:type_name -> rill.runtime.v1.HealthResponse.InstancesHealthEntry 10, // 2: rill.runtime.v1.InstanceHealthResponse.instance_health:type_name -> rill.runtime.v1.InstanceHealth - 126, // 3: rill.runtime.v1.InstanceHealth.metrics_view_errors:type_name -> rill.runtime.v1.InstanceHealth.MetricsViewErrorsEntry - 136, // 4: rill.runtime.v1.Instance.created_on:type_name -> google.protobuf.Timestamp - 136, // 5: rill.runtime.v1.Instance.updated_on:type_name -> google.protobuf.Timestamp + 135, // 3: rill.runtime.v1.InstanceHealth.metrics_view_errors:type_name -> rill.runtime.v1.InstanceHealth.MetricsViewErrorsEntry + 147, // 4: rill.runtime.v1.Instance.created_on:type_name -> google.protobuf.Timestamp + 147, // 5: rill.runtime.v1.Instance.updated_on:type_name -> google.protobuf.Timestamp 12, // 6: rill.runtime.v1.Instance.connectors:type_name -> rill.runtime.v1.Connector 12, // 7: rill.runtime.v1.Instance.project_connectors:type_name -> rill.runtime.v1.Connector - 127, // 8: rill.runtime.v1.Instance.variables:type_name -> rill.runtime.v1.Instance.VariablesEntry - 128, // 9: rill.runtime.v1.Instance.project_variables:type_name -> rill.runtime.v1.Instance.ProjectVariablesEntry - 129, // 10: rill.runtime.v1.Instance.feature_flags:type_name -> rill.runtime.v1.Instance.FeatureFlagsEntry - 130, // 11: rill.runtime.v1.Instance.annotations:type_name -> rill.runtime.v1.Instance.AnnotationsEntry - 137, // 12: rill.runtime.v1.Connector.config:type_name -> google.protobuf.Struct - 137, // 13: rill.runtime.v1.Connector.provision_args:type_name -> google.protobuf.Struct + 136, // 8: rill.runtime.v1.Instance.variables:type_name -> rill.runtime.v1.Instance.VariablesEntry + 137, // 9: rill.runtime.v1.Instance.project_variables:type_name -> rill.runtime.v1.Instance.ProjectVariablesEntry + 138, // 10: rill.runtime.v1.Instance.feature_flags:type_name -> rill.runtime.v1.Instance.FeatureFlagsEntry + 139, // 11: rill.runtime.v1.Instance.annotations:type_name -> rill.runtime.v1.Instance.AnnotationsEntry + 148, // 12: rill.runtime.v1.Connector.config:type_name -> google.protobuf.Struct + 148, // 13: rill.runtime.v1.Connector.provision_args:type_name -> google.protobuf.Struct 11, // 14: rill.runtime.v1.ListInstancesResponse.instances:type_name -> rill.runtime.v1.Instance 11, // 15: rill.runtime.v1.GetInstanceResponse.instance:type_name -> rill.runtime.v1.Instance 12, // 16: rill.runtime.v1.CreateInstanceRequest.connectors:type_name -> rill.runtime.v1.Connector - 131, // 17: rill.runtime.v1.CreateInstanceRequest.variables:type_name -> rill.runtime.v1.CreateInstanceRequest.VariablesEntry - 132, // 18: rill.runtime.v1.CreateInstanceRequest.annotations:type_name -> rill.runtime.v1.CreateInstanceRequest.AnnotationsEntry + 140, // 17: rill.runtime.v1.CreateInstanceRequest.variables:type_name -> rill.runtime.v1.CreateInstanceRequest.VariablesEntry + 141, // 18: rill.runtime.v1.CreateInstanceRequest.annotations:type_name -> rill.runtime.v1.CreateInstanceRequest.AnnotationsEntry 11, // 19: rill.runtime.v1.CreateInstanceResponse.instance:type_name -> rill.runtime.v1.Instance 12, // 20: rill.runtime.v1.EditInstanceRequest.connectors:type_name -> rill.runtime.v1.Connector 11, // 21: rill.runtime.v1.EditInstanceResponse.instance:type_name -> rill.runtime.v1.Instance 27, // 22: rill.runtime.v1.ListFilesResponse.files:type_name -> rill.runtime.v1.DirEntry 0, // 23: rill.runtime.v1.WatchFilesResponse.event:type_name -> rill.runtime.v1.FileEvent - 136, // 24: rill.runtime.v1.GetFileResponse.updated_on:type_name -> google.protobuf.Timestamp + 147, // 24: rill.runtime.v1.GetFileResponse.updated_on:type_name -> google.protobuf.Timestamp 40, // 25: rill.runtime.v1.ListExamplesResponse.examples:type_name -> rill.runtime.v1.Example - 137, // 26: rill.runtime.v1.QueryResolverRequest.resolver_properties:type_name -> google.protobuf.Struct - 137, // 27: rill.runtime.v1.QueryResolverRequest.resolver_args:type_name -> google.protobuf.Struct - 137, // 28: rill.runtime.v1.QueryResolverResponse.meta:type_name -> google.protobuf.Struct - 138, // 29: rill.runtime.v1.QueryResolverResponse.schema:type_name -> rill.runtime.v1.StructType - 137, // 30: rill.runtime.v1.QueryResolverResponse.data:type_name -> google.protobuf.Struct - 1, // 31: rill.runtime.v1.Log.level:type_name -> rill.runtime.v1.LogLevel - 136, // 32: rill.runtime.v1.Log.time:type_name -> google.protobuf.Timestamp - 137, // 33: rill.runtime.v1.ModelPartition.data:type_name -> google.protobuf.Struct - 136, // 34: rill.runtime.v1.ModelPartition.watermark:type_name -> google.protobuf.Timestamp - 136, // 35: rill.runtime.v1.ModelPartition.executed_on:type_name -> google.protobuf.Timestamp - 1, // 36: rill.runtime.v1.GetLogsRequest.level:type_name -> rill.runtime.v1.LogLevel - 53, // 37: rill.runtime.v1.GetLogsResponse.logs:type_name -> rill.runtime.v1.Log - 1, // 38: rill.runtime.v1.WatchLogsRequest.level:type_name -> rill.runtime.v1.LogLevel - 53, // 39: rill.runtime.v1.WatchLogsResponse.log:type_name -> rill.runtime.v1.Log - 139, // 40: rill.runtime.v1.ListResourcesResponse.resources:type_name -> rill.runtime.v1.Resource - 2, // 41: rill.runtime.v1.WatchResourcesResponse.event:type_name -> rill.runtime.v1.ResourceEvent - 140, // 42: rill.runtime.v1.WatchResourcesResponse.name:type_name -> rill.runtime.v1.ResourceName - 139, // 43: rill.runtime.v1.WatchResourcesResponse.resource:type_name -> rill.runtime.v1.Resource - 140, // 44: rill.runtime.v1.GetResourceRequest.name:type_name -> rill.runtime.v1.ResourceName - 139, // 45: rill.runtime.v1.GetResourceResponse.resource:type_name -> rill.runtime.v1.Resource - 139, // 46: rill.runtime.v1.GetExploreResponse.explore:type_name -> rill.runtime.v1.Resource - 139, // 47: rill.runtime.v1.GetExploreResponse.metrics_view:type_name -> rill.runtime.v1.Resource - 54, // 48: rill.runtime.v1.GetModelPartitionsResponse.partitions:type_name -> rill.runtime.v1.ModelPartition - 140, // 49: rill.runtime.v1.CreateTriggerRequest.resources:type_name -> rill.runtime.v1.ResourceName - 141, // 50: rill.runtime.v1.CreateTriggerRequest.models:type_name -> rill.runtime.v1.RefreshModelTrigger - 133, // 51: rill.runtime.v1.ConnectorDriver.config_properties:type_name -> rill.runtime.v1.ConnectorDriver.Property - 133, // 52: rill.runtime.v1.ConnectorDriver.source_properties:type_name -> rill.runtime.v1.ConnectorDriver.Property - 71, // 53: rill.runtime.v1.AnalyzedConnector.driver:type_name -> rill.runtime.v1.ConnectorDriver - 137, // 54: rill.runtime.v1.AnalyzedConnector.config:type_name -> google.protobuf.Struct - 137, // 55: rill.runtime.v1.AnalyzedConnector.preset_config:type_name -> google.protobuf.Struct - 137, // 56: rill.runtime.v1.AnalyzedConnector.project_config:type_name -> google.protobuf.Struct - 134, // 57: rill.runtime.v1.AnalyzedConnector.env_config:type_name -> rill.runtime.v1.AnalyzedConnector.EnvConfigEntry - 137, // 58: rill.runtime.v1.AnalyzedConnector.provision_args:type_name -> google.protobuf.Struct - 140, // 59: rill.runtime.v1.AnalyzedConnector.used_by:type_name -> rill.runtime.v1.ResourceName - 71, // 60: rill.runtime.v1.ListConnectorDriversResponse.connectors:type_name -> rill.runtime.v1.ConnectorDriver - 72, // 61: rill.runtime.v1.AnalyzeConnectorsResponse.connectors:type_name -> rill.runtime.v1.AnalyzedConnector - 12, // 62: rill.runtime.v1.ListNotifierConnectorsResponse.connectors:type_name -> rill.runtime.v1.Connector - 136, // 63: rill.runtime.v1.Conversation.created_on:type_name -> google.protobuf.Timestamp - 136, // 64: rill.runtime.v1.Conversation.updated_on:type_name -> google.protobuf.Timestamp - 80, // 65: rill.runtime.v1.Conversation.messages:type_name -> rill.runtime.v1.Message - 136, // 66: rill.runtime.v1.Message.created_on:type_name -> google.protobuf.Timestamp - 136, // 67: rill.runtime.v1.Message.updated_on:type_name -> google.protobuf.Timestamp - 142, // 68: rill.runtime.v1.Message.content:type_name -> rill.ai.v1.ContentBlock - 143, // 69: rill.runtime.v1.AnalystAgentContext.where:type_name -> rill.runtime.v1.Expression - 135, // 70: rill.runtime.v1.AnalystAgentContext.where_per_metrics_view:type_name -> rill.runtime.v1.AnalystAgentContext.WherePerMetricsViewEntry - 136, // 71: rill.runtime.v1.AnalystAgentContext.time_start:type_name -> google.protobuf.Timestamp - 136, // 72: rill.runtime.v1.AnalystAgentContext.time_end:type_name -> google.protobuf.Timestamp - 79, // 73: rill.runtime.v1.ListConversationsResponse.conversations:type_name -> rill.runtime.v1.Conversation - 79, // 74: rill.runtime.v1.GetConversationResponse.conversation:type_name -> rill.runtime.v1.Conversation - 80, // 75: rill.runtime.v1.GetConversationResponse.messages:type_name -> rill.runtime.v1.Message - 144, // 76: rill.runtime.v1.ListToolsResponse.tools:type_name -> rill.ai.v1.Tool - 81, // 77: rill.runtime.v1.CompleteRequest.analyst_agent_context:type_name -> rill.runtime.v1.AnalystAgentContext - 82, // 78: rill.runtime.v1.CompleteRequest.developer_agent_context:type_name -> rill.runtime.v1.DeveloperAgentContext - 83, // 79: rill.runtime.v1.CompleteRequest.feedback_agent_context:type_name -> rill.runtime.v1.FeedbackAgentContext - 80, // 80: rill.runtime.v1.CompleteResponse.messages:type_name -> rill.runtime.v1.Message - 81, // 81: rill.runtime.v1.CompleteStreamingRequest.analyst_agent_context:type_name -> rill.runtime.v1.AnalystAgentContext - 82, // 82: rill.runtime.v1.CompleteStreamingRequest.developer_agent_context:type_name -> rill.runtime.v1.DeveloperAgentContext - 83, // 83: rill.runtime.v1.CompleteStreamingRequest.feedback_agent_context:type_name -> rill.runtime.v1.FeedbackAgentContext - 80, // 84: rill.runtime.v1.CompleteStreamingResponse.message:type_name -> rill.runtime.v1.Message - 80, // 85: rill.runtime.v1.GetAIMessageResponse.message:type_name -> rill.runtime.v1.Message - 137, // 86: rill.runtime.v1.IssueDevJWTRequest.attributes:type_name -> google.protobuf.Struct - 104, // 87: rill.runtime.v1.AnalyzeVariablesResponse.variables:type_name -> rill.runtime.v1.AnalyzedVariable - 140, // 88: rill.runtime.v1.AnalyzedVariable.used_by:type_name -> rill.runtime.v1.ResourceName - 107, // 89: rill.runtime.v1.ListGitCommitsResponse.commits:type_name -> rill.runtime.v1.GitCommit - 136, // 90: rill.runtime.v1.GitCommit.committed_on:type_name -> google.protobuf.Timestamp - 112, // 91: rill.runtime.v1.ListGitBranchesResponse.branches:type_name -> rill.runtime.v1.GitBranch - 10, // 92: rill.runtime.v1.HealthResponse.InstancesHealthEntry.value:type_name -> rill.runtime.v1.InstanceHealth - 3, // 93: rill.runtime.v1.ConnectorDriver.Property.type:type_name -> rill.runtime.v1.ConnectorDriver.Property.Type - 143, // 94: rill.runtime.v1.AnalystAgentContext.WherePerMetricsViewEntry.value:type_name -> rill.runtime.v1.Expression - 4, // 95: rill.runtime.v1.RuntimeService.Ping:input_type -> rill.runtime.v1.PingRequest - 6, // 96: rill.runtime.v1.RuntimeService.Health:input_type -> rill.runtime.v1.HealthRequest - 8, // 97: rill.runtime.v1.RuntimeService.InstanceHealth:input_type -> rill.runtime.v1.InstanceHealthRequest - 13, // 98: rill.runtime.v1.RuntimeService.ListInstances:input_type -> rill.runtime.v1.ListInstancesRequest - 15, // 99: rill.runtime.v1.RuntimeService.GetInstance:input_type -> rill.runtime.v1.GetInstanceRequest - 17, // 100: rill.runtime.v1.RuntimeService.CreateInstance:input_type -> rill.runtime.v1.CreateInstanceRequest - 21, // 101: rill.runtime.v1.RuntimeService.EditInstance:input_type -> rill.runtime.v1.EditInstanceRequest - 19, // 102: rill.runtime.v1.RuntimeService.DeleteInstance:input_type -> rill.runtime.v1.DeleteInstanceRequest - 23, // 103: rill.runtime.v1.RuntimeService.ReloadConfig:input_type -> rill.runtime.v1.ReloadConfigRequest - 25, // 104: rill.runtime.v1.RuntimeService.ListFiles:input_type -> rill.runtime.v1.ListFilesRequest - 28, // 105: rill.runtime.v1.RuntimeService.WatchFiles:input_type -> rill.runtime.v1.WatchFilesRequest - 30, // 106: rill.runtime.v1.RuntimeService.GetFile:input_type -> rill.runtime.v1.GetFileRequest - 32, // 107: rill.runtime.v1.RuntimeService.PutFile:input_type -> rill.runtime.v1.PutFileRequest - 34, // 108: rill.runtime.v1.RuntimeService.CreateDirectory:input_type -> rill.runtime.v1.CreateDirectoryRequest - 36, // 109: rill.runtime.v1.RuntimeService.DeleteFile:input_type -> rill.runtime.v1.DeleteFileRequest - 38, // 110: rill.runtime.v1.RuntimeService.RenameFile:input_type -> rill.runtime.v1.RenameFileRequest - 41, // 111: rill.runtime.v1.RuntimeService.ListExamples:input_type -> rill.runtime.v1.ListExamplesRequest - 43, // 112: rill.runtime.v1.RuntimeService.UnpackExample:input_type -> rill.runtime.v1.UnpackExampleRequest - 45, // 113: rill.runtime.v1.RuntimeService.UnpackEmpty:input_type -> rill.runtime.v1.UnpackEmptyRequest - 47, // 114: rill.runtime.v1.RuntimeService.GenerateMetricsViewFile:input_type -> rill.runtime.v1.GenerateMetricsViewFileRequest - 49, // 115: rill.runtime.v1.RuntimeService.GenerateCanvasFile:input_type -> rill.runtime.v1.GenerateCanvasFileRequest - 51, // 116: rill.runtime.v1.RuntimeService.QueryResolver:input_type -> rill.runtime.v1.QueryResolverRequest - 55, // 117: rill.runtime.v1.RuntimeService.GetLogs:input_type -> rill.runtime.v1.GetLogsRequest - 57, // 118: rill.runtime.v1.RuntimeService.WatchLogs:input_type -> rill.runtime.v1.WatchLogsRequest - 59, // 119: rill.runtime.v1.RuntimeService.ListResources:input_type -> rill.runtime.v1.ListResourcesRequest - 61, // 120: rill.runtime.v1.RuntimeService.WatchResources:input_type -> rill.runtime.v1.WatchResourcesRequest - 63, // 121: rill.runtime.v1.RuntimeService.GetResource:input_type -> rill.runtime.v1.GetResourceRequest - 65, // 122: rill.runtime.v1.RuntimeService.GetExplore:input_type -> rill.runtime.v1.GetExploreRequest - 67, // 123: rill.runtime.v1.RuntimeService.GetModelPartitions:input_type -> rill.runtime.v1.GetModelPartitionsRequest - 69, // 124: rill.runtime.v1.RuntimeService.CreateTrigger:input_type -> rill.runtime.v1.CreateTriggerRequest - 73, // 125: rill.runtime.v1.RuntimeService.ListConnectorDrivers:input_type -> rill.runtime.v1.ListConnectorDriversRequest - 75, // 126: rill.runtime.v1.RuntimeService.AnalyzeConnectors:input_type -> rill.runtime.v1.AnalyzeConnectorsRequest - 77, // 127: rill.runtime.v1.RuntimeService.ListNotifierConnectors:input_type -> rill.runtime.v1.ListNotifierConnectorsRequest - 84, // 128: rill.runtime.v1.RuntimeService.ListConversations:input_type -> rill.runtime.v1.ListConversationsRequest - 86, // 129: rill.runtime.v1.RuntimeService.GetConversation:input_type -> rill.runtime.v1.GetConversationRequest - 88, // 130: rill.runtime.v1.RuntimeService.ShareConversation:input_type -> rill.runtime.v1.ShareConversationRequest - 90, // 131: rill.runtime.v1.RuntimeService.ForkConversation:input_type -> rill.runtime.v1.ForkConversationRequest - 92, // 132: rill.runtime.v1.RuntimeService.ListTools:input_type -> rill.runtime.v1.ListToolsRequest - 94, // 133: rill.runtime.v1.RuntimeService.Complete:input_type -> rill.runtime.v1.CompleteRequest - 96, // 134: rill.runtime.v1.RuntimeService.CompleteStreaming:input_type -> rill.runtime.v1.CompleteStreamingRequest - 98, // 135: rill.runtime.v1.RuntimeService.GetAIMessage:input_type -> rill.runtime.v1.GetAIMessageRequest - 100, // 136: rill.runtime.v1.RuntimeService.IssueDevJWT:input_type -> rill.runtime.v1.IssueDevJWTRequest - 102, // 137: rill.runtime.v1.RuntimeService.AnalyzeVariables:input_type -> rill.runtime.v1.AnalyzeVariablesRequest - 105, // 138: rill.runtime.v1.RuntimeService.ListGitCommits:input_type -> rill.runtime.v1.ListGitCommitsRequest - 108, // 139: rill.runtime.v1.RuntimeService.GitStatus:input_type -> rill.runtime.v1.GitStatusRequest - 110, // 140: rill.runtime.v1.RuntimeService.ListGitBranches:input_type -> rill.runtime.v1.ListGitBranchesRequest - 113, // 141: rill.runtime.v1.RuntimeService.GitCommit:input_type -> rill.runtime.v1.GitCommitRequest - 115, // 142: rill.runtime.v1.RuntimeService.RestoreGitCommit:input_type -> rill.runtime.v1.RestoreGitCommitRequest - 117, // 143: rill.runtime.v1.RuntimeService.GitMergeToBranch:input_type -> rill.runtime.v1.GitMergeToBranchRequest - 119, // 144: rill.runtime.v1.RuntimeService.GitSwitchBranch:input_type -> rill.runtime.v1.GitSwitchBranchRequest - 121, // 145: rill.runtime.v1.RuntimeService.GitPull:input_type -> rill.runtime.v1.GitPullRequest - 123, // 146: rill.runtime.v1.RuntimeService.GitPush:input_type -> rill.runtime.v1.GitPushRequest - 5, // 147: rill.runtime.v1.RuntimeService.Ping:output_type -> rill.runtime.v1.PingResponse - 7, // 148: rill.runtime.v1.RuntimeService.Health:output_type -> rill.runtime.v1.HealthResponse - 9, // 149: rill.runtime.v1.RuntimeService.InstanceHealth:output_type -> rill.runtime.v1.InstanceHealthResponse - 14, // 150: rill.runtime.v1.RuntimeService.ListInstances:output_type -> rill.runtime.v1.ListInstancesResponse - 16, // 151: rill.runtime.v1.RuntimeService.GetInstance:output_type -> rill.runtime.v1.GetInstanceResponse - 18, // 152: rill.runtime.v1.RuntimeService.CreateInstance:output_type -> rill.runtime.v1.CreateInstanceResponse - 22, // 153: rill.runtime.v1.RuntimeService.EditInstance:output_type -> rill.runtime.v1.EditInstanceResponse - 20, // 154: rill.runtime.v1.RuntimeService.DeleteInstance:output_type -> rill.runtime.v1.DeleteInstanceResponse - 24, // 155: rill.runtime.v1.RuntimeService.ReloadConfig:output_type -> rill.runtime.v1.ReloadConfigResponse - 26, // 156: rill.runtime.v1.RuntimeService.ListFiles:output_type -> rill.runtime.v1.ListFilesResponse - 29, // 157: rill.runtime.v1.RuntimeService.WatchFiles:output_type -> rill.runtime.v1.WatchFilesResponse - 31, // 158: rill.runtime.v1.RuntimeService.GetFile:output_type -> rill.runtime.v1.GetFileResponse - 33, // 159: rill.runtime.v1.RuntimeService.PutFile:output_type -> rill.runtime.v1.PutFileResponse - 35, // 160: rill.runtime.v1.RuntimeService.CreateDirectory:output_type -> rill.runtime.v1.CreateDirectoryResponse - 37, // 161: rill.runtime.v1.RuntimeService.DeleteFile:output_type -> rill.runtime.v1.DeleteFileResponse - 39, // 162: rill.runtime.v1.RuntimeService.RenameFile:output_type -> rill.runtime.v1.RenameFileResponse - 42, // 163: rill.runtime.v1.RuntimeService.ListExamples:output_type -> rill.runtime.v1.ListExamplesResponse - 44, // 164: rill.runtime.v1.RuntimeService.UnpackExample:output_type -> rill.runtime.v1.UnpackExampleResponse - 46, // 165: rill.runtime.v1.RuntimeService.UnpackEmpty:output_type -> rill.runtime.v1.UnpackEmptyResponse - 48, // 166: rill.runtime.v1.RuntimeService.GenerateMetricsViewFile:output_type -> rill.runtime.v1.GenerateMetricsViewFileResponse - 50, // 167: rill.runtime.v1.RuntimeService.GenerateCanvasFile:output_type -> rill.runtime.v1.GenerateCanvasFileResponse - 52, // 168: rill.runtime.v1.RuntimeService.QueryResolver:output_type -> rill.runtime.v1.QueryResolverResponse - 56, // 169: rill.runtime.v1.RuntimeService.GetLogs:output_type -> rill.runtime.v1.GetLogsResponse - 58, // 170: rill.runtime.v1.RuntimeService.WatchLogs:output_type -> rill.runtime.v1.WatchLogsResponse - 60, // 171: rill.runtime.v1.RuntimeService.ListResources:output_type -> rill.runtime.v1.ListResourcesResponse - 62, // 172: rill.runtime.v1.RuntimeService.WatchResources:output_type -> rill.runtime.v1.WatchResourcesResponse - 64, // 173: rill.runtime.v1.RuntimeService.GetResource:output_type -> rill.runtime.v1.GetResourceResponse - 66, // 174: rill.runtime.v1.RuntimeService.GetExplore:output_type -> rill.runtime.v1.GetExploreResponse - 68, // 175: rill.runtime.v1.RuntimeService.GetModelPartitions:output_type -> rill.runtime.v1.GetModelPartitionsResponse - 70, // 176: rill.runtime.v1.RuntimeService.CreateTrigger:output_type -> rill.runtime.v1.CreateTriggerResponse - 74, // 177: rill.runtime.v1.RuntimeService.ListConnectorDrivers:output_type -> rill.runtime.v1.ListConnectorDriversResponse - 76, // 178: rill.runtime.v1.RuntimeService.AnalyzeConnectors:output_type -> rill.runtime.v1.AnalyzeConnectorsResponse - 78, // 179: rill.runtime.v1.RuntimeService.ListNotifierConnectors:output_type -> rill.runtime.v1.ListNotifierConnectorsResponse - 85, // 180: rill.runtime.v1.RuntimeService.ListConversations:output_type -> rill.runtime.v1.ListConversationsResponse - 87, // 181: rill.runtime.v1.RuntimeService.GetConversation:output_type -> rill.runtime.v1.GetConversationResponse - 89, // 182: rill.runtime.v1.RuntimeService.ShareConversation:output_type -> rill.runtime.v1.ShareConversationResponse - 91, // 183: rill.runtime.v1.RuntimeService.ForkConversation:output_type -> rill.runtime.v1.ForkConversationResponse - 93, // 184: rill.runtime.v1.RuntimeService.ListTools:output_type -> rill.runtime.v1.ListToolsResponse - 95, // 185: rill.runtime.v1.RuntimeService.Complete:output_type -> rill.runtime.v1.CompleteResponse - 97, // 186: rill.runtime.v1.RuntimeService.CompleteStreaming:output_type -> rill.runtime.v1.CompleteStreamingResponse - 99, // 187: rill.runtime.v1.RuntimeService.GetAIMessage:output_type -> rill.runtime.v1.GetAIMessageResponse - 101, // 188: rill.runtime.v1.RuntimeService.IssueDevJWT:output_type -> rill.runtime.v1.IssueDevJWTResponse - 103, // 189: rill.runtime.v1.RuntimeService.AnalyzeVariables:output_type -> rill.runtime.v1.AnalyzeVariablesResponse - 106, // 190: rill.runtime.v1.RuntimeService.ListGitCommits:output_type -> rill.runtime.v1.ListGitCommitsResponse - 109, // 191: rill.runtime.v1.RuntimeService.GitStatus:output_type -> rill.runtime.v1.GitStatusResponse - 111, // 192: rill.runtime.v1.RuntimeService.ListGitBranches:output_type -> rill.runtime.v1.ListGitBranchesResponse - 114, // 193: rill.runtime.v1.RuntimeService.GitCommit:output_type -> rill.runtime.v1.GitCommitResponse - 116, // 194: rill.runtime.v1.RuntimeService.RestoreGitCommit:output_type -> rill.runtime.v1.RestoreGitCommitResponse - 118, // 195: rill.runtime.v1.RuntimeService.GitMergeToBranch:output_type -> rill.runtime.v1.GitMergeToBranchResponse - 120, // 196: rill.runtime.v1.RuntimeService.GitSwitchBranch:output_type -> rill.runtime.v1.GitSwitchBranchResponse - 122, // 197: rill.runtime.v1.RuntimeService.GitPull:output_type -> rill.runtime.v1.GitPullResponse - 124, // 198: rill.runtime.v1.RuntimeService.GitPush:output_type -> rill.runtime.v1.GitPushResponse - 147, // [147:199] is the sub-list for method output_type - 95, // [95:147] is the sub-list for method input_type - 95, // [95:95] is the sub-list for extension type_name - 95, // [95:95] is the sub-list for extension extendee - 0, // [0:95] is the sub-list for field type_name + 148, // 26: rill.runtime.v1.GenerateTemplateRequest.properties:type_name -> google.protobuf.Struct + 142, // 27: rill.runtime.v1.GenerateTemplateResponse.env_vars:type_name -> rill.runtime.v1.GenerateTemplateResponse.EnvVarsEntry + 54, // 28: rill.runtime.v1.Template.files:type_name -> rill.runtime.v1.TemplateFile + 148, // 29: rill.runtime.v1.Template.json_schema:type_name -> google.protobuf.Struct + 53, // 30: rill.runtime.v1.ListTemplatesResponse.templates:type_name -> rill.runtime.v1.Template + 148, // 31: rill.runtime.v1.GenerateFileRequest.properties:type_name -> google.protobuf.Struct + 59, // 32: rill.runtime.v1.GenerateFileResponse.files:type_name -> rill.runtime.v1.GeneratedFile + 143, // 33: rill.runtime.v1.GenerateFileResponse.env_vars:type_name -> rill.runtime.v1.GenerateFileResponse.EnvVarsEntry + 148, // 34: rill.runtime.v1.QueryResolverRequest.resolver_properties:type_name -> google.protobuf.Struct + 148, // 35: rill.runtime.v1.QueryResolverRequest.resolver_args:type_name -> google.protobuf.Struct + 148, // 36: rill.runtime.v1.QueryResolverResponse.meta:type_name -> google.protobuf.Struct + 149, // 37: rill.runtime.v1.QueryResolverResponse.schema:type_name -> rill.runtime.v1.StructType + 148, // 38: rill.runtime.v1.QueryResolverResponse.data:type_name -> google.protobuf.Struct + 1, // 39: rill.runtime.v1.Log.level:type_name -> rill.runtime.v1.LogLevel + 147, // 40: rill.runtime.v1.Log.time:type_name -> google.protobuf.Timestamp + 148, // 41: rill.runtime.v1.ModelPartition.data:type_name -> google.protobuf.Struct + 147, // 42: rill.runtime.v1.ModelPartition.watermark:type_name -> google.protobuf.Timestamp + 147, // 43: rill.runtime.v1.ModelPartition.executed_on:type_name -> google.protobuf.Timestamp + 1, // 44: rill.runtime.v1.GetLogsRequest.level:type_name -> rill.runtime.v1.LogLevel + 62, // 45: rill.runtime.v1.GetLogsResponse.logs:type_name -> rill.runtime.v1.Log + 1, // 46: rill.runtime.v1.WatchLogsRequest.level:type_name -> rill.runtime.v1.LogLevel + 62, // 47: rill.runtime.v1.WatchLogsResponse.log:type_name -> rill.runtime.v1.Log + 150, // 48: rill.runtime.v1.ListResourcesResponse.resources:type_name -> rill.runtime.v1.Resource + 2, // 49: rill.runtime.v1.WatchResourcesResponse.event:type_name -> rill.runtime.v1.ResourceEvent + 151, // 50: rill.runtime.v1.WatchResourcesResponse.name:type_name -> rill.runtime.v1.ResourceName + 150, // 51: rill.runtime.v1.WatchResourcesResponse.resource:type_name -> rill.runtime.v1.Resource + 151, // 52: rill.runtime.v1.GetResourceRequest.name:type_name -> rill.runtime.v1.ResourceName + 150, // 53: rill.runtime.v1.GetResourceResponse.resource:type_name -> rill.runtime.v1.Resource + 150, // 54: rill.runtime.v1.GetExploreResponse.explore:type_name -> rill.runtime.v1.Resource + 150, // 55: rill.runtime.v1.GetExploreResponse.metrics_view:type_name -> rill.runtime.v1.Resource + 63, // 56: rill.runtime.v1.GetModelPartitionsResponse.partitions:type_name -> rill.runtime.v1.ModelPartition + 151, // 57: rill.runtime.v1.CreateTriggerRequest.resources:type_name -> rill.runtime.v1.ResourceName + 152, // 58: rill.runtime.v1.CreateTriggerRequest.models:type_name -> rill.runtime.v1.RefreshModelTrigger + 144, // 59: rill.runtime.v1.ConnectorDriver.config_properties:type_name -> rill.runtime.v1.ConnectorDriver.Property + 144, // 60: rill.runtime.v1.ConnectorDriver.source_properties:type_name -> rill.runtime.v1.ConnectorDriver.Property + 80, // 61: rill.runtime.v1.AnalyzedConnector.driver:type_name -> rill.runtime.v1.ConnectorDriver + 148, // 62: rill.runtime.v1.AnalyzedConnector.config:type_name -> google.protobuf.Struct + 148, // 63: rill.runtime.v1.AnalyzedConnector.preset_config:type_name -> google.protobuf.Struct + 148, // 64: rill.runtime.v1.AnalyzedConnector.project_config:type_name -> google.protobuf.Struct + 145, // 65: rill.runtime.v1.AnalyzedConnector.env_config:type_name -> rill.runtime.v1.AnalyzedConnector.EnvConfigEntry + 148, // 66: rill.runtime.v1.AnalyzedConnector.provision_args:type_name -> google.protobuf.Struct + 151, // 67: rill.runtime.v1.AnalyzedConnector.used_by:type_name -> rill.runtime.v1.ResourceName + 80, // 68: rill.runtime.v1.ListConnectorDriversResponse.connectors:type_name -> rill.runtime.v1.ConnectorDriver + 81, // 69: rill.runtime.v1.AnalyzeConnectorsResponse.connectors:type_name -> rill.runtime.v1.AnalyzedConnector + 12, // 70: rill.runtime.v1.ListNotifierConnectorsResponse.connectors:type_name -> rill.runtime.v1.Connector + 147, // 71: rill.runtime.v1.Conversation.created_on:type_name -> google.protobuf.Timestamp + 147, // 72: rill.runtime.v1.Conversation.updated_on:type_name -> google.protobuf.Timestamp + 89, // 73: rill.runtime.v1.Conversation.messages:type_name -> rill.runtime.v1.Message + 147, // 74: rill.runtime.v1.Message.created_on:type_name -> google.protobuf.Timestamp + 147, // 75: rill.runtime.v1.Message.updated_on:type_name -> google.protobuf.Timestamp + 153, // 76: rill.runtime.v1.Message.content:type_name -> rill.ai.v1.ContentBlock + 154, // 77: rill.runtime.v1.AnalystAgentContext.where:type_name -> rill.runtime.v1.Expression + 146, // 78: rill.runtime.v1.AnalystAgentContext.where_per_metrics_view:type_name -> rill.runtime.v1.AnalystAgentContext.WherePerMetricsViewEntry + 147, // 79: rill.runtime.v1.AnalystAgentContext.time_start:type_name -> google.protobuf.Timestamp + 147, // 80: rill.runtime.v1.AnalystAgentContext.time_end:type_name -> google.protobuf.Timestamp + 88, // 81: rill.runtime.v1.ListConversationsResponse.conversations:type_name -> rill.runtime.v1.Conversation + 88, // 82: rill.runtime.v1.GetConversationResponse.conversation:type_name -> rill.runtime.v1.Conversation + 89, // 83: rill.runtime.v1.GetConversationResponse.messages:type_name -> rill.runtime.v1.Message + 155, // 84: rill.runtime.v1.ListToolsResponse.tools:type_name -> rill.ai.v1.Tool + 90, // 85: rill.runtime.v1.CompleteRequest.analyst_agent_context:type_name -> rill.runtime.v1.AnalystAgentContext + 91, // 86: rill.runtime.v1.CompleteRequest.developer_agent_context:type_name -> rill.runtime.v1.DeveloperAgentContext + 92, // 87: rill.runtime.v1.CompleteRequest.feedback_agent_context:type_name -> rill.runtime.v1.FeedbackAgentContext + 89, // 88: rill.runtime.v1.CompleteResponse.messages:type_name -> rill.runtime.v1.Message + 90, // 89: rill.runtime.v1.CompleteStreamingRequest.analyst_agent_context:type_name -> rill.runtime.v1.AnalystAgentContext + 91, // 90: rill.runtime.v1.CompleteStreamingRequest.developer_agent_context:type_name -> rill.runtime.v1.DeveloperAgentContext + 92, // 91: rill.runtime.v1.CompleteStreamingRequest.feedback_agent_context:type_name -> rill.runtime.v1.FeedbackAgentContext + 89, // 92: rill.runtime.v1.CompleteStreamingResponse.message:type_name -> rill.runtime.v1.Message + 89, // 93: rill.runtime.v1.GetAIMessageResponse.message:type_name -> rill.runtime.v1.Message + 148, // 94: rill.runtime.v1.IssueDevJWTRequest.attributes:type_name -> google.protobuf.Struct + 113, // 95: rill.runtime.v1.AnalyzeVariablesResponse.variables:type_name -> rill.runtime.v1.AnalyzedVariable + 151, // 96: rill.runtime.v1.AnalyzedVariable.used_by:type_name -> rill.runtime.v1.ResourceName + 116, // 97: rill.runtime.v1.ListGitCommitsResponse.commits:type_name -> rill.runtime.v1.GitCommit + 147, // 98: rill.runtime.v1.GitCommit.committed_on:type_name -> google.protobuf.Timestamp + 121, // 99: rill.runtime.v1.ListGitBranchesResponse.branches:type_name -> rill.runtime.v1.GitBranch + 10, // 100: rill.runtime.v1.HealthResponse.InstancesHealthEntry.value:type_name -> rill.runtime.v1.InstanceHealth + 3, // 101: rill.runtime.v1.ConnectorDriver.Property.type:type_name -> rill.runtime.v1.ConnectorDriver.Property.Type + 154, // 102: rill.runtime.v1.AnalystAgentContext.WherePerMetricsViewEntry.value:type_name -> rill.runtime.v1.Expression + 4, // 103: rill.runtime.v1.RuntimeService.Ping:input_type -> rill.runtime.v1.PingRequest + 6, // 104: rill.runtime.v1.RuntimeService.Health:input_type -> rill.runtime.v1.HealthRequest + 8, // 105: rill.runtime.v1.RuntimeService.InstanceHealth:input_type -> rill.runtime.v1.InstanceHealthRequest + 13, // 106: rill.runtime.v1.RuntimeService.ListInstances:input_type -> rill.runtime.v1.ListInstancesRequest + 15, // 107: rill.runtime.v1.RuntimeService.GetInstance:input_type -> rill.runtime.v1.GetInstanceRequest + 17, // 108: rill.runtime.v1.RuntimeService.CreateInstance:input_type -> rill.runtime.v1.CreateInstanceRequest + 21, // 109: rill.runtime.v1.RuntimeService.EditInstance:input_type -> rill.runtime.v1.EditInstanceRequest + 19, // 110: rill.runtime.v1.RuntimeService.DeleteInstance:input_type -> rill.runtime.v1.DeleteInstanceRequest + 23, // 111: rill.runtime.v1.RuntimeService.ReloadConfig:input_type -> rill.runtime.v1.ReloadConfigRequest + 25, // 112: rill.runtime.v1.RuntimeService.ListFiles:input_type -> rill.runtime.v1.ListFilesRequest + 28, // 113: rill.runtime.v1.RuntimeService.WatchFiles:input_type -> rill.runtime.v1.WatchFilesRequest + 30, // 114: rill.runtime.v1.RuntimeService.GetFile:input_type -> rill.runtime.v1.GetFileRequest + 32, // 115: rill.runtime.v1.RuntimeService.PutFile:input_type -> rill.runtime.v1.PutFileRequest + 34, // 116: rill.runtime.v1.RuntimeService.CreateDirectory:input_type -> rill.runtime.v1.CreateDirectoryRequest + 36, // 117: rill.runtime.v1.RuntimeService.DeleteFile:input_type -> rill.runtime.v1.DeleteFileRequest + 38, // 118: rill.runtime.v1.RuntimeService.RenameFile:input_type -> rill.runtime.v1.RenameFileRequest + 41, // 119: rill.runtime.v1.RuntimeService.ListExamples:input_type -> rill.runtime.v1.ListExamplesRequest + 43, // 120: rill.runtime.v1.RuntimeService.UnpackExample:input_type -> rill.runtime.v1.UnpackExampleRequest + 45, // 121: rill.runtime.v1.RuntimeService.UnpackEmpty:input_type -> rill.runtime.v1.UnpackEmptyRequest + 47, // 122: rill.runtime.v1.RuntimeService.GenerateMetricsViewFile:input_type -> rill.runtime.v1.GenerateMetricsViewFileRequest + 49, // 123: rill.runtime.v1.RuntimeService.GenerateCanvasFile:input_type -> rill.runtime.v1.GenerateCanvasFileRequest + 51, // 124: rill.runtime.v1.RuntimeService.GenerateTemplate:input_type -> rill.runtime.v1.GenerateTemplateRequest + 55, // 125: rill.runtime.v1.RuntimeService.ListTemplates:input_type -> rill.runtime.v1.ListTemplatesRequest + 57, // 126: rill.runtime.v1.RuntimeService.GenerateFile:input_type -> rill.runtime.v1.GenerateFileRequest + 60, // 127: rill.runtime.v1.RuntimeService.QueryResolver:input_type -> rill.runtime.v1.QueryResolverRequest + 64, // 128: rill.runtime.v1.RuntimeService.GetLogs:input_type -> rill.runtime.v1.GetLogsRequest + 66, // 129: rill.runtime.v1.RuntimeService.WatchLogs:input_type -> rill.runtime.v1.WatchLogsRequest + 68, // 130: rill.runtime.v1.RuntimeService.ListResources:input_type -> rill.runtime.v1.ListResourcesRequest + 70, // 131: rill.runtime.v1.RuntimeService.WatchResources:input_type -> rill.runtime.v1.WatchResourcesRequest + 72, // 132: rill.runtime.v1.RuntimeService.GetResource:input_type -> rill.runtime.v1.GetResourceRequest + 74, // 133: rill.runtime.v1.RuntimeService.GetExplore:input_type -> rill.runtime.v1.GetExploreRequest + 76, // 134: rill.runtime.v1.RuntimeService.GetModelPartitions:input_type -> rill.runtime.v1.GetModelPartitionsRequest + 78, // 135: rill.runtime.v1.RuntimeService.CreateTrigger:input_type -> rill.runtime.v1.CreateTriggerRequest + 82, // 136: rill.runtime.v1.RuntimeService.ListConnectorDrivers:input_type -> rill.runtime.v1.ListConnectorDriversRequest + 84, // 137: rill.runtime.v1.RuntimeService.AnalyzeConnectors:input_type -> rill.runtime.v1.AnalyzeConnectorsRequest + 86, // 138: rill.runtime.v1.RuntimeService.ListNotifierConnectors:input_type -> rill.runtime.v1.ListNotifierConnectorsRequest + 93, // 139: rill.runtime.v1.RuntimeService.ListConversations:input_type -> rill.runtime.v1.ListConversationsRequest + 95, // 140: rill.runtime.v1.RuntimeService.GetConversation:input_type -> rill.runtime.v1.GetConversationRequest + 97, // 141: rill.runtime.v1.RuntimeService.ShareConversation:input_type -> rill.runtime.v1.ShareConversationRequest + 99, // 142: rill.runtime.v1.RuntimeService.ForkConversation:input_type -> rill.runtime.v1.ForkConversationRequest + 101, // 143: rill.runtime.v1.RuntimeService.ListTools:input_type -> rill.runtime.v1.ListToolsRequest + 103, // 144: rill.runtime.v1.RuntimeService.Complete:input_type -> rill.runtime.v1.CompleteRequest + 105, // 145: rill.runtime.v1.RuntimeService.CompleteStreaming:input_type -> rill.runtime.v1.CompleteStreamingRequest + 107, // 146: rill.runtime.v1.RuntimeService.GetAIMessage:input_type -> rill.runtime.v1.GetAIMessageRequest + 109, // 147: rill.runtime.v1.RuntimeService.IssueDevJWT:input_type -> rill.runtime.v1.IssueDevJWTRequest + 111, // 148: rill.runtime.v1.RuntimeService.AnalyzeVariables:input_type -> rill.runtime.v1.AnalyzeVariablesRequest + 114, // 149: rill.runtime.v1.RuntimeService.ListGitCommits:input_type -> rill.runtime.v1.ListGitCommitsRequest + 117, // 150: rill.runtime.v1.RuntimeService.GitStatus:input_type -> rill.runtime.v1.GitStatusRequest + 119, // 151: rill.runtime.v1.RuntimeService.ListGitBranches:input_type -> rill.runtime.v1.ListGitBranchesRequest + 122, // 152: rill.runtime.v1.RuntimeService.GitCommit:input_type -> rill.runtime.v1.GitCommitRequest + 124, // 153: rill.runtime.v1.RuntimeService.RestoreGitCommit:input_type -> rill.runtime.v1.RestoreGitCommitRequest + 126, // 154: rill.runtime.v1.RuntimeService.GitMergeToBranch:input_type -> rill.runtime.v1.GitMergeToBranchRequest + 128, // 155: rill.runtime.v1.RuntimeService.GitSwitchBranch:input_type -> rill.runtime.v1.GitSwitchBranchRequest + 130, // 156: rill.runtime.v1.RuntimeService.GitPull:input_type -> rill.runtime.v1.GitPullRequest + 132, // 157: rill.runtime.v1.RuntimeService.GitPush:input_type -> rill.runtime.v1.GitPushRequest + 5, // 158: rill.runtime.v1.RuntimeService.Ping:output_type -> rill.runtime.v1.PingResponse + 7, // 159: rill.runtime.v1.RuntimeService.Health:output_type -> rill.runtime.v1.HealthResponse + 9, // 160: rill.runtime.v1.RuntimeService.InstanceHealth:output_type -> rill.runtime.v1.InstanceHealthResponse + 14, // 161: rill.runtime.v1.RuntimeService.ListInstances:output_type -> rill.runtime.v1.ListInstancesResponse + 16, // 162: rill.runtime.v1.RuntimeService.GetInstance:output_type -> rill.runtime.v1.GetInstanceResponse + 18, // 163: rill.runtime.v1.RuntimeService.CreateInstance:output_type -> rill.runtime.v1.CreateInstanceResponse + 22, // 164: rill.runtime.v1.RuntimeService.EditInstance:output_type -> rill.runtime.v1.EditInstanceResponse + 20, // 165: rill.runtime.v1.RuntimeService.DeleteInstance:output_type -> rill.runtime.v1.DeleteInstanceResponse + 24, // 166: rill.runtime.v1.RuntimeService.ReloadConfig:output_type -> rill.runtime.v1.ReloadConfigResponse + 26, // 167: rill.runtime.v1.RuntimeService.ListFiles:output_type -> rill.runtime.v1.ListFilesResponse + 29, // 168: rill.runtime.v1.RuntimeService.WatchFiles:output_type -> rill.runtime.v1.WatchFilesResponse + 31, // 169: rill.runtime.v1.RuntimeService.GetFile:output_type -> rill.runtime.v1.GetFileResponse + 33, // 170: rill.runtime.v1.RuntimeService.PutFile:output_type -> rill.runtime.v1.PutFileResponse + 35, // 171: rill.runtime.v1.RuntimeService.CreateDirectory:output_type -> rill.runtime.v1.CreateDirectoryResponse + 37, // 172: rill.runtime.v1.RuntimeService.DeleteFile:output_type -> rill.runtime.v1.DeleteFileResponse + 39, // 173: rill.runtime.v1.RuntimeService.RenameFile:output_type -> rill.runtime.v1.RenameFileResponse + 42, // 174: rill.runtime.v1.RuntimeService.ListExamples:output_type -> rill.runtime.v1.ListExamplesResponse + 44, // 175: rill.runtime.v1.RuntimeService.UnpackExample:output_type -> rill.runtime.v1.UnpackExampleResponse + 46, // 176: rill.runtime.v1.RuntimeService.UnpackEmpty:output_type -> rill.runtime.v1.UnpackEmptyResponse + 48, // 177: rill.runtime.v1.RuntimeService.GenerateMetricsViewFile:output_type -> rill.runtime.v1.GenerateMetricsViewFileResponse + 50, // 178: rill.runtime.v1.RuntimeService.GenerateCanvasFile:output_type -> rill.runtime.v1.GenerateCanvasFileResponse + 52, // 179: rill.runtime.v1.RuntimeService.GenerateTemplate:output_type -> rill.runtime.v1.GenerateTemplateResponse + 56, // 180: rill.runtime.v1.RuntimeService.ListTemplates:output_type -> rill.runtime.v1.ListTemplatesResponse + 58, // 181: rill.runtime.v1.RuntimeService.GenerateFile:output_type -> rill.runtime.v1.GenerateFileResponse + 61, // 182: rill.runtime.v1.RuntimeService.QueryResolver:output_type -> rill.runtime.v1.QueryResolverResponse + 65, // 183: rill.runtime.v1.RuntimeService.GetLogs:output_type -> rill.runtime.v1.GetLogsResponse + 67, // 184: rill.runtime.v1.RuntimeService.WatchLogs:output_type -> rill.runtime.v1.WatchLogsResponse + 69, // 185: rill.runtime.v1.RuntimeService.ListResources:output_type -> rill.runtime.v1.ListResourcesResponse + 71, // 186: rill.runtime.v1.RuntimeService.WatchResources:output_type -> rill.runtime.v1.WatchResourcesResponse + 73, // 187: rill.runtime.v1.RuntimeService.GetResource:output_type -> rill.runtime.v1.GetResourceResponse + 75, // 188: rill.runtime.v1.RuntimeService.GetExplore:output_type -> rill.runtime.v1.GetExploreResponse + 77, // 189: rill.runtime.v1.RuntimeService.GetModelPartitions:output_type -> rill.runtime.v1.GetModelPartitionsResponse + 79, // 190: rill.runtime.v1.RuntimeService.CreateTrigger:output_type -> rill.runtime.v1.CreateTriggerResponse + 83, // 191: rill.runtime.v1.RuntimeService.ListConnectorDrivers:output_type -> rill.runtime.v1.ListConnectorDriversResponse + 85, // 192: rill.runtime.v1.RuntimeService.AnalyzeConnectors:output_type -> rill.runtime.v1.AnalyzeConnectorsResponse + 87, // 193: rill.runtime.v1.RuntimeService.ListNotifierConnectors:output_type -> rill.runtime.v1.ListNotifierConnectorsResponse + 94, // 194: rill.runtime.v1.RuntimeService.ListConversations:output_type -> rill.runtime.v1.ListConversationsResponse + 96, // 195: rill.runtime.v1.RuntimeService.GetConversation:output_type -> rill.runtime.v1.GetConversationResponse + 98, // 196: rill.runtime.v1.RuntimeService.ShareConversation:output_type -> rill.runtime.v1.ShareConversationResponse + 100, // 197: rill.runtime.v1.RuntimeService.ForkConversation:output_type -> rill.runtime.v1.ForkConversationResponse + 102, // 198: rill.runtime.v1.RuntimeService.ListTools:output_type -> rill.runtime.v1.ListToolsResponse + 104, // 199: rill.runtime.v1.RuntimeService.Complete:output_type -> rill.runtime.v1.CompleteResponse + 106, // 200: rill.runtime.v1.RuntimeService.CompleteStreaming:output_type -> rill.runtime.v1.CompleteStreamingResponse + 108, // 201: rill.runtime.v1.RuntimeService.GetAIMessage:output_type -> rill.runtime.v1.GetAIMessageResponse + 110, // 202: rill.runtime.v1.RuntimeService.IssueDevJWT:output_type -> rill.runtime.v1.IssueDevJWTResponse + 112, // 203: rill.runtime.v1.RuntimeService.AnalyzeVariables:output_type -> rill.runtime.v1.AnalyzeVariablesResponse + 115, // 204: rill.runtime.v1.RuntimeService.ListGitCommits:output_type -> rill.runtime.v1.ListGitCommitsResponse + 118, // 205: rill.runtime.v1.RuntimeService.GitStatus:output_type -> rill.runtime.v1.GitStatusResponse + 120, // 206: rill.runtime.v1.RuntimeService.ListGitBranches:output_type -> rill.runtime.v1.ListGitBranchesResponse + 123, // 207: rill.runtime.v1.RuntimeService.GitCommit:output_type -> rill.runtime.v1.GitCommitResponse + 125, // 208: rill.runtime.v1.RuntimeService.RestoreGitCommit:output_type -> rill.runtime.v1.RestoreGitCommitResponse + 127, // 209: rill.runtime.v1.RuntimeService.GitMergeToBranch:output_type -> rill.runtime.v1.GitMergeToBranchResponse + 129, // 210: rill.runtime.v1.RuntimeService.GitSwitchBranch:output_type -> rill.runtime.v1.GitSwitchBranchResponse + 131, // 211: rill.runtime.v1.RuntimeService.GitPull:output_type -> rill.runtime.v1.GitPullResponse + 133, // 212: rill.runtime.v1.RuntimeService.GitPush:output_type -> rill.runtime.v1.GitPushResponse + 158, // [158:213] is the sub-list for method output_type + 103, // [103:158] is the sub-list for method input_type + 103, // [103:103] is the sub-list for extension type_name + 103, // [103:103] is the sub-list for extension extendee + 0, // [0:103] is the sub-list for field type_name } func init() { file_rill_runtime_v1_api_proto_init() } @@ -10668,7 +11461,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[47].Exporter = func(v any, i int) any { - switch v := v.(*QueryResolverRequest); i { + switch v := v.(*GenerateTemplateRequest); i { case 0: return &v.state case 1: @@ -10680,7 +11473,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[48].Exporter = func(v any, i int) any { - switch v := v.(*QueryResolverResponse); i { + switch v := v.(*GenerateTemplateResponse); i { case 0: return &v.state case 1: @@ -10692,7 +11485,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[49].Exporter = func(v any, i int) any { - switch v := v.(*Log); i { + switch v := v.(*Template); i { case 0: return &v.state case 1: @@ -10704,7 +11497,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[50].Exporter = func(v any, i int) any { - switch v := v.(*ModelPartition); i { + switch v := v.(*TemplateFile); i { case 0: return &v.state case 1: @@ -10716,7 +11509,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[51].Exporter = func(v any, i int) any { - switch v := v.(*GetLogsRequest); i { + switch v := v.(*ListTemplatesRequest); i { case 0: return &v.state case 1: @@ -10728,7 +11521,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[52].Exporter = func(v any, i int) any { - switch v := v.(*GetLogsResponse); i { + switch v := v.(*ListTemplatesResponse); i { case 0: return &v.state case 1: @@ -10740,7 +11533,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[53].Exporter = func(v any, i int) any { - switch v := v.(*WatchLogsRequest); i { + switch v := v.(*GenerateFileRequest); i { case 0: return &v.state case 1: @@ -10752,7 +11545,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[54].Exporter = func(v any, i int) any { - switch v := v.(*WatchLogsResponse); i { + switch v := v.(*GenerateFileResponse); i { case 0: return &v.state case 1: @@ -10764,7 +11557,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[55].Exporter = func(v any, i int) any { - switch v := v.(*ListResourcesRequest); i { + switch v := v.(*GeneratedFile); i { case 0: return &v.state case 1: @@ -10776,7 +11569,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[56].Exporter = func(v any, i int) any { - switch v := v.(*ListResourcesResponse); i { + switch v := v.(*QueryResolverRequest); i { case 0: return &v.state case 1: @@ -10788,7 +11581,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[57].Exporter = func(v any, i int) any { - switch v := v.(*WatchResourcesRequest); i { + switch v := v.(*QueryResolverResponse); i { case 0: return &v.state case 1: @@ -10800,7 +11593,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[58].Exporter = func(v any, i int) any { - switch v := v.(*WatchResourcesResponse); i { + switch v := v.(*Log); i { case 0: return &v.state case 1: @@ -10812,7 +11605,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[59].Exporter = func(v any, i int) any { - switch v := v.(*GetResourceRequest); i { + switch v := v.(*ModelPartition); i { case 0: return &v.state case 1: @@ -10824,7 +11617,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[60].Exporter = func(v any, i int) any { - switch v := v.(*GetResourceResponse); i { + switch v := v.(*GetLogsRequest); i { case 0: return &v.state case 1: @@ -10836,7 +11629,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[61].Exporter = func(v any, i int) any { - switch v := v.(*GetExploreRequest); i { + switch v := v.(*GetLogsResponse); i { case 0: return &v.state case 1: @@ -10848,7 +11641,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[62].Exporter = func(v any, i int) any { - switch v := v.(*GetExploreResponse); i { + switch v := v.(*WatchLogsRequest); i { case 0: return &v.state case 1: @@ -10860,7 +11653,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[63].Exporter = func(v any, i int) any { - switch v := v.(*GetModelPartitionsRequest); i { + switch v := v.(*WatchLogsResponse); i { case 0: return &v.state case 1: @@ -10872,7 +11665,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[64].Exporter = func(v any, i int) any { - switch v := v.(*GetModelPartitionsResponse); i { + switch v := v.(*ListResourcesRequest); i { case 0: return &v.state case 1: @@ -10884,7 +11677,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[65].Exporter = func(v any, i int) any { - switch v := v.(*CreateTriggerRequest); i { + switch v := v.(*ListResourcesResponse); i { case 0: return &v.state case 1: @@ -10896,7 +11689,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[66].Exporter = func(v any, i int) any { - switch v := v.(*CreateTriggerResponse); i { + switch v := v.(*WatchResourcesRequest); i { case 0: return &v.state case 1: @@ -10908,7 +11701,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[67].Exporter = func(v any, i int) any { - switch v := v.(*ConnectorDriver); i { + switch v := v.(*WatchResourcesResponse); i { case 0: return &v.state case 1: @@ -10920,7 +11713,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[68].Exporter = func(v any, i int) any { - switch v := v.(*AnalyzedConnector); i { + switch v := v.(*GetResourceRequest); i { case 0: return &v.state case 1: @@ -10932,7 +11725,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[69].Exporter = func(v any, i int) any { - switch v := v.(*ListConnectorDriversRequest); i { + switch v := v.(*GetResourceResponse); i { case 0: return &v.state case 1: @@ -10944,7 +11737,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[70].Exporter = func(v any, i int) any { - switch v := v.(*ListConnectorDriversResponse); i { + switch v := v.(*GetExploreRequest); i { case 0: return &v.state case 1: @@ -10956,7 +11749,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[71].Exporter = func(v any, i int) any { - switch v := v.(*AnalyzeConnectorsRequest); i { + switch v := v.(*GetExploreResponse); i { case 0: return &v.state case 1: @@ -10968,7 +11761,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[72].Exporter = func(v any, i int) any { - switch v := v.(*AnalyzeConnectorsResponse); i { + switch v := v.(*GetModelPartitionsRequest); i { case 0: return &v.state case 1: @@ -10980,7 +11773,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[73].Exporter = func(v any, i int) any { - switch v := v.(*ListNotifierConnectorsRequest); i { + switch v := v.(*GetModelPartitionsResponse); i { case 0: return &v.state case 1: @@ -10992,7 +11785,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[74].Exporter = func(v any, i int) any { - switch v := v.(*ListNotifierConnectorsResponse); i { + switch v := v.(*CreateTriggerRequest); i { case 0: return &v.state case 1: @@ -11004,7 +11797,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[75].Exporter = func(v any, i int) any { - switch v := v.(*Conversation); i { + switch v := v.(*CreateTriggerResponse); i { case 0: return &v.state case 1: @@ -11016,7 +11809,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[76].Exporter = func(v any, i int) any { - switch v := v.(*Message); i { + switch v := v.(*ConnectorDriver); i { case 0: return &v.state case 1: @@ -11028,7 +11821,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[77].Exporter = func(v any, i int) any { - switch v := v.(*AnalystAgentContext); i { + switch v := v.(*AnalyzedConnector); i { case 0: return &v.state case 1: @@ -11040,7 +11833,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[78].Exporter = func(v any, i int) any { - switch v := v.(*DeveloperAgentContext); i { + switch v := v.(*ListConnectorDriversRequest); i { case 0: return &v.state case 1: @@ -11052,7 +11845,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[79].Exporter = func(v any, i int) any { - switch v := v.(*FeedbackAgentContext); i { + switch v := v.(*ListConnectorDriversResponse); i { case 0: return &v.state case 1: @@ -11064,7 +11857,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[80].Exporter = func(v any, i int) any { - switch v := v.(*ListConversationsRequest); i { + switch v := v.(*AnalyzeConnectorsRequest); i { case 0: return &v.state case 1: @@ -11076,7 +11869,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[81].Exporter = func(v any, i int) any { - switch v := v.(*ListConversationsResponse); i { + switch v := v.(*AnalyzeConnectorsResponse); i { case 0: return &v.state case 1: @@ -11088,7 +11881,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[82].Exporter = func(v any, i int) any { - switch v := v.(*GetConversationRequest); i { + switch v := v.(*ListNotifierConnectorsRequest); i { case 0: return &v.state case 1: @@ -11100,7 +11893,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[83].Exporter = func(v any, i int) any { - switch v := v.(*GetConversationResponse); i { + switch v := v.(*ListNotifierConnectorsResponse); i { case 0: return &v.state case 1: @@ -11112,7 +11905,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[84].Exporter = func(v any, i int) any { - switch v := v.(*ShareConversationRequest); i { + switch v := v.(*Conversation); i { case 0: return &v.state case 1: @@ -11124,7 +11917,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[85].Exporter = func(v any, i int) any { - switch v := v.(*ShareConversationResponse); i { + switch v := v.(*Message); i { case 0: return &v.state case 1: @@ -11136,7 +11929,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[86].Exporter = func(v any, i int) any { - switch v := v.(*ForkConversationRequest); i { + switch v := v.(*AnalystAgentContext); i { case 0: return &v.state case 1: @@ -11148,7 +11941,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[87].Exporter = func(v any, i int) any { - switch v := v.(*ForkConversationResponse); i { + switch v := v.(*DeveloperAgentContext); i { case 0: return &v.state case 1: @@ -11160,7 +11953,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[88].Exporter = func(v any, i int) any { - switch v := v.(*ListToolsRequest); i { + switch v := v.(*FeedbackAgentContext); i { case 0: return &v.state case 1: @@ -11172,7 +11965,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[89].Exporter = func(v any, i int) any { - switch v := v.(*ListToolsResponse); i { + switch v := v.(*ListConversationsRequest); i { case 0: return &v.state case 1: @@ -11184,7 +11977,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[90].Exporter = func(v any, i int) any { - switch v := v.(*CompleteRequest); i { + switch v := v.(*ListConversationsResponse); i { case 0: return &v.state case 1: @@ -11196,7 +11989,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[91].Exporter = func(v any, i int) any { - switch v := v.(*CompleteResponse); i { + switch v := v.(*GetConversationRequest); i { case 0: return &v.state case 1: @@ -11208,7 +12001,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[92].Exporter = func(v any, i int) any { - switch v := v.(*CompleteStreamingRequest); i { + switch v := v.(*GetConversationResponse); i { case 0: return &v.state case 1: @@ -11220,7 +12013,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[93].Exporter = func(v any, i int) any { - switch v := v.(*CompleteStreamingResponse); i { + switch v := v.(*ShareConversationRequest); i { case 0: return &v.state case 1: @@ -11232,7 +12025,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[94].Exporter = func(v any, i int) any { - switch v := v.(*GetAIMessageRequest); i { + switch v := v.(*ShareConversationResponse); i { case 0: return &v.state case 1: @@ -11244,7 +12037,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[95].Exporter = func(v any, i int) any { - switch v := v.(*GetAIMessageResponse); i { + switch v := v.(*ForkConversationRequest); i { case 0: return &v.state case 1: @@ -11256,7 +12049,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[96].Exporter = func(v any, i int) any { - switch v := v.(*IssueDevJWTRequest); i { + switch v := v.(*ForkConversationResponse); i { case 0: return &v.state case 1: @@ -11268,7 +12061,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[97].Exporter = func(v any, i int) any { - switch v := v.(*IssueDevJWTResponse); i { + switch v := v.(*ListToolsRequest); i { case 0: return &v.state case 1: @@ -11280,7 +12073,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[98].Exporter = func(v any, i int) any { - switch v := v.(*AnalyzeVariablesRequest); i { + switch v := v.(*ListToolsResponse); i { case 0: return &v.state case 1: @@ -11292,7 +12085,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[99].Exporter = func(v any, i int) any { - switch v := v.(*AnalyzeVariablesResponse); i { + switch v := v.(*CompleteRequest); i { case 0: return &v.state case 1: @@ -11304,7 +12097,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[100].Exporter = func(v any, i int) any { - switch v := v.(*AnalyzedVariable); i { + switch v := v.(*CompleteResponse); i { case 0: return &v.state case 1: @@ -11316,7 +12109,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[101].Exporter = func(v any, i int) any { - switch v := v.(*ListGitCommitsRequest); i { + switch v := v.(*CompleteStreamingRequest); i { case 0: return &v.state case 1: @@ -11328,7 +12121,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[102].Exporter = func(v any, i int) any { - switch v := v.(*ListGitCommitsResponse); i { + switch v := v.(*CompleteStreamingResponse); i { case 0: return &v.state case 1: @@ -11340,7 +12133,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[103].Exporter = func(v any, i int) any { - switch v := v.(*GitCommit); i { + switch v := v.(*GetAIMessageRequest); i { case 0: return &v.state case 1: @@ -11352,7 +12145,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[104].Exporter = func(v any, i int) any { - switch v := v.(*GitStatusRequest); i { + switch v := v.(*GetAIMessageResponse); i { case 0: return &v.state case 1: @@ -11364,7 +12157,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[105].Exporter = func(v any, i int) any { - switch v := v.(*GitStatusResponse); i { + switch v := v.(*IssueDevJWTRequest); i { case 0: return &v.state case 1: @@ -11376,7 +12169,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[106].Exporter = func(v any, i int) any { - switch v := v.(*ListGitBranchesRequest); i { + switch v := v.(*IssueDevJWTResponse); i { case 0: return &v.state case 1: @@ -11388,7 +12181,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[107].Exporter = func(v any, i int) any { - switch v := v.(*ListGitBranchesResponse); i { + switch v := v.(*AnalyzeVariablesRequest); i { case 0: return &v.state case 1: @@ -11400,7 +12193,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[108].Exporter = func(v any, i int) any { - switch v := v.(*GitBranch); i { + switch v := v.(*AnalyzeVariablesResponse); i { case 0: return &v.state case 1: @@ -11412,7 +12205,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[109].Exporter = func(v any, i int) any { - switch v := v.(*GitCommitRequest); i { + switch v := v.(*AnalyzedVariable); i { case 0: return &v.state case 1: @@ -11424,7 +12217,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[110].Exporter = func(v any, i int) any { - switch v := v.(*GitCommitResponse); i { + switch v := v.(*ListGitCommitsRequest); i { case 0: return &v.state case 1: @@ -11436,7 +12229,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[111].Exporter = func(v any, i int) any { - switch v := v.(*RestoreGitCommitRequest); i { + switch v := v.(*ListGitCommitsResponse); i { case 0: return &v.state case 1: @@ -11448,7 +12241,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[112].Exporter = func(v any, i int) any { - switch v := v.(*RestoreGitCommitResponse); i { + switch v := v.(*GitCommit); i { case 0: return &v.state case 1: @@ -11460,7 +12253,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[113].Exporter = func(v any, i int) any { - switch v := v.(*GitMergeToBranchRequest); i { + switch v := v.(*GitStatusRequest); i { case 0: return &v.state case 1: @@ -11472,7 +12265,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[114].Exporter = func(v any, i int) any { - switch v := v.(*GitMergeToBranchResponse); i { + switch v := v.(*GitStatusResponse); i { case 0: return &v.state case 1: @@ -11484,7 +12277,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[115].Exporter = func(v any, i int) any { - switch v := v.(*GitSwitchBranchRequest); i { + switch v := v.(*ListGitBranchesRequest); i { case 0: return &v.state case 1: @@ -11496,7 +12289,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[116].Exporter = func(v any, i int) any { - switch v := v.(*GitSwitchBranchResponse); i { + switch v := v.(*ListGitBranchesResponse); i { case 0: return &v.state case 1: @@ -11508,7 +12301,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[117].Exporter = func(v any, i int) any { - switch v := v.(*GitPullRequest); i { + switch v := v.(*GitBranch); i { case 0: return &v.state case 1: @@ -11520,7 +12313,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[118].Exporter = func(v any, i int) any { - switch v := v.(*GitPullResponse); i { + switch v := v.(*GitCommitRequest); i { case 0: return &v.state case 1: @@ -11532,7 +12325,7 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[119].Exporter = func(v any, i int) any { - switch v := v.(*GitPushRequest); i { + switch v := v.(*GitCommitResponse); i { case 0: return &v.state case 1: @@ -11544,7 +12337,103 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[120].Exporter = func(v any, i int) any { - switch v := v.(*GitPushResponse); i { + switch v := v.(*RestoreGitCommitRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_rill_runtime_v1_api_proto_msgTypes[121].Exporter = func(v any, i int) any { + switch v := v.(*RestoreGitCommitResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_rill_runtime_v1_api_proto_msgTypes[122].Exporter = func(v any, i int) any { + switch v := v.(*GitMergeToBranchRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_rill_runtime_v1_api_proto_msgTypes[123].Exporter = func(v any, i int) any { + switch v := v.(*GitMergeToBranchResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_rill_runtime_v1_api_proto_msgTypes[124].Exporter = func(v any, i int) any { + switch v := v.(*GitSwitchBranchRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_rill_runtime_v1_api_proto_msgTypes[125].Exporter = func(v any, i int) any { + switch v := v.(*GitSwitchBranchResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_rill_runtime_v1_api_proto_msgTypes[126].Exporter = func(v any, i int) any { + switch v := v.(*GitPullRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_rill_runtime_v1_api_proto_msgTypes[127].Exporter = func(v any, i int) any { + switch v := v.(*GitPullResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_rill_runtime_v1_api_proto_msgTypes[128].Exporter = func(v any, i int) any { + switch v := v.(*GitPushRequest); i { case 0: return &v.state case 1: @@ -11556,6 +12445,18 @@ func file_rill_runtime_v1_api_proto_init() { } } file_rill_runtime_v1_api_proto_msgTypes[129].Exporter = func(v any, i int) any { + switch v := v.(*GitPushResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_rill_runtime_v1_api_proto_msgTypes[140].Exporter = func(v any, i int) any { switch v := v.(*ConnectorDriver_Property); i { case 0: return &v.state @@ -11575,7 +12476,7 @@ func file_rill_runtime_v1_api_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_rill_runtime_v1_api_proto_rawDesc, NumEnums: 4, - NumMessages: 132, + NumMessages: 143, NumExtensions: 0, NumServices: 1, }, diff --git a/proto/gen/rill/runtime/v1/api.pb.gw.go b/proto/gen/rill/runtime/v1/api.pb.gw.go index 4f136bd9b01..af2ae5bdb9c 100644 --- a/proto/gen/rill/runtime/v1/api.pb.gw.go +++ b/proto/gen/rill/runtime/v1/api.pb.gw.go @@ -1124,6 +1124,162 @@ func local_request_RuntimeService_GenerateCanvasFile_0(ctx context.Context, mars } +func request_RuntimeService_GenerateTemplate_0(ctx context.Context, marshaler runtime.Marshaler, client RuntimeServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GenerateTemplateRequest + var metadata runtime.ServerMetadata + + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["instance_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "instance_id") + } + + protoReq.InstanceId, err = runtime.String(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "instance_id", err) + } + + msg, err := client.GenerateTemplate(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_RuntimeService_GenerateTemplate_0(ctx context.Context, marshaler runtime.Marshaler, server RuntimeServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GenerateTemplateRequest + var metadata runtime.ServerMetadata + + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["instance_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "instance_id") + } + + protoReq.InstanceId, err = runtime.String(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "instance_id", err) + } + + msg, err := server.GenerateTemplate(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_RuntimeService_ListTemplates_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_RuntimeService_ListTemplates_0(ctx context.Context, marshaler runtime.Marshaler, client RuntimeServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq ListTemplatesRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_RuntimeService_ListTemplates_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.ListTemplates(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_RuntimeService_ListTemplates_0(ctx context.Context, marshaler runtime.Marshaler, server RuntimeServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq ListTemplatesRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_RuntimeService_ListTemplates_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.ListTemplates(ctx, &protoReq) + return msg, metadata, err + +} + +func request_RuntimeService_GenerateFile_0(ctx context.Context, marshaler runtime.Marshaler, client RuntimeServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GenerateFileRequest + var metadata runtime.ServerMetadata + + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["instance_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "instance_id") + } + + protoReq.InstanceId, err = runtime.String(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "instance_id", err) + } + + msg, err := client.GenerateFile(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_RuntimeService_GenerateFile_0(ctx context.Context, marshaler runtime.Marshaler, server RuntimeServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GenerateFileRequest + var metadata runtime.ServerMetadata + + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["instance_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "instance_id") + } + + protoReq.InstanceId, err = runtime.String(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "instance_id", err) + } + + msg, err := server.GenerateFile(ctx, &protoReq) + return msg, metadata, err + +} + func request_RuntimeService_QueryResolver_0(ctx context.Context, marshaler runtime.Marshaler, client RuntimeServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryResolverRequest var metadata runtime.ServerMetadata @@ -3516,6 +3672,81 @@ func RegisterRuntimeServiceHandlerServer(ctx context.Context, mux *runtime.Serve }) + mux.Handle("POST", pattern_RuntimeService_GenerateTemplate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/rill.runtime.v1.RuntimeService/GenerateTemplate", runtime.WithHTTPPathPattern("/v1/instances/{instance_id}/generate/template")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_RuntimeService_GenerateTemplate_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + + forward_RuntimeService_GenerateTemplate_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_RuntimeService_ListTemplates_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/rill.runtime.v1.RuntimeService/ListTemplates", runtime.WithHTTPPathPattern("/v1/templates")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_RuntimeService_ListTemplates_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + + forward_RuntimeService_ListTemplates_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_RuntimeService_GenerateFile_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/rill.runtime.v1.RuntimeService/GenerateFile", runtime.WithHTTPPathPattern("/v1/instances/{instance_id}/generate/file")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_RuntimeService_GenerateFile_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + + forward_RuntimeService_GenerateFile_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("POST", pattern_RuntimeService_QueryResolver_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -4740,6 +4971,72 @@ func RegisterRuntimeServiceHandlerClient(ctx context.Context, mux *runtime.Serve }) + mux.Handle("POST", pattern_RuntimeService_GenerateTemplate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/rill.runtime.v1.RuntimeService/GenerateTemplate", runtime.WithHTTPPathPattern("/v1/instances/{instance_id}/generate/template")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_RuntimeService_GenerateTemplate_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + + forward_RuntimeService_GenerateTemplate_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_RuntimeService_ListTemplates_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/rill.runtime.v1.RuntimeService/ListTemplates", runtime.WithHTTPPathPattern("/v1/templates")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_RuntimeService_ListTemplates_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + + forward_RuntimeService_ListTemplates_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_RuntimeService_GenerateFile_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/rill.runtime.v1.RuntimeService/GenerateFile", runtime.WithHTTPPathPattern("/v1/instances/{instance_id}/generate/file")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_RuntimeService_GenerateFile_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + + forward_RuntimeService_GenerateFile_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("POST", pattern_RuntimeService_QueryResolver_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -5468,6 +5765,12 @@ var ( pattern_RuntimeService_GenerateCanvasFile_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 2, 4}, []string{"v1", "instances", "instance_id", "files", "generate-canvas"}, "")) + pattern_RuntimeService_GenerateTemplate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 2, 4}, []string{"v1", "instances", "instance_id", "generate", "template"}, "")) + + pattern_RuntimeService_ListTemplates_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "templates"}, "")) + + pattern_RuntimeService_GenerateFile_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 2, 4}, []string{"v1", "instances", "instance_id", "generate", "file"}, "")) + pattern_RuntimeService_QueryResolver_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 2, 4}, []string{"v1", "instances", "instance_id", "query", "resolver"}, "")) pattern_RuntimeService_GetLogs_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3}, []string{"v1", "instances", "instance_id", "logs"}, "")) @@ -5574,6 +5877,12 @@ var ( forward_RuntimeService_GenerateCanvasFile_0 = runtime.ForwardResponseMessage + forward_RuntimeService_GenerateTemplate_0 = runtime.ForwardResponseMessage + + forward_RuntimeService_ListTemplates_0 = runtime.ForwardResponseMessage + + forward_RuntimeService_GenerateFile_0 = runtime.ForwardResponseMessage + forward_RuntimeService_QueryResolver_0 = runtime.ForwardResponseMessage forward_RuntimeService_GetLogs_0 = runtime.ForwardResponseMessage diff --git a/proto/gen/rill/runtime/v1/api.pb.validate.go b/proto/gen/rill/runtime/v1/api.pb.validate.go index 7e5a02dd9e3..72d2bf69266 100644 --- a/proto/gen/rill/runtime/v1/api.pb.validate.go +++ b/proto/gen/rill/runtime/v1/api.pb.validate.go @@ -5849,6 +5849,1213 @@ var _ interface { ErrorName() string } = GenerateCanvasFileResponseValidationError{} +// Validate checks the field values on GenerateTemplateRequest with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *GenerateTemplateRequest) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on GenerateTemplateRequest with the +// rules defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// GenerateTemplateRequestMultiError, or nil if none found. +func (m *GenerateTemplateRequest) ValidateAll() error { + return m.validate(true) +} + +func (m *GenerateTemplateRequest) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if !_GenerateTemplateRequest_InstanceId_Pattern.MatchString(m.GetInstanceId()) { + err := GenerateTemplateRequestValidationError{ + field: "InstanceId", + reason: "value does not match regex pattern \"^[_\\\\-a-zA-Z0-9]+$\"", + } + if !all { + return err + } + errors = append(errors, err) + } + + if _, ok := _GenerateTemplateRequest_ResourceType_InLookup[m.GetResourceType()]; !ok { + err := GenerateTemplateRequestValidationError{ + field: "ResourceType", + reason: "value must be in list [connector model]", + } + if !all { + return err + } + errors = append(errors, err) + } + + if !_GenerateTemplateRequest_Driver_Pattern.MatchString(m.GetDriver()) { + err := GenerateTemplateRequestValidationError{ + field: "Driver", + reason: "value does not match regex pattern \"^[a-z][a-z0-9_]*$\"", + } + if !all { + return err + } + errors = append(errors, err) + } + + if all { + switch v := interface{}(m.GetProperties()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, GenerateTemplateRequestValidationError{ + field: "Properties", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, GenerateTemplateRequestValidationError{ + field: "Properties", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetProperties()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return GenerateTemplateRequestValidationError{ + field: "Properties", + reason: "embedded message failed validation", + cause: err, + } + } + } + + // no validation rules for ConnectorName + + if len(errors) > 0 { + return GenerateTemplateRequestMultiError(errors) + } + + return nil +} + +// GenerateTemplateRequestMultiError is an error wrapping multiple validation +// errors returned by GenerateTemplateRequest.ValidateAll() if the designated +// constraints aren't met. +type GenerateTemplateRequestMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m GenerateTemplateRequestMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m GenerateTemplateRequestMultiError) AllErrors() []error { return m } + +// GenerateTemplateRequestValidationError is the validation error returned by +// GenerateTemplateRequest.Validate if the designated constraints aren't met. +type GenerateTemplateRequestValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e GenerateTemplateRequestValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e GenerateTemplateRequestValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e GenerateTemplateRequestValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e GenerateTemplateRequestValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e GenerateTemplateRequestValidationError) ErrorName() string { + return "GenerateTemplateRequestValidationError" +} + +// Error satisfies the builtin error interface +func (e GenerateTemplateRequestValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sGenerateTemplateRequest.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = GenerateTemplateRequestValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = GenerateTemplateRequestValidationError{} + +var _GenerateTemplateRequest_InstanceId_Pattern = regexp.MustCompile("^[_\\-a-zA-Z0-9]+$") + +var _GenerateTemplateRequest_ResourceType_InLookup = map[string]struct{}{ + "connector": {}, + "model": {}, +} + +var _GenerateTemplateRequest_Driver_Pattern = regexp.MustCompile("^[a-z][a-z0-9_]*$") + +// Validate checks the field values on GenerateTemplateResponse with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *GenerateTemplateResponse) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on GenerateTemplateResponse with the +// rules defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// GenerateTemplateResponseMultiError, or nil if none found. +func (m *GenerateTemplateResponse) ValidateAll() error { + return m.validate(true) +} + +func (m *GenerateTemplateResponse) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for Blob + + // no validation rules for EnvVars + + // no validation rules for ResourceType + + // no validation rules for Driver + + if len(errors) > 0 { + return GenerateTemplateResponseMultiError(errors) + } + + return nil +} + +// GenerateTemplateResponseMultiError is an error wrapping multiple validation +// errors returned by GenerateTemplateResponse.ValidateAll() if the designated +// constraints aren't met. +type GenerateTemplateResponseMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m GenerateTemplateResponseMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m GenerateTemplateResponseMultiError) AllErrors() []error { return m } + +// GenerateTemplateResponseValidationError is the validation error returned by +// GenerateTemplateResponse.Validate if the designated constraints aren't met. +type GenerateTemplateResponseValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e GenerateTemplateResponseValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e GenerateTemplateResponseValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e GenerateTemplateResponseValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e GenerateTemplateResponseValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e GenerateTemplateResponseValidationError) ErrorName() string { + return "GenerateTemplateResponseValidationError" +} + +// Error satisfies the builtin error interface +func (e GenerateTemplateResponseValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sGenerateTemplateResponse.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = GenerateTemplateResponseValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = GenerateTemplateResponseValidationError{} + +// Validate checks the field values on Template with the rules defined in the +// proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *Template) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on Template with the rules defined in +// the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in TemplateMultiError, or nil +// if none found. +func (m *Template) ValidateAll() error { + return m.validate(true) +} + +func (m *Template) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for Name + + // no validation rules for DisplayName + + // no validation rules for Driver + + // no validation rules for Olap + + for idx, item := range m.GetFiles() { + _, _ = idx, item + + if all { + switch v := interface{}(item).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, TemplateValidationError{ + field: fmt.Sprintf("Files[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, TemplateValidationError{ + field: fmt.Sprintf("Files[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return TemplateValidationError{ + field: fmt.Sprintf("Files[%v]", idx), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + + if all { + switch v := interface{}(m.GetJsonSchema()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, TemplateValidationError{ + field: "JsonSchema", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, TemplateValidationError{ + field: "JsonSchema", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetJsonSchema()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return TemplateValidationError{ + field: "JsonSchema", + reason: "embedded message failed validation", + cause: err, + } + } + } + + // no validation rules for Description + + // no validation rules for DocsUrl + + // no validation rules for Icon + + // no validation rules for SmallIcon + + if len(errors) > 0 { + return TemplateMultiError(errors) + } + + return nil +} + +// TemplateMultiError is an error wrapping multiple validation errors returned +// by Template.ValidateAll() if the designated constraints aren't met. +type TemplateMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m TemplateMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m TemplateMultiError) AllErrors() []error { return m } + +// TemplateValidationError is the validation error returned by +// Template.Validate if the designated constraints aren't met. +type TemplateValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e TemplateValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e TemplateValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e TemplateValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e TemplateValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e TemplateValidationError) ErrorName() string { return "TemplateValidationError" } + +// Error satisfies the builtin error interface +func (e TemplateValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sTemplate.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = TemplateValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = TemplateValidationError{} + +// Validate checks the field values on TemplateFile with the rules defined in +// the proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *TemplateFile) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on TemplateFile with the rules defined +// in the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in TemplateFileMultiError, or +// nil if none found. +func (m *TemplateFile) ValidateAll() error { + return m.validate(true) +} + +func (m *TemplateFile) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for Name + + // no validation rules for PathPattern + + if len(errors) > 0 { + return TemplateFileMultiError(errors) + } + + return nil +} + +// TemplateFileMultiError is an error wrapping multiple validation errors +// returned by TemplateFile.ValidateAll() if the designated constraints aren't met. +type TemplateFileMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m TemplateFileMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m TemplateFileMultiError) AllErrors() []error { return m } + +// TemplateFileValidationError is the validation error returned by +// TemplateFile.Validate if the designated constraints aren't met. +type TemplateFileValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e TemplateFileValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e TemplateFileValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e TemplateFileValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e TemplateFileValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e TemplateFileValidationError) ErrorName() string { return "TemplateFileValidationError" } + +// Error satisfies the builtin error interface +func (e TemplateFileValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sTemplateFile.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = TemplateFileValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = TemplateFileValidationError{} + +// Validate checks the field values on ListTemplatesRequest with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *ListTemplatesRequest) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on ListTemplatesRequest with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// ListTemplatesRequestMultiError, or nil if none found. +func (m *ListTemplatesRequest) ValidateAll() error { + return m.validate(true) +} + +func (m *ListTemplatesRequest) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if len(errors) > 0 { + return ListTemplatesRequestMultiError(errors) + } + + return nil +} + +// ListTemplatesRequestMultiError is an error wrapping multiple validation +// errors returned by ListTemplatesRequest.ValidateAll() if the designated +// constraints aren't met. +type ListTemplatesRequestMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m ListTemplatesRequestMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m ListTemplatesRequestMultiError) AllErrors() []error { return m } + +// ListTemplatesRequestValidationError is the validation error returned by +// ListTemplatesRequest.Validate if the designated constraints aren't met. +type ListTemplatesRequestValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e ListTemplatesRequestValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e ListTemplatesRequestValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e ListTemplatesRequestValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e ListTemplatesRequestValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e ListTemplatesRequestValidationError) ErrorName() string { + return "ListTemplatesRequestValidationError" +} + +// Error satisfies the builtin error interface +func (e ListTemplatesRequestValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sListTemplatesRequest.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = ListTemplatesRequestValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = ListTemplatesRequestValidationError{} + +// Validate checks the field values on ListTemplatesResponse with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *ListTemplatesResponse) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on ListTemplatesResponse with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// ListTemplatesResponseMultiError, or nil if none found. +func (m *ListTemplatesResponse) ValidateAll() error { + return m.validate(true) +} + +func (m *ListTemplatesResponse) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + for idx, item := range m.GetTemplates() { + _, _ = idx, item + + if all { + switch v := interface{}(item).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, ListTemplatesResponseValidationError{ + field: fmt.Sprintf("Templates[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, ListTemplatesResponseValidationError{ + field: fmt.Sprintf("Templates[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ListTemplatesResponseValidationError{ + field: fmt.Sprintf("Templates[%v]", idx), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + + if len(errors) > 0 { + return ListTemplatesResponseMultiError(errors) + } + + return nil +} + +// ListTemplatesResponseMultiError is an error wrapping multiple validation +// errors returned by ListTemplatesResponse.ValidateAll() if the designated +// constraints aren't met. +type ListTemplatesResponseMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m ListTemplatesResponseMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m ListTemplatesResponseMultiError) AllErrors() []error { return m } + +// ListTemplatesResponseValidationError is the validation error returned by +// ListTemplatesResponse.Validate if the designated constraints aren't met. +type ListTemplatesResponseValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e ListTemplatesResponseValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e ListTemplatesResponseValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e ListTemplatesResponseValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e ListTemplatesResponseValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e ListTemplatesResponseValidationError) ErrorName() string { + return "ListTemplatesResponseValidationError" +} + +// Error satisfies the builtin error interface +func (e ListTemplatesResponseValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sListTemplatesResponse.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = ListTemplatesResponseValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = ListTemplatesResponseValidationError{} + +// Validate checks the field values on GenerateFileRequest with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *GenerateFileRequest) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on GenerateFileRequest with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// GenerateFileRequestMultiError, or nil if none found. +func (m *GenerateFileRequest) ValidateAll() error { + return m.validate(true) +} + +func (m *GenerateFileRequest) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if !_GenerateFileRequest_InstanceId_Pattern.MatchString(m.GetInstanceId()) { + err := GenerateFileRequestValidationError{ + field: "InstanceId", + reason: "value does not match regex pattern \"^[_\\\\-a-zA-Z0-9]+$\"", + } + if !all { + return err + } + errors = append(errors, err) + } + + if utf8.RuneCountInString(m.GetTemplateName()) < 1 { + err := GenerateFileRequestValidationError{ + field: "TemplateName", + reason: "value length must be at least 1 runes", + } + if !all { + return err + } + errors = append(errors, err) + } + + // no validation rules for Output + + if all { + switch v := interface{}(m.GetProperties()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, GenerateFileRequestValidationError{ + field: "Properties", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, GenerateFileRequestValidationError{ + field: "Properties", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetProperties()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return GenerateFileRequestValidationError{ + field: "Properties", + reason: "embedded message failed validation", + cause: err, + } + } + } + + // no validation rules for ConnectorName + + // no validation rules for Preview + + if len(errors) > 0 { + return GenerateFileRequestMultiError(errors) + } + + return nil +} + +// GenerateFileRequestMultiError is an error wrapping multiple validation +// errors returned by GenerateFileRequest.ValidateAll() if the designated +// constraints aren't met. +type GenerateFileRequestMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m GenerateFileRequestMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m GenerateFileRequestMultiError) AllErrors() []error { return m } + +// GenerateFileRequestValidationError is the validation error returned by +// GenerateFileRequest.Validate if the designated constraints aren't met. +type GenerateFileRequestValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e GenerateFileRequestValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e GenerateFileRequestValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e GenerateFileRequestValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e GenerateFileRequestValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e GenerateFileRequestValidationError) ErrorName() string { + return "GenerateFileRequestValidationError" +} + +// Error satisfies the builtin error interface +func (e GenerateFileRequestValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sGenerateFileRequest.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = GenerateFileRequestValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = GenerateFileRequestValidationError{} + +var _GenerateFileRequest_InstanceId_Pattern = regexp.MustCompile("^[_\\-a-zA-Z0-9]+$") + +// Validate checks the field values on GenerateFileResponse with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *GenerateFileResponse) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on GenerateFileResponse with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// GenerateFileResponseMultiError, or nil if none found. +func (m *GenerateFileResponse) ValidateAll() error { + return m.validate(true) +} + +func (m *GenerateFileResponse) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + for idx, item := range m.GetFiles() { + _, _ = idx, item + + if all { + switch v := interface{}(item).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, GenerateFileResponseValidationError{ + field: fmt.Sprintf("Files[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, GenerateFileResponseValidationError{ + field: fmt.Sprintf("Files[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return GenerateFileResponseValidationError{ + field: fmt.Sprintf("Files[%v]", idx), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + + // no validation rules for EnvVars + + if len(errors) > 0 { + return GenerateFileResponseMultiError(errors) + } + + return nil +} + +// GenerateFileResponseMultiError is an error wrapping multiple validation +// errors returned by GenerateFileResponse.ValidateAll() if the designated +// constraints aren't met. +type GenerateFileResponseMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m GenerateFileResponseMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m GenerateFileResponseMultiError) AllErrors() []error { return m } + +// GenerateFileResponseValidationError is the validation error returned by +// GenerateFileResponse.Validate if the designated constraints aren't met. +type GenerateFileResponseValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e GenerateFileResponseValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e GenerateFileResponseValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e GenerateFileResponseValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e GenerateFileResponseValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e GenerateFileResponseValidationError) ErrorName() string { + return "GenerateFileResponseValidationError" +} + +// Error satisfies the builtin error interface +func (e GenerateFileResponseValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sGenerateFileResponse.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = GenerateFileResponseValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = GenerateFileResponseValidationError{} + +// Validate checks the field values on GeneratedFile with the rules defined in +// the proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *GeneratedFile) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on GeneratedFile with the rules defined +// in the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in GeneratedFileMultiError, or +// nil if none found. +func (m *GeneratedFile) ValidateAll() error { + return m.validate(true) +} + +func (m *GeneratedFile) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for Path + + // no validation rules for Blob + + if len(errors) > 0 { + return GeneratedFileMultiError(errors) + } + + return nil +} + +// GeneratedFileMultiError is an error wrapping multiple validation errors +// returned by GeneratedFile.ValidateAll() if the designated constraints +// aren't met. +type GeneratedFileMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m GeneratedFileMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m GeneratedFileMultiError) AllErrors() []error { return m } + +// GeneratedFileValidationError is the validation error returned by +// GeneratedFile.Validate if the designated constraints aren't met. +type GeneratedFileValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e GeneratedFileValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e GeneratedFileValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e GeneratedFileValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e GeneratedFileValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e GeneratedFileValidationError) ErrorName() string { return "GeneratedFileValidationError" } + +// Error satisfies the builtin error interface +func (e GeneratedFileValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sGeneratedFile.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = GeneratedFileValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = GeneratedFileValidationError{} + // Validate checks the field values on QueryResolverRequest with the rules // defined in the proto definition for this message. If any rules are // violated, the first error encountered is returned, or nil if there are no violations. diff --git a/proto/gen/rill/runtime/v1/api_grpc.pb.go b/proto/gen/rill/runtime/v1/api_grpc.pb.go index e262ff3539e..37d8736194b 100644 --- a/proto/gen/rill/runtime/v1/api_grpc.pb.go +++ b/proto/gen/rill/runtime/v1/api_grpc.pb.go @@ -40,6 +40,9 @@ const ( RuntimeService_UnpackEmpty_FullMethodName = "/rill.runtime.v1.RuntimeService/UnpackEmpty" RuntimeService_GenerateMetricsViewFile_FullMethodName = "/rill.runtime.v1.RuntimeService/GenerateMetricsViewFile" RuntimeService_GenerateCanvasFile_FullMethodName = "/rill.runtime.v1.RuntimeService/GenerateCanvasFile" + RuntimeService_GenerateTemplate_FullMethodName = "/rill.runtime.v1.RuntimeService/GenerateTemplate" + RuntimeService_ListTemplates_FullMethodName = "/rill.runtime.v1.RuntimeService/ListTemplates" + RuntimeService_GenerateFile_FullMethodName = "/rill.runtime.v1.RuntimeService/GenerateFile" RuntimeService_QueryResolver_FullMethodName = "/rill.runtime.v1.RuntimeService/QueryResolver" RuntimeService_GetLogs_FullMethodName = "/rill.runtime.v1.RuntimeService/GetLogs" RuntimeService_WatchLogs_FullMethodName = "/rill.runtime.v1.RuntimeService/WatchLogs" @@ -124,6 +127,12 @@ type RuntimeServiceClient interface { GenerateMetricsViewFile(ctx context.Context, in *GenerateMetricsViewFileRequest, opts ...grpc.CallOption) (*GenerateMetricsViewFileResponse, error) // GenerateCanvasFile generates a canvas YAML file from a metrics view GenerateCanvasFile(ctx context.Context, in *GenerateCanvasFileRequest, opts ...grpc.CallOption) (*GenerateCanvasFileResponse, error) + // GenerateTemplate generates a connector or model YAML file from structured form data + GenerateTemplate(ctx context.Context, in *GenerateTemplateRequest, opts ...grpc.CallOption) (*GenerateTemplateResponse, error) + // ListTemplates returns available template definitions for generating project files + ListTemplates(ctx context.Context, in *ListTemplatesRequest, opts ...grpc.CallOption) (*ListTemplatesResponse, error) + // GenerateFile renders a template with properties and optionally writes the resulting files + GenerateFile(ctx context.Context, in *GenerateFileRequest, opts ...grpc.CallOption) (*GenerateFileResponse, error) // QueryResolver queries a resolver with the given properties and arguments QueryResolver(ctx context.Context, in *QueryResolverRequest, opts ...grpc.CallOption) (*QueryResolverResponse, error) // GetLogs returns recent logs from a controller @@ -423,6 +432,36 @@ func (c *runtimeServiceClient) GenerateCanvasFile(ctx context.Context, in *Gener return out, nil } +func (c *runtimeServiceClient) GenerateTemplate(ctx context.Context, in *GenerateTemplateRequest, opts ...grpc.CallOption) (*GenerateTemplateResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GenerateTemplateResponse) + err := c.cc.Invoke(ctx, RuntimeService_GenerateTemplate_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *runtimeServiceClient) ListTemplates(ctx context.Context, in *ListTemplatesRequest, opts ...grpc.CallOption) (*ListTemplatesResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListTemplatesResponse) + err := c.cc.Invoke(ctx, RuntimeService_ListTemplates_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *runtimeServiceClient) GenerateFile(ctx context.Context, in *GenerateFileRequest, opts ...grpc.CallOption) (*GenerateFileResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GenerateFileResponse) + err := c.cc.Invoke(ctx, RuntimeService_GenerateFile_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *runtimeServiceClient) QueryResolver(ctx context.Context, in *QueryResolverRequest, opts ...grpc.CallOption) (*QueryResolverResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(QueryResolverResponse) @@ -811,6 +850,12 @@ type RuntimeServiceServer interface { GenerateMetricsViewFile(context.Context, *GenerateMetricsViewFileRequest) (*GenerateMetricsViewFileResponse, error) // GenerateCanvasFile generates a canvas YAML file from a metrics view GenerateCanvasFile(context.Context, *GenerateCanvasFileRequest) (*GenerateCanvasFileResponse, error) + // GenerateTemplate generates a connector or model YAML file from structured form data + GenerateTemplate(context.Context, *GenerateTemplateRequest) (*GenerateTemplateResponse, error) + // ListTemplates returns available template definitions for generating project files + ListTemplates(context.Context, *ListTemplatesRequest) (*ListTemplatesResponse, error) + // GenerateFile renders a template with properties and optionally writes the resulting files + GenerateFile(context.Context, *GenerateFileRequest) (*GenerateFileResponse, error) // QueryResolver queries a resolver with the given properties and arguments QueryResolver(context.Context, *QueryResolverRequest) (*QueryResolverResponse, error) // GetLogs returns recent logs from a controller @@ -954,6 +999,15 @@ func (UnimplementedRuntimeServiceServer) GenerateMetricsViewFile(context.Context func (UnimplementedRuntimeServiceServer) GenerateCanvasFile(context.Context, *GenerateCanvasFileRequest) (*GenerateCanvasFileResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GenerateCanvasFile not implemented") } +func (UnimplementedRuntimeServiceServer) GenerateTemplate(context.Context, *GenerateTemplateRequest) (*GenerateTemplateResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GenerateTemplate not implemented") +} +func (UnimplementedRuntimeServiceServer) ListTemplates(context.Context, *ListTemplatesRequest) (*ListTemplatesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ListTemplates not implemented") +} +func (UnimplementedRuntimeServiceServer) GenerateFile(context.Context, *GenerateFileRequest) (*GenerateFileResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GenerateFile not implemented") +} func (UnimplementedRuntimeServiceServer) QueryResolver(context.Context, *QueryResolverRequest) (*QueryResolverResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method QueryResolver not implemented") } @@ -1439,6 +1493,60 @@ func _RuntimeService_GenerateCanvasFile_Handler(srv interface{}, ctx context.Con return interceptor(ctx, in, info, handler) } +func _RuntimeService_GenerateTemplate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GenerateTemplateRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RuntimeServiceServer).GenerateTemplate(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: RuntimeService_GenerateTemplate_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RuntimeServiceServer).GenerateTemplate(ctx, req.(*GenerateTemplateRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _RuntimeService_ListTemplates_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListTemplatesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RuntimeServiceServer).ListTemplates(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: RuntimeService_ListTemplates_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RuntimeServiceServer).ListTemplates(ctx, req.(*ListTemplatesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _RuntimeService_GenerateFile_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GenerateFileRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RuntimeServiceServer).GenerateFile(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: RuntimeService_GenerateFile_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RuntimeServiceServer).GenerateFile(ctx, req.(*GenerateFileRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _RuntimeService_QueryResolver_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(QueryResolverRequest) if err := dec(in); err != nil { @@ -2063,6 +2171,18 @@ var RuntimeService_ServiceDesc = grpc.ServiceDesc{ MethodName: "GenerateCanvasFile", Handler: _RuntimeService_GenerateCanvasFile_Handler, }, + { + MethodName: "GenerateTemplate", + Handler: _RuntimeService_GenerateTemplate_Handler, + }, + { + MethodName: "ListTemplates", + Handler: _RuntimeService_ListTemplates_Handler, + }, + { + MethodName: "GenerateFile", + Handler: _RuntimeService_GenerateFile_Handler, + }, { MethodName: "QueryResolver", Handler: _RuntimeService_QueryResolver_Handler, diff --git a/proto/gen/rill/runtime/v1/runtime.swagger.yaml b/proto/gen/rill/runtime/v1/runtime.swagger.yaml index de602a1d20e..f88244e4a98 100644 --- a/proto/gen/rill/runtime/v1/runtime.swagger.yaml +++ b/proto/gen/rill/runtime/v1/runtime.swagger.yaml @@ -1163,6 +1163,80 @@ paths: type: boolean tags: - RuntimeService + /v1/instances/{instanceId}/generate/file: + post: + summary: GenerateFile renders a template with properties and optionally writes the resulting files + operationId: RuntimeService_GenerateFile + responses: + "200": + description: A successful response. + schema: + $ref: '#/definitions/v1GenerateFileResponse' + default: + description: An unexpected error response. + schema: + $ref: '#/definitions/rpcStatus' + parameters: + - name: instanceId + in: path + required: true + type: string + - name: body + in: body + required: true + schema: + type: object + properties: + templateName: + type: string + title: Template name (e.g. "s3", "s3-duckdb", "iceberg-duckdb") + output: + type: string + title: 'Output filter: "connector", "model", or empty for all files' + properties: + type: object + connectorName: + type: string + title: Connector name reference (for model outputs that reference a connector) + preview: + type: boolean + title: If true, render without writing files (for YAML preview) + tags: + - RuntimeService + /v1/instances/{instanceId}/generate/template: + post: + summary: GenerateTemplate generates a connector or model YAML file from structured form data + operationId: RuntimeService_GenerateTemplate + responses: + "200": + description: A successful response. + schema: + $ref: '#/definitions/v1GenerateTemplateResponse' + default: + description: An unexpected error response. + schema: + $ref: '#/definitions/rpcStatus' + parameters: + - name: instanceId + in: path + required: true + type: string + - name: body + in: body + required: true + schema: + type: object + properties: + resourceType: + type: string + driver: + type: string + properties: + type: object + connectorName: + type: string + tags: + - RuntimeService /v1/instances/{instanceId}/git/branches: get: operationId: RuntimeService_ListGitBranches @@ -3567,6 +3641,30 @@ paths: $ref: '#/definitions/rpcStatus' tags: - RuntimeService + /v1/templates: + get: + summary: ListTemplates returns available template definitions for generating project files + operationId: RuntimeService_ListTemplates + responses: + "200": + description: A successful response. + schema: + $ref: '#/definitions/v1ListTemplatesResponse' + default: + description: An unexpected error response. + schema: + $ref: '#/definitions/rpcStatus' + parameters: + - name: tags + description: Optional tag filter; only templates matching ALL tags are returned. + in: query + required: false + type: array + items: + type: string + collectionFormat: multi + tags: + - RuntimeService definitions: ColumnTimeSeriesRequestBasicMeasure: type: object @@ -5310,6 +5408,18 @@ definitions: type: boolean description: Indicates if AI-based generation succeeded. If it failed, it falls back to the simpler heuristic approach. title: Response message for RuntimeService.GenerateCanvasFile + v1GenerateFileResponse: + type: object + properties: + files: + type: array + items: + type: object + $ref: '#/definitions/v1GeneratedFile' + envVars: + type: object + additionalProperties: + type: string v1GenerateMetricsViewFileResponse: type: object properties: @@ -5317,6 +5427,29 @@ definitions: type: boolean description: Indicates if AI-based generation succeeded. If it failed, it falls back to the simpler heuristic approach. title: Response message for RuntimeService.GenerateMetricsViewFile + v1GenerateTemplateResponse: + type: object + properties: + blob: + type: string + envVars: + type: object + additionalProperties: + type: string + resourceType: + type: string + title: Actual resource type used; may differ from request when driver is rewritten + driver: + type: string + title: Actual driver used; may differ from request when rewritten to duckdb + v1GeneratedFile: + type: object + properties: + path: + type: string + blob: + type: string + description: GeneratedFile is a single rendered output file. v1GetAIMessageResponse: type: object properties: @@ -5713,6 +5846,14 @@ definitions: $ref: '#/definitions/v1TableInfo' nextPageToken: type: string + v1ListTemplatesResponse: + type: object + properties: + templates: + type: array + items: + type: object + $ref: '#/definitions/v1Template' v1ListToolsResponse: type: object properties: @@ -7773,6 +7914,50 @@ definitions: type: array items: type: object + v1Template: + type: object + properties: + name: + type: string + displayName: + type: string + driver: + type: string + olap: + type: string + tags: + type: array + items: + type: string + files: + type: array + items: + type: object + $ref: '#/definitions/v1TemplateFile' + jsonSchema: + type: object + description: JSON Schema for form generation and property metadata. + description: + type: string + description: Short description of the template. + docsUrl: + type: string + description: Link to documentation. + icon: + type: string + description: Icon component name for full-size display. + smallIcon: + type: string + description: Icon component name for small display. + description: Template describes a declarative template for generating project files. + v1TemplateFile: + type: object + properties: + name: + type: string + pathPattern: + type: string + description: TemplateFile describes a single output file within a template. v1Theme: type: object properties: diff --git a/proto/rill/runtime/v1/api.proto b/proto/rill/runtime/v1/api.proto index 13fe3dd46fe..e670f11067a 100644 --- a/proto/rill/runtime/v1/api.proto +++ b/proto/rill/runtime/v1/api.proto @@ -157,6 +157,27 @@ service RuntimeService { }; } + // GenerateTemplate generates a connector or model YAML file from structured form data + rpc GenerateTemplate(GenerateTemplateRequest) returns (GenerateTemplateResponse) { + option (google.api.http) = { + post: "/v1/instances/{instance_id}/generate/template", + body: "*" + }; + } + + // ListTemplates returns available template definitions for generating project files + rpc ListTemplates(ListTemplatesRequest) returns (ListTemplatesResponse) { + option (google.api.http) = {get: "/v1/templates"}; + } + + // GenerateFile renders a template with properties and optionally writes the resulting files + rpc GenerateFile(GenerateFileRequest) returns (GenerateFileResponse) { + option (google.api.http) = { + post: "/v1/instances/{instance_id}/generate/file", + body: "*" + }; + } + // QueryResolver queries a resolver with the given properties and arguments rpc QueryResolver(QueryResolverRequest) returns (QueryResolverResponse) { option (google.api.http) = { @@ -722,6 +743,82 @@ message GenerateCanvasFileResponse { bool ai_succeeded = 1; } +message GenerateTemplateRequest { + string instance_id = 1 [(validate.rules).string = {pattern: "^[_\\-a-zA-Z0-9]+$"}]; + string resource_type = 2 [(validate.rules).string = {in: ["connector", "model"]}]; + string driver = 3 [(validate.rules).string = {pattern: "^[a-z][a-z0-9_]*$"}]; + google.protobuf.Struct properties = 4; + string connector_name = 5; +} + +message GenerateTemplateResponse { + string blob = 1; + map env_vars = 2; + // Actual resource type used; may differ from request when driver is rewritten + string resource_type = 3; + // Actual driver used; may differ from request when rewritten to duckdb + string driver = 4; +} + +// Template describes a declarative template for generating project files. +message Template { + string name = 1; + string display_name = 2; + string driver = 3; + string olap = 4; + repeated string tags = 5; + repeated TemplateFile files = 6; + // JSON Schema for form generation and property metadata. + google.protobuf.Struct json_schema = 7; + // Short description of the template. + string description = 8; + // Link to documentation. + string docs_url = 9; + // Icon component name for full-size display. + string icon = 10; + // Icon component name for small display. + string small_icon = 11; +} + +// TemplateFile describes a single output file within a template. +message TemplateFile { + string name = 1; + string path_pattern = 2; +} + +message ListTemplatesRequest { + // Optional tag filter; only templates matching ALL tags are returned. + repeated string tags = 1; +} + +message ListTemplatesResponse { + repeated Template templates = 1; +} + +message GenerateFileRequest { + string instance_id = 1 [(validate.rules).string = {pattern: "^[_\\-a-zA-Z0-9]+$"}]; + // Template name (e.g. "s3", "s3-duckdb", "iceberg-duckdb") + string template_name = 2 [(validate.rules).string.min_len = 1]; + // Output filter: "connector", "model", or empty for all files + string output = 3; + google.protobuf.Struct properties = 4; + // Connector name reference (for model outputs that reference a connector) + string connector_name = 5; + // If true, render without writing files (for YAML preview) + bool preview = 6; +} + +message GenerateFileResponse { + repeated GeneratedFile files = 1; + map env_vars = 2; +} + +// GeneratedFile is a single rendered output file. +message GeneratedFile { + string path = 1; + string blob = 2; +} + message QueryResolverRequest { string instance_id = 1; string resolver = 2; diff --git a/runtime/drivers/athena/athena.go b/runtime/drivers/athena/athena.go index d0a4a2e3b49..3457aa4966b 100644 --- a/runtime/drivers/athena/athena.go +++ b/runtime/drivers/athena/athena.go @@ -43,6 +43,7 @@ var spec = drivers.Spec{ Placeholder: "your_access_key_id", Required: true, Secret: true, + EnvVarName: "AWS_ACCESS_KEY_ID", }, { Key: "aws_secret_access_key", @@ -52,6 +53,7 @@ var spec = drivers.Spec{ Placeholder: "your_secret_access_key", Required: true, Secret: true, + EnvVarName: "AWS_SECRET_ACCESS_KEY", }, { Key: "output_location", diff --git a/runtime/drivers/azure/azure.go b/runtime/drivers/azure/azure.go index 228ab0f2cde..a70d56025fe 100644 --- a/runtime/drivers/azure/azure.go +++ b/runtime/drivers/azure/azure.go @@ -29,14 +29,16 @@ var spec = drivers.Spec{ Secret: true, }, { - Key: "azure_storage_key", - Type: drivers.StringPropertyType, - Secret: true, + Key: "azure_storage_key", + Type: drivers.StringPropertyType, + Secret: true, + EnvVarName: "AZURE_STORAGE_KEY", }, { - Key: "azure_storage_sas_token", - Type: drivers.StringPropertyType, - Secret: true, + Key: "azure_storage_sas_token", + Type: drivers.StringPropertyType, + Secret: true, + EnvVarName: "AZURE_STORAGE_SAS_TOKEN", }, { Key: "azure_storage_connection_string", @@ -45,6 +47,7 @@ var spec = drivers.Spec{ Description: "Azure connection string for storage account", Placeholder: "Paste your Azure connection string here", Secret: true, + EnvVarName: "AZURE_STORAGE_CONNECTION_STRING", }, }, SourceProperties: []*drivers.PropertySpec{ diff --git a/runtime/drivers/bigquery/bigquery.go b/runtime/drivers/bigquery/bigquery.go index e8371bc5314..dfc3d7134f1 100644 --- a/runtime/drivers/bigquery/bigquery.go +++ b/runtime/drivers/bigquery/bigquery.go @@ -43,6 +43,7 @@ var spec = drivers.Spec{ Description: "GCP credentials as JSON string", Placeholder: "Paste your GCP service account JSON here", Secret: true, + EnvVarName: "GOOGLE_APPLICATION_CREDENTIALS", Required: true, }, }, diff --git a/runtime/drivers/clickhouse/clickhouse.go b/runtime/drivers/clickhouse/clickhouse.go index 9818fdba1a6..e1d90658df3 100644 --- a/runtime/drivers/clickhouse/clickhouse.go +++ b/runtime/drivers/clickhouse/clickhouse.go @@ -67,6 +67,7 @@ var spec = drivers.Spec{ DisplayName: "Connection string", Placeholder: "clickhouse://localhost:9000?username=default&password=password", Secret: true, + EnvVarName: "CLICKHOUSE_DSN", NoPrompt: true, }, { @@ -106,6 +107,7 @@ var spec = drivers.Spec{ Description: "Password to connect to the ClickHouse server", Placeholder: "Database password", Secret: true, + EnvVarName: "CLICKHOUSE_PASSWORD", Hint: "Password to your database", }, { diff --git a/runtime/drivers/connectors.go b/runtime/drivers/connectors.go index 72cad88651a..1d32ab1ee60 100644 --- a/runtime/drivers/connectors.go +++ b/runtime/drivers/connectors.go @@ -47,7 +47,12 @@ type PropertySpec struct { Default string Placeholder string Secret bool - NoPrompt bool + // EnvVarName is the conventional env var name for this property (e.g. AWS_ACCESS_KEY_ID, GOOGLE_APPLICATION_CREDENTIALS). + // It must be specified explicitly because the mapping doesn't follow a mechanical pattern; + // some keys use well-known names shared across drivers (AWS_*), others add infixes (AZURE_STORAGE_*), + // and others diverge entirely from the key name (GCS key_id -> GCP_ACCESS_KEY_ID). + EnvVarName string + NoPrompt bool } // PropertyType is an enum of types supported for connector properties. diff --git a/runtime/drivers/druid/druid.go b/runtime/drivers/druid/druid.go index bbef301dfa8..4eaba78e4b8 100644 --- a/runtime/drivers/druid/druid.go +++ b/runtime/drivers/druid/druid.go @@ -42,6 +42,7 @@ var spec = drivers.Spec{ DisplayName: "Connection string", Placeholder: "https://example.com/druid/v2/sql/avatica-protobuf?authentication=BASIC&avaticaUser=username&avaticaPassword=password", Secret: true, + EnvVarName: "DRUID_DSN", NoPrompt: true, }, { @@ -76,6 +77,7 @@ var spec = drivers.Spec{ Description: "Password to connect to the Druid server", Placeholder: "password", Secret: true, + EnvVarName: "DRUID_PASSWORD", }, { Key: "ssl", diff --git a/runtime/drivers/duckdb/duckdb.go b/runtime/drivers/duckdb/duckdb.go index 5f2f540434d..e6b4e1239ed 100644 --- a/runtime/drivers/duckdb/duckdb.go +++ b/runtime/drivers/duckdb/duckdb.go @@ -105,6 +105,7 @@ var motherduckSpec = drivers.Spec{ Key: "token", Type: drivers.StringPropertyType, Secret: true, + EnvVarName: "MOTHERDUCK_TOKEN", Required: true, DisplayName: "Token", Description: "MotherDuck token", diff --git a/runtime/drivers/gcs/gcs.go b/runtime/drivers/gcs/gcs.go index 1e8e0a3d72b..3fa91c9fd3c 100644 --- a/runtime/drivers/gcs/gcs.go +++ b/runtime/drivers/gcs/gcs.go @@ -37,6 +37,7 @@ var spec = drivers.Spec{ Description: "GCP credentials as JSON string", Placeholder: "Paste your GCP service account JSON here", Secret: true, + EnvVarName: "GOOGLE_APPLICATION_CREDENTIALS", }, { Key: "key_id", @@ -45,6 +46,7 @@ var spec = drivers.Spec{ Description: "HMAC access key ID for S3-compatible authentication", Hint: "Optional S3-compatible Key ID when used in compatibility mode", Secret: true, + EnvVarName: "GCP_ACCESS_KEY_ID", }, { Key: "secret", @@ -53,6 +55,7 @@ var spec = drivers.Spec{ Description: "HMAC secret access key for S3-compatible authentication", Hint: "Optional S3-compatible Secret when used in compatibility mode", Secret: true, + EnvVarName: "GCP_SECRET_ACCESS_KEY", }, }, SourceProperties: []*drivers.PropertySpec{ diff --git a/runtime/drivers/https/https.go b/runtime/drivers/https/https.go index 89aede1c3a7..d99690305b5 100644 --- a/runtime/drivers/https/https.go +++ b/runtime/drivers/https/https.go @@ -26,6 +26,14 @@ var spec = drivers.Spec{ Description: "Connect to a remote file.", DocsURL: "https://docs.rilldata.com/developers/build/connect/#adding-a-remote-source", // Important: Any edits to the below properties must be accompanied by changes to the client-side form validation schemas. + ConfigProperties: []*drivers.PropertySpec{ + { + Key: "headers", + Type: drivers.StringPropertyType, + DisplayName: "Headers", + Description: "HTTP headers to include in requests.", + }, + }, SourceProperties: []*drivers.PropertySpec{ { Key: "path", diff --git a/runtime/drivers/mysql/mysql.go b/runtime/drivers/mysql/mysql.go index 600cb670194..152d2eab94c 100644 --- a/runtime/drivers/mysql/mysql.go +++ b/runtime/drivers/mysql/mysql.go @@ -38,6 +38,7 @@ var spec = drivers.Spec{ Placeholder: "mysql://user:password@host:3306/my-db", Hint: "Can be configured here or by setting the 'connector.mysql.dsn' environment variable (using '.env' or '--env')", Secret: true, + EnvVarName: "MYSQL_DSN", }, { Key: "user", @@ -54,6 +55,7 @@ var spec = drivers.Spec{ Placeholder: "your_password", Hint: "MySQL password for authentication", Secret: true, + EnvVarName: "MYSQL_PASSWORD", }, { Key: "host", diff --git a/runtime/drivers/pinot/pinot.go b/runtime/drivers/pinot/pinot.go index 890fc50c281..4f3692e5011 100644 --- a/runtime/drivers/pinot/pinot.go +++ b/runtime/drivers/pinot/pinot.go @@ -36,6 +36,7 @@ var spec = drivers.Spec{ DisplayName: "Connection string", Placeholder: "http(s)://username:password@localhost:8000?controller=localhost:9000", Secret: true, + EnvVarName: "PINOT_DSN", NoPrompt: true, }, { @@ -86,6 +87,7 @@ var spec = drivers.Spec{ Description: "Password to connect to the Pinot server", Placeholder: "password", Secret: true, + EnvVarName: "PINOT_PASSWORD", }, { Key: "ssl", diff --git a/runtime/drivers/postgres/postgres.go b/runtime/drivers/postgres/postgres.go index 1e177dd13a4..257b774063b 100644 --- a/runtime/drivers/postgres/postgres.go +++ b/runtime/drivers/postgres/postgres.go @@ -39,6 +39,7 @@ var spec = drivers.Spec{ Placeholder: "postgresql://postgres:postgres@localhost:5432/postgres", Hint: "Can be configured here or by setting the 'connector.postgres.dsn' environment variable (using '.env' or '--env').", Secret: true, + EnvVarName: "POSTGRES_DSN", }, { Key: "host", @@ -71,6 +72,7 @@ var spec = drivers.Spec{ Placeholder: "your_password", Hint: "Postgres password for authentication", Secret: true, + EnvVarName: "POSTGRES_PASSWORD", }, { Key: "dbname", diff --git a/runtime/drivers/redshift/redshift.go b/runtime/drivers/redshift/redshift.go index a1d1af16066..7b0bcdb54fb 100644 --- a/runtime/drivers/redshift/redshift.go +++ b/runtime/drivers/redshift/redshift.go @@ -40,6 +40,7 @@ var spec = drivers.Spec{ Placeholder: "your_access_key_id", Required: true, Secret: true, + EnvVarName: "AWS_ACCESS_KEY_ID", }, { Key: "aws_secret_access_key", @@ -49,6 +50,7 @@ var spec = drivers.Spec{ Placeholder: "your_secret_access_key", Required: true, Secret: true, + EnvVarName: "AWS_SECRET_ACCESS_KEY", }, { Key: "workgroup", diff --git a/runtime/drivers/s3/s3.go b/runtime/drivers/s3/s3.go index b28ad243316..d0b1cae13a8 100644 --- a/runtime/drivers/s3/s3.go +++ b/runtime/drivers/s3/s3.go @@ -33,6 +33,7 @@ var spec = drivers.Spec{ Description: "AWS access key ID for explicit credentials", Placeholder: "Enter your AWS access key ID", Secret: true, + EnvVarName: "AWS_ACCESS_KEY_ID", Required: true, }, { @@ -42,6 +43,7 @@ var spec = drivers.Spec{ Description: "AWS secret access key for explicit credentials", Placeholder: "Enter your AWS secret access key", Secret: true, + EnvVarName: "AWS_SECRET_ACCESS_KEY", Required: true, }, { @@ -66,6 +68,7 @@ var spec = drivers.Spec{ Key: "aws_role_arn", Type: drivers.StringPropertyType, Secret: true, + EnvVarName: "AWS_ROLE_ARN", Description: "AWS Role ARN to assume", }, { diff --git a/runtime/drivers/salesforce/salesforce.go b/runtime/drivers/salesforce/salesforce.go index 7d1518807b9..9048d8e5aed 100644 --- a/runtime/drivers/salesforce/salesforce.go +++ b/runtime/drivers/salesforce/salesforce.go @@ -35,14 +35,16 @@ var spec = drivers.Spec{ Secret: false, }, { - Key: "password", - Type: drivers.StringPropertyType, - Secret: true, + Key: "password", + Type: drivers.StringPropertyType, + Secret: true, + EnvVarName: "SALESFORCE_PASSWORD", }, { - Key: "key", - Type: drivers.StringPropertyType, - Secret: true, + Key: "key", + Type: drivers.StringPropertyType, + Secret: true, + EnvVarName: "SALESFORCE_KEY", }, { Key: "endpoint", @@ -99,6 +101,7 @@ var spec = drivers.Spec{ Hint: "Your Salesforce password, optionally followed by a security token if required.", Placeholder: "your_password", Secret: true, + EnvVarName: "SALESFORCE_PASSWORD", }, { Key: "key", @@ -108,6 +111,7 @@ var spec = drivers.Spec{ Hint: "Paste your JWT private key for token-based authentication. Used with Connected App and Client ID.", Placeholder: "your_jwt_key", Secret: true, + EnvVarName: "SALESFORCE_KEY", }, { Key: "endpoint", diff --git a/runtime/drivers/snowflake/snowflake.go b/runtime/drivers/snowflake/snowflake.go index cd62dca9c87..dde348e488e 100644 --- a/runtime/drivers/snowflake/snowflake.go +++ b/runtime/drivers/snowflake/snowflake.go @@ -44,6 +44,7 @@ var spec = drivers.Spec{ Placeholder: "@//?warehouse=&role=&authenticator=SNOWFLAKE_JWT&privateKey=", Hint: "Can be configured here or by setting the 'connector.snowflake.dsn' environment variable (using '.env' or '--env').", Secret: true, + EnvVarName: "SNOWFLAKE_DSN", }, { Key: "account", @@ -69,6 +70,7 @@ var spec = drivers.Spec{ Placeholder: "your_password", Hint: "Your Snowflake database password. This will be stored securely and used to authenticate your connection.", Secret: true, + EnvVarName: "SNOWFLAKE_PASSWORD", }, { Key: "database", diff --git a/runtime/server/generate_template.go b/runtime/server/generate_template.go new file mode 100644 index 00000000000..85f69a35b34 --- /dev/null +++ b/runtime/server/generate_template.go @@ -0,0 +1,131 @@ +package server + +import ( + "context" + "fmt" + + runtimev1 "github.com/rilldata/rill/proto/gen/rill/runtime/v1" + "github.com/rilldata/rill/runtime" + "github.com/rilldata/rill/runtime/drivers" + "github.com/rilldata/rill/runtime/pkg/observability" + "github.com/rilldata/rill/runtime/server/auth" + "github.com/rilldata/rill/runtime/templates" + "go.opentelemetry.io/otel/attribute" + "go.uber.org/zap" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +// GenerateTemplate generates a connector or model YAML file from structured form data. +// Deprecated: use GenerateFile instead. This handler delegates to the templates package. +func (s *Server) GenerateTemplate(ctx context.Context, req *runtimev1.GenerateTemplateRequest) (*runtimev1.GenerateTemplateResponse, error) { + observability.AddRequestAttributes(ctx, + attribute.String("args.instance_id", req.InstanceId), + attribute.String("args.resource_type", req.ResourceType), + attribute.String("args.driver", req.Driver), + attribute.String("args.connector_name", req.ConnectorName), + ) + s.addInstanceRequestAttributes(ctx, req.InstanceId) + + if !auth.GetClaims(ctx, req.InstanceId).Can(runtime.EditRepo) { + return nil, ErrForbidden + } + + // Validate resource type + if req.ResourceType != "connector" && req.ResourceType != "model" { + return nil, status.Errorf(codes.InvalidArgument, "resource_type must be \"connector\" or \"model\"") + } + + // Validate driver exists + drv, ok := drivers.Connectors[req.Driver] + if !ok { + return nil, status.Errorf(codes.InvalidArgument, "unknown driver %q", req.Driver) + } + spec := drv.Spec() + + // Convert properties + var props map[string]any + if req.Properties != nil { + props = req.Properties.AsMap() + } else { + props = make(map[string]any) + } + + // Validate properties against the driver spec (backward compat) + if err := validateProperties(spec, req.ResourceType, props); err != nil { + return nil, status.Errorf(codes.InvalidArgument, "%s", err) + } + + // Look up template + tmpl, ok := s.templateRegistry.LookupByDriver(req.Driver, req.ResourceType) + if !ok { + return nil, status.Errorf(codes.Internal, "no template for driver %q resource type %q", req.Driver, req.ResourceType) + } + + // Read existing .env for env var conflict resolution + existingEnv := make(map[string]bool) + repo, release, err := s.runtime.Repo(ctx, req.InstanceId) + if err == nil { + existingEnv = templates.ReadEnvKeys(ctx, repo) + release() + } else { + s.logger.Warn("failed to open repo for .env conflict resolution; env var conflicts may not be detected", zap.Error(err)) + } + + // Render using the templates package + result, err := templates.Render(&templates.RenderInput{ + Template: tmpl, + Output: req.ResourceType, + Properties: props, + ConnectorName: req.ConnectorName, + ExistingEnv: existingEnv, + }) + if err != nil { + return nil, status.Errorf(codes.Internal, "rendering template: %s", err) + } + + blob := "" + if len(result.Files) > 0 { + blob = result.Files[0].Blob + } + + // Backward compat: the old API returned "duckdb" as the driver for + // object store, file store, HTTPS, and SQLite models that get rewritten to DuckDB. + responseDriver := req.Driver + if req.ResourceType == "model" { + if spec.ImplementsObjectStore || spec.ImplementsFileStore || req.Driver == "sqlite" || req.Driver == "https" { + responseDriver = "duckdb" + } + } + + return &runtimev1.GenerateTemplateResponse{ + Blob: blob, + EnvVars: result.EnvVars, + ResourceType: req.ResourceType, + Driver: responseDriver, + }, nil +} + +// validateProperties rejects unknown property keys. +func validateProperties(spec drivers.Spec, resourceType string, properties map[string]any) error { + allowed := make(map[string]bool) + var props []*drivers.PropertySpec + if resourceType == "connector" { + props = spec.ConfigProperties + } else { + props = spec.SourceProperties + // Universal model properties: sql and name are always allowed for models, + // even if the driver's SourceProperties doesn't list them explicitly. + allowed["sql"] = true + allowed["name"] = true + } + for _, p := range props { + allowed[p.Key] = true + } + for key := range properties { + if !allowed[key] { + return fmt.Errorf("unknown property %q for driver", key) + } + } + return nil +} diff --git a/runtime/server/generate_template_test.go b/runtime/server/generate_template_test.go new file mode 100644 index 00000000000..48650af50d1 --- /dev/null +++ b/runtime/server/generate_template_test.go @@ -0,0 +1,942 @@ +package server_test + +import ( + "fmt" + "sort" + "testing" + + runtimev1 "github.com/rilldata/rill/proto/gen/rill/runtime/v1" + "github.com/rilldata/rill/runtime/drivers" + "github.com/rilldata/rill/runtime/pkg/activity" + "github.com/rilldata/rill/runtime/pkg/ratelimit" + "github.com/rilldata/rill/runtime/server" + "github.com/rilldata/rill/runtime/testruntime" + "github.com/stretchr/testify/require" + "go.uber.org/zap" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/types/known/structpb" + + // Register all connector drivers + _ "github.com/rilldata/rill/runtime/drivers/athena" + _ "github.com/rilldata/rill/runtime/drivers/azure" + _ "github.com/rilldata/rill/runtime/drivers/bigquery" + _ "github.com/rilldata/rill/runtime/drivers/clickhouse" + _ "github.com/rilldata/rill/runtime/drivers/druid" + _ "github.com/rilldata/rill/runtime/drivers/duckdb" + _ "github.com/rilldata/rill/runtime/drivers/file" + _ "github.com/rilldata/rill/runtime/drivers/gcs" + _ "github.com/rilldata/rill/runtime/drivers/https" + _ "github.com/rilldata/rill/runtime/drivers/mysql" + _ "github.com/rilldata/rill/runtime/drivers/pinot" + _ "github.com/rilldata/rill/runtime/drivers/postgres" + _ "github.com/rilldata/rill/runtime/drivers/redshift" + _ "github.com/rilldata/rill/runtime/drivers/s3" + _ "github.com/rilldata/rill/runtime/drivers/salesforce" + _ "github.com/rilldata/rill/runtime/drivers/snowflake" + _ "github.com/rilldata/rill/runtime/drivers/sqlite" + _ "github.com/rilldata/rill/runtime/drivers/starrocks" +) + +// TestPropertySpecSecretFlags asserts that PropertySpec.Secret flags match expected values. +func TestPropertySpecSecretFlags(t *testing.T) { + expected := map[string][]string{ + "s3": {"aws_access_key_id", "aws_secret_access_key", "aws_role_arn", "aws_role_session_name", "aws_external_id"}, + "gcs": {"google_application_credentials", "key_id", "secret"}, + "azure": {"azure_storage_account", "azure_storage_key", "azure_storage_sas_token", "azure_storage_connection_string"}, + "clickhouse": {"dsn", "password"}, + "postgres": {"dsn", "password"}, + "bigquery": {"google_application_credentials"}, + "snowflake": {"dsn", "password"}, + "redshift": {"aws_access_key_id", "aws_secret_access_key"}, + "motherduck": {"token"}, + "athena": {"aws_access_key_id", "aws_secret_access_key"}, + "mysql": {"dsn", "password"}, + "druid": {"dsn", "password"}, + "pinot": {"dsn", "password"}, + "starrocks": {"dsn", "password"}, + "salesforce": {"password", "key"}, + } + + for driverName, drv := range drivers.Connectors { + expectedKeys, ok := expected[driverName] + if !ok { + continue + } + spec := drv.Spec() + actualSecrets := secretKeys(spec.ConfigProperties) + sort.Strings(expectedKeys) + sort.Strings(actualSecrets) + require.Equal(t, expectedKeys, actualSecrets, "driver %s: secret keys mismatch", driverName) + } +} + +func secretKeys(props []*drivers.PropertySpec) []string { + var keys []string + for _, p := range props { + if p.Secret { + keys = append(keys, p.Key) + } + } + return keys +} + +// TestGenerateTemplate tests the GenerateTemplate RPC handler end-to-end. +func TestGenerateTemplate(t *testing.T) { + rt, instanceID := testruntime.NewInstanceWithOptions(t, testruntime.InstanceOptions{ + Files: map[string]string{ + "rill.yaml": ``, + }, + }) + + ctx := testCtx() + srv, err := server.NewServer(ctx, &server.Options{}, rt, zap.NewNop(), ratelimit.NewNoop(), activity.NewNoopClient(), nil) + require.NoError(t, err) + + tt := []struct { + name string + req *runtimev1.GenerateTemplateRequest + wantContains []string + wantExcludes []string + wantEnvKeys []string + wantDriver string + wantResType string + wantErr codes.Code + }{ + { + name: "s3 connector", + req: &runtimev1.GenerateTemplateRequest{ + InstanceId: instanceID, + ResourceType: "connector", + Driver: "s3", + Properties: mustStruct(map[string]any{"aws_access_key_id": "AKIATEST", "aws_secret_access_key": "secretkey"}), + }, + wantContains: []string{ + "driver: s3", + `{{ .env.AWS_ACCESS_KEY_ID }}`, + `{{ .env.AWS_SECRET_ACCESS_KEY }}`, + }, + wantExcludes: []string{"AKIATEST", "secretkey"}, + wantEnvKeys: []string{"AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY"}, + wantDriver: "s3", + wantResType: "connector", + }, + { + name: "bigquery connector", + req: &runtimev1.GenerateTemplateRequest{ + InstanceId: instanceID, + ResourceType: "connector", + Driver: "bigquery", + Properties: mustStruct(map[string]any{"project_id": "my-project", "google_application_credentials": `{"type":"service_account"}`}), + }, + wantContains: []string{ + "driver: bigquery", + `project_id: "my-project"`, + `{{ .env.GOOGLE_APPLICATION_CREDENTIALS }}`, + }, + wantExcludes: []string{"service_account"}, + wantEnvKeys: []string{"GOOGLE_APPLICATION_CREDENTIALS"}, + wantDriver: "bigquery", + wantResType: "connector", + }, + { + name: "postgres connector with params", + req: &runtimev1.GenerateTemplateRequest{ + InstanceId: instanceID, + ResourceType: "connector", + Driver: "postgres", + Properties: mustStruct(map[string]any{"host": "db.example.com", "port": "5432", "password": "my_pg_secret"}), + }, + wantContains: []string{ + "driver: postgres", + `host: "db.example.com"`, + `{{ .env.POSTGRES_PASSWORD }}`, + }, + wantExcludes: []string{"my_pg_secret"}, + wantDriver: "postgres", + wantResType: "connector", + }, + { + name: "empty values filtered", + req: &runtimev1.GenerateTemplateRequest{ + InstanceId: instanceID, + ResourceType: "connector", + Driver: "postgres", + Properties: mustStruct(map[string]any{"host": "db.example.com", "port": "", "dbname": ""}), + }, + wantContains: []string{"host:"}, + wantExcludes: []string{"port:", "dbname:"}, + wantDriver: "postgres", + wantResType: "connector", + }, + { + name: "s3 model rewritten to duckdb parquet", + req: &runtimev1.GenerateTemplateRequest{ + InstanceId: instanceID, + ResourceType: "model", + Driver: "s3", + Properties: mustStruct(map[string]any{"path": "s3://bucket/data.parquet", "name": "my_source"}), + ConnectorName: "my_s3", + }, + wantContains: []string{ + "type: model", + "connector: duckdb", + "read_parquet", + `create_secrets_from_connectors: "my_s3"`, + }, + wantDriver: "duckdb", + wantResType: "model", + }, + { + name: "s3 model rewritten to duckdb csv", + req: &runtimev1.GenerateTemplateRequest{ + InstanceId: instanceID, + ResourceType: "model", + Driver: "s3", + Properties: mustStruct(map[string]any{"path": "s3://bucket/data.csv", "name": "test"}), + }, + wantContains: []string{ + "read_csv", + "auto_detect=true", + "ignore_errors=1", + "header=true", + }, + wantDriver: "duckdb", + wantResType: "model", + }, + { + name: "gcs model rewritten with json", + req: &runtimev1.GenerateTemplateRequest{ + InstanceId: instanceID, + ResourceType: "model", + Driver: "gcs", + Properties: mustStruct(map[string]any{"path": "gs://bucket/data.json", "name": "test"}), + }, + wantContains: []string{ + "read_json", + "auto_detect=true", + "format='auto'", + }, + wantDriver: "duckdb", + wantResType: "model", + }, + { + name: "https model defaults to json", + req: &runtimev1.GenerateTemplateRequest{ + InstanceId: instanceID, + ResourceType: "model", + Driver: "https", + Properties: mustStruct(map[string]any{"path": "https://api.example.com/data", "name": "test"}), + ConnectorName: "my_http", + }, + wantContains: []string{ + "read_json", + `create_secrets_from_connectors: "my_http"`, + }, + wantDriver: "duckdb", + wantResType: "model", + }, + { + name: "local_file csv model", + req: &runtimev1.GenerateTemplateRequest{ + InstanceId: instanceID, + ResourceType: "model", + Driver: "local_file", + Properties: mustStruct(map[string]any{"path": "/data/file.csv", "name": "test"}), + }, + wantContains: []string{ + "read_csv", + }, + wantExcludes: []string{"create_secrets_from_connectors"}, + wantDriver: "duckdb", + wantResType: "model", + }, + { + name: "sqlite model rewritten", + req: &runtimev1.GenerateTemplateRequest{ + InstanceId: instanceID, + ResourceType: "model", + Driver: "sqlite", + Properties: mustStruct(map[string]any{"db": "/data/app.db", "table": "users", "name": "test"}), + }, + wantContains: []string{ + "type: model", + "sqlite_scan('/data/app.db', 'users')", + }, + wantDriver: "duckdb", + wantResType: "model", + }, + { + name: "redshift model without dev section", + req: &runtimev1.GenerateTemplateRequest{ + InstanceId: instanceID, + ResourceType: "model", + Driver: "redshift", + Properties: mustStruct(map[string]any{"sql": "SELECT * FROM events"}), + ConnectorName: "rs_prod", + }, + wantContains: []string{"type: model", `connector: "rs_prod"`, "materialize: true"}, + wantExcludes: []string{"dev:"}, + wantDriver: "redshift", + wantResType: "model", + }, + { + name: "unknown driver rejected", + req: &runtimev1.GenerateTemplateRequest{ + InstanceId: instanceID, + ResourceType: "connector", + Driver: "nonexistent", + Properties: mustStruct(map[string]any{}), + }, + wantErr: codes.InvalidArgument, + }, + { + name: "unknown property rejected", + req: &runtimev1.GenerateTemplateRequest{ + InstanceId: instanceID, + ResourceType: "connector", + Driver: "postgres", + Properties: mustStruct(map[string]any{"bogus_key": "value"}), + }, + wantErr: codes.InvalidArgument, + }, + { + name: "invalid resource type rejected", + req: &runtimev1.GenerateTemplateRequest{ + InstanceId: instanceID, + ResourceType: "dashboard", + Driver: "postgres", + Properties: mustStruct(map[string]any{}), + }, + wantErr: codes.InvalidArgument, + }, + { + name: "secret values never in error messages", + req: &runtimev1.GenerateTemplateRequest{ + InstanceId: instanceID, + ResourceType: "connector", + Driver: "postgres", + Properties: mustStruct(map[string]any{"bogus_key": "super_secret_value"}), + }, + wantErr: codes.InvalidArgument, + }, + } + + for _, tc := range tt { + t.Run(tc.name, func(t *testing.T) { + resp, err := srv.GenerateTemplate(ctx, tc.req) + if tc.wantErr != 0 { + require.Error(t, err) + s, ok := status.FromError(err) + require.True(t, ok) + require.Equal(t, tc.wantErr, s.Code()) + // Ensure secret values never appear in error messages + require.NotContains(t, err.Error(), "super_secret_value") + return + } + require.NoError(t, err) + + for _, c := range tc.wantContains { + require.Contains(t, resp.Blob, c, "blob should contain %q", c) + } + for _, e := range tc.wantExcludes { + require.NotContains(t, resp.Blob, e, "blob should not contain %q", e) + } + if tc.wantDriver != "" { + require.Equal(t, tc.wantDriver, resp.Driver) + } + if tc.wantResType != "" { + require.Equal(t, tc.wantResType, resp.ResourceType) + } + for _, envKey := range tc.wantEnvKeys { + require.Contains(t, resp.EnvVars, envKey, "env_vars should contain key %q", envKey) + } + }) + } +} + +// TestGenerateTemplateEnvConflict tests env var conflict resolution with existing .env files. +func TestGenerateTemplateEnvConflict(t *testing.T) { + rt, instanceID := testruntime.NewInstanceWithOptions(t, testruntime.InstanceOptions{ + Files: map[string]string{ + "rill.yaml": ``, + ".env": "POSTGRES_PASSWORD=old_value\n", + }, + }) + + ctx := testCtx() + srv, err := server.NewServer(ctx, &server.Options{}, rt, zap.NewNop(), ratelimit.NewNoop(), activity.NewNoopClient(), nil) + require.NoError(t, err) + + resp, err := srv.GenerateTemplate(ctx, &runtimev1.GenerateTemplateRequest{ + InstanceId: instanceID, + ResourceType: "connector", + Driver: "postgres", + Properties: mustStruct(map[string]any{"host": "db.example.com", "password": "new_secret"}), + }) + require.NoError(t, err) + + // Should use POSTGRES_PASSWORD_1 since POSTGRES_PASSWORD already exists + require.Contains(t, resp.EnvVars, "POSTGRES_PASSWORD_1") + require.Contains(t, resp.Blob, "{{ .env.POSTGRES_PASSWORD_1 }}") + require.NotContains(t, resp.Blob, "new_secret") +} + +// TestGenerateTemplateEnvConflictDouble tests double-conflict resolution. +func TestGenerateTemplateEnvConflictDouble(t *testing.T) { + rt, instanceID := testruntime.NewInstanceWithOptions(t, testruntime.InstanceOptions{ + Files: map[string]string{ + "rill.yaml": ``, + ".env": "POSTGRES_PASSWORD=old\nPOSTGRES_PASSWORD_1=also_old\n", + }, + }) + + ctx := testCtx() + srv, err := server.NewServer(ctx, &server.Options{}, rt, zap.NewNop(), ratelimit.NewNoop(), activity.NewNoopClient(), nil) + require.NoError(t, err) + + resp, err := srv.GenerateTemplate(ctx, &runtimev1.GenerateTemplateRequest{ + InstanceId: instanceID, + ResourceType: "connector", + Driver: "postgres", + Properties: mustStruct(map[string]any{"host": "db.example.com", "password": "new_secret"}), + }) + require.NoError(t, err) + + require.Contains(t, resp.EnvVars, "POSTGRES_PASSWORD_2") + require.Contains(t, resp.Blob, "{{ .env.POSTGRES_PASSWORD_2 }}") +} + +// TestGenerateTemplateMotherduckConnector tests MotherDuck connector generation. +func TestGenerateTemplateMotherduckConnector(t *testing.T) { + rt, instanceID := testruntime.NewInstanceWithOptions(t, testruntime.InstanceOptions{ + Files: map[string]string{ + "rill.yaml": ``, + }, + }) + + ctx := testCtx() + srv, err := server.NewServer(ctx, &server.Options{}, rt, zap.NewNop(), ratelimit.NewNoop(), activity.NewNoopClient(), nil) + require.NoError(t, err) + + resp, err := srv.GenerateTemplate(ctx, &runtimev1.GenerateTemplateRequest{ + InstanceId: instanceID, + ResourceType: "connector", + Driver: "motherduck", + Properties: mustStruct(map[string]any{"path": "md:my_db", "token": "my_token_123"}), + }) + require.NoError(t, err) + + require.Contains(t, resp.Blob, "driver: motherduck") + require.Contains(t, resp.Blob, `{{ .env.MOTHERDUCK_TOKEN }}`) + require.NotContains(t, resp.Blob, "my_token_123") + require.Contains(t, resp.EnvVars, "MOTHERDUCK_TOKEN") + require.Equal(t, "my_token_123", resp.EnvVars["MOTHERDUCK_TOKEN"]) +} + +// TestGenerateTemplateSnowflakeConnector tests Snowflake connector generation. +func TestGenerateTemplateSnowflakeConnector(t *testing.T) { + rt, instanceID := testruntime.NewInstanceWithOptions(t, testruntime.InstanceOptions{ + Files: map[string]string{ + "rill.yaml": ``, + }, + }) + + ctx := testCtx() + srv, err := server.NewServer(ctx, &server.Options{}, rt, zap.NewNop(), ratelimit.NewNoop(), activity.NewNoopClient(), nil) + require.NoError(t, err) + + resp, err := srv.GenerateTemplate(ctx, &runtimev1.GenerateTemplateRequest{ + InstanceId: instanceID, + ResourceType: "connector", + Driver: "snowflake", + Properties: mustStruct(map[string]any{"account": "my_account", "user": "admin", "password": "pw123", "database": "analytics"}), + }) + require.NoError(t, err) + + require.Contains(t, resp.Blob, "driver: snowflake") + require.Contains(t, resp.Blob, `account: "my_account"`) + require.Contains(t, resp.Blob, `{{ .env.SNOWFLAKE_PASSWORD }}`) + require.NotContains(t, resp.Blob, "pw123") +} + +// TestGenerateTemplateAllConnectorDrivers ensures every registered connector can generate a connector YAML. +func TestGenerateTemplateAllConnectorDrivers(t *testing.T) { + rt, instanceID := testruntime.NewInstanceWithOptions(t, testruntime.InstanceOptions{ + Files: map[string]string{ + "rill.yaml": ``, + }, + }) + + ctx := testCtx() + srv, err := server.NewServer(ctx, &server.Options{}, rt, zap.NewNop(), ratelimit.NewNoop(), activity.NewNoopClient(), nil) + require.NoError(t, err) + + // Drivers that have ConfigProperties (connector-type drivers) + driversWithConfig := []struct { + name string + props map[string]any + }{ + {"s3", map[string]any{"aws_access_key_id": "test", "aws_secret_access_key": "test"}}, + {"gcs", map[string]any{"google_application_credentials": "{}"}}, + {"azure", map[string]any{"azure_storage_connection_string": "test"}}, + {"postgres", map[string]any{"host": "localhost"}}, + {"bigquery", map[string]any{"google_application_credentials": "{}"}}, + {"snowflake", map[string]any{"account": "test", "user": "test", "password": "test"}}, + {"redshift", map[string]any{"aws_access_key_id": "test", "aws_secret_access_key": "test"}}, + {"motherduck", map[string]any{"path": "md:test", "token": "test"}}, + {"athena", map[string]any{"aws_access_key_id": "test", "aws_secret_access_key": "test"}}, + {"mysql", map[string]any{"host": "localhost"}}, + {"druid", map[string]any{"host": "localhost"}}, + {"pinot", map[string]any{"broker_host": "localhost"}}, + {"starrocks", map[string]any{"host": "localhost"}}, + {"https", map[string]any{}}, + } + + for _, d := range driversWithConfig { + t.Run(d.name, func(t *testing.T) { + resp, err := srv.GenerateTemplate(ctx, &runtimev1.GenerateTemplateRequest{ + InstanceId: instanceID, + ResourceType: "connector", + Driver: d.name, + Properties: mustStruct(d.props), + }) + require.NoError(t, err) + require.Contains(t, resp.Blob, "type: connector") + require.Contains(t, resp.Blob, "driver: "+d.name) + }) + } +} + +// TestGenerateTemplateDuckDBRewrite tests all DuckDB rewrite cases. +func TestGenerateTemplateDuckDBRewrite(t *testing.T) { + rt, instanceID := testruntime.NewInstanceWithOptions(t, testruntime.InstanceOptions{ + Files: map[string]string{ + "rill.yaml": ``, + }, + }) + + ctx := testCtx() + srv, err := server.NewServer(ctx, &server.Options{}, rt, zap.NewNop(), ratelimit.NewNoop(), activity.NewNoopClient(), nil) + require.NoError(t, err) + + tt := []struct { + name string + driver string + props map[string]any + connName string + wantDriver string + wantContains []string + wantExcludes []string + }{ + { + name: "s3 parquet", + driver: "s3", + props: map[string]any{"path": "s3://bucket/data.parquet", "name": "test"}, + wantDriver: "duckdb", + wantContains: []string{ + "read_parquet('s3://bucket/data.parquet')", + }, + }, + { + name: "s3 csv", + driver: "s3", + props: map[string]any{"path": "s3://bucket/data.csv", "name": "test"}, + wantDriver: "duckdb", + wantContains: []string{ + "read_csv('s3://bucket/data.csv', auto_detect=true, ignore_errors=1, header=true)", + }, + }, + { + name: "s3 compressed parquet", + driver: "s3", + props: map[string]any{"path": "s3://bucket/data.v1.parquet.gz", "name": "test"}, + wantDriver: "duckdb", + wantContains: []string{ + "read_parquet('s3://bucket/data.v1.parquet.gz')", + }, + }, + { + name: "gcs ndjson", + driver: "gcs", + props: map[string]any{"path": "gs://bucket/data.ndjson", "name": "test"}, + wantDriver: "duckdb", + wantContains: []string{ + "read_json('gs://bucket/data.ndjson', auto_detect=true, format='auto')", + }, + }, + { + name: "azure tsv", + driver: "azure", + props: map[string]any{"path": "azure://container/data.tsv", "name": "test"}, + wantDriver: "duckdb", + wantContains: []string{ + "read_csv('azure://container/data.tsv', auto_detect=true, ignore_errors=1, header=true)", + }, + }, + { + name: "s3 unknown extension", + driver: "s3", + props: map[string]any{"path": "s3://bucket/data.avro", "name": "test"}, + wantDriver: "duckdb", + wantContains: []string{ + "select * from 's3://bucket/data.avro'", + }, + }, + { + name: "s3 with connector name sets secrets", + driver: "s3", + props: map[string]any{"path": "s3://bucket/data.parquet", "name": "test"}, + connName: "my_s3", + wantDriver: "duckdb", + wantContains: []string{`create_secrets_from_connectors: "my_s3"`}, + }, + { + name: "https defaults to json", + driver: "https", + props: map[string]any{"path": "https://api.example.com/data", "name": "test"}, + wantDriver: "duckdb", + wantContains: []string{ + "read_json('https://api.example.com/data', auto_detect=true, format='auto')", + }, + }, + { + name: "https with csv extension", + driver: "https", + props: map[string]any{"path": "https://example.com/data.csv", "name": "test"}, + wantDriver: "duckdb", + wantContains: []string{ + "read_csv('https://example.com/data.csv', auto_detect=true, ignore_errors=1, header=true)", + }, + }, + { + name: "https with connector name", + driver: "https", + props: map[string]any{"path": "https://api.example.com/data", "name": "test"}, + connName: "my_http", + wantDriver: "duckdb", + wantContains: []string{`create_secrets_from_connectors: "my_http"`}, + }, + { + name: "local_file csv", + driver: "local_file", + props: map[string]any{"path": "/data/file.csv", "name": "test"}, + wantDriver: "duckdb", + wantContains: []string{"read_csv('/data/file.csv'"}, + wantExcludes: []string{"create_secrets_from_connectors"}, + }, + { + name: "sqlite", + driver: "sqlite", + props: map[string]any{"db": "/data/app.db", "table": "users", "name": "test"}, + wantDriver: "duckdb", + wantContains: []string{ + "sqlite_scan('/data/app.db', 'users')", + }, + }, + } + + for _, tc := range tt { + t.Run(tc.name, func(t *testing.T) { + resp, err := srv.GenerateTemplate(ctx, &runtimev1.GenerateTemplateRequest{ + InstanceId: instanceID, + ResourceType: "model", + Driver: tc.driver, + Properties: mustStruct(tc.props), + ConnectorName: tc.connName, + }) + require.NoError(t, err) + require.Equal(t, tc.wantDriver, resp.Driver) + require.Equal(t, "model", resp.ResourceType) + for _, c := range tc.wantContains { + require.Contains(t, resp.Blob, c, "blob should contain %q", c) + } + for _, e := range tc.wantExcludes { + require.NotContains(t, resp.Blob, e, "blob should not contain %q", e) + } + }) + } +} + +// TestGenerateTemplateEnvVarNaming tests env var name resolution. +func TestGenerateTemplateEnvVarNaming(t *testing.T) { + rt, instanceID := testruntime.NewInstanceWithOptions(t, testruntime.InstanceOptions{ + Files: map[string]string{ + "rill.yaml": ``, + }, + }) + + ctx := testCtx() + srv, err := server.NewServer(ctx, &server.Options{}, rt, zap.NewNop(), ratelimit.NewNoop(), activity.NewNoopClient(), nil) + require.NoError(t, err) + + tt := []struct { + name string + driver string + props map[string]any + wantEnvKey string + }{ + { + name: "s3 access key uses EnvVarName", + driver: "s3", + props: map[string]any{"aws_access_key_id": "test"}, + wantEnvKey: "AWS_ACCESS_KEY_ID", + }, + { + name: "bigquery creds uses EnvVarName", + driver: "bigquery", + props: map[string]any{"google_application_credentials": "{}"}, + wantEnvKey: "GOOGLE_APPLICATION_CREDENTIALS", + }, + { + name: "motherduck token uses EnvVarName", + driver: "motherduck", + props: map[string]any{"token": "test", "path": "md:test"}, + wantEnvKey: "MOTHERDUCK_TOKEN", + }, + { + name: "starrocks dsn uses fallback format", + driver: "starrocks", + props: map[string]any{"dsn": "test"}, + wantEnvKey: "STARROCKS_DSN", + }, + { + name: "starrocks password uses fallback format", + driver: "starrocks", + props: map[string]any{"password": "test"}, + wantEnvKey: "STARROCKS_PASSWORD", + }, + } + + for _, tc := range tt { + t.Run(tc.name, func(t *testing.T) { + resp, err := srv.GenerateTemplate(ctx, &runtimev1.GenerateTemplateRequest{ + InstanceId: instanceID, + ResourceType: "connector", + Driver: tc.driver, + Properties: mustStruct(tc.props), + }) + require.NoError(t, err) + require.Contains(t, resp.EnvVars, tc.wantEnvKey, "env_vars should contain %q", tc.wantEnvKey) + require.Contains(t, resp.Blob, fmt.Sprintf("{{ .env.%s }}", tc.wantEnvKey)) + }) + } +} + +// TestGenerateTemplateValidateProperties tests property validation. +func TestGenerateTemplateValidateProperties(t *testing.T) { + rt, instanceID := testruntime.NewInstanceWithOptions(t, testruntime.InstanceOptions{ + Files: map[string]string{ + "rill.yaml": ``, + }, + }) + + ctx := testCtx() + srv, err := server.NewServer(ctx, &server.Options{}, rt, zap.NewNop(), ratelimit.NewNoop(), activity.NewNoopClient(), nil) + require.NoError(t, err) + + tt := []struct { + name string + driver string + resourceType string + props map[string]any + wantErr bool + }{ + { + name: "valid connector props", + driver: "postgres", + resourceType: "connector", + props: map[string]any{"host": "localhost"}, + wantErr: false, + }, + { + name: "unknown prop rejected", + driver: "postgres", + resourceType: "connector", + props: map[string]any{"bogus": "value"}, + wantErr: true, + }, + { + name: "source prop on connector rejected", + driver: "duckdb", + resourceType: "connector", + props: map[string]any{"sql": "SELECT 1"}, + wantErr: true, + }, + { + name: "source prop on model accepted", + driver: "duckdb", + resourceType: "model", + props: map[string]any{"sql": "SELECT 1"}, + wantErr: false, + }, + { + name: "empty properties valid", + driver: "postgres", + resourceType: "connector", + props: map[string]any{}, + wantErr: false, + }, + } + + for _, tc := range tt { + t.Run(tc.name, func(t *testing.T) { + _, err := srv.GenerateTemplate(ctx, &runtimev1.GenerateTemplateRequest{ + InstanceId: instanceID, + ResourceType: tc.resourceType, + Driver: tc.driver, + Properties: mustStruct(tc.props), + }) + if tc.wantErr { + require.Error(t, err) + s, ok := status.FromError(err) + require.True(t, ok) + require.Equal(t, codes.InvalidArgument, s.Code()) + } else { + require.NoError(t, err) + } + }) + } +} + +// TestGenerateTemplateHTTPSConnectorWithHeaders tests HTTPS connector with non-sensitive headers. +func TestGenerateTemplateHTTPSConnectorWithHeaders(t *testing.T) { + rt, instanceID := testruntime.NewInstanceWithOptions(t, testruntime.InstanceOptions{ + Files: map[string]string{ + "rill.yaml": ``, + }, + }) + + ctx := testCtx() + srv, err := server.NewServer(ctx, &server.Options{}, rt, zap.NewNop(), ratelimit.NewNoop(), activity.NewNoopClient(), nil) + require.NoError(t, err) + + resp, err := srv.GenerateTemplate(ctx, &runtimev1.GenerateTemplateRequest{ + InstanceId: instanceID, + ResourceType: "connector", + Driver: "https", + Properties: mustStruct(map[string]any{ + "headers": map[string]any{ + "Content-Type": "application/json", + "Accept": "text/html", + }, + }), + }) + require.NoError(t, err) + + require.Contains(t, resp.Blob, "type: connector") + require.Contains(t, resp.Blob, "driver: https") + require.Contains(t, resp.Blob, "headers:") + require.Contains(t, resp.Blob, `"application/json"`) + require.Contains(t, resp.Blob, `"text/html"`) + require.Empty(t, resp.EnvVars) +} + +// TestGenerateTemplateHTTPSConnectorWithSensitiveHeaders tests Authorization header extraction. +func TestGenerateTemplateHTTPSConnectorWithSensitiveHeaders(t *testing.T) { + rt, instanceID := testruntime.NewInstanceWithOptions(t, testruntime.InstanceOptions{ + Files: map[string]string{ + "rill.yaml": ``, + }, + }) + + ctx := testCtx() + srv, err := server.NewServer(ctx, &server.Options{}, rt, zap.NewNop(), ratelimit.NewNoop(), activity.NewNoopClient(), nil) + require.NoError(t, err) + + resp, err := srv.GenerateTemplate(ctx, &runtimev1.GenerateTemplateRequest{ + InstanceId: instanceID, + ResourceType: "connector", + Driver: "https", + Properties: mustStruct(map[string]any{ + "headers": map[string]any{ + "Authorization": "my_secret_token", + }, + }), + }) + require.NoError(t, err) + + require.Contains(t, resp.Blob, "{{ .env.connector.https.authorization }}") + require.NotContains(t, resp.Blob, "my_secret_token") + require.Contains(t, resp.EnvVars, "connector.https.authorization") + require.Equal(t, "my_secret_token", resp.EnvVars["connector.https.authorization"]) +} + +// TestGenerateTemplateHTTPSConnectorBearerPrefix tests Bearer scheme preservation. +func TestGenerateTemplateHTTPSConnectorBearerPrefix(t *testing.T) { + rt, instanceID := testruntime.NewInstanceWithOptions(t, testruntime.InstanceOptions{ + Files: map[string]string{ + "rill.yaml": ``, + }, + }) + + ctx := testCtx() + srv, err := server.NewServer(ctx, &server.Options{}, rt, zap.NewNop(), ratelimit.NewNoop(), activity.NewNoopClient(), nil) + require.NoError(t, err) + + resp, err := srv.GenerateTemplate(ctx, &runtimev1.GenerateTemplateRequest{ + InstanceId: instanceID, + ResourceType: "connector", + Driver: "https", + Properties: mustStruct(map[string]any{ + "headers": map[string]any{ + "Authorization": "Bearer my_token_123", + }, + }), + }) + require.NoError(t, err) + + // Bearer prefix preserved in YAML, only token in envVars + require.Contains(t, resp.Blob, "Bearer {{ .env.connector.https.authorization }}") + require.NotContains(t, resp.Blob, "my_token_123") + require.Contains(t, resp.EnvVars, "connector.https.authorization") + require.Equal(t, "my_token_123", resp.EnvVars["connector.https.authorization"]) +} + +// TestGenerateTemplateHTTPSConnectorMixedHeaders tests a mix of sensitive and non-sensitive headers. +func TestGenerateTemplateHTTPSConnectorMixedHeaders(t *testing.T) { + rt, instanceID := testruntime.NewInstanceWithOptions(t, testruntime.InstanceOptions{ + Files: map[string]string{ + "rill.yaml": ``, + }, + }) + + ctx := testCtx() + srv, err := server.NewServer(ctx, &server.Options{}, rt, zap.NewNop(), ratelimit.NewNoop(), activity.NewNoopClient(), nil) + require.NoError(t, err) + + resp, err := srv.GenerateTemplate(ctx, &runtimev1.GenerateTemplateRequest{ + InstanceId: instanceID, + ResourceType: "connector", + Driver: "https", + Properties: mustStruct(map[string]any{ + "headers": map[string]any{ + "Content-Type": "application/json", + "Authorization": "Basic dXNlcjpwYXNz", + "X-API-Key": "secret_key_value", + }, + }), + }) + require.NoError(t, err) + + // Non-sensitive header as plain text + require.Contains(t, resp.Blob, `"application/json"`) + + // Authorization with Basic prefix preserved + require.Contains(t, resp.Blob, "Basic {{ .env.connector.https.authorization }}") + require.NotContains(t, resp.Blob, "dXNlcjpwYXNz") + require.Equal(t, "dXNlcjpwYXNz", resp.EnvVars["connector.https.authorization"]) + + // X-API-Key is sensitive, no prefix + require.Contains(t, resp.Blob, "{{ .env.connector.https.x_api_key }}") + require.NotContains(t, resp.Blob, "secret_key_value") + require.Equal(t, "secret_key_value", resp.EnvVars["connector.https.x_api_key"]) +} + +func mustStruct(m map[string]any) *structpb.Struct { + s, err := structpb.NewStruct(m) + if err != nil { + panic(err) + } + return s +} diff --git a/runtime/server/server.go b/runtime/server/server.go index 1d95c4fbd82..ac0cad74b5a 100644 --- a/runtime/server/server.go +++ b/runtime/server/server.go @@ -27,6 +27,7 @@ import ( "github.com/rilldata/rill/runtime/pkg/securetoken" "github.com/rilldata/rill/runtime/queries" "github.com/rilldata/rill/runtime/server/auth" + "github.com/rilldata/rill/runtime/templates" "github.com/rs/cors" "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" "go.uber.org/zap" @@ -55,14 +56,15 @@ type Server struct { runtimev1.UnsafeRuntimeServiceServer runtimev1.UnsafeQueryServiceServer runtimev1.UnsafeConnectorServiceServer - runtime *runtime.Runtime - opts *Options - logger *zap.Logger - aud *auth.Audience - codec *securetoken.Codec - limiter ratelimit.Limiter - activity *activity.Client - ai *ai.Runner + runtime *runtime.Runtime + opts *Options + logger *zap.Logger + aud *auth.Audience + codec *securetoken.Codec + limiter ratelimit.Limiter + activity *activity.Client + ai *ai.Runner + templateRegistry *templates.Registry // set for local runtimes adminOverride drivers.AdminService } @@ -85,15 +87,21 @@ func NewServer(ctx context.Context, opts *Options, rt *runtime.Runtime, logger * codec = securetoken.NewCodec(opts.SessionKeyPairs) } + tmplRegistry, err := templates.NewRegistry() + if err != nil { + return nil, fmt.Errorf("loading template registry: %w", err) + } + srv := &Server{ - runtime: rt, - opts: opts, - logger: logger, - codec: codec, - limiter: limiter, - activity: activityClient, - ai: ai.NewRunner(rt, activityClient), - adminOverride: adminOverride, + runtime: rt, + opts: opts, + logger: logger, + codec: codec, + limiter: limiter, + activity: activityClient, + ai: ai.NewRunner(rt, activityClient), + templateRegistry: tmplRegistry, + adminOverride: adminOverride, } if opts.AuthEnable { diff --git a/runtime/server/templates.go b/runtime/server/templates.go new file mode 100644 index 00000000000..a07b4df2c7a --- /dev/null +++ b/runtime/server/templates.go @@ -0,0 +1,195 @@ +package server + +import ( + "context" + "os" + "strings" + + runtimev1 "github.com/rilldata/rill/proto/gen/rill/runtime/v1" + "github.com/rilldata/rill/runtime" + "github.com/rilldata/rill/runtime/pkg/observability" + "github.com/rilldata/rill/runtime/server/auth" + "github.com/rilldata/rill/runtime/templates" + "go.opentelemetry.io/otel/attribute" + "go.uber.org/zap" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/types/known/structpb" +) + +// ListTemplates returns available template definitions, optionally filtered by tags. +func (s *Server) ListTemplates(ctx context.Context, req *runtimev1.ListTemplatesRequest) (*runtimev1.ListTemplatesResponse, error) { + tmplList := s.templateRegistry.ListByTags(req.Tags) + + pbs := make([]*runtimev1.Template, len(tmplList)) + for i, t := range tmplList { + files := make([]*runtimev1.TemplateFile, len(t.Files)) + for j, f := range t.Files { + files[j] = &runtimev1.TemplateFile{ + Name: f.Name, + PathPattern: f.PathTemplate, + } + } + var schemaPb *structpb.Struct + if t.JSONSchema != nil { + var err error + schemaPb, err = structpb.NewStruct(t.JSONSchema) + if err != nil { + return nil, status.Errorf(codes.Internal, "converting schema for %q: %s", t.Name, err) + } + } + + pbs[i] = &runtimev1.Template{ + Name: t.Name, + DisplayName: t.DisplayName, + Description: t.Description, + DocsUrl: t.DocsURL, + Driver: t.Driver, + Olap: t.OLAP, + Icon: t.Icon, + SmallIcon: t.SmallIcon, + Tags: t.Tags, + Files: files, + JsonSchema: schemaPb, + } + } + + return &runtimev1.ListTemplatesResponse{Templates: pbs}, nil +} + +// GenerateFile renders a template and optionally writes the resulting files. +func (s *Server) GenerateFile(ctx context.Context, req *runtimev1.GenerateFileRequest) (*runtimev1.GenerateFileResponse, error) { + observability.AddRequestAttributes(ctx, + attribute.String("args.instance_id", req.InstanceId), + attribute.String("args.template_name", req.TemplateName), + attribute.String("args.output", req.Output), + attribute.String("args.connector_name", req.ConnectorName), + attribute.Bool("args.preview", req.Preview), + ) + s.addInstanceRequestAttributes(ctx, req.InstanceId) + + if !auth.GetClaims(ctx, req.InstanceId).Can(runtime.EditRepo) { + return nil, ErrForbidden + } + + // Look up template + tmpl, ok := s.templateRegistry.Get(req.TemplateName) + if !ok { + return nil, status.Errorf(codes.InvalidArgument, "unknown template %q", req.TemplateName) + } + + // Convert properties + var props map[string]any + if req.Properties != nil { + props = req.Properties.AsMap() + } else { + props = make(map[string]any) + } + + // Read existing .env for conflict resolution + existingEnv := make(map[string]bool) + repo, release, err := s.runtime.Repo(ctx, req.InstanceId) + if err == nil { + existingEnv = templates.ReadEnvKeys(ctx, repo) + release() + } else { + s.logger.Warn("failed to open repo for .env conflict resolution; env var conflicts may not be detected", zap.Error(err)) + } + + // Render + result, err := templates.Render(&templates.RenderInput{ + Template: tmpl, + Output: req.Output, + Properties: props, + ConnectorName: req.ConnectorName, + ExistingEnv: existingEnv, + }) + if err != nil { + return nil, status.Errorf(codes.Internal, "rendering template: %s", err) + } + + // Write files if not preview mode + if !req.Preview { + if err := s.writeRenderedFiles(ctx, req.InstanceId, result); err != nil { + return nil, err + } + } + + // Build response + pbFiles := make([]*runtimev1.GeneratedFile, len(result.Files)) + for i, f := range result.Files { + pbFiles[i] = &runtimev1.GeneratedFile{ + Path: f.Path, + Blob: f.Blob, + } + } + + return &runtimev1.GenerateFileResponse{ + Files: pbFiles, + EnvVars: result.EnvVars, + }, nil +} + +// writeRenderedFiles writes all rendered output files and merges env vars into .env. +// Writes .env first so that YAML files referencing {{ .env.VAR }} have their secrets available. +func (s *Server) writeRenderedFiles(ctx context.Context, instanceID string, result *templates.RenderOutput) error { + repo, release, err := s.runtime.Repo(ctx, instanceID) + if err != nil { + return status.Errorf(codes.Internal, "opening repo: %s", err) + } + defer release() + + // Write .env first so secrets are available when YAML files are parsed + if len(result.EnvVars) > 0 { + envContent, err := repo.Get(ctx, ".env") + if err != nil && !os.IsNotExist(err) { + s.logger.Warn("failed to read .env; existing env vars may be overwritten", zap.Error(err)) + } + for key, val := range result.EnvVars { + envContent = appendEnvVar(envContent, key, val) + } + if err := repo.Put(ctx, ".env", strings.NewReader(envContent)); err != nil { + return status.Errorf(codes.Internal, "writing .env: %s", err) + } + } + + // Write rendered files + for _, f := range result.Files { + if err := repo.Put(ctx, f.Path, strings.NewReader(f.Blob)); err != nil { + return status.Errorf(codes.Internal, "writing file %q: %s", f.Path, err) + } + } + + return nil +} + +// appendEnvVar updates an existing env var or appends a new one. +// If the key already exists, its value is replaced in-place. +// Values are sanitized: newlines are stripped to prevent injection of extra +// env vars, and values containing spaces or special characters are quoted. +func appendEnvVar(content, key, value string) string { + // Sanitize: strip newlines to prevent env var injection + value = strings.ReplaceAll(value, "\n", "") + value = strings.ReplaceAll(value, "\r", "") + + // Quote values that contain spaces, '=', or '#' (comment char). + // Escape backslashes first, then double quotes, to avoid double-escaping. + if strings.ContainsAny(value, ` =#'"\\`) { + value = strings.ReplaceAll(value, `\`, `\\`) + value = `"` + strings.ReplaceAll(value, `"`, `\"`) + `"` + } + + prefix := key + "=" + lines := strings.Split(content, "\n") + for i, line := range lines { + if strings.HasPrefix(line, prefix) { + lines[i] = prefix + value + return strings.Join(lines, "\n") + } + } + // Key not found; append + if content != "" && content[len(content)-1] != '\n' { + content += "\n" + } + return content + prefix + value + "\n" +} diff --git a/runtime/templates/definitions/duckdb-models/athena-duckdb.json b/runtime/templates/definitions/duckdb-models/athena-duckdb.json new file mode 100644 index 00000000000..372babbe7fa --- /dev/null +++ b/runtime/templates/definitions/duckdb-models/athena-duckdb.json @@ -0,0 +1,88 @@ +{ + "name": "athena-duckdb", + "display_name": "Amazon Athena", + "description": "Query Amazon Athena and ingest into DuckDB", + "docs_url": "https://docs.rilldata.com/developers/build/connectors/data-source/athena", + "driver": "athena", + "olap": "duckdb", + "icon": "AmazonAthena", + "small_icon": "AthenaIcon", + "tags": [ + "athena", + "aws", + "warehouse", + "duckdb", + "source", + "connector" + ], + "json_schema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "x-category": "warehouse", + "properties": { + "aws_access_key_id": { + "type": "string", + "title": "AWS access key ID", + "description": "AWS access key ID used to authenticate to Athena", + "x-placeholder": "your_access_key_id", + "x-secret": true, + "x-env-var": "AWS_ACCESS_KEY_ID", + "x-step": "connector" + }, + "aws_secret_access_key": { + "type": "string", + "title": "AWS secret access key", + "description": "AWS secret access key paired with the access key ID", + "x-placeholder": "your_secret_access_key", + "x-secret": true, + "x-env-var": "AWS_SECRET_ACCESS_KEY", + "x-step": "connector" + }, + "output_location": { + "type": "string", + "title": "S3 output location", + "description": "S3 URI where Athena should write query results (e.g., s3://bucket/path/)", + "pattern": "^s3://.+", + "errorMessage": { + "pattern": "Must be an S3 URI (e.g., s3://bucket/path/)" + }, + "x-placeholder": "s3://bucket-name/path/", + "x-step": "connector" + }, + "sql": { + "type": "string", + "title": "SQL", + "description": "SQL query to run against your warehouse", + "x-placeholder": "Input SQL", + "x-step": "explorer" + }, + "name": { + "type": "string", + "title": "Model name", + "description": "Name for the source model", + "pattern": "^[a-zA-Z0-9_]+$", + "x-placeholder": "my_model", + "x-step": "explorer" + } + }, + "required": [ + "aws_access_key_id", + "aws_secret_access_key", + "output_location", + "sql", + "name" + ] + }, + "files": [ + { + "name": "connector", + "path_template": "connectors/[[ .connector_name ]].yaml", + "code_template": "# Connector YAML\n# Reference documentation: [[ .docs_url ]]\ntype: connector\ndriver: athena\n[[ renderProps .config_props ]]\n" + }, + { + "name": "model", + "path_template": "models/[[ .model_name ]].yaml", + "code_template": "# Model YAML\n# Reference documentation: https://docs.rilldata.com/developers/build/connectors/data-source/athena\n\ntype: model\n[[ if .connector_name -]]\nconnector: \"[[ .connector_name ]]\"\n[[ end -]]\nmaterialize: true\n[[ if .sql -]]\nsql: |\n [[ .sql | indent 2 ]]\n\ndev:\n sql: |\n [[ .sql ]] limit 10000\n[[ end -]]\n" + } + ] +} diff --git a/runtime/templates/definitions/duckdb-models/azure-duckdb.json b/runtime/templates/definitions/duckdb-models/azure-duckdb.json new file mode 100644 index 00000000000..49040dd0a36 --- /dev/null +++ b/runtime/templates/definitions/duckdb-models/azure-duckdb.json @@ -0,0 +1,196 @@ +{ + "name": "azure-duckdb", + "display_name": "Azure Blob Storage", + "description": "Read files from Azure Blob Storage into DuckDB using the appropriate file reader", + "docs_url": "https://docs.rilldata.com/developers/build/connectors/data-source/azure", + "driver": "azure", + "olap": "duckdb", + "icon": "MicrosoftAzureBlobStorage", + "small_icon": "MicrosoftAzureBlobStorageIcon", + "tags": [ + "azure", + "microsoft", + "object-storage", + "duckdb", + "source", + "connector" + ], + "json_schema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "x-category": "objectStore", + "properties": { + "auth_method": { + "type": "string", + "title": "Authentication method", + "description": "Choose how to authenticate to Azure Blob Storage", + "enum": [ + "connection_string", + "account_key", + "sas_token", + "public" + ], + "default": "connection_string", + "x-display": "radio", + "x-enum-labels": [ + "Connection String", + "Storage Account Key", + "SAS Token", + "Public" + ], + "x-enum-descriptions": [ + "Provide a full Azure Storage connection string.", + "Provide the storage account name and access key.", + "Provide the storage account name and SAS token.", + "Access publicly readable blobs without credentials." + ], + "x-ui-only": true, + "x-grouped-fields": { + "connection_string": [ + "azure_storage_connection_string" + ], + "account_key": [ + "azure_storage_account", + "azure_storage_key" + ], + "sas_token": [ + "azure_storage_account", + "azure_storage_sas_token" + ], + "public": [] + }, + "x-step": "connector" + }, + "azure_storage_connection_string": { + "type": "string", + "title": "Connection string", + "description": "Paste an Azure Storage connection string", + "x-placeholder": "Enter Azure storage connection string", + "x-secret": true, + "x-env-var": "AZURE_STORAGE_CONNECTION_STRING", + "x-step": "connector", + "x-visible-if": { + "auth_method": "connection_string" + } + }, + "azure_storage_account": { + "type": "string", + "title": "Storage account", + "description": "The name of the Azure storage account", + "x-placeholder": "Enter Azure storage account", + "x-step": "connector", + "x-visible-if": { + "auth_method": [ + "account_key", + "sas_token" + ] + } + }, + "azure_storage_key": { + "type": "string", + "title": "Access key", + "description": "Primary or secondary access key for the storage account", + "x-placeholder": "Enter Azure storage access key", + "x-secret": true, + "x-env-var": "AZURE_STORAGE_KEY", + "x-step": "connector", + "x-visible-if": { + "auth_method": "account_key" + } + }, + "azure_storage_sas_token": { + "type": "string", + "title": "SAS token", + "description": "Shared Access Signature token for the storage account (starting with ?sv=)", + "x-placeholder": "Enter Azure SAS token", + "x-secret": true, + "x-env-var": "AZURE_STORAGE_SAS_TOKEN", + "x-step": "connector", + "x-visible-if": { + "auth_method": "sas_token" + } + }, + "path": { + "type": "string", + "title": "Blob URI", + "description": "URI to the Azure blob container or directory", + "pattern": "^(azure://|https?://).+", + "errorMessage": { + "pattern": "Must be an Azure URI (e.g. azure://container/path or https://account.blob.core.windows.net/container/path)" + }, + "x-placeholder": "azure://container/path", + "x-step": "source" + }, + "name": { + "type": "string", + "title": "Model name", + "description": "Name for the source model", + "pattern": "^[a-zA-Z0-9_]+$", + "x-placeholder": "my_model", + "x-step": "source" + } + }, + "required": [ + "path", + "name" + ], + "allOf": [ + { + "if": { + "properties": { + "auth_method": { + "const": "connection_string" + } + } + }, + "then": { + "required": [ + "azure_storage_connection_string" + ] + } + }, + { + "if": { + "properties": { + "auth_method": { + "const": "account_key" + } + } + }, + "then": { + "required": [ + "azure_storage_account", + "azure_storage_key" + ] + } + }, + { + "if": { + "properties": { + "auth_method": { + "const": "sas_token" + } + } + }, + "then": { + "required": [ + "azure_storage_account", + "azure_storage_sas_token" + ] + } + } + ] + }, + "files": [ + { + "name": "connector", + "path_template": "connectors/[[ .connector_name ]].yaml", + "code_template": "# Connector YAML\n# Reference documentation: [[ .docs_url ]]\ntype: connector\ndriver: azure\n[[ renderProps .config_props ]]\n" + }, + { + "name": "model", + "path_template": "models/[[ .model_name ]].yaml", + "code_template": "type: model\nconnector: duckdb\n[[ if .connector_name -]]\ncreate_secrets_from_connectors: \"[[ .connector_name ]]\"\n[[ end -]]\nsql: |\n [[ duckdbSQL .path false ]]\n" + } + ] +} diff --git a/runtime/templates/definitions/duckdb-models/bigquery-duckdb.json b/runtime/templates/definitions/duckdb-models/bigquery-duckdb.json new file mode 100644 index 00000000000..44f2085c387 --- /dev/null +++ b/runtime/templates/definitions/duckdb-models/bigquery-duckdb.json @@ -0,0 +1,81 @@ +{ + "name": "bigquery-duckdb", + "display_name": "BigQuery", + "description": "Query Google BigQuery and ingest into DuckDB", + "docs_url": "https://docs.rilldata.com/developers/build/connectors/data-source/bigquery", + "driver": "bigquery", + "olap": "duckdb", + "icon": "GoogleBigQuery", + "small_icon": "GoogleBigQueryIcon", + "tags": [ + "bigquery", + "google", + "warehouse", + "duckdb", + "source", + "connector" + ], + "json_schema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "x-category": "warehouse", + "properties": { + "google_application_credentials": { + "type": "string", + "title": "GCP credentials", + "description": "Service account JSON (uploaded or pasted)", + "format": "file", + "x-display": "file", + "x-file-accept": ".json", + "x-file-encoding": "json", + "x-file-extract": { + "project_id": "project_id" + }, + "x-secret": true, + "x-env-var": "GOOGLE_APPLICATION_CREDENTIALS", + "x-step": "connector" + }, + "project_id": { + "type": "string", + "title": "Project ID", + "description": "Google Cloud project ID to use for queries", + "x-placeholder": "my-project", + "x-hint": "If empty, Rill will use the project ID from your credentials when available.", + "x-step": "connector" + }, + "sql": { + "type": "string", + "title": "SQL", + "description": "SQL query to run against your warehouse", + "x-placeholder": "Input SQL", + "x-step": "explorer" + }, + "name": { + "type": "string", + "title": "Model name", + "description": "Name for the source model", + "pattern": "^[a-zA-Z0-9_]+$", + "x-placeholder": "my_model", + "x-step": "explorer" + } + }, + "required": [ + "google_application_credentials", + "project_id", + "sql", + "name" + ] + }, + "files": [ + { + "name": "connector", + "path_template": "connectors/[[ .connector_name ]].yaml", + "code_template": "# Connector YAML\n# Reference documentation: [[ .docs_url ]]\ntype: connector\ndriver: bigquery\n[[ renderProps .config_props ]]\n" + }, + { + "name": "model", + "path_template": "models/[[ .model_name ]].yaml", + "code_template": "# Model YAML\n# Reference documentation: https://docs.rilldata.com/developers/build/connectors/data-source/bigquery\ntype: model\n[[ if .connector_name -]]\nconnector: \"[[ .connector_name ]]\"\n[[ end -]]\nmaterialize: true\n[[ if .sql -]]\nsql: |\n [[ .sql | indent 2 ]]\n\ndev:\n sql: |\n [[ .sql ]] limit 10000\n[[ end -]]\n" + } + ] +} diff --git a/runtime/templates/definitions/duckdb-models/clickhouse-duckdb.json b/runtime/templates/definitions/duckdb-models/clickhouse-duckdb.json new file mode 100644 index 00000000000..b4e018ce942 --- /dev/null +++ b/runtime/templates/definitions/duckdb-models/clickhouse-duckdb.json @@ -0,0 +1,50 @@ +{ + "name": "clickhouse-duckdb", + "display_name": "ClickHouse", + "description": "Query ClickHouse tables and ingest into DuckDB", + "docs_url": "https://docs.rilldata.com/developers/build/connectors/olap/clickhouse", + "driver": "clickhouse", + "olap": "duckdb", + "icon": "ClickHouse", + "small_icon": "ClickHouseIcon", + "tags": [ + "clickhouse", + "olap", + "duckdb", + "source", + "model" + ], + "json_schema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "x-category": "sqlStore", + "properties": { + "sql": { + "type": "string", + "title": "SQL", + "description": "SQL query to run against ClickHouse", + "x-placeholder": "SELECT * FROM my_table", + "x-step": "explorer" + }, + "name": { + "type": "string", + "title": "Model name", + "description": "Name for the source model", + "pattern": "^[a-zA-Z0-9_]+$", + "x-placeholder": "my_model", + "x-step": "explorer" + } + }, + "required": [ + "sql", + "name" + ] + }, + "files": [ + { + "name": "model", + "path_template": "models/[[ .model_name ]].yaml", + "code_template": "# Model YAML\n# Reference documentation: https://docs.rilldata.com/developers/build/connectors/olap/clickhouse\ntype: model\n[[ if .connector_name -]]\nconnector: \"[[ .connector_name ]]\"\n[[ end -]]\nmaterialize: true\n[[ if .sql -]]\nsql: |\n [[ .sql | indent 2 ]]\n\ndev:\n sql: |\n [[ .sql ]] limit 10000\n[[ end -]]\n" + } + ] +} diff --git a/runtime/templates/definitions/duckdb-models/delta-duckdb.json b/runtime/templates/definitions/duckdb-models/delta-duckdb.json new file mode 100644 index 00000000000..f0d2adf9b30 --- /dev/null +++ b/runtime/templates/definitions/duckdb-models/delta-duckdb.json @@ -0,0 +1,193 @@ +{ + "name": "delta-duckdb", + "display_name": "Delta Lake", + "description": "Query Delta Lake tables using DuckDB's delta extension", + "docs_url": "https://docs.rilldata.com/developers/build/connectors/data-source/delta", + "driver": "delta", + "olap": "duckdb", + "icon": "DeltaLake", + "small_icon": "DeltaLakeIcon", + "tags": [ + "delta", + "table-format", + "duckdb", + "source" + ], + "json_schema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "x-category": "objectStore", + "properties": { + "storage_type": { + "type": "string", + "title": "Storage type", + "description": "Where your Delta table is stored", + "enum": [ + "s3", + "gcs", + "azure", + "local" + ], + "default": "s3", + "x-display": "radio", + "x-enum-labels": [ + "Amazon S3", + "Google Cloud Storage", + "Azure Blob Storage", + "Local / Public" + ], + "x-enum-descriptions": [ + "Delta table stored in an S3 bucket.", + "Delta table stored in a GCS bucket.", + "Delta table stored in Azure Blob Storage.", + "Local path or publicly accessible URL." + ], + "x-ui-only": true, + "x-grouped-fields": { + "s3": [ + "aws_access_key_id", + "aws_secret_access_key", + "aws_region" + ], + "gcs": [ + "google_application_credentials" + ], + "azure": [ + "azure_storage_account", + "azure_storage_key" + ], + "local": [] + }, + "x-step": "connector" + }, + "aws_access_key_id": { + "type": "string", + "title": "AWS Access Key ID", + "description": "Access key for the S3 bucket containing your Delta table", + "x-placeholder": "Enter AWS access key ID", + "x-secret": true, + "x-env-var": "AWS_ACCESS_KEY_ID", + "x-visible-if": { + "storage_type": "s3" + }, + "x-step": "connector" + }, + "aws_secret_access_key": { + "type": "string", + "title": "AWS Secret Access Key", + "description": "Secret key for the S3 bucket containing your Delta table", + "x-placeholder": "Enter AWS secret access key", + "x-secret": true, + "x-env-var": "AWS_SECRET_ACCESS_KEY", + "x-visible-if": { + "storage_type": "s3" + }, + "x-step": "connector" + }, + "aws_region": { + "type": "string", + "title": "AWS Region", + "description": "AWS region of the S3 bucket", + "x-placeholder": "us-east-1", + "x-visible-if": { + "storage_type": "s3" + }, + "x-step": "connector" + }, + "google_application_credentials": { + "type": "string", + "title": "Service Account Key (JSON)", + "description": "Upload a JSON key file for a service account with GCS access", + "x-display": "file", + "x-file-accept": ".json", + "x-file-encoding": "json", + "x-secret": true, + "x-env-var": "GOOGLE_APPLICATION_CREDENTIALS", + "x-visible-if": { + "storage_type": "gcs" + }, + "x-step": "connector" + }, + "azure_storage_account": { + "type": "string", + "title": "Storage Account Name", + "description": "Azure storage account name", + "x-placeholder": "mystorageaccount", + "x-visible-if": { + "storage_type": "azure" + }, + "x-step": "connector" + }, + "azure_storage_key": { + "type": "string", + "title": "Storage Account Key", + "description": "Azure storage account access key", + "x-placeholder": "Enter storage account key", + "x-secret": true, + "x-env-var": "AZURE_STORAGE_KEY", + "x-visible-if": { + "storage_type": "azure" + }, + "x-step": "connector" + }, + "path": { + "type": "string", + "title": "Delta Table Path", + "description": "Path to your Delta table (e.g. s3://bucket/delta_table, gs://bucket/delta_table)", + "x-placeholder": "s3://bucket/delta_table", + "x-step": "source" + }, + "name": { + "type": "string", + "title": "Model name", + "description": "Name for the source model", + "pattern": "^[a-zA-Z0-9_]+$", + "x-placeholder": "my_delta_table", + "x-step": "source" + } + }, + "required": [ + "path", + "name" + ], + "allOf": [ + { + "if": { + "properties": { + "storage_type": { + "const": "s3" + } + } + }, + "then": { + "required": [ + "aws_access_key_id", + "aws_secret_access_key" + ] + } + }, + { + "if": { + "properties": { + "storage_type": { + "const": "azure" + } + } + }, + "then": { + "required": [ + "azure_storage_account", + "azure_storage_key" + ] + } + } + ] + }, + "files": [ + { + "name": "model", + "path_template": "models/[[ .model_name ]].yaml", + "code_template": "type: model\n[[ if .connector_name -]]\ncreate_secrets_from_connectors: \"[[ .connector_name ]]\"\n[[ end -]]\n\nsql: |\n SELECT * FROM delta_scan('[[ .path ]]');\n" + } + ] +} diff --git a/runtime/templates/definitions/duckdb-models/duckdb-duckdb.json b/runtime/templates/definitions/duckdb-models/duckdb-duckdb.json new file mode 100644 index 00000000000..f5612f7948e --- /dev/null +++ b/runtime/templates/definitions/duckdb-models/duckdb-duckdb.json @@ -0,0 +1,47 @@ +{ + "name": "duckdb-duckdb", + "display_name": "DuckDB", + "description": "Write SQL models against DuckDB", + "docs_url": "https://docs.rilldata.com/developers/build/connectors/olap/duckdb", + "driver": "duckdb", + "olap": "duckdb", + "icon": "DuckDB", + "small_icon": "DuckDBIcon", + "tags": [ + "duckdb", + "model" + ], + "json_schema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "x-category": "sqlStore", + "properties": { + "sql": { + "type": "string", + "title": "SQL", + "description": "SQL query to run", + "x-placeholder": "SELECT * FROM my_table", + "x-step": "explorer" + }, + "name": { + "type": "string", + "title": "Model name", + "description": "Name for the model", + "pattern": "^[a-zA-Z0-9_]+$", + "x-placeholder": "my_model", + "x-step": "explorer" + } + }, + "required": [ + "sql", + "name" + ] + }, + "files": [ + { + "name": "model", + "path_template": "models/[[ .model_name ]].yaml", + "code_template": "# Model YAML\n# Reference documentation: https://docs.rilldata.com/developers/build/connectors/olap/duckdb\ntype: model\n[[ if .connector_name -]]\nconnector: \"[[ .connector_name ]]\"\n[[ end -]]\n[[ if .sql -]]\nsql: |\n [[ .sql | indent 2 ]]\n[[ end -]]\n" + } + ] +} diff --git a/runtime/templates/definitions/duckdb-models/gcs-duckdb.json b/runtime/templates/definitions/duckdb-models/gcs-duckdb.json new file mode 100644 index 00000000000..7a47a9d0dd8 --- /dev/null +++ b/runtime/templates/definitions/duckdb-models/gcs-duckdb.json @@ -0,0 +1,164 @@ +{ + "name": "gcs-duckdb", + "display_name": "Google Cloud Storage", + "description": "Read files from Google Cloud Storage into DuckDB using the appropriate file reader", + "docs_url": "https://docs.rilldata.com/developers/build/connectors/data-source/gcs", + "driver": "gcs", + "olap": "duckdb", + "icon": "GoogleCloudStorage", + "small_icon": "GoogleCloudStorageIcon", + "tags": [ + "gcs", + "google", + "object-storage", + "duckdb", + "source", + "connector" + ], + "json_schema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "x-category": "objectStore", + "properties": { + "auth_method": { + "type": "string", + "title": "Authentication method", + "description": "Choose how to authenticate to GCS", + "enum": [ + "credentials", + "hmac", + "public" + ], + "default": "credentials", + "x-display": "radio", + "x-enum-labels": [ + "GCP credentials", + "HMAC keys", + "Public" + ], + "x-enum-descriptions": [ + "Upload a JSON key file for a service account with GCS access.", + "Use HMAC access key and secret for S3-compatible authentication.", + "Access publicly readable buckets without credentials." + ], + "x-ui-only": true, + "x-grouped-fields": { + "credentials": [ + "google_application_credentials" + ], + "hmac": [ + "key_id", + "secret" + ], + "public": [] + }, + "x-step": "connector" + }, + "google_application_credentials": { + "type": "string", + "title": "Service account key", + "description": "Upload a JSON key file for a service account with GCS access.", + "format": "file", + "x-display": "file", + "x-file-accept": ".json", + "x-file-encoding": "json", + "x-secret": true, + "x-env-var": "GOOGLE_APPLICATION_CREDENTIALS", + "x-step": "connector", + "x-visible-if": { + "auth_method": "credentials" + } + }, + "key_id": { + "type": "string", + "title": "Access Key ID", + "description": "HMAC access key ID for S3-compatible authentication", + "x-placeholder": "Enter your HMAC access key ID", + "x-secret": true, + "x-env-var": "GCP_ACCESS_KEY_ID", + "x-step": "connector", + "x-visible-if": { + "auth_method": "hmac" + } + }, + "secret": { + "type": "string", + "title": "Secret Access Key", + "description": "HMAC secret access key for S3-compatible authentication", + "x-placeholder": "Enter your HMAC secret access key", + "x-secret": true, + "x-env-var": "GCP_SECRET_ACCESS_KEY", + "x-step": "connector", + "x-visible-if": { + "auth_method": "hmac" + } + }, + "path": { + "type": "string", + "title": "GCS URI", + "description": "Path to your GCS bucket or prefix", + "pattern": "^gs://[^/]+(/.*)?$", + "errorMessage": { + "pattern": "Must be a GS URI (e.g. gs://bucket/path)" + }, + "x-placeholder": "gs://bucket/path", + "x-step": "source" + }, + "name": { + "type": "string", + "title": "Model name", + "description": "Name for the source model", + "pattern": "^[a-zA-Z0-9_]+$", + "x-placeholder": "my_model", + "x-step": "source" + } + }, + "required": [ + "path", + "name" + ], + "allOf": [ + { + "if": { + "properties": { + "auth_method": { + "const": "credentials" + } + } + }, + "then": { + "required": [ + "google_application_credentials" + ] + } + }, + { + "if": { + "properties": { + "auth_method": { + "const": "hmac" + } + } + }, + "then": { + "required": [ + "key_id", + "secret" + ] + } + } + ] + }, + "files": [ + { + "name": "connector", + "path_template": "connectors/[[ .connector_name ]].yaml", + "code_template": "# Connector YAML\n# Reference documentation: [[ .docs_url ]]\ntype: connector\ndriver: gcs\n[[ renderProps .config_props ]]\n" + }, + { + "name": "model", + "path_template": "models/[[ .model_name ]].yaml", + "code_template": "type: model\nconnector: duckdb\n[[ if .connector_name -]]\ncreate_secrets_from_connectors: \"[[ .connector_name ]]\"\n[[ end -]]\nsql: |\n [[ duckdbSQL .path false ]]\n" + } + ] +} diff --git a/runtime/templates/definitions/duckdb-models/https-duckdb.json b/runtime/templates/definitions/duckdb-models/https-duckdb.json new file mode 100644 index 00000000000..477ce5a97cd --- /dev/null +++ b/runtime/templates/definitions/duckdb-models/https-duckdb.json @@ -0,0 +1,80 @@ +{ + "name": "https-duckdb", + "display_name": "HTTP(S) Endpoint", + "description": "Read files from an HTTP/HTTPS URL into DuckDB using the appropriate file reader", + "docs_url": "https://docs.rilldata.com/developers/build/connect/#adding-a-remote-source", + "driver": "https", + "olap": "duckdb", + "icon": "HTTPS", + "small_icon": "HTTPSIcon", + "tags": [ + "https", + "http", + "url", + "file-store", + "duckdb", + "source", + "connector" + ], + "json_schema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "x-category": "fileStore", + "x-button-labels": { + "*": { + "*": { + "idle": "Continue", + "loading": "Continuing..." + } + } + }, + "properties": { + "headers": { + "title": "Headers", + "description": "HTTP headers to include in the request", + "x-display": "key-value", + "x-placeholder": "Header name", + "x-hint": "e.g. Authorization: Bearer ", + "x-step": "connector" + }, + "path": { + "type": "string", + "title": "URI", + "description": "HTTP/HTTPS URL to the remote file", + "pattern": "^https?://.+", + "errorMessage": { + "pattern": "URI must start with http:// or https://" + }, + "x-placeholder": "https://example.com/file.csv", + "x-step": "source" + }, + "name": { + "type": "string", + "title": "Model name", + "description": "Name for the source model", + "pattern": "^[a-zA-Z0-9_]+$", + "errorMessage": { + "pattern": "Model name can only contain letters, numbers, and underscores" + }, + "x-placeholder": "my_model", + "x-step": "source" + } + }, + "required": [ + "path", + "name" + ] + }, + "files": [ + { + "name": "connector", + "path_template": "connectors/[[ .connector_name ]].yaml", + "code_template": "# Connector YAML\n# Reference documentation: [[ .docs_url ]]\ntype: connector\ndriver: https\n[[ renderProps .config_props ]]\n" + }, + { + "name": "model", + "path_template": "models/[[ .model_name ]].yaml", + "code_template": "type: model\nconnector: duckdb\n[[ if .connector_name -]]\ncreate_secrets_from_connectors: \"[[ .connector_name ]]\"\n[[ end -]]\nsql: |\n [[ duckdbSQL .path true ]]\n" + } + ] +} diff --git a/runtime/templates/definitions/duckdb-models/iceberg-duckdb.json b/runtime/templates/definitions/duckdb-models/iceberg-duckdb.json new file mode 100644 index 00000000000..563b1565743 --- /dev/null +++ b/runtime/templates/definitions/duckdb-models/iceberg-duckdb.json @@ -0,0 +1,78 @@ +{ + "name": "iceberg-duckdb", + "display_name": "Iceberg", + "description": "Query Apache Iceberg tables using DuckDB's iceberg extension", + "docs_url": "https://docs.rilldata.com/developers/build/connectors/data-source/iceberg", + "driver": "iceberg", + "olap": "duckdb", + "icon": "ApacheIceberg", + "small_icon": "ApacheIcebergIcon", + "tags": [ + "iceberg", + "table-format", + "duckdb", + "source" + ], + "json_schema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "x-category": "objectStore", + "properties": { + "aws_access_key_id": { + "type": "string", + "title": "AWS Access Key ID", + "description": "Access key for the S3 bucket containing your Iceberg table", + "x-placeholder": "Enter AWS access key ID", + "x-secret": true, + "x-env-var": "AWS_ACCESS_KEY_ID", + "x-step": "connector" + }, + "aws_secret_access_key": { + "type": "string", + "title": "AWS Secret Access Key", + "description": "Secret key for the S3 bucket containing your Iceberg table", + "x-placeholder": "Enter AWS secret access key", + "x-secret": true, + "x-env-var": "AWS_SECRET_ACCESS_KEY", + "x-step": "connector" + }, + "aws_region": { + "type": "string", + "title": "AWS Region", + "description": "AWS region of the S3 bucket", + "x-placeholder": "us-east-1", + "x-step": "connector" + }, + "path": { + "type": "string", + "title": "Iceberg Table Path", + "description": "S3 path to your Iceberg table metadata", + "pattern": "^s3://.*", + "errorMessage": { + "pattern": "Must be an S3 URI (e.g. s3://bucket/warehouse/my_table)" + }, + "x-placeholder": "s3://bucket/warehouse/my_table", + "x-step": "source" + }, + "name": { + "type": "string", + "title": "Model name", + "description": "Name for the source model", + "pattern": "^[a-zA-Z0-9_]+$", + "x-placeholder": "my_iceberg_table", + "x-step": "source" + } + }, + "required": [ + "path", + "name" + ] + }, + "files": [ + { + "name": "model", + "path_template": "models/[[ .model_name ]].yaml", + "code_template": "type: model\n[[ if .connector_name -]]\ncreate_secrets_from_connectors: \"[[ .connector_name ]]\"\n[[ end -]]\n\nsql: |\n SELECT * FROM iceberg_scan('[[ .path ]]');\n" + } + ] +} diff --git a/runtime/templates/definitions/duckdb-models/local-file-duckdb.json b/runtime/templates/definitions/duckdb-models/local-file-duckdb.json new file mode 100644 index 00000000000..a32c76ae7d5 --- /dev/null +++ b/runtime/templates/definitions/duckdb-models/local-file-duckdb.json @@ -0,0 +1,49 @@ +{ + "name": "local_file-duckdb", + "display_name": "Local File", + "description": "Read local files into DuckDB", + "docs_url": "https://docs.rilldata.com/developers/build/connectors/olap/duckdb", + "driver": "local_file", + "olap": "duckdb", + "icon": "LocalFile", + "small_icon": "LocalFileIcon", + "tags": [ + "local-file", + "file", + "file-store", + "duckdb", + "source" + ], + "json_schema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "x-category": "fileStore", + "properties": { + "path": { + "type": "string", + "title": "Path", + "description": "Local file path or glob (relative to project root)", + "x-placeholder": "data/*.parquet", + "x-step": "source" + }, + "name": { + "type": "string", + "title": "Source name", + "description": "Name for the source", + "x-placeholder": "my_new_source", + "x-step": "explorer" + } + }, + "required": [ + "path", + "name" + ] + }, + "files": [ + { + "name": "model", + "path_template": "models/[[ .model_name ]].yaml", + "code_template": "# Model YAML\n# Reference documentation: https://docs.rilldata.com/developers/build/connectors/olap/duckdb\ntype: model\nconnector: duckdb\nsql: |\n [[ duckdbSQL .path true ]]\n" + } + ] +} diff --git a/runtime/templates/definitions/duckdb-models/mysql-duckdb.json b/runtime/templates/definitions/duckdb-models/mysql-duckdb.json new file mode 100644 index 00000000000..adbcd40d26d --- /dev/null +++ b/runtime/templates/definitions/duckdb-models/mysql-duckdb.json @@ -0,0 +1,171 @@ +{ + "name": "mysql-duckdb", + "display_name": "MySQL", + "description": "Query MySQL databases and ingest into DuckDB", + "docs_url": "https://docs.rilldata.com/developers/build/connectors/data-source/mysql", + "driver": "mysql", + "olap": "duckdb", + "icon": "MySQL", + "small_icon": "MySqlIcon", + "tags": [ + "mysql", + "database", + "duckdb", + "source", + "connector" + ], + "json_schema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "x-category": "sqlStore", + "properties": { + "connection_mode": { + "type": "string", + "title": "Connection method", + "enum": [ + "parameters", + "dsn" + ], + "default": "parameters", + "x-display": "tabs", + "x-enum-labels": [ + "Enter parameters", + "Enter connection string" + ], + "x-ui-only": true, + "x-tab-group": { + "parameters": [ + "host", + "port", + "database", + "user", + "password", + "ssl-mode" + ], + "dsn": [ + "dsn" + ] + }, + "x-step": "connector" + }, + "dsn": { + "type": "string", + "title": "MySQL connection string", + "description": "Full DSN, e.g. mysql://user:password@host:3306/database?ssl-mode=REQUIRED", + "x-placeholder": "mysql://user:password@host:3306/database", + "x-secret": true, + "x-env-var": "MYSQL_DSN", + "x-hint": "Use DSN or fill host/user/password/database below (not both at once).", + "x-step": "connector" + }, + "host": { + "type": "string", + "title": "Host", + "description": "MySQL server hostname or IP", + "x-placeholder": "localhost", + "x-step": "connector" + }, + "port": { + "type": "string", + "title": "Port", + "description": "MySQL server port", + "pattern": "^\\d+$", + "errorMessage": { + "pattern": "Port must be a number" + }, + "default": "3306", + "x-placeholder": "3306", + "x-step": "connector" + }, + "database": { + "type": "string", + "title": "Database", + "description": "Database name", + "x-placeholder": "my_database", + "x-step": "connector" + }, + "user": { + "type": "string", + "title": "Username", + "description": "MySQL user", + "x-placeholder": "mysql", + "x-step": "connector" + }, + "password": { + "type": "string", + "title": "Password", + "description": "MySQL password", + "x-placeholder": "your_password", + "x-secret": true, + "x-env-var": "MYSQL_PASSWORD", + "x-step": "connector" + }, + "ssl-mode": { + "type": "string", + "title": "SSL mode", + "description": "Use DISABLED, PREFERRED, or REQUIRED", + "enum": [ + "DISABLED", + "PREFERRED", + "REQUIRED" + ], + "x-placeholder": "PREFERRED", + "x-step": "connector" + }, + "sql": { + "type": "string", + "title": "SQL", + "description": "SQL query to run against your database", + "x-placeholder": "SELECT * FROM my_table", + "x-step": "explorer" + }, + "name": { + "type": "string", + "title": "Model name", + "description": "Name for the source model", + "pattern": "^[a-zA-Z0-9_]+$", + "x-placeholder": "my_model", + "x-step": "explorer" + } + }, + "required": [ + "sql", + "name" + ], + "allOf": [ + { + "if": { + "properties": { + "connection_mode": { + "const": "dsn" + } + } + }, + "then": { + "required": [ + "dsn" + ] + }, + "else": { + "required": [ + "host", + "database", + "user" + ] + } + } + ] + }, + "files": [ + { + "name": "connector", + "path_template": "connectors/[[ .connector_name ]].yaml", + "code_template": "# Connector YAML\n# Reference documentation: [[ .docs_url ]]\ntype: connector\ndriver: mysql\n[[ renderProps .config_props ]]\n" + }, + { + "name": "model", + "path_template": "models/[[ .model_name ]].yaml", + "code_template": "# Model YAML\n# Reference documentation: https://docs.rilldata.com/developers/build/connectors/data-source/mysql\ntype: model\n[[ if .connector_name -]]\nconnector: \"[[ .connector_name ]]\"\n[[ end -]]\nmaterialize: true\n[[ if .sql -]]\nsql: |\n [[ .sql | indent 2 ]]\n\ndev:\n sql: |\n [[ .sql ]] limit 10000\n[[ end -]]\n" + } + ] +} diff --git a/runtime/templates/definitions/duckdb-models/postgres-duckdb.json b/runtime/templates/definitions/duckdb-models/postgres-duckdb.json new file mode 100644 index 00000000000..2a32814ad2f --- /dev/null +++ b/runtime/templates/definitions/duckdb-models/postgres-duckdb.json @@ -0,0 +1,173 @@ +{ + "name": "postgres-duckdb", + "display_name": "PostgreSQL", + "description": "Query PostgreSQL databases and ingest into DuckDB", + "docs_url": "https://docs.rilldata.com/developers/build/connectors/data-source/postgres", + "driver": "postgres", + "olap": "duckdb", + "icon": "Postgres", + "small_icon": "PostgresIcon", + "tags": [ + "postgres", + "postgresql", + "database", + "duckdb", + "source", + "connector" + ], + "json_schema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "x-category": "sqlStore", + "properties": { + "connection_mode": { + "type": "string", + "title": "Connection method", + "enum": [ + "parameters", + "dsn" + ], + "default": "parameters", + "x-display": "tabs", + "x-enum-labels": [ + "Enter parameters", + "Enter connection string" + ], + "x-ui-only": true, + "x-tab-group": { + "parameters": [ + "host", + "port", + "user", + "password", + "dbname", + "sslmode" + ], + "dsn": [ + "dsn" + ] + }, + "x-step": "connector" + }, + "dsn": { + "type": "string", + "title": "Postgres connection string", + "description": "e.g. postgresql://user:password@host:5432/dbname?sslmode=require", + "x-placeholder": "postgresql://postgres:postgres@localhost:5432/postgres", + "x-secret": true, + "x-env-var": "POSTGRES_DSN", + "x-hint": "Use a DSN or provide host/user/password/dbname below (but not both).", + "x-step": "connector" + }, + "host": { + "type": "string", + "title": "Host", + "description": "Postgres server hostname or IP", + "x-placeholder": "localhost", + "x-step": "connector" + }, + "port": { + "type": "string", + "title": "Port", + "description": "Postgres server port", + "pattern": "^\\d+$", + "errorMessage": { + "pattern": "Port must be a number" + }, + "default": "5432", + "x-placeholder": "5432", + "x-step": "connector" + }, + "user": { + "type": "string", + "title": "Username", + "description": "Postgres user", + "x-placeholder": "postgres", + "x-step": "connector" + }, + "password": { + "type": "string", + "title": "Password", + "description": "Postgres password", + "x-placeholder": "your_password", + "x-secret": true, + "x-env-var": "POSTGRES_PASSWORD", + "x-step": "connector" + }, + "dbname": { + "type": "string", + "title": "Database", + "description": "Database name", + "x-placeholder": "postgres", + "x-step": "connector" + }, + "sslmode": { + "type": "string", + "title": "SSL mode", + "description": "Use disable, allow, prefer, require", + "enum": [ + "disable", + "allow", + "prefer", + "require" + ], + "x-placeholder": "require", + "x-step": "connector" + }, + "sql": { + "type": "string", + "title": "SQL", + "description": "SQL query to run against your database", + "x-placeholder": "SELECT * FROM my_table", + "x-step": "explorer" + }, + "name": { + "type": "string", + "title": "Model name", + "description": "Name for the source model", + "pattern": "^[a-zA-Z0-9_]+$", + "x-placeholder": "my_model", + "x-step": "explorer" + } + }, + "required": [ + "sql", + "name" + ], + "allOf": [ + { + "if": { + "properties": { + "connection_mode": { + "const": "dsn" + } + } + }, + "then": { + "required": [ + "dsn" + ] + }, + "else": { + "required": [ + "host", + "user", + "dbname" + ] + } + } + ] + }, + "files": [ + { + "name": "connector", + "path_template": "connectors/[[ .connector_name ]].yaml", + "code_template": "# Connector YAML\n# Reference documentation: [[ .docs_url ]]\ntype: connector\ndriver: postgres\n[[ renderProps .config_props ]]\n" + }, + { + "name": "model", + "path_template": "models/[[ .model_name ]].yaml", + "code_template": "# Model YAML\n# Reference documentation: https://docs.rilldata.com/developers/build/connectors/data-source/postgres\ntype: model\n[[ if .connector_name -]]\nconnector: \"[[ .connector_name ]]\"\n[[ end -]]\nmaterialize: true\n[[ if .sql -]]\nsql: |\n [[ .sql | indent 2 ]]\n\ndev:\n sql: |\n [[ .sql ]] limit 10000\n[[ end -]]\n" + } + ] +} diff --git a/runtime/templates/definitions/duckdb-models/redshift-duckdb.json b/runtime/templates/definitions/duckdb-models/redshift-duckdb.json new file mode 100644 index 00000000000..dc355e6b0c7 --- /dev/null +++ b/runtime/templates/definitions/duckdb-models/redshift-duckdb.json @@ -0,0 +1,105 @@ +{ + "name": "redshift-duckdb", + "display_name": "Amazon Redshift", + "description": "Query Amazon Redshift and ingest into DuckDB", + "docs_url": "https://docs.rilldata.com/developers/build/connectors/data-source/redshift", + "driver": "redshift", + "olap": "duckdb", + "icon": "AmazonRedshift", + "small_icon": "RedshiftIcon", + "tags": [ + "redshift", + "aws", + "warehouse", + "duckdb", + "source", + "connector" + ], + "json_schema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "x-category": "warehouse", + "properties": { + "aws_access_key_id": { + "type": "string", + "title": "AWS access key ID", + "description": "AWS access key ID", + "x-placeholder": "your_access_key_id", + "x-secret": true, + "x-env-var": "AWS_ACCESS_KEY_ID", + "x-step": "connector" + }, + "aws_secret_access_key": { + "type": "string", + "title": "AWS secret access key", + "description": "AWS secret access key", + "x-placeholder": "your_secret_access_key", + "x-secret": true, + "x-env-var": "AWS_SECRET_ACCESS_KEY", + "x-step": "connector" + }, + "region": { + "type": "string", + "title": "AWS region", + "description": "AWS region (e.g. us-east-1)", + "x-placeholder": "us-east-1", + "x-step": "connector" + }, + "database": { + "type": "string", + "title": "Database", + "description": "Redshift database name", + "x-placeholder": "dev", + "x-step": "connector" + }, + "workgroup": { + "type": "string", + "title": "Workgroup", + "description": "Redshift Serverless workgroup name", + "x-placeholder": "default", + "x-step": "connector" + }, + "cluster_identifier": { + "type": "string", + "title": "Cluster identifier", + "description": "Redshift cluster identifier (use when not using serverless)", + "x-placeholder": "redshift-cluster-1", + "x-step": "connector" + }, + "sql": { + "type": "string", + "title": "SQL", + "description": "SQL query to run against your warehouse", + "x-placeholder": "Input SQL", + "x-step": "explorer" + }, + "name": { + "type": "string", + "title": "Model name", + "description": "Name for the source model", + "pattern": "^[a-zA-Z0-9_]+$", + "x-placeholder": "my_model", + "x-step": "explorer" + } + }, + "required": [ + "aws_access_key_id", + "aws_secret_access_key", + "database", + "sql", + "name" + ] + }, + "files": [ + { + "name": "connector", + "path_template": "connectors/[[ .connector_name ]].yaml", + "code_template": "# Connector YAML\n# Reference documentation: [[ .docs_url ]]\ntype: connector\ndriver: redshift\n[[ renderProps .config_props ]]\n" + }, + { + "name": "model", + "path_template": "models/[[ .model_name ]].yaml", + "code_template": "# Model YAML\n# Reference documentation: https://docs.rilldata.com/developers/build/connectors/data-source/redshift\ntype: model\n[[ if .connector_name -]]\nconnector: \"[[ .connector_name ]]\"\n[[ end -]]\nmaterialize: true\n[[ if .sql -]]\nsql: |\n [[ .sql | indent 2 ]]\n[[ end ]]\n" + } + ] +} diff --git a/runtime/templates/definitions/duckdb-models/s3-duckdb.json b/runtime/templates/definitions/duckdb-models/s3-duckdb.json new file mode 100644 index 00000000000..3b6827fac7a --- /dev/null +++ b/runtime/templates/definitions/duckdb-models/s3-duckdb.json @@ -0,0 +1,164 @@ +{ + "name": "s3-duckdb", + "display_name": "Amazon S3", + "description": "Read files from Amazon S3 into DuckDB using the appropriate file reader", + "docs_url": "https://docs.rilldata.com/developers/build/connectors/data-source/s3", + "driver": "s3", + "olap": "duckdb", + "icon": "AmazonS3", + "small_icon": "AmazonS3Icon", + "tags": [ + "s3", + "aws", + "object-storage", + "duckdb", + "source", + "connector" + ], + "json_schema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "x-category": "objectStore", + "properties": { + "auth_method": { + "type": "string", + "title": "Authentication method", + "description": "Choose how to authenticate to S3", + "enum": [ + "access_keys", + "public" + ], + "default": "access_keys", + "x-display": "radio", + "x-enum-labels": [ + "Access keys", + "Public" + ], + "x-enum-descriptions": [ + "Use AWS access key ID and secret access key.", + "Access publicly readable buckets without credentials." + ], + "x-ui-only": true, + "x-grouped-fields": { + "access_keys": [ + "aws_access_key_id", + "aws_secret_access_key", + "region", + "endpoint", + "aws_role_arn" + ], + "public": [] + }, + "x-step": "connector" + }, + "aws_access_key_id": { + "type": "string", + "title": "Access Key ID", + "description": "AWS access key ID for the bucket", + "x-placeholder": "Enter AWS access key ID", + "x-secret": true, + "x-env-var": "AWS_ACCESS_KEY_ID", + "x-step": "connector", + "x-visible-if": { + "auth_method": "access_keys" + } + }, + "aws_secret_access_key": { + "type": "string", + "title": "Secret Access Key", + "description": "AWS secret access key for the bucket", + "x-placeholder": "Enter AWS secret access key", + "x-secret": true, + "x-env-var": "AWS_SECRET_ACCESS_KEY", + "x-step": "connector", + "x-visible-if": { + "auth_method": "access_keys" + } + }, + "region": { + "type": "string", + "title": "Region", + "description": "Rill uses your default AWS region unless you set it explicitly.", + "x-placeholder": "us-east-1", + "x-step": "connector", + "x-visible-if": { + "auth_method": "access_keys" + } + }, + "endpoint": { + "type": "string", + "title": "Endpoint", + "description": "Override the S3 endpoint (for S3-compatible services like R2/MinIO).", + "x-placeholder": "https://s3.example.com", + "x-step": "connector", + "x-visible-if": { + "auth_method": "access_keys" + } + }, + "aws_role_arn": { + "type": "string", + "title": "AWS Role ARN", + "description": "AWS Role ARN to assume", + "x-placeholder": "arn:aws:iam::123456789012:role/MyRole", + "x-secret": true, + "x-env-var": "AWS_ROLE_ARN", + "x-step": "connector", + "x-visible-if": { + "auth_method": "access_keys" + } + }, + "path": { + "type": "string", + "title": "S3 URI", + "description": "Path to your S3 bucket or prefix", + "pattern": "^s3://[^/]+(/.*)?$", + "errorMessage": { + "pattern": "Must be an S3 URI (e.g. s3://bucket/path)" + }, + "x-placeholder": "s3://bucket/path", + "x-step": "source" + }, + "name": { + "type": "string", + "title": "Model name", + "description": "Name for the source model", + "pattern": "^[a-zA-Z0-9_]+$", + "x-placeholder": "my_model", + "x-step": "source" + } + }, + "required": [ + "path", + "name" + ], + "allOf": [ + { + "if": { + "properties": { + "auth_method": { + "const": "access_keys" + } + } + }, + "then": { + "required": [ + "aws_access_key_id", + "aws_secret_access_key" + ] + } + } + ] + }, + "files": [ + { + "name": "connector", + "path_template": "connectors/[[ .connector_name ]].yaml", + "code_template": "# Connector YAML\n# Reference documentation: [[ .docs_url ]]\ntype: connector\ndriver: s3\n[[ renderProps .config_props ]]\n" + }, + { + "name": "model", + "path_template": "models/[[ .model_name ]].yaml", + "code_template": "type: model\nconnector: duckdb\n[[ if .connector_name -]]\ncreate_secrets_from_connectors: \"[[ .connector_name ]]\"\n[[ end -]]\nsql: |\n [[ duckdbSQL .path false ]]\n" + } + ] +} diff --git a/runtime/templates/definitions/duckdb-models/salesforce-duckdb.json b/runtime/templates/definitions/duckdb-models/salesforce-duckdb.json new file mode 100644 index 00000000000..b088e7bee64 --- /dev/null +++ b/runtime/templates/definitions/duckdb-models/salesforce-duckdb.json @@ -0,0 +1,142 @@ +{ + "name": "salesforce-duckdb", + "display_name": "Salesforce", + "description": "Query Salesforce objects and ingest into DuckDB", + "docs_url": "https://docs.rilldata.com/developers/build/connectors/data-source/salesforce", + "driver": "salesforce", + "olap": "duckdb", + "icon": "Salesforce", + "small_icon": "SalesforceIcon", + "tags": [ + "salesforce", + "crm", + "warehouse", + "duckdb", + "source", + "connector" + ], + "json_schema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "x-category": "sourceOnly", + "x-form-height": "tall", + "properties": { + "soql": { + "type": "string", + "title": "SOQL", + "description": "SOQL query to extract data", + "x-placeholder": "SELECT Id, Name FROM Opportunity", + "x-step": "source" + }, + "sobject": { + "type": "string", + "title": "SObject", + "description": "Salesforce object to query", + "x-placeholder": "Opportunity", + "x-step": "source" + }, + "queryAll": { + "type": "boolean", + "title": "Query all", + "description": "Include deleted and archived records", + "default": false, + "x-step": "source" + }, + "username": { + "type": "string", + "title": "Username", + "description": "Salesforce username (usually an email)", + "x-placeholder": "user@example.com" + }, + "password": { + "type": "string", + "title": "Password", + "description": "Salesforce password, optionally followed by security token if required", + "x-placeholder": "your_password_or_password+token", + "x-secret": true, + "x-env-var": "SALESFORCE_PASSWORD" + }, + "key": { + "type": "string", + "title": "JWT private key", + "description": "PEM-formatted private key for JWT auth", + "x-display": "textarea", + "x-placeholder": "your_private_key", + "x-secret": true, + "x-env-var": "SALESFORCE_KEY" + }, + "client_id": { + "type": "string", + "title": "Connected App Client ID", + "description": "Client ID (consumer key) for JWT auth", + "x-placeholder": "Connected App client ID" + }, + "endpoint": { + "type": "string", + "title": "Login endpoint", + "description": "Salesforce login URL (e.g., login.salesforce.com or test.salesforce.com)", + "x-placeholder": "login.salesforce.com" + }, + "name": { + "type": "string", + "title": "Source name", + "description": "Name for the source", + "x-placeholder": "my_new_source", + "x-step": "source" + } + }, + "required": [ + "soql", + "sobject", + "name" + ], + "allOf": [ + { + "if": { + "not": { + "required": [ + "key" + ], + "properties": { + "key": { + "minLength": 1 + } + } + } + }, + "then": { + "required": [ + "username", + "password", + "endpoint" + ] + } + }, + { + "if": { + "required": [ + "key" + ], + "properties": { + "key": { + "minLength": 1 + } + } + }, + "then": { + "required": [ + "client_id", + "username" + ] + } + } + ] + }, + "files": [ + { + "name": "model", + "path_template": "models/[[ .model_name ]].yaml", + "code_template": "# Model YAML\n# Reference documentation: https://docs.rilldata.com/developers/build/connectors/data-source/salesforce\ntype: model\n[[ if .connector_name -]]\nconnector: \"[[ .connector_name ]]\"\n[[ end -]]\nmaterialize: true\n[[ renderProps .source_props -]]\n[[ if .sql -]]\nsql: |\n [[ .sql | indent 2 ]]\n\ndev:\n sql: |\n [[ .sql ]] limit 10000\n[[ end -]]\n" + } + ] +} diff --git a/runtime/templates/definitions/duckdb-models/snowflake-duckdb.json b/runtime/templates/definitions/duckdb-models/snowflake-duckdb.json new file mode 100644 index 00000000000..c1f970a23d2 --- /dev/null +++ b/runtime/templates/definitions/duckdb-models/snowflake-duckdb.json @@ -0,0 +1,232 @@ +{ + "name": "snowflake-duckdb", + "display_name": "Snowflake", + "description": "Query Snowflake data warehouses and ingest into DuckDB", + "docs_url": "https://docs.rilldata.com/developers/build/connectors/data-source/snowflake", + "driver": "snowflake", + "olap": "duckdb", + "icon": "Snowflake", + "small_icon": "SnowflakeIcon", + "tags": [ + "snowflake", + "warehouse", + "duckdb", + "source", + "connector" + ], + "json_schema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "x-category": "warehouse", + "x-form-height": "tall", + "properties": { + "auth_method": { + "type": "string", + "title": "Authentication method", + "enum": [ + "password", + "private_key", + "dsn" + ], + "default": "password", + "x-display": "tabs", + "x-enum-labels": [ + "User/Password", + "Private Key", + "Connection String" + ], + "x-ui-only": true, + "x-tab-group": { + "password": [ + "account", + "user", + "password", + "warehouse", + "database", + "schema", + "role" + ], + "private_key": [ + "account", + "user", + "privateKey", + "warehouse", + "database", + "schema", + "role" + ], + "dsn": [ + "dsn" + ] + }, + "x-step": "connector" + }, + "account": { + "type": "string", + "title": "Account identifier", + "description": "Snowflake account identifier (from your Snowflake URL, before .snowflakecomputing.com)", + "x-placeholder": "abc12345.us-east-1", + "x-hint": "e.g. abc12345 or abc12345.us-east-1 \u2014 don't include https://", + "x-step": "connector" + }, + "user": { + "type": "string", + "title": "Username", + "description": "Snowflake username", + "x-placeholder": "your_username", + "x-step": "connector" + }, + "password": { + "type": "string", + "title": "Password", + "description": "Snowflake password", + "x-placeholder": "your_password", + "x-secret": true, + "x-env-var": "SNOWFLAKE_PASSWORD", + "x-visible-if": { + "auth_method": "password" + }, + "x-step": "connector" + }, + "privateKey": { + "type": "string", + "title": "Private key", + "description": "Upload your Snowflake private key file (.pem or .p8)", + "format": "file", + "x-display": "file", + "x-file-accept": ".pem,.p8", + "x-file-encoding": "base64", + "x-secret": true, + "x-env-var": "SNOWFLAKE_PRIVATEKEY", + "x-visible-if": { + "auth_method": "private_key" + }, + "x-step": "connector" + }, + "warehouse": { + "type": "string", + "title": "Warehouse", + "description": "Compute warehouse", + "x-placeholder": "your_warehouse", + "x-step": "connector" + }, + "database": { + "type": "string", + "title": "Database", + "description": "Snowflake database", + "x-placeholder": "your_database", + "x-step": "connector" + }, + "schema": { + "type": "string", + "title": "Schema", + "description": "Default schema", + "x-placeholder": "public", + "x-step": "connector" + }, + "role": { + "type": "string", + "title": "Role", + "description": "Snowflake role", + "x-placeholder": "your_role", + "x-step": "connector" + }, + "dsn": { + "type": "string", + "title": "Connection string", + "description": "Full Snowflake DSN, e.g. @//?warehouse=&role=", + "x-placeholder": "@//?warehouse=&role=", + "x-secret": true, + "x-env-var": "SNOWFLAKE_DSN", + "x-hint": "Include authenticator and privateKey query params for JWT if needed.", + "x-visible-if": { + "auth_method": "dsn" + }, + "x-step": "connector" + }, + "sql": { + "type": "string", + "title": "SQL", + "description": "SQL query to run against your warehouse", + "x-placeholder": "Input SQL", + "x-step": "explorer" + }, + "name": { + "type": "string", + "title": "Model name", + "description": "Name for the source model", + "pattern": "^[a-zA-Z0-9_]+$", + "x-placeholder": "my_model", + "x-step": "explorer" + } + }, + "required": [ + "sql", + "name" + ], + "allOf": [ + { + "if": { + "properties": { + "auth_method": { + "const": "password" + } + } + }, + "then": { + "required": [ + "account", + "user", + "password", + "database", + "warehouse" + ] + } + }, + { + "if": { + "properties": { + "auth_method": { + "const": "private_key" + } + } + }, + "then": { + "required": [ + "account", + "user", + "privateKey", + "database", + "warehouse" + ] + } + }, + { + "if": { + "properties": { + "auth_method": { + "const": "dsn" + } + } + }, + "then": { + "required": [ + "dsn" + ] + } + } + ] + }, + "files": [ + { + "name": "connector", + "path_template": "connectors/[[ .connector_name ]].yaml", + "code_template": "# Connector YAML\n# Reference documentation: [[ .docs_url ]]\ntype: connector\ndriver: snowflake\n[[ renderProps .config_props ]]\n" + }, + { + "name": "model", + "path_template": "models/[[ .model_name ]].yaml", + "code_template": "# Model YAML\n# Reference documentation: https://docs.rilldata.com/developers/build/connectors/data-source/snowflake\ntype: model\n[[ if .connector_name -]]\nconnector: \"[[ .connector_name ]]\"\n[[ end -]]\nmaterialize: true\n[[ if .sql -]]\nsql: |\n [[ .sql | indent 2 ]]\n\ndev:\n sql: |\n [[ .sql ]] limit 10000\n[[ end -]]\n" + } + ] +} diff --git a/runtime/templates/definitions/duckdb-models/sqlite-duckdb.json b/runtime/templates/definitions/duckdb-models/sqlite-duckdb.json new file mode 100644 index 00000000000..9c3d71458ae --- /dev/null +++ b/runtime/templates/definitions/duckdb-models/sqlite-duckdb.json @@ -0,0 +1,53 @@ +{ + "name": "sqlite-duckdb", + "display_name": "SQLite", + "description": "Read SQLite tables into DuckDB", + "docs_url": "https://docs.rilldata.com/developers/build/connectors/data-source/sqlite", + "driver": "sqlite", + "olap": "duckdb", + "icon": "SQLite", + "small_icon": "SQLiteIcon", + "tags": [ + "sqlite", + "database", + "duckdb", + "source" + ], + "json_schema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "x-category": "sourceOnly", + "properties": { + "db": { + "type": "string", + "title": "Database file", + "description": "Path to SQLite db file", + "x-placeholder": "/path/to/sqlite.db" + }, + "table": { + "type": "string", + "title": "Table", + "description": "SQLite table name", + "x-placeholder": "table" + }, + "name": { + "type": "string", + "title": "Source name", + "description": "Name of the source", + "x-placeholder": "my_new_source" + } + }, + "required": [ + "db", + "table", + "name" + ] + }, + "files": [ + { + "name": "model", + "path_template": "models/[[ .model_name ]].yaml", + "code_template": "# Model YAML\n# Reference documentation: https://docs.rilldata.com/developers/build/connectors/data-source/sqlite\ntype: model\nconnector: duckdb\nsql: |\n SELECT * FROM sqlite_scan('[[ .db ]]', '[[ .table ]]');\n" + } + ] +} diff --git a/runtime/templates/definitions/duckdb-models/supabase-duckdb.json b/runtime/templates/definitions/duckdb-models/supabase-duckdb.json new file mode 100644 index 00000000000..28e5401ed43 --- /dev/null +++ b/runtime/templates/definitions/duckdb-models/supabase-duckdb.json @@ -0,0 +1,147 @@ +{ + "name": "supabase-duckdb", + "display_name": "Supabase", + "description": "Query Supabase databases and ingest into DuckDB", + "docs_url": "https://docs.rilldata.com/developers/build/connectors/data-source/postgres", + "driver": "supabase", + "olap": "duckdb", + "icon": "Supabase", + "small_icon": "SupabaseIcon", + "tags": [ + "supabase", + "postgres", + "database", + "duckdb", + "source", + "connector" + ], + + "json_schema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "x-category": "sqlStore", + + "properties": { + "connection_mode": { + "type": "string", + "title": "Connection method", + "enum": ["parameters", "dsn"], + "default": "parameters", + "x-display": "tabs", + "x-enum-labels": ["Enter parameters", "Enter connection string"], + "x-ui-only": true, + "x-tab-group": { + "parameters": ["host", "port", "user", "password", "dbname", "sslmode"], + "dsn": ["dsn"] + }, + "x-step": "connector" + }, + + "dsn": { + "type": "string", + "title": "Supabase connection string", + "description": "e.g. postgresql://postgres.[ref]:[password]@aws-0-[region].pooler.supabase.com:5432/postgres", + "x-placeholder": "postgresql://postgres.[ref]:[password]@aws-0-[region].pooler.supabase.com:5432/postgres", + "x-secret": true, + "x-env-var": "SUPABASE_DSN", + "x-hint": "Use a DSN or provide host/user/password/dbname below (but not both).", + "x-step": "connector" + }, + + "host": { + "type": "string", + "title": "Host", + "description": "Supabase database host", + "x-placeholder": "aws-0-[region].pooler.supabase.com", + "x-step": "connector" + }, + + "port": { + "type": "string", + "title": "Port", + "description": "Supabase database port", + "pattern": "^\\d+$", + "errorMessage": { "pattern": "Port must be a number" }, + "default": "5432", + "x-placeholder": "5432", + "x-step": "connector" + }, + + "user": { + "type": "string", + "title": "Username", + "description": "Supabase database user", + "x-placeholder": "postgres.[ref]", + "x-step": "connector" + }, + + "password": { + "type": "string", + "title": "Password", + "description": "Supabase database password", + "x-placeholder": "your_password", + "x-secret": true, + "x-env-var": "SUPABASE_PASSWORD", + "x-step": "connector" + }, + + "dbname": { + "type": "string", + "title": "Database", + "description": "Database name", + "x-placeholder": "postgres", + "x-step": "connector" + }, + + "sslmode": { + "type": "string", + "title": "SSL mode", + "description": "Use disable, allow, prefer, require", + "enum": ["disable", "allow", "prefer", "require"], + "default": "require", + "x-placeholder": "require", + "x-step": "connector" + }, + + "sql": { + "type": "string", + "title": "SQL", + "description": "SQL query to run against your database", + "x-placeholder": "SELECT * FROM my_table", + "x-step": "explorer" + }, + + "name": { + "type": "string", + "title": "Model name", + "description": "Name for the source model", + "pattern": "^[a-zA-Z0-9_]+$", + "x-placeholder": "my_model", + "x-step": "explorer" + } + }, + + "required": ["sql", "name"], + + "allOf": [ + { + "if": { "properties": { "connection_mode": { "const": "dsn" } } }, + "then": { "required": ["dsn"] }, + "else": { "required": ["host", "user", "dbname"] } + } + ] + }, + + "files": [ + { + "name": "connector", + "path_template": "connectors/[[ .connector_name ]].yaml", + "code_template": "# Connector YAML\n# Reference documentation: [[ .docs_url ]]\ntype: connector\ndriver: supabase\n[[ renderProps .config_props ]]\n" + }, + { + "name": "model", + "path_template": "models/[[ .model_name ]].yaml", + "code_template": "# Model YAML\n# Reference documentation: https://docs.rilldata.com/developers/build/connectors/data-source/postgres\ntype: model\n[[ if .connector_name -]]\nconnector: \"[[ .connector_name ]]\"\n[[ end -]]\nmaterialize: true\n[[ if .sql -]]\nsql: |\n [[ .sql | indent 2 ]]\n\ndev:\n sql: |\n [[ .sql ]] limit 10000\n[[ end -]]\n" + } + ] +} diff --git a/runtime/templates/definitions/olap/druid.json b/runtime/templates/definitions/olap/druid.json new file mode 100644 index 00000000000..9d46c2d7023 --- /dev/null +++ b/runtime/templates/definitions/olap/druid.json @@ -0,0 +1,123 @@ +{ + "name": "druid", + "display_name": "Druid", + "description": "Connect to an Apache Druid OLAP engine", + "docs_url": "https://docs.rilldata.com/developers/build/connectors/olap/druid", + "driver": "druid", + "icon": "ApacheDruid", + "small_icon": "ApacheDruidIcon", + "tags": [ + "druid", + "olap", + "analytics", + "connector" + ], + "json_schema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "x-category": "olap", + "properties": { + "connection_mode": { + "type": "string", + "title": "Connection method", + "enum": [ + "parameters", + "dsn" + ], + "default": "parameters", + "x-display": "tabs", + "x-enum-labels": [ + "Enter parameters", + "Enter connection string" + ], + "x-ui-only": true, + "x-tab-group": { + "parameters": [ + "host", + "port", + "username", + "password", + "ssl" + ], + "dsn": [ + "dsn" + ] + }, + "x-step": "connector" + }, + "dsn": { + "type": "string", + "title": "Connection string", + "description": "Full Druid SQL/Avatica endpoint", + "x-placeholder": "https://example.com/druid/v2/sql/avatica-protobuf?authentication=BASIC&avaticaUser=user&avaticaPassword=pass", + "x-secret": true, + "x-env-var": "DRUID_DSN", + "x-step": "connector" + }, + "host": { + "type": "string", + "title": "Host", + "description": "Druid host or IP", + "x-placeholder": "localhost", + "x-step": "connector" + }, + "port": { + "type": "string", + "title": "Port", + "description": "Druid port", + "pattern": "^\\d+$", + "errorMessage": { + "pattern": "Port must be a number" + }, + "x-placeholder": "8888", + "x-step": "connector" + }, + "username": { + "type": "string", + "title": "Username", + "description": "Druid username", + "x-placeholder": "default", + "x-step": "connector" + }, + "password": { + "type": "string", + "title": "Password", + "description": "Druid password", + "x-placeholder": "password", + "x-secret": true, + "x-env-var": "DRUID_PASSWORD", + "x-step": "connector" + }, + "ssl": { + "type": "boolean", + "title": "SSL", + "description": "Use SSL for the connection", + "default": true, + "x-step": "connector" + } + }, + "required": [], + "oneOf": [ + { + "title": "Use connection string", + "required": [ + "dsn" + ] + }, + { + "title": "Use individual parameters", + "required": [ + "host", + "ssl" + ] + } + ] + }, + "files": [ + { + "name": "connector", + "path_template": "connectors/[[ .connector_name ]].yaml", + "code_template": "# Connector YAML\n# Reference documentation: https://docs.rilldata.com/developers/build/connectors/olap/druid\ntype: connector\ndriver: druid\n[[ renderProps .props ]]\n" + } + ] +} diff --git a/runtime/templates/definitions/olap/duckdb.json b/runtime/templates/definitions/olap/duckdb.json new file mode 100644 index 00000000000..93d09dae3b4 --- /dev/null +++ b/runtime/templates/definitions/olap/duckdb.json @@ -0,0 +1,125 @@ +{ + "name": "duckdb", + "display_name": "DuckDB", + "description": "Connect to a DuckDB OLAP engine", + "docs_url": "https://docs.rilldata.com/developers/build/connectors/olap/duckdb", + "driver": "duckdb", + "icon": "DuckDB", + "small_icon": "DuckDBIcon", + "tags": [ + "duckdb", + "olap", + "connector" + ], + "json_schema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "x-category": "olap", + "x-button-labels": { + "connector_type": { + "rill-managed": { + "idle": "Connect", + "loading": "Connecting..." + } + } + }, + "properties": { + "connector_type": { + "type": "string", + "title": "Connection type", + "enum": [ + "rill-managed", + "self-hosted" + ], + "default": "rill-managed", + "x-display": "select", + "x-select-style": "rich", + "x-enum-labels": [ + "Rill Managed", + "Local File" + ], + "x-enum-descriptions": [ + "Rill manages your DuckDB infrastructure", + "Connect to your own DuckDB database file" + ], + "x-ui-only": true, + "x-grouped-fields": { + "rill-managed": [ + "managed" + ], + "self-hosted": [ + "path" + ] + }, + "x-step": "connector" + }, + "managed": { + "type": "boolean", + "title": "Managed", + "description": "This option uses DuckDB as an OLAP engine with Rill-managed infrastructure. No additional configuration is required.", + "default": true, + "x-informational": true, + "x-ui-only": true, + "x-visible-if": { + "connector_type": "rill-managed" + }, + "x-step": "connector" + }, + "path": { + "type": "string", + "title": "Path", + "description": "Path to external DuckDB database", + "x-placeholder": "/path/to/main.db", + "x-visible-if": { + "connector_type": "self-hosted" + }, + "x-step": "connector" + } + }, + "required": [ + "connector_type" + ], + "allOf": [ + { + "if": { + "properties": { + "connector_type": { + "const": "rill-managed" + } + } + }, + "then": { + "required": [ + "managed" + ], + "properties": { + "managed": { + "const": true + } + } + } + }, + { + "if": { + "properties": { + "connector_type": { + "const": "self-hosted" + } + } + }, + "then": { + "required": [ + "path" + ] + } + } + ] + }, + "files": [ + { + "name": "connector", + "path_template": "connectors/[[ .connector_name ]].yaml", + "code_template": "# Connector YAML\n# Reference documentation: https://docs.rilldata.com/developers/build/connectors/olap/duckdb\ntype: connector\ndriver: duckdb\n[[ renderProps .props ]]\n" + } + ] +} diff --git a/runtime/templates/definitions/olap/motherduck.json b/runtime/templates/definitions/olap/motherduck.json new file mode 100644 index 00000000000..f4466f13192 --- /dev/null +++ b/runtime/templates/definitions/olap/motherduck.json @@ -0,0 +1,57 @@ +{ + "name": "motherduck", + "display_name": "MotherDuck", + "description": "Connect to a MotherDuck OLAP engine", + "docs_url": "https://docs.rilldata.com/developers/build/connectors/olap/motherduck", + "driver": "motherduck", + "icon": "MotherDuck", + "small_icon": "MotherDuckIcon", + "tags": [ + "motherduck", + "duckdb", + "olap", + "connector" + ], + "json_schema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "x-category": "olap", + "properties": { + "path": { + "type": "string", + "title": "Path", + "description": "MotherDuck database path (prefix with md:)", + "x-placeholder": "md:my_db", + "x-step": "connector" + }, + "token": { + "type": "string", + "title": "Token", + "description": "MotherDuck token", + "x-placeholder": "your_motherduck_token", + "x-secret": true, + "x-env-var": "MOTHERDUCK_TOKEN", + "x-step": "connector" + }, + "schema_name": { + "type": "string", + "title": "Schema name", + "description": "Default schema to use", + "x-placeholder": "main", + "x-step": "connector" + } + }, + "required": [ + "path", + "token", + "schema_name" + ] + }, + "files": [ + { + "name": "connector", + "path_template": "connectors/[[ .connector_name ]].yaml", + "code_template": "# Connector YAML\n# Reference documentation: https://docs.rilldata.com/developers/build/connectors/olap/motherduck\ntype: connector\ndriver: motherduck\n[[ renderProps .props ]]\n" + } + ] +} diff --git a/runtime/templates/definitions/olap/pinot.json b/runtime/templates/definitions/olap/pinot.json new file mode 100644 index 00000000000..d5560ba1f49 --- /dev/null +++ b/runtime/templates/definitions/olap/pinot.json @@ -0,0 +1,144 @@ +{ + "name": "pinot", + "display_name": "Pinot", + "description": "Connect to an Apache Pinot OLAP engine", + "docs_url": "https://docs.rilldata.com/developers/build/connectors/olap/pinot", + "driver": "pinot", + "icon": "ApachePinot", + "small_icon": "ApachePinotIcon", + "tags": [ + "pinot", + "olap", + "analytics", + "connector" + ], + "json_schema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "x-category": "olap", + "properties": { + "connection_mode": { + "type": "string", + "title": "Connection method", + "enum": [ + "parameters", + "dsn" + ], + "default": "parameters", + "x-display": "tabs", + "x-enum-labels": [ + "Enter parameters", + "Enter connection string" + ], + "x-ui-only": true, + "x-tab-group": { + "parameters": [ + "broker_host", + "broker_port", + "controller_host", + "controller_port", + "username", + "password", + "ssl" + ], + "dsn": [ + "dsn" + ] + }, + "x-step": "connector" + }, + "dsn": { + "type": "string", + "title": "Connection string", + "description": "Full Pinot connection string", + "x-placeholder": "https://username:password@localhost:8000?controller=localhost:9000", + "x-secret": true, + "x-env-var": "PINOT_DSN", + "x-step": "connector" + }, + "broker_host": { + "type": "string", + "title": "Broker host", + "description": "Pinot broker host", + "x-placeholder": "localhost", + "x-step": "connector" + }, + "broker_port": { + "type": "string", + "title": "Broker port", + "description": "Pinot broker port", + "pattern": "^\\d+$", + "errorMessage": { + "pattern": "Port must be a number" + }, + "x-placeholder": "8000", + "x-step": "connector" + }, + "controller_host": { + "type": "string", + "title": "Controller host", + "description": "Pinot controller host", + "x-placeholder": "localhost", + "x-step": "connector" + }, + "controller_port": { + "type": "string", + "title": "Controller port", + "description": "Pinot controller port", + "pattern": "^\\d+$", + "errorMessage": { + "pattern": "Port must be a number" + }, + "x-placeholder": "9000", + "x-step": "connector" + }, + "username": { + "type": "string", + "title": "Username", + "description": "Pinot username", + "x-placeholder": "default", + "x-step": "connector" + }, + "password": { + "type": "string", + "title": "Password", + "description": "Pinot password", + "x-placeholder": "password", + "x-secret": true, + "x-env-var": "PINOT_PASSWORD", + "x-step": "connector" + }, + "ssl": { + "type": "boolean", + "title": "SSL", + "description": "Use SSL", + "default": true, + "x-step": "connector" + } + }, + "required": [], + "oneOf": [ + { + "title": "Use connection string", + "required": [ + "dsn" + ] + }, + { + "title": "Use individual parameters", + "required": [ + "broker_host", + "controller_host", + "ssl" + ] + } + ] + }, + "files": [ + { + "name": "connector", + "path_template": "connectors/[[ .connector_name ]].yaml", + "code_template": "# Connector YAML\n# Reference documentation: https://docs.rilldata.com/developers/build/connectors/olap/pinot\ntype: connector\ndriver: pinot\n[[ renderProps .props ]]\n" + } + ] +} diff --git a/runtime/templates/definitions/olap/starrocks.json b/runtime/templates/definitions/olap/starrocks.json new file mode 100644 index 00000000000..2442024771d --- /dev/null +++ b/runtime/templates/definitions/olap/starrocks.json @@ -0,0 +1,148 @@ +{ + "name": "starrocks", + "display_name": "StarRocks", + "description": "Connect to a StarRocks OLAP engine", + "docs_url": "https://docs.rilldata.com/developers/build/connectors/olap/starrocks", + "driver": "starrocks", + "icon": "StarRocks", + "small_icon": "StarRocksIcon", + "tags": [ + "starrocks", + "olap", + "analytics", + "connector" + ], + "json_schema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "x-category": "olap", + "x-form-height": "tall", + "properties": { + "connection_mode": { + "type": "string", + "title": "Connection method", + "enum": [ + "parameters", + "dsn" + ], + "default": "parameters", + "x-display": "tabs", + "x-enum-labels": [ + "Enter parameters", + "Enter connection string" + ], + "x-ui-only": true, + "x-tab-group": { + "parameters": [ + "host", + "port", + "username", + "password", + "catalog", + "database", + "ssl" + ], + "dsn": [ + "dsn" + ] + }, + "x-step": "connector" + }, + "dsn": { + "type": "string", + "title": "Connection string", + "description": "MySQL DSN format. If provided, do not set host/port/username/password.", + "x-placeholder": "user:password@tcp(host:9030)/?timeout=30s&readTimeout=300s&parseTime=true", + "x-secret": true, + "x-env-var": "STARROCKS_DSN", + "x-step": "connector" + }, + "host": { + "type": "string", + "title": "Host", + "description": "Hostname or IP address of the StarRocks FE node", + "x-placeholder": "localhost", + "x-step": "connector" + }, + "port": { + "type": "string", + "title": "Port", + "description": "MySQL protocol port of the StarRocks FE node", + "pattern": "^\\d+$", + "errorMessage": { + "pattern": "Port must be a number" + }, + "default": "9030", + "x-placeholder": "9030", + "x-step": "connector" + }, + "username": { + "type": "string", + "title": "Username", + "description": "Username to connect to StarRocks", + "default": "root", + "x-placeholder": "root", + "x-step": "connector" + }, + "password": { + "type": "string", + "title": "Password", + "description": "Password to connect to StarRocks", + "x-placeholder": "password", + "x-secret": true, + "x-env-var": "STARROCKS_PASSWORD", + "x-step": "connector" + }, + "catalog": { + "type": "string", + "title": "Catalog", + "description": "StarRocks catalog name. Use default_catalog for internal tables, or specify an external catalog.", + "default": "default_catalog", + "x-placeholder": "default_catalog", + "x-step": "connector" + }, + "database": { + "type": "string", + "title": "Database", + "description": "Name of the StarRocks database to connect to", + "x-placeholder": "default", + "x-step": "connector" + }, + "ssl": { + "type": "boolean", + "title": "SSL", + "description": "Enable SSL/TLS encryption for the connection", + "x-step": "connector" + } + }, + "required": [], + "allOf": [ + { + "if": { + "properties": { + "connection_mode": { + "const": "dsn" + } + } + }, + "then": { + "required": [ + "dsn" + ] + }, + "else": { + "required": [ + "host" + ] + } + } + ] + }, + "files": [ + { + "name": "connector", + "path_template": "connectors/[[ .connector_name ]].yaml", + "code_template": "# Connector YAML\n# Reference documentation: https://docs.rilldata.com/developers/build/connectors/olap/starrocks\ntype: connector\ndriver: starrocks\n[[ renderProps .props ]]\n" + } + ] +} diff --git a/runtime/templates/duckdb_test.go b/runtime/templates/duckdb_test.go new file mode 100644 index 00000000000..99ec50137cb --- /dev/null +++ b/runtime/templates/duckdb_test.go @@ -0,0 +1,81 @@ +package templates + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestDuckdbSQL(t *testing.T) { + tests := []struct { + name string + path string + defaultToJSON bool + wantContains string + }{ + {"parquet", "s3://bucket/data.parquet", false, "read_parquet"}, + {"csv", "s3://bucket/data.csv", false, "read_csv"}, + {"tsv", "s3://bucket/data.tsv", false, "read_csv"}, + {"json", "s3://bucket/data.json", false, "read_json"}, + {"ndjson", "s3://bucket/data.ndjson", false, "read_json"}, + {"compound parquet.gz", "s3://bucket/data.v1.parquet.gz", false, "read_parquet"}, + {"unknown default generic", "s3://bucket/data.xyz", false, "select * from 's3://bucket/data.xyz'"}, + {"unknown default json", "https://example.com/api", true, "read_json"}, + {"txt", "s3://bucket/data.txt", false, "read_csv"}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + query := duckdbSQL(tt.path, tt.defaultToJSON) + require.Contains(t, query, tt.wantContains) + require.Contains(t, query, tt.path) + }) + } +} + +func TestMatchesExtFixedFalsePositive(t *testing.T) { + // This was a bug: "parquet-archive/readme.txt" should NOT match ".parquet" + require.False(t, matchesExt("s3://bucket/parquet-archive/readme.txt", ".parquet"), + "path with 'parquet' in directory name should not match .parquet extension") + + // But actual parquet files should match + require.True(t, matchesExt("s3://bucket/data.parquet", ".parquet")) + require.True(t, matchesExt("s3://bucket/data.v1.parquet.gz", ".parquet")) +} + +func TestMatchesExtCompound(t *testing.T) { + require.True(t, matchesExt("data.csv.gz", ".csv")) + require.True(t, matchesExt("data.ndjson.gz", ".ndjson")) + require.False(t, matchesExt("data.xyz", ".csv", ".json")) +} + +func TestClickhouseURLSuffix(t *testing.T) { + props := []ProcessedProp{ + {Key: "headers", Value: "\n Authorization: \"Bearer {{ .env.connector.https.authorization }}\"\n X-API-Key: \"{{ .env.connector.https.x_api_key }}\"", Quoted: false}, + } + + // CSV URL with headers: includes format and headers() + result := clickhouseURLSuffix("https://example.com/data.csv", props) + require.Contains(t, result, "CSVWithNames") + require.Contains(t, result, "headers(") + require.Contains(t, result, "'Authorization'='Bearer {{ .env.connector.https.authorization }}'") + require.Contains(t, result, "'X-API-Key'='{{ .env.connector.https.x_api_key }}'") + + // Parquet URL with headers + result = clickhouseURLSuffix("https://example.com/data.parquet", props) + require.Contains(t, result, "Parquet") + require.Contains(t, result, "headers(") + + // JSON URL with headers + result = clickhouseURLSuffix("https://example.com/data.ndjson", props) + require.Contains(t, result, "JSONEachRow") + + // No headers: returns empty (ClickHouse auto-detects) + noHeaders := []ProcessedProp{ + {Key: "path", Value: "https://example.com", Quoted: true}, + } + require.Equal(t, "", clickhouseURLSuffix("https://example.com/data.csv", noHeaders)) + + // Nil/wrong type: returns empty + require.Equal(t, "", clickhouseURLSuffix("https://example.com/data.csv", nil)) +} diff --git a/runtime/templates/env.go b/runtime/templates/env.go new file mode 100644 index 00000000000..8fc8edee09d --- /dev/null +++ b/runtime/templates/env.go @@ -0,0 +1,48 @@ +package templates + +import ( + "bufio" + "context" + "fmt" + "strings" + + "github.com/rilldata/rill/runtime/drivers" +) + +// ResolveEnvVarNameForKey determines the env var name for a secret property key, +// using an explicit env var name when provided, or falling back to DRIVER_KEY format. +// This variant does not require a *drivers.PropertySpec; used by schema-based templates. +func ResolveEnvVarNameForKey(driverName, key, explicitEnvVarName string, existingEnv map[string]bool) string { + var base string + if explicitEnvVarName != "" { + base = explicitEnvVarName + } else { + base = strings.ToUpper(driverName) + "_" + strings.ToUpper(key) + } + + candidate := base + for i := 1; existingEnv[candidate]; i++ { + candidate = fmt.Sprintf("%s_%d", base, i) + } + return candidate +} + +// ReadEnvKeys parses a .env file into a set of key names. +func ReadEnvKeys(ctx context.Context, repo drivers.RepoStore) map[string]bool { + keys := make(map[string]bool) + content, err := repo.Get(ctx, ".env") + if err != nil { + return keys + } + scanner := bufio.NewScanner(strings.NewReader(content)) + for scanner.Scan() { + line := strings.TrimSpace(scanner.Text()) + if line == "" || strings.HasPrefix(line, "#") { + continue + } + if idx := strings.IndexByte(line, '='); idx > 0 { + keys[line[:idx]] = true + } + } + return keys +} diff --git a/runtime/templates/env_test.go b/runtime/templates/env_test.go new file mode 100644 index 00000000000..6bcbb160c6a --- /dev/null +++ b/runtime/templates/env_test.go @@ -0,0 +1,40 @@ +package templates + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestResolveEnvVarNameWithExplicitName(t *testing.T) { + existing := make(map[string]bool) + + name := ResolveEnvVarNameForKey("s3", "aws_access_key_id", "AWS_ACCESS_KEY_ID", existing) + require.Equal(t, "AWS_ACCESS_KEY_ID", name) +} + +func TestResolveEnvVarNameFallback(t *testing.T) { + existing := make(map[string]bool) + + name := ResolveEnvVarNameForKey("starrocks", "password", "", existing) + require.Equal(t, "STARROCKS_PASSWORD", name) +} + +func TestResolveEnvVarNameConflict(t *testing.T) { + existing := map[string]bool{ + "AWS_ACCESS_KEY_ID": true, + } + + name := ResolveEnvVarNameForKey("s3", "aws_access_key_id", "AWS_ACCESS_KEY_ID", existing) + require.Equal(t, "AWS_ACCESS_KEY_ID_1", name) +} + +func TestResolveEnvVarNameDoubleConflict(t *testing.T) { + existing := map[string]bool{ + "AWS_ACCESS_KEY_ID": true, + "AWS_ACCESS_KEY_ID_1": true, + } + + name := ResolveEnvVarNameForKey("s3", "aws_access_key_id", "AWS_ACCESS_KEY_ID", existing) + require.Equal(t, "AWS_ACCESS_KEY_ID_2", name) +} diff --git a/runtime/templates/funcmap.go b/runtime/templates/funcmap.go new file mode 100644 index 00000000000..6b54199bc9c --- /dev/null +++ b/runtime/templates/funcmap.go @@ -0,0 +1,288 @@ +package templates + +import ( + "fmt" + "path/filepath" + "strings" + "text/template" +) + +// sharedFuncMap is the template function map available to all template definitions. +// Allocated once since all entries are stateless functions. +var sharedFuncMap = template.FuncMap{ + "renderProps": renderProps, + "indent": indent, + "quote": quote, + "propVal": propVal, + "default": defaultVal, + "duckdbSQL": duckdbSQL, + "s3ToHTTPS": s3ToHTTPS, + "gcsToHTTPS": gcsToHTTPS, + "azureContainer": azureContainer, + "azureBlobPath": azureBlobPath, + "azureEndpoint": azureEndpoint, + "clickhouseFormat": clickhouseFormat, + "clickhouseURLSuffix": clickhouseURLSuffix, +} + +// renderProps renders a slice of ProcessedProp as YAML key-value lines. +// Each property is rendered on its own line with appropriate formatting: +// quoted values get double quotes, unquoted values are rendered as-is. +func renderProps(props []ProcessedProp) string { + if len(props) == 0 { + return "" + } + var b strings.Builder + for i, p := range props { + if i > 0 { + b.WriteByte('\n') + } + if p.Quoted { + fmt.Fprintf(&b, "%s: %q", p.Key, p.Value) + } else { + fmt.Fprintf(&b, "%s: %s", p.Key, p.Value) + } + } + return b.String() +} + +// indent prepends each line of text with n spaces. +func indent(n int, text string) string { + pad := strings.Repeat(" ", n) + lines := strings.Split(text, "\n") + for i, line := range lines { + if line != "" { + lines[i] = pad + line + } + } + return strings.Join(lines, "\n") +} + +// quote wraps a string in double quotes. +func quote(s string) string { + return fmt.Sprintf("%q", s) +} + +// propVal extracts a value from a []ProcessedProp by key. +// Returns "" if the key is not found or props is not the expected type. +func propVal(props any, key string) string { + ps, ok := props.([]ProcessedProp) + if !ok { + return "" + } + for _, p := range ps { + if p.Key == key { + return p.Value + } + } + return "" +} + +// defaultVal returns val if non-empty, otherwise fallback. +// Registered as "default" in the template function map. +// NOTE: Use positional syntax only: [[ default (expr) "fallback" ]]. +// Pipeline syntax ([[ expr | default "fallback" ]]) would swap arguments +// because text/template pipes into the last parameter. +func defaultVal(val, fallback string) string { + if val == "" { + return fallback + } + return val +} + +// duckdbSQL maps a file path to a DuckDB read function call based on file extension. +// When defaultToJSON is true, unknown extensions default to read_json; otherwise select * from 'path'. +func duckdbSQL(path string, defaultToJSON bool) string { + switch { + case matchesExt(path, ".csv", ".tsv", ".txt"): + return fmt.Sprintf("select * from read_csv('%s', auto_detect=true, ignore_errors=1, header=true)", path) + case matchesExt(path, ".parquet"): + return fmt.Sprintf("select * from read_parquet('%s')", path) + case matchesExt(path, ".json", ".ndjson"): + return fmt.Sprintf("select * from read_json('%s', auto_detect=true, format='auto')", path) + default: + if defaultToJSON { + return fmt.Sprintf("select * from read_json('%s', auto_detect=true, format='auto')", path) + } + return fmt.Sprintf("select * from '%s'", path) + } +} + +// matchesExt checks if the file path has any of the target extensions. +// Handles compound extensions like .v1.parquet.gz by checking the basename +// for extension substrings, using suffix matching on path segments to avoid +// false positives (e.g. "parquet-archive/readme.txt" should NOT match ".parquet"). +func matchesExt(path string, targets ...string) bool { + ext := strings.ToLower(filepath.Ext(path)) + base := strings.ToLower(filepath.Base(path)) + for _, t := range targets { + if ext == t { + return true + } + // Check for compound extensions in the basename only (not the full path). + // Look for the target extension followed by a dot or end-of-string. + idx := strings.Index(base, t) + if idx > 0 { + after := idx + len(t) + if after == len(base) || base[after] == '.' { + return true + } + } + } + return false +} + +// s3ToHTTPS converts an s3:// URI to an HTTPS URL for ClickHouse's s3() function. +// "s3://bucket/key" becomes "https://bucket.s3.amazonaws.com/key". +// If the path is already HTTPS, it is returned as-is. +func s3ToHTTPS(path string) string { + if strings.HasPrefix(path, "https://") || strings.HasPrefix(path, "http://") { + return path + } + trimmed := strings.TrimPrefix(path, "s3://") + idx := strings.IndexByte(trimmed, '/') + if idx < 0 { + return fmt.Sprintf("https://%s.s3.amazonaws.com", trimmed) + } + bucket := trimmed[:idx] + key := trimmed[idx:] + return fmt.Sprintf("https://%s.s3.amazonaws.com%s", bucket, key) +} + +// gcsToHTTPS converts a gs:// URI to an HTTPS URL for ClickHouse's gcs() function. +// "gs://bucket/key" becomes "https://storage.googleapis.com/bucket/key". +// If the path is already HTTPS, it is returned as-is. +func gcsToHTTPS(path string) string { + if strings.HasPrefix(path, "https://") || strings.HasPrefix(path, "http://") { + return path + } + trimmed := strings.TrimPrefix(path, "gs://") + return fmt.Sprintf("https://storage.googleapis.com/%s", trimmed) +} + +// clickhouseURLSuffix generates additional arguments for ClickHouse's url() table function. +// When headers are present, returns ", Format, headers('K1'='V1', 'K2'='V2')" where +// Format is auto-detected from the URL extension. Returns empty string when no headers +// are present (ClickHouse auto-detects everything from the URL). +func clickhouseURLSuffix(path string, props any) string { + hdrs := extractClickhouseHeaders(props) + if hdrs == "" { + return "" + } + format := clickhouseFormat(path) + return fmt.Sprintf(",\n %s,\n %s\n ", format, hdrs) +} + +// clickhouseFormat maps a URL path to a ClickHouse input format name. +func clickhouseFormat(path string) string { + switch { + case matchesExt(path, ".csv", ".txt"): + return "CSVWithNames" + case matchesExt(path, ".tsv"): + return "TabSeparatedWithNames" + case matchesExt(path, ".json", ".ndjson", ".jsonl"): + return "JSONEachRow" + case matchesExt(path, ".parquet"): + return "Parquet" + default: + return "JSONEachRow" + } +} + +// extractClickhouseHeaders extracts header ProcessedProps and formats them +// for ClickHouse's headers() syntax: headers('Key1'='value1', 'Key2'='value2'). +// Returns empty string if no headers are present. +func extractClickhouseHeaders(props any) string { + ps, ok := props.([]ProcessedProp) + if !ok { + return "" + } + var headerProp *ProcessedProp + for i := range ps { + if ps[i].Key == "headers" { + headerProp = &ps[i] + break + } + } + if headerProp == nil { + return "" + } + + // Parse the YAML-style header lines (e.g. "Authorization: \"Bearer {{ .env.X }}\"") + var pairs []string + for _, line := range strings.Split(headerProp.Value, "\n") { + line = strings.TrimSpace(line) + if line == "" { + continue + } + idx := strings.IndexByte(line, ':') + if idx < 0 { + continue + } + key := strings.TrimSpace(line[:idx]) + val := strings.TrimSpace(line[idx+1:]) + val = strings.Trim(val, "\"") + pairs = append(pairs, fmt.Sprintf("'%s'='%s'", key, val)) + } + if len(pairs) == 0 { + return "" + } + return fmt.Sprintf("headers(%s)", strings.Join(pairs, ", ")) +} + +// azureContainer extracts the container name from an Azure URI. +// Supports both "azure://container/blob/path" and "https://account.blob.core.windows.net/container/blob/path". +func azureContainer(path string) string { + path = stripAzurePrefix(path) + idx := strings.IndexByte(path, '/') + if idx < 0 { + return path + } + return path[:idx] +} + +// azureBlobPath extracts the blob path from an Azure URI. +// Supports both "azure://container/blob/path" and "https://account.blob.core.windows.net/container/blob/path". +func azureBlobPath(path string) string { + path = stripAzurePrefix(path) + idx := strings.IndexByte(path, '/') + if idx < 0 { + return "" + } + return path[idx+1:] +} + +// azureEndpoint returns the blob service endpoint for a given Azure URI. +// For "https://account.blob.core.windows.net/..." it returns "https://account.blob.core.windows.net". +// For "azure://..." it builds the endpoint from the account property. +func azureEndpoint(path, account string) string { + if strings.HasPrefix(path, "https://") || strings.HasPrefix(path, "http://") { + u := strings.TrimPrefix(path, "https://") + u = strings.TrimPrefix(u, "http://") + idx := strings.IndexByte(u, '/') + if idx > 0 { + return "https://" + u[:idx] + } + return "https://" + u + } + return fmt.Sprintf("https://%s.blob.core.windows.net", account) +} + +// stripAzurePrefix strips the scheme and host from an Azure URI, returning "container/blob/path". +// Handles "azure://container/path" and "https://account.blob.core.windows.net/container/path". +func stripAzurePrefix(path string) string { + if strings.HasPrefix(path, "azure://") { + return strings.TrimPrefix(path, "azure://") + } + // HTTPS: strip scheme + host, leaving "/container/path" + if strings.HasPrefix(path, "https://") || strings.HasPrefix(path, "http://") { + noScheme := strings.TrimPrefix(path, "https://") + noScheme = strings.TrimPrefix(noScheme, "http://") + idx := strings.IndexByte(noScheme, '/') + if idx >= 0 { + return noScheme[idx+1:] + } + return "" + } + return path +} diff --git a/runtime/templates/headers.go b/runtime/templates/headers.go new file mode 100644 index 00000000000..3764b13fa7a --- /dev/null +++ b/runtime/templates/headers.go @@ -0,0 +1,52 @@ +package templates + +import ( + "fmt" + "regexp" + "strings" +) + +// sensitiveHeaderPattern matches header keys that carry secret values. +var sensitiveHeaderPattern = regexp.MustCompile( + `(?i)^(authorization|x-api-key|api-key|token|x-token|x-auth|x-secret|proxy-authorization)$`, +) + +// headerKeyCleanupPattern sanitizes a header key into a valid .env variable segment. +// Compiled at package level to avoid per-call regex compilation. +var headerKeyCleanupPattern = regexp.MustCompile(`[^a-z0-9]+`) + +// IsSensitiveHeaderKey returns true when a header key likely carries a secret value. +func IsSensitiveHeaderKey(key string) bool { + return sensitiveHeaderPattern.MatchString(strings.TrimSpace(key)) +} + +// AuthSchemePrefixes are common HTTP authentication scheme prefixes. +// When a sensitive header value starts with one of these (case-insensitive), +// only the token portion is stored in .env. +var AuthSchemePrefixes = []string{"Bearer ", "Basic ", "Token ", "Bot "} + +// SplitAuthSchemePrefix splits a value into scheme prefix and secret if it starts +// with a known auth scheme. Returns ("", "", false) when no prefix matches. +func SplitAuthSchemePrefix(value string) (scheme, secret string, ok bool) { + for _, prefix := range AuthSchemePrefixes { + if len(value) > len(prefix) && strings.EqualFold(value[:len(prefix)], prefix) { + return value[:len(prefix)], value[len(prefix):], true + } + } + return "", "", false +} + +// HeaderKeyToEnvSegment sanitizes a header key into a valid .env variable segment. +func HeaderKeyToEnvSegment(key string) string { + return headerKeyCleanupPattern.ReplaceAllString(strings.ToLower(key), "_") +} + +// ResolveHeaderEnvVarName determines the env var name for a header, resolving conflicts. +func ResolveHeaderEnvVarName(connectorName, segment string, existingEnv map[string]bool) string { + base := fmt.Sprintf("connector.%s.%s", connectorName, segment) + candidate := base + for i := 1; existingEnv[candidate]; i++ { + candidate = fmt.Sprintf("%s_%d", base, i) + } + return candidate +} diff --git a/runtime/templates/headers_test.go b/runtime/templates/headers_test.go new file mode 100644 index 00000000000..be0dc08d31b --- /dev/null +++ b/runtime/templates/headers_test.go @@ -0,0 +1,56 @@ +package templates + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestIsSensitiveHeaderKey(t *testing.T) { + sensitive := []string{"Authorization", "X-API-Key", "API-Key", "Token", "X-Token", "X-Auth", "X-Secret", "Proxy-Authorization"} + for _, key := range sensitive { + require.True(t, IsSensitiveHeaderKey(key), "expected %q to be sensitive", key) + } + + notSensitive := []string{"Content-Type", "Accept", "X-Request-ID", "User-Agent"} + for _, key := range notSensitive { + require.False(t, IsSensitiveHeaderKey(key), "expected %q to not be sensitive", key) + } +} + +func TestSplitAuthSchemePrefix(t *testing.T) { + scheme, secret, ok := SplitAuthSchemePrefix("Bearer my-token-123") + require.True(t, ok) + require.Equal(t, "Bearer ", scheme) + require.Equal(t, "my-token-123", secret) + + scheme, secret, ok = SplitAuthSchemePrefix("Basic dXNlcjpwYXNz") + require.True(t, ok) + require.Equal(t, "Basic ", scheme) + require.Equal(t, "dXNlcjpwYXNz", secret) + + // No prefix + _, _, ok = SplitAuthSchemePrefix("plain-token") + require.False(t, ok) + + // Prefix only (no token part) + _, _, ok = SplitAuthSchemePrefix("Bearer") + require.False(t, ok) +} + +func TestHeaderKeyToEnvSegment(t *testing.T) { + require.Equal(t, "x_api_key", HeaderKeyToEnvSegment("X-API-Key")) + require.Equal(t, "authorization", HeaderKeyToEnvSegment("Authorization")) + require.Equal(t, "content_type", HeaderKeyToEnvSegment("Content-Type")) +} + +func TestResolveHeaderEnvVarName(t *testing.T) { + existing := make(map[string]bool) + name := ResolveHeaderEnvVarName("my_conn", "authorization", existing) + require.Equal(t, "connector.my_conn.authorization", name) + + // Conflict + existing[name] = true + name2 := ResolveHeaderEnvVarName("my_conn", "authorization", existing) + require.Equal(t, "connector.my_conn.authorization_1", name2) +} diff --git a/runtime/templates/registry.go b/runtime/templates/registry.go new file mode 100644 index 00000000000..190f5039fb3 --- /dev/null +++ b/runtime/templates/registry.go @@ -0,0 +1,225 @@ +package templates + +import ( + "bytes" + "embed" + "encoding/json" + "fmt" + "io/fs" + "path" + "sort" + "strings" +) + +//go:embed definitions +var definitionsFS embed.FS + +// Registry holds all loaded template definitions. +type Registry struct { + templates map[string]*Template + sorted []*Template // sorted by name for stable List() output +} + +// NewRegistry loads all embedded template definitions from the definitions/ directory tree. +func NewRegistry() (*Registry, error) { + r := &Registry{ + templates: make(map[string]*Template), + } + + err := fs.WalkDir(definitionsFS, "definitions", func(fpath string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + if d.IsDir() || !strings.HasSuffix(d.Name(), ".json") { + return nil + } + + data, err := definitionsFS.ReadFile(fpath) + if err != nil { + return fmt.Errorf("reading template %s: %w", fpath, err) + } + + // Skip stub files (placeholders for future implementation); + // these may be empty or contain only a "_reason" field. + if len(bytes.TrimSpace(data)) == 0 { + return nil + } + + var t Template + if err := json.Unmarshal(data, &t); err != nil { + return fmt.Errorf("parsing template %s: %w", fpath, err) + } + + if t.Name == "" { + // Stub file with metadata (e.g. _reason) but no template definition; skip it + return nil + } + + if _, exists := r.templates[t.Name]; exists { + return fmt.Errorf("duplicate template name %q in %s", t.Name, fpath) + } + + // Resolve code_template_file references + dir := path.Dir(fpath) + for i := range t.Files { + if t.Files[i].CodeTemplateFile == "" { + continue + } + tmplPath := dir + "/" + t.Files[i].CodeTemplateFile + content, err := definitionsFS.ReadFile(tmplPath) + if err != nil { + return fmt.Errorf("reading code template file %s for %s: %w", tmplPath, fpath, err) + } + t.Files[i].CodeTemplate = string(content) + } + + // Preserve JSON-defined property order (Go maps lose insertion order). + // Store on struct for backend use, and in the schema as []any for + // protobuf Struct conversion ([]string is not protobuf-compatible). + if t.JSONSchema != nil { + t.PropertyOrder = extractPropertyOrder(data) + if len(t.PropertyOrder) > 0 { + orderAny := make([]any, len(t.PropertyOrder)) + for i, k := range t.PropertyOrder { + orderAny[i] = k + } + t.JSONSchema["x-property-order"] = orderAny + } + } + + r.templates[t.Name] = &t + return nil + }) + if err != nil { + return nil, fmt.Errorf("loading template definitions: %w", err) + } + + // Build sorted list + r.sorted = make([]*Template, 0, len(r.templates)) + for _, t := range r.templates { + r.sorted = append(r.sorted, t) + } + sort.Slice(r.sorted, func(i, j int) bool { + return r.sorted[i].Name < r.sorted[j].Name + }) + + return r, nil +} + +// List returns all templates sorted by name. +func (r *Registry) List() []*Template { + return r.sorted +} + +// ListByTags returns templates that match ALL of the given tags. +// If tags is empty, returns all templates. +func (r *Registry) ListByTags(tags []string) []*Template { + if len(tags) == 0 { + return r.sorted + } + + var result []*Template + for _, t := range r.sorted { + if matchesAllTags(t.Tags, tags) { + result = append(result, t) + } + } + return result +} + +// Get returns a template by name, or nil and false if not found. +func (r *Registry) Get(name string) (*Template, bool) { + t, ok := r.templates[name] + return t, ok +} + +// LookupByDriver finds the template for a given driver and output type. +// This is used by the backward-compatible GenerateTemplate RPC to map +// (driver, resource_type) pairs to template names. +func (r *Registry) LookupByDriver(driver, resourceType string) (*Template, bool) { + switch resourceType { + case "connector": + // Combined templates (e.g. s3-duckdb) contain both connector and model files. + // Check for a combined template first; fall back to standalone connector template. + if t, ok := r.Get(driver + "-duckdb"); ok && hasFileNamed(t, "connector") { + return t, true + } + return r.Get(driver) + case "model": + // Model templates use the pattern driver-{olap} (e.g. s3-duckdb, s3-clickhouse). + // LookupByDriver defaults to DuckDB; for other OLAPs use Get() directly. + return r.Get(driver + "-duckdb") + } + return nil, false +} + +// hasFileNamed returns true if the template has a file entry with the given name. +func hasFileNamed(t *Template, name string) bool { + for _, f := range t.Files { + if f.Name == name { + return true + } + } + return false +} + +// extractPropertyOrder parses raw JSON bytes to extract the key ordering of +// json_schema.properties. Go's map[string]any loses insertion order on unmarshal, +// but json.Decoder preserves it. +func extractPropertyOrder(raw []byte) []string { + var outer struct { + JSONSchema json.RawMessage `json:"json_schema"` + } + if err := json.Unmarshal(raw, &outer); err != nil || outer.JSONSchema == nil { + return nil + } + + var schema struct { + Properties json.RawMessage `json:"properties"` + } + if err := json.Unmarshal(outer.JSONSchema, &schema); err != nil || schema.Properties == nil { + return nil + } + + dec := json.NewDecoder(bytes.NewReader(schema.Properties)) + tok, err := dec.Token() // opening { + if err != nil { + return nil + } + if delim, ok := tok.(json.Delim); !ok || delim != '{' { + return nil + } + + var keys []string + for dec.More() { + tok, err := dec.Token() + if err != nil { + break + } + key, ok := tok.(string) + if !ok { + break + } + keys = append(keys, key) + // Skip the property value object + var discard json.RawMessage + if err := dec.Decode(&discard); err != nil { + break + } + } + return keys +} + +// matchesAllTags returns true if the template's tags contain all of the required tags. +func matchesAllTags(templateTags, requiredTags []string) bool { + tagSet := make(map[string]bool, len(templateTags)) + for _, t := range templateTags { + tagSet[t] = true + } + for _, req := range requiredTags { + if !tagSet[req] { + return false + } + } + return true +} diff --git a/runtime/templates/registry_test.go b/runtime/templates/registry_test.go new file mode 100644 index 00000000000..7febf6eb447 --- /dev/null +++ b/runtime/templates/registry_test.go @@ -0,0 +1,157 @@ +package templates + +import ( + "testing" + + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/types/known/structpb" +) + +func TestNewRegistry(t *testing.T) { + r, err := NewRegistry() + require.NoError(t, err) + require.NotNil(t, r) + + // Verify all definitions loaded + all := r.List() + require.Greater(t, len(all), 20, "expected at least 20 template definitions") +} + +func TestRegistryGet(t *testing.T) { + r, err := NewRegistry() + require.NoError(t, err) + + // Known templates exist + for _, name := range []string{"duckdb", "s3-duckdb", "gcs-duckdb", "iceberg-duckdb", "snowflake-duckdb"} { + t.Run(name, func(t *testing.T) { + tmpl, ok := r.Get(name) + require.True(t, ok, "template %q should exist", name) + require.Equal(t, name, tmpl.Name) + require.NotEmpty(t, tmpl.DisplayName) + require.NotEmpty(t, tmpl.Files) + }) + } + + // Unknown template doesn't exist + _, ok := r.Get("nonexistent") + require.False(t, ok) +} + +func TestRegistryListByTags(t *testing.T) { + r, err := NewRegistry() + require.NoError(t, err) + + // Filter by "duckdb" should return DuckDB-related templates + duckdbTemplates := r.ListByTags([]string{"duckdb"}) + require.Greater(t, len(duckdbTemplates), 5, "expected several duckdb-tagged templates") + for _, tmpl := range duckdbTemplates { + require.Contains(t, tmpl.Tags, "duckdb") + } + + // Filter by "olap" + "connector" should return OLAP connector templates + olapConnectors := r.ListByTags([]string{"olap", "connector"}) + require.Greater(t, len(olapConnectors), 0) + for _, tmpl := range olapConnectors { + require.Contains(t, tmpl.Tags, "olap") + require.Contains(t, tmpl.Tags, "connector") + } + + // Empty tags returns all templates + allTemplates := r.ListByTags(nil) + require.Equal(t, len(r.List()), len(allTemplates)) +} + +func TestRegistryLookupByDriver(t *testing.T) { + r, err := NewRegistry() + require.NoError(t, err) + + // Connector lookup: combined templates (s3-duckdb has connector file) + tmpl, ok := r.LookupByDriver("s3", "connector") + require.True(t, ok) + require.Equal(t, "s3-duckdb", tmpl.Name) + + // Model lookup for object stores: driver-duckdb + tmpl, ok = r.LookupByDriver("s3", "model") + require.True(t, ok) + require.Equal(t, "s3-duckdb", tmpl.Name) + + // Model lookup for warehouses: driver-duckdb + tmpl, ok = r.LookupByDriver("snowflake", "model") + require.True(t, ok) + require.Equal(t, "snowflake-duckdb", tmpl.Name) +} + +func TestRegistryTemplatesSorted(t *testing.T) { + r, err := NewRegistry() + require.NoError(t, err) + + all := r.List() + for i := 1; i < len(all); i++ { + require.Less(t, all[i-1].Name, all[i].Name, "templates should be sorted by name") + } +} + +func TestRegistryAllDefinitionsValid(t *testing.T) { + r, err := NewRegistry() + require.NoError(t, err) + + for _, tmpl := range r.List() { + t.Run(tmpl.Name, func(t *testing.T) { + require.NotEmpty(t, tmpl.Name) + require.NotEmpty(t, tmpl.DisplayName) + require.NotEmpty(t, tmpl.Tags) + require.NotEmpty(t, tmpl.Files) + + for _, f := range tmpl.Files { + require.NotEmpty(t, f.Name, "file name required for template %s", tmpl.Name) + require.NotEmpty(t, f.PathTemplate, "path template required for template %s file %s", tmpl.Name, f.Name) + require.NotEmpty(t, f.CodeTemplate, "code template required for template %s file %s", tmpl.Name, f.Name) + require.Contains(t, []string{"connector", "model"}, f.Name, "file name must be connector or model for template %s", tmpl.Name) + } + }) + } +} + +func TestRegistryTemplatesWithJSONSchemaValid(t *testing.T) { + r, err := NewRegistry() + require.NoError(t, err) + + var found int + for _, tmpl := range r.List() { + if tmpl.JSONSchema == nil { + continue + } + found++ + t.Run(tmpl.Name, func(t *testing.T) { + // Schema must be an object type + typ, ok := tmpl.JSONSchema["type"] + require.True(t, ok, "json_schema must have a type field") + require.Equal(t, "object", typ) + + // Schema must have properties + propsRaw, ok := tmpl.JSONSchema["properties"] + require.True(t, ok, "json_schema must have properties") + propsMap, ok := propsRaw.(map[string]any) + require.True(t, ok, "properties must be a map") + require.Greater(t, len(propsMap), 0, "properties must not be empty") + + // Each property with x-secret must have x-env-var + for key, propRaw := range propsMap { + prop, ok := propRaw.(map[string]any) + if !ok { + continue + } + if secret, _ := prop["x-secret"].(bool); secret { + envVar, hasEnvVar := prop["x-env-var"] + require.True(t, hasEnvVar, "property %q has x-secret but no x-env-var", key) + require.NotEmpty(t, envVar, "x-env-var for %q must not be empty", key) + } + } + + // Verify structpb conversion works (catches int vs float64 issues) + _, err := structpb.NewStruct(tmpl.JSONSchema) + require.NoError(t, err, "json_schema for %q must be convertible to protobuf Struct", tmpl.Name) + }) + } + require.Greater(t, found, 0, "expected at least one template with json_schema") +} diff --git a/runtime/templates/render.go b/runtime/templates/render.go new file mode 100644 index 00000000000..dfc15ad06ca --- /dev/null +++ b/runtime/templates/render.go @@ -0,0 +1,389 @@ +package templates + +import ( + "bytes" + "fmt" + "sort" + "strings" + "text/template" +) + +// RenderInput contains all parameters for rendering a template. +type RenderInput struct { + Template *Template + Output string // "connector", "model", or "" for all files + Properties map[string]any // raw form values + ConnectorName string // for model outputs: the connector to reference + ExistingEnv map[string]bool +} + +// RenderOutput contains the result of rendering. +type RenderOutput struct { + Files []RenderedFile + EnvVars map[string]string +} + +// RenderedFile is a single rendered output file. +type RenderedFile struct { + Path string + Blob string +} + +// Render executes a template with the given input, producing rendered files and env vars. +// The rendering pipeline: +// 1. Pre-processes properties (secret extraction, empty filtering, derived fields) +// 2. Builds a template data map +// 3. Renders each matching file's path and code templates +func Render(input *RenderInput) (*RenderOutput, error) { + if input.Template == nil { + return nil, fmt.Errorf("template is nil") + } + + envVars := make(map[string]string) + existingEnv := cloneEnvMap(input.ExistingEnv) + + // Build the template data context + data := buildTemplateData(input, existingEnv, envVars) + + // Render each matching file + var files []RenderedFile + for _, f := range input.Template.Files { + if input.Output != "" && f.Name != input.Output { + continue + } + + path, err := renderString(f.Name+"_path", f.PathTemplate, data) + if err != nil { + return nil, fmt.Errorf("rendering path template for %q: %w", f.Name, err) + } + + blob, err := renderString(f.Name+"_code", f.CodeTemplate, data) + if err != nil { + return nil, fmt.Errorf("rendering code template for %q: %w", f.Name, err) + } + + files = append(files, RenderedFile{ + Path: strings.TrimSpace(path), + Blob: blob, + }) + } + + return &RenderOutput{Files: files, EnvVars: envVars}, nil +} + +// buildTemplateData creates the data map passed to Go templates. +// It pre-processes properties: extracts secrets, filters empties, adds derived fields. +func buildTemplateData(input *RenderInput, existingEnv map[string]bool, envVars map[string]string) map[string]any { + data := make(map[string]any) + + // Basic fields + data["driver"] = input.Template.Driver + data["connector_name"] = input.ConnectorName + data["docs_url"] = input.Template.DocsURL + + // Derive model_name from the "name" property if present + if name, ok := input.Properties["name"]; ok && !isEmpty(name) { + data["model_name"] = fmt.Sprintf("%v", name) + } + + // Pre-populate schema properties: use "default" if defined, otherwise empty string. + // This ensures templates render cleanly and conditional branches (e.g. auth_method) + // work correctly even when the frontend omits optional UI-only fields. + if input.Template.JSONSchema != nil { + for k, prop := range schemaProperties(input.Template.JSONSchema) { + if def := schemaFieldString(prop, "default"); def != "" { + data[k] = def + } else { + data[k] = "" + } + } + } + + // Copy all raw properties into data (overwrites empty defaults above) + for k, v := range input.Properties { + if !isEmpty(v) { + data[k] = fmt.Sprintf("%v", v) + } + } + + // Schema-based path: extract property metadata from JSON Schema + if input.Template.JSONSchema != nil { + allProps := processPropertiesFromSchema( + input.Template.JSONSchema, + input.Template.PropertyOrder, + input.Template.Driver, + input.Properties, + existingEnv, + envVars, + ) + + // Split by x-step so connector and model files get the right properties + configProps, sourceProps := splitPropsByStep(allProps, input.Template.JSONSchema) + data["props"] = configProps + data["config_props"] = configProps + data["source_props"] = sourceProps + + return data + } + + // Template without schema: pass properties as-is + return data +} + +// processPropertiesFromSchema pre-processes properties using JSON Schema metadata. +// Fields with "x-secret": true are extracted to env vars; "x-ui-only": true fields are skipped. +// Quoting is determined by the schema "type" field (number/boolean unquoted; everything else quoted). +func processPropertiesFromSchema( + schema map[string]any, + propertyOrder []string, + driverName string, + rawProps map[string]any, + existingEnv map[string]bool, + envVars map[string]string, +) []ProcessedProp { + propsMap := schemaProperties(schema) + if len(propsMap) == 0 { + return nil + } + + // Use schema-defined property order if available (preserves JSON key ordering); + // fall back to alphabetical for deterministic output. + keys := propertyOrder + if len(keys) == 0 { + keys = make([]string, 0, len(propsMap)) + for k := range propsMap { + keys = append(keys, k) + } + sort.Strings(keys) + } + + var result []ProcessedProp + for _, key := range keys { + prop := propsMap[key] + + // Skip UI-only fields (e.g. auth_method radio buttons) + if schemaFieldBool(prop, "x-ui-only") { + continue + } + + val, ok := rawProps[key] + if !ok || isEmpty(val) { + continue + } + + // Skip properties whose value matches the schema default when x-omit-if-default is set. + // For example, ClickHouse's "managed" defaults to false; rendering "managed: false" + // is unnecessary noise, but "managed: true" (rill-managed) must appear. + if schemaFieldBool(prop, "x-omit-if-default") { + if defVal, hasDefault := prop["default"]; hasDefault && fmt.Sprint(val) == fmt.Sprint(defVal) { + continue + } + } + + // Handle map-typed properties (e.g. headers). + // The frontend key-value editor sends [{key, value}, ...]; convert to a flat map. + mapVal, isMap := val.(map[string]any) + if !isMap { + if arrVal, isArr := val.([]any); isArr { + mapVal = kvArrayToMap(arrVal) + if mapVal == nil { + // Empty or malformed array (e.g. []); skip to avoid rendering "[]" + continue + } + isMap = true + } + } + if isMap { + headerIdent := driverName + headerProps := processHeaders(mapVal, headerIdent, existingEnv, envVars) + result = append(result, headerProps...) + continue + } + + strVal := fmt.Sprintf("%v", val) + + if schemaFieldBool(prop, "x-secret") { + envName := ResolveEnvVarNameForKey(driverName, key, schemaFieldString(prop, "x-env-var"), existingEnv) + existingEnv[envName] = true + envVars[envName] = strVal + result = append(result, ProcessedProp{ + Key: key, + Value: fmt.Sprintf("{{ .env.%s }}", envName), + Quoted: true, + }) + } else { + propType := schemaFieldString(prop, "type") + quoted := propType != "number" && propType != "boolean" + result = append(result, ProcessedProp{ + Key: key, + Value: strVal, + Quoted: quoted, + }) + } + } + return result +} + +// splitPropsByStep separates processed props into connector-step and source-step slices +// based on the x-step field in the JSON Schema. Props without x-step go into both. +func splitPropsByStep(props []ProcessedProp, schema map[string]any) (configProps, sourceProps []ProcessedProp) { + propsMap := schemaProperties(schema) + for _, p := range props { + step := "" + if propSchema, ok := propsMap[p.Key]; ok { + step = schemaFieldString(propSchema, "x-step") + } + switch step { + case "connector": + configProps = append(configProps, p) + case "source": + sourceProps = append(sourceProps, p) + case "explorer": + // Explorer-step props are accessed directly as template variables (e.g. .sql, .name); + // they are excluded from renderProps output to avoid duplication. + default: + configProps = append(configProps, p) + sourceProps = append(sourceProps, p) + } + } + return +} + +// kvArrayToMap converts [{key: "k", value: "v"}, ...] (from the frontend key-value editor) +// to map[string]any{"k": "v", ...}. Returns nil if the array is empty or not in the expected format. +func kvArrayToMap(arr []any) map[string]any { + result := make(map[string]any, len(arr)) + for _, item := range arr { + obj, ok := item.(map[string]any) + if !ok { + return nil + } + k, _ := obj["key"].(string) + v, _ := obj["value"].(string) + if k != "" { + result[k] = v + } + } + if len(result) == 0 { + return nil + } + return result +} + +// schemaProperties extracts the "properties" map from a JSON Schema object. +func schemaProperties(schema map[string]any) map[string]map[string]any { + raw, ok := schema["properties"] + if !ok { + return nil + } + outer, ok := raw.(map[string]any) + if !ok { + return nil + } + result := make(map[string]map[string]any, len(outer)) + for k, v := range outer { + if prop, ok := v.(map[string]any); ok { + result[k] = prop + } + } + return result +} + +// schemaFieldBool returns the bool value of a field in a schema property map. +func schemaFieldBool(prop map[string]any, key string) bool { + v, _ := prop[key].(bool) + return v +} + +// schemaFieldString returns the string value of a field in a schema property map. +func schemaFieldString(prop map[string]any, key string) string { + v, _ := prop[key].(string) + return v +} + +// processHeaders processes a map of header key-value pairs, extracting sensitive values. +func processHeaders(headers map[string]any, connectorName string, existingEnv map[string]bool, envVars map[string]string) []ProcessedProp { + if len(headers) == 0 { + return nil + } + + // Sort keys for deterministic output + keys := make([]string, 0, len(headers)) + for k := range headers { + keys = append(keys, k) + } + sort.Strings(keys) + + // Build a single "headers" prop whose value is a YAML mapping + var headerLines []string + for _, key := range keys { + strVal := fmt.Sprintf("%v", headers[key]) + if IsSensitiveHeaderKey(key) { + envSegment := HeaderKeyToEnvSegment(key) + envName := ResolveHeaderEnvVarName(connectorName, envSegment, existingEnv) + existingEnv[envName] = true + if scheme, secret, ok := SplitAuthSchemePrefix(strVal); ok { + envVars[envName] = secret + headerLines = append(headerLines, fmt.Sprintf(" %s: \"%s{{ .env.%s }}\"", key, scheme, envName)) + } else { + envVars[envName] = strVal + headerLines = append(headerLines, fmt.Sprintf(" %s: \"{{ .env.%s }}\"", key, envName)) + } + } else { + headerLines = append(headerLines, fmt.Sprintf(" %s: %q", key, strVal)) + } + } + + // Return as a single rendered block (the template will output it as-is) + return []ProcessedProp{{ + Key: "headers", + Value: "\n" + strings.Join(headerLines, "\n"), + Quoted: false, // The value is a nested YAML mapping, not a scalar + }} +} + +// renderString renders a Go template string using [[ ]] delimiters. +func renderString(name, tmplText string, data map[string]any) (string, error) { + t, err := template.New(name). + Delims("[[", "]]"). + Funcs(sharedFuncMap). + Parse(tmplText) + if err != nil { + return "", fmt.Errorf("parsing template: %w", err) + } + + var buf bytes.Buffer + if err := t.Execute(&buf, data); err != nil { + return "", fmt.Errorf("executing template: %w", err) + } + return buf.String(), nil +} + +// isEmpty checks if a value is empty (nil, empty string, or empty map). +func isEmpty(v any) bool { + if v == nil { + return true + } + switch val := v.(type) { + case string: + return val == "" + case bool: + return false // bools are never "empty" + case map[string]any: + return len(val) == 0 + default: + return fmt.Sprintf("%v", v) == "" + } +} + +// cloneEnvMap creates a shallow copy of an env key map. +func cloneEnvMap(m map[string]bool) map[string]bool { + if m == nil { + return make(map[string]bool) + } + clone := make(map[string]bool, len(m)) + for k, v := range m { + clone[k] = v + } + return clone +} diff --git a/runtime/templates/render_test.go b/runtime/templates/render_test.go new file mode 100644 index 00000000000..f8da8132869 --- /dev/null +++ b/runtime/templates/render_test.go @@ -0,0 +1,478 @@ +package templates + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestRenderConnectorTemplate(t *testing.T) { + registry, err := NewRegistry() + require.NoError(t, err) + + // s3-duckdb is a combined template with both connector and model files + tmpl, ok := registry.Get("s3-duckdb") + require.True(t, ok) + + result, err := Render(&RenderInput{ + Template: tmpl, + Output: "connector", + Properties: map[string]any{ + "aws_access_key_id": "AKIAIOSFODNN7EXAMPLE", + "aws_secret_access_key": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "region": "us-east-1", + }, + ConnectorName: "my_s3", + ExistingEnv: make(map[string]bool), + }) + require.NoError(t, err) + require.Len(t, result.Files, 1) + + blob := result.Files[0].Blob + require.Contains(t, blob, "type: connector") + require.Contains(t, blob, "driver: s3") + require.Contains(t, blob, `aws_access_key_id: "{{ .env.AWS_ACCESS_KEY_ID }}"`) + require.Contains(t, blob, `aws_secret_access_key: "{{ .env.AWS_SECRET_ACCESS_KEY }}"`) + require.Contains(t, blob, `region: "us-east-1"`) + require.NotContains(t, blob, "AKIAIOSFODNN7EXAMPLE") + + // Connector output should NOT contain source-step properties + require.NotContains(t, blob, "path") + require.NotContains(t, blob, "name") + + // Verify env vars extracted + require.Equal(t, "AKIAIOSFODNN7EXAMPLE", result.EnvVars["AWS_ACCESS_KEY_ID"]) + require.Equal(t, "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", result.EnvVars["AWS_SECRET_ACCESS_KEY"]) + + // Verify path + require.Equal(t, "connectors/my_s3.yaml", result.Files[0].Path) +} + +func TestRenderDuckDBModelTemplate(t *testing.T) { + registry, err := NewRegistry() + require.NoError(t, err) + + tmpl, ok := registry.Get("s3-duckdb") + require.True(t, ok) + + result, err := Render(&RenderInput{ + Template: tmpl, + Output: "model", + Properties: map[string]any{ + "path": "s3://my-bucket/data/*.parquet", + "name": "my_model", + }, + ConnectorName: "my_s3_connector", + ExistingEnv: make(map[string]bool), + }) + require.NoError(t, err) + require.Len(t, result.Files, 1) + + blob := result.Files[0].Blob + require.Contains(t, blob, "type: model") + require.Contains(t, blob, "connector: duckdb") + require.Contains(t, blob, `create_secrets_from_connectors: "my_s3_connector"`) + require.Contains(t, blob, "read_parquet") + require.Contains(t, blob, "s3://my-bucket/data/*.parquet") + + // Verify path uses model_name from "name" property + require.Equal(t, "models/my_model.yaml", result.Files[0].Path) +} + +func TestRenderWarehouseModelTemplate(t *testing.T) { + registry, err := NewRegistry() + require.NoError(t, err) + + tmpl, ok := registry.Get("snowflake-duckdb") + require.True(t, ok) + + result, err := Render(&RenderInput{ + Template: tmpl, + Output: "model", + Properties: map[string]any{ + "sql": "SELECT * FROM my_table", + "name": "snowflake_data", + }, + ConnectorName: "my_snowflake", + ExistingEnv: make(map[string]bool), + }) + require.NoError(t, err) + require.Len(t, result.Files, 1) + + blob := result.Files[0].Blob + require.Contains(t, blob, "type: model") + require.Contains(t, blob, `connector: "my_snowflake"`) + require.Contains(t, blob, "materialize: true") + require.Contains(t, blob, "SELECT * FROM my_table") + require.Contains(t, blob, "SELECT * FROM my_table limit 10000") + + require.Equal(t, "models/snowflake_data.yaml", result.Files[0].Path) +} + +func TestRenderRedshiftModelNoDevSection(t *testing.T) { + registry, err := NewRegistry() + require.NoError(t, err) + + tmpl, ok := registry.Get("redshift-duckdb") + require.True(t, ok) + + result, err := Render(&RenderInput{ + Template: tmpl, + Output: "model", + Properties: map[string]any{ + "sql": "SELECT * FROM my_table", + "name": "rs_data", + }, + ConnectorName: "my_redshift", + ExistingEnv: make(map[string]bool), + }) + require.NoError(t, err) + require.Len(t, result.Files, 1) + + blob := result.Files[0].Blob + require.Contains(t, blob, "type: model") + require.Contains(t, blob, `connector: "my_redshift"`) + // Redshift template should NOT have a dev section + require.NotContains(t, blob, "dev:") + require.NotContains(t, blob, `ref "self"`) +} + +func TestRenderIcebergDuckDB(t *testing.T) { + registry, err := NewRegistry() + require.NoError(t, err) + + tmpl, ok := registry.Get("iceberg-duckdb") + require.True(t, ok) + + result, err := Render(&RenderInput{ + Template: tmpl, + Output: "model", + Properties: map[string]any{ + "path": "s3://my-iceberg-bucket/warehouse/my_table", + "name": "iceberg_data", + }, + ExistingEnv: make(map[string]bool), + }) + require.NoError(t, err) + require.Len(t, result.Files, 1) + + blob := result.Files[0].Blob + require.Contains(t, blob, "type: model") + require.Contains(t, blob, "iceberg_scan") + require.Contains(t, blob, "s3://my-iceberg-bucket/warehouse/my_table") + + require.Equal(t, "models/iceberg_data.yaml", result.Files[0].Path) +} + +func TestRenderEnvVarConflict(t *testing.T) { + registry, err := NewRegistry() + require.NoError(t, err) + + // s3-duckdb is a combined template with json_schema + tmpl, ok := registry.Get("s3-duckdb") + require.True(t, ok) + + // Pre-populate existing env to force conflict + existingEnv := map[string]bool{ + "AWS_ACCESS_KEY_ID": true, + "AWS_SECRET_ACCESS_KEY": true, + } + + result, err := Render(&RenderInput{ + Template: tmpl, + Output: "connector", + Properties: map[string]any{ + "aws_access_key_id": "AKIA_NEW", + "aws_secret_access_key": "SECRET_NEW", + }, + ConnectorName: "s3_2", + ExistingEnv: existingEnv, + }) + require.NoError(t, err) + + // Env vars should have _1 suffix due to conflict + require.Contains(t, result.EnvVars, "AWS_ACCESS_KEY_ID_1") + require.Contains(t, result.EnvVars, "AWS_SECRET_ACCESS_KEY_1") + require.Contains(t, result.Files[0].Blob, "AWS_ACCESS_KEY_ID_1") +} + +func TestRenderOutputFilter(t *testing.T) { + // Create a two-file template inline for testing + tmpl := &Template{ + Name: "test-multi", + DisplayName: "Test Multi-file", + Tags: []string{"test"}, + Files: []File{ + { + Name: "connector", + PathTemplate: "connectors/[[ .connector_name ]].yaml", + CodeTemplate: "type: connector\ndriver: test\n", + }, + { + Name: "model", + PathTemplate: "models/[[ .model_name ]].yaml", + CodeTemplate: "type: model\nconnector: duckdb\n", + }, + }, + } + + // All files + result, err := Render(&RenderInput{ + Template: tmpl, + Output: "", + Properties: map[string]any{"name": "test"}, + ConnectorName: "test_conn", + ExistingEnv: make(map[string]bool), + }) + require.NoError(t, err) + require.Len(t, result.Files, 2) + + // Connector only + result, err = Render(&RenderInput{ + Template: tmpl, + Output: "connector", + Properties: map[string]any{"name": "test"}, + ConnectorName: "test_conn", + ExistingEnv: make(map[string]bool), + }) + require.NoError(t, err) + require.Len(t, result.Files, 1) + require.Contains(t, result.Files[0].Blob, "type: connector") + + // Model only + result, err = Render(&RenderInput{ + Template: tmpl, + Output: "model", + Properties: map[string]any{"name": "test"}, + ConnectorName: "test_conn", + ExistingEnv: make(map[string]bool), + }) + require.NoError(t, err) + require.Len(t, result.Files, 1) + require.Contains(t, result.Files[0].Blob, "type: model") +} + +func TestRenderLocalFileDuckDB(t *testing.T) { + registry, err := NewRegistry() + require.NoError(t, err) + + tmpl, ok := registry.Get("local_file-duckdb") + require.True(t, ok) + + result, err := Render(&RenderInput{ + Template: tmpl, + Output: "model", + Properties: map[string]any{ + "path": "data/sales.csv", + "name": "sales", + }, + ExistingEnv: make(map[string]bool), + }) + require.NoError(t, err) + require.Len(t, result.Files, 1) + + blob := result.Files[0].Blob + require.Contains(t, blob, "type: model") + require.Contains(t, blob, "connector: duckdb") + require.Contains(t, blob, "read_csv") + require.Contains(t, blob, "data/sales.csv") +} + +func TestRenderSQLiteDuckDB(t *testing.T) { + registry, err := NewRegistry() + require.NoError(t, err) + + tmpl, ok := registry.Get("sqlite-duckdb") + require.True(t, ok) + + result, err := Render(&RenderInput{ + Template: tmpl, + Output: "model", + Properties: map[string]any{ + "db": "/data/app.db", + "table": "users", + "name": "sqlite_users", + }, + ExistingEnv: make(map[string]bool), + }) + require.NoError(t, err) + require.Len(t, result.Files, 1) + + blob := result.Files[0].Blob + require.Contains(t, blob, "type: model") + require.Contains(t, blob, "connector: duckdb") + require.Contains(t, blob, "sqlite_scan") + require.Contains(t, blob, "/data/app.db") + require.Contains(t, blob, "users") +} + +// --- Schema-based template tests --- + +func TestRenderIcebergDuckDBWithSchema(t *testing.T) { + registry, err := NewRegistry() + require.NoError(t, err) + + tmpl, ok := registry.Get("iceberg-duckdb") + require.True(t, ok) + require.NotNil(t, tmpl.JSONSchema, "iceberg-duckdb should have json_schema") + + result, err := Render(&RenderInput{ + Template: tmpl, + Output: "model", + Properties: map[string]any{ + "aws_access_key_id": "AKIAEXAMPLE", + "aws_secret_access_key": "wJalrXUtnFEMI/EXAMPLEKEY", + "aws_region": "us-west-2", + "path": "s3://my-iceberg-bucket/warehouse/my_table", + "name": "iceberg_test", + }, + ExistingEnv: make(map[string]bool), + }) + require.NoError(t, err) + require.Len(t, result.Files, 1) + + blob := result.Files[0].Blob + require.Contains(t, blob, "type: model") + require.Contains(t, blob, "iceberg_scan") + require.Contains(t, blob, "s3://my-iceberg-bucket/warehouse/my_table") + + // Verify path uses model_name from "name" property + require.Equal(t, "models/iceberg_test.yaml", result.Files[0].Path) + + // Verify secret extraction via JSON Schema + require.Equal(t, "AKIAEXAMPLE", result.EnvVars["AWS_ACCESS_KEY_ID"]) + require.Equal(t, "wJalrXUtnFEMI/EXAMPLEKEY", result.EnvVars["AWS_SECRET_ACCESS_KEY"]) + + // Raw secrets should NOT appear in the blob + require.NotContains(t, blob, "AKIAEXAMPLE") + require.NotContains(t, blob, "wJalrXUtnFEMI/EXAMPLEKEY") +} + +func TestRenderSchemaEnvVarConflict(t *testing.T) { + tmpl := &Template{ + Name: "test-schema", + DisplayName: "Test Schema", + Tags: []string{"test"}, + JSONSchema: map[string]any{ + "type": "object", + "properties": map[string]any{ + "api_key": map[string]any{ + "type": "string", + "x-secret": true, + "x-env-var": "MY_API_KEY", + }, + }, + }, + Files: []File{ + { + Name: "connector", + PathTemplate: "connectors/test.yaml", + CodeTemplate: "type: connector\n[[ renderProps .props ]]", + }, + }, + } + + // Pre-populate existing env to force conflict + existingEnv := map[string]bool{"MY_API_KEY": true} + + result, err := Render(&RenderInput{ + Template: tmpl, + Properties: map[string]any{"api_key": "secret123"}, + ExistingEnv: existingEnv, + }) + require.NoError(t, err) + + // Should use MY_API_KEY_1 due to conflict + require.Contains(t, result.EnvVars, "MY_API_KEY_1") + require.Equal(t, "secret123", result.EnvVars["MY_API_KEY_1"]) + require.Contains(t, result.Files[0].Blob, "MY_API_KEY_1") +} + +func TestRenderSchemaUIOnlyFieldsSkipped(t *testing.T) { + tmpl := &Template{ + Name: "test-ui-only", + DisplayName: "Test UI Only", + Tags: []string{"test"}, + JSONSchema: map[string]any{ + "type": "object", + "properties": map[string]any{ + "auth_method": map[string]any{ + "type": "string", + "x-ui-only": true, + }, + "host": map[string]any{ + "type": "string", + }, + }, + }, + Files: []File{ + { + Name: "connector", + PathTemplate: "connectors/test.yaml", + CodeTemplate: "type: connector\n[[ renderProps .props ]]", + }, + }, + } + + result, err := Render(&RenderInput{ + Template: tmpl, + Properties: map[string]any{ + "auth_method": "access_keys", + "host": "example.com", + }, + ExistingEnv: make(map[string]bool), + }) + require.NoError(t, err) + + blob := result.Files[0].Blob + require.Contains(t, blob, "host") + require.NotContains(t, blob, "auth_method") +} + +func TestRenderSchemaPropertyTypes(t *testing.T) { + tmpl := &Template{ + Name: "test-types", + DisplayName: "Test Types", + Tags: []string{"test"}, + JSONSchema: map[string]any{ + "type": "object", + "properties": map[string]any{ + "host": map[string]any{ + "type": "string", + }, + "port": map[string]any{ + "type": "number", + }, + "ssl": map[string]any{ + "type": "boolean", + }, + }, + }, + Files: []File{ + { + Name: "connector", + PathTemplate: "connectors/test.yaml", + CodeTemplate: "type: connector\n[[ renderProps .props ]]", + }, + }, + } + + result, err := Render(&RenderInput{ + Template: tmpl, + Properties: map[string]any{ + "host": "example.com", + "port": "9440", + "ssl": "true", + }, + ExistingEnv: make(map[string]bool), + }) + require.NoError(t, err) + + blob := result.Files[0].Blob + // Strings should be quoted + require.Contains(t, blob, `host: "example.com"`) + // Numbers should not be quoted + require.Contains(t, blob, "port: 9440") + // Booleans should not be quoted + require.Contains(t, blob, "ssl: true") +} diff --git a/runtime/templates/template.go b/runtime/templates/template.go new file mode 100644 index 00000000000..9113b58c9b7 --- /dev/null +++ b/runtime/templates/template.go @@ -0,0 +1,43 @@ +package templates + +// Template is a declarative definition for generating project files (connectors, models, etc.) +// from structured form data. Each template knows how to produce one or more output files. +// +// Templates with JSONSchema are self-contained: the schema drives form rendering (frontend) +// and property metadata like secret detection (backend). Templates without JSONSchema fall +// back to drivers.Spec for property metadata. +type Template struct { + Name string `json:"name"` + DisplayName string `json:"display_name"` + Description string `json:"description,omitempty"` // short description for UI display + DocsURL string `json:"docs_url,omitempty"` // link to documentation + Driver string `json:"driver"` // primary driver (e.g. "s3"); empty for driverless templates like iceberg + OLAP string `json:"olap"` // target OLAP engine (e.g. "duckdb"); empty for OLAP connector templates + Icon string `json:"icon,omitempty"` // icon component name for full-size display (e.g. add-data grid) + SmallIcon string `json:"small_icon,omitempty"` // icon component name for small display (e.g. nav, cards) + Tags []string `json:"tags"` + JSONSchema map[string]any `json:"json_schema,omitempty"` // JSON Schema for form generation and property metadata + PropertyOrder []string `json:"-"` // JSON-defined property key order; computed at load time + Files []File `json:"files"` +} + +// File describes a single output file within a template. +// PathTemplate and CodeTemplate use Go text/template syntax with [[ ]] delimiters +// to avoid collision with Rill's {{ .env.VAR }} runtime syntax. +// +// CodeTemplate can be specified inline (code_template) or loaded from a separate file +// (code_template_file) for readability. If both are set, code_template_file wins. +type File struct { + Name string `json:"name"` // output name: "connector" or "model" + PathTemplate string `json:"path_template"` // Go template for the file path + CodeTemplate string `json:"code_template,omitempty"` // Go template for the file content (inline) + CodeTemplateFile string `json:"code_template_file,omitempty"` // path to .tmpl file (relative to the JSON definition) +} + +// ProcessedProp is a property that has been pre-processed for template rendering. +// Secret values are replaced with {{ .env.VAR }} references; empty values are filtered. +type ProcessedProp struct { + Key string + Value string + Quoted bool // true for strings and secrets; false for numbers and booleans +} diff --git a/web-admin/src/client/gen/default/default.ts b/web-admin/src/client/gen/default/default.ts index 1f3e088e94e..567762547a1 100644 --- a/web-admin/src/client/gen/default/default.ts +++ b/web-admin/src/client/gen/default/default.ts @@ -1,5 +1,5 @@ /** - * Generated by orval v7.9.0 🍺 + * Generated by orval v7.21.0 🍺 * Do not edit manually. * Rill Admin API * Rill Admin API enables programmatic management of Rill Cloud resources, including organizations, projects, and user access. It provides endpoints for creating, updating, and deleting these resources, as well as managing authentication and permissions. @@ -383,7 +383,7 @@ export const adminServiceGetBillingProjectCredentials = ( }; export const getAdminServiceGetBillingProjectCredentialsQueryKey = ( - v1GetBillingProjectCredentialsRequest: V1GetBillingProjectCredentialsRequest, + v1GetBillingProjectCredentialsRequest?: V1GetBillingProjectCredentialsRequest, ) => { return [ `/v1/billing/metrics-project-credentials`, @@ -649,7 +649,7 @@ export const adminServiceGetDeploymentConfig = ( }; export const getAdminServiceGetDeploymentConfigQueryKey = ( - deploymentId: string, + deploymentId?: string, ) => { return [`/v1/deployments/${deploymentId}/config`] as const; }; @@ -1697,7 +1697,7 @@ export const adminServiceGetOrganizationNameForDomain = ( }; export const getAdminServiceGetOrganizationNameForDomainQueryKey = ( - domain: string, + domain?: string, ) => { return [`/v1/organization-for-domain/${domain}`] as const; }; @@ -1981,7 +1981,7 @@ export const adminServiceGetOrganization = ( }; export const getAdminServiceGetOrganizationQueryKey = ( - org: string, + org?: string, params?: AdminServiceGetOrganizationParams, ) => { return [`/v1/orgs/${org}`, ...(params ? [params] : [])] as const; @@ -2252,7 +2252,7 @@ export const adminServiceListOrganizationBillingIssues = ( }; export const getAdminServiceListOrganizationBillingIssuesQueryKey = ( - org: string, + org?: string, params?: AdminServiceListOrganizationBillingIssuesParams, ) => { return [ @@ -2361,7 +2361,7 @@ export const adminServiceGetPaymentsPortalURL = ( }; export const getAdminServiceGetPaymentsPortalURLQueryKey = ( - org: string, + org?: string, params?: AdminServiceGetPaymentsPortalURLParams, ) => { return [ @@ -2469,7 +2469,7 @@ export const adminServiceGetBillingSubscription = ( }; export const getAdminServiceGetBillingSubscriptionQueryKey = ( - org: string, + org?: string, params?: AdminServiceGetBillingSubscriptionParams, ) => { return [ @@ -3006,8 +3006,19 @@ export const adminServiceListOrganizationInvites = ( }); }; +export const getAdminServiceListOrganizationInvitesInfiniteQueryKey = ( + org?: string, + params?: AdminServiceListOrganizationInvitesParams, +) => { + return [ + "infinite", + `/v1/orgs/${org}/invites`, + ...(params ? [params] : []), + ] as const; +}; + export const getAdminServiceListOrganizationInvitesQueryKey = ( - org: string, + org?: string, params?: AdminServiceListOrganizationInvitesParams, ) => { return [`/v1/orgs/${org}/invites`, ...(params ? [params] : [])] as const; @@ -3039,7 +3050,7 @@ export const getAdminServiceListOrganizationInvitesInfiniteQueryOptions = < const queryKey = queryOptions?.queryKey ?? - getAdminServiceListOrganizationInvitesQueryKey(org, params); + getAdminServiceListOrganizationInvitesInfiniteQueryKey(org, params); const queryFn: QueryFunction< Awaited>, @@ -3217,8 +3228,19 @@ export const adminServiceListOrganizationMemberUsers = ( }); }; +export const getAdminServiceListOrganizationMemberUsersInfiniteQueryKey = ( + org?: string, + params?: AdminServiceListOrganizationMemberUsersParams, +) => { + return [ + "infinite", + `/v1/orgs/${org}/members`, + ...(params ? [params] : []), + ] as const; +}; + export const getAdminServiceListOrganizationMemberUsersQueryKey = ( - org: string, + org?: string, params?: AdminServiceListOrganizationMemberUsersParams, ) => { return [`/v1/orgs/${org}/members`, ...(params ? [params] : [])] as const; @@ -3250,7 +3272,7 @@ export const getAdminServiceListOrganizationMemberUsersInfiniteQueryOptions = < const queryKey = queryOptions?.queryKey ?? - getAdminServiceListOrganizationMemberUsersQueryKey(org, params); + getAdminServiceListOrganizationMemberUsersInfiniteQueryKey(org, params); const queryFn: QueryFunction< Awaited>, @@ -3520,8 +3542,8 @@ export const adminServiceGetOrganizationMemberUser = ( }; export const getAdminServiceGetOrganizationMemberUserQueryKey = ( - org: string, - email: string, + org?: string, + email?: string, ) => { return [`/v1/orgs/${org}/members/${email}`] as const; }; @@ -4022,7 +4044,7 @@ export const adminServiceListProjectsForOrganization = ( }; export const getAdminServiceListProjectsForOrganizationQueryKey = ( - org: string, + org?: string, params?: AdminServiceListProjectsForOrganizationParams, ) => { return [`/v1/orgs/${org}/projects`, ...(params ? [params] : [])] as const; @@ -4216,7 +4238,7 @@ export const adminServiceListProjectsForOrganizationAndUser = ( }; export const getAdminServiceListProjectsForOrganizationAndUserQueryKey = ( - org: string, + org?: string, params?: AdminServiceListProjectsForOrganizationAndUserParams, ) => { return [ @@ -4338,8 +4360,8 @@ export const adminServiceGetProject = ( }; export const getAdminServiceGetProjectQueryKey = ( - org: string, - project: string, + org?: string, + project?: string, params?: AdminServiceGetProjectParams, ) => { return [ @@ -5101,9 +5123,9 @@ export const adminServiceGetAlertYAML = ( }; export const getAdminServiceGetAlertYAMLQueryKey = ( - org: string, - project: string, - name: string, + org?: string, + project?: string, + name?: string, ) => { return [`/v1/orgs/${org}/projects/${project}/alerts/${name}/yaml`] as const; }; @@ -5211,8 +5233,8 @@ export const adminServiceGetCloneCredentials = ( }; export const getAdminServiceGetCloneCredentialsQueryKey = ( - org: string, - project: string, + org?: string, + project?: string, params?: AdminServiceGetCloneCredentialsParams, ) => { return [ @@ -5438,9 +5460,9 @@ export const adminServiceGetDeploymentCredentials = ( }; export const getAdminServiceGetDeploymentCredentialsQueryKey = ( - org: string, - project: string, - adminServiceGetDeploymentCredentialsBody: AdminServiceGetDeploymentCredentialsBody, + org?: string, + project?: string, + adminServiceGetDeploymentCredentialsBody?: AdminServiceGetDeploymentCredentialsBody, ) => { return [ `/v1/orgs/${org}/projects/${project}/credentials`, @@ -5562,8 +5584,8 @@ export const adminServiceListDeployments = ( }; export const getAdminServiceListDeploymentsQueryKey = ( - org: string, - project: string, + org?: string, + project?: string, params?: AdminServiceListDeploymentsParams, ) => { return [ @@ -5950,8 +5972,8 @@ export const adminServiceListProjectInvites = ( }; export const getAdminServiceListProjectInvitesQueryKey = ( - org: string, - project: string, + org?: string, + project?: string, params?: AdminServiceListProjectInvitesParams, ) => { return [ @@ -6064,8 +6086,8 @@ export const adminServiceListProjectMemberUsers = ( }; export const getAdminServiceListProjectMemberUsersQueryKey = ( - org: string, - project: string, + org?: string, + project?: string, params?: AdminServiceListProjectMemberUsersParams, ) => { return [ @@ -6274,9 +6296,9 @@ export const adminServiceGetProjectMemberUser = ( }; export const getAdminServiceGetProjectMemberUserQueryKey = ( - org: string, - project: string, - email: string, + org?: string, + project?: string, + email?: string, ) => { return [`/v1/orgs/${org}/projects/${project}/members/${email}`] as const; }; @@ -6581,9 +6603,9 @@ export const adminServiceListUsergroupsForProjectAndUser = ( }; export const getAdminServiceListUsergroupsForProjectAndUserQueryKey = ( - org: string, - project: string, - email: string, + org?: string, + project?: string, + email?: string, ) => { return [ `/v1/orgs/${org}/projects/${project}/members/${email}/usergroups`, @@ -6888,9 +6910,9 @@ export const adminServiceGenerateReportYAML = ( }; export const getAdminServiceGenerateReportYAMLQueryKey = ( - org: string, - project: string, - adminServiceCreateReportBodyBody: AdminServiceCreateReportBodyBody, + org?: string, + project?: string, + adminServiceCreateReportBodyBody?: AdminServiceCreateReportBodyBody, ) => { return [ `/v1/orgs/${org}/projects/${project}/reports/-/yaml`, @@ -7536,8 +7558,8 @@ export const adminServiceListProjectMemberServices = ( }; export const getAdminServiceListProjectMemberServicesQueryKey = ( - org: string, - project: string, + org?: string, + project?: string, ) => { return [`/v1/orgs/${org}/projects/${project}/services`] as const; }; @@ -7839,9 +7861,21 @@ export const adminServiceListMagicAuthTokens = ( }); }; +export const getAdminServiceListMagicAuthTokensInfiniteQueryKey = ( + org?: string, + project?: string, + params?: AdminServiceListMagicAuthTokensParams, +) => { + return [ + "infinite", + `/v1/orgs/${org}/projects/${project}/tokens/magic`, + ...(params ? [params] : []), + ] as const; +}; + export const getAdminServiceListMagicAuthTokensQueryKey = ( - org: string, - project: string, + org?: string, + project?: string, params?: AdminServiceListMagicAuthTokensParams, ) => { return [ @@ -7877,7 +7911,7 @@ export const getAdminServiceListMagicAuthTokensInfiniteQueryOptions = < const queryKey = queryOptions?.queryKey ?? - getAdminServiceListMagicAuthTokensQueryKey(org, project, params); + getAdminServiceListMagicAuthTokensInfiniteQueryKey(org, project, params); const queryFn: QueryFunction< Awaited>, @@ -8157,8 +8191,8 @@ export const adminServiceListProjectMemberUsergroups = ( }; export const getAdminServiceListProjectMemberUsergroupsQueryKey = ( - org: string, - project: string, + org?: string, + project?: string, params?: AdminServiceListProjectMemberUsergroupsParams, ) => { return [ @@ -8590,8 +8624,8 @@ export const adminServiceSearchProjectUsers = ( }; export const getAdminServiceSearchProjectUsersQueryKey = ( - org: string, - project: string, + org?: string, + project?: string, params?: AdminServiceSearchProjectUsersParams, ) => { return [ @@ -8704,8 +8738,8 @@ export const adminServiceGetProjectVariables = ( }; export const getAdminServiceGetProjectVariablesQueryKey = ( - org: string, - project: string, + org?: string, + project?: string, params?: AdminServiceGetProjectVariablesParams, ) => { return [ @@ -8923,8 +8957,8 @@ export const adminServiceListProjectWhitelistedDomains = ( }; export const getAdminServiceListProjectWhitelistedDomainsQueryKey = ( - org: string, - project: string, + org?: string, + project?: string, ) => { return [`/v1/orgs/${org}/projects/${project}/whitelisted`] as const; }; @@ -9218,7 +9252,7 @@ export const adminServiceListServices = (org: string, signal?: AbortSignal) => { }); }; -export const getAdminServiceListServicesQueryKey = (org: string) => { +export const getAdminServiceListServicesQueryKey = (org?: string) => { return [`/v1/orgs/${org}/services`] as const; }; @@ -9400,8 +9434,8 @@ export const adminServiceGetService = ( }; export const getAdminServiceGetServiceQueryKey = ( - org: string, - name: string, + org?: string, + name?: string, ) => { return [`/v1/orgs/${org}/services/${name}`] as const; }; @@ -9854,8 +9888,8 @@ export const adminServiceListServiceAuthTokens = ( }; export const getAdminServiceListServiceAuthTokensQueryKey = ( - org: string, - serviceName: string, + org?: string, + serviceName?: string, ) => { return [`/v1/orgs/${org}/services/${serviceName}/tokens`] as const; }; @@ -10069,7 +10103,7 @@ export const adminServiceListOrganizationMemberUsergroups = ( }; export const getAdminServiceListOrganizationMemberUsergroupsQueryKey = ( - org: string, + org?: string, params?: AdminServiceListOrganizationMemberUsergroupsParams, ) => { return [`/v1/orgs/${org}/usergroups`, ...(params ? [params] : [])] as const; @@ -10273,7 +10307,7 @@ export const adminServiceListUsergroupsForOrganizationAndUser = ( }; export const getAdminServiceListUsergroupsForOrganizationAndUserQueryKey = ( - org: string, + org?: string, params?: AdminServiceListUsergroupsForOrganizationAndUserParams, ) => { return [ @@ -10396,8 +10430,8 @@ export const adminServiceGetUsergroup = ( }; export const getAdminServiceGetUsergroupQueryKey = ( - org: string, - usergroup: string, + org?: string, + usergroup?: string, params?: AdminServiceGetUsergroupParams, ) => { return [ @@ -10676,8 +10710,8 @@ export const adminServiceListUsergroupMemberUsers = ( }; export const getAdminServiceListUsergroupMemberUsersQueryKey = ( - org: string, - usergroup: string, + org?: string, + usergroup?: string, params?: AdminServiceListUsergroupMemberUsersParams, ) => { return [ @@ -11295,7 +11329,7 @@ export const adminServiceListWhitelistedDomains = ( }); }; -export const getAdminServiceListWhitelistedDomainsQueryKey = (org: string) => { +export const getAdminServiceListWhitelistedDomainsQueryKey = (org?: string) => { return [`/v1/orgs/${org}/whitelisted`] as const; }; @@ -11636,7 +11670,7 @@ export const adminServiceGetProjectAccessRequest = ( }); }; -export const getAdminServiceGetProjectAccessRequestQueryKey = (id: string) => { +export const getAdminServiceGetProjectAccessRequestQueryKey = (id?: string) => { return [`/v1/project-access-request/${id}`] as const; }; @@ -12173,7 +12207,7 @@ export const adminServiceGetProjectByID = ( }); }; -export const getAdminServiceGetProjectByIDQueryKey = (id: string) => { +export const getAdminServiceGetProjectByIDQueryKey = (id?: string) => { return [`/v1/projects/${id}`] as const; }; @@ -12352,7 +12386,7 @@ export const adminServiceGetRepoMeta = ( }); }; -export const getAdminServiceGetRepoMetaQueryKey = (projectId: string) => { +export const getAdminServiceGetRepoMetaQueryKey = (projectId?: string) => { return [`/v1/projects/${projectId}/repo/meta`] as const; }; @@ -12451,7 +12485,7 @@ export const adminServicePullVirtualRepo = ( }; export const getAdminServicePullVirtualRepoQueryKey = ( - projectId: string, + projectId?: string, params?: AdminServicePullVirtualRepoParams, ) => { return [ @@ -12559,7 +12593,7 @@ export const adminServiceGetVirtualFile = ( }; export const getAdminServiceGetVirtualFileQueryKey = ( - projectId: string, + projectId?: string, params?: AdminServiceGetVirtualFileParams, ) => { return [ @@ -14818,7 +14852,7 @@ export const adminServiceListUserAuthTokens = ( }; export const getAdminServiceListUserAuthTokensQueryKey = ( - userId: string, + userId?: string, params?: AdminServiceListUserAuthTokensParams, ) => { return [`/v1/users/${userId}/tokens`, ...(params ? [params] : [])] as const; @@ -15359,7 +15393,7 @@ export const adminServiceGetBookmark = ( }); }; -export const getAdminServiceGetBookmarkQueryKey = (bookmarkId: string) => { +export const getAdminServiceGetBookmarkQueryKey = (bookmarkId?: string) => { return [`/v1/users/bookmarks/${bookmarkId}`] as const; }; diff --git a/web-admin/src/client/gen/index.schemas.ts b/web-admin/src/client/gen/index.schemas.ts index 720a37c4798..d4a44bb2fef 100644 --- a/web-admin/src/client/gen/index.schemas.ts +++ b/web-admin/src/client/gen/index.schemas.ts @@ -1,5 +1,5 @@ /** - * Generated by orval v7.9.0 🍺 + * Generated by orval v7.21.0 🍺 * Do not edit manually. * Rill Admin API * Rill Admin API enables programmatic management of Rill Cloud resources, including organizations, projects, and user access. It provides endpoints for creating, updating, and deleting these resources, as well as managing authentication and permissions. diff --git a/web-common/src/components/icons/connectors/GoogleCloudStorageIcon.svelte b/web-common/src/components/icons/connectors/GoogleCloudStorageIcon.svelte index db60ba30180..26d2f5aae42 100644 --- a/web-common/src/components/icons/connectors/GoogleCloudStorageIcon.svelte +++ b/web-common/src/components/icons/connectors/GoogleCloudStorageIcon.svelte @@ -3,30 +3,37 @@ + + + diff --git a/web-common/src/components/icons/connectors/LocalFileIcon.svelte b/web-common/src/components/icons/connectors/LocalFileIcon.svelte new file mode 100644 index 00000000000..f43911e65dd --- /dev/null +++ b/web-common/src/components/icons/connectors/LocalFileIcon.svelte @@ -0,0 +1,21 @@ + + + + + + + diff --git a/web-common/src/features/add-data/form/SourceForm.svelte b/web-common/src/features/add-data/form/SourceForm.svelte index 8aacc250ec3..959c4785089 100644 --- a/web-common/src/features/add-data/form/SourceForm.svelte +++ b/web-common/src/features/add-data/form/SourceForm.svelte @@ -1,9 +1,15 @@
{#if paramsError} - +
+ +
{/if} = { + gcs: { + type: "object", + "x-category": "objectStore", + properties: { + google_application_credentials: { + type: "string", + "x-step": "connector", + }, + path: { type: "string", "x-step": "source" }, + }, + } as unknown as MultiStepFormSchema, + snowflake: { + type: "object", + "x-category": "warehouse", + properties: { + account: { type: "string", "x-step": "connector" }, + sql: { type: "string", "x-step": "explorer" }, + name: { type: "string", "x-step": "explorer" }, + }, + } as unknown as MultiStepFormSchema, +}; + describe("AddDataFormManager", () => { + beforeAll(() => { + populateSchemaCache(testSchemas); + }); beforeEach(() => { resetConnectorStep(); }); diff --git a/web-common/src/features/sources/modal/AddDataFormManager.ts b/web-common/src/features/sources/modal/AddDataFormManager.ts index e724961bc57..9a49da1ecf0 100644 --- a/web-common/src/features/sources/modal/AddDataFormManager.ts +++ b/web-common/src/features/sources/modal/AddDataFormManager.ts @@ -24,19 +24,16 @@ import { type ConnectorStepState, } from "./connectorStepStore"; import { get } from "svelte/store"; -import { compileConnectorYAML } from "../../connectors/code-utils"; -import { compileSourceYAML, prepareSourceFormData } from "../sourceUtils"; import type { ActionResult } from "@sveltejs/kit"; import type { QueryClient } from "@tanstack/query-core"; import { filterSchemaValuesForSubmit, findRadioEnumKey, getSchemaFieldMetaList, - getSchemaSecretKeys, - getSchemaStringKeys, } from "../../templates/schema-utils"; import type { ButtonLabels } from "../../templates/schemas/types"; import { processFileContent } from "../../templates/file-encoding"; +import { generateTemplate } from "./generate-template"; type FormData = Record; // Use unknown to be compatible with superforms' complex ValidationErrors type @@ -486,123 +483,99 @@ export class AddDataFormManager { /** * Compute YAML preview for the current form state. - * Schema conditionals handle connector-specific requirements. + * All connectors use the GenerateTemplate RPC. */ - computeYamlPreview(ctx: { + async computeYamlPreview(ctx: { + client: RuntimeClient; stepState: ConnectorStepState | undefined; isMultiStepConnector: boolean; isConnectorForm: boolean; formValues: Record; - existingEnvBlob?: string; - }): string { + }): Promise { const connector = this.connector; const { + client, stepState, isMultiStepConnector, isConnectorForm, formValues, - existingEnvBlob, } = ctx; const schema = getConnectorSchema(this.schemaName); - const schemaConnectorFields = schema - ? getSchemaFieldMetaList(schema, { step: "connector" }) - : null; - const schemaConnectorSecretKeys = schema - ? getSchemaSecretKeys(schema, { step: "connector" }) - : undefined; - const schemaConnectorStringKeys = schema - ? getSchemaStringKeys(schema, { step: "connector" }) - : undefined; - - const connectorPropertiesForPreview = schemaConnectorFields ?? []; - - const getConnectorYamlPreview = (values: Record) => { + + const isOnConnectorStep = !stepState || stepState.step === "connector"; + const isOnSourceOrExplorerStep = + stepState?.step === "source" || stepState?.step === "explorer"; + + if (isMultiStepConnector && isOnConnectorStep) { + // Step 1 of multi-step: preview the connector YAML const filteredValues = schema - ? filterSchemaValuesForSubmit(schema, values, { step: "connector" }) - : values; - return compileConnectorYAML(connector, filteredValues, { - fieldFilter: (property) => { - if ("internal" in property && property.internal) return false; - return !("noPrompt" in property && property.noPrompt); - }, - orderedProperties: connectorPropertiesForPreview, - secretKeys: schemaConnectorSecretKeys, - stringKeys: schemaConnectorStringKeys, - schema: schema ?? undefined, - existingEnvBlob, + ? filterSchemaValuesForSubmit(schema, formValues, { + step: "connector", + }) + : formValues; + const response = await generateTemplate(client, { + resourceType: "connector", + driver: connector.name as string, + properties: filteredValues, }); - }; + return response.blob ?? ""; + } + + if (isMultiStepConnector && isOnSourceOrExplorerStep) { + // Step 2 of multi-step: preview the model/source YAML + const combinedValues = { + ...(stepState?.connectorConfig || {}), + ...formValues, + } as Record; - const getSourceYamlPreview = (values: Record) => { - // For multi-step connectors in step 2, filter out connector properties - let filteredValues = values; - if ( - (isMultiStepConnector && stepState?.step === "source") || - stepState?.step === "explorer" - ) { + // Filter out connector-step properties + let sourceValues = combinedValues; + if (schema) { const connectorPropertyKeys = new Set( - schema - ? getSchemaFieldMetaList(schema, { step: "connector" }).map( - (field) => field.key, - ) - : [], + getSchemaFieldMetaList(schema, { step: "connector" }).map( + (field) => field.key, + ), ); - filteredValues = Object.fromEntries( - Object.entries(values).filter( + sourceValues = Object.fromEntries( + Object.entries(combinedValues).filter( ([key]) => !connectorPropertyKeys.has(key), ), ); } - const [rewrittenConnector, rewrittenFormValues] = prepareSourceFormData( - connector, - filteredValues, - { - connectorInstanceName: stepState?.connectorInstanceName || undefined, - }, - ); - const isExplorerStep = stepState?.step === "explorer"; - const isRewrittenToDuckDb = rewrittenConnector.name === "duckdb"; - const rewrittenSchema = getConnectorSchema(rewrittenConnector.name ?? ""); - const sourceStep = isExplorerStep ? "explorer" : "source"; - const rewrittenSecretKeys = rewrittenSchema - ? getSchemaSecretKeys(rewrittenSchema, { step: sourceStep }) - : undefined; - const rewrittenStringKeys = rewrittenSchema - ? getSchemaStringKeys(rewrittenSchema, { step: sourceStep }) - : undefined; - if (isRewrittenToDuckDb || isExplorerStep) { - // When rewritten to DuckDB, don't use the original connectorInstanceName. - // The original connector is referenced via create_secrets_from_connectors. - const yamlConnectorInstanceName = isRewrittenToDuckDb - ? undefined - : stepState?.connectorInstanceName || undefined; - return compileSourceYAML(rewrittenConnector, rewrittenFormValues, { - secretKeys: rewrittenSecretKeys, - stringKeys: rewrittenStringKeys, - originalDriverName: connector.name || undefined, - connectorInstanceName: yamlConnectorInstanceName, - }); - } - return getConnectorYamlPreview(rewrittenFormValues); - }; + const response = await generateTemplate(client, { + resourceType: "model", + driver: connector.name as string, + properties: sourceValues, + connectorName: + stepState?.connectorInstanceName || (connector.name as string), + }); + return response.blob ?? ""; + } - // Multi-step connectors (S3, GCS, Azure) - if (isMultiStepConnector) { - if (stepState?.step === "connector") { - return getConnectorYamlPreview(formValues); - } else { - const combinedValues = { - ...(stepState?.connectorConfig || {}), - ...formValues, - } as Record; - return getSourceYamlPreview(combinedValues); - } + if (isConnectorForm) { + // Single-step connector + const filteredValues = schema + ? filterSchemaValuesForSubmit(schema, formValues, { + step: "connector", + }) + : formValues; + const response = await generateTemplate(client, { + resourceType: "connector", + driver: connector.name as string, + properties: filteredValues, + }); + return response.blob ?? ""; } - if (isConnectorForm) return getConnectorYamlPreview(formValues); - return getSourceYamlPreview(formValues); + // Single-step source form + const response = await generateTemplate(client, { + resourceType: "model", + driver: connector.name as string, + properties: formValues, + }); + return response.blob ?? ""; } /** diff --git a/web-common/src/features/sources/modal/AddDataModal.svelte b/web-common/src/features/sources/modal/AddDataModal.svelte index 472bebf5336..48fa4b99cc7 100644 --- a/web-common/src/features/sources/modal/AddDataModal.svelte +++ b/web-common/src/features/sources/modal/AddDataModal.svelte @@ -3,6 +3,8 @@ import { getScreenNameFromPage } from "@rilldata/web-common/features/file-explorer/telemetry"; import { cn } from "@rilldata/web-common/lib/shadcn"; import type { V1ConnectorDriver } from "@rilldata/web-common/runtime-client"; + import { createQuery } from "@tanstack/svelte-query"; + import { derived } from "svelte/store"; import { onMount } from "svelte"; import { behaviourEvent } from "../../../metrics/initMetrics"; import { @@ -11,6 +13,11 @@ } from "../../../metrics/service/BehaviourEventTypes"; import { MetricsEventSpace } from "../../../metrics/service/MetricsTypes"; import { useRuntimeClient } from "../../../runtime-client/v2"; + import { + createRuntimeServiceGetInstance, + createRuntimeServiceListTemplates, + getRuntimeServiceListTemplatesQueryOptions, + } from "../../../runtime-client/v2/gen/runtime-service"; import { connectorIconMapping } from "../../connectors/connector-icon-mapping"; import { useIsModelingSupportedForDefaultOlapDriverOLAP as useIsModelingSupportedForDefaultOlapDriver } from "../../connectors/selectors"; import { duplicateSourceName } from "../sources-store"; @@ -19,7 +26,6 @@ import LocalSourceUpload from "./LocalSourceUpload.svelte"; import RequestConnectorForm from "./RequestConnectorForm.svelte"; import { - connectors, getConnectorSchema, getFormWidth, isMultiStepConnector as isMultiStepConnectorSchema, @@ -30,6 +36,50 @@ import { resetConnectorStep } from "./connectorStepStore"; import LoadingSpinner from "@rilldata/web-common/components/icons/LoadingSpinner.svelte"; + const runtimeClient = useRuntimeClient(); + + // Fetch instance to get the active OLAP driver + const instanceQuery = createRuntimeServiceGetInstance(runtimeClient, { + sensitive: true, + }); + + // Fetch source templates filtered by the active OLAP driver. + // Uses derived query options so TanStack re-fetches when olapDriver changes. + const sourceTemplatesQueryOptions = derived( + [instanceQuery], + ([$instance]) => { + const olap = $instance.data?.instance?.olapConnector || ""; + return getRuntimeServiceListTemplatesQueryOptions( + runtimeClient, + { tags: ["source", olap] }, + { query: { enabled: !!olap } }, + ); + }, + ); + const sourceTemplatesQuery = createQuery(sourceTemplatesQueryOptions); + + // Fetch OLAP templates + const olapTemplatesQuery = createRuntimeServiceListTemplates(runtimeClient, { + tags: ["olap"], + }); + + // Map templates to ConnectorInfo for the UI + $: sourceConnectors = ($sourceTemplatesQuery.data?.templates ?? []).map( + (t): ConnectorInfo => ({ + name: t.driver ?? t.name ?? "", + displayName: t.displayName ?? t.name ?? "", + category: "source" as any, + }), + ); + + $: olapConnectors = ($olapTemplatesQuery.data?.templates ?? []).map( + (t): ConnectorInfo => ({ + name: t.driver ?? t.name ?? "", + displayName: t.displayName ?? t.name ?? "", + category: "olap" as any, + }), + ); + let step = 0; let selectedConnector: null | V1ConnectorDriver = null; let selectedSchemaName: string | null = null; @@ -38,12 +88,6 @@ let requestConnector = false; let isSubmittingForm = false; - // Filter connectors by category from JSON schemas - $: sourceConnectors = connectors.filter( - (c) => c.category !== "olap" && c.category !== "ai", - ); - $: olapConnectors = connectors.filter((c) => c.category === "olap"); - // Get the form width class for the selected connector $: selectedSchema = selectedSchemaName ? getConnectorSchema(selectedSchemaName) @@ -94,8 +138,9 @@ // Handle pending connector name when connectors finish loading // When connector is provided via Import Data button, ensure step stays at 2 - $: if (pendingConnectorName && connectors.length > 0) { - const found = connectors.find((c) => c.name === pendingConnectorName); + $: allConnectors = [...sourceConnectors, ...olapConnectors]; + $: if (pendingConnectorName && allConnectors.length > 0) { + const found = allConnectors.find((c) => c.name === pendingConnectorName); if (found) { selectedConnector = toConnectorDriver(found); selectedSchemaName = pendingConnectorName; @@ -184,8 +229,6 @@ resetModal(); } - const runtimeClient = useRuntimeClient(); - $: isModelingSupportedForDefaultOlapDriver = useIsModelingSupportedForDefaultOlapDriver(runtimeClient); $: isModelingSupported = $isModelingSupportedForDefaultOlapDriver.data; diff --git a/web-common/src/features/sources/modal/FormValidation.test.ts b/web-common/src/features/sources/modal/FormValidation.test.ts index 722052755c4..4ad28ddbcd6 100644 --- a/web-common/src/features/sources/modal/FormValidation.test.ts +++ b/web-common/src/features/sources/modal/FormValidation.test.ts @@ -1,6 +1,21 @@ -import { describe, it, expect } from "vitest"; +import { describe, it, expect, beforeAll } from "vitest"; import { getValidationSchemaForConnector } from "./FormValidation"; +import { populateSchemaCache } from "./connector-schemas"; +import type { MultiStepFormSchema } from "../../templates/schemas/types"; + +// Load the real S3 schema from the backend template definition. +// This ensures frontend validation stays in sync with the backend. +import s3Template from "../../../../../runtime/templates/definitions/duckdb-models/s3-duckdb.json"; + +beforeAll(() => { + populateSchemaCache({ + s3: { + ...s3Template.json_schema, + title: s3Template.display_name, + } as unknown as MultiStepFormSchema, + }); +}); describe("getValidationSchemaForConnector (multi-step auth)", () => { it("enforces required fields for access key auth", async () => { diff --git a/web-common/src/features/sources/modal/MultiStepConnectorFlow.svelte b/web-common/src/features/sources/modal/MultiStepConnectorFlow.svelte index 227707fd9b9..792173b0d00 100644 --- a/web-common/src/features/sources/modal/MultiStepConnectorFlow.svelte +++ b/web-common/src/features/sources/modal/MultiStepConnectorFlow.svelte @@ -11,8 +11,8 @@ getSchemaInitialValues, } from "../../templates/schema-utils"; import { getConnectorSchema } from "./connector-schemas"; - import { isMultiStepConnectorDisabled } from "./utils"; import { ICONS } from "./icons"; + import { isMultiStepConnectorDisabled } from "./utils"; import type { AddDataFormManager } from "./AddDataFormManager"; import type { MultiStepFormSchema } from "../../templates/schemas/types"; diff --git a/web-common/src/features/sources/modal/add-source-visibility.spec.ts b/web-common/src/features/sources/modal/add-source-visibility.spec.ts index 2de9e06f51e..e64313e9c17 100644 --- a/web-common/src/features/sources/modal/add-source-visibility.spec.ts +++ b/web-common/src/features/sources/modal/add-source-visibility.spec.ts @@ -1,9 +1,37 @@ -import { describe, it, expect, beforeEach } from "vitest"; +import { describe, it, expect, beforeAll, beforeEach } from "vitest"; import { addSourceModal } from "./add-source-visibility"; import { resetConnectorStep, connectorStepStore } from "./connectorStepStore"; +import { populateSchemaCache } from "./connector-schemas"; +import type { MultiStepFormSchema } from "../../templates/schemas/types"; import { get } from "svelte/store"; +const testSchemas: Record = { + gcs: { + type: "object", + "x-category": "objectStore", + properties: { + google_application_credentials: { + type: "string", + "x-step": "connector", + }, + path: { type: "string", "x-step": "source" }, + }, + } as unknown as MultiStepFormSchema, + snowflake: { + type: "object", + "x-category": "warehouse", + properties: { + account: { type: "string", "x-step": "connector" }, + sql: { type: "string", "x-step": "explorer" }, + name: { type: "string", "x-step": "explorer" }, + }, + } as unknown as MultiStepFormSchema, +}; + describe("addSourceModal", () => { + beforeAll(() => { + populateSchemaCache(testSchemas); + }); beforeEach(() => { resetConnectorStep(); }); diff --git a/web-common/src/features/sources/modal/connector-schemas.spec.ts b/web-common/src/features/sources/modal/connector-schemas.spec.ts index 36e3995f074..873ec707b26 100644 --- a/web-common/src/features/sources/modal/connector-schemas.spec.ts +++ b/web-common/src/features/sources/modal/connector-schemas.spec.ts @@ -1,4 +1,4 @@ -import { describe, it, expect } from "vitest"; +import { describe, it, expect, beforeAll } from "vitest"; import { getSchemaNameFromDriver, getConnectorSchema, @@ -7,11 +7,131 @@ import { hasExplorerStep, getFormHeight, shouldShowSkipLink, - toConnectorDriver, - multiStepFormSchemas, + populateSchemaCache, } from "./connector-schemas"; +import type { MultiStepFormSchema } from "../../templates/schemas/types"; + +// Minimal test schemas that exercise the functions without requiring the API +const testSchemas: Record = { + postgres: { + $schema: "http://json-schema.org/draft-07/schema#", + type: "object", + title: "Postgres", + "x-category": "sqlStore", + properties: { + host: { type: "string", title: "Host", "x-step": "connector" }, + sql: { type: "string", title: "SQL", "x-step": "explorer" }, + name: { type: "string", title: "Name", "x-step": "explorer" }, + }, + } as unknown as MultiStepFormSchema, + mysql: { + $schema: "http://json-schema.org/draft-07/schema#", + type: "object", + title: "MySQL", + "x-category": "sqlStore", + properties: { + host: { type: "string", title: "Host", "x-step": "connector" }, + sql: { type: "string", title: "SQL", "x-step": "explorer" }, + name: { type: "string", title: "Name", "x-step": "explorer" }, + }, + } as unknown as MultiStepFormSchema, + s3: { + $schema: "http://json-schema.org/draft-07/schema#", + type: "object", + title: "S3", + "x-category": "objectStore", + properties: { + aws_access_key_id: { + type: "string", + title: "Access Key", + "x-step": "connector", + }, + path: { type: "string", title: "Path", "x-step": "source" }, + }, + } as unknown as MultiStepFormSchema, + gcs: { + $schema: "http://json-schema.org/draft-07/schema#", + type: "object", + title: "GCS", + "x-category": "objectStore", + properties: { + google_application_credentials: { + type: "string", + title: "Credentials", + "x-step": "connector", + }, + path: { type: "string", title: "Path", "x-step": "source" }, + }, + } as unknown as MultiStepFormSchema, + azure: { + $schema: "http://json-schema.org/draft-07/schema#", + type: "object", + title: "Azure", + "x-category": "objectStore", + properties: { + azure_storage_account: { + type: "string", + title: "Account", + "x-step": "connector", + }, + path: { type: "string", title: "Path", "x-step": "source" }, + }, + } as unknown as MultiStepFormSchema, + snowflake: { + $schema: "http://json-schema.org/draft-07/schema#", + type: "object", + title: "Snowflake", + "x-category": "warehouse", + "x-form-height": "tall", + properties: { + account: { type: "string", title: "Account", "x-step": "connector" }, + sql: { type: "string", title: "SQL", "x-step": "explorer" }, + name: { type: "string", title: "Name", "x-step": "explorer" }, + }, + } as unknown as MultiStepFormSchema, + clickhouse: { + $schema: "http://json-schema.org/draft-07/schema#", + type: "object", + title: "ClickHouse", + "x-category": "olap", + properties: { + host: { type: "string", title: "Host" }, + }, + } as unknown as MultiStepFormSchema, + duckdb: { + $schema: "http://json-schema.org/draft-07/schema#", + type: "object", + title: "DuckDB", + "x-category": "olap", + properties: { + path: { type: "string", title: "Path" }, + }, + } as unknown as MultiStepFormSchema, + salesforce: { + $schema: "http://json-schema.org/draft-07/schema#", + type: "object", + title: "Salesforce", + "x-category": "sqlStore", + properties: { + client_id: { type: "string", title: "Client ID", "x-step": "connector" }, + }, + } as unknown as MultiStepFormSchema, + sqlite: { + $schema: "http://json-schema.org/draft-07/schema#", + type: "object", + title: "SQLite", + "x-category": "sourceOnly", + properties: { + db: { type: "string", title: "Database" }, + }, + } as unknown as MultiStepFormSchema, +}; describe("connector-schemas", () => { + beforeAll(() => { + populateSchemaCache(testSchemas); + }); + describe("getSchemaNameFromDriver", () => { it("returns driver name when it directly matches a schema name", () => { expect(getSchemaNameFromDriver("postgres")).toBe("postgres"); @@ -21,16 +141,11 @@ describe("connector-schemas", () => { }); it("returns schema name for drivers with x-driver override (when no direct match)", () => { - // Find schemas with x-driver overrides that don't directly match another schema name - for (const [schemaName, schema] of Object.entries(multiStepFormSchemas)) { - const xDriver = schema?.["x-driver"]; - // Only test if x-driver is set and doesn't match an existing schema name - // (because direct schema name matches take precedence) - if ( - xDriver && - xDriver !== schemaName && - !(xDriver in multiStepFormSchemas) - ) { + for (const [schemaName, schema] of Object.entries(testSchemas)) { + const xDriver = (schema as Record)?.["x-driver"] as + | string + | undefined; + if (xDriver && xDriver !== schemaName && !(xDriver in testSchemas)) { expect(getSchemaNameFromDriver(xDriver)).toBe(schemaName); } } @@ -44,7 +159,7 @@ describe("connector-schemas", () => { }); it("handles all registered schema names", () => { - const schemaNames = Object.keys(multiStepFormSchemas); + const schemaNames = Object.keys(testSchemas); for (const name of schemaNames) { const result = getSchemaNameFromDriver(name); expect(result).toBe(name); @@ -78,8 +193,9 @@ describe("connector-schemas", () => { }); it("returns x-driver value when specified in schema", () => { - for (const [schemaName, schema] of Object.entries(multiStepFormSchemas)) { - const expected = schema?.["x-driver"] ?? schemaName; + for (const [schemaName, schema] of Object.entries(testSchemas)) { + const expected = + (schema as Record)?.["x-driver"] ?? schemaName; expect(getBackendConnectorName(schemaName)).toBe(expected); } }); @@ -91,21 +207,14 @@ describe("connector-schemas", () => { describe("isMultiStepConnector", () => { it("returns true for object store connectors", () => { - const s3Schema = getConnectorSchema("s3"); - const gcsSchema = getConnectorSchema("gcs"); - const azureSchema = getConnectorSchema("azure"); - - expect(isMultiStepConnector(s3Schema)).toBe(true); - expect(isMultiStepConnector(gcsSchema)).toBe(true); - expect(isMultiStepConnector(azureSchema)).toBe(true); + expect(isMultiStepConnector(getConnectorSchema("s3"))).toBe(true); + expect(isMultiStepConnector(getConnectorSchema("gcs"))).toBe(true); + expect(isMultiStepConnector(getConnectorSchema("azure"))).toBe(true); }); it("returns false for non-object store connectors", () => { - const postgresSchema = getConnectorSchema("postgres"); - const mysqlSchema = getConnectorSchema("mysql"); - - expect(isMultiStepConnector(postgresSchema)).toBe(false); - expect(isMultiStepConnector(mysqlSchema)).toBe(false); + expect(isMultiStepConnector(getConnectorSchema("postgres"))).toBe(false); + expect(isMultiStepConnector(getConnectorSchema("mysql"))).toBe(false); }); it("returns false for AI connectors", () => { @@ -119,21 +228,19 @@ describe("connector-schemas", () => { describe("hasExplorerStep", () => { it("returns true for SQL store and warehouse connectors", () => { - const snowflakeSchema = getConnectorSchema("snowflake"); - const postgresSchema = getConnectorSchema("postgres"); + const snowflake = getConnectorSchema("snowflake"); + const postgres = getConnectorSchema("postgres"); - // Check based on category - if (snowflakeSchema?.["x-category"] === "warehouse") { - expect(hasExplorerStep(snowflakeSchema)).toBe(true); + if (snowflake?.["x-category"] === "warehouse") { + expect(hasExplorerStep(snowflake)).toBe(true); } - if (postgresSchema?.["x-category"] === "sqlStore") { - expect(hasExplorerStep(postgresSchema)).toBe(true); + if (postgres?.["x-category"] === "sqlStore") { + expect(hasExplorerStep(postgres)).toBe(true); } }); it("returns false for object store connectors", () => { - const s3Schema = getConnectorSchema("s3"); - expect(hasExplorerStep(s3Schema)).toBe(false); + expect(hasExplorerStep(getConnectorSchema("s3"))).toBe(false); }); it("returns false for AI connectors", () => { @@ -149,8 +256,8 @@ describe("connector-schemas", () => { it("returns tall height for schemas with x-form-height: tall", () => { const FORM_HEIGHT_TALL = "max-h-[40rem] min-h-[40rem]"; - for (const [, schema] of Object.entries(multiStepFormSchemas)) { - if (schema?.["x-form-height"] === "tall") { + for (const [, schema] of Object.entries(testSchemas)) { + if ((schema as Record)?.["x-form-height"] === "tall") { expect(getFormHeight(schema)).toBe(FORM_HEIGHT_TALL); } } @@ -159,8 +266,8 @@ describe("connector-schemas", () => { it("returns default height for schemas without x-form-height", () => { const FORM_HEIGHT_DEFAULT = "max-h-[34.5rem] min-h-[34.5rem]"; - for (const [, schema] of Object.entries(multiStepFormSchemas)) { - if (!schema?.["x-form-height"]) { + for (const [, schema] of Object.entries(testSchemas)) { + if (!(schema as Record)?.["x-form-height"]) { expect(getFormHeight(schema)).toBe(FORM_HEIGHT_DEFAULT); } } @@ -209,45 +316,4 @@ describe("connector-schemas", () => { ); }); }); - - describe("toConnectorDriver", () => { - it("returns null for unknown schema names", () => { - expect(toConnectorDriver("nonexistent")).toBeNull(); - }); - - it("sets implementsAi for AI connectors", () => { - const claude = toConnectorDriver("claude"); - expect(claude).not.toBeNull(); - expect(claude!.name).toBe("claude"); - expect(claude!.displayName).toBe("Claude"); - expect(claude!.implementsAi).toBe(true); - expect(claude!.implementsOlap).toBe(false); - expect(claude!.implementsWarehouse).toBe(false); - expect(claude!.implementsObjectStore).toBe(false); - expect(claude!.implementsSqlStore).toBe(false); - }); - - it("sets implementsWarehouse for warehouse connectors", () => { - const bq = toConnectorDriver("bigquery"); - expect(bq).not.toBeNull(); - expect(bq!.name).toBe("bigquery"); - expect(bq!.displayName).toBe("BigQuery"); - expect(bq!.implementsWarehouse).toBe(true); - expect(bq!.implementsAi).toBe(false); - }); - - it("sets implementsObjectStore for object store connectors", () => { - const s3 = toConnectorDriver("s3"); - expect(s3).not.toBeNull(); - expect(s3!.implementsObjectStore).toBe(true); - expect(s3!.implementsAi).toBe(false); - }); - - it("sets implementsOlap for OLAP connectors", () => { - const ch = toConnectorDriver("clickhouse"); - expect(ch).not.toBeNull(); - expect(ch!.implementsOlap).toBe(true); - expect(ch!.implementsAi).toBe(false); - }); - }); }); diff --git a/web-common/src/features/sources/modal/connector-schemas.ts b/web-common/src/features/sources/modal/connector-schemas.ts index 29778a0053e..4d0ab98d6ae 100644 --- a/web-common/src/features/sources/modal/connector-schemas.ts +++ b/web-common/src/features/sources/modal/connector-schemas.ts @@ -102,6 +102,58 @@ export function getConnectorSchema( return schema?.properties ? schema : null; } +/** + * Maps driver names to their full template names (e.g. "kafka" → "kafka-clickhouse"). + * Populated when templates are registered from the ListTemplates API. + */ +export const templateNameMap = new Map(); + +/** + * Register a template schema dynamically. Called when templates are fetched + * from the ListTemplates API so that connectors not in the static schema map + * (e.g. kafka, hudi for ClickHouse) work in the form flow. + * Also updates connectorInfoMap so getConnectorDriverForSchema resolves. + */ +export function registerTemplateSchema( + driverName: string, + templateName: string, + schema: MultiStepFormSchema, + displayName: string, +) { + multiStepFormSchemas[driverName] = schema; + templateNameMap.set(driverName, templateName); + const category = (schema["x-category"] ?? "sourceOnly") as ConnectorCategory; + connectorInfoMap.set(driverName, { + name: driverName, + displayName, + category, + }); +} + +// Replace the in-memory schema cache with the provided schemas. +// Test-only seam: lets specs run with a minimal, deterministic schema set +// instead of the full static + API-loaded registry. +export function populateSchemaCache( + schemas: Record, +) { + for (const key of Object.keys(multiStepFormSchemas)) { + delete multiStepFormSchemas[key]; + } + connectorInfoMap.clear(); + templateNameMap.clear(); + + for (const [name, schema] of Object.entries(schemas)) { + multiStepFormSchemas[name] = schema; + const category = (schema["x-category"] ?? + "sourceOnly") as ConnectorCategory; + connectorInfoMap.set(name, { + name, + displayName: schema.title ?? name, + category, + }); + } +} + /** * Get the backend driver name for a given schema name. * Returns x-driver if specified, otherwise returns the schema name. diff --git a/web-common/src/features/sources/modal/constants.ts b/web-common/src/features/sources/modal/constants.ts index 42c85b04f63..907884fcd40 100644 --- a/web-common/src/features/sources/modal/constants.ts +++ b/web-common/src/features/sources/modal/constants.ts @@ -87,6 +87,8 @@ export const SOURCES = [ "delta", "gcs", "iceberg", + "kafka", + "mongodb", "mysql", "postgres", "redshift", diff --git a/web-common/src/features/sources/modal/generate-template.spec.ts b/web-common/src/features/sources/modal/generate-template.spec.ts new file mode 100644 index 00000000000..53c0d63008b --- /dev/null +++ b/web-common/src/features/sources/modal/generate-template.spec.ts @@ -0,0 +1,176 @@ +import { describe, it, expect, vi, beforeEach } from "vitest"; +import { mergeEnvVars } from "./generate-template"; +import type { RuntimeClient } from "../../../runtime-client/v2"; + +// Mock the runtime client +const mockGetFile = vi.fn(); +vi.mock("../../../runtime-client", () => ({ + getRuntimeServiceGetFileQueryKey: vi.fn( + (instanceId: string, params: { path: string }) => [ + "runtimeServiceGetFile", + instanceId, + params, + ], + ), + runtimeServiceGetFile: (...args: unknown[]) => mockGetFile(...args), +})); + +// Mock replaceOrAddEnvVariable (use actual implementation) +vi.mock("../../connectors/code-utils", async () => { + return { + replaceOrAddEnvVariable: ( + existingEnvBlob: string, + key: string, + newValue: string, + ): string => { + const lines = existingEnvBlob.split("\n"); + let keyFound = false; + + const updatedLines = lines.map((line) => { + if (line.startsWith(`${key}=`)) { + keyFound = true; + return `${key}=${newValue}`; + } + return line; + }); + + if (!keyFound) { + updatedLines.push(`${key}=${newValue}`); + } + + const newBlob = updatedLines + .filter((line, index) => !(line === "" && index === 0)) + .join("\n") + .trim(); + + return newBlob; + }, + }; +}); + +const mockClient = { + instanceId: "test-instance", +} as unknown as RuntimeClient; + +describe("mergeEnvVars", () => { + let queryClient: any; + + beforeEach(() => { + vi.clearAllMocks(); + queryClient = { + invalidateQueries: vi.fn().mockResolvedValue(undefined), + fetchQuery: vi.fn(), + }; + }); + + it("should merge env vars into existing .env content", async () => { + queryClient.fetchQuery.mockResolvedValue({ + blob: "EXISTING_VAR=existing_value", + }); + + const result = await mergeEnvVars(mockClient, queryClient, { + CLICKHOUSE_PASSWORD: "secret123", + CLICKHOUSE_HOST: "ch.example.com", + }); + + expect(result.originalBlob).toBe("EXISTING_VAR=existing_value"); + expect(result.newBlob).toContain("EXISTING_VAR=existing_value"); + expect(result.newBlob).toContain("CLICKHOUSE_PASSWORD=secret123"); + expect(result.newBlob).toContain("CLICKHOUSE_HOST=ch.example.com"); + }); + + it("should handle empty .env file", async () => { + queryClient.fetchQuery.mockResolvedValue({ blob: "" }); + + const result = await mergeEnvVars(mockClient, queryClient, { + S3_ACCESS_KEY: "AKID123", + }); + + expect(result.originalBlob).toBe(""); + expect(result.newBlob).toContain("S3_ACCESS_KEY=AKID123"); + }); + + it("should handle .env file not found", async () => { + queryClient.fetchQuery.mockRejectedValue( + new Error("open .env: no such file or directory"), + ); + + const result = await mergeEnvVars(mockClient, queryClient, { + NEW_VAR: "new_value", + }); + + expect(result.originalBlob).toBe(""); + expect(result.newBlob).toContain("NEW_VAR=new_value"); + }); + + it("should update existing env var values", async () => { + queryClient.fetchQuery.mockResolvedValue({ + blob: "CLICKHOUSE_PASSWORD=old_secret", + }); + + const result = await mergeEnvVars(mockClient, queryClient, { + CLICKHOUSE_PASSWORD: "new_secret", + }); + + expect(result.newBlob).toContain("CLICKHOUSE_PASSWORD=new_secret"); + expect(result.newBlob).not.toContain("old_secret"); + }); + + it("should handle empty envVars map", async () => { + queryClient.fetchQuery.mockResolvedValue({ + blob: "EXISTING=value", + }); + + const result = await mergeEnvVars(mockClient, queryClient, {}); + + expect(result.originalBlob).toBe("EXISTING=value"); + expect(result.newBlob).toBe("EXISTING=value"); + }); + + it("should skip entries with empty keys or values", async () => { + queryClient.fetchQuery.mockResolvedValue({ blob: "" }); + + const result = await mergeEnvVars(mockClient, queryClient, { + "": "no_key", + VALID_KEY: "", + REAL_KEY: "real_value", + }); + + expect(result.newBlob).toContain("REAL_KEY=real_value"); + expect(result.newBlob).not.toContain("no_key"); + expect(result.newBlob).not.toContain("VALID_KEY"); + }); + + it("should invalidate query cache before fetching", async () => { + queryClient.fetchQuery.mockResolvedValue({ blob: "" }); + + await mergeEnvVars(mockClient, queryClient, { KEY: "value" }); + + expect(queryClient.invalidateQueries).toHaveBeenCalledBefore( + queryClient.fetchQuery, + ); + }); + + it("should re-throw non-file-not-found errors", async () => { + const error = new Error("network error"); + queryClient.fetchQuery.mockRejectedValue(error); + + await expect( + mergeEnvVars(mockClient, queryClient, { KEY: "value" }), + ).rejects.toThrow("network error"); + }); + + it("should handle suffixed env var names from backend", async () => { + queryClient.fetchQuery.mockResolvedValue({ + blob: "CLICKHOUSE_PASSWORD=first_secret", + }); + + // Backend already resolved the conflict and returned _1 suffix + const result = await mergeEnvVars(mockClient, queryClient, { + CLICKHOUSE_PASSWORD_1: "second_secret", + }); + + expect(result.newBlob).toContain("CLICKHOUSE_PASSWORD=first_secret"); + expect(result.newBlob).toContain("CLICKHOUSE_PASSWORD_1=second_secret"); + }); +}); diff --git a/web-common/src/features/sources/modal/generate-template.ts b/web-common/src/features/sources/modal/generate-template.ts new file mode 100644 index 00000000000..dfeb06be1b5 --- /dev/null +++ b/web-common/src/features/sources/modal/generate-template.ts @@ -0,0 +1,120 @@ +import type { QueryClient } from "@tanstack/query-core"; +import { + getRuntimeServiceGetFileQueryKey, + runtimeServiceGenerateFile, + runtimeServiceGetFile, +} from "../../../runtime-client/v2/gen/runtime-service"; +import type { RuntimeClient } from "../../../runtime-client/v2"; +import { replaceOrAddEnvVariable } from "../../connectors/code-utils"; +import { OLAP_ENGINES } from "./constants"; + +const OLAP_SET = new Set(OLAP_ENGINES); + +// OLAP per instance, populated by createConnectorSchemas() when schemas load. +// Avoids a redundant GetInstance call on first generateTemplate invocation. +const olapCache = new Map(); + +/** Set the cached OLAP value for an instance. Called by connector-schemas.ts. */ +export function setOlapCache(instanceId: string, olap: string) { + olapCache.set(instanceId, olap); +} + +/** + * Resolve the template name from (driver, olap). + * OLAP engine connectors have standalone templates (e.g., "clickhouse"). + * Source connectors use combined templates (e.g., "s3-duckdb", "athena-duckdb") + * regardless of whether we're rendering the connector or model output. + */ +function resolveTemplateName(driver: string, olap: string): string { + if (OLAP_SET.has(driver)) return driver; + return `${driver}-${olap}`; +} + +/** + * Call the GenerateFile RPC to produce YAML + env var names from + * structured form data. The backend handles rewrites, env var + * naming/conflict resolution, and YAML formatting via declarative templates. + * + * Uses preview mode so the server renders without writing files; + * the caller handles file writing and reconciliation. + */ +export async function generateTemplate( + client: RuntimeClient, + opts: { + resourceType: string; + driver: string; + properties: Record; + connectorName?: string; + }, +): Promise<{ blob: string; envVars: Record }> { + // Resolve OLAP from cache (populated by createConnectorSchemas on modal open). + // Falls back to "duckdb" if the cache is empty (shouldn't happen in normal flow). + const olap = OLAP_SET.has(opts.driver) + ? opts.driver + : (olapCache.get(client.instanceId) ?? "duckdb"); + + const templateName = resolveTemplateName(opts.driver, olap); + + const response = await runtimeServiceGenerateFile(client, { + templateName, + output: opts.resourceType, + properties: opts.properties, + connectorName: opts.connectorName, + preview: true, + }); + + // Flatten to match the interface callers expect + return { + blob: response.files?.[0]?.blob ?? "", + envVars: response.envVars ?? {}, + }; +} + +/** + * Merge env vars returned by GenerateFile into the existing `.env` file. + * The backend already resolved names and conflict suffixes, so this is + * a straight key=value merge. + * + * Returns the updated blob and the original blob (for rollback). + */ +export async function mergeEnvVars( + client: RuntimeClient, + queryClient: QueryClient, + envVars: Record, +): Promise<{ newBlob: string; originalBlob: string }> { + // Invalidate cache to get fresh .env content + await queryClient.invalidateQueries({ + queryKey: getRuntimeServiceGetFileQueryKey(client.instanceId, { + path: ".env", + }), + }); + + let blob: string; + let originalBlob: string; + try { + const file = await queryClient.fetchQuery({ + queryKey: getRuntimeServiceGetFileQueryKey(client.instanceId, { + path: ".env", + }), + queryFn: () => runtimeServiceGetFile(client, { path: ".env" }), + }); + blob = file.blob || ""; + originalBlob = blob; + } catch (error) { + const msg = + (error as any)?.message ?? (error as any)?.response?.data?.message ?? ""; + if (msg.includes("no such file")) { + blob = ""; + originalBlob = ""; + } else { + throw error; + } + } + + for (const [key, value] of Object.entries(envVars)) { + if (!key || !value) continue; + blob = replaceOrAddEnvVariable(blob, key, value); + } + + return { newBlob: blob, originalBlob }; +} diff --git a/web-common/src/features/sources/modal/icons.ts b/web-common/src/features/sources/modal/icons.ts index 6b6c5eb5c6d..850fe5a28e0 100644 --- a/web-common/src/features/sources/modal/icons.ts +++ b/web-common/src/features/sources/modal/icons.ts @@ -3,6 +3,8 @@ import AmazonRedshift from "@rilldata/web-common/components/icons/connectors/Ama import MySQL from "@rilldata/web-common/components/icons/connectors/MySQL.svelte"; import AmazonS3 from "../../../components/icons/connectors/AmazonS3.svelte"; import ApacheDruid from "../../../components/icons/connectors/ApacheDruid.svelte"; +import ApacheHudi from "../../../components/icons/connectors/ApacheHudi.svelte"; +import ApacheKafka from "../../../components/icons/connectors/ApacheKafka.svelte"; import ApachePinot from "../../../components/icons/connectors/ApachePinot.svelte"; import ClickHouse from "../../../components/icons/connectors/ClickHouse.svelte"; import DuckDB from "../../../components/icons/connectors/DuckDB.svelte"; @@ -41,6 +43,8 @@ export const ICONS = { https: Https, clickhouse: ClickHouse, druid: ApacheDruid, + hudi: ApacheHudi, + kafka: ApacheKafka, pinot: ApachePinot, starrocks: StarRocks, supabase: Supabase, diff --git a/web-common/src/features/sources/modal/submitAddDataForm.ts b/web-common/src/features/sources/modal/submitAddDataForm.ts index fa809007cc9..aa5c02ab2bd 100644 --- a/web-common/src/features/sources/modal/submitAddDataForm.ts +++ b/web-common/src/features/sources/modal/submitAddDataForm.ts @@ -15,8 +15,6 @@ import { } from "../../../runtime-client"; import type { RuntimeClient } from "../../../runtime-client/v2"; import { - compileConnectorYAML, - updateDotEnvWithSecrets, updateRillYAMLWithAiConnector, updateRillYAMLWithOlapConnector, } from "../../connectors/code-utils"; @@ -31,15 +29,9 @@ import { ResourceKind } from "../../entity-management/resource-selectors"; import { EntityType } from "../../entity-management/types"; import { EMPTY_PROJECT_TITLE } from "../../welcome/constants"; import { isProjectInitialized } from "../../welcome/is-project-initialized"; -import { compileSourceYAML, prepareSourceFormData } from "../sourceUtils"; -import { AI_CONNECTORS, OLAP_ENGINES } from "./constants"; import { sourceIngestionTracker } from "../sources-store"; -import { getConnectorSchema } from "./connector-schemas"; -import { - getSchemaFieldMetaList, - getSchemaSecretKeys, - getSchemaStringKeys, -} from "../../templates/schema-utils"; +import { AI_CONNECTORS, OLAP_ENGINES } from "./constants"; +import { generateTemplate, mergeEnvVars } from "./generate-template"; interface AddDataFormValues { // name: string; // Commenting out until we add user-provided names for Connectors @@ -160,19 +152,8 @@ async function saveConnectorWithoutTest( formValues: AddDataFormValues, newConnectorName: string, client: RuntimeClient, - existingEnvBlob?: string, + _existingEnvBlob?: string, ): Promise { - const schema = getConnectorSchema(connector.name ?? ""); - const schemaFields = schema - ? getSchemaFieldMetaList(schema, { step: "connector" }) - : []; - const schemaSecretKeys = schema - ? getSchemaSecretKeys(schema, { step: "connector" }) - : []; - const schemaStringKeys = schema - ? getSchemaStringKeys(schema, { step: "connector" }) - : []; - // Create connector file const newConnectorFilePath = getFileAPIPathFromNameAndType( newConnectorName, @@ -182,15 +163,16 @@ async function saveConnectorWithoutTest( // Mark to avoid rollback by concurrent submissions savedWithoutTestPaths.add(newConnectorFilePath); - // Update .env file with secrets (keep ordering consistent with Test and Connect). - // When existingEnvBlob is provided (e.g. Save overriding an in-flight Test and Connect), - // use it as the baseline so env var names stay consistent and don't get _1 suffixes. - const { newBlob: newEnvBlob, originalBlob: envBlobForYaml } = - await updateDotEnvWithSecrets(client, queryClient, connector, formValues, { - secretKeys: schemaSecretKeys, - schema: schema ?? undefined, - existingEnvBlob: existingEnvBlob, - }); + const templateResponse = await generateTemplate(client, { + resourceType: "connector", + driver: connector.name as string, + properties: formValues, + }); + const { newBlob: newEnvBlob } = await mergeEnvVars( + client, + queryClient, + templateResponse.envVars ?? {}, + ); await runtimeServicePutFile(client, { path: ".env", @@ -199,20 +181,9 @@ async function saveConnectorWithoutTest( createOnly: false, }); - // Always create/overwrite to ensure the connector file is created immediately await runtimeServicePutFile(client, { path: newConnectorFilePath, - blob: compileConnectorYAML(connector, formValues, { - connectorInstanceName: newConnectorName, - orderedProperties: schemaFields, - secretKeys: schemaSecretKeys, - stringKeys: schemaStringKeys, - schema: schema ?? undefined, - existingEnvBlob: envBlobForYaml, - fieldFilter: schemaFields - ? (property) => !("internal" in property && property.internal) - : undefined, - }), + blob: templateResponse.blob ?? "", create: true, createOnly: false, }); @@ -238,16 +209,6 @@ export async function submitAddConnectorForm( existingEnvBlob?: string, ): Promise { await beforeSubmitForm(client, connector); - const schema = getConnectorSchema(connector.name ?? ""); - const schemaFields = schema - ? getSchemaFieldMetaList(schema, { step: "connector" }) - : []; - const schemaSecretKeys = schema - ? getSchemaSecretKeys(schema, { step: "connector" }) - : []; - const schemaStringKeys = schema - ? getSchemaStringKeys(schema, { step: "connector" }) - : []; // Create a unique key for this connector submission const uniqueConnectorSubmissionKey = `${client.instanceId}:${connector.name}`; @@ -312,20 +273,19 @@ export async function submitAddConnectorForm( throw new Error("Operation cancelled"); } - // Capture original .env and compute updated contents up front - // Use originalBlob from updateDotEnvWithSecrets for consistent conflict detection - const envResult = await updateDotEnvWithSecrets( + const templateResponse = await generateTemplate(client, { + resourceType: "connector", + driver: connector.name as string, + properties: formValues, + }); + const envResult = await mergeEnvVars( client, queryClient, - connector, - formValues, - { - secretKeys: schemaSecretKeys, - schema: schema ?? undefined, - }, + templateResponse.envVars ?? {}, ); const newEnvBlob = envResult.newBlob; originalEnvBlob = envResult.originalBlob; + const connectorYamlBlob = templateResponse.blob ?? ""; if (saveAnyway) { // Save: bypass reconciliation entirely via centralized helper @@ -356,17 +316,7 @@ export async function submitAddConnectorForm( await runtimeServicePutFile(client, { path: newConnectorFilePath, - blob: compileConnectorYAML(connector, formValues, { - connectorInstanceName: newConnectorName, - orderedProperties: schemaFields, - secretKeys: schemaSecretKeys, - stringKeys: schemaStringKeys, - schema: schema ?? undefined, - existingEnvBlob: originalEnvBlob, - fieldFilter: schemaFields - ? (property) => !("internal" in property && property.internal) - : undefined, - }), + blob: connectorYamlBlob, create: true, createOnly: false, }); @@ -453,27 +403,15 @@ export async function submitAddSourceForm( await beforeSubmitForm(client, connector); const newSourceName = formValues.name as string; - const [rewrittenConnector, rewrittenFormValues] = prepareSourceFormData( - connector, - formValues, - { connectorInstanceName }, - ); - const schema = getConnectorSchema(rewrittenConnector.name ?? ""); - const schemaSecretKeys = schema - ? getSchemaSecretKeys(schema, { step: "source" }) - : []; - const schemaStringKeys = schema - ? getSchemaStringKeys(schema, { step: "source" }) - : []; - - // When connector is rewritten to DuckDB (e.g., S3 -> DuckDB), don't use - // the original connectorInstanceName in YAML. The original connector is - // referenced via create_secrets_from_connectors for credential access. - const isRewrittenToDuckDb = - rewrittenConnector.name === "duckdb" && connector.name !== "duckdb"; - const yamlConnectorInstanceName = isRewrittenToDuckDb - ? undefined - : connectorInstanceName; + // Use the GenerateTemplate RPC; backend handles DuckDB rewrite and env var naming + const templateResponse = await generateTemplate(client, { + resourceType: "model", + driver: connector.name as string, + properties: formValues, + connectorName: connectorInstanceName || (connector.name as string), + }); + const { newBlob: newEnvBlob, originalBlob: originalEnvBlob } = + await mergeEnvVars(client, queryClient, templateResponse.envVars ?? {}); // Create model YAML file const newSourceFilePath = getFileAPIPathFromNameAndType( @@ -483,29 +421,12 @@ export async function submitAddSourceForm( sourceIngestionTracker.trackPending(`/${newSourceFilePath}`); await runtimeServicePutFile(client, { path: newSourceFilePath, - blob: compileSourceYAML(rewrittenConnector, rewrittenFormValues, { - secretKeys: schemaSecretKeys, - stringKeys: schemaStringKeys, - connectorInstanceName: yamlConnectorInstanceName, - originalDriverName: connector.name || undefined, - }), + blob: templateResponse.blob ?? "", create: true, createOnly: false, }); - // Create or update the `.env` file - const { newBlob: newEnvBlob, originalBlob: originalEnvBlob } = - await updateDotEnvWithSecrets( - client, - queryClient, - rewrittenConnector, - rewrittenFormValues, - { - secretKeys: schemaSecretKeys, - }, - ); - - // Make sure the file has reconciled before testing the connection + // Make sure the .env file has reconciled before testing the connection await runtimeServicePutFileAndWaitForReconciliation(client, { path: ".env", blob: newEnvBlob, diff --git a/web-common/src/features/sources/modal/utils.spec.ts b/web-common/src/features/sources/modal/utils.spec.ts new file mode 100644 index 00000000000..55b17b9d918 --- /dev/null +++ b/web-common/src/features/sources/modal/utils.spec.ts @@ -0,0 +1,127 @@ +import { describe, it, expect } from "vitest"; +import { normalizeConnectorError } from "./utils"; + +describe("normalizeConnectorError", () => { + it("should handle standard Error instance", () => { + const error = new Error("connection refused"); + const result = normalizeConnectorError("postgres", error); + expect(result.message).toBe("connection refused"); + expect(result.details).toBeUndefined(); + }); + + it("should handle Error with details (from waitForResourceReconciliation)", () => { + const error = new Error("Resource configuration failed to reconcile"); + (error as any).details = + 'failed to connect to "host=localhost user=postgres database=postgres": connection refused'; + + // submitAddConnectorForm re-throws as a plain object with { message, details } + const rethrown = { + message: error.message, + details: (error as any).details, + }; + const result = normalizeConnectorError("postgres", rethrown); + + expect(result.message).toBe("Resource configuration failed to reconcile"); + expect(result.details).toBe( + 'failed to connect to "host=localhost user=postgres database=postgres": connection refused', + ); + }); + + it("should handle error with HTTP response data", () => { + const error = { + response: { + data: { + message: 'unknown property "bad_prop" for driver', + code: 3, // InvalidArgument + }, + }, + }; + const result = normalizeConnectorError("postgres", error); + + // Postgres is not in connectorErrorMap, so it gets the generic template + expect(result.message).toContain("postgres"); + expect(result.details).toBe('unknown property "bad_prop" for driver'); + }); + + it("should handle plain object with message only", () => { + const error = { message: "Unable to establish a connection" }; + const result = normalizeConnectorError("postgres", error); + expect(result.message).toBe("Unable to establish a connection"); + expect(result.details).toBeUndefined(); + }); + + it("should handle plain object with same message and details", () => { + const error = { + message: "connection refused", + details: "connection refused", + }; + const result = normalizeConnectorError("postgres", error); + expect(result.message).toBe("connection refused"); + // details should be undefined when same as message + expect(result.details).toBeUndefined(); + }); + + it("should handle unknown error types", () => { + const result = normalizeConnectorError("postgres", 42); + expect(result.message).toBe("Unknown error"); + expect(result.details).toBeUndefined(); + }); + + it("should handle null error", () => { + const result = normalizeConnectorError("postgres", null); + expect(result.message).toBe("Unknown error"); + }); + + it("should handle string error", () => { + // Strings don't match any of the type guards (not Error, not object with response, not object with message) + const result = normalizeConnectorError("postgres", "some error"); + expect(result.message).toBe("Unknown error"); + }); + + it("should use humanReadableErrorMessage for ClickHouse connection errors", () => { + const error = { + response: { + data: { + message: "connection refused to host:9000", + code: 2, // Unknown gRPC code + }, + }, + }; + const result = normalizeConnectorError("clickhouse", error); + + // ClickHouse has custom error mapping for "connection refused" + expect(result.message).toContain("Could not connect to ClickHouse"); + // Details should have the original message since humanReadable differs + expect(result.details).toBe("connection refused to host:9000"); + }); + + it("should handle GenerateTemplate RPC validation error", () => { + const error = { + response: { + data: { + message: 'unknown property "connection_mode" for driver', + code: 3, // InvalidArgument + }, + }, + }; + const result = normalizeConnectorError("postgres", error); + + expect(result.message).toBeTruthy(); + // The details should include the original error + expect(result.details).toBe( + 'unknown property "connection_mode" for driver', + ); + }); + + it("should handle reconciliation error that was auto-deleted", () => { + const error = new Error( + "Resource configuration failed to reconcile and was automatically deleted. This usually indicates a connection or configuration error.", + ); + const result = normalizeConnectorError("postgres", error); + + expect(result.message).toBe( + "Resource configuration failed to reconcile and was automatically deleted. This usually indicates a connection or configuration error.", + ); + expect(result.details).toBeUndefined(); + }); +}); diff --git a/web-common/src/features/templates/JSONSchemaFormRenderer.svelte b/web-common/src/features/templates/JSONSchemaFormRenderer.svelte index 9e050955aca..e8ff071cfc0 100644 --- a/web-common/src/features/templates/JSONSchemaFormRenderer.svelte +++ b/web-common/src/features/templates/JSONSchemaFormRenderer.svelte @@ -181,10 +181,23 @@ values: Record, ) { const properties = currentSchema.properties ?? {}; - return Object.entries(properties).filter(([key]) => { + const entries = Object.entries(properties).filter(([key]) => { if (!isStepMatch(currentSchema, key, currentStep)) return false; return isVisibleForValues(currentSchema, key, values); }); + + // Sort by x-property-order to preserve the JSON-defined field ordering + // (protobuf Struct deserialization does not guarantee key order). + const order = currentSchema["x-property-order"] as string[] | undefined; + if (order) { + const orderMap = new Map(order.map((key, i) => [key, i])); + entries.sort( + ([a], [b]) => + (orderMap.get(a) ?? Infinity) - (orderMap.get(b) ?? Infinity), + ); + } + + return entries; } function matchesCondition( diff --git a/web-common/src/features/templates/schemas/types.ts b/web-common/src/features/templates/schemas/types.ts index 059d592fc7f..93f84779802 100644 --- a/web-common/src/features/templates/schemas/types.ts +++ b/web-common/src/features/templates/schemas/types.ts @@ -122,6 +122,7 @@ export type ConnectorCategory = | "objectStore" | "fileStore" | "warehouse" + | "sourceOnly" | "ai"; export type ButtonLabels = { @@ -168,6 +169,10 @@ export type JSONSchemaObject = { * Example: { "connector_type": { "rill-managed": { idle: "Connect", loading: "Connecting..." } } } */ "x-button-labels"?: Record>; + /** Full-size icon name (resolved to a Svelte component by ICON_COMPONENTS registry). */ + "x-icon"?: string; + /** Small icon name (resolved to a Svelte component by ICON_COMPONENTS registry). */ + "x-small-icon"?: string; }; export type MultiStepFormSchema = JSONSchemaObject; diff --git a/web-common/src/proto/gen/rill/runtime/v1/api_connect.ts b/web-common/src/proto/gen/rill/runtime/v1/api_connect.ts index a4d010842f9..d818ba4c39e 100644 --- a/web-common/src/proto/gen/rill/runtime/v1/api_connect.ts +++ b/web-common/src/proto/gen/rill/runtime/v1/api_connect.ts @@ -3,7 +3,7 @@ /* eslint-disable */ // @ts-nocheck -import { AnalyzeConnectorsRequest, AnalyzeConnectorsResponse, AnalyzeVariablesRequest, AnalyzeVariablesResponse, CompleteRequest, CompleteResponse, CompleteStreamingRequest, CompleteStreamingResponse, CreateDirectoryRequest, CreateDirectoryResponse, CreateInstanceRequest, CreateInstanceResponse, CreateTriggerRequest, CreateTriggerResponse, DeleteFileRequest, DeleteFileResponse, DeleteInstanceRequest, DeleteInstanceResponse, EditInstanceRequest, EditInstanceResponse, ForkConversationRequest, ForkConversationResponse, GenerateCanvasFileRequest, GenerateCanvasFileResponse, GenerateMetricsViewFileRequest, GenerateMetricsViewFileResponse, GetAIMessageRequest, GetAIMessageResponse, GetConversationRequest, GetConversationResponse, GetExploreRequest, GetExploreResponse, GetFileRequest, GetFileResponse, GetInstanceRequest, GetInstanceResponse, GetLogsRequest, GetLogsResponse, GetModelPartitionsRequest, GetModelPartitionsResponse, GetResourceRequest, GetResourceResponse, GitCommitRequest, GitCommitResponse, GitMergeToBranchRequest, GitMergeToBranchResponse, GitPullRequest, GitPullResponse, GitPushRequest, GitPushResponse, GitStatusRequest, GitStatusResponse, GitSwitchBranchRequest, GitSwitchBranchResponse, HealthRequest, HealthResponse, InstanceHealthRequest, InstanceHealthResponse, IssueDevJWTRequest, IssueDevJWTResponse, ListConnectorDriversRequest, ListConnectorDriversResponse, ListConversationsRequest, ListConversationsResponse, ListExamplesRequest, ListExamplesResponse, ListFilesRequest, ListFilesResponse, ListGitBranchesRequest, ListGitBranchesResponse, ListGitCommitsRequest, ListGitCommitsResponse, ListInstancesRequest, ListInstancesResponse, ListNotifierConnectorsRequest, ListNotifierConnectorsResponse, ListResourcesRequest, ListResourcesResponse, ListToolsRequest, ListToolsResponse, PingRequest, PingResponse, PutFileRequest, PutFileResponse, QueryResolverRequest, QueryResolverResponse, ReloadConfigRequest, ReloadConfigResponse, RenameFileRequest, RenameFileResponse, RestoreGitCommitRequest, RestoreGitCommitResponse, ShareConversationRequest, ShareConversationResponse, UnpackEmptyRequest, UnpackEmptyResponse, UnpackExampleRequest, UnpackExampleResponse, WatchFilesRequest, WatchFilesResponse, WatchLogsRequest, WatchLogsResponse, WatchResourcesRequest, WatchResourcesResponse } from "./api_pb.js"; +import { AnalyzeConnectorsRequest, AnalyzeConnectorsResponse, AnalyzeVariablesRequest, AnalyzeVariablesResponse, CompleteRequest, CompleteResponse, CompleteStreamingRequest, CompleteStreamingResponse, CreateDirectoryRequest, CreateDirectoryResponse, CreateInstanceRequest, CreateInstanceResponse, CreateTriggerRequest, CreateTriggerResponse, DeleteFileRequest, DeleteFileResponse, DeleteInstanceRequest, DeleteInstanceResponse, EditInstanceRequest, EditInstanceResponse, ForkConversationRequest, ForkConversationResponse, GenerateCanvasFileRequest, GenerateCanvasFileResponse, GenerateFileRequest, GenerateFileResponse, GenerateMetricsViewFileRequest, GenerateMetricsViewFileResponse, GenerateTemplateRequest, GenerateTemplateResponse, GetAIMessageRequest, GetAIMessageResponse, GetConversationRequest, GetConversationResponse, GetExploreRequest, GetExploreResponse, GetFileRequest, GetFileResponse, GetInstanceRequest, GetInstanceResponse, GetLogsRequest, GetLogsResponse, GetModelPartitionsRequest, GetModelPartitionsResponse, GetResourceRequest, GetResourceResponse, GitCommitRequest, GitCommitResponse, GitMergeToBranchRequest, GitMergeToBranchResponse, GitPullRequest, GitPullResponse, GitPushRequest, GitPushResponse, GitStatusRequest, GitStatusResponse, GitSwitchBranchRequest, GitSwitchBranchResponse, HealthRequest, HealthResponse, InstanceHealthRequest, InstanceHealthResponse, IssueDevJWTRequest, IssueDevJWTResponse, ListConnectorDriversRequest, ListConnectorDriversResponse, ListConversationsRequest, ListConversationsResponse, ListExamplesRequest, ListExamplesResponse, ListFilesRequest, ListFilesResponse, ListGitBranchesRequest, ListGitBranchesResponse, ListGitCommitsRequest, ListGitCommitsResponse, ListInstancesRequest, ListInstancesResponse, ListNotifierConnectorsRequest, ListNotifierConnectorsResponse, ListResourcesRequest, ListResourcesResponse, ListTemplatesRequest, ListTemplatesResponse, ListToolsRequest, ListToolsResponse, PingRequest, PingResponse, PutFileRequest, PutFileResponse, QueryResolverRequest, QueryResolverResponse, ReloadConfigRequest, ReloadConfigResponse, RenameFileRequest, RenameFileResponse, RestoreGitCommitRequest, RestoreGitCommitResponse, ShareConversationRequest, ShareConversationResponse, UnpackEmptyRequest, UnpackEmptyResponse, UnpackExampleRequest, UnpackExampleResponse, WatchFilesRequest, WatchFilesResponse, WatchLogsRequest, WatchLogsResponse, WatchResourcesRequest, WatchResourcesResponse } from "./api_pb.js"; import { MethodKind } from "@bufbuild/protobuf"; /** @@ -248,6 +248,39 @@ export const RuntimeService = { O: GenerateCanvasFileResponse, kind: MethodKind.Unary, }, + /** + * GenerateTemplate generates a connector or model YAML file from structured form data + * + * @generated from rpc rill.runtime.v1.RuntimeService.GenerateTemplate + */ + generateTemplate: { + name: "GenerateTemplate", + I: GenerateTemplateRequest, + O: GenerateTemplateResponse, + kind: MethodKind.Unary, + }, + /** + * ListTemplates returns available template definitions for generating project files + * + * @generated from rpc rill.runtime.v1.RuntimeService.ListTemplates + */ + listTemplates: { + name: "ListTemplates", + I: ListTemplatesRequest, + O: ListTemplatesResponse, + kind: MethodKind.Unary, + }, + /** + * GenerateFile renders a template with properties and optionally writes the resulting files + * + * @generated from rpc rill.runtime.v1.RuntimeService.GenerateFile + */ + generateFile: { + name: "GenerateFile", + I: GenerateFileRequest, + O: GenerateFileResponse, + kind: MethodKind.Unary, + }, /** * QueryResolver queries a resolver with the given properties and arguments * diff --git a/web-common/src/proto/gen/rill/runtime/v1/api_pb.ts b/web-common/src/proto/gen/rill/runtime/v1/api_pb.ts index 09ea474dde6..2f3c2f7da1c 100644 --- a/web-common/src/proto/gen/rill/runtime/v1/api_pb.ts +++ b/web-common/src/proto/gen/rill/runtime/v1/api_pb.ts @@ -2432,6 +2432,519 @@ export class GenerateCanvasFileResponse extends Message$1 { + /** + * @generated from field: string instance_id = 1; + */ + instanceId = ""; + + /** + * @generated from field: string resource_type = 2; + */ + resourceType = ""; + + /** + * @generated from field: string driver = 3; + */ + driver = ""; + + /** + * @generated from field: google.protobuf.Struct properties = 4; + */ + properties?: Struct; + + /** + * @generated from field: string connector_name = 5; + */ + connectorName = ""; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "rill.runtime.v1.GenerateTemplateRequest"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "instance_id", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 2, name: "resource_type", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 3, name: "driver", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 4, name: "properties", kind: "message", T: Struct }, + { no: 5, name: "connector_name", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): GenerateTemplateRequest { + return new GenerateTemplateRequest().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): GenerateTemplateRequest { + return new GenerateTemplateRequest().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): GenerateTemplateRequest { + return new GenerateTemplateRequest().fromJsonString(jsonString, options); + } + + static equals(a: GenerateTemplateRequest | PlainMessage | undefined, b: GenerateTemplateRequest | PlainMessage | undefined): boolean { + return proto3.util.equals(GenerateTemplateRequest, a, b); + } +} + +/** + * @generated from message rill.runtime.v1.GenerateTemplateResponse + */ +export class GenerateTemplateResponse extends Message$1 { + /** + * @generated from field: string blob = 1; + */ + blob = ""; + + /** + * @generated from field: map env_vars = 2; + */ + envVars: { [key: string]: string } = {}; + + /** + * Actual resource type used; may differ from request when driver is rewritten + * + * @generated from field: string resource_type = 3; + */ + resourceType = ""; + + /** + * Actual driver used; may differ from request when rewritten to duckdb + * + * @generated from field: string driver = 4; + */ + driver = ""; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "rill.runtime.v1.GenerateTemplateResponse"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "blob", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 2, name: "env_vars", kind: "map", K: 9 /* ScalarType.STRING */, V: {kind: "scalar", T: 9 /* ScalarType.STRING */} }, + { no: 3, name: "resource_type", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 4, name: "driver", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): GenerateTemplateResponse { + return new GenerateTemplateResponse().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): GenerateTemplateResponse { + return new GenerateTemplateResponse().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): GenerateTemplateResponse { + return new GenerateTemplateResponse().fromJsonString(jsonString, options); + } + + static equals(a: GenerateTemplateResponse | PlainMessage | undefined, b: GenerateTemplateResponse | PlainMessage | undefined): boolean { + return proto3.util.equals(GenerateTemplateResponse, a, b); + } +} + +/** + * Template describes a declarative template for generating project files. + * + * @generated from message rill.runtime.v1.Template + */ +export class Template extends Message$1