1use agent_client_protocol_schema::v1;
14
15pub use v1::AuthenticateRequest;
19pub use v1::CloseSessionRequest;
21pub use v1::DeleteSessionRequest;
23pub use v1::InitializeRequest;
25pub use v1::ListSessionsRequest;
27pub use v1::LoadSessionRequest;
29pub use v1::LogoutRequest;
31pub use v1::NewSessionRequest;
33pub use v1::PromptRequest;
35pub use v1::ResumeSessionRequest;
37pub use v1::SetSessionConfigOptionRequest;
39pub use v1::SetSessionModeRequest;
41
42pub use v1::AuthenticateResponse;
46pub use v1::CloseSessionResponse;
48pub use v1::DeleteSessionResponse;
50pub use v1::InitializeResponse;
52pub use v1::ListSessionsResponse;
54pub use v1::LoadSessionResponse;
56pub use v1::LogoutResponse;
58pub use v1::NewSessionResponse;
60pub use v1::PromptResponse;
62pub use v1::ResumeSessionResponse;
64pub use v1::SetSessionConfigOptionResponse;
66pub use v1::SetSessionModeResponse;
68
69pub use v1::AgentNotification;
73pub use v1::CancelNotification;
75pub use v1::CancelRequestNotification;
77pub use v1::ClientNotification;
79pub use v1::ExtNotification;
81pub use v1::ProtocolLevelNotification;
83pub use v1::SessionNotification;
85
86pub use v1::AgentRequest;
90pub use v1::AgentResponse;
92pub use v1::ClientRequest;
94pub use v1::ClientResponse;
96
97pub use v1::ToolCall;
101pub use v1::ToolCallContent;
103pub use v1::ToolCallId;
105pub use v1::ToolCallLocation;
107pub use v1::ToolCallStatus;
109pub use v1::ToolCallUpdate;
111pub use v1::ToolCallUpdateFields;
113pub use v1::AudioContent;
120pub use v1::BlobResourceContents;
122pub use v1::ContentBlock;
124pub use v1::ContentChunk;
126pub use v1::EmbeddedResource;
128pub use v1::EmbeddedResourceResource;
130pub use v1::ImageContent;
132pub use v1::ResourceLink;
134pub use v1::Role;
136pub use v1::TextContent;
138pub use v1::TextResourceContents;
140
141pub use v1::Annotations;
145pub use v1::Cost;
147pub use v1::Meta;
149pub use v1::UsageUpdate;
151
152pub use v1::AgentCapabilities;
156pub use v1::BooleanConfigOptionCapabilities;
158pub use v1::ClientCapabilities;
160pub use v1::ClientSessionCapabilities;
162pub use v1::FileSystemCapabilities;
164pub use v1::McpCapabilities;
166pub use v1::PromptCapabilities;
168pub use v1::SessionAdditionalDirectoriesCapabilities;
170pub use v1::SessionCapabilities;
172pub use v1::SessionCloseCapabilities;
174pub use v1::SessionConfigOptionsCapabilities;
176pub use v1::SessionDeleteCapabilities;
178pub use v1::SessionListCapabilities;
180pub use v1::SessionResumeCapabilities;
182
183pub use v1::PermissionOption;
187pub use v1::PermissionOptionId;
189pub use v1::PermissionOptionKind;
191pub use v1::RequestPermissionOutcome;
193pub use v1::RequestPermissionRequest;
195pub use v1::RequestPermissionResponse;
197pub use v1::SelectedPermissionOutcome;
199
200pub use v1::SessionConfigBoolean;
204pub use v1::SessionConfigGroupId;
206pub use v1::SessionConfigId;
208pub use v1::SessionConfigKind;
210pub use v1::SessionConfigOption;
212pub use v1::SessionConfigOptionCategory;
214pub use v1::SessionConfigOptionValue;
216pub use v1::SessionConfigSelect;
218pub use v1::SessionConfigSelectGroup;
220pub use v1::SessionConfigSelectOption;
222pub use v1::SessionConfigSelectOptions;
224pub use v1::SessionConfigValueId;
226pub use v1::SessionId;
228pub use v1::SessionInfo;
230pub use v1::SessionMode;
232pub use v1::SessionModeId;
234pub use v1::SessionModeState;
236
237pub use v1::AvailableCommandsUpdate;
241pub use v1::ConfigOptionUpdate;
243pub use v1::CurrentModeUpdate;
245pub use v1::SessionInfoUpdate;
247pub use v1::SessionUpdate;
249
250pub use v1::Plan;
254pub use v1::PlanEntry;
256pub use v1::PlanEntryPriority;
258pub use v1::PlanEntryStatus;
260
261pub use v1::TerminalExitStatus;
265pub use v1::TerminalId;
267
268pub use v1::McpServer;
272pub use v1::McpServerHttp;
274pub use v1::McpServerSse;
276pub use v1::McpServerStdio;
278
279pub use v1::AgentAuthCapabilities;
283pub use v1::AuthMethod;
285pub use v1::AuthMethodAgent;
287pub use v1::AuthMethodId;
289pub use v1::LogoutCapabilities;
291
292pub use v1::AgentMethodNames;
296pub use v1::AvailableCommand;
298pub use v1::AvailableCommandInput;
300pub use v1::ClientMethodNames;
302pub use v1::Diff;
304pub use v1::EnvVariable;
306pub use v1::GeneralMethodNames;
308pub use v1::HttpHeader;
310pub use v1::Implementation;
312pub use v1::MessageId;
314pub use v1::StopReason;
316pub use v1::UnstructuredCommandInput;
318
319pub use v1::Error;
323pub use v1::ErrorCode;
325
326pub use v1::ExtRequest;
330pub use v1::ExtResponse;
332
333pub use agent_client_protocol_schema::ProtocolVersion;
337
338pub use v1::Response;
342
343#[cfg(test)]
348mod tests {
349 use super::*;
350
351 fn assert_roundtrip<
355 T: serde::Serialize + serde::de::DeserializeOwned + std::fmt::Debug + PartialEq,
356 >(
357 val: &T,
358 ) {
359 let json = serde_json::to_string(val).expect("serialize");
360 let val2: T = serde_json::from_str(&json).expect("deserialize");
361 assert_eq!(val, &val2, "roundtrip failed for JSON: {json}");
362 }
363
364 fn assert_json_roundtrip<
366 T: serde::de::DeserializeOwned + serde::Serialize + std::fmt::Debug + PartialEq,
367 >(
368 json: &str,
369 ) {
370 let val: T = serde_json::from_str(json).expect("deserialize from literal");
371 let serialized = serde_json::to_string(&val).expect("serialize");
372 let val2: T = serde_json::from_str(&serialized).expect("deserialize from serialized");
373 assert_eq!(
374 val, val2,
375 "json roundtrip failed\n input: {json}\n serialized: {serialized}"
376 );
377 }
378
379 #[test]
382 fn tool_kind_variants_roundtrip() {
383 for kind in [
384 crate::acp::ToolKind::Read,
385 crate::acp::ToolKind::Edit,
386 crate::acp::ToolKind::Write,
387 crate::acp::ToolKind::Execute,
388 crate::acp::ToolKind::Search,
389 crate::acp::ToolKind::Fetch,
390 crate::acp::ToolKind::WebSearch,
391 crate::acp::ToolKind::Other,
392 ] {
393 assert_roundtrip(&kind);
394 }
395 }
396
397 #[test]
398 fn tool_call_status_variants_roundtrip() {
399 for status in [
400 ToolCallStatus::Pending,
401 ToolCallStatus::InProgress,
402 ToolCallStatus::Completed,
403 ToolCallStatus::Failed,
404 ] {
405 assert_roundtrip(&status);
406 }
407 }
408
409 #[test]
410 fn stop_reason_variants_roundtrip() {
411 for reason in [
412 StopReason::EndTurn,
413 StopReason::Cancelled,
414 StopReason::MaxTokens,
415 StopReason::MaxTurnRequests,
416 StopReason::Refusal,
417 ] {
418 assert_roundtrip(&reason);
419 }
420 }
421
422 #[test]
423 fn permission_option_kind_variants_roundtrip() {
424 for kind in [
425 PermissionOptionKind::AllowOnce,
426 PermissionOptionKind::AllowAlways,
427 PermissionOptionKind::RejectOnce,
428 PermissionOptionKind::RejectAlways,
429 ] {
430 assert_roundtrip(&kind);
431 }
432 }
433
434 #[test]
435 fn plan_entry_status_variants_roundtrip() {
436 for status in [
437 PlanEntryStatus::Pending,
438 PlanEntryStatus::InProgress,
439 PlanEntryStatus::Completed,
440 ] {
441 assert_roundtrip(&status);
442 }
443 }
444
445 #[test]
446 fn plan_entry_priority_variants_roundtrip() {
447 for priority in [
448 PlanEntryPriority::Low,
449 PlanEntryPriority::Medium,
450 PlanEntryPriority::High,
451 ] {
452 assert_roundtrip(&priority);
453 }
454 }
455
456 #[test]
457 fn error_code_variants_roundtrip() {
458 for code in [
459 ErrorCode::ParseError,
460 ErrorCode::InvalidRequest,
461 ErrorCode::MethodNotFound,
462 ErrorCode::InvalidParams,
463 ErrorCode::InternalError,
464 ] {
465 assert_roundtrip(&code);
466 }
467 }
468
469 #[test]
470 fn role_variants_roundtrip() {
471 assert_roundtrip(&Role::User);
472 assert_roundtrip(&Role::Assistant);
473 }
474
475 #[test]
476 fn session_config_kind_variants_roundtrip() {
477 assert_json_roundtrip::<SessionConfigKind>(r#"{"type":"boolean","currentValue":true}"#);
480 assert_json_roundtrip::<SessionConfigKind>(
483 r#"{"type":"select","currentValue":"a","options":[{"value":"a","name":"A"}]}"#,
484 );
485 }
486
487 #[test]
488 fn content_block_variants_roundtrip() {
489 assert_json_roundtrip::<ContentBlock>(r#"{"type":"text","text":"hello"}"#);
491 assert_json_roundtrip::<ContentBlock>(
493 r#"{"type":"image","data":"AAAA","mimeType":"image/png"}"#,
494 );
495 assert_json_roundtrip::<ContentBlock>(
497 r#"{"type":"audio","data":"AAAA","mimeType":"audio/wav"}"#,
498 );
499 assert_json_roundtrip::<ContentBlock>(
501 r#"{"type":"resource_link","uri":"file:///tmp/data.txt","name":"data.txt","mimeType":"text/plain"}"#,
502 );
503 assert_json_roundtrip::<ContentBlock>(
505 r#"{"type":"resource","resource":{"uri":"file:///tmp/x","mimeType":"text/plain","text":"content"}}"#,
506 );
507 }
508
509 #[test]
510 fn tool_call_content_variants_roundtrip() {
511 assert_json_roundtrip::<ToolCallContent>(
513 r#"{"type":"content","content":{"type":"text","text":"output"}}"#,
514 );
515 assert_json_roundtrip::<ToolCallContent>(
517 r#"{"type":"diff","path":"/tmp/file.txt","newText":"hello"}"#,
518 );
519 assert_json_roundtrip::<ToolCallContent>(r#"{"type":"terminal","terminalId":"t1"}"#);
521 }
522
523 #[test]
524 fn session_update_variants_roundtrip() {
525 assert_json_roundtrip::<SessionUpdate>(
527 r#"{"sessionUpdate":"user_message_chunk","content":{"type":"text","text":"hello"}}"#,
528 );
529 assert_json_roundtrip::<SessionUpdate>(
531 r#"{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"hi"}}"#,
532 );
533 assert_json_roundtrip::<SessionUpdate>(
535 r#"{"sessionUpdate":"tool_call","toolCallId":"tc1","title":"test","kind":"bash","status":"in_progress"}"#,
536 );
537 assert_json_roundtrip::<SessionUpdate>(
539 r#"{"sessionUpdate":"tool_call_update","toolCallId":"tc1","status":"completed"}"#,
540 );
541 }
542
543 #[test]
544 fn mcp_server_variants_roundtrip() {
545 assert_json_roundtrip::<McpServer>(
547 r#"{"name":"fs","command":"node","args":["server.js"],"env":[]}"#,
548 );
549 assert_json_roundtrip::<McpServer>(
551 r#"{"type":"http","name":"api","url":"http://localhost:8080","headers":[]}"#,
552 );
553 assert_json_roundtrip::<McpServer>(
555 r#"{"type":"sse","name":"events","url":"http://localhost:8080/sse","headers":[]}"#,
556 );
557 }
558
559 #[test]
560 fn embedded_resource_resource_variants_roundtrip() {
561 assert_json_roundtrip::<EmbeddedResourceResource>(
563 r#"{"uri":"file:///tmp/x","mimeType":"text/plain","text":"hello"}"#,
564 );
565 assert_json_roundtrip::<EmbeddedResourceResource>(
567 r#"{"uri":"file:///tmp/x","mimeType":"application/octet-stream","blob":"AAAA"}"#,
568 );
569 }
570
571 #[test]
572 fn auth_method_variants_roundtrip() {
573 assert_json_roundtrip::<AuthMethod>(r#"{"id":"github","name":"GitHub"}"#);
576 }
577
578 #[test]
579 fn available_command_input_variants_roundtrip() {
580 assert_json_roundtrip::<AvailableCommandInput>(r#"{"hint":"query"}"#);
582 }
583
584 #[test]
587 fn initialize_request_roundtrip() {
588 assert_json_roundtrip::<InitializeRequest>(
589 r#"{"protocolVersion":1,"clientCapabilities":{"terminal":true},"clientInfo":{"name":"zed","version":"1.0"}}"#,
590 );
591 }
592
593 #[test]
594 fn initialize_response_roundtrip() {
595 assert_json_roundtrip::<InitializeResponse>(
596 r#"{"protocolVersion":1,"agentInfo":{"name":"recursive","version":"0.7.0"},"agentCapabilities":{"promptCapabilities":{"text":true}}}"#,
597 );
598 }
599
600 #[test]
601 fn new_session_request_roundtrip() {
602 assert_json_roundtrip::<NewSessionRequest>(r#"{"cwd":"/tmp","mcpServers":[]}"#);
603 }
604
605 #[test]
606 fn new_session_response_roundtrip() {
607 assert_json_roundtrip::<NewSessionResponse>(r#"{"sessionId":"s1","capabilities":{}}"#);
608 }
609
610 #[test]
611 fn prompt_request_roundtrip() {
612 assert_json_roundtrip::<PromptRequest>(
613 r#"{"sessionId":"s1","prompt":[{"type":"text","text":"hello"}]}"#,
614 );
615 }
616
617 #[test]
618 fn prompt_response_roundtrip() {
619 assert_json_roundtrip::<PromptResponse>(r#"{"stopReason":"end_turn"}"#);
620 }
621
622 #[test]
623 fn cancel_notification_roundtrip() {
624 assert_json_roundtrip::<CancelNotification>(
625 r#"{"sessionId":"s1","reason":"user request"}"#,
626 );
627 }
628
629 #[test]
630 fn session_notification_roundtrip() {
631 assert_json_roundtrip::<SessionNotification>(
632 r#"{"sessionId":"s1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"hi"}}}"#,
633 );
634 }
635
636 #[test]
637 fn tool_call_roundtrip() {
638 assert_json_roundtrip::<ToolCall>(
639 r#"{"toolCallId":"tc1","title":"test","kind":"bash","status":"in_progress"}"#,
640 );
641 }
642
643 #[test]
644 fn tool_call_update_roundtrip() {
645 assert_json_roundtrip::<ToolCallUpdate>(r#"{"toolCallId":"tc1","status":"completed"}"#);
646 }
647
648 #[test]
649 fn tool_call_location_roundtrip() {
650 assert_json_roundtrip::<ToolCallLocation>(r#"{"path":"/tmp/file.txt","line":42}"#);
651 }
652
653 #[test]
654 fn diff_roundtrip() {
655 assert_json_roundtrip::<Diff>(r#"{"path":"/tmp/file.txt","newText":"hello"}"#);
656 }
657
658 #[test]
659 fn annotations_roundtrip() {
660 assert_json_roundtrip::<Annotations>(r#"{"audience":["user"],"priority":0.5}"#);
661 }
662
663 #[test]
664 fn cost_roundtrip() {
665 assert_json_roundtrip::<Cost>(r#"{"amount":0.05,"currency":"USD"}"#);
666 }
667
668 #[test]
669 fn content_chunk_roundtrip() {
670 assert_json_roundtrip::<ContentChunk>(
671 r#"{"type":"text","content":{"type":"text","text":"hello"}}"#,
672 );
673 }
674
675 #[test]
676 fn agent_capabilities_roundtrip() {
677 assert_json_roundtrip::<AgentCapabilities>(
678 r#"{"promptCapabilities":{"text":true},"mcpCapabilities":{"http":true}}"#,
679 );
680 }
681
682 #[test]
683 fn client_capabilities_roundtrip() {
684 assert_json_roundtrip::<ClientCapabilities>(r#"{"terminal":true}"#);
685 }
686
687 #[test]
688 fn session_capabilities_roundtrip() {
689 assert_json_roundtrip::<SessionCapabilities>(r#"{}"#);
690 }
691
692 #[test]
693 fn request_permission_request_roundtrip() {
694 assert_json_roundtrip::<RequestPermissionRequest>(
696 r#"{"sessionId":"s1","toolCall":{"toolCallId":"tc1"},"options":[{"kind":"allow_once","optionId":"opt1","name":"Allow"}]}"#,
697 );
698 }
699
700 #[test]
701 fn request_permission_response_roundtrip() {
702 assert_json_roundtrip::<RequestPermissionResponse>(
703 r#"{"outcome":{"outcome":"selected","optionId":"opt1"}}"#,
704 );
705 }
706
707 #[test]
708 fn implementation_roundtrip() {
709 assert_json_roundtrip::<Implementation>(r#"{"name":"recursive","version":"0.7.0"}"#);
710 }
711
712 #[test]
713 fn load_session_request_roundtrip() {
714 assert_json_roundtrip::<LoadSessionRequest>(
715 r#"{"sessionId":"s1","cwd":"/tmp","mcpServers":[]}"#,
716 );
717 }
718
719 #[test]
720 fn load_session_response_roundtrip() {
721 assert_json_roundtrip::<LoadSessionResponse>(r#"{"sessionId":"s1","messages":[]}"#);
722 }
723
724 #[test]
725 fn close_session_request_roundtrip() {
726 assert_json_roundtrip::<CloseSessionRequest>(r#"{"sessionId":"s1"}"#);
727 }
728
729 #[test]
730 fn close_session_response_roundtrip() {
731 assert_json_roundtrip::<CloseSessionResponse>(r#"{}"#);
732 }
733
734 #[test]
735 fn session_id_roundtrip() {
736 assert_json_roundtrip::<SessionId>(r#""session-abc-123""#);
737 }
738
739 #[test]
740 fn tool_call_id_roundtrip() {
741 assert_json_roundtrip::<ToolCallId>(r#""tc-xyz""#);
742 }
743
744 #[test]
745 fn message_id_roundtrip() {
746 assert_json_roundtrip::<MessageId>(r#""msg-456""#);
747 }
748
749 #[test]
750 fn terminal_id_roundtrip() {
751 assert_json_roundtrip::<TerminalId>(r#""term-1""#);
752 }
753
754 #[test]
755 fn text_content_roundtrip() {
756 assert_json_roundtrip::<TextContent>(r#"{"type":"text","text":"hello"}"#);
757 }
758
759 #[test]
760 fn image_content_roundtrip() {
761 assert_json_roundtrip::<ImageContent>(
762 r#"{"type":"image","data":"AAAA","mimeType":"image/png"}"#,
763 );
764 }
765
766 #[test]
767 fn plan_roundtrip() {
768 assert_json_roundtrip::<Plan>(r#"{"entries":[]}"#);
769 }
770
771 #[test]
772 fn plan_entry_roundtrip() {
773 assert_json_roundtrip::<PlanEntry>(
774 r#"{"id":"p1","content":"Do X","status":"pending","priority":"medium"}"#,
775 );
776 }
777
778 #[test]
779 fn session_mode_roundtrip() {
780 assert_json_roundtrip::<SessionMode>(r#"{"id":"default","name":"Default"}"#);
781 }
782
783 #[test]
784 fn mcp_capabilities_roundtrip() {
785 assert_json_roundtrip::<McpCapabilities>(r#"{"http":true,"sse":false}"#);
786 }
787
788 #[test]
789 fn file_system_capabilities_roundtrip() {
790 assert_json_roundtrip::<FileSystemCapabilities>(
791 r#"{"readTextFile":true,"writeTextFile":false}"#,
792 );
793 }
794
795 #[test]
796 fn error_roundtrip() {
797 assert_json_roundtrip::<Error>(r#"{"code":-32600,"message":"Invalid Request"}"#);
798 }
799
800 #[test]
801 fn usage_update_roundtrip() {
802 assert_json_roundtrip::<UsageUpdate>(r#"{"used":1500,"size":200000}"#);
803 }
804
805 #[test]
806 fn auth_method_agent_roundtrip() {
807 assert_json_roundtrip::<AuthMethodAgent>(r#"{"id":"github","name":"GitHub"}"#);
808 }
809
810 #[test]
811 fn env_variable_roundtrip() {
812 assert_json_roundtrip::<EnvVariable>(r#"{"name":"API_KEY","value":"secret123"}"#);
813 }
814
815 #[test]
816 fn http_header_roundtrip() {
817 assert_json_roundtrip::<HttpHeader>(r#"{"name":"Authorization","value":"Bearer token"}"#);
818 }
819
820 #[test]
823 fn option_field_none() {
824 assert_json_roundtrip::<Implementation>(r#"{"name":"test","version":"1.0"}"#);
826 assert_json_roundtrip::<Implementation>(
828 r#"{"name":"test","version":"1.0","title":"Test App"}"#,
829 );
830 assert_json_roundtrip::<Annotations>(r#"{}"#);
832 assert_json_roundtrip::<ToolCallLocation>(r#"{"path":"/tmp/f"}"#);
834 assert_json_roundtrip::<Diff>(r#"{"path":"/tmp/f","newText":"new"}"#);
836 }
837
838 #[test]
839 fn vec_field_empty() {
840 assert_json_roundtrip::<Plan>(r#"{"entries":[]}"#);
842 assert_json_roundtrip::<PromptRequest>(r#"{"sessionId":"s1","prompt":[]}"#);
844 assert_json_roundtrip::<LoadSessionResponse>(r#"{"sessionId":"s1","messages":[]}"#);
846 assert_json_roundtrip::<ToolCall>(
848 r#"{"toolCallId":"tc1","title":"t","content":[],"locations":[]}"#,
849 );
850 }
851
852 #[test]
853 fn nested_enum_coverage() {
854 assert_json_roundtrip::<ContentChunk>(
856 r#"{"type":"text","content":{"type":"text","text":"hello"}}"#,
857 );
858 assert_json_roundtrip::<ContentChunk>(
860 r#"{"type":"image","content":{"type":"image","data":"AAAA","mimeType":"image/png"}}"#,
861 );
862 assert_json_roundtrip::<ContentChunk>(
864 r#"{"type":"resource_link","content":{"type":"resource_link","uri":"file:///x","name":"x","mimeType":"text/plain"}}"#,
865 );
866
867 assert_json_roundtrip::<SessionNotification>(
869 r#"{"sessionId":"s1","update":{"sessionUpdate":"tool_call","toolCallId":"tc1","title":"Run","kind":"execute","status":"in_progress"}}"#,
870 );
871 }
872
873 #[test]
874 fn enum_non_default_variant_roundtrip() {
875 assert_roundtrip(&crate::acp::ToolKind::Read);
877 assert_roundtrip(&crate::acp::ToolKind::Edit);
878 assert_roundtrip(&ToolCallStatus::Completed);
880 assert_roundtrip(&ToolCallStatus::Failed);
881 assert_roundtrip(&StopReason::Cancelled);
883 assert_roundtrip(&StopReason::Refusal);
884 }
885
886 #[test]
887 fn session_update_plan_variant_roundtrip() {
888 assert_json_roundtrip::<SessionUpdate>(r#"{"sessionUpdate":"plan","entries":[]}"#);
890 }
891
892 #[test]
893 fn session_update_usage_update_variant_roundtrip() {
894 assert_json_roundtrip::<SessionUpdate>(
895 r#"{"sessionUpdate":"usage_update","used":1000,"size":200000}"#,
896 );
897 }
898
899 #[test]
900 fn permission_option_all_kinds() {
901 for (kind_str, kind) in [
902 ("allow_once", PermissionOptionKind::AllowOnce),
903 ("allow_always", PermissionOptionKind::AllowAlways),
904 ("reject_once", PermissionOptionKind::RejectOnce),
905 ("reject_always", PermissionOptionKind::RejectAlways),
906 ] {
907 let json = format!(r#"{{"kind":"{kind_str}","optionId":"o1","name":"L"}}"#);
908 assert_json_roundtrip::<PermissionOption>(&json);
909 assert_roundtrip(&kind);
910 }
911 }
912}