diff --git a/protos/sift/artifacts/v1/artifacts.proto b/protos/sift/artifacts/v1/artifacts.proto new file mode 100644 index 000000000..610fb2635 --- /dev/null +++ b/protos/sift/artifacts/v1/artifacts.proto @@ -0,0 +1,246 @@ +syntax = "proto3"; + +package sift.artifacts.v1; + +import "google/api/annotations.proto"; +import "protoc-gen-openapiv2/options/annotations.proto"; +import "google/protobuf/timestamp.proto"; + +option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = { + info: {title: "Artifact Service"} +}; + +// ArtifactService manages artifacts: independent, org-scoped, versioned +// documents. An artifact is not owned by a conversation. A conversation may +// reference an artifact through a link, any number of conversations may link +// the same artifact, and an artifact may exist with no link at all (for +// example, created over MCP outside an agent session). +// +// The service carries artifact metadata only. Version bytes live in +// remote_files (entity_type 'artifact_versions', entity_id = +// artifact_version_id): upload via the remote-files multipart endpoint, +// download via RemoteFileService.GetRemoteFileDownloadUrl. +service ArtifactService { + // Creates an artifact plus its version-1 row, or appends a version when + // artifact_id is set. When conversation_id is set on create, the new + // artifact is also linked to that conversation. + rpc CreateArtifact(CreateArtifactRequest) returns (CreateArtifactResponse) { + option (google.api.http) = { + post: "/api/v1/artifacts" + body: "*" + }; + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + summary: "CreateArtifact" + description: "Create a new artifact or append a version to an existing one." + operation_id: "ArtifactService_CreateArtifactV1" + }; + } + + // Resolves to the latest version unless artifact_version_id pins one. + rpc GetArtifact(GetArtifactRequest) returns (GetArtifactResponse) { + option (google.api.http) = {get: "/api/v1/artifacts/{artifact_id}"}; + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + summary: "GetArtifact" + description: "Get one artifact, resolved to the latest version unless artifact_version_id pins one." + operation_id: "ArtifactService_GetArtifactV1" + }; + } + + // One entry per artifact, resolved to its latest version, oldest first. + // With conversation_id set, only artifacts linked to that conversation; + // otherwise every artifact created by the caller. + rpc ListArtifacts(ListArtifactsRequest) returns (ListArtifactsResponse) { + option (google.api.http) = {get: "/api/v1/artifacts"}; + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + summary: "ListArtifacts" + description: "List artifacts created by the caller, optionally filtered to one conversation." + operation_id: "ArtifactService_ListArtifactsV1" + }; + } + + // Full version history of one artifact, newest first. + rpc ListArtifactVersions(ListArtifactVersionsRequest) returns (ListArtifactVersionsResponse) { + option (google.api.http) = {get: "/api/v1/artifacts/{artifact_id}/versions"}; + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + summary: "ListArtifactVersions" + description: "List the version history of one artifact, newest first." + operation_id: "ArtifactService_ListArtifactVersionsV1" + }; + } + + // Links an existing artifact to a conversation. Idempotent: linking an + // already-linked pair succeeds without effect. + rpc LinkArtifactToConversation(LinkArtifactToConversationRequest) returns (LinkArtifactToConversationResponse) { + option (google.api.http) = { + post: "/api/v1/artifacts/{artifact_id}/conversations/{conversation_id}:link" + }; + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + summary: "LinkArtifactToConversation" + description: "Link an existing artifact to a conversation." + operation_id: "ArtifactService_LinkArtifactToConversationV1" + }; + } + + // Removes one conversation's link to an artifact. The artifact itself is + // untouched. Idempotent: unlinking a missing link succeeds. + rpc UnlinkArtifactFromConversation(UnlinkArtifactFromConversationRequest) returns (UnlinkArtifactFromConversationResponse) { + option (google.api.http) = { + post: "/api/v1/artifacts/{artifact_id}/conversations/{conversation_id}:unlink" + }; + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + summary: "UnlinkArtifactFromConversation" + description: "Remove a conversation's link to an artifact." + operation_id: "ArtifactService_UnlinkArtifactFromConversationV1" + }; + } + + // Sets archived_date. Versions, stored bytes, and conversation links are + // left in place. Idempotent: archiving an already-archived artifact + // succeeds without changing archived_date. + rpc ArchiveArtifact(ArchiveArtifactRequest) returns (ArchiveArtifactResponse) { + option (google.api.http) = {post: "/api/v1/artifacts/{artifact_id}/archive"}; + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + summary: "ArchiveArtifact" + description: "Archive an artifact. Versions, stored bytes, and conversation links are left in place." + operation_id: "ArtifactService_ArchiveArtifactV1" + }; + } + + // Clears archived_date. Idempotent: unarchiving an active artifact + // succeeds without effect. + rpc UnarchiveArtifact(UnarchiveArtifactRequest) returns (UnarchiveArtifactResponse) { + option (google.api.http) = {post: "/api/v1/artifacts/{artifact_id}/unarchive"}; + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + summary: "UnarchiveArtifact" + description: "Unarchive an artifact." + operation_id: "ArtifactService_UnarchiveArtifactV1" + }; + } +} + +enum ArtifactAuthoringKind { + ARTIFACT_AUTHORING_KIND_UNSPECIFIED = 0; + ARTIFACT_AUTHORING_KIND_AGENT = 1; + ARTIFACT_AUTHORING_KIND_USER = 2; +} + +// Container fields flattened together with one resolved version. +message Artifact { + string artifact_id = 1; + string organization_id = 2; + string created_by_user_id = 3; + ArtifactAuthoringKind authoring_kind = 5; + google.protobuf.Timestamp created_date = 6; + string artifact_version_id = 7; + uint32 version = 8; + optional string title = 9; + optional string summary = 10; + // Set only for versions authored inside a conversation, and there only + // after the introducing message persists: uploads attach before the user + // sends, and agent turns persist messages only at end of turn. + optional string authoring_message_id = 11; + repeated string source_tool_use_ids = 12; + // Unset until bytes are uploaded. + optional string remote_file_id = 13; + google.protobuf.Timestamp version_created_date = 14; + // From the version's remote_files row. Unset until bytes are uploaded. + // Clients infer preview behavior from file_name / file_mime_type. + optional string file_name = 15; + optional string file_mime_type = 16; + // Unset while the artifact is active. + optional google.protobuf.Timestamp archived_date = 17; +} + +message ArtifactVersion { + string artifact_version_id = 1; + string artifact_id = 2; + uint32 version = 3; + optional string title = 4; + optional string summary = 5; + optional string authoring_message_id = 6; + repeated string source_tool_use_ids = 7; + optional string remote_file_id = 8; + google.protobuf.Timestamp created_date = 9; + // From the version's remote_files row. Unset until bytes are uploaded. + optional string file_name = 10; + optional string file_mime_type = 11; +} + +message CreateArtifactRequest { + // Set to append a version to an existing artifact; unset to create one. + optional string artifact_id = 1; + // Set to link the new artifact to a conversation at create time. Legal + // only on create (not on append), and only for the conversation's author. + optional string conversation_id = 2; + optional string title = 4; + optional string summary = 5; + // Defaults to USER. AGENT is self-reported: the agent pod authenticates + // with the requesting user's transient key, so until scoped pod + // credentials land (ENG-12831) authorship attribution rides on the same + // trust as the pod's message persistence path. + optional ArtifactAuthoringKind authoring_kind = 6; +} + +message CreateArtifactResponse { + Artifact artifact = 1; +} + +message GetArtifactRequest { + string artifact_id = 1; + optional string artifact_version_id = 2; +} + +message GetArtifactResponse { + Artifact artifact = 1; +} + +message ListArtifactsRequest { + // Unset lists every artifact created by the caller. + optional string conversation_id = 1; + uint32 page_size = 2; + string page_token = 3; + // When false (the default), archived artifacts are omitted. + bool include_archived = 4; +} + +message ListArtifactsResponse { + repeated Artifact artifacts = 1; + string next_page_token = 2; +} + +message ListArtifactVersionsRequest { + string artifact_id = 1; + uint32 page_size = 2; + string page_token = 3; +} + +message ListArtifactVersionsResponse { + repeated ArtifactVersion versions = 1; + string next_page_token = 2; +} + +message LinkArtifactToConversationRequest { + string artifact_id = 1; + string conversation_id = 2; +} + +message LinkArtifactToConversationResponse {} + +message UnlinkArtifactFromConversationRequest { + string artifact_id = 1; + string conversation_id = 2; +} + +message UnlinkArtifactFromConversationResponse {} + +message ArchiveArtifactRequest { + string artifact_id = 1; +} + +message ArchiveArtifactResponse {} + +message UnarchiveArtifactRequest { + string artifact_id = 1; +} + +message UnarchiveArtifactResponse {} diff --git a/rust/crates/sift_cli/CHANGELOG.md b/rust/crates/sift_cli/CHANGELOG.md index 76c49453c..4e2ffd922 100644 --- a/rust/crates/sift_cli/CHANGELOG.md +++ b/rust/crates/sift_cli/CHANGELOG.md @@ -7,6 +7,14 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### What's New +- Added artifact MCP tools: `list_artifacts`, `download_artifact`, and + `create_artifact`, backed by public `sift.artifacts.v1.ArtifactService`. + `create_artifact` writes artifact metadata (and can link a new artifact to a + conversation). Creating requires `--allow-create`; appending a version to an + existing artifact also requires `--allow-destructive`. `download_artifact` returns + a `download_url` when the version has uploaded bytes and fails instead of + returning a partial artifact when that URL cannot be minted. These tools are + enabled per account by the agents feature flag, resolved at server startup. - Some MCP tools are now enabled per account by feature flags resolved at server startup. A tool absent from the tool list needs its account flag enabled and an MCP restart. diff --git a/rust/crates/sift_cli/assets/skills/sift/SKILL.md b/rust/crates/sift_cli/assets/skills/sift/SKILL.md index aa42a10bb..af38f1286 100644 --- a/rust/crates/sift_cli/assets/skills/sift/SKILL.md +++ b/rust/crates/sift_cli/assets/skills/sift/SKILL.md @@ -53,7 +53,13 @@ exists. started with `--disable-update-check` omit this tool. `ping` is a connectivity check; when it fails, expect every other Sift tool to fail too. - **Discovery:** `list_assets`, `list_runs`, `list_channels`, `list_reports`, - `list_report_templates`, `list_rules`, `list_rule_versions`, `list_annotations`. + `list_report_templates`, `list_rules`, `list_rule_versions`, `list_annotations`, + `list_artifacts`. +- **Artifacts:** `download_artifact` (latest version, or pin `artifact_version_id`). + The artifact tools, including `list_artifacts` and the `create_artifact` + write below, are enabled per account by the agents feature flag resolved when + the MCP server starts, so they may be absent from the tool list. Enabling + them requires an account setting and an MCP restart. - **Derived channels:** `list_calculated_channels`, `list_calculated_channel_versions`, `list_user_defined_functions`, `list_user_defined_function_versions`. @@ -81,7 +87,7 @@ exists. `create_user_defined_function`, `update_user_defined_function`, `archive_user_defined_function`, `unarchive_user_defined_function`, `create_test_report`, `append_test_measurements`, `update_asset`, - `update_run`. + `update_run`, `create_artifact`. ## Workflows that span tools @@ -134,6 +140,13 @@ exists. Send a rename on its own. The API applies a `name` change by itself and ignores every other field, so `update_user_defined_function` rejects `name` combined with anything else. +- **Create an artifact.** `create_artifact` with a `title` / `summary`. + Pass `conversation_id` to link it to a chat, and `authoring_kind=agent` when + a Sift agent produced it. Append a version by passing the existing + `artifact_id`. Creating is gated by `--allow-create`; appending a version to + an existing artifact also needs `--allow-destructive`. Discover artifacts + with `list_artifacts` (oldest first, no `order_by`); fetch a version or its + `download_url` with `download_artifact`. - **Produce a chart.** Build a link with `explore_url`. When the user wants a chart and numbers, do both and give the user both. - **Answer a question about how Sift works.** Call `search_docs`. Do not answer diff --git a/rust/crates/sift_mcp/src/feature_flags.rs b/rust/crates/sift_mcp/src/feature_flags.rs index cfe14d1ea..7cebd2664 100644 --- a/rust/crates/sift_mcp/src/feature_flags.rs +++ b/rust/crates/sift_mcp/src/feature_flags.rs @@ -14,6 +14,9 @@ pub(crate) static TOOL_FEATURE_FLAGS: &[(&str, &str)] = &[ ("count_test_measurements", "test-reports"), ("create_test_report", "test-reports"), ("append_test_measurements", "test-reports"), + ("list_artifacts", "chat-agents-service"), + ("download_artifact", "chat-agents-service"), + ("create_artifact", "chat-agents-service"), ]; #[derive(Clone, Debug, Default, Deserialize)] diff --git a/rust/crates/sift_mcp/src/server/mod.rs b/rust/crates/sift_mcp/src/server/mod.rs index 2dfe4c118..902629cdc 100644 --- a/rust/crates/sift_mcp/src/server/mod.rs +++ b/rust/crates/sift_mcp/src/server/mod.rs @@ -39,13 +39,13 @@ pub(crate) const BASE_INSTRUCTIONS: &str = concat!( "rules: fields at their default value (false, 0, empty string/list) are ", "omitted, so a missing boolean key means false, not unknown." ); -use crate::service::test_reports::TestReportService; use crate::service::{ - annotations::AnnotationService, assets::AssetService, + annotations::AnnotationService, artifacts::ArtifactService, assets::AssetService, calculated_channels::CalculatedChannelService, channels::ChannelService, data::DataService, docs::DocsService, ingest::IngestService, ping::PingService, report_templates::ReportTemplateService, reports::ReportService, - rule_evaluation::RuleEvaluationService, rules::RuleService, runs::RunService, url::UrlService, + rule_evaluation::RuleEvaluationService, rules::RuleService, runs::RunService, + test_reports::TestReportService, url::UrlService, user_defined_functions::UserDefinedFunctionService, users::UserService, }; @@ -55,6 +55,7 @@ pub struct SiftMcpServer { pub prompt_router: PromptRouter, pub annotation_service: AnnotationService, + pub artifact_service: ArtifactService, pub asset_service: AssetService, pub calculated_channel_service: CalculatedChannelService, pub channel_service: ChannelService, @@ -197,6 +198,7 @@ impl SiftMcpServer { tool_router.merge(Self::rules_router()); tool_router.merge(Self::rule_evaluation_router()); tool_router.merge(Self::annotations_router()); + tool_router.merge(Self::artifacts_router()); tool_router.merge(Self::test_reports_router()); tool_router.merge(Self::docs_router()); tool_router.merge(Self::user_defined_functions_router()); @@ -215,6 +217,7 @@ impl SiftMcpServer { let retry_policy = RetryPolicy::default(); let annotation_service = AnnotationService::new(channel.clone(), retry_policy.clone()); + let artifact_service = ArtifactService::new(channel.clone(), retry_policy.clone()); let asset_service = AssetService::new(channel.clone(), retry_policy.clone()); let calculated_channel_service = CalculatedChannelService::new(channel.clone(), retry_policy.clone()); @@ -238,6 +241,7 @@ impl SiftMcpServer { Self { annotation_service, + artifact_service, asset_service, calculated_channel_service, channel_service, diff --git a/rust/crates/sift_mcp/src/server/test.rs b/rust/crates/sift_mcp/src/server/test.rs index 881df4b69..ca03f41dd 100644 --- a/rust/crates/sift_mcp/src/server/test.rs +++ b/rust/crates/sift_mcp/src/server/test.rs @@ -173,6 +173,27 @@ async fn feature_flag_gates_test_report_tools() { enabled_handle.abort(); } +#[tokio::test] +async fn each_feature_flag_gates_only_its_own_tools() { + for &(_, flag) in TOOL_FEATURE_FLAGS { + let flags: FeatureFlags = + serde_json::from_value(serde_json::json!({ "variants": { flag: { "value": "on" } } })) + .unwrap(); + let (server, handle) = + server_with_feature_flags(None, 0, ClientEventReporter::default(), flags).await; + let routed = server.tool_router.list_all(); + for &(tool_name, tool_flag) in TOOL_FEATURE_FLAGS { + let is_routed = routed.iter().any(|tool| tool.name == tool_name); + assert_eq!( + is_routed, + tool_flag == flag, + "with only `{flag}` enabled, `{tool_name}` routed = {is_routed}" + ); + } + handle.abort(); + } +} + async fn initialized_client_with_feature_flags( feature_flags: FeatureFlags, ) -> ( diff --git a/rust/crates/sift_mcp/src/service/artifacts/mod.rs b/rust/crates/sift_mcp/src/service/artifacts/mod.rs new file mode 100644 index 000000000..02a6cd225 --- /dev/null +++ b/rust/crates/sift_mcp/src/service/artifacts/mod.rs @@ -0,0 +1,206 @@ +use anyhow::{Context, Result, anyhow, bail}; +use serde::Serialize; +use sift_rs::{ + SiftChannel, + artifacts::v1::{ + Artifact, ArtifactAuthoringKind, CreateArtifactRequest, GetArtifactRequest, + ListArtifactsRequest, ListArtifactsResponse, + artifact_service_client::ArtifactServiceClient, + }, + remote_files::v1::{ + GetRemoteFileDownloadUrlRequest, remote_file_service_client::RemoteFileServiceClient, + }, +}; + +use crate::policy::{RetryPolicy, with_retry}; +use crate::service::common; + +#[cfg(test)] +mod test; + +#[derive(Clone, Debug, Serialize)] +pub struct ArtifactView { + #[serde(flatten)] + pub inner: Artifact, + #[serde(skip_serializing_if = "Option::is_none")] + pub download_url: Option, +} + +#[derive(Clone)] +pub struct ArtifactService { + channel: SiftChannel, + policy: RetryPolicy, +} + +impl ArtifactService { + pub fn new(channel: SiftChannel, policy: RetryPolicy) -> Self { + Self { channel, policy } + } + + pub async fn list_artifacts( + &self, + conversation_id: Option, + include_archived: bool, + limit: Option, + ) -> Result> { + let (page_size, record_limit) = common::paging(limit); + let mut page_token = String::new(); + let mut results = Vec::new(); + let mut has_more = false; + + loop { + let channel = self.channel.clone(); + let conversation_id = conversation_id.clone(); + let token = page_token.clone(); + + let resp = with_retry(&self.policy, move || { + let channel = channel.clone(); + let conversation_id = conversation_id.clone(); + let token = token.clone(); + async move { + let mut client = ArtifactServiceClient::new(channel); + client + .list_artifacts(ListArtifactsRequest { + conversation_id, + page_size, + page_token: token, + include_archived, + }) + .await + .map(|resp| resp.into_inner()) + } + }) + .await + .context("failed to query artifacts")?; + + let ListArtifactsResponse { + artifacts, + next_page_token, + } = resp; + if artifacts.is_empty() { + break; + } + results.extend(artifacts); + if results.len() >= record_limit { + has_more = results.len() > record_limit || !next_page_token.is_empty(); + break; + } + if next_page_token.is_empty() { + break; + } + page_token = next_page_token; + } + + results.truncate(record_limit); + Ok(common::Page { + items: results, + has_more, + }) + } + + pub async fn download_artifact( + &self, + artifact_id: String, + artifact_version_id: Option, + ) -> Result { + let artifact = self.get_artifact(artifact_id, artifact_version_id).await?; + let download_url = match artifact.remote_file_id.clone() { + Some(remote_file_id) => Some(self.download_url(remote_file_id).await?), + None => None, + }; + Ok(ArtifactView { + inner: artifact, + download_url, + }) + } + + pub async fn create_artifact( + &self, + title: Option, + summary: Option, + conversation_id: Option, + artifact_id: Option, + authoring_kind: ArtifactAuthoringKind, + ) -> Result { + let channel = self.channel.clone(); + let created = with_retry(&self.policy, move || { + let channel = channel.clone(); + let artifact_id = artifact_id.clone(); + let conversation_id = conversation_id.clone(); + let title = title.clone(); + let summary = summary.clone(); + async move { + let mut client = ArtifactServiceClient::new(channel); + client + .create_artifact(CreateArtifactRequest { + artifact_id, + conversation_id, + title, + summary, + authoring_kind: Some(authoring_kind as i32), + }) + .await + .map(|resp| resp.into_inner()) + } + }) + .await + .context("failed to create artifact")? + .artifact + .ok_or_else(|| anyhow!("create artifact response missing artifact"))?; + + Ok(ArtifactView { + inner: created, + download_url: None, + }) + } + + async fn get_artifact( + &self, + artifact_id: String, + artifact_version_id: Option, + ) -> Result { + let channel = self.channel.clone(); + with_retry(&self.policy, move || { + let channel = channel.clone(); + let artifact_id = artifact_id.clone(); + let artifact_version_id = artifact_version_id.clone(); + async move { + let mut client = ArtifactServiceClient::new(channel); + client + .get_artifact(GetArtifactRequest { + artifact_id, + artifact_version_id, + }) + .await + .map(|resp| resp.into_inner()) + } + }) + .await + .context("failed to get artifact")? + .artifact + .ok_or_else(|| anyhow!("get artifact response missing artifact")) + } + + async fn download_url(&self, remote_file_id: String) -> Result { + let channel = self.channel.clone(); + let resp = with_retry(&self.policy, move || { + let channel = channel.clone(); + let remote_file_id = remote_file_id.clone(); + async move { + let mut client = RemoteFileServiceClient::new(channel); + client + .get_remote_file_download_url(GetRemoteFileDownloadUrlRequest { + remote_file_id, + }) + .await + .map(|resp| resp.into_inner()) + } + }) + .await + .context("failed to get artifact download url")?; + if resp.download_url.is_empty() { + bail!("download url response was empty"); + } + Ok(resp.download_url) + } +} diff --git a/rust/crates/sift_mcp/src/service/artifacts/test.rs b/rust/crates/sift_mcp/src/service/artifacts/test.rs new file mode 100644 index 000000000..6e89594d6 --- /dev/null +++ b/rust/crates/sift_mcp/src/service/artifacts/test.rs @@ -0,0 +1,344 @@ +use sift_rs::{ + artifacts::v1::{ + Artifact, ArtifactAuthoringKind, CreateArtifactResponse, GetArtifactResponse, + ListArtifactsResponse, artifact_service_server::ArtifactServiceServer, + }, + remote_files::v1::{ + GetRemoteFileDownloadUrlResponse, remote_file_service_server::RemoteFileServiceServer, + }, +}; +use sift_test_util::{ + grpc::memory_sift_channel, + mock::{artifacts::v1::MockArtifactServiceImpl, remote_files::v1::MockRemoteFileServiceImpl}, +}; +use tokio::task::JoinHandle; +use tonic::{Code, Response, Status, transport::Server}; + +use super::ArtifactService; +use crate::policy::RetryPolicy; + +fn sample_artifact() -> Artifact { + Artifact { + artifact_id: "art-1".into(), + organization_id: "org-1".into(), + created_by_user_id: "user-1".into(), + authoring_kind: ArtifactAuthoringKind::Agent as i32, + artifact_version_id: "ver-1".into(), + version: 1, + title: Some("report".into()), + file_name: Some("report.md".into()), + file_mime_type: Some("text/markdown".into()), + ..Default::default() + } +} + +async fn service_with_mock(mock: MockArtifactServiceImpl) -> (ArtifactService, JoinHandle<()>) { + service_with_mocks(mock, MockRemoteFileServiceImpl::new()).await +} + +async fn service_with_mocks( + artifacts: MockArtifactServiceImpl, + remote_files: MockRemoteFileServiceImpl, +) -> (ArtifactService, JoinHandle<()>) { + let (client, server) = tokio::io::duplex(1024); + let channel = memory_sift_channel(client).await; + + let handle = tokio::spawn(async move { + Server::builder() + .add_service(ArtifactServiceServer::new(artifacts)) + .add_service(RemoteFileServiceServer::new(remote_files)) + .serve_with_incoming(tokio_stream::once(Ok::<_, std::io::Error>(server))) + .await + .unwrap(); + }); + + ( + ArtifactService::new(channel, RetryPolicy::default()), + handle, + ) +} + +#[tokio::test] +async fn list_artifacts_returns_single_page() { + let mut mock = MockArtifactServiceImpl::new(); + mock.expect_list_artifacts() + .withf(|req| req.get_ref().conversation_id.as_deref() == Some("conv-1")) + .returning(|_| { + Ok(Response::new(ListArtifactsResponse { + artifacts: vec![sample_artifact()], + next_page_token: String::new(), + })) + }); + + let (service, _h) = service_with_mock(mock).await; + let page = service + .list_artifacts(Some("conv-1".into()), false, None) + .await + .expect("list"); + assert_eq!(page.items.len(), 1); + assert_eq!(page.items[0].artifact_id, "art-1"); + assert!(!page.has_more); +} + +#[tokio::test] +async fn list_artifacts_paginates_until_token_empty() { + let mut mock = MockArtifactServiceImpl::new(); + mock.expect_list_artifacts().returning(|req| { + let req = req.into_inner(); + assert_eq!(req.page_size, 200); + let (artifacts, next) = match req.page_token.as_str() { + "" => ( + vec![Artifact { + artifact_id: "a1".into(), + artifact_version_id: "v1".into(), + version: 1, + ..Default::default() + }], + "50".to_string(), + ), + "50" => ( + vec![Artifact { + artifact_id: "a2".into(), + artifact_version_id: "v2".into(), + version: 1, + ..Default::default() + }], + String::new(), + ), + other => return Err(Status::invalid_argument(format!("bad token: {other}"))), + }; + Ok(Response::new(ListArtifactsResponse { + artifacts, + next_page_token: next, + })) + }); + + let (service, _h) = service_with_mock(mock).await; + let page = service + .list_artifacts(None, false, Some(200)) + .await + .expect("list"); + assert_eq!( + page.items + .iter() + .map(|a| a.artifact_id.as_str()) + .collect::>(), + ["a1", "a2"] + ); + assert!(!page.has_more); +} + +#[tokio::test] +async fn list_artifacts_limit_truncates() { + let mut mock = MockArtifactServiceImpl::new(); + mock.expect_list_artifacts().returning(|_| { + Ok(Response::new(ListArtifactsResponse { + artifacts: vec![ + Artifact { + artifact_id: "a1".into(), + ..Default::default() + }, + Artifact { + artifact_id: "a2".into(), + ..Default::default() + }, + Artifact { + artifact_id: "a3".into(), + ..Default::default() + }, + ], + next_page_token: String::new(), + })) + }); + + let (service, _h) = service_with_mock(mock).await; + let page = service + .list_artifacts(None, false, Some(2)) + .await + .expect("list"); + assert_eq!(page.items.len(), 2); + assert!(page.has_more); +} + +#[tokio::test] +async fn list_artifacts_propagates_not_found() { + let mut mock = MockArtifactServiceImpl::new(); + mock.expect_list_artifacts() + .returning(|_| Err(Status::not_found("conversation not found"))); + + let (service, _h) = service_with_mock(mock).await; + let err = service + .list_artifacts(Some("missing".into()), false, None) + .await + .expect_err("expected error"); + let status = err.downcast_ref::().expect("status"); + assert_eq!(status.code(), Code::NotFound); +} + +#[tokio::test] +async fn download_artifact_returns_latest() { + let mut mock = MockArtifactServiceImpl::new(); + mock.expect_get_artifact() + .withf(|req| { + let req = req.get_ref(); + req.artifact_id == "art-1" && req.artifact_version_id.is_none() + }) + .returning(|_| { + Ok(Response::new(GetArtifactResponse { + artifact: Some(sample_artifact()), + })) + }); + + let (service, _h) = service_with_mock(mock).await; + let artifact = service + .download_artifact("art-1".into(), None) + .await + .expect("get"); + assert_eq!(artifact.inner.artifact_id, "art-1"); + assert_eq!(artifact.inner.version, 1); + assert!(artifact.download_url.is_none()); +} + +fn uploaded_artifact() -> Artifact { + Artifact { + remote_file_id: Some("rf-1".into()), + ..sample_artifact() + } +} + +fn get_returns_uploaded() -> MockArtifactServiceImpl { + let mut mock = MockArtifactServiceImpl::new(); + mock.expect_get_artifact().returning(|_| { + Ok(Response::new(GetArtifactResponse { + artifact: Some(uploaded_artifact()), + })) + }); + mock +} + +#[tokio::test] +async fn download_artifact_attaches_download_url_when_bytes_uploaded() { + let mut remote_files = MockRemoteFileServiceImpl::new(); + remote_files + .expect_get_remote_file_download_url() + .withf(|req| req.get_ref().remote_file_id == "rf-1") + .times(1) + .returning(|_| { + Ok(Response::new(GetRemoteFileDownloadUrlResponse { + download_url: "https://files.test.local/rf-1?sig=abc".into(), + })) + }); + + let (service, _h) = service_with_mocks(get_returns_uploaded(), remote_files).await; + let artifact = service + .download_artifact("art-1".into(), None) + .await + .expect("get"); + assert_eq!(artifact.inner.remote_file_id.as_deref(), Some("rf-1")); + assert_eq!( + artifact.download_url.as_deref(), + Some("https://files.test.local/rf-1?sig=abc") + ); +} + +#[tokio::test] +async fn download_artifact_propagates_download_url_error() { + let mut remote_files = MockRemoteFileServiceImpl::new(); + remote_files + .expect_get_remote_file_download_url() + .returning(|_| Err(Status::permission_denied("no access to remote file"))); + + let (service, _h) = service_with_mocks(get_returns_uploaded(), remote_files).await; + let err = service + .download_artifact("art-1".into(), None) + .await + .expect_err("download url failure must not be swallowed"); + let status = err.downcast_ref::().expect("status"); + assert_eq!(status.code(), Code::PermissionDenied); +} + +#[tokio::test] +async fn download_artifact_rejects_empty_download_url() { + let mut remote_files = MockRemoteFileServiceImpl::new(); + remote_files + .expect_get_remote_file_download_url() + .returning(|_| { + Ok(Response::new(GetRemoteFileDownloadUrlResponse { + download_url: String::new(), + })) + }); + + let (service, _h) = service_with_mocks(get_returns_uploaded(), remote_files).await; + let err = service + .download_artifact("art-1".into(), None) + .await + .expect_err("empty url is an error"); + assert!(err.to_string().contains("download url response was empty")); +} + +#[test] +fn artifact_view_serializes_flat_with_snake_case_download_url() { + let with_url = super::ArtifactView { + inner: uploaded_artifact(), + download_url: Some("https://files.test.local/rf-1".into()), + }; + let value = serde_json::to_value(&with_url).expect("serialize"); + assert_eq!(value["artifactId"], "art-1"); + assert_eq!(value["remoteFileId"], "rf-1"); + assert_eq!(value["download_url"], "https://files.test.local/rf-1"); + assert!(value.get("downloadUrl").is_none()); + assert!(value.get("inner").is_none()); + + let without_url = super::ArtifactView { + inner: sample_artifact(), + download_url: None, + }; + let value = serde_json::to_value(&without_url).expect("serialize"); + assert_eq!(value["artifactId"], "art-1"); + assert!(value.get("download_url").is_none()); +} + +#[test] +fn artifact_view_serialization_error_propagates() { + let unknown_kind = super::ArtifactView { + inner: Artifact { + authoring_kind: 999, + ..sample_artifact() + }, + download_url: None, + }; + let err = serde_json::to_value(&unknown_kind).expect_err("unknown enum variant is an error"); + assert!(err.to_string().contains("999"), "{err}"); +} + +#[tokio::test] +async fn create_artifact_returns_created_row() { + let mut mock = MockArtifactServiceImpl::new(); + mock.expect_create_artifact() + .withf(|req| { + let req = req.get_ref(); + req.conversation_id.as_deref() == Some("conv-1") + && req.title.as_deref() == Some("report") + && req.summary.as_deref() == Some("summary") + && req.authoring_kind == Some(ArtifactAuthoringKind::Agent as i32) + }) + .returning(|_| { + Ok(Response::new(CreateArtifactResponse { + artifact: Some(sample_artifact()), + })) + }); + + let (service, _h) = service_with_mock(mock).await; + let artifact = service + .create_artifact( + Some("report".into()), + Some("summary".into()), + Some("conv-1".into()), + None, + ArtifactAuthoringKind::Agent, + ) + .await + .expect("create"); + assert_eq!(artifact.inner.artifact_id, "art-1"); + assert_eq!(artifact.inner.version, 1); +} diff --git a/rust/crates/sift_mcp/src/service/mod.rs b/rust/crates/sift_mcp/src/service/mod.rs index d61fedc02..c603531a2 100644 --- a/rust/crates/sift_mcp/src/service/mod.rs +++ b/rust/crates/sift_mcp/src/service/mod.rs @@ -1,4 +1,5 @@ pub mod annotations; +pub mod artifacts; pub mod assets; pub mod calculated_channels; pub mod channels; diff --git a/rust/crates/sift_mcp/src/tool/artifacts/mod.rs b/rust/crates/sift_mcp/src/tool/artifacts/mod.rs new file mode 100644 index 000000000..25df75e39 --- /dev/null +++ b/rust/crates/sift_mcp/src/tool/artifacts/mod.rs @@ -0,0 +1,324 @@ +use rmcp::{ + ErrorData, + handler::server::wrapper::Parameters, + model::{CallToolResult, ContentBlock}, + schemars::{self, JsonSchema}, + tool, tool_router, +}; +use serde::Deserialize; +use sift_rs::artifacts::v1::ArtifactAuthoringKind; + +use crate::{ + error::{self, from_anyhow}, + server::SiftMcpServer, + tool::common::{list_body, to_values}, +}; + +#[cfg(test)] +mod test; + +#[derive(Debug, Deserialize, JsonSchema)] +pub struct ArtifactListParams { + conversation_id: Option, + include_archived: Option, + limit: Option, + fields: Option>, +} + +#[derive(Debug, Deserialize, JsonSchema)] +pub struct DownloadArtifactParams { + artifact_id: String, + artifact_version_id: Option, +} + +#[derive(Debug, Deserialize, JsonSchema)] +pub struct CreateArtifactParams { + title: Option, + summary: Option, + conversation_id: Option, + artifact_id: Option, + authoring_kind: Option, +} + +/// Also accepts the proto enum names so an agent can echo a value it read from `list_artifacts`. +fn parse_authoring_kind(value: Option) -> Result { + let lowered = value + .as_deref() + .map(str::trim) + .unwrap_or("user") + .to_ascii_lowercase(); + match lowered.as_str() { + "" | "user" | "artifact_authoring_kind_user" => Ok(ArtifactAuthoringKind::User), + "agent" | "artifact_authoring_kind_agent" => Ok(ArtifactAuthoringKind::Agent), + other => Err(ErrorData::invalid_params( + format!("unknown `authoring_kind` `{other}`; expected `user` or `agent`"), + None, + )), + } +} + +#[tool_router(router = artifacts_router, vis = "pub(crate)")] +impl SiftMcpServer { + #[tool( + name = "list_artifacts", + description = " + List artifacts created by the caller, optionally restricted to those linked to one conversation. + + Artifacts are first-class versioned documents. Each list entry is the latest version of one + artifact. Bytes are not returned; use `download_artifact` for a download URL when a version has + uploaded files. + + Results are returned oldest first. There is no `order_by` or `filter`, so when `has_more` is + still `true` at `limit: 200`, the newest artifacts are not reachable from an unscoped + listing; scope with `conversation_id` instead. + + Output: + - `{ \"artifacts\": [Artifact, ...] }`. Each item includes `artifact_id`, `artifact_version_id`, + `version`, `title`, `summary`, `authoring_kind`, `file_name`, `file_mime_type`, `remote_file_id`, + `created_date`, and `archived_date` when set. + - `count`: how many items THIS response carries — read it instead of + counting the array yourself. It is the size of the page you got back, not + how many artifacts the caller has. + - `has_more`: `true` when the service hit `limit` with matches left over, so + this page is not the whole set. Never report `count` as a total while + `has_more` is `true` — raise `limit` or scope with `conversation_id` and ask again. + Because results are oldest first, a capped page holds the oldest artifacts, not + the newest. + + Parameters: + - `conversation_id`: optional. When set, only artifacts linked to that conversation. When omitted, + every artifact the caller created. + - `include_archived`: optional. Default `false` omits archived artifacts. Set `true` only when the + user asks for archived ones. + - `limit`: max items to return. Start at 50 and only raise it if the result is capped + and you still need more. Values are clamped to `1..=200`; omitting it defaults to 50. + - `fields`: optional array of field names to keep on each item, e.g. + `[\"title\"]`. Omit it for the full object. Names match case-insensitively + and ignore underscores and hyphens, so `artifact_id`, `artifactId` and + `artifact-id` all work. Any name that matched nothing on any returned item + is listed in `unmatched_fields`; an empty page reports none, since it + says nothing about whether a name was spelled right. + Reach for this whenever you need only a few fields: full objects are wide, + and a large listing can exceed the response size limit without it. + + Errors: + - `INVALID_PARAMS` if `conversation_id` is empty when set. + - `RESOURCE_NOT_FOUND` if `conversation_id` does not exist or is not visible to the caller. + - `INTERNAL_ERROR` for upstream failures. + + Guidance: + - Prefer scoping by `conversation_id` when the user is talking about one chat. + - This list has no CEL `filter`; narrow with `conversation_id` or follow up with `download_artifact`. + ", + annotations(title = "artifacts/list_artifacts", read_only_hint = true) + )] + pub async fn list_artifacts(&self, params: Parameters) -> error::McpResult { + let Parameters(ArtifactListParams { + conversation_id, + include_archived, + limit, + fields, + }) = params; + + if let Some(id) = conversation_id.as_deref() + && id.trim().is_empty() + { + return Err(ErrorData::invalid_params( + "`conversation_id` must not be empty when set", + None, + )); + } + + let page = self + .artifact_service + .list_artifacts(conversation_id, include_archived.unwrap_or(false), limit) + .await + .map_err(from_anyhow)?; + + let artifacts = to_values(&page.items)?; + + Ok(CallToolResult::structured(list_body( + "artifacts", + artifacts, + fields, + page.has_more, + ))) + } + + #[tool( + name = "download_artifact", + description = " + Get one artifact by `artifact_id`, resolved to the latest version unless `artifact_version_id` pins one. + + Output: + - `{ \"artifact\": Artifact }`. Same chrome as `list_artifacts`, plus `download_url` when the + version has uploaded bytes (`remote_file_id` is set). `download_url` is a short-lived signed + URL; fetch it only when the user needs the body. When `remote_file_id` is absent, the version + has no uploaded bytes and `download_url` is omitted. + + Parameters: + - `artifact_id`: required stable container id. + - `artifact_version_id`: optional pin. Omit to get the latest version. + + Errors: + - `INVALID_PARAMS` if `artifact_id` is empty, or `artifact_version_id` is empty when set. + - `RESOURCE_NOT_FOUND` if the artifact (or pinned version) does not exist or is not visible to the caller. + - `INTERNAL_ERROR` for upstream failures, including a failure to mint the download URL for a + version that has uploaded bytes. The tool does not return a partial artifact in that case. + + Guidance: + - Use this when you need a specific version or a download URL. Use `list_artifacts` to discover ids. + ", + annotations(title = "artifacts/download_artifact", read_only_hint = true) + )] + pub async fn download_artifact( + &self, + params: Parameters, + ) -> error::McpResult { + let Parameters(DownloadArtifactParams { + artifact_id, + artifact_version_id, + }) = params; + + if artifact_id.trim().is_empty() { + return Err(ErrorData::invalid_params( + "`artifact_id` must not be empty", + None, + )); + } + if let Some(id) = artifact_version_id.as_deref() + && id.trim().is_empty() + { + return Err(ErrorData::invalid_params( + "`artifact_version_id` must not be empty when set", + None, + )); + } + + let artifact = self + .artifact_service + .download_artifact(artifact_id, artifact_version_id) + .await + .map_err(from_anyhow)?; + + Ok(CallToolResult::structured( + serde_json::json!({ "artifact": artifact }), + )) + } + + #[tool( + name = "create_artifact", + description = " + Create a new artifact, or append a version to an existing one. This writes artifact metadata + only; version bytes live in remote_files and are not uploaded by this tool. + + Output: + - `{ \"artifact\": Artifact, \"next_step\": string }`. The returned artifact is the created or + appended version, including `artifact_id`, `artifact_version_id`, and `version`. + + Parameters: + - `title`: optional display title stored on the version. + - `summary`: optional short description stored on the version. + - `conversation_id`: optional. Legal only when creating a new artifact (not when appending). + Links the new artifact to that conversation. The caller must be the conversation's author. + - `artifact_id`: optional. Set to append a new version to an existing artifact. Omit to create + a new artifact. `conversation_id` must be omitted when this is set. + - `authoring_kind`: optional; `user` (default) or `agent`, matched case-insensitively. The + proto names that `list_artifacts` / `download_artifact` emit (`ARTIFACT_AUTHORING_KIND_USER`, + `ARTIFACT_AUTHORING_KIND_AGENT`) are also accepted. Use `agent` when a Sift agent is + producing the artifact during a turn. + + Access: + - Creating a new artifact needs `--allow-create`. + - Appending a version to an existing artifact changes what every linked conversation + resolves to, so it needs `--allow-destructive`. + + Errors: + - `INVALID_PARAMS` if `authoring_kind` is not `user` or `agent`, if `conversation_id` is set + while appending, or if `artifact_id` / `conversation_id` is empty when set. + - `INVALID_REQUEST` if the server was launched without the flag the call needs (see Access). + - `RESOURCE_NOT_FOUND` if the conversation or existing artifact is not visible to the caller. + - `INTERNAL_ERROR` for upstream failures. + + Guidance: + - This is a write. CONFIRM the title and destination conversation with the user before invoking. + - Edits always create a new version; there is no edit-in-place path. + ", + annotations( + title = "artifacts/create_artifact", + read_only_hint = false, + destructive_hint = false, + idempotent_hint = false, + ) + )] + pub async fn create_artifact( + &self, + params: Parameters, + ) -> error::McpResult { + self.require_create()?; + + let Parameters(CreateArtifactParams { + title, + summary, + conversation_id, + artifact_id, + authoring_kind, + }) = params; + + // Appending rewrites what every linked conversation resolves to, so it takes the stronger gate. + if artifact_id.is_some() { + self.require_destructive()?; + } + + if let Some(id) = artifact_id.as_deref() + && id.trim().is_empty() + { + return Err(ErrorData::invalid_params( + "`artifact_id` must not be empty when set", + None, + )); + } + if let Some(id) = conversation_id.as_deref() + && id.trim().is_empty() + { + return Err(ErrorData::invalid_params( + "`conversation_id` must not be empty when set", + None, + )); + } + if artifact_id.is_some() && conversation_id.is_some() { + return Err(ErrorData::invalid_params( + "`conversation_id` is legal only when creating an artifact; omit it when appending a version", + None, + )); + } + + let authoring_kind = parse_authoring_kind(authoring_kind)?; + let appending = artifact_id.is_some(); + let artifact = self + .artifact_service + .create_artifact(title, summary, conversation_id, artifact_id, authoring_kind) + .await + .map_err(from_anyhow)?; + + let next_step = if appending { + format!( + "Appended version {} to artifact {}. Surface the new version to the user and confirm it \ + matches their intent.", + artifact.inner.version, artifact.inner.artifact_id + ) + } else { + format!( + "Created artifact {} version {}. Surface the title and destination to the user and confirm \ + they match their intent before further edits.", + artifact.inner.artifact_id, artifact.inner.version + ) + }; + let mut result = CallToolResult::structured(serde_json::json!({ + "artifact": artifact, + "next_step": next_step, + })); + result.content = vec![ContentBlock::text(next_step)]; + Ok(result) + } +} diff --git a/rust/crates/sift_mcp/src/tool/artifacts/test.rs b/rust/crates/sift_mcp/src/tool/artifacts/test.rs new file mode 100644 index 000000000..5f2d52111 --- /dev/null +++ b/rust/crates/sift_mcp/src/tool/artifacts/test.rs @@ -0,0 +1,373 @@ +use rmcp::{handler::server::wrapper::Parameters, model::ErrorCode}; +use sift_rs::{ + artifacts::v1::{ + Artifact, ArtifactAuthoringKind, CreateArtifactResponse, GetArtifactResponse, + ListArtifactsResponse, artifact_service_server::ArtifactServiceServer, + }, + remote_files::v1::{ + GetRemoteFileDownloadUrlResponse, remote_file_service_server::RemoteFileServiceServer, + }, +}; +use sift_test_util::{ + grpc::memory_sift_channel, + mock::{artifacts::v1::MockArtifactServiceImpl, remote_files::v1::MockRemoteFileServiceImpl}, +}; +use tokio::task::JoinHandle; +use tonic::{Response, Status, transport::Server}; + +use super::{CreateArtifactParams, DownloadArtifactParams}; +use crate::{ + server::SiftMcpServer, + tool::{artifacts::ArtifactListParams, common::test_support::structured_field}, +}; + +fn sample_artifact() -> Artifact { + Artifact { + artifact_id: "art-1".into(), + organization_id: "org-1".into(), + artifact_version_id: "ver-1".into(), + version: 1, + title: Some("report".into()), + authoring_kind: ArtifactAuthoringKind::Agent as i32, + ..Default::default() + } +} + +async fn server_with_mock( + mock: MockArtifactServiceImpl, + allow_create: bool, +) -> (SiftMcpServer, JoinHandle<()>) { + server_with_mocks( + mock, + MockRemoteFileServiceImpl::new(), + allow_create, + allow_create, + ) + .await +} + +async fn server_with_mocks( + artifacts: MockArtifactServiceImpl, + remote_files: MockRemoteFileServiceImpl, + allow_create: bool, + allow_destructive: bool, +) -> (SiftMcpServer, JoinHandle<()>) { + let (client, server) = tokio::io::duplex(1024); + let channel = memory_sift_channel(client).await; + + let handle = tokio::spawn(async move { + Server::builder() + .add_service(ArtifactServiceServer::new(artifacts)) + .add_service(RemoteFileServiceServer::new(remote_files)) + .serve_with_incoming(tokio_stream::once(Ok::<_, std::io::Error>(server))) + .await + .unwrap(); + }); + + ( + SiftMcpServer::new( + channel, + String::from("https://app.test.local"), + allow_create, + allow_destructive, + ), + handle, + ) +} + +fn get_returns(artifact: Artifact) -> MockArtifactServiceImpl { + let mut mock = MockArtifactServiceImpl::new(); + mock.expect_get_artifact().returning(move |_| { + Ok(Response::new(GetArtifactResponse { + artifact: Some(artifact.clone()), + })) + }); + mock +} + +#[tokio::test] +async fn list_artifacts_returns_rows() { + let mut mock = MockArtifactServiceImpl::new(); + mock.expect_list_artifacts().returning(|_| { + Ok(Response::new(ListArtifactsResponse { + artifacts: vec![sample_artifact()], + next_page_token: String::new(), + })) + }); + + let (server, _h) = server_with_mock(mock, true).await; + let resp = server + .list_artifacts(Parameters(ArtifactListParams { + conversation_id: Some("conv-1".into()), + include_archived: None, + limit: None, + fields: None, + })) + .await + .expect("list"); + let artifacts = structured_field(resp, "artifacts"); + assert_eq!(artifacts.as_array().unwrap().len(), 1); + assert_eq!(artifacts[0]["artifactId"], "art-1"); +} + +#[tokio::test] +async fn list_artifacts_rejects_empty_conversation_id() { + let (server, _h) = server_with_mock(MockArtifactServiceImpl::new(), true).await; + let err = server + .list_artifacts(Parameters(ArtifactListParams { + conversation_id: Some(" ".into()), + include_archived: None, + limit: None, + fields: None, + })) + .await + .expect_err("empty conversation"); + assert_eq!(err.code, ErrorCode::INVALID_PARAMS); +} + +#[tokio::test] +async fn get_artifact_rejects_empty_id() { + let (server, _h) = server_with_mock(MockArtifactServiceImpl::new(), true).await; + let err = server + .download_artifact(Parameters(DownloadArtifactParams { + artifact_id: String::new(), + artifact_version_id: None, + })) + .await + .expect_err("empty id"); + assert_eq!(err.code, ErrorCode::INVALID_PARAMS); +} + +#[tokio::test] +async fn get_artifact_returns_snake_case_download_url() { + let uploaded = Artifact { + remote_file_id: Some("rf-1".into()), + ..sample_artifact() + }; + let mut remote_files = MockRemoteFileServiceImpl::new(); + remote_files + .expect_get_remote_file_download_url() + .returning(|_| { + Ok(Response::new(GetRemoteFileDownloadUrlResponse { + download_url: "https://files.test.local/rf-1".into(), + })) + }); + + let (server, _h) = server_with_mocks(get_returns(uploaded), remote_files, false, false).await; + let resp = server + .download_artifact(Parameters(DownloadArtifactParams { + artifact_id: "art-1".into(), + artifact_version_id: None, + })) + .await + .expect("get"); + let artifact = structured_field(resp, "artifact"); + assert_eq!(artifact["artifactId"], "art-1"); + assert_eq!(artifact["download_url"], "https://files.test.local/rf-1"); + assert!(artifact.get("downloadUrl").is_none()); +} + +#[tokio::test] +async fn get_artifact_omits_download_url_without_bytes() { + let (server, _h) = server_with_mock(get_returns(sample_artifact()), false).await; + let resp = server + .download_artifact(Parameters(DownloadArtifactParams { + artifact_id: "art-1".into(), + artifact_version_id: None, + })) + .await + .expect("get"); + let artifact = structured_field(resp, "artifact"); + assert!(artifact.get("download_url").is_none()); +} + +#[tokio::test] +async fn get_artifact_surfaces_download_url_failure() { + let uploaded = Artifact { + remote_file_id: Some("rf-1".into()), + ..sample_artifact() + }; + let mut remote_files = MockRemoteFileServiceImpl::new(); + remote_files + .expect_get_remote_file_download_url() + .returning(|_| Err(Status::not_found("remote file gone"))); + + let (server, _h) = server_with_mocks(get_returns(uploaded), remote_files, false, false).await; + let err = server + .download_artifact(Parameters(DownloadArtifactParams { + artifact_id: "art-1".into(), + artifact_version_id: None, + })) + .await + .expect_err("download failure is an error, not a partial artifact"); + assert_eq!(err.code, ErrorCode::RESOURCE_NOT_FOUND); +} + +#[tokio::test] +async fn create_artifact_blocked_without_allow_create() { + let (server, _h) = server_with_mock(MockArtifactServiceImpl::new(), false).await; + let err = server + .create_artifact(Parameters(CreateArtifactParams { + title: None, + summary: None, + conversation_id: None, + artifact_id: None, + authoring_kind: None, + })) + .await + .expect_err("gated"); + assert_eq!(err.code, ErrorCode::INVALID_REQUEST); + assert!(err.message.contains("--allow-create")); +} + +#[tokio::test] +async fn create_artifact_append_blocked_without_allow_destructive() { + let (server, _h) = server_with_mocks( + MockArtifactServiceImpl::new(), + MockRemoteFileServiceImpl::new(), + true, + false, + ) + .await; + let err = server + .create_artifact(Parameters(CreateArtifactParams { + title: Some("v2".into()), + summary: None, + conversation_id: None, + artifact_id: Some("art-1".into()), + authoring_kind: None, + })) + .await + .expect_err("append gated"); + assert_eq!(err.code, ErrorCode::INVALID_REQUEST); + assert!(err.message.contains("--allow-destructive")); +} + +#[tokio::test] +async fn create_artifact_append_reports_appended_version() { + let mut mock = MockArtifactServiceImpl::new(); + mock.expect_create_artifact() + .withf(|req| { + let req = req.get_ref(); + req.artifact_id.as_deref() == Some("art-1") && req.conversation_id.is_none() + }) + .returning(|_| { + Ok(Response::new(CreateArtifactResponse { + artifact: Some(Artifact { + artifact_version_id: "ver-2".into(), + version: 2, + ..sample_artifact() + }), + })) + }); + + let (server, _h) = server_with_mock(mock, true).await; + let resp = server + .create_artifact(Parameters(CreateArtifactParams { + title: Some("v2".into()), + summary: None, + conversation_id: None, + artifact_id: Some("art-1".into()), + authoring_kind: None, + })) + .await + .expect("append"); + let next_step = structured_field(resp, "next_step"); + let next_step = next_step.as_str().unwrap(); + assert!( + next_step.starts_with("Appended version 2 to artifact art-1"), + "{next_step}" + ); + assert!(!next_step.contains("Created"), "{next_step}"); +} + +#[tokio::test] +async fn create_artifact_accepts_authoring_kind_in_any_case() { + for (input, expected) in [ + ("Agent", ArtifactAuthoringKind::Agent), + ("AGENT", ArtifactAuthoringKind::Agent), + ( + "ARTIFACT_AUTHORING_KIND_AGENT", + ArtifactAuthoringKind::Agent, + ), + ("User", ArtifactAuthoringKind::User), + ("artifact_authoring_kind_user", ArtifactAuthoringKind::User), + ] { + let mut mock = MockArtifactServiceImpl::new(); + mock.expect_create_artifact() + .withf(move |req| req.get_ref().authoring_kind == Some(expected as i32)) + .returning(|_| { + Ok(Response::new(CreateArtifactResponse { + artifact: Some(sample_artifact()), + })) + }); + let (server, _h) = server_with_mock(mock, true).await; + server + .create_artifact(Parameters(CreateArtifactParams { + title: None, + summary: None, + conversation_id: None, + artifact_id: None, + authoring_kind: Some(input.into()), + })) + .await + .unwrap_or_else(|err| panic!("{input}: {err:?}")); + } +} + +#[tokio::test] +async fn create_artifact_rejects_unknown_authoring_kind() { + let (server, _h) = server_with_mock(MockArtifactServiceImpl::new(), true).await; + let err = server + .create_artifact(Parameters(CreateArtifactParams { + title: None, + summary: None, + conversation_id: None, + artifact_id: None, + authoring_kind: Some("robot".into()), + })) + .await + .expect_err("unknown kind"); + assert_eq!(err.code, ErrorCode::INVALID_PARAMS); +} + +#[tokio::test] +async fn create_artifact_rejects_append_with_conversation() { + let (server, _h) = server_with_mock(MockArtifactServiceImpl::new(), true).await; + let err = server + .create_artifact(Parameters(CreateArtifactParams { + title: None, + summary: None, + conversation_id: Some("conv-1".into()), + artifact_id: Some("art-1".into()), + authoring_kind: None, + })) + .await + .expect_err("illegal combo"); + assert_eq!(err.code, ErrorCode::INVALID_PARAMS); +} + +#[tokio::test] +async fn create_artifact_happy_path() { + let mut mock = MockArtifactServiceImpl::new(); + mock.expect_create_artifact().returning(|_| { + Ok(Response::new(CreateArtifactResponse { + artifact: Some(sample_artifact()), + })) + }); + + let (server, _h) = server_with_mock(mock, true).await; + let resp = server + .create_artifact(Parameters(CreateArtifactParams { + title: Some("report".into()), + summary: None, + conversation_id: Some("conv-1".into()), + artifact_id: None, + authoring_kind: Some("agent".into()), + })) + .await + .expect("create"); + let artifact = structured_field(resp, "artifact"); + assert_eq!(artifact["artifactId"], "art-1"); + assert!(artifact.get("download_url").is_none()); +} diff --git a/rust/crates/sift_mcp/src/tool/mod.rs b/rust/crates/sift_mcp/src/tool/mod.rs index 5032b3a57..95e2a3296 100644 --- a/rust/crates/sift_mcp/src/tool/mod.rs +++ b/rust/crates/sift_mcp/src/tool/mod.rs @@ -1,4 +1,5 @@ pub mod annotations; +pub mod artifacts; pub mod assets; pub mod calculated_channels; pub mod channels; diff --git a/rust/crates/sift_mcp/src/tool_events.json b/rust/crates/sift_mcp/src/tool_events.json index 91334fea0..f75da337d 100644 --- a/rust/crates/sift_mcp/src/tool_events.json +++ b/rust/crates/sift_mcp/src/tool_events.json @@ -7,15 +7,18 @@ "count_test_measurements": "CLIENT_EVENT_USER_CALLED_MCP_TOOL_COUNT_TEST_MEASUREMENTS", "count_test_steps": "CLIENT_EVENT_USER_CALLED_MCP_TOOL_COUNT_TEST_STEPS", "create_annotation": "CLIENT_EVENT_USER_CALLED_MCP_TOOL_CREATE_ANNOTATION", + "create_artifact": "CLIENT_EVENT_USER_CALLED_MCP_TOOL_CREATE_ARTIFACT", "create_calculated_channel": "CLIENT_EVENT_USER_CALLED_MCP_TOOL_CREATE_CALCULATED_CHANNEL", "create_report": "CLIENT_EVENT_USER_CALLED_MCP_TOOL_CREATE_REPORT", "create_report_template": "CLIENT_EVENT_USER_CALLED_MCP_TOOL_CREATE_REPORT_TEMPLATE", "create_rule": "CLIENT_EVENT_USER_CALLED_MCP_TOOL_CREATE_RULE", "create_test_report": "CLIENT_EVENT_USER_CALLED_MCP_TOOL_CREATE_TEST_REPORT", "create_user_defined_function": "CLIENT_EVENT_USER_CALLED_MCP_TOOL_CREATE_USER_DEFINED_FUNCTION", + "download_artifact": "CLIENT_EVENT_USER_CALLED_MCP_TOOL_DOWNLOAD_ARTIFACT", "explore_url": "CLIENT_EVENT_USER_CALLED_MCP_TOOL_EXPLORE_URL", "get_data": "CLIENT_EVENT_USER_CALLED_MCP_TOOL_GET_DATA", "list_annotations": "CLIENT_EVENT_USER_CALLED_MCP_TOOL_LIST_ANNOTATIONS", + "list_artifacts": "CLIENT_EVENT_USER_CALLED_MCP_TOOL_LIST_ARTIFACTS", "list_assets": "CLIENT_EVENT_USER_CALLED_MCP_TOOL_LIST_ASSETS", "list_calculated_channel_versions": "CLIENT_EVENT_USER_CALLED_MCP_TOOL_LIST_CALCULATED_CHANNEL_VERSIONS", "list_calculated_channels": "CLIENT_EVENT_USER_CALLED_MCP_TOOL_LIST_CALCULATED_CHANNELS", diff --git a/rust/crates/sift_rs/src/gen/mod.rs b/rust/crates/sift_rs/src/gen/mod.rs index 5116bcf6c..a9f7ca5a7 100644 --- a/rust/crates/sift_rs/src/gen/mod.rs +++ b/rust/crates/sift_rs/src/gen/mod.rs @@ -21,6 +21,13 @@ pub mod sift { // @@protoc_insertion_point(sift.api_keys.v2) } } + pub mod artifacts { + // @@protoc_insertion_point(attribute:sift.artifacts.v1) + pub mod v1 { + include!("sift/artifacts/v1/sift.artifacts.v1.rs"); + // @@protoc_insertion_point(sift.artifacts.v1) + } + } pub mod assets { // @@protoc_insertion_point(attribute:sift.assets.v1) pub mod v1 { diff --git a/rust/crates/sift_rs/src/gen/sift/artifacts/v1/sift.artifacts.v1.rs b/rust/crates/sift_rs/src/gen/sift/artifacts/v1/sift.artifacts.v1.rs new file mode 100644 index 000000000..16fa3710f --- /dev/null +++ b/rust/crates/sift_rs/src/gen/sift/artifacts/v1/sift.artifacts.v1.rs @@ -0,0 +1,1110 @@ +// @generated +// This file is @generated by prost-build. +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct Artifact { + #[prost(string, tag="1")] + pub artifact_id: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub organization_id: ::prost::alloc::string::String, + #[prost(string, tag="3")] + pub created_by_user_id: ::prost::alloc::string::String, + #[prost(enumeration="ArtifactAuthoringKind", tag="5")] + pub authoring_kind: i32, + #[prost(message, optional, tag="6")] + pub created_date: ::core::option::Option<::pbjson_types::Timestamp>, + #[prost(string, tag="7")] + pub artifact_version_id: ::prost::alloc::string::String, + #[prost(uint32, tag="8")] + pub version: u32, + #[prost(string, optional, tag="9")] + pub title: ::core::option::Option<::prost::alloc::string::String>, + #[prost(string, optional, tag="10")] + pub summary: ::core::option::Option<::prost::alloc::string::String>, + #[prost(string, optional, tag="11")] + pub authoring_message_id: ::core::option::Option<::prost::alloc::string::String>, + #[prost(string, repeated, tag="12")] + pub source_tool_use_ids: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + #[prost(string, optional, tag="13")] + pub remote_file_id: ::core::option::Option<::prost::alloc::string::String>, + #[prost(message, optional, tag="14")] + pub version_created_date: ::core::option::Option<::pbjson_types::Timestamp>, + #[prost(string, optional, tag="15")] + pub file_name: ::core::option::Option<::prost::alloc::string::String>, + #[prost(string, optional, tag="16")] + pub file_mime_type: ::core::option::Option<::prost::alloc::string::String>, + #[prost(message, optional, tag="17")] + pub archived_date: ::core::option::Option<::pbjson_types::Timestamp>, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct ArtifactVersion { + #[prost(string, tag="1")] + pub artifact_version_id: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub artifact_id: ::prost::alloc::string::String, + #[prost(uint32, tag="3")] + pub version: u32, + #[prost(string, optional, tag="4")] + pub title: ::core::option::Option<::prost::alloc::string::String>, + #[prost(string, optional, tag="5")] + pub summary: ::core::option::Option<::prost::alloc::string::String>, + #[prost(string, optional, tag="6")] + pub authoring_message_id: ::core::option::Option<::prost::alloc::string::String>, + #[prost(string, repeated, tag="7")] + pub source_tool_use_ids: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + #[prost(string, optional, tag="8")] + pub remote_file_id: ::core::option::Option<::prost::alloc::string::String>, + #[prost(message, optional, tag="9")] + pub created_date: ::core::option::Option<::pbjson_types::Timestamp>, + #[prost(string, optional, tag="10")] + pub file_name: ::core::option::Option<::prost::alloc::string::String>, + #[prost(string, optional, tag="11")] + pub file_mime_type: ::core::option::Option<::prost::alloc::string::String>, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct CreateArtifactRequest { + #[prost(string, optional, tag="1")] + pub artifact_id: ::core::option::Option<::prost::alloc::string::String>, + #[prost(string, optional, tag="2")] + pub conversation_id: ::core::option::Option<::prost::alloc::string::String>, + #[prost(string, optional, tag="4")] + pub title: ::core::option::Option<::prost::alloc::string::String>, + #[prost(string, optional, tag="5")] + pub summary: ::core::option::Option<::prost::alloc::string::String>, + #[prost(enumeration="ArtifactAuthoringKind", optional, tag="6")] + pub authoring_kind: ::core::option::Option, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct CreateArtifactResponse { + #[prost(message, optional, tag="1")] + pub artifact: ::core::option::Option, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct GetArtifactRequest { + #[prost(string, tag="1")] + pub artifact_id: ::prost::alloc::string::String, + #[prost(string, optional, tag="2")] + pub artifact_version_id: ::core::option::Option<::prost::alloc::string::String>, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct GetArtifactResponse { + #[prost(message, optional, tag="1")] + pub artifact: ::core::option::Option, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct ListArtifactsRequest { + #[prost(string, optional, tag="1")] + pub conversation_id: ::core::option::Option<::prost::alloc::string::String>, + #[prost(uint32, tag="2")] + pub page_size: u32, + #[prost(string, tag="3")] + pub page_token: ::prost::alloc::string::String, + #[prost(bool, tag="4")] + pub include_archived: bool, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ListArtifactsResponse { + #[prost(message, repeated, tag="1")] + pub artifacts: ::prost::alloc::vec::Vec, + #[prost(string, tag="2")] + pub next_page_token: ::prost::alloc::string::String, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct ListArtifactVersionsRequest { + #[prost(string, tag="1")] + pub artifact_id: ::prost::alloc::string::String, + #[prost(uint32, tag="2")] + pub page_size: u32, + #[prost(string, tag="3")] + pub page_token: ::prost::alloc::string::String, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ListArtifactVersionsResponse { + #[prost(message, repeated, tag="1")] + pub versions: ::prost::alloc::vec::Vec, + #[prost(string, tag="2")] + pub next_page_token: ::prost::alloc::string::String, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct LinkArtifactToConversationRequest { + #[prost(string, tag="1")] + pub artifact_id: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub conversation_id: ::prost::alloc::string::String, +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct LinkArtifactToConversationResponse { +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct UnlinkArtifactFromConversationRequest { + #[prost(string, tag="1")] + pub artifact_id: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub conversation_id: ::prost::alloc::string::String, +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct UnlinkArtifactFromConversationResponse { +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct ArchiveArtifactRequest { + #[prost(string, tag="1")] + pub artifact_id: ::prost::alloc::string::String, +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct ArchiveArtifactResponse { +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct UnarchiveArtifactRequest { + #[prost(string, tag="1")] + pub artifact_id: ::prost::alloc::string::String, +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct UnarchiveArtifactResponse { +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum ArtifactAuthoringKind { + Unspecified = 0, + Agent = 1, + User = 2, +} +impl ArtifactAuthoringKind { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Unspecified => "ARTIFACT_AUTHORING_KIND_UNSPECIFIED", + Self::Agent => "ARTIFACT_AUTHORING_KIND_AGENT", + Self::User => "ARTIFACT_AUTHORING_KIND_USER", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "ARTIFACT_AUTHORING_KIND_UNSPECIFIED" => Some(Self::Unspecified), + "ARTIFACT_AUTHORING_KIND_AGENT" => Some(Self::Agent), + "ARTIFACT_AUTHORING_KIND_USER" => Some(Self::User), + _ => None, + } + } +} +/// Encoded file descriptor set for the `sift.artifacts.v1` package +pub const FILE_DESCRIPTOR_SET: &[u8] = &[ + 0x0a, 0x87, 0x72, 0x0a, 0x21, 0x73, 0x69, 0x66, 0x74, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, + 0x63, 0x74, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x11, 0x73, 0x69, 0x66, 0x74, 0x2e, 0x61, 0x72, 0x74, + 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d, + 0x67, 0x65, 0x6e, 0x2d, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2f, 0x6f, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xfc, 0x06, 0x0a, 0x08, 0x41, 0x72, 0x74, + 0x69, 0x66, 0x61, 0x63, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, + 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x72, 0x74, 0x69, + 0x66, 0x61, 0x63, 0x74, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, + 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0e, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, + 0x2b, 0x0a, 0x12, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x75, 0x73, + 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x4f, 0x0a, 0x0e, + 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x28, 0x2e, 0x73, 0x69, 0x66, 0x74, 0x2e, 0x61, 0x72, 0x74, 0x69, + 0x66, 0x61, 0x63, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, + 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x0d, + 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x3d, 0x0a, + 0x0c, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x64, 0x61, 0x74, 0x65, 0x18, 0x06, 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, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x65, 0x12, 0x2e, 0x0a, 0x13, + 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x61, 0x72, 0x74, 0x69, 0x66, + 0x61, 0x63, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, + 0x09, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x88, 0x01, + 0x01, 0x12, 0x1d, 0x0a, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x0a, 0x20, 0x01, + 0x28, 0x09, 0x48, 0x01, 0x52, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x88, 0x01, 0x01, + 0x12, 0x35, 0x0a, 0x14, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, + 0x52, 0x12, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x2d, 0x0a, 0x13, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x5f, 0x74, 0x6f, 0x6f, 0x6c, 0x5f, 0x75, 0x73, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x0c, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x6f, 0x6f, 0x6c, + 0x55, 0x73, 0x65, 0x49, 0x64, 0x73, 0x12, 0x29, 0x0a, 0x0e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, + 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x48, 0x03, + 0x52, 0x0c, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x64, 0x88, 0x01, + 0x01, 0x12, 0x4c, 0x0a, 0x14, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x64, 0x5f, 0x64, 0x61, 0x74, 0x65, 0x18, 0x0e, 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, 0x12, 0x76, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x65, 0x12, + 0x20, 0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0f, 0x20, 0x01, + 0x28, 0x09, 0x48, 0x04, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x88, 0x01, + 0x01, 0x12, 0x29, 0x0a, 0x0e, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x6d, 0x69, 0x6d, 0x65, 0x5f, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x48, 0x05, 0x52, 0x0c, 0x66, 0x69, 0x6c, + 0x65, 0x4d, 0x69, 0x6d, 0x65, 0x54, 0x79, 0x70, 0x65, 0x88, 0x01, 0x01, 0x12, 0x44, 0x0a, 0x0d, + 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x64, 0x5f, 0x64, 0x61, 0x74, 0x65, 0x18, 0x11, 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, 0x48, + 0x06, 0x52, 0x0c, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x64, 0x44, 0x61, 0x74, 0x65, 0x88, + 0x01, 0x01, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x42, 0x0a, 0x0a, 0x08, + 0x5f, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x42, 0x17, 0x0a, 0x15, 0x5f, 0x61, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, + 0x64, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x66, 0x69, 0x6c, + 0x65, 0x5f, 0x69, 0x64, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x6e, 0x61, + 0x6d, 0x65, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x6d, 0x69, 0x6d, 0x65, + 0x5f, 0x74, 0x79, 0x70, 0x65, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, + 0x65, 0x64, 0x5f, 0x64, 0x61, 0x74, 0x65, 0x22, 0xb6, 0x04, 0x0a, 0x0f, 0x41, 0x72, 0x74, 0x69, + 0x66, 0x61, 0x63, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x0a, 0x13, 0x61, + 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, + 0x63, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x61, + 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0a, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x88, 0x01, + 0x01, 0x12, 0x1d, 0x0a, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x09, 0x48, 0x01, 0x52, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x88, 0x01, 0x01, + 0x12, 0x35, 0x0a, 0x14, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, + 0x52, 0x12, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x2d, 0x0a, 0x13, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x5f, 0x74, 0x6f, 0x6f, 0x6c, 0x5f, 0x75, 0x73, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x07, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x6f, 0x6f, 0x6c, + 0x55, 0x73, 0x65, 0x49, 0x64, 0x73, 0x12, 0x29, 0x0a, 0x0e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, + 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x48, 0x03, + 0x52, 0x0c, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x64, 0x88, 0x01, + 0x01, 0x12, 0x3d, 0x0a, 0x0c, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x64, 0x61, 0x74, + 0x65, 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, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x65, + 0x12, 0x20, 0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0a, 0x20, + 0x01, 0x28, 0x09, 0x48, 0x04, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x88, + 0x01, 0x01, 0x12, 0x29, 0x0a, 0x0e, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x6d, 0x69, 0x6d, 0x65, 0x5f, + 0x74, 0x79, 0x70, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x48, 0x05, 0x52, 0x0c, 0x66, 0x69, + 0x6c, 0x65, 0x4d, 0x69, 0x6d, 0x65, 0x54, 0x79, 0x70, 0x65, 0x88, 0x01, 0x01, 0x42, 0x08, 0x0a, + 0x06, 0x5f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x73, 0x75, 0x6d, 0x6d, + 0x61, 0x72, 0x79, 0x42, 0x17, 0x0a, 0x15, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x6e, + 0x67, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x42, 0x11, 0x0a, 0x0f, + 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x42, + 0x0c, 0x0a, 0x0a, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x11, 0x0a, + 0x0f, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x6d, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, + 0x22, 0xc8, 0x02, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x72, 0x74, 0x69, 0x66, + 0x61, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x0b, 0x61, 0x72, + 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, + 0x00, 0x52, 0x0a, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x49, 0x64, 0x88, 0x01, 0x01, + 0x12, 0x2c, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x0e, 0x63, 0x6f, 0x6e, + 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x19, + 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, + 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x88, 0x01, 0x01, 0x12, 0x1d, 0x0a, 0x07, 0x73, 0x75, 0x6d, + 0x6d, 0x61, 0x72, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x03, 0x52, 0x07, 0x73, 0x75, + 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x88, 0x01, 0x01, 0x12, 0x54, 0x0a, 0x0e, 0x61, 0x75, 0x74, 0x68, + 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x28, 0x2e, 0x73, 0x69, 0x66, 0x74, 0x2e, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, + 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x41, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x4b, 0x69, 0x6e, 0x64, 0x48, 0x04, 0x52, 0x0d, 0x61, 0x75, + 0x74, 0x68, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x4b, 0x69, 0x6e, 0x64, 0x88, 0x01, 0x01, 0x42, 0x0e, + 0x0a, 0x0c, 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x42, 0x12, + 0x0a, 0x10, 0x5f, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x69, 0x64, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x42, 0x0a, 0x0a, 0x08, + 0x5f, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x61, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x6b, 0x69, 0x6e, 0x64, 0x22, 0x51, 0x0a, 0x16, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x08, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x73, 0x69, 0x66, 0x74, 0x2e, 0x61, + 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x72, 0x74, 0x69, + 0x66, 0x61, 0x63, 0x74, 0x52, 0x08, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x22, 0x82, + 0x01, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, + 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x72, 0x74, 0x69, + 0x66, 0x61, 0x63, 0x74, 0x49, 0x64, 0x12, 0x33, 0x0a, 0x13, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, + 0x63, 0x74, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x11, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x56, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x88, 0x01, 0x01, 0x42, 0x16, 0x0a, 0x14, 0x5f, + 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x5f, 0x69, 0x64, 0x22, 0x4e, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, + 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x08, 0x61, 0x72, + 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x73, + 0x69, 0x66, 0x74, 0x2e, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2e, 0x76, 0x31, + 0x2e, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x08, 0x61, 0x72, 0x74, 0x69, 0x66, + 0x61, 0x63, 0x74, 0x22, 0xbf, 0x01, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x72, 0x74, 0x69, + 0x66, 0x61, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x0f, + 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x88, 0x01, 0x01, 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, 0x12, 0x29, 0x0a, 0x10, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, + 0x65, 0x5f, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, + 0x64, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x22, 0x7a, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x72, 0x74, + 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, + 0x0a, 0x09, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x1b, 0x2e, 0x73, 0x69, 0x66, 0x74, 0x2e, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, + 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x09, + 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 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, 0x7a, 0x0a, 0x1b, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, + 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 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, 0x86, 0x01, + 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x56, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, + 0x0a, 0x08, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x22, 0x2e, 0x73, 0x69, 0x66, 0x74, 0x2e, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, + 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x56, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x76, 0x65, 0x72, 0x73, 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, 0x6d, 0x0a, 0x21, 0x4c, 0x69, 0x6e, 0x6b, 0x41, 0x72, + 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x54, 0x6f, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x61, + 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0a, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 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, 0x24, 0x0a, 0x22, 0x4c, 0x69, 0x6e, 0x6b, 0x41, 0x72, 0x74, + 0x69, 0x66, 0x61, 0x63, 0x74, 0x54, 0x6f, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x71, 0x0a, 0x25, 0x55, + 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x46, 0x72, 0x6f, + 0x6d, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x72, 0x74, 0x69, 0x66, + 0x61, 0x63, 0x74, 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, 0x28, + 0x0a, 0x26, 0x55, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, + 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x39, 0x0a, 0x16, 0x41, 0x72, 0x63, 0x68, + 0x69, 0x76, 0x65, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, + 0x74, 0x49, 0x64, 0x22, 0x19, 0x0a, 0x17, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x41, 0x72, + 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3b, + 0x0a, 0x18, 0x55, 0x6e, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x41, 0x72, 0x74, 0x69, 0x66, + 0x61, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x72, + 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0a, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x49, 0x64, 0x22, 0x1b, 0x0a, 0x19, 0x55, + 0x6e, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2a, 0x85, 0x01, 0x0a, 0x15, 0x41, 0x72, 0x74, + 0x69, 0x66, 0x61, 0x63, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x4b, 0x69, + 0x6e, 0x64, 0x12, 0x27, 0x0a, 0x23, 0x41, 0x52, 0x54, 0x49, 0x46, 0x41, 0x43, 0x54, 0x5f, 0x41, + 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49, 0x4e, 0x47, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x55, 0x4e, + 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x21, 0x0a, 0x1d, 0x41, + 0x52, 0x54, 0x49, 0x46, 0x41, 0x43, 0x54, 0x5f, 0x41, 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49, 0x4e, + 0x47, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x41, 0x47, 0x45, 0x4e, 0x54, 0x10, 0x01, 0x12, 0x20, + 0x0a, 0x1c, 0x41, 0x52, 0x54, 0x49, 0x46, 0x41, 0x43, 0x54, 0x5f, 0x41, 0x55, 0x54, 0x48, 0x4f, + 0x52, 0x49, 0x4e, 0x47, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x55, 0x53, 0x45, 0x52, 0x10, 0x02, + 0x32, 0xb7, 0x12, 0x0a, 0x0f, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x12, 0xf8, 0x01, 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, + 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x12, 0x28, 0x2e, 0x73, 0x69, 0x66, 0x74, 0x2e, 0x61, + 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x29, 0x2e, 0x73, 0x69, 0x66, 0x74, 0x2e, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, + 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x72, 0x74, 0x69, + 0x66, 0x61, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x90, 0x01, 0x92, + 0x41, 0x71, 0x12, 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, + 0x63, 0x74, 0x1a, 0x3d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x20, 0x61, 0x20, 0x6e, 0x65, 0x77, + 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x20, 0x6f, 0x72, 0x20, 0x61, 0x70, 0x70, + 0x65, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, + 0x20, 0x61, 0x6e, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x6e, 0x65, + 0x2e, 0x2a, 0x20, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x5f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, + 0x74, 0x56, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x3a, 0x01, 0x2a, 0x22, 0x11, 0x2f, 0x61, + 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x12, + 0x8d, 0x02, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x12, + 0x25, 0x2e, 0x73, 0x69, 0x66, 0x74, 0x2e, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, + 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x73, 0x69, 0x66, 0x74, 0x2e, 0x61, 0x72, + 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x72, + 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xae, + 0x01, 0x92, 0x41, 0x83, 0x01, 0x12, 0x0b, 0x47, 0x65, 0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, + 0x63, 0x74, 0x1a, 0x55, 0x47, 0x65, 0x74, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x61, 0x72, 0x74, 0x69, + 0x66, 0x61, 0x63, 0x74, 0x2c, 0x20, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x20, 0x74, + 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x20, 0x76, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x75, 0x6e, 0x6c, 0x65, 0x73, 0x73, 0x20, 0x61, 0x72, 0x74, 0x69, + 0x66, 0x61, 0x63, 0x74, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x20, + 0x70, 0x69, 0x6e, 0x73, 0x20, 0x6f, 0x6e, 0x65, 0x2e, 0x2a, 0x1d, 0x41, 0x72, 0x74, 0x69, 0x66, + 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x47, 0x65, 0x74, 0x41, 0x72, + 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x56, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x21, 0x12, 0x1f, + 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, + 0x73, 0x2f, 0x7b, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x7d, 0x12, + 0x89, 0x02, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, + 0x73, 0x12, 0x27, 0x2e, 0x73, 0x69, 0x66, 0x74, 0x2e, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, + 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, + 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x73, 0x69, 0x66, + 0x74, 0x2e, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xa4, 0x01, 0x92, 0x41, 0x87, 0x01, 0x12, 0x0d, 0x4c, 0x69, 0x73, + 0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x1a, 0x55, 0x4c, 0x69, 0x73, 0x74, + 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x27, 0x73, 0x20, 0x6f, 0x72, 0x67, 0x61, 0x6e, + 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, + 0x6c, 0x6c, 0x79, 0x20, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, + 0x6f, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x2e, 0x2a, 0x1f, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x5f, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, + 0x56, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, + 0x31, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x12, 0xa4, 0x02, 0x0a, 0x14, + 0x4c, 0x69, 0x73, 0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x56, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2e, 0x2e, 0x73, 0x69, 0x66, 0x74, 0x2e, 0x61, 0x72, 0x74, 0x69, + 0x66, 0x61, 0x63, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x72, 0x74, + 0x69, 0x66, 0x61, 0x63, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x73, 0x69, 0x66, 0x74, 0x2e, 0x61, 0x72, 0x74, 0x69, + 0x66, 0x61, 0x63, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x72, 0x74, + 0x69, 0x66, 0x61, 0x63, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xaa, 0x01, 0x92, 0x41, 0x77, 0x12, 0x14, 0x4c, 0x69, 0x73, + 0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x73, 0x1a, 0x37, 0x4c, 0x69, 0x73, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x76, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x20, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x6f, + 0x6e, 0x65, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x2c, 0x20, 0x6e, 0x65, 0x77, + 0x65, 0x73, 0x74, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x2e, 0x2a, 0x26, 0x41, 0x72, 0x74, 0x69, + 0x66, 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x4c, 0x69, 0x73, 0x74, + 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, + 0x56, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2a, 0x12, 0x28, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, + 0x31, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2f, 0x7b, 0x61, 0x72, 0x74, + 0x69, 0x66, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x73, 0x12, 0xd3, 0x02, 0x0a, 0x1a, 0x4c, 0x69, 0x6e, 0x6b, 0x41, 0x72, 0x74, 0x69, 0x66, + 0x61, 0x63, 0x74, 0x54, 0x6f, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x34, 0x2e, 0x73, 0x69, 0x66, 0x74, 0x2e, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, + 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x6e, 0x6b, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, + 0x63, 0x74, 0x54, 0x6f, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x73, 0x69, 0x66, 0x74, 0x2e, 0x61, + 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x6e, 0x6b, + 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x54, 0x6f, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, + 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xc7, + 0x01, 0x92, 0x41, 0x78, 0x12, 0x1a, 0x4c, 0x69, 0x6e, 0x6b, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, + 0x63, 0x74, 0x54, 0x6f, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x1a, 0x2c, 0x4c, 0x69, 0x6e, 0x6b, 0x20, 0x61, 0x6e, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x69, + 0x6e, 0x67, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x61, + 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x2a, 0x2c, + 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, + 0x4c, 0x69, 0x6e, 0x6b, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x54, 0x6f, 0x43, 0x6f, + 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x31, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x46, 0x22, 0x44, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x72, 0x74, 0x69, + 0x66, 0x61, 0x63, 0x74, 0x73, 0x2f, 0x7b, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5f, + 0x69, 0x64, 0x7d, 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, 0x3a, 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0xea, 0x02, 0x0a, 0x1e, 0x55, 0x6e, 0x6c, + 0x69, 0x6e, 0x6b, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x46, 0x72, 0x6f, 0x6d, 0x43, + 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x38, 0x2e, 0x73, 0x69, + 0x66, 0x74, 0x2e, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, + 0x55, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x46, 0x72, + 0x6f, 0x6d, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x39, 0x2e, 0x73, 0x69, 0x66, 0x74, 0x2e, 0x61, 0x72, 0x74, + 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, + 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x6f, 0x6e, 0x76, + 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0xd2, 0x01, 0x92, 0x41, 0x80, 0x01, 0x12, 0x1e, 0x55, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x41, + 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x6f, 0x6e, 0x76, 0x65, + 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x2c, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x20, + 0x61, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x27, 0x73, + 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x72, 0x74, 0x69, + 0x66, 0x61, 0x63, 0x74, 0x2e, 0x2a, 0x30, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x55, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x41, 0x72, 0x74, + 0x69, 0x66, 0x61, 0x63, 0x74, 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x48, 0x22, 0x46, 0x2f, + 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, + 0x2f, 0x7b, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x7d, 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, 0x3a, 0x75, + 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0xaa, 0x02, 0x0a, 0x0f, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, + 0x65, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x12, 0x29, 0x2e, 0x73, 0x69, 0x66, 0x74, + 0x2e, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x72, + 0x63, 0x68, 0x69, 0x76, 0x65, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x73, 0x69, 0x66, 0x74, 0x2e, 0x61, 0x72, 0x74, 0x69, + 0x66, 0x61, 0x63, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, + 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0xbf, 0x01, 0x92, 0x41, 0x8c, 0x01, 0x12, 0x0f, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, + 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x1a, 0x56, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, + 0x65, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x2e, 0x20, 0x56, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x20, + 0x62, 0x79, 0x74, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, + 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x20, 0x61, 0x72, + 0x65, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2e, + 0x2a, 0x21, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x5f, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, + 0x74, 0x56, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x29, 0x22, 0x27, 0x2f, 0x61, 0x70, 0x69, 0x2f, + 0x76, 0x31, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2f, 0x7b, 0x61, 0x72, + 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x61, 0x72, 0x63, 0x68, 0x69, + 0x76, 0x65, 0x12, 0xf5, 0x01, 0x0a, 0x11, 0x55, 0x6e, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, + 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x12, 0x2b, 0x2e, 0x73, 0x69, 0x66, 0x74, 0x2e, + 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x61, + 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x73, 0x69, 0x66, 0x74, 0x2e, 0x61, 0x72, 0x74, + 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x61, 0x72, 0x63, 0x68, + 0x69, 0x76, 0x65, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x84, 0x01, 0x92, 0x41, 0x50, 0x12, 0x11, 0x55, 0x6e, 0x61, 0x72, 0x63, + 0x68, 0x69, 0x76, 0x65, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x1a, 0x16, 0x55, 0x6e, + 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, + 0x61, 0x63, 0x74, 0x2e, 0x2a, 0x23, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x55, 0x6e, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x41, + 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x56, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x22, + 0x29, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, + 0x74, 0x73, 0x2f, 0x7b, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x7d, + 0x2f, 0x75, 0x6e, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x42, 0xa4, 0x01, 0x92, 0x41, 0x14, + 0x12, 0x12, 0x0a, 0x10, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x20, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x73, 0x69, 0x66, 0x74, 0x2e, 0x61, + 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x42, 0x0e, 0x41, 0x72, 0x74, + 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0xa2, 0x02, 0x03, + 0x53, 0x41, 0x58, 0xaa, 0x02, 0x11, 0x53, 0x69, 0x66, 0x74, 0x2e, 0x41, 0x72, 0x74, 0x69, 0x66, + 0x61, 0x63, 0x74, 0x73, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x11, 0x53, 0x69, 0x66, 0x74, 0x5c, 0x41, + 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x1d, 0x53, 0x69, + 0x66, 0x74, 0x5c, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x5c, 0x56, 0x31, 0x5c, + 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x13, 0x53, 0x69, + 0x66, 0x74, 0x3a, 0x3a, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x3a, 0x3a, 0x56, + 0x31, 0x4a, 0x9e, 0x43, 0x0a, 0x07, 0x12, 0x05, 0x00, 0x00, 0xf5, 0x01, 0x24, 0x0a, 0x08, 0x0a, + 0x01, 0x0c, 0x12, 0x03, 0x00, 0x00, 0x12, 0x0a, 0x08, 0x0a, 0x01, 0x02, 0x12, 0x03, 0x02, 0x00, + 0x1a, 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x00, 0x12, 0x03, 0x04, 0x00, 0x26, 0x0a, 0x09, 0x0a, 0x02, + 0x03, 0x01, 0x12, 0x03, 0x05, 0x00, 0x38, 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x02, 0x12, 0x03, 0x06, + 0x00, 0x29, 0x0a, 0x09, 0x0a, 0x01, 0x08, 0x12, 0x04, 0x08, 0x00, 0x0a, 0x02, 0x0a, 0x0b, 0x0a, + 0x03, 0x08, 0x92, 0x08, 0x12, 0x04, 0x08, 0x00, 0x0a, 0x02, 0x0a, 0x0b, 0x0a, 0x04, 0x08, 0x92, + 0x08, 0x02, 0x12, 0x03, 0x09, 0x02, 0x23, 0x0a, 0x0c, 0x0a, 0x05, 0x08, 0x92, 0x08, 0x02, 0x01, + 0x12, 0x03, 0x09, 0x09, 0x22, 0x0a, 0xe9, 0x04, 0x0a, 0x02, 0x06, 0x00, 0x12, 0x04, 0x16, 0x00, + 0x76, 0x01, 0x1a, 0xdc, 0x04, 0x20, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x73, 0x20, 0x61, 0x72, + 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x3a, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x70, 0x65, 0x6e, + 0x64, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x6f, 0x72, 0x67, 0x2d, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x64, + 0x2c, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x0a, 0x20, 0x64, 0x6f, 0x63, + 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x20, 0x41, 0x6e, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, + 0x61, 0x63, 0x74, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6f, 0x77, 0x6e, 0x65, 0x64, + 0x20, 0x62, 0x79, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x2e, 0x20, 0x41, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x20, 0x6d, 0x61, 0x79, 0x0a, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, + 0x65, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x20, 0x74, 0x68, + 0x72, 0x6f, 0x75, 0x67, 0x68, 0x20, 0x61, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x2c, 0x20, 0x61, 0x6e, + 0x79, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x63, 0x6f, 0x6e, 0x76, + 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x6c, 0x69, + 0x6e, 0x6b, 0x0a, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x61, 0x72, 0x74, + 0x69, 0x66, 0x61, 0x63, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x72, + 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, + 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6e, 0x6f, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x61, 0x74, + 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x28, 0x66, 0x6f, 0x72, 0x0a, 0x20, 0x65, 0x78, 0x61, 0x6d, 0x70, + 0x6c, 0x65, 0x2c, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x6f, 0x76, 0x65, 0x72, + 0x20, 0x4d, 0x43, 0x50, 0x20, 0x6f, 0x75, 0x74, 0x73, 0x69, 0x64, 0x65, 0x20, 0x61, 0x6e, 0x20, + 0x61, 0x67, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x29, 0x2e, 0x0a, + 0x0a, 0x20, 0x54, 0x68, 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, 0x63, 0x61, + 0x72, 0x72, 0x69, 0x65, 0x73, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x20, 0x6d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x2e, 0x20, 0x56, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x6c, 0x69, 0x76, 0x65, + 0x20, 0x69, 0x6e, 0x0a, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, + 0x73, 0x20, 0x28, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x20, 0x27, + 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x73, 0x27, 0x2c, 0x20, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x69, 0x64, 0x20, 0x3d, 0x0a, + 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x5f, 0x69, 0x64, 0x29, 0x3a, 0x20, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x76, 0x69, + 0x61, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2d, 0x66, 0x69, 0x6c, + 0x65, 0x73, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, 0x72, 0x74, 0x20, 0x65, 0x6e, 0x64, + 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2c, 0x0a, 0x20, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, + 0x20, 0x76, 0x69, 0x61, 0x20, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, + 0x46, 0x69, 0x6c, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x72, 0x6c, 0x2e, + 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x06, 0x00, 0x01, 0x12, 0x03, 0x16, 0x08, 0x17, 0x0a, 0xc9, 0x01, + 0x0a, 0x04, 0x06, 0x00, 0x02, 0x00, 0x12, 0x04, 0x1a, 0x02, 0x24, 0x03, 0x1a, 0xba, 0x01, 0x20, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, + 0x61, 0x63, 0x74, 0x20, 0x70, 0x6c, 0x75, 0x73, 0x20, 0x69, 0x74, 0x73, 0x20, 0x76, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x2d, 0x31, 0x20, 0x72, 0x6f, 0x77, 0x2c, 0x20, 0x6f, 0x72, 0x20, 0x61, + 0x70, 0x70, 0x65, 0x6e, 0x64, 0x73, 0x20, 0x61, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x20, 0x77, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5f, + 0x69, 0x64, 0x20, 0x69, 0x73, 0x20, 0x73, 0x65, 0x74, 0x2e, 0x20, 0x57, 0x68, 0x65, 0x6e, 0x20, + 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x20, + 0x69, 0x73, 0x20, 0x73, 0x65, 0x74, 0x20, 0x6f, 0x6e, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x65, 0x77, 0x0a, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, + 0x61, 0x63, 0x74, 0x20, 0x69, 0x73, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x6c, 0x69, 0x6e, 0x6b, + 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, + 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, + 0x00, 0x01, 0x12, 0x03, 0x1a, 0x06, 0x14, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x00, 0x02, + 0x12, 0x03, 0x1a, 0x15, 0x2a, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, + 0x1a, 0x35, 0x4b, 0x0a, 0x0d, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x00, 0x04, 0x12, 0x04, 0x1b, 0x04, + 0x1e, 0x06, 0x0a, 0x11, 0x0a, 0x09, 0x06, 0x00, 0x02, 0x00, 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x12, + 0x04, 0x1b, 0x04, 0x1e, 0x06, 0x0a, 0x11, 0x0a, 0x0a, 0x06, 0x00, 0x02, 0x00, 0x04, 0xb0, 0xca, + 0xbc, 0x22, 0x04, 0x12, 0x03, 0x1c, 0x06, 0x1f, 0x0a, 0x11, 0x0a, 0x0a, 0x06, 0x00, 0x02, 0x00, + 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x07, 0x12, 0x03, 0x1d, 0x06, 0x0f, 0x0a, 0x0d, 0x0a, 0x05, 0x06, + 0x00, 0x02, 0x00, 0x04, 0x12, 0x04, 0x1f, 0x04, 0x23, 0x06, 0x0a, 0x0f, 0x0a, 0x07, 0x06, 0x00, + 0x02, 0x00, 0x04, 0x92, 0x08, 0x12, 0x04, 0x1f, 0x04, 0x23, 0x06, 0x0a, 0x0f, 0x0a, 0x08, 0x06, + 0x00, 0x02, 0x00, 0x04, 0x92, 0x08, 0x02, 0x12, 0x03, 0x20, 0x06, 0x1f, 0x0a, 0x0f, 0x0a, 0x08, + 0x06, 0x00, 0x02, 0x00, 0x04, 0x92, 0x08, 0x03, 0x12, 0x03, 0x21, 0x06, 0x52, 0x0a, 0x0f, 0x0a, + 0x08, 0x06, 0x00, 0x02, 0x00, 0x04, 0x92, 0x08, 0x05, 0x12, 0x03, 0x22, 0x06, 0x36, 0x0a, 0x53, + 0x0a, 0x04, 0x06, 0x00, 0x02, 0x01, 0x12, 0x04, 0x27, 0x02, 0x2e, 0x03, 0x1a, 0x45, 0x20, 0x52, + 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, + 0x61, 0x74, 0x65, 0x73, 0x74, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x75, 0x6e, + 0x6c, 0x65, 0x73, 0x73, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5f, 0x76, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x20, 0x70, 0x69, 0x6e, 0x73, 0x20, 0x6f, 0x6e, + 0x65, 0x2e, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x27, 0x06, + 0x11, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x01, 0x02, 0x12, 0x03, 0x27, 0x12, 0x24, 0x0a, + 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, 0x27, 0x2f, 0x42, 0x0a, 0x0c, 0x0a, + 0x05, 0x06, 0x00, 0x02, 0x01, 0x04, 0x12, 0x03, 0x28, 0x04, 0x48, 0x0a, 0x10, 0x0a, 0x09, 0x06, + 0x00, 0x02, 0x01, 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x12, 0x03, 0x28, 0x04, 0x48, 0x0a, 0x11, 0x0a, + 0x0a, 0x06, 0x00, 0x02, 0x01, 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x02, 0x12, 0x03, 0x28, 0x20, 0x46, + 0x0a, 0x0d, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x01, 0x04, 0x12, 0x04, 0x29, 0x04, 0x2d, 0x06, 0x0a, + 0x0f, 0x0a, 0x07, 0x06, 0x00, 0x02, 0x01, 0x04, 0x92, 0x08, 0x12, 0x04, 0x29, 0x04, 0x2d, 0x06, + 0x0a, 0x0f, 0x0a, 0x08, 0x06, 0x00, 0x02, 0x01, 0x04, 0x92, 0x08, 0x02, 0x12, 0x03, 0x2a, 0x06, + 0x1c, 0x0a, 0x0f, 0x0a, 0x08, 0x06, 0x00, 0x02, 0x01, 0x04, 0x92, 0x08, 0x03, 0x12, 0x03, 0x2b, + 0x06, 0x6a, 0x0a, 0x0f, 0x0a, 0x08, 0x06, 0x00, 0x02, 0x01, 0x04, 0x92, 0x08, 0x05, 0x12, 0x03, + 0x2c, 0x06, 0x33, 0x0a, 0xd5, 0x01, 0x0a, 0x04, 0x06, 0x00, 0x02, 0x02, 0x12, 0x04, 0x33, 0x02, + 0x3a, 0x03, 0x1a, 0xc6, 0x01, 0x20, 0x4f, 0x6e, 0x65, 0x20, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x20, + 0x70, 0x65, 0x72, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x2c, 0x20, 0x72, 0x65, + 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x74, 0x73, 0x20, 0x6c, 0x61, + 0x74, 0x65, 0x73, 0x74, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x6f, 0x6c, + 0x64, 0x65, 0x73, 0x74, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x2e, 0x0a, 0x20, 0x57, 0x69, 0x74, + 0x68, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, + 0x64, 0x20, 0x73, 0x65, 0x74, 0x2c, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x61, 0x72, 0x74, 0x69, + 0x66, 0x61, 0x63, 0x74, 0x73, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, + 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x3b, 0x0a, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x77, 0x69, 0x73, 0x65, 0x20, 0x65, 0x76, + 0x65, 0x72, 0x79, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x20, 0x69, 0x6e, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x27, 0x73, 0x20, 0x6f, 0x72, 0x67, + 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x06, + 0x00, 0x02, 0x02, 0x01, 0x12, 0x03, 0x33, 0x06, 0x13, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, + 0x02, 0x02, 0x12, 0x03, 0x33, 0x14, 0x28, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x02, 0x03, + 0x12, 0x03, 0x33, 0x33, 0x48, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x02, 0x04, 0x12, 0x03, + 0x34, 0x04, 0x3a, 0x0a, 0x10, 0x0a, 0x09, 0x06, 0x00, 0x02, 0x02, 0x04, 0xb0, 0xca, 0xbc, 0x22, + 0x12, 0x03, 0x34, 0x04, 0x3a, 0x0a, 0x11, 0x0a, 0x0a, 0x06, 0x00, 0x02, 0x02, 0x04, 0xb0, 0xca, + 0xbc, 0x22, 0x02, 0x12, 0x03, 0x34, 0x20, 0x38, 0x0a, 0x0d, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x02, + 0x04, 0x12, 0x04, 0x35, 0x04, 0x39, 0x06, 0x0a, 0x0f, 0x0a, 0x07, 0x06, 0x00, 0x02, 0x02, 0x04, + 0x92, 0x08, 0x12, 0x04, 0x35, 0x04, 0x39, 0x06, 0x0a, 0x0f, 0x0a, 0x08, 0x06, 0x00, 0x02, 0x02, + 0x04, 0x92, 0x08, 0x02, 0x12, 0x03, 0x36, 0x06, 0x1e, 0x0a, 0x0f, 0x0a, 0x08, 0x06, 0x00, 0x02, + 0x02, 0x04, 0x92, 0x08, 0x03, 0x12, 0x03, 0x37, 0x06, 0x6a, 0x0a, 0x0f, 0x0a, 0x08, 0x06, 0x00, + 0x02, 0x02, 0x04, 0x92, 0x08, 0x05, 0x12, 0x03, 0x38, 0x06, 0x35, 0x0a, 0x43, 0x0a, 0x04, 0x06, + 0x00, 0x02, 0x03, 0x12, 0x04, 0x3d, 0x02, 0x44, 0x03, 0x1a, 0x35, 0x20, 0x46, 0x75, 0x6c, 0x6c, + 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, + 0x20, 0x6f, 0x66, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, + 0x2c, 0x20, 0x6e, 0x65, 0x77, 0x65, 0x73, 0x74, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x2e, 0x0a, + 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x03, 0x01, 0x12, 0x03, 0x3d, 0x06, 0x1a, 0x0a, 0x0c, + 0x0a, 0x05, 0x06, 0x00, 0x02, 0x03, 0x02, 0x12, 0x03, 0x3d, 0x1b, 0x36, 0x0a, 0x0c, 0x0a, 0x05, + 0x06, 0x00, 0x02, 0x03, 0x03, 0x12, 0x03, 0x3d, 0x41, 0x5d, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, + 0x02, 0x03, 0x04, 0x12, 0x03, 0x3e, 0x04, 0x51, 0x0a, 0x10, 0x0a, 0x09, 0x06, 0x00, 0x02, 0x03, + 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x12, 0x03, 0x3e, 0x04, 0x51, 0x0a, 0x11, 0x0a, 0x0a, 0x06, 0x00, + 0x02, 0x03, 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x02, 0x12, 0x03, 0x3e, 0x20, 0x4f, 0x0a, 0x0d, 0x0a, + 0x05, 0x06, 0x00, 0x02, 0x03, 0x04, 0x12, 0x04, 0x3f, 0x04, 0x43, 0x06, 0x0a, 0x0f, 0x0a, 0x07, + 0x06, 0x00, 0x02, 0x03, 0x04, 0x92, 0x08, 0x12, 0x04, 0x3f, 0x04, 0x43, 0x06, 0x0a, 0x0f, 0x0a, + 0x08, 0x06, 0x00, 0x02, 0x03, 0x04, 0x92, 0x08, 0x02, 0x12, 0x03, 0x40, 0x06, 0x25, 0x0a, 0x0f, + 0x0a, 0x08, 0x06, 0x00, 0x02, 0x03, 0x04, 0x92, 0x08, 0x03, 0x12, 0x03, 0x41, 0x06, 0x4c, 0x0a, + 0x0f, 0x0a, 0x08, 0x06, 0x00, 0x02, 0x03, 0x04, 0x92, 0x08, 0x05, 0x12, 0x03, 0x42, 0x06, 0x3c, + 0x0a, 0x82, 0x01, 0x0a, 0x04, 0x06, 0x00, 0x02, 0x04, 0x12, 0x04, 0x48, 0x02, 0x51, 0x03, 0x1a, + 0x74, 0x20, 0x4c, 0x69, 0x6e, 0x6b, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, + 0x69, 0x6e, 0x67, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x20, 0x74, 0x6f, 0x20, + 0x61, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x20, + 0x49, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x6c, 0x69, 0x6e, 0x6b, + 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x0a, 0x20, 0x61, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x2d, + 0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x64, 0x20, 0x70, 0x61, 0x69, 0x72, 0x20, 0x73, 0x75, 0x63, 0x63, + 0x65, 0x65, 0x64, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x65, 0x66, 0x66, + 0x65, 0x63, 0x74, 0x2e, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x04, 0x01, 0x12, 0x03, + 0x48, 0x06, 0x20, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x04, 0x02, 0x12, 0x03, 0x48, 0x21, + 0x42, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x04, 0x03, 0x12, 0x03, 0x48, 0x4d, 0x6f, 0x0a, + 0x0d, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x04, 0x04, 0x12, 0x04, 0x49, 0x04, 0x4b, 0x06, 0x0a, 0x11, + 0x0a, 0x09, 0x06, 0x00, 0x02, 0x04, 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x12, 0x04, 0x49, 0x04, 0x4b, + 0x06, 0x0a, 0x11, 0x0a, 0x0a, 0x06, 0x00, 0x02, 0x04, 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x04, 0x12, + 0x03, 0x4a, 0x06, 0x52, 0x0a, 0x0d, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x04, 0x04, 0x12, 0x04, 0x4c, + 0x04, 0x50, 0x06, 0x0a, 0x0f, 0x0a, 0x07, 0x06, 0x00, 0x02, 0x04, 0x04, 0x92, 0x08, 0x12, 0x04, + 0x4c, 0x04, 0x50, 0x06, 0x0a, 0x0f, 0x0a, 0x08, 0x06, 0x00, 0x02, 0x04, 0x04, 0x92, 0x08, 0x02, + 0x12, 0x03, 0x4d, 0x06, 0x2b, 0x0a, 0x0f, 0x0a, 0x08, 0x06, 0x00, 0x02, 0x04, 0x04, 0x92, 0x08, + 0x03, 0x12, 0x03, 0x4e, 0x06, 0x41, 0x0a, 0x0f, 0x0a, 0x08, 0x06, 0x00, 0x02, 0x04, 0x04, 0x92, + 0x08, 0x05, 0x12, 0x03, 0x4f, 0x06, 0x42, 0x0a, 0x92, 0x01, 0x0a, 0x04, 0x06, 0x00, 0x02, 0x05, + 0x12, 0x04, 0x55, 0x02, 0x5e, 0x03, 0x1a, 0x83, 0x01, 0x20, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, + 0x73, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x27, 0x73, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6e, 0x20, + 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x61, 0x72, + 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x20, 0x69, 0x74, 0x73, 0x65, 0x6c, 0x66, 0x20, 0x69, 0x73, + 0x0a, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x75, 0x63, 0x68, 0x65, 0x64, 0x2e, 0x20, 0x49, 0x64, 0x65, + 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x75, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x69, + 0x6e, 0x67, 0x20, 0x61, 0x20, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x6c, 0x69, 0x6e, + 0x6b, 0x20, 0x73, 0x75, 0x63, 0x63, 0x65, 0x65, 0x64, 0x73, 0x2e, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, + 0x06, 0x00, 0x02, 0x05, 0x01, 0x12, 0x03, 0x55, 0x06, 0x24, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, + 0x02, 0x05, 0x02, 0x12, 0x03, 0x55, 0x25, 0x4a, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x05, + 0x03, 0x12, 0x03, 0x55, 0x55, 0x7b, 0x0a, 0x0d, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x05, 0x04, 0x12, + 0x04, 0x56, 0x04, 0x58, 0x06, 0x0a, 0x11, 0x0a, 0x09, 0x06, 0x00, 0x02, 0x05, 0x04, 0xb0, 0xca, + 0xbc, 0x22, 0x12, 0x04, 0x56, 0x04, 0x58, 0x06, 0x0a, 0x11, 0x0a, 0x0a, 0x06, 0x00, 0x02, 0x05, + 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x04, 0x12, 0x03, 0x57, 0x06, 0x54, 0x0a, 0x0d, 0x0a, 0x05, 0x06, + 0x00, 0x02, 0x05, 0x04, 0x12, 0x04, 0x59, 0x04, 0x5d, 0x06, 0x0a, 0x0f, 0x0a, 0x07, 0x06, 0x00, + 0x02, 0x05, 0x04, 0x92, 0x08, 0x12, 0x04, 0x59, 0x04, 0x5d, 0x06, 0x0a, 0x0f, 0x0a, 0x08, 0x06, + 0x00, 0x02, 0x05, 0x04, 0x92, 0x08, 0x02, 0x12, 0x03, 0x5a, 0x06, 0x2f, 0x0a, 0x0f, 0x0a, 0x08, + 0x06, 0x00, 0x02, 0x05, 0x04, 0x92, 0x08, 0x03, 0x12, 0x03, 0x5b, 0x06, 0x41, 0x0a, 0x0f, 0x0a, + 0x08, 0x06, 0x00, 0x02, 0x05, 0x04, 0x92, 0x08, 0x05, 0x12, 0x03, 0x5c, 0x06, 0x46, 0x0a, 0xc4, + 0x01, 0x0a, 0x04, 0x06, 0x00, 0x02, 0x06, 0x12, 0x04, 0x63, 0x02, 0x6a, 0x03, 0x1a, 0xb5, 0x01, + 0x20, 0x53, 0x65, 0x74, 0x73, 0x20, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x64, 0x5f, 0x64, + 0x61, 0x74, 0x65, 0x2e, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x73, + 0x74, 0x6f, 0x72, 0x65, 0x64, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, + 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x69, + 0x6e, 0x6b, 0x73, 0x20, 0x61, 0x72, 0x65, 0x0a, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x20, 0x69, 0x6e, + 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2e, 0x20, 0x49, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, + 0x6e, 0x74, 0x3a, 0x20, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, + 0x20, 0x61, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x2d, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, + 0x64, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x0a, 0x20, 0x73, 0x75, 0x63, 0x63, + 0x65, 0x65, 0x64, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x63, 0x68, 0x61, + 0x6e, 0x67, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x64, 0x5f, 0x64, + 0x61, 0x74, 0x65, 0x2e, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x06, 0x01, 0x12, 0x03, + 0x63, 0x06, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x06, 0x02, 0x12, 0x03, 0x63, 0x16, + 0x2c, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x06, 0x03, 0x12, 0x03, 0x63, 0x37, 0x4e, 0x0a, + 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x06, 0x04, 0x12, 0x03, 0x64, 0x04, 0x51, 0x0a, 0x10, 0x0a, + 0x09, 0x06, 0x00, 0x02, 0x06, 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x12, 0x03, 0x64, 0x04, 0x51, 0x0a, + 0x11, 0x0a, 0x0a, 0x06, 0x00, 0x02, 0x06, 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x04, 0x12, 0x03, 0x64, + 0x20, 0x4f, 0x0a, 0x0d, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x06, 0x04, 0x12, 0x04, 0x65, 0x04, 0x69, + 0x06, 0x0a, 0x0f, 0x0a, 0x07, 0x06, 0x00, 0x02, 0x06, 0x04, 0x92, 0x08, 0x12, 0x04, 0x65, 0x04, + 0x69, 0x06, 0x0a, 0x0f, 0x0a, 0x08, 0x06, 0x00, 0x02, 0x06, 0x04, 0x92, 0x08, 0x02, 0x12, 0x03, + 0x66, 0x06, 0x20, 0x0a, 0x0f, 0x0a, 0x08, 0x06, 0x00, 0x02, 0x06, 0x04, 0x92, 0x08, 0x03, 0x12, + 0x03, 0x67, 0x06, 0x6b, 0x0a, 0x0f, 0x0a, 0x08, 0x06, 0x00, 0x02, 0x06, 0x04, 0x92, 0x08, 0x05, + 0x12, 0x03, 0x68, 0x06, 0x37, 0x0a, 0x6a, 0x0a, 0x04, 0x06, 0x00, 0x02, 0x07, 0x12, 0x04, 0x6e, + 0x02, 0x75, 0x03, 0x1a, 0x5c, 0x20, 0x43, 0x6c, 0x65, 0x61, 0x72, 0x73, 0x20, 0x61, 0x72, 0x63, + 0x68, 0x69, 0x76, 0x65, 0x64, 0x5f, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x20, 0x49, 0x64, 0x65, 0x6d, + 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x75, 0x6e, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, + 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x20, 0x61, 0x72, + 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x0a, 0x20, 0x73, 0x75, 0x63, 0x63, 0x65, 0x65, 0x64, 0x73, + 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x2e, + 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x07, 0x01, 0x12, 0x03, 0x6e, 0x06, 0x17, 0x0a, + 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x07, 0x02, 0x12, 0x03, 0x6e, 0x18, 0x30, 0x0a, 0x0c, 0x0a, + 0x05, 0x06, 0x00, 0x02, 0x07, 0x03, 0x12, 0x03, 0x6e, 0x3b, 0x54, 0x0a, 0x0c, 0x0a, 0x05, 0x06, + 0x00, 0x02, 0x07, 0x04, 0x12, 0x03, 0x6f, 0x04, 0x53, 0x0a, 0x10, 0x0a, 0x09, 0x06, 0x00, 0x02, + 0x07, 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x12, 0x03, 0x6f, 0x04, 0x53, 0x0a, 0x11, 0x0a, 0x0a, 0x06, + 0x00, 0x02, 0x07, 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x04, 0x12, 0x03, 0x6f, 0x20, 0x51, 0x0a, 0x0d, + 0x0a, 0x05, 0x06, 0x00, 0x02, 0x07, 0x04, 0x12, 0x04, 0x70, 0x04, 0x74, 0x06, 0x0a, 0x0f, 0x0a, + 0x07, 0x06, 0x00, 0x02, 0x07, 0x04, 0x92, 0x08, 0x12, 0x04, 0x70, 0x04, 0x74, 0x06, 0x0a, 0x0f, + 0x0a, 0x08, 0x06, 0x00, 0x02, 0x07, 0x04, 0x92, 0x08, 0x02, 0x12, 0x03, 0x71, 0x06, 0x22, 0x0a, + 0x0f, 0x0a, 0x08, 0x06, 0x00, 0x02, 0x07, 0x04, 0x92, 0x08, 0x03, 0x12, 0x03, 0x72, 0x06, 0x2b, + 0x0a, 0x0f, 0x0a, 0x08, 0x06, 0x00, 0x02, 0x07, 0x04, 0x92, 0x08, 0x05, 0x12, 0x03, 0x73, 0x06, + 0x39, 0x0a, 0x0a, 0x0a, 0x02, 0x05, 0x00, 0x12, 0x04, 0x78, 0x00, 0x7c, 0x01, 0x0a, 0x0a, 0x0a, + 0x03, 0x05, 0x00, 0x01, 0x12, 0x03, 0x78, 0x05, 0x1a, 0x0a, 0x0b, 0x0a, 0x04, 0x05, 0x00, 0x02, + 0x00, 0x12, 0x03, 0x79, 0x02, 0x2a, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x00, 0x01, 0x12, + 0x03, 0x79, 0x02, 0x25, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x00, 0x02, 0x12, 0x03, 0x79, + 0x28, 0x29, 0x0a, 0x0b, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x01, 0x12, 0x03, 0x7a, 0x02, 0x24, 0x0a, + 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x7a, 0x02, 0x1f, 0x0a, 0x0c, 0x0a, + 0x05, 0x05, 0x00, 0x02, 0x01, 0x02, 0x12, 0x03, 0x7a, 0x22, 0x23, 0x0a, 0x0b, 0x0a, 0x04, 0x05, + 0x00, 0x02, 0x02, 0x12, 0x03, 0x7b, 0x02, 0x23, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x02, + 0x01, 0x12, 0x03, 0x7b, 0x02, 0x1e, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x02, 0x02, 0x12, + 0x03, 0x7b, 0x21, 0x22, 0x0a, 0x4d, 0x0a, 0x02, 0x04, 0x00, 0x12, 0x05, 0x7f, 0x00, 0x97, 0x01, + 0x01, 0x1a, 0x40, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x20, 0x66, 0x69, + 0x65, 0x6c, 0x64, 0x73, 0x20, 0x66, 0x6c, 0x61, 0x74, 0x74, 0x65, 0x6e, 0x65, 0x64, 0x20, 0x74, + 0x6f, 0x67, 0x65, 0x74, 0x68, 0x65, 0x72, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6f, 0x6e, 0x65, + 0x20, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x2e, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x00, 0x01, 0x12, 0x03, 0x7f, 0x08, 0x10, 0x0a, + 0x0c, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x00, 0x12, 0x04, 0x80, 0x01, 0x02, 0x19, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x00, 0x02, 0x00, 0x05, 0x12, 0x04, 0x80, 0x01, 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, 0x04, 0x80, 0x01, 0x09, 0x14, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x00, 0x02, 0x00, 0x03, 0x12, 0x04, 0x80, 0x01, 0x17, 0x18, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x00, + 0x02, 0x01, 0x12, 0x04, 0x81, 0x01, 0x02, 0x1d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, + 0x05, 0x12, 0x04, 0x81, 0x01, 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x01, + 0x12, 0x04, 0x81, 0x01, 0x09, 0x18, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x03, 0x12, + 0x04, 0x81, 0x01, 0x1b, 0x1c, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x02, 0x12, 0x04, 0x82, + 0x01, 0x02, 0x20, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x05, 0x12, 0x04, 0x82, 0x01, + 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x01, 0x12, 0x04, 0x82, 0x01, 0x09, + 0x1b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x03, 0x12, 0x04, 0x82, 0x01, 0x1e, 0x1f, + 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x03, 0x12, 0x04, 0x83, 0x01, 0x02, 0x2b, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x00, 0x02, 0x03, 0x06, 0x12, 0x04, 0x83, 0x01, 0x02, 0x17, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x00, 0x02, 0x03, 0x01, 0x12, 0x04, 0x83, 0x01, 0x18, 0x26, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x00, 0x02, 0x03, 0x03, 0x12, 0x04, 0x83, 0x01, 0x29, 0x2a, 0x0a, 0x0c, 0x0a, 0x04, 0x04, + 0x00, 0x02, 0x04, 0x12, 0x04, 0x84, 0x01, 0x02, 0x2d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, + 0x04, 0x06, 0x12, 0x04, 0x84, 0x01, 0x02, 0x1b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x04, + 0x01, 0x12, 0x04, 0x84, 0x01, 0x1c, 0x28, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x04, 0x03, + 0x12, 0x04, 0x84, 0x01, 0x2b, 0x2c, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x05, 0x12, 0x04, + 0x85, 0x01, 0x02, 0x21, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x05, 0x05, 0x12, 0x04, 0x85, + 0x01, 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x05, 0x01, 0x12, 0x04, 0x85, 0x01, + 0x09, 0x1c, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x05, 0x03, 0x12, 0x04, 0x85, 0x01, 0x1f, + 0x20, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x06, 0x12, 0x04, 0x86, 0x01, 0x02, 0x15, 0x0a, + 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x06, 0x05, 0x12, 0x04, 0x86, 0x01, 0x02, 0x08, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x00, 0x02, 0x06, 0x01, 0x12, 0x04, 0x86, 0x01, 0x09, 0x10, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x00, 0x02, 0x06, 0x03, 0x12, 0x04, 0x86, 0x01, 0x13, 0x14, 0x0a, 0x0c, 0x0a, 0x04, + 0x04, 0x00, 0x02, 0x07, 0x12, 0x04, 0x87, 0x01, 0x02, 0x1c, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x00, + 0x02, 0x07, 0x04, 0x12, 0x04, 0x87, 0x01, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, + 0x07, 0x05, 0x12, 0x04, 0x87, 0x01, 0x0b, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x07, + 0x01, 0x12, 0x04, 0x87, 0x01, 0x12, 0x17, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x07, 0x03, + 0x12, 0x04, 0x87, 0x01, 0x1a, 0x1b, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x08, 0x12, 0x04, + 0x88, 0x01, 0x02, 0x1f, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x08, 0x04, 0x12, 0x04, 0x88, + 0x01, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x08, 0x05, 0x12, 0x04, 0x88, 0x01, + 0x0b, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x08, 0x01, 0x12, 0x04, 0x88, 0x01, 0x12, + 0x19, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x08, 0x03, 0x12, 0x04, 0x88, 0x01, 0x1c, 0x1e, + 0x0a, 0xdb, 0x01, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x09, 0x12, 0x04, 0x8c, 0x01, 0x02, 0x2c, 0x1a, + 0xcc, 0x01, 0x20, 0x53, 0x65, 0x74, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x66, 0x6f, 0x72, 0x20, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x65, + 0x64, 0x20, 0x69, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, + 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x0a, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x69, 0x6e, 0x74, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x69, 0x6e, 0x67, 0x20, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x70, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x73, 0x3a, + 0x20, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x20, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x20, + 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x75, 0x73, 0x65, 0x72, 0x0a, + 0x20, 0x73, 0x65, 0x6e, 0x64, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x67, 0x65, 0x6e, + 0x74, 0x20, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x70, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x20, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x61, 0x74, + 0x20, 0x65, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x75, 0x72, 0x6e, 0x2e, 0x0a, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x00, 0x02, 0x09, 0x04, 0x12, 0x04, 0x8c, 0x01, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x00, 0x02, 0x09, 0x05, 0x12, 0x04, 0x8c, 0x01, 0x0b, 0x11, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x00, 0x02, 0x09, 0x01, 0x12, 0x04, 0x8c, 0x01, 0x12, 0x26, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x00, 0x02, 0x09, 0x03, 0x12, 0x04, 0x8c, 0x01, 0x29, 0x2b, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x00, + 0x02, 0x0a, 0x12, 0x04, 0x8d, 0x01, 0x02, 0x2b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x0a, + 0x04, 0x12, 0x04, 0x8d, 0x01, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x0a, 0x05, + 0x12, 0x04, 0x8d, 0x01, 0x0b, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x0a, 0x01, 0x12, + 0x04, 0x8d, 0x01, 0x12, 0x25, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x0a, 0x03, 0x12, 0x04, + 0x8d, 0x01, 0x28, 0x2a, 0x0a, 0x2f, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x0b, 0x12, 0x04, 0x8f, 0x01, + 0x02, 0x26, 0x1a, 0x21, 0x20, 0x55, 0x6e, 0x73, 0x65, 0x74, 0x20, 0x75, 0x6e, 0x74, 0x69, 0x6c, + 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x75, 0x70, 0x6c, 0x6f, 0x61, + 0x64, 0x65, 0x64, 0x2e, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x0b, 0x04, 0x12, 0x04, + 0x8f, 0x01, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x0b, 0x05, 0x12, 0x04, 0x8f, + 0x01, 0x0b, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x0b, 0x01, 0x12, 0x04, 0x8f, 0x01, + 0x12, 0x20, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x0b, 0x03, 0x12, 0x04, 0x8f, 0x01, 0x23, + 0x25, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x0c, 0x12, 0x04, 0x90, 0x01, 0x02, 0x36, 0x0a, + 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x0c, 0x06, 0x12, 0x04, 0x90, 0x01, 0x02, 0x1b, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x00, 0x02, 0x0c, 0x01, 0x12, 0x04, 0x90, 0x01, 0x1c, 0x30, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x00, 0x02, 0x0c, 0x03, 0x12, 0x04, 0x90, 0x01, 0x33, 0x35, 0x0a, 0x96, 0x01, 0x0a, + 0x04, 0x04, 0x00, 0x02, 0x0d, 0x12, 0x04, 0x93, 0x01, 0x02, 0x21, 0x1a, 0x87, 0x01, 0x20, 0x46, + 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x27, + 0x73, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x72, + 0x6f, 0x77, 0x2e, 0x20, 0x55, 0x6e, 0x73, 0x65, 0x74, 0x20, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x20, + 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, + 0x65, 0x64, 0x2e, 0x0a, 0x20, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x69, 0x6e, 0x66, + 0x65, 0x72, 0x20, 0x70, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x20, 0x62, 0x65, 0x68, 0x61, 0x76, + 0x69, 0x6f, 0x72, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x6e, 0x61, + 0x6d, 0x65, 0x20, 0x2f, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x6d, 0x69, 0x6d, 0x65, 0x5f, 0x74, + 0x79, 0x70, 0x65, 0x2e, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x0d, 0x04, 0x12, 0x04, + 0x93, 0x01, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x0d, 0x05, 0x12, 0x04, 0x93, + 0x01, 0x0b, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x0d, 0x01, 0x12, 0x04, 0x93, 0x01, + 0x12, 0x1b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x0d, 0x03, 0x12, 0x04, 0x93, 0x01, 0x1e, + 0x20, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x0e, 0x12, 0x04, 0x94, 0x01, 0x02, 0x26, 0x0a, + 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x0e, 0x04, 0x12, 0x04, 0x94, 0x01, 0x02, 0x0a, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x00, 0x02, 0x0e, 0x05, 0x12, 0x04, 0x94, 0x01, 0x0b, 0x11, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x00, 0x02, 0x0e, 0x01, 0x12, 0x04, 0x94, 0x01, 0x12, 0x20, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x00, 0x02, 0x0e, 0x03, 0x12, 0x04, 0x94, 0x01, 0x23, 0x25, 0x0a, 0x33, 0x0a, 0x04, 0x04, + 0x00, 0x02, 0x0f, 0x12, 0x04, 0x96, 0x01, 0x02, 0x38, 0x1a, 0x25, 0x20, 0x55, 0x6e, 0x73, 0x65, + 0x74, 0x20, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x74, 0x69, + 0x66, 0x61, 0x63, 0x74, 0x20, 0x69, 0x73, 0x20, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2e, 0x0a, + 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x0f, 0x04, 0x12, 0x04, 0x96, 0x01, 0x02, 0x0a, 0x0a, + 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x0f, 0x06, 0x12, 0x04, 0x96, 0x01, 0x0b, 0x24, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x00, 0x02, 0x0f, 0x01, 0x12, 0x04, 0x96, 0x01, 0x25, 0x32, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x00, 0x02, 0x0f, 0x03, 0x12, 0x04, 0x96, 0x01, 0x35, 0x37, 0x0a, 0x0c, 0x0a, 0x02, + 0x04, 0x01, 0x12, 0x06, 0x99, 0x01, 0x00, 0xa6, 0x01, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x01, + 0x01, 0x12, 0x04, 0x99, 0x01, 0x08, 0x17, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x00, 0x12, + 0x04, 0x9a, 0x01, 0x02, 0x21, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x05, 0x12, 0x04, + 0x9a, 0x01, 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x01, 0x12, 0x04, 0x9a, + 0x01, 0x09, 0x1c, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x03, 0x12, 0x04, 0x9a, 0x01, + 0x1f, 0x20, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x01, 0x12, 0x04, 0x9b, 0x01, 0x02, 0x19, + 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x05, 0x12, 0x04, 0x9b, 0x01, 0x02, 0x08, 0x0a, + 0x0d, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x01, 0x12, 0x04, 0x9b, 0x01, 0x09, 0x14, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x03, 0x12, 0x04, 0x9b, 0x01, 0x17, 0x18, 0x0a, 0x0c, 0x0a, + 0x04, 0x04, 0x01, 0x02, 0x02, 0x12, 0x04, 0x9c, 0x01, 0x02, 0x15, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x01, 0x02, 0x02, 0x05, 0x12, 0x04, 0x9c, 0x01, 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x01, + 0x02, 0x02, 0x01, 0x12, 0x04, 0x9c, 0x01, 0x09, 0x10, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x01, 0x02, + 0x02, 0x03, 0x12, 0x04, 0x9c, 0x01, 0x13, 0x14, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x03, + 0x12, 0x04, 0x9d, 0x01, 0x02, 0x1c, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x03, 0x04, 0x12, + 0x04, 0x9d, 0x01, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x03, 0x05, 0x12, 0x04, + 0x9d, 0x01, 0x0b, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x03, 0x01, 0x12, 0x04, 0x9d, + 0x01, 0x12, 0x17, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x03, 0x03, 0x12, 0x04, 0x9d, 0x01, + 0x1a, 0x1b, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x04, 0x12, 0x04, 0x9e, 0x01, 0x02, 0x1e, + 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x04, 0x04, 0x12, 0x04, 0x9e, 0x01, 0x02, 0x0a, 0x0a, + 0x0d, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x04, 0x05, 0x12, 0x04, 0x9e, 0x01, 0x0b, 0x11, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x01, 0x02, 0x04, 0x01, 0x12, 0x04, 0x9e, 0x01, 0x12, 0x19, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x01, 0x02, 0x04, 0x03, 0x12, 0x04, 0x9e, 0x01, 0x1c, 0x1d, 0x0a, 0x0c, 0x0a, 0x04, + 0x04, 0x01, 0x02, 0x05, 0x12, 0x04, 0x9f, 0x01, 0x02, 0x2b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x01, + 0x02, 0x05, 0x04, 0x12, 0x04, 0x9f, 0x01, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x01, 0x02, + 0x05, 0x05, 0x12, 0x04, 0x9f, 0x01, 0x0b, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x05, + 0x01, 0x12, 0x04, 0x9f, 0x01, 0x12, 0x26, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x05, 0x03, + 0x12, 0x04, 0x9f, 0x01, 0x29, 0x2a, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x06, 0x12, 0x04, + 0xa0, 0x01, 0x02, 0x2a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x06, 0x04, 0x12, 0x04, 0xa0, + 0x01, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x06, 0x05, 0x12, 0x04, 0xa0, 0x01, + 0x0b, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x06, 0x01, 0x12, 0x04, 0xa0, 0x01, 0x12, + 0x25, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x06, 0x03, 0x12, 0x04, 0xa0, 0x01, 0x28, 0x29, + 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x07, 0x12, 0x04, 0xa1, 0x01, 0x02, 0x25, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x01, 0x02, 0x07, 0x04, 0x12, 0x04, 0xa1, 0x01, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x01, 0x02, 0x07, 0x05, 0x12, 0x04, 0xa1, 0x01, 0x0b, 0x11, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x01, 0x02, 0x07, 0x01, 0x12, 0x04, 0xa1, 0x01, 0x12, 0x20, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x01, 0x02, 0x07, 0x03, 0x12, 0x04, 0xa1, 0x01, 0x23, 0x24, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x01, + 0x02, 0x08, 0x12, 0x04, 0xa2, 0x01, 0x02, 0x2d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x08, + 0x06, 0x12, 0x04, 0xa2, 0x01, 0x02, 0x1b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x08, 0x01, + 0x12, 0x04, 0xa2, 0x01, 0x1c, 0x28, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x08, 0x03, 0x12, + 0x04, 0xa2, 0x01, 0x2b, 0x2c, 0x0a, 0x54, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x09, 0x12, 0x04, 0xa4, + 0x01, 0x02, 0x21, 0x1a, 0x46, 0x20, 0x46, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x76, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x27, 0x73, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, + 0x66, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x72, 0x6f, 0x77, 0x2e, 0x20, 0x55, 0x6e, 0x73, 0x65, 0x74, + 0x20, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x61, 0x72, 0x65, + 0x20, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x2e, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x01, 0x02, 0x09, 0x04, 0x12, 0x04, 0xa4, 0x01, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x01, + 0x02, 0x09, 0x05, 0x12, 0x04, 0xa4, 0x01, 0x0b, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x01, 0x02, + 0x09, 0x01, 0x12, 0x04, 0xa4, 0x01, 0x12, 0x1b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x09, + 0x03, 0x12, 0x04, 0xa4, 0x01, 0x1e, 0x20, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x0a, 0x12, + 0x04, 0xa5, 0x01, 0x02, 0x26, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x0a, 0x04, 0x12, 0x04, + 0xa5, 0x01, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x0a, 0x05, 0x12, 0x04, 0xa5, + 0x01, 0x0b, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x0a, 0x01, 0x12, 0x04, 0xa5, 0x01, + 0x12, 0x20, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x0a, 0x03, 0x12, 0x04, 0xa5, 0x01, 0x23, + 0x25, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x02, 0x12, 0x06, 0xa8, 0x01, 0x00, 0xb5, 0x01, 0x01, 0x0a, + 0x0b, 0x0a, 0x03, 0x04, 0x02, 0x01, 0x12, 0x04, 0xa8, 0x01, 0x08, 0x1d, 0x0a, 0x55, 0x0a, 0x04, + 0x04, 0x02, 0x02, 0x00, 0x12, 0x04, 0xaa, 0x01, 0x02, 0x22, 0x1a, 0x47, 0x20, 0x53, 0x65, 0x74, + 0x20, 0x74, 0x6f, 0x20, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x76, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6e, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, + 0x69, 0x6e, 0x67, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x3b, 0x20, 0x75, 0x6e, + 0x73, 0x65, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x20, 0x6f, 0x6e, + 0x65, 0x2e, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x04, 0x12, 0x04, 0xaa, 0x01, + 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x05, 0x12, 0x04, 0xaa, 0x01, 0x0b, + 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x01, 0x12, 0x04, 0xaa, 0x01, 0x12, 0x1d, + 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x03, 0x12, 0x04, 0xaa, 0x01, 0x20, 0x21, 0x0a, + 0x9e, 0x01, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x01, 0x12, 0x04, 0xad, 0x01, 0x02, 0x26, 0x1a, 0x8f, + 0x01, 0x20, 0x53, 0x65, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x20, 0x74, + 0x6f, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x20, 0x61, 0x74, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x2e, + 0x20, 0x4c, 0x65, 0x67, 0x61, 0x6c, 0x0a, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x20, + 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x20, 0x28, 0x6e, 0x6f, 0x74, 0x20, 0x6f, 0x6e, 0x20, 0x61, + 0x70, 0x70, 0x65, 0x6e, 0x64, 0x29, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x6e, 0x6c, 0x79, + 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x27, 0x73, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x2e, 0x0a, + 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, 0x04, 0x12, 0x04, 0xad, 0x01, 0x02, 0x0a, 0x0a, + 0x0d, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, 0x05, 0x12, 0x04, 0xad, 0x01, 0x0b, 0x11, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, 0x01, 0x12, 0x04, 0xad, 0x01, 0x12, 0x21, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x02, 0x02, 0x01, 0x03, 0x12, 0x04, 0xad, 0x01, 0x24, 0x25, 0x0a, 0x0c, 0x0a, 0x04, + 0x04, 0x02, 0x02, 0x02, 0x12, 0x04, 0xae, 0x01, 0x02, 0x1c, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x02, + 0x02, 0x02, 0x04, 0x12, 0x04, 0xae, 0x01, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x02, 0x02, + 0x02, 0x05, 0x12, 0x04, 0xae, 0x01, 0x0b, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x02, + 0x01, 0x12, 0x04, 0xae, 0x01, 0x12, 0x17, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x02, 0x03, + 0x12, 0x04, 0xae, 0x01, 0x1a, 0x1b, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x03, 0x12, 0x04, + 0xaf, 0x01, 0x02, 0x1e, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x03, 0x04, 0x12, 0x04, 0xaf, + 0x01, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x03, 0x05, 0x12, 0x04, 0xaf, 0x01, + 0x0b, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x03, 0x01, 0x12, 0x04, 0xaf, 0x01, 0x12, + 0x19, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x03, 0x03, 0x12, 0x04, 0xaf, 0x01, 0x1c, 0x1d, + 0x0a, 0x8a, 0x02, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x04, 0x12, 0x04, 0xb4, 0x01, 0x02, 0x34, 0x1a, + 0xfb, 0x01, 0x20, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x55, + 0x53, 0x45, 0x52, 0x2e, 0x20, 0x41, 0x47, 0x45, 0x4e, 0x54, 0x20, 0x69, 0x73, 0x20, 0x73, 0x65, + 0x6c, 0x66, 0x2d, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x3a, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x20, 0x70, 0x6f, 0x64, 0x20, 0x61, 0x75, 0x74, 0x68, 0x65, + 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x0a, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x75, 0x73, + 0x65, 0x72, 0x27, 0x73, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x6b, + 0x65, 0x79, 0x2c, 0x20, 0x73, 0x6f, 0x20, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x20, 0x73, 0x63, 0x6f, + 0x70, 0x65, 0x64, 0x20, 0x70, 0x6f, 0x64, 0x0a, 0x20, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, + 0x69, 0x61, 0x6c, 0x73, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x28, 0x45, 0x4e, 0x47, 0x2d, 0x31, + 0x32, 0x38, 0x33, 0x31, 0x29, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x73, 0x68, 0x69, 0x70, + 0x20, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x69, 0x64, + 0x65, 0x73, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x0a, 0x20, + 0x74, 0x72, 0x75, 0x73, 0x74, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x6f, 0x64, + 0x27, 0x73, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x70, 0x65, 0x72, 0x73, 0x69, + 0x73, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x70, 0x61, 0x74, 0x68, 0x2e, 0x0a, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x02, 0x02, 0x04, 0x04, 0x12, 0x04, 0xb4, 0x01, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x02, 0x02, 0x04, 0x06, 0x12, 0x04, 0xb4, 0x01, 0x0b, 0x20, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x02, 0x02, 0x04, 0x01, 0x12, 0x04, 0xb4, 0x01, 0x21, 0x2f, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x02, + 0x02, 0x04, 0x03, 0x12, 0x04, 0xb4, 0x01, 0x32, 0x33, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x03, 0x12, + 0x06, 0xb7, 0x01, 0x00, 0xb9, 0x01, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x03, 0x01, 0x12, 0x04, + 0xb7, 0x01, 0x08, 0x1e, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x03, 0x02, 0x00, 0x12, 0x04, 0xb8, 0x01, + 0x02, 0x18, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x06, 0x12, 0x04, 0xb8, 0x01, 0x02, + 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x01, 0x12, 0x04, 0xb8, 0x01, 0x0b, 0x13, + 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x03, 0x12, 0x04, 0xb8, 0x01, 0x16, 0x17, 0x0a, + 0x0c, 0x0a, 0x02, 0x04, 0x04, 0x12, 0x06, 0xbb, 0x01, 0x00, 0xbe, 0x01, 0x01, 0x0a, 0x0b, 0x0a, + 0x03, 0x04, 0x04, 0x01, 0x12, 0x04, 0xbb, 0x01, 0x08, 0x1a, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x04, + 0x02, 0x00, 0x12, 0x04, 0xbc, 0x01, 0x02, 0x19, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x00, + 0x05, 0x12, 0x04, 0xbc, 0x01, 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x00, 0x01, + 0x12, 0x04, 0xbc, 0x01, 0x09, 0x14, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x00, 0x03, 0x12, + 0x04, 0xbc, 0x01, 0x17, 0x18, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x04, 0x02, 0x01, 0x12, 0x04, 0xbd, + 0x01, 0x02, 0x2a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x01, 0x04, 0x12, 0x04, 0xbd, 0x01, + 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x01, 0x05, 0x12, 0x04, 0xbd, 0x01, 0x0b, + 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x01, 0x01, 0x12, 0x04, 0xbd, 0x01, 0x12, 0x25, + 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x01, 0x03, 0x12, 0x04, 0xbd, 0x01, 0x28, 0x29, 0x0a, + 0x0c, 0x0a, 0x02, 0x04, 0x05, 0x12, 0x06, 0xc0, 0x01, 0x00, 0xc2, 0x01, 0x01, 0x0a, 0x0b, 0x0a, + 0x03, 0x04, 0x05, 0x01, 0x12, 0x04, 0xc0, 0x01, 0x08, 0x1b, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x05, + 0x02, 0x00, 0x12, 0x04, 0xc1, 0x01, 0x02, 0x18, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x00, + 0x06, 0x12, 0x04, 0xc1, 0x01, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x00, 0x01, + 0x12, 0x04, 0xc1, 0x01, 0x0b, 0x13, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x00, 0x03, 0x12, + 0x04, 0xc1, 0x01, 0x16, 0x17, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x06, 0x12, 0x06, 0xc4, 0x01, 0x00, + 0xcb, 0x01, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x06, 0x01, 0x12, 0x04, 0xc4, 0x01, 0x08, 0x1c, + 0x0a, 0x48, 0x0a, 0x04, 0x04, 0x06, 0x02, 0x00, 0x12, 0x04, 0xc6, 0x01, 0x02, 0x26, 0x1a, 0x3a, + 0x20, 0x55, 0x6e, 0x73, 0x65, 0x74, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x73, 0x20, 0x65, 0x76, 0x65, + 0x72, 0x79, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x27, 0x73, 0x20, 0x6f, 0x72, 0x67, 0x61, + 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x06, + 0x02, 0x00, 0x04, 0x12, 0x04, 0xc6, 0x01, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x06, 0x02, + 0x00, 0x05, 0x12, 0x04, 0xc6, 0x01, 0x0b, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x00, + 0x01, 0x12, 0x04, 0xc6, 0x01, 0x12, 0x21, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x00, 0x03, + 0x12, 0x04, 0xc6, 0x01, 0x24, 0x25, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x06, 0x02, 0x01, 0x12, 0x04, + 0xc7, 0x01, 0x02, 0x17, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x01, 0x05, 0x12, 0x04, 0xc7, + 0x01, 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x01, 0x01, 0x12, 0x04, 0xc7, 0x01, + 0x09, 0x12, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x01, 0x03, 0x12, 0x04, 0xc7, 0x01, 0x15, + 0x16, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x06, 0x02, 0x02, 0x12, 0x04, 0xc8, 0x01, 0x02, 0x18, 0x0a, + 0x0d, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x02, 0x05, 0x12, 0x04, 0xc8, 0x01, 0x02, 0x08, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x06, 0x02, 0x02, 0x01, 0x12, 0x04, 0xc8, 0x01, 0x09, 0x13, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x06, 0x02, 0x02, 0x03, 0x12, 0x04, 0xc8, 0x01, 0x16, 0x17, 0x0a, 0x49, 0x0a, 0x04, + 0x04, 0x06, 0x02, 0x03, 0x12, 0x04, 0xca, 0x01, 0x02, 0x1c, 0x1a, 0x3b, 0x20, 0x57, 0x68, 0x65, + 0x6e, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x20, 0x28, 0x74, 0x68, 0x65, 0x20, 0x64, 0x65, 0x66, + 0x61, 0x75, 0x6c, 0x74, 0x29, 0x2c, 0x20, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x64, 0x20, + 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6f, 0x6d, + 0x69, 0x74, 0x74, 0x65, 0x64, 0x2e, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x03, 0x05, + 0x12, 0x04, 0xca, 0x01, 0x02, 0x06, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x03, 0x01, 0x12, + 0x04, 0xca, 0x01, 0x07, 0x17, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x03, 0x03, 0x12, 0x04, + 0xca, 0x01, 0x1a, 0x1b, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x07, 0x12, 0x06, 0xcd, 0x01, 0x00, 0xd0, + 0x01, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x07, 0x01, 0x12, 0x04, 0xcd, 0x01, 0x08, 0x1d, 0x0a, + 0x0c, 0x0a, 0x04, 0x04, 0x07, 0x02, 0x00, 0x12, 0x04, 0xce, 0x01, 0x02, 0x22, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x07, 0x02, 0x00, 0x04, 0x12, 0x04, 0xce, 0x01, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x07, 0x02, 0x00, 0x06, 0x12, 0x04, 0xce, 0x01, 0x0b, 0x13, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x07, 0x02, 0x00, 0x01, 0x12, 0x04, 0xce, 0x01, 0x14, 0x1d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x07, + 0x02, 0x00, 0x03, 0x12, 0x04, 0xce, 0x01, 0x20, 0x21, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x07, 0x02, + 0x01, 0x12, 0x04, 0xcf, 0x01, 0x02, 0x1d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x07, 0x02, 0x01, 0x05, + 0x12, 0x04, 0xcf, 0x01, 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x07, 0x02, 0x01, 0x01, 0x12, + 0x04, 0xcf, 0x01, 0x09, 0x18, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x07, 0x02, 0x01, 0x03, 0x12, 0x04, + 0xcf, 0x01, 0x1b, 0x1c, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x08, 0x12, 0x06, 0xd2, 0x01, 0x00, 0xd6, + 0x01, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x08, 0x01, 0x12, 0x04, 0xd2, 0x01, 0x08, 0x23, 0x0a, + 0x0c, 0x0a, 0x04, 0x04, 0x08, 0x02, 0x00, 0x12, 0x04, 0xd3, 0x01, 0x02, 0x19, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x08, 0x02, 0x00, 0x05, 0x12, 0x04, 0xd3, 0x01, 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x08, 0x02, 0x00, 0x01, 0x12, 0x04, 0xd3, 0x01, 0x09, 0x14, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x08, 0x02, 0x00, 0x03, 0x12, 0x04, 0xd3, 0x01, 0x17, 0x18, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x08, + 0x02, 0x01, 0x12, 0x04, 0xd4, 0x01, 0x02, 0x17, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x08, 0x02, 0x01, + 0x05, 0x12, 0x04, 0xd4, 0x01, 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x08, 0x02, 0x01, 0x01, + 0x12, 0x04, 0xd4, 0x01, 0x09, 0x12, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x08, 0x02, 0x01, 0x03, 0x12, + 0x04, 0xd4, 0x01, 0x15, 0x16, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x08, 0x02, 0x02, 0x12, 0x04, 0xd5, + 0x01, 0x02, 0x18, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x08, 0x02, 0x02, 0x05, 0x12, 0x04, 0xd5, 0x01, + 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x08, 0x02, 0x02, 0x01, 0x12, 0x04, 0xd5, 0x01, 0x09, + 0x13, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x08, 0x02, 0x02, 0x03, 0x12, 0x04, 0xd5, 0x01, 0x16, 0x17, + 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x09, 0x12, 0x06, 0xd8, 0x01, 0x00, 0xdb, 0x01, 0x01, 0x0a, 0x0b, + 0x0a, 0x03, 0x04, 0x09, 0x01, 0x12, 0x04, 0xd8, 0x01, 0x08, 0x24, 0x0a, 0x0c, 0x0a, 0x04, 0x04, + 0x09, 0x02, 0x00, 0x12, 0x04, 0xd9, 0x01, 0x02, 0x28, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x09, 0x02, + 0x00, 0x04, 0x12, 0x04, 0xd9, 0x01, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x09, 0x02, 0x00, + 0x06, 0x12, 0x04, 0xd9, 0x01, 0x0b, 0x1a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x09, 0x02, 0x00, 0x01, + 0x12, 0x04, 0xd9, 0x01, 0x1b, 0x23, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x09, 0x02, 0x00, 0x03, 0x12, + 0x04, 0xd9, 0x01, 0x26, 0x27, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x09, 0x02, 0x01, 0x12, 0x04, 0xda, + 0x01, 0x02, 0x1d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x09, 0x02, 0x01, 0x05, 0x12, 0x04, 0xda, 0x01, + 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x09, 0x02, 0x01, 0x01, 0x12, 0x04, 0xda, 0x01, 0x09, + 0x18, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x09, 0x02, 0x01, 0x03, 0x12, 0x04, 0xda, 0x01, 0x1b, 0x1c, + 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x0a, 0x12, 0x06, 0xdd, 0x01, 0x00, 0xe0, 0x01, 0x01, 0x0a, 0x0b, + 0x0a, 0x03, 0x04, 0x0a, 0x01, 0x12, 0x04, 0xdd, 0x01, 0x08, 0x29, 0x0a, 0x0c, 0x0a, 0x04, 0x04, + 0x0a, 0x02, 0x00, 0x12, 0x04, 0xde, 0x01, 0x02, 0x19, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0a, 0x02, + 0x00, 0x05, 0x12, 0x04, 0xde, 0x01, 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0a, 0x02, 0x00, + 0x01, 0x12, 0x04, 0xde, 0x01, 0x09, 0x14, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0a, 0x02, 0x00, 0x03, + 0x12, 0x04, 0xde, 0x01, 0x17, 0x18, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x0a, 0x02, 0x01, 0x12, 0x04, + 0xdf, 0x01, 0x02, 0x1d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0a, 0x02, 0x01, 0x05, 0x12, 0x04, 0xdf, + 0x01, 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0a, 0x02, 0x01, 0x01, 0x12, 0x04, 0xdf, 0x01, + 0x09, 0x18, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0a, 0x02, 0x01, 0x03, 0x12, 0x04, 0xdf, 0x01, 0x1b, + 0x1c, 0x0a, 0x0a, 0x0a, 0x02, 0x04, 0x0b, 0x12, 0x04, 0xe2, 0x01, 0x00, 0x2d, 0x0a, 0x0b, 0x0a, + 0x03, 0x04, 0x0b, 0x01, 0x12, 0x04, 0xe2, 0x01, 0x08, 0x2a, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x0c, + 0x12, 0x06, 0xe4, 0x01, 0x00, 0xe7, 0x01, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x0c, 0x01, 0x12, + 0x04, 0xe4, 0x01, 0x08, 0x2d, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x0c, 0x02, 0x00, 0x12, 0x04, 0xe5, + 0x01, 0x02, 0x19, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0c, 0x02, 0x00, 0x05, 0x12, 0x04, 0xe5, 0x01, + 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0c, 0x02, 0x00, 0x01, 0x12, 0x04, 0xe5, 0x01, 0x09, + 0x14, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0c, 0x02, 0x00, 0x03, 0x12, 0x04, 0xe5, 0x01, 0x17, 0x18, + 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x0c, 0x02, 0x01, 0x12, 0x04, 0xe6, 0x01, 0x02, 0x1d, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x0c, 0x02, 0x01, 0x05, 0x12, 0x04, 0xe6, 0x01, 0x02, 0x08, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x0c, 0x02, 0x01, 0x01, 0x12, 0x04, 0xe6, 0x01, 0x09, 0x18, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x0c, 0x02, 0x01, 0x03, 0x12, 0x04, 0xe6, 0x01, 0x1b, 0x1c, 0x0a, 0x0a, 0x0a, 0x02, 0x04, + 0x0d, 0x12, 0x04, 0xe9, 0x01, 0x00, 0x31, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x0d, 0x01, 0x12, 0x04, + 0xe9, 0x01, 0x08, 0x2e, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x0e, 0x12, 0x06, 0xeb, 0x01, 0x00, 0xed, + 0x01, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x0e, 0x01, 0x12, 0x04, 0xeb, 0x01, 0x08, 0x1e, 0x0a, + 0x0c, 0x0a, 0x04, 0x04, 0x0e, 0x02, 0x00, 0x12, 0x04, 0xec, 0x01, 0x02, 0x19, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x0e, 0x02, 0x00, 0x05, 0x12, 0x04, 0xec, 0x01, 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x0e, 0x02, 0x00, 0x01, 0x12, 0x04, 0xec, 0x01, 0x09, 0x14, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x0e, 0x02, 0x00, 0x03, 0x12, 0x04, 0xec, 0x01, 0x17, 0x18, 0x0a, 0x0a, 0x0a, 0x02, 0x04, 0x0f, + 0x12, 0x04, 0xef, 0x01, 0x00, 0x22, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x0f, 0x01, 0x12, 0x04, 0xef, + 0x01, 0x08, 0x1f, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x10, 0x12, 0x06, 0xf1, 0x01, 0x00, 0xf3, 0x01, + 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x10, 0x01, 0x12, 0x04, 0xf1, 0x01, 0x08, 0x20, 0x0a, 0x0c, + 0x0a, 0x04, 0x04, 0x10, 0x02, 0x00, 0x12, 0x04, 0xf2, 0x01, 0x02, 0x19, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x10, 0x02, 0x00, 0x05, 0x12, 0x04, 0xf2, 0x01, 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x10, 0x02, 0x00, 0x01, 0x12, 0x04, 0xf2, 0x01, 0x09, 0x14, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x10, + 0x02, 0x00, 0x03, 0x12, 0x04, 0xf2, 0x01, 0x17, 0x18, 0x0a, 0x0a, 0x0a, 0x02, 0x04, 0x11, 0x12, + 0x04, 0xf5, 0x01, 0x00, 0x24, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x11, 0x01, 0x12, 0x04, 0xf5, 0x01, + 0x08, 0x21, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +]; +include!("sift.artifacts.v1.tonic.rs"); +include!("sift.artifacts.v1.serde.rs"); +// @@protoc_insertion_point(module) \ No newline at end of file diff --git a/rust/crates/sift_rs/src/gen/sift/artifacts/v1/sift.artifacts.v1.serde.rs b/rust/crates/sift_rs/src/gen/sift/artifacts/v1/sift.artifacts.v1.serde.rs new file mode 100644 index 000000000..2ee3a723e --- /dev/null +++ b/rust/crates/sift_rs/src/gen/sift/artifacts/v1/sift.artifacts.v1.serde.rs @@ -0,0 +1,2349 @@ +// @generated +impl serde::Serialize for ArchiveArtifactRequest { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.artifact_id.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("sift.artifacts.v1.ArchiveArtifactRequest", len)?; + if !self.artifact_id.is_empty() { + struct_ser.serialize_field("artifactId", &self.artifact_id)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for ArchiveArtifactRequest { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "artifact_id", + "artifactId", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + ArtifactId, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "artifactId" | "artifact_id" => Ok(GeneratedField::ArtifactId), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = ArchiveArtifactRequest; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct sift.artifacts.v1.ArchiveArtifactRequest") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut artifact_id__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::ArtifactId => { + if artifact_id__.is_some() { + return Err(serde::de::Error::duplicate_field("artifactId")); + } + artifact_id__ = Some(map_.next_value()?); + } + } + } + Ok(ArchiveArtifactRequest { + artifact_id: artifact_id__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("sift.artifacts.v1.ArchiveArtifactRequest", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for ArchiveArtifactResponse { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let len = 0; + let struct_ser = serializer.serialize_struct("sift.artifacts.v1.ArchiveArtifactResponse", len)?; + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for ArchiveArtifactResponse { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + Err(serde::de::Error::unknown_field(value, FIELDS)) + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = ArchiveArtifactResponse; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct sift.artifacts.v1.ArchiveArtifactResponse") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + while map_.next_key::()?.is_some() { + let _ = map_.next_value::()?; + } + Ok(ArchiveArtifactResponse { + }) + } + } + deserializer.deserialize_struct("sift.artifacts.v1.ArchiveArtifactResponse", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for Artifact { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.artifact_id.is_empty() { + len += 1; + } + if !self.organization_id.is_empty() { + len += 1; + } + if !self.created_by_user_id.is_empty() { + len += 1; + } + if self.authoring_kind != 0 { + len += 1; + } + if self.created_date.is_some() { + len += 1; + } + if !self.artifact_version_id.is_empty() { + len += 1; + } + if self.version != 0 { + len += 1; + } + if self.title.is_some() { + len += 1; + } + if self.summary.is_some() { + len += 1; + } + if self.authoring_message_id.is_some() { + len += 1; + } + if !self.source_tool_use_ids.is_empty() { + len += 1; + } + if self.remote_file_id.is_some() { + len += 1; + } + if self.version_created_date.is_some() { + len += 1; + } + if self.file_name.is_some() { + len += 1; + } + if self.file_mime_type.is_some() { + len += 1; + } + if self.archived_date.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("sift.artifacts.v1.Artifact", len)?; + if !self.artifact_id.is_empty() { + struct_ser.serialize_field("artifactId", &self.artifact_id)?; + } + if !self.organization_id.is_empty() { + struct_ser.serialize_field("organizationId", &self.organization_id)?; + } + if !self.created_by_user_id.is_empty() { + struct_ser.serialize_field("createdByUserId", &self.created_by_user_id)?; + } + if self.authoring_kind != 0 { + let v = ArtifactAuthoringKind::try_from(self.authoring_kind) + .map_err(|_| serde::ser::Error::custom(format!("Invalid variant {}", self.authoring_kind)))?; + struct_ser.serialize_field("authoringKind", &v)?; + } + if let Some(v) = self.created_date.as_ref() { + struct_ser.serialize_field("createdDate", v)?; + } + if !self.artifact_version_id.is_empty() { + struct_ser.serialize_field("artifactVersionId", &self.artifact_version_id)?; + } + if self.version != 0 { + struct_ser.serialize_field("version", &self.version)?; + } + if let Some(v) = self.title.as_ref() { + struct_ser.serialize_field("title", v)?; + } + if let Some(v) = self.summary.as_ref() { + struct_ser.serialize_field("summary", v)?; + } + if let Some(v) = self.authoring_message_id.as_ref() { + struct_ser.serialize_field("authoringMessageId", v)?; + } + if !self.source_tool_use_ids.is_empty() { + struct_ser.serialize_field("sourceToolUseIds", &self.source_tool_use_ids)?; + } + if let Some(v) = self.remote_file_id.as_ref() { + struct_ser.serialize_field("remoteFileId", v)?; + } + if let Some(v) = self.version_created_date.as_ref() { + struct_ser.serialize_field("versionCreatedDate", v)?; + } + if let Some(v) = self.file_name.as_ref() { + struct_ser.serialize_field("fileName", v)?; + } + if let Some(v) = self.file_mime_type.as_ref() { + struct_ser.serialize_field("fileMimeType", v)?; + } + if let Some(v) = self.archived_date.as_ref() { + struct_ser.serialize_field("archivedDate", v)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for Artifact { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "artifact_id", + "artifactId", + "organization_id", + "organizationId", + "created_by_user_id", + "createdByUserId", + "authoring_kind", + "authoringKind", + "created_date", + "createdDate", + "artifact_version_id", + "artifactVersionId", + "version", + "title", + "summary", + "authoring_message_id", + "authoringMessageId", + "source_tool_use_ids", + "sourceToolUseIds", + "remote_file_id", + "remoteFileId", + "version_created_date", + "versionCreatedDate", + "file_name", + "fileName", + "file_mime_type", + "fileMimeType", + "archived_date", + "archivedDate", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + ArtifactId, + OrganizationId, + CreatedByUserId, + AuthoringKind, + CreatedDate, + ArtifactVersionId, + Version, + Title, + Summary, + AuthoringMessageId, + SourceToolUseIds, + RemoteFileId, + VersionCreatedDate, + FileName, + FileMimeType, + ArchivedDate, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "artifactId" | "artifact_id" => Ok(GeneratedField::ArtifactId), + "organizationId" | "organization_id" => Ok(GeneratedField::OrganizationId), + "createdByUserId" | "created_by_user_id" => Ok(GeneratedField::CreatedByUserId), + "authoringKind" | "authoring_kind" => Ok(GeneratedField::AuthoringKind), + "createdDate" | "created_date" => Ok(GeneratedField::CreatedDate), + "artifactVersionId" | "artifact_version_id" => Ok(GeneratedField::ArtifactVersionId), + "version" => Ok(GeneratedField::Version), + "title" => Ok(GeneratedField::Title), + "summary" => Ok(GeneratedField::Summary), + "authoringMessageId" | "authoring_message_id" => Ok(GeneratedField::AuthoringMessageId), + "sourceToolUseIds" | "source_tool_use_ids" => Ok(GeneratedField::SourceToolUseIds), + "remoteFileId" | "remote_file_id" => Ok(GeneratedField::RemoteFileId), + "versionCreatedDate" | "version_created_date" => Ok(GeneratedField::VersionCreatedDate), + "fileName" | "file_name" => Ok(GeneratedField::FileName), + "fileMimeType" | "file_mime_type" => Ok(GeneratedField::FileMimeType), + "archivedDate" | "archived_date" => Ok(GeneratedField::ArchivedDate), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = Artifact; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct sift.artifacts.v1.Artifact") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut artifact_id__ = None; + let mut organization_id__ = None; + let mut created_by_user_id__ = None; + let mut authoring_kind__ = None; + let mut created_date__ = None; + let mut artifact_version_id__ = None; + let mut version__ = None; + let mut title__ = None; + let mut summary__ = None; + let mut authoring_message_id__ = None; + let mut source_tool_use_ids__ = None; + let mut remote_file_id__ = None; + let mut version_created_date__ = None; + let mut file_name__ = None; + let mut file_mime_type__ = None; + let mut archived_date__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::ArtifactId => { + if artifact_id__.is_some() { + return Err(serde::de::Error::duplicate_field("artifactId")); + } + artifact_id__ = Some(map_.next_value()?); + } + GeneratedField::OrganizationId => { + if organization_id__.is_some() { + return Err(serde::de::Error::duplicate_field("organizationId")); + } + organization_id__ = Some(map_.next_value()?); + } + GeneratedField::CreatedByUserId => { + if created_by_user_id__.is_some() { + return Err(serde::de::Error::duplicate_field("createdByUserId")); + } + created_by_user_id__ = Some(map_.next_value()?); + } + GeneratedField::AuthoringKind => { + if authoring_kind__.is_some() { + return Err(serde::de::Error::duplicate_field("authoringKind")); + } + authoring_kind__ = Some(map_.next_value::()? as i32); + } + GeneratedField::CreatedDate => { + if created_date__.is_some() { + return Err(serde::de::Error::duplicate_field("createdDate")); + } + created_date__ = map_.next_value()?; + } + GeneratedField::ArtifactVersionId => { + if artifact_version_id__.is_some() { + return Err(serde::de::Error::duplicate_field("artifactVersionId")); + } + artifact_version_id__ = Some(map_.next_value()?); + } + GeneratedField::Version => { + if version__.is_some() { + return Err(serde::de::Error::duplicate_field("version")); + } + version__ = + Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } + GeneratedField::Title => { + if title__.is_some() { + return Err(serde::de::Error::duplicate_field("title")); + } + title__ = map_.next_value()?; + } + GeneratedField::Summary => { + if summary__.is_some() { + return Err(serde::de::Error::duplicate_field("summary")); + } + summary__ = map_.next_value()?; + } + GeneratedField::AuthoringMessageId => { + if authoring_message_id__.is_some() { + return Err(serde::de::Error::duplicate_field("authoringMessageId")); + } + authoring_message_id__ = map_.next_value()?; + } + GeneratedField::SourceToolUseIds => { + if source_tool_use_ids__.is_some() { + return Err(serde::de::Error::duplicate_field("sourceToolUseIds")); + } + source_tool_use_ids__ = Some(map_.next_value()?); + } + GeneratedField::RemoteFileId => { + if remote_file_id__.is_some() { + return Err(serde::de::Error::duplicate_field("remoteFileId")); + } + remote_file_id__ = map_.next_value()?; + } + GeneratedField::VersionCreatedDate => { + if version_created_date__.is_some() { + return Err(serde::de::Error::duplicate_field("versionCreatedDate")); + } + version_created_date__ = map_.next_value()?; + } + GeneratedField::FileName => { + if file_name__.is_some() { + return Err(serde::de::Error::duplicate_field("fileName")); + } + file_name__ = map_.next_value()?; + } + GeneratedField::FileMimeType => { + if file_mime_type__.is_some() { + return Err(serde::de::Error::duplicate_field("fileMimeType")); + } + file_mime_type__ = map_.next_value()?; + } + GeneratedField::ArchivedDate => { + if archived_date__.is_some() { + return Err(serde::de::Error::duplicate_field("archivedDate")); + } + archived_date__ = map_.next_value()?; + } + } + } + Ok(Artifact { + artifact_id: artifact_id__.unwrap_or_default(), + organization_id: organization_id__.unwrap_or_default(), + created_by_user_id: created_by_user_id__.unwrap_or_default(), + authoring_kind: authoring_kind__.unwrap_or_default(), + created_date: created_date__, + artifact_version_id: artifact_version_id__.unwrap_or_default(), + version: version__.unwrap_or_default(), + title: title__, + summary: summary__, + authoring_message_id: authoring_message_id__, + source_tool_use_ids: source_tool_use_ids__.unwrap_or_default(), + remote_file_id: remote_file_id__, + version_created_date: version_created_date__, + file_name: file_name__, + file_mime_type: file_mime_type__, + archived_date: archived_date__, + }) + } + } + deserializer.deserialize_struct("sift.artifacts.v1.Artifact", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for ArtifactAuthoringKind { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + let variant = match self { + Self::Unspecified => "ARTIFACT_AUTHORING_KIND_UNSPECIFIED", + Self::Agent => "ARTIFACT_AUTHORING_KIND_AGENT", + Self::User => "ARTIFACT_AUTHORING_KIND_USER", + }; + serializer.serialize_str(variant) + } +} +impl<'de> serde::Deserialize<'de> for ArtifactAuthoringKind { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "ARTIFACT_AUTHORING_KIND_UNSPECIFIED", + "ARTIFACT_AUTHORING_KIND_AGENT", + "ARTIFACT_AUTHORING_KIND_USER", + ]; + + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = ArtifactAuthoringKind; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + fn visit_i64(self, v: i64) -> std::result::Result + where + E: serde::de::Error, + { + i32::try_from(v) + .ok() + .and_then(|x| x.try_into().ok()) + .ok_or_else(|| { + serde::de::Error::invalid_value(serde::de::Unexpected::Signed(v), &self) + }) + } + + fn visit_u64(self, v: u64) -> std::result::Result + where + E: serde::de::Error, + { + i32::try_from(v) + .ok() + .and_then(|x| x.try_into().ok()) + .ok_or_else(|| { + serde::de::Error::invalid_value(serde::de::Unexpected::Unsigned(v), &self) + }) + } + + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "ARTIFACT_AUTHORING_KIND_UNSPECIFIED" => Ok(ArtifactAuthoringKind::Unspecified), + "ARTIFACT_AUTHORING_KIND_AGENT" => Ok(ArtifactAuthoringKind::Agent), + "ARTIFACT_AUTHORING_KIND_USER" => Ok(ArtifactAuthoringKind::User), + _ => Err(serde::de::Error::unknown_variant(value, FIELDS)), + } + } + } + deserializer.deserialize_any(GeneratedVisitor) + } +} +impl serde::Serialize for ArtifactVersion { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.artifact_version_id.is_empty() { + len += 1; + } + if !self.artifact_id.is_empty() { + len += 1; + } + if self.version != 0 { + len += 1; + } + if self.title.is_some() { + len += 1; + } + if self.summary.is_some() { + len += 1; + } + if self.authoring_message_id.is_some() { + len += 1; + } + if !self.source_tool_use_ids.is_empty() { + len += 1; + } + if self.remote_file_id.is_some() { + len += 1; + } + if self.created_date.is_some() { + len += 1; + } + if self.file_name.is_some() { + len += 1; + } + if self.file_mime_type.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("sift.artifacts.v1.ArtifactVersion", len)?; + if !self.artifact_version_id.is_empty() { + struct_ser.serialize_field("artifactVersionId", &self.artifact_version_id)?; + } + if !self.artifact_id.is_empty() { + struct_ser.serialize_field("artifactId", &self.artifact_id)?; + } + if self.version != 0 { + struct_ser.serialize_field("version", &self.version)?; + } + if let Some(v) = self.title.as_ref() { + struct_ser.serialize_field("title", v)?; + } + if let Some(v) = self.summary.as_ref() { + struct_ser.serialize_field("summary", v)?; + } + if let Some(v) = self.authoring_message_id.as_ref() { + struct_ser.serialize_field("authoringMessageId", v)?; + } + if !self.source_tool_use_ids.is_empty() { + struct_ser.serialize_field("sourceToolUseIds", &self.source_tool_use_ids)?; + } + if let Some(v) = self.remote_file_id.as_ref() { + struct_ser.serialize_field("remoteFileId", v)?; + } + if let Some(v) = self.created_date.as_ref() { + struct_ser.serialize_field("createdDate", v)?; + } + if let Some(v) = self.file_name.as_ref() { + struct_ser.serialize_field("fileName", v)?; + } + if let Some(v) = self.file_mime_type.as_ref() { + struct_ser.serialize_field("fileMimeType", v)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for ArtifactVersion { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "artifact_version_id", + "artifactVersionId", + "artifact_id", + "artifactId", + "version", + "title", + "summary", + "authoring_message_id", + "authoringMessageId", + "source_tool_use_ids", + "sourceToolUseIds", + "remote_file_id", + "remoteFileId", + "created_date", + "createdDate", + "file_name", + "fileName", + "file_mime_type", + "fileMimeType", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + ArtifactVersionId, + ArtifactId, + Version, + Title, + Summary, + AuthoringMessageId, + SourceToolUseIds, + RemoteFileId, + CreatedDate, + FileName, + FileMimeType, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "artifactVersionId" | "artifact_version_id" => Ok(GeneratedField::ArtifactVersionId), + "artifactId" | "artifact_id" => Ok(GeneratedField::ArtifactId), + "version" => Ok(GeneratedField::Version), + "title" => Ok(GeneratedField::Title), + "summary" => Ok(GeneratedField::Summary), + "authoringMessageId" | "authoring_message_id" => Ok(GeneratedField::AuthoringMessageId), + "sourceToolUseIds" | "source_tool_use_ids" => Ok(GeneratedField::SourceToolUseIds), + "remoteFileId" | "remote_file_id" => Ok(GeneratedField::RemoteFileId), + "createdDate" | "created_date" => Ok(GeneratedField::CreatedDate), + "fileName" | "file_name" => Ok(GeneratedField::FileName), + "fileMimeType" | "file_mime_type" => Ok(GeneratedField::FileMimeType), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = ArtifactVersion; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct sift.artifacts.v1.ArtifactVersion") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut artifact_version_id__ = None; + let mut artifact_id__ = None; + let mut version__ = None; + let mut title__ = None; + let mut summary__ = None; + let mut authoring_message_id__ = None; + let mut source_tool_use_ids__ = None; + let mut remote_file_id__ = None; + let mut created_date__ = None; + let mut file_name__ = None; + let mut file_mime_type__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::ArtifactVersionId => { + if artifact_version_id__.is_some() { + return Err(serde::de::Error::duplicate_field("artifactVersionId")); + } + artifact_version_id__ = Some(map_.next_value()?); + } + GeneratedField::ArtifactId => { + if artifact_id__.is_some() { + return Err(serde::de::Error::duplicate_field("artifactId")); + } + artifact_id__ = Some(map_.next_value()?); + } + GeneratedField::Version => { + if version__.is_some() { + return Err(serde::de::Error::duplicate_field("version")); + } + version__ = + Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } + GeneratedField::Title => { + if title__.is_some() { + return Err(serde::de::Error::duplicate_field("title")); + } + title__ = map_.next_value()?; + } + GeneratedField::Summary => { + if summary__.is_some() { + return Err(serde::de::Error::duplicate_field("summary")); + } + summary__ = map_.next_value()?; + } + GeneratedField::AuthoringMessageId => { + if authoring_message_id__.is_some() { + return Err(serde::de::Error::duplicate_field("authoringMessageId")); + } + authoring_message_id__ = map_.next_value()?; + } + GeneratedField::SourceToolUseIds => { + if source_tool_use_ids__.is_some() { + return Err(serde::de::Error::duplicate_field("sourceToolUseIds")); + } + source_tool_use_ids__ = Some(map_.next_value()?); + } + GeneratedField::RemoteFileId => { + if remote_file_id__.is_some() { + return Err(serde::de::Error::duplicate_field("remoteFileId")); + } + remote_file_id__ = map_.next_value()?; + } + GeneratedField::CreatedDate => { + if created_date__.is_some() { + return Err(serde::de::Error::duplicate_field("createdDate")); + } + created_date__ = map_.next_value()?; + } + GeneratedField::FileName => { + if file_name__.is_some() { + return Err(serde::de::Error::duplicate_field("fileName")); + } + file_name__ = map_.next_value()?; + } + GeneratedField::FileMimeType => { + if file_mime_type__.is_some() { + return Err(serde::de::Error::duplicate_field("fileMimeType")); + } + file_mime_type__ = map_.next_value()?; + } + } + } + Ok(ArtifactVersion { + artifact_version_id: artifact_version_id__.unwrap_or_default(), + artifact_id: artifact_id__.unwrap_or_default(), + version: version__.unwrap_or_default(), + title: title__, + summary: summary__, + authoring_message_id: authoring_message_id__, + source_tool_use_ids: source_tool_use_ids__.unwrap_or_default(), + remote_file_id: remote_file_id__, + created_date: created_date__, + file_name: file_name__, + file_mime_type: file_mime_type__, + }) + } + } + deserializer.deserialize_struct("sift.artifacts.v1.ArtifactVersion", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for CreateArtifactRequest { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.artifact_id.is_some() { + len += 1; + } + if self.conversation_id.is_some() { + len += 1; + } + if self.title.is_some() { + len += 1; + } + if self.summary.is_some() { + len += 1; + } + if self.authoring_kind.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("sift.artifacts.v1.CreateArtifactRequest", len)?; + if let Some(v) = self.artifact_id.as_ref() { + struct_ser.serialize_field("artifactId", v)?; + } + if let Some(v) = self.conversation_id.as_ref() { + struct_ser.serialize_field("conversationId", v)?; + } + if let Some(v) = self.title.as_ref() { + struct_ser.serialize_field("title", v)?; + } + if let Some(v) = self.summary.as_ref() { + struct_ser.serialize_field("summary", v)?; + } + if let Some(v) = self.authoring_kind.as_ref() { + let v = ArtifactAuthoringKind::try_from(*v) + .map_err(|_| serde::ser::Error::custom(format!("Invalid variant {}", *v)))?; + struct_ser.serialize_field("authoringKind", &v)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for CreateArtifactRequest { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "artifact_id", + "artifactId", + "conversation_id", + "conversationId", + "title", + "summary", + "authoring_kind", + "authoringKind", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + ArtifactId, + ConversationId, + Title, + Summary, + AuthoringKind, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "artifactId" | "artifact_id" => Ok(GeneratedField::ArtifactId), + "conversationId" | "conversation_id" => Ok(GeneratedField::ConversationId), + "title" => Ok(GeneratedField::Title), + "summary" => Ok(GeneratedField::Summary), + "authoringKind" | "authoring_kind" => Ok(GeneratedField::AuthoringKind), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = CreateArtifactRequest; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct sift.artifacts.v1.CreateArtifactRequest") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut artifact_id__ = None; + let mut conversation_id__ = None; + let mut title__ = None; + let mut summary__ = None; + let mut authoring_kind__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::ArtifactId => { + if artifact_id__.is_some() { + return Err(serde::de::Error::duplicate_field("artifactId")); + } + artifact_id__ = map_.next_value()?; + } + GeneratedField::ConversationId => { + if conversation_id__.is_some() { + return Err(serde::de::Error::duplicate_field("conversationId")); + } + conversation_id__ = map_.next_value()?; + } + GeneratedField::Title => { + if title__.is_some() { + return Err(serde::de::Error::duplicate_field("title")); + } + title__ = map_.next_value()?; + } + GeneratedField::Summary => { + if summary__.is_some() { + return Err(serde::de::Error::duplicate_field("summary")); + } + summary__ = map_.next_value()?; + } + GeneratedField::AuthoringKind => { + if authoring_kind__.is_some() { + return Err(serde::de::Error::duplicate_field("authoringKind")); + } + authoring_kind__ = map_.next_value::<::std::option::Option>()?.map(|x| x as i32); + } + } + } + Ok(CreateArtifactRequest { + artifact_id: artifact_id__, + conversation_id: conversation_id__, + title: title__, + summary: summary__, + authoring_kind: authoring_kind__, + }) + } + } + deserializer.deserialize_struct("sift.artifacts.v1.CreateArtifactRequest", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for CreateArtifactResponse { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.artifact.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("sift.artifacts.v1.CreateArtifactResponse", len)?; + if let Some(v) = self.artifact.as_ref() { + struct_ser.serialize_field("artifact", v)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for CreateArtifactResponse { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "artifact", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Artifact, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "artifact" => Ok(GeneratedField::Artifact), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = CreateArtifactResponse; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct sift.artifacts.v1.CreateArtifactResponse") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut artifact__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Artifact => { + if artifact__.is_some() { + return Err(serde::de::Error::duplicate_field("artifact")); + } + artifact__ = map_.next_value()?; + } + } + } + Ok(CreateArtifactResponse { + artifact: artifact__, + }) + } + } + deserializer.deserialize_struct("sift.artifacts.v1.CreateArtifactResponse", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for GetArtifactRequest { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.artifact_id.is_empty() { + len += 1; + } + if self.artifact_version_id.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("sift.artifacts.v1.GetArtifactRequest", len)?; + if !self.artifact_id.is_empty() { + struct_ser.serialize_field("artifactId", &self.artifact_id)?; + } + if let Some(v) = self.artifact_version_id.as_ref() { + struct_ser.serialize_field("artifactVersionId", v)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for GetArtifactRequest { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "artifact_id", + "artifactId", + "artifact_version_id", + "artifactVersionId", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + ArtifactId, + ArtifactVersionId, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "artifactId" | "artifact_id" => Ok(GeneratedField::ArtifactId), + "artifactVersionId" | "artifact_version_id" => Ok(GeneratedField::ArtifactVersionId), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GetArtifactRequest; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct sift.artifacts.v1.GetArtifactRequest") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut artifact_id__ = None; + let mut artifact_version_id__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::ArtifactId => { + if artifact_id__.is_some() { + return Err(serde::de::Error::duplicate_field("artifactId")); + } + artifact_id__ = Some(map_.next_value()?); + } + GeneratedField::ArtifactVersionId => { + if artifact_version_id__.is_some() { + return Err(serde::de::Error::duplicate_field("artifactVersionId")); + } + artifact_version_id__ = map_.next_value()?; + } + } + } + Ok(GetArtifactRequest { + artifact_id: artifact_id__.unwrap_or_default(), + artifact_version_id: artifact_version_id__, + }) + } + } + deserializer.deserialize_struct("sift.artifacts.v1.GetArtifactRequest", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for GetArtifactResponse { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.artifact.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("sift.artifacts.v1.GetArtifactResponse", len)?; + if let Some(v) = self.artifact.as_ref() { + struct_ser.serialize_field("artifact", v)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for GetArtifactResponse { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "artifact", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Artifact, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "artifact" => Ok(GeneratedField::Artifact), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GetArtifactResponse; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct sift.artifacts.v1.GetArtifactResponse") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut artifact__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Artifact => { + if artifact__.is_some() { + return Err(serde::de::Error::duplicate_field("artifact")); + } + artifact__ = map_.next_value()?; + } + } + } + Ok(GetArtifactResponse { + artifact: artifact__, + }) + } + } + deserializer.deserialize_struct("sift.artifacts.v1.GetArtifactResponse", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for LinkArtifactToConversationRequest { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.artifact_id.is_empty() { + len += 1; + } + if !self.conversation_id.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("sift.artifacts.v1.LinkArtifactToConversationRequest", len)?; + if !self.artifact_id.is_empty() { + struct_ser.serialize_field("artifactId", &self.artifact_id)?; + } + if !self.conversation_id.is_empty() { + struct_ser.serialize_field("conversationId", &self.conversation_id)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for LinkArtifactToConversationRequest { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "artifact_id", + "artifactId", + "conversation_id", + "conversationId", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + ArtifactId, + ConversationId, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "artifactId" | "artifact_id" => Ok(GeneratedField::ArtifactId), + "conversationId" | "conversation_id" => Ok(GeneratedField::ConversationId), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = LinkArtifactToConversationRequest; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct sift.artifacts.v1.LinkArtifactToConversationRequest") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut artifact_id__ = None; + let mut conversation_id__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::ArtifactId => { + if artifact_id__.is_some() { + return Err(serde::de::Error::duplicate_field("artifactId")); + } + artifact_id__ = Some(map_.next_value()?); + } + GeneratedField::ConversationId => { + if conversation_id__.is_some() { + return Err(serde::de::Error::duplicate_field("conversationId")); + } + conversation_id__ = Some(map_.next_value()?); + } + } + } + Ok(LinkArtifactToConversationRequest { + artifact_id: artifact_id__.unwrap_or_default(), + conversation_id: conversation_id__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("sift.artifacts.v1.LinkArtifactToConversationRequest", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for LinkArtifactToConversationResponse { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let len = 0; + let struct_ser = serializer.serialize_struct("sift.artifacts.v1.LinkArtifactToConversationResponse", len)?; + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for LinkArtifactToConversationResponse { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + Err(serde::de::Error::unknown_field(value, FIELDS)) + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = LinkArtifactToConversationResponse; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct sift.artifacts.v1.LinkArtifactToConversationResponse") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + while map_.next_key::()?.is_some() { + let _ = map_.next_value::()?; + } + Ok(LinkArtifactToConversationResponse { + }) + } + } + deserializer.deserialize_struct("sift.artifacts.v1.LinkArtifactToConversationResponse", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for ListArtifactVersionsRequest { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.artifact_id.is_empty() { + len += 1; + } + if self.page_size != 0 { + len += 1; + } + if !self.page_token.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("sift.artifacts.v1.ListArtifactVersionsRequest", len)?; + if !self.artifact_id.is_empty() { + struct_ser.serialize_field("artifactId", &self.artifact_id)?; + } + if self.page_size != 0 { + struct_ser.serialize_field("pageSize", &self.page_size)?; + } + if !self.page_token.is_empty() { + struct_ser.serialize_field("pageToken", &self.page_token)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for ListArtifactVersionsRequest { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "artifact_id", + "artifactId", + "page_size", + "pageSize", + "page_token", + "pageToken", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + ArtifactId, + PageSize, + PageToken, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "artifactId" | "artifact_id" => Ok(GeneratedField::ArtifactId), + "pageSize" | "page_size" => Ok(GeneratedField::PageSize), + "pageToken" | "page_token" => Ok(GeneratedField::PageToken), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = ListArtifactVersionsRequest; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct sift.artifacts.v1.ListArtifactVersionsRequest") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut artifact_id__ = None; + let mut page_size__ = None; + let mut page_token__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::ArtifactId => { + if artifact_id__.is_some() { + return Err(serde::de::Error::duplicate_field("artifactId")); + } + artifact_id__ = Some(map_.next_value()?); + } + GeneratedField::PageSize => { + if page_size__.is_some() { + return Err(serde::de::Error::duplicate_field("pageSize")); + } + page_size__ = + Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } + GeneratedField::PageToken => { + if page_token__.is_some() { + return Err(serde::de::Error::duplicate_field("pageToken")); + } + page_token__ = Some(map_.next_value()?); + } + } + } + Ok(ListArtifactVersionsRequest { + artifact_id: artifact_id__.unwrap_or_default(), + page_size: page_size__.unwrap_or_default(), + page_token: page_token__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("sift.artifacts.v1.ListArtifactVersionsRequest", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for ListArtifactVersionsResponse { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.versions.is_empty() { + len += 1; + } + if !self.next_page_token.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("sift.artifacts.v1.ListArtifactVersionsResponse", len)?; + if !self.versions.is_empty() { + struct_ser.serialize_field("versions", &self.versions)?; + } + if !self.next_page_token.is_empty() { + struct_ser.serialize_field("nextPageToken", &self.next_page_token)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for ListArtifactVersionsResponse { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "versions", + "next_page_token", + "nextPageToken", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Versions, + NextPageToken, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "versions" => Ok(GeneratedField::Versions), + "nextPageToken" | "next_page_token" => Ok(GeneratedField::NextPageToken), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = ListArtifactVersionsResponse; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct sift.artifacts.v1.ListArtifactVersionsResponse") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut versions__ = None; + let mut next_page_token__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Versions => { + if versions__.is_some() { + return Err(serde::de::Error::duplicate_field("versions")); + } + versions__ = Some(map_.next_value()?); + } + GeneratedField::NextPageToken => { + if next_page_token__.is_some() { + return Err(serde::de::Error::duplicate_field("nextPageToken")); + } + next_page_token__ = Some(map_.next_value()?); + } + } + } + Ok(ListArtifactVersionsResponse { + versions: versions__.unwrap_or_default(), + next_page_token: next_page_token__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("sift.artifacts.v1.ListArtifactVersionsResponse", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for ListArtifactsRequest { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.conversation_id.is_some() { + len += 1; + } + if self.page_size != 0 { + len += 1; + } + if !self.page_token.is_empty() { + len += 1; + } + if self.include_archived { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("sift.artifacts.v1.ListArtifactsRequest", len)?; + if let Some(v) = self.conversation_id.as_ref() { + struct_ser.serialize_field("conversationId", v)?; + } + if self.page_size != 0 { + struct_ser.serialize_field("pageSize", &self.page_size)?; + } + if !self.page_token.is_empty() { + struct_ser.serialize_field("pageToken", &self.page_token)?; + } + if self.include_archived { + struct_ser.serialize_field("includeArchived", &self.include_archived)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for ListArtifactsRequest { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "conversation_id", + "conversationId", + "page_size", + "pageSize", + "page_token", + "pageToken", + "include_archived", + "includeArchived", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + ConversationId, + PageSize, + PageToken, + IncludeArchived, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "conversationId" | "conversation_id" => Ok(GeneratedField::ConversationId), + "pageSize" | "page_size" => Ok(GeneratedField::PageSize), + "pageToken" | "page_token" => Ok(GeneratedField::PageToken), + "includeArchived" | "include_archived" => Ok(GeneratedField::IncludeArchived), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = ListArtifactsRequest; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct sift.artifacts.v1.ListArtifactsRequest") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut conversation_id__ = None; + let mut page_size__ = None; + let mut page_token__ = None; + let mut include_archived__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::ConversationId => { + if conversation_id__.is_some() { + return Err(serde::de::Error::duplicate_field("conversationId")); + } + conversation_id__ = map_.next_value()?; + } + GeneratedField::PageSize => { + if page_size__.is_some() { + return Err(serde::de::Error::duplicate_field("pageSize")); + } + page_size__ = + Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } + GeneratedField::PageToken => { + if page_token__.is_some() { + return Err(serde::de::Error::duplicate_field("pageToken")); + } + page_token__ = Some(map_.next_value()?); + } + GeneratedField::IncludeArchived => { + if include_archived__.is_some() { + return Err(serde::de::Error::duplicate_field("includeArchived")); + } + include_archived__ = Some(map_.next_value()?); + } + } + } + Ok(ListArtifactsRequest { + conversation_id: conversation_id__, + page_size: page_size__.unwrap_or_default(), + page_token: page_token__.unwrap_or_default(), + include_archived: include_archived__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("sift.artifacts.v1.ListArtifactsRequest", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for ListArtifactsResponse { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.artifacts.is_empty() { + len += 1; + } + if !self.next_page_token.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("sift.artifacts.v1.ListArtifactsResponse", len)?; + if !self.artifacts.is_empty() { + struct_ser.serialize_field("artifacts", &self.artifacts)?; + } + if !self.next_page_token.is_empty() { + struct_ser.serialize_field("nextPageToken", &self.next_page_token)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for ListArtifactsResponse { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "artifacts", + "next_page_token", + "nextPageToken", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Artifacts, + NextPageToken, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "artifacts" => Ok(GeneratedField::Artifacts), + "nextPageToken" | "next_page_token" => Ok(GeneratedField::NextPageToken), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = ListArtifactsResponse; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct sift.artifacts.v1.ListArtifactsResponse") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut artifacts__ = None; + let mut next_page_token__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Artifacts => { + if artifacts__.is_some() { + return Err(serde::de::Error::duplicate_field("artifacts")); + } + artifacts__ = Some(map_.next_value()?); + } + GeneratedField::NextPageToken => { + if next_page_token__.is_some() { + return Err(serde::de::Error::duplicate_field("nextPageToken")); + } + next_page_token__ = Some(map_.next_value()?); + } + } + } + Ok(ListArtifactsResponse { + artifacts: artifacts__.unwrap_or_default(), + next_page_token: next_page_token__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("sift.artifacts.v1.ListArtifactsResponse", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for UnarchiveArtifactRequest { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.artifact_id.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("sift.artifacts.v1.UnarchiveArtifactRequest", len)?; + if !self.artifact_id.is_empty() { + struct_ser.serialize_field("artifactId", &self.artifact_id)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for UnarchiveArtifactRequest { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "artifact_id", + "artifactId", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + ArtifactId, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "artifactId" | "artifact_id" => Ok(GeneratedField::ArtifactId), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = UnarchiveArtifactRequest; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct sift.artifacts.v1.UnarchiveArtifactRequest") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut artifact_id__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::ArtifactId => { + if artifact_id__.is_some() { + return Err(serde::de::Error::duplicate_field("artifactId")); + } + artifact_id__ = Some(map_.next_value()?); + } + } + } + Ok(UnarchiveArtifactRequest { + artifact_id: artifact_id__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("sift.artifacts.v1.UnarchiveArtifactRequest", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for UnarchiveArtifactResponse { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let len = 0; + let struct_ser = serializer.serialize_struct("sift.artifacts.v1.UnarchiveArtifactResponse", len)?; + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for UnarchiveArtifactResponse { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + Err(serde::de::Error::unknown_field(value, FIELDS)) + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = UnarchiveArtifactResponse; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct sift.artifacts.v1.UnarchiveArtifactResponse") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + while map_.next_key::()?.is_some() { + let _ = map_.next_value::()?; + } + Ok(UnarchiveArtifactResponse { + }) + } + } + deserializer.deserialize_struct("sift.artifacts.v1.UnarchiveArtifactResponse", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for UnlinkArtifactFromConversationRequest { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.artifact_id.is_empty() { + len += 1; + } + if !self.conversation_id.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("sift.artifacts.v1.UnlinkArtifactFromConversationRequest", len)?; + if !self.artifact_id.is_empty() { + struct_ser.serialize_field("artifactId", &self.artifact_id)?; + } + if !self.conversation_id.is_empty() { + struct_ser.serialize_field("conversationId", &self.conversation_id)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for UnlinkArtifactFromConversationRequest { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "artifact_id", + "artifactId", + "conversation_id", + "conversationId", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + ArtifactId, + ConversationId, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "artifactId" | "artifact_id" => Ok(GeneratedField::ArtifactId), + "conversationId" | "conversation_id" => Ok(GeneratedField::ConversationId), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = UnlinkArtifactFromConversationRequest; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct sift.artifacts.v1.UnlinkArtifactFromConversationRequest") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut artifact_id__ = None; + let mut conversation_id__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::ArtifactId => { + if artifact_id__.is_some() { + return Err(serde::de::Error::duplicate_field("artifactId")); + } + artifact_id__ = Some(map_.next_value()?); + } + GeneratedField::ConversationId => { + if conversation_id__.is_some() { + return Err(serde::de::Error::duplicate_field("conversationId")); + } + conversation_id__ = Some(map_.next_value()?); + } + } + } + Ok(UnlinkArtifactFromConversationRequest { + artifact_id: artifact_id__.unwrap_or_default(), + conversation_id: conversation_id__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("sift.artifacts.v1.UnlinkArtifactFromConversationRequest", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for UnlinkArtifactFromConversationResponse { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let len = 0; + let struct_ser = serializer.serialize_struct("sift.artifacts.v1.UnlinkArtifactFromConversationResponse", len)?; + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for UnlinkArtifactFromConversationResponse { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + Err(serde::de::Error::unknown_field(value, FIELDS)) + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = UnlinkArtifactFromConversationResponse; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct sift.artifacts.v1.UnlinkArtifactFromConversationResponse") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + while map_.next_key::()?.is_some() { + let _ = map_.next_value::()?; + } + Ok(UnlinkArtifactFromConversationResponse { + }) + } + } + deserializer.deserialize_struct("sift.artifacts.v1.UnlinkArtifactFromConversationResponse", FIELDS, GeneratedVisitor) + } +} diff --git a/rust/crates/sift_rs/src/gen/sift/artifacts/v1/sift.artifacts.v1.tonic.rs b/rust/crates/sift_rs/src/gen/sift/artifacts/v1/sift.artifacts.v1.tonic.rs new file mode 100644 index 000000000..84a646a54 --- /dev/null +++ b/rust/crates/sift_rs/src/gen/sift/artifacts/v1/sift.artifacts.v1.tonic.rs @@ -0,0 +1,892 @@ +// @generated +/// Generated client implementations. +pub mod artifact_service_client { + #![allow( + unused_variables, + dead_code, + missing_docs, + clippy::wildcard_imports, + clippy::let_unit_value, + )] + use tonic::codegen::*; + use tonic::codegen::http::Uri; + #[derive(Debug, Clone)] + pub struct ArtifactServiceClient { + inner: tonic::client::Grpc, + } + impl ArtifactServiceClient { + /// Attempt to create a new client by connecting to a given endpoint. + pub async fn connect(dst: D) -> Result + where + D: TryInto, + D::Error: Into, + { + let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; + Ok(Self::new(conn)) + } + } + impl ArtifactServiceClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + std::marker::Send + 'static, + ::Error: Into + std::marker::Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> ArtifactServiceClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + , + >>::Error: Into + std::marker::Send + std::marker::Sync, + { + ArtifactServiceClient::new(InterceptedService::new(inner, interceptor)) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_decoding_message_size(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_encoding_message_size(limit); + self + } + pub async fn create_artifact( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/sift.artifacts.v1.ArtifactService/CreateArtifact", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "sift.artifacts.v1.ArtifactService", + "CreateArtifact", + ), + ); + self.inner.unary(req, path, codec).await + } + pub async fn get_artifact( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/sift.artifacts.v1.ArtifactService/GetArtifact", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new("sift.artifacts.v1.ArtifactService", "GetArtifact"), + ); + self.inner.unary(req, path, codec).await + } + pub async fn list_artifacts( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/sift.artifacts.v1.ArtifactService/ListArtifacts", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new("sift.artifacts.v1.ArtifactService", "ListArtifacts"), + ); + self.inner.unary(req, path, codec).await + } + pub async fn list_artifact_versions( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/sift.artifacts.v1.ArtifactService/ListArtifactVersions", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "sift.artifacts.v1.ArtifactService", + "ListArtifactVersions", + ), + ); + self.inner.unary(req, path, codec).await + } + pub async fn link_artifact_to_conversation( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/sift.artifacts.v1.ArtifactService/LinkArtifactToConversation", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "sift.artifacts.v1.ArtifactService", + "LinkArtifactToConversation", + ), + ); + self.inner.unary(req, path, codec).await + } + pub async fn unlink_artifact_from_conversation( + &mut self, + request: impl tonic::IntoRequest< + super::UnlinkArtifactFromConversationRequest, + >, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/sift.artifacts.v1.ArtifactService/UnlinkArtifactFromConversation", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "sift.artifacts.v1.ArtifactService", + "UnlinkArtifactFromConversation", + ), + ); + self.inner.unary(req, path, codec).await + } + pub async fn archive_artifact( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/sift.artifacts.v1.ArtifactService/ArchiveArtifact", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "sift.artifacts.v1.ArtifactService", + "ArchiveArtifact", + ), + ); + self.inner.unary(req, path, codec).await + } + pub async fn unarchive_artifact( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/sift.artifacts.v1.ArtifactService/UnarchiveArtifact", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "sift.artifacts.v1.ArtifactService", + "UnarchiveArtifact", + ), + ); + self.inner.unary(req, path, codec).await + } + } +} +/// Generated server implementations. +pub mod artifact_service_server { + #![allow( + unused_variables, + dead_code, + missing_docs, + clippy::wildcard_imports, + clippy::let_unit_value, + )] + use tonic::codegen::*; + /// Generated trait containing gRPC methods that should be implemented for use with ArtifactServiceServer. + #[async_trait] + pub trait ArtifactService: std::marker::Send + std::marker::Sync + 'static { + async fn create_artifact( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + async fn get_artifact( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + async fn list_artifacts( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + async fn list_artifact_versions( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + async fn link_artifact_to_conversation( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + async fn unlink_artifact_from_conversation( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + async fn archive_artifact( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + async fn unarchive_artifact( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + } + #[derive(Debug)] + pub struct ArtifactServiceServer { + inner: Arc, + accept_compression_encodings: EnabledCompressionEncodings, + send_compression_encodings: EnabledCompressionEncodings, + max_decoding_message_size: Option, + max_encoding_message_size: Option, + } + impl ArtifactServiceServer { + pub fn new(inner: T) -> Self { + Self::from_arc(Arc::new(inner)) + } + pub fn from_arc(inner: Arc) -> Self { + Self { + inner, + accept_compression_encodings: Default::default(), + send_compression_encodings: Default::default(), + max_decoding_message_size: None, + max_encoding_message_size: None, + } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> InterceptedService + where + F: tonic::service::Interceptor, + { + InterceptedService::new(Self::new(inner), interceptor) + } + /// Enable decompressing requests with the given encoding. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.accept_compression_encodings.enable(encoding); + self + } + /// Compress responses with the given encoding, if the client supports it. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.send_compression_encodings.enable(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.max_decoding_message_size = Some(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.max_encoding_message_size = Some(limit); + self + } + } + impl tonic::codegen::Service> for ArtifactServiceServer + where + T: ArtifactService, + B: Body + std::marker::Send + 'static, + B::Error: Into + std::marker::Send + 'static, + { + type Response = http::Response; + type Error = std::convert::Infallible; + type Future = BoxFuture; + fn poll_ready( + &mut self, + _cx: &mut Context<'_>, + ) -> Poll> { + Poll::Ready(Ok(())) + } + fn call(&mut self, req: http::Request) -> Self::Future { + match req.uri().path() { + "/sift.artifacts.v1.ArtifactService/CreateArtifact" => { + #[allow(non_camel_case_types)] + struct CreateArtifactSvc(pub Arc); + impl< + T: ArtifactService, + > tonic::server::UnaryService + for CreateArtifactSvc { + type Response = super::CreateArtifactResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::create_artifact(&inner, request) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = CreateArtifactSvc(inner); + let codec = tonic_prost::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/sift.artifacts.v1.ArtifactService/GetArtifact" => { + #[allow(non_camel_case_types)] + struct GetArtifactSvc(pub Arc); + impl< + T: ArtifactService, + > tonic::server::UnaryService + for GetArtifactSvc { + type Response = super::GetArtifactResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_artifact(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = GetArtifactSvc(inner); + let codec = tonic_prost::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/sift.artifacts.v1.ArtifactService/ListArtifacts" => { + #[allow(non_camel_case_types)] + struct ListArtifactsSvc(pub Arc); + impl< + T: ArtifactService, + > tonic::server::UnaryService + for ListArtifactsSvc { + type Response = super::ListArtifactsResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::list_artifacts(&inner, request) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = ListArtifactsSvc(inner); + let codec = tonic_prost::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/sift.artifacts.v1.ArtifactService/ListArtifactVersions" => { + #[allow(non_camel_case_types)] + struct ListArtifactVersionsSvc(pub Arc); + impl< + T: ArtifactService, + > tonic::server::UnaryService + for ListArtifactVersionsSvc { + type Response = super::ListArtifactVersionsResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::list_artifact_versions( + &inner, + request, + ) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = ListArtifactVersionsSvc(inner); + let codec = tonic_prost::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/sift.artifacts.v1.ArtifactService/LinkArtifactToConversation" => { + #[allow(non_camel_case_types)] + struct LinkArtifactToConversationSvc(pub Arc); + impl< + T: ArtifactService, + > tonic::server::UnaryService< + super::LinkArtifactToConversationRequest, + > for LinkArtifactToConversationSvc { + type Response = super::LinkArtifactToConversationResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request< + super::LinkArtifactToConversationRequest, + >, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::link_artifact_to_conversation( + &inner, + request, + ) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = LinkArtifactToConversationSvc(inner); + let codec = tonic_prost::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/sift.artifacts.v1.ArtifactService/UnlinkArtifactFromConversation" => { + #[allow(non_camel_case_types)] + struct UnlinkArtifactFromConversationSvc( + pub Arc, + ); + impl< + T: ArtifactService, + > tonic::server::UnaryService< + super::UnlinkArtifactFromConversationRequest, + > for UnlinkArtifactFromConversationSvc { + type Response = super::UnlinkArtifactFromConversationResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request< + super::UnlinkArtifactFromConversationRequest, + >, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::unlink_artifact_from_conversation( + &inner, + request, + ) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = UnlinkArtifactFromConversationSvc(inner); + let codec = tonic_prost::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/sift.artifacts.v1.ArtifactService/ArchiveArtifact" => { + #[allow(non_camel_case_types)] + struct ArchiveArtifactSvc(pub Arc); + impl< + T: ArtifactService, + > tonic::server::UnaryService + for ArchiveArtifactSvc { + type Response = super::ArchiveArtifactResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::archive_artifact(&inner, request) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = ArchiveArtifactSvc(inner); + let codec = tonic_prost::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/sift.artifacts.v1.ArtifactService/UnarchiveArtifact" => { + #[allow(non_camel_case_types)] + struct UnarchiveArtifactSvc(pub Arc); + impl< + T: ArtifactService, + > tonic::server::UnaryService + for UnarchiveArtifactSvc { + type Response = super::UnarchiveArtifactResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::unarchive_artifact(&inner, request) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = UnarchiveArtifactSvc(inner); + let codec = tonic_prost::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + _ => { + Box::pin(async move { + let mut response = http::Response::new( + tonic::body::Body::default(), + ); + let headers = response.headers_mut(); + headers + .insert( + tonic::Status::GRPC_STATUS, + (tonic::Code::Unimplemented as i32).into(), + ); + headers + .insert( + http::header::CONTENT_TYPE, + tonic::metadata::GRPC_CONTENT_TYPE, + ); + Ok(response) + }) + } + } + } + } + impl Clone for ArtifactServiceServer { + fn clone(&self) -> Self { + let inner = self.inner.clone(); + Self { + inner, + accept_compression_encodings: self.accept_compression_encodings, + send_compression_encodings: self.send_compression_encodings, + max_decoding_message_size: self.max_decoding_message_size, + max_encoding_message_size: self.max_encoding_message_size, + } + } + } + /// Generated gRPC service name + pub const SERVICE_NAME: &str = "sift.artifacts.v1.ArtifactService"; + impl tonic::server::NamedService for ArtifactServiceServer { + const NAME: &'static str = SERVICE_NAME; + } +} diff --git a/rust/crates/sift_test_util/src/mock/artifacts/mod.rs b/rust/crates/sift_test_util/src/mock/artifacts/mod.rs new file mode 100644 index 000000000..a3a6d96c3 --- /dev/null +++ b/rust/crates/sift_test_util/src/mock/artifacts/mod.rs @@ -0,0 +1 @@ +pub mod v1; diff --git a/rust/crates/sift_test_util/src/mock/artifacts/v1.rs b/rust/crates/sift_test_util/src/mock/artifacts/v1.rs new file mode 100644 index 000000000..df81ce46c --- /dev/null +++ b/rust/crates/sift_test_util/src/mock/artifacts/v1.rs @@ -0,0 +1,75 @@ +use async_trait::async_trait; +use mockall::mock; +use sift_rs::artifacts::v1::{ + ArchiveArtifactRequest, ArchiveArtifactResponse, CreateArtifactRequest, CreateArtifactResponse, + GetArtifactRequest, GetArtifactResponse, LinkArtifactToConversationRequest, + LinkArtifactToConversationResponse, ListArtifactVersionsRequest, ListArtifactVersionsResponse, + ListArtifactsRequest, ListArtifactsResponse, UnarchiveArtifactRequest, + UnarchiveArtifactResponse, UnlinkArtifactFromConversationRequest, + UnlinkArtifactFromConversationResponse, artifact_service_server::ArtifactService, +}; +use tonic::{Request, Response, Status}; + +mock! { + pub ArtifactServiceImpl {} + + #[async_trait] + impl ArtifactService for ArtifactServiceImpl { + async fn create_artifact( + &self, + request: Request, + ) -> std::result::Result< + Response, + Status, + >; + async fn get_artifact( + &self, + request: Request, + ) -> std::result::Result< + Response, + Status, + >; + async fn list_artifacts( + &self, + request: Request, + ) -> std::result::Result< + Response, + Status, + >; + async fn list_artifact_versions( + &self, + request: Request, + ) -> std::result::Result< + Response, + Status, + >; + async fn link_artifact_to_conversation( + &self, + request: Request, + ) -> std::result::Result< + Response, + Status, + >; + async fn unlink_artifact_from_conversation( + &self, + request: Request, + ) -> std::result::Result< + Response, + Status, + >; + async fn archive_artifact( + &self, + request: Request, + ) -> std::result::Result< + Response, + Status, + >; + async fn unarchive_artifact( + &self, + request: Request, + ) -> std::result::Result< + Response, + Status, + >; + } +} diff --git a/rust/crates/sift_test_util/src/mock/mod.rs b/rust/crates/sift_test_util/src/mock/mod.rs index 8d9c64c10..ae0053c50 100644 --- a/rust/crates/sift_test_util/src/mock/mod.rs +++ b/rust/crates/sift_test_util/src/mock/mod.rs @@ -1,10 +1,12 @@ pub mod annotations; +pub mod artifacts; pub mod assets; pub mod calculated_channels; pub mod channels; pub mod data; pub mod docs; pub mod me; +pub mod remote_files; pub mod report_templates; pub mod reports; pub mod rule_evaluation; diff --git a/rust/crates/sift_test_util/src/mock/remote_files/mod.rs b/rust/crates/sift_test_util/src/mock/remote_files/mod.rs new file mode 100644 index 000000000..a3a6d96c3 --- /dev/null +++ b/rust/crates/sift_test_util/src/mock/remote_files/mod.rs @@ -0,0 +1 @@ +pub mod v1; diff --git a/rust/crates/sift_test_util/src/mock/remote_files/v1.rs b/rust/crates/sift_test_util/src/mock/remote_files/v1.rs new file mode 100644 index 000000000..b8a05d667 --- /dev/null +++ b/rust/crates/sift_test_util/src/mock/remote_files/v1.rs @@ -0,0 +1,68 @@ +use async_trait::async_trait; +use mockall::mock; +use sift_rs::remote_files::v1::{ + BatchDeleteRemoteFilesRequest, BatchDeleteRemoteFilesResponse, CreateRemoteFileRequest, + CreateRemoteFileResponse, DeleteRemoteFileRequest, DeleteRemoteFileResponse, + GetRemoteFileDownloadUrlRequest, GetRemoteFileDownloadUrlResponse, GetRemoteFileRequest, + GetRemoteFileResponse, ListRemoteFilesRequest, ListRemoteFilesResponse, + UpdateRemoteFileRequest, UpdateRemoteFileResponse, + remote_file_service_server::RemoteFileService, +}; +use tonic::{Request, Response, Status}; + +mock! { + pub RemoteFileServiceImpl {} + + #[async_trait] + impl RemoteFileService for RemoteFileServiceImpl { + async fn get_remote_file( + &self, + request: Request, + ) -> std::result::Result< + Response, + Status, + >; + async fn create_remote_file( + &self, + request: Request, + ) -> std::result::Result< + Response, + Status, + >; + async fn list_remote_files( + &self, + request: Request, + ) -> std::result::Result< + Response, + Status, + >; + async fn update_remote_file( + &self, + request: Request, + ) -> std::result::Result< + Response, + Status, + >; + async fn delete_remote_file( + &self, + request: Request, + ) -> std::result::Result< + Response, + Status, + >; + async fn batch_delete_remote_files( + &self, + request: Request, + ) -> std::result::Result< + Response, + Status, + >; + async fn get_remote_file_download_url( + &self, + request: Request, + ) -> std::result::Result< + Response, + Status, + >; + } +}