1use std::{path::PathBuf, sync::Arc};
7
8#[cfg(any(feature = "unstable_auth_methods", feature = "unstable_llm_providers"))]
9use std::collections::HashMap;
10
11use derive_more::{Display, From};
12use schemars::JsonSchema;
13use serde::{Deserialize, Serialize};
14use serde_with::{DefaultOnError, VecSkipError, serde_as, skip_serializing_none};
15
16use crate::{
17 ClientCapabilities, ContentBlock, ExtNotification, ExtRequest, ExtResponse, IntoOption, Meta,
18 ProtocolVersion, SessionId, SkipListener,
19};
20
21#[cfg(feature = "unstable_mcp_over_acp")]
22use super::mcp::{
23 MCP_MESSAGE_METHOD_NAME, MessageMcpNotification, MessageMcpRequest, MessageMcpResponse,
24};
25
26#[cfg(feature = "unstable_nes")]
27use crate::{
28 AcceptNesNotification, CloseNesRequest, CloseNesResponse, DidChangeDocumentNotification,
29 DidCloseDocumentNotification, DidFocusDocumentNotification, DidOpenDocumentNotification,
30 DidSaveDocumentNotification, NesCapabilities, PositionEncodingKind, RejectNesNotification,
31 StartNesRequest, StartNesResponse, SuggestNesRequest, SuggestNesResponse,
32};
33
34#[cfg(feature = "unstable_nes")]
35use crate::{
36 DOCUMENT_DID_CHANGE_METHOD_NAME, DOCUMENT_DID_CLOSE_METHOD_NAME,
37 DOCUMENT_DID_FOCUS_METHOD_NAME, DOCUMENT_DID_OPEN_METHOD_NAME, DOCUMENT_DID_SAVE_METHOD_NAME,
38 NES_ACCEPT_METHOD_NAME, NES_CLOSE_METHOD_NAME, NES_REJECT_METHOD_NAME, NES_START_METHOD_NAME,
39 NES_SUGGEST_METHOD_NAME,
40};
41
42#[serde_as]
50#[skip_serializing_none]
51#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
52#[schemars(extend("x-side" = "agent", "x-method" = INITIALIZE_METHOD_NAME))]
53#[serde(rename_all = "camelCase")]
54#[non_exhaustive]
55pub struct InitializeRequest {
56 pub protocol_version: ProtocolVersion,
58 #[serde(default)]
60 pub client_capabilities: ClientCapabilities,
61 #[serde_as(deserialize_as = "DefaultOnError")]
65 #[serde(default)]
66 pub client_info: Option<Implementation>,
67 #[serde(rename = "_meta")]
73 pub meta: Option<Meta>,
74}
75
76impl InitializeRequest {
77 #[must_use]
78 pub fn new(protocol_version: ProtocolVersion) -> Self {
79 Self {
80 protocol_version,
81 client_capabilities: ClientCapabilities::default(),
82 client_info: None,
83 meta: None,
84 }
85 }
86
87 #[must_use]
89 pub fn client_capabilities(mut self, client_capabilities: ClientCapabilities) -> Self {
90 self.client_capabilities = client_capabilities;
91 self
92 }
93
94 #[must_use]
96 pub fn client_info(mut self, client_info: impl IntoOption<Implementation>) -> Self {
97 self.client_info = client_info.into_option();
98 self
99 }
100
101 #[must_use]
107 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
108 self.meta = meta.into_option();
109 self
110 }
111}
112
113#[serde_as]
119#[skip_serializing_none]
120#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
121#[schemars(extend("x-side" = "agent", "x-method" = INITIALIZE_METHOD_NAME))]
122#[serde(rename_all = "camelCase")]
123#[non_exhaustive]
124pub struct InitializeResponse {
125 pub protocol_version: ProtocolVersion,
130 #[serde(default)]
132 pub agent_capabilities: AgentCapabilities,
133 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
135 #[serde(default)]
136 pub auth_methods: Vec<AuthMethod>,
137 #[serde_as(deserialize_as = "DefaultOnError")]
141 #[serde(default)]
142 pub agent_info: Option<Implementation>,
143 #[serde(rename = "_meta")]
149 pub meta: Option<Meta>,
150}
151
152impl InitializeResponse {
153 #[must_use]
154 pub fn new(protocol_version: ProtocolVersion) -> Self {
155 Self {
156 protocol_version,
157 agent_capabilities: AgentCapabilities::default(),
158 auth_methods: vec![],
159 agent_info: None,
160 meta: None,
161 }
162 }
163
164 #[must_use]
166 pub fn agent_capabilities(mut self, agent_capabilities: AgentCapabilities) -> Self {
167 self.agent_capabilities = agent_capabilities;
168 self
169 }
170
171 #[must_use]
173 pub fn auth_methods(mut self, auth_methods: Vec<AuthMethod>) -> Self {
174 self.auth_methods = auth_methods;
175 self
176 }
177
178 #[must_use]
180 pub fn agent_info(mut self, agent_info: impl IntoOption<Implementation>) -> Self {
181 self.agent_info = agent_info.into_option();
182 self
183 }
184
185 #[must_use]
191 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
192 self.meta = meta.into_option();
193 self
194 }
195}
196
197#[skip_serializing_none]
201#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
202#[serde(rename_all = "camelCase")]
203#[non_exhaustive]
204pub struct Implementation {
205 pub name: String,
208 pub title: Option<String>,
213 pub version: String,
216 #[serde(rename = "_meta")]
222 pub meta: Option<Meta>,
223}
224
225impl Implementation {
226 #[must_use]
227 pub fn new(name: impl Into<String>, version: impl Into<String>) -> Self {
228 Self {
229 name: name.into(),
230 title: None,
231 version: version.into(),
232 meta: None,
233 }
234 }
235
236 #[must_use]
241 pub fn title(mut self, title: impl IntoOption<String>) -> Self {
242 self.title = title.into_option();
243 self
244 }
245
246 #[must_use]
252 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
253 self.meta = meta.into_option();
254 self
255 }
256}
257
258#[skip_serializing_none]
264#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
265#[schemars(extend("x-side" = "agent", "x-method" = AUTHENTICATE_METHOD_NAME))]
266#[serde(rename_all = "camelCase")]
267#[non_exhaustive]
268pub struct AuthenticateRequest {
269 pub method_id: AuthMethodId,
272 #[serde(rename = "_meta")]
278 pub meta: Option<Meta>,
279}
280
281impl AuthenticateRequest {
282 #[must_use]
283 pub fn new(method_id: impl Into<AuthMethodId>) -> Self {
284 Self {
285 method_id: method_id.into(),
286 meta: None,
287 }
288 }
289
290 #[must_use]
296 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
297 self.meta = meta.into_option();
298 self
299 }
300}
301
302#[skip_serializing_none]
304#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
305#[schemars(extend("x-side" = "agent", "x-method" = AUTHENTICATE_METHOD_NAME))]
306#[serde(rename_all = "camelCase")]
307#[non_exhaustive]
308pub struct AuthenticateResponse {
309 #[serde(rename = "_meta")]
315 pub meta: Option<Meta>,
316}
317
318impl AuthenticateResponse {
319 #[must_use]
320 pub fn new() -> Self {
321 Self::default()
322 }
323
324 #[must_use]
330 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
331 self.meta = meta.into_option();
332 self
333 }
334}
335
336#[skip_serializing_none]
342#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
343#[schemars(extend("x-side" = "agent", "x-method" = LOGOUT_METHOD_NAME))]
344#[serde(rename_all = "camelCase")]
345#[non_exhaustive]
346pub struct LogoutRequest {
347 #[serde(rename = "_meta")]
353 pub meta: Option<Meta>,
354}
355
356impl LogoutRequest {
357 #[must_use]
358 pub fn new() -> Self {
359 Self::default()
360 }
361
362 #[must_use]
368 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
369 self.meta = meta.into_option();
370 self
371 }
372}
373
374#[skip_serializing_none]
376#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
377#[schemars(extend("x-side" = "agent", "x-method" = LOGOUT_METHOD_NAME))]
378#[serde(rename_all = "camelCase")]
379#[non_exhaustive]
380pub struct LogoutResponse {
381 #[serde(rename = "_meta")]
387 pub meta: Option<Meta>,
388}
389
390impl LogoutResponse {
391 #[must_use]
392 pub fn new() -> Self {
393 Self::default()
394 }
395
396 #[must_use]
402 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
403 self.meta = meta.into_option();
404 self
405 }
406}
407
408#[serde_as]
410#[skip_serializing_none]
411#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
412#[serde(rename_all = "camelCase")]
413#[non_exhaustive]
414pub struct AgentAuthCapabilities {
415 #[serde_as(deserialize_as = "DefaultOnError")]
419 #[serde(default)]
420 pub logout: Option<LogoutCapabilities>,
421 #[serde(rename = "_meta")]
427 pub meta: Option<Meta>,
428}
429
430impl AgentAuthCapabilities {
431 #[must_use]
432 pub fn new() -> Self {
433 Self::default()
434 }
435
436 #[must_use]
438 pub fn logout(mut self, logout: impl IntoOption<LogoutCapabilities>) -> Self {
439 self.logout = logout.into_option();
440 self
441 }
442
443 #[must_use]
449 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
450 self.meta = meta.into_option();
451 self
452 }
453}
454
455#[skip_serializing_none]
459#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
460#[non_exhaustive]
461pub struct LogoutCapabilities {
462 #[serde(rename = "_meta")]
468 pub meta: Option<Meta>,
469}
470
471impl LogoutCapabilities {
472 #[must_use]
473 pub fn new() -> Self {
474 Self::default()
475 }
476
477 #[must_use]
483 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
484 self.meta = meta.into_option();
485 self
486 }
487}
488
489#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
490#[serde(transparent)]
491#[from(Arc<str>, String, &'static str)]
492#[non_exhaustive]
493pub struct AuthMethodId(pub Arc<str>);
494
495impl AuthMethodId {
496 #[must_use]
497 pub fn new(id: impl Into<Arc<str>>) -> Self {
498 Self(id.into())
499 }
500}
501
502#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
507#[serde(tag = "type", rename_all = "snake_case")]
508#[non_exhaustive]
509pub enum AuthMethod {
510 #[cfg(feature = "unstable_auth_methods")]
516 EnvVar(AuthMethodEnvVar),
517 #[cfg(feature = "unstable_auth_methods")]
523 Terminal(AuthMethodTerminal),
524 #[serde(untagged)]
528 Agent(AuthMethodAgent),
529}
530
531impl AuthMethod {
532 #[must_use]
534 pub fn id(&self) -> &AuthMethodId {
535 match self {
536 Self::Agent(a) => &a.id,
537 #[cfg(feature = "unstable_auth_methods")]
538 Self::EnvVar(e) => &e.id,
539 #[cfg(feature = "unstable_auth_methods")]
540 Self::Terminal(t) => &t.id,
541 }
542 }
543
544 #[must_use]
546 pub fn name(&self) -> &str {
547 match self {
548 Self::Agent(a) => &a.name,
549 #[cfg(feature = "unstable_auth_methods")]
550 Self::EnvVar(e) => &e.name,
551 #[cfg(feature = "unstable_auth_methods")]
552 Self::Terminal(t) => &t.name,
553 }
554 }
555
556 #[must_use]
558 pub fn description(&self) -> Option<&str> {
559 match self {
560 Self::Agent(a) => a.description.as_deref(),
561 #[cfg(feature = "unstable_auth_methods")]
562 Self::EnvVar(e) => e.description.as_deref(),
563 #[cfg(feature = "unstable_auth_methods")]
564 Self::Terminal(t) => t.description.as_deref(),
565 }
566 }
567
568 #[must_use]
574 pub fn meta(&self) -> Option<&Meta> {
575 match self {
576 Self::Agent(a) => a.meta.as_ref(),
577 #[cfg(feature = "unstable_auth_methods")]
578 Self::EnvVar(e) => e.meta.as_ref(),
579 #[cfg(feature = "unstable_auth_methods")]
580 Self::Terminal(t) => t.meta.as_ref(),
581 }
582 }
583}
584
585#[skip_serializing_none]
589#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
590#[serde(rename_all = "camelCase")]
591#[non_exhaustive]
592pub struct AuthMethodAgent {
593 pub id: AuthMethodId,
595 pub name: String,
597 pub description: Option<String>,
599 #[serde(rename = "_meta")]
605 pub meta: Option<Meta>,
606}
607
608impl AuthMethodAgent {
609 #[must_use]
610 pub fn new(id: impl Into<AuthMethodId>, name: impl Into<String>) -> Self {
611 Self {
612 id: id.into(),
613 name: name.into(),
614 description: None,
615 meta: None,
616 }
617 }
618
619 #[must_use]
621 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
622 self.description = description.into_option();
623 self
624 }
625
626 #[must_use]
632 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
633 self.meta = meta.into_option();
634 self
635 }
636}
637
638#[cfg(feature = "unstable_auth_methods")]
646#[skip_serializing_none]
647#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
648#[serde(rename_all = "camelCase")]
649#[non_exhaustive]
650pub struct AuthMethodEnvVar {
651 pub id: AuthMethodId,
653 pub name: String,
655 pub description: Option<String>,
657 pub vars: Vec<AuthEnvVar>,
659 pub link: Option<String>,
661 #[serde(rename = "_meta")]
667 pub meta: Option<Meta>,
668}
669
670#[cfg(feature = "unstable_auth_methods")]
671impl AuthMethodEnvVar {
672 #[must_use]
673 pub fn new(
674 id: impl Into<AuthMethodId>,
675 name: impl Into<String>,
676 vars: Vec<AuthEnvVar>,
677 ) -> Self {
678 Self {
679 id: id.into(),
680 name: name.into(),
681 description: None,
682 vars,
683 link: None,
684 meta: None,
685 }
686 }
687
688 #[must_use]
690 pub fn link(mut self, link: impl IntoOption<String>) -> Self {
691 self.link = link.into_option();
692 self
693 }
694
695 #[must_use]
697 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
698 self.description = description.into_option();
699 self
700 }
701
702 #[must_use]
708 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
709 self.meta = meta.into_option();
710 self
711 }
712}
713
714#[cfg(feature = "unstable_auth_methods")]
720#[skip_serializing_none]
721#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
722#[serde(rename_all = "camelCase")]
723#[non_exhaustive]
724pub struct AuthEnvVar {
725 pub name: String,
727 pub label: Option<String>,
729 #[serde(default = "default_true", skip_serializing_if = "is_true")]
734 #[schemars(extend("default" = true))]
735 pub secret: bool,
736 #[serde(default, skip_serializing_if = "is_false")]
740 #[schemars(extend("default" = false))]
741 pub optional: bool,
742 #[serde(rename = "_meta")]
748 pub meta: Option<Meta>,
749}
750
751#[cfg(feature = "unstable_auth_methods")]
752fn default_true() -> bool {
753 true
754}
755
756#[cfg(feature = "unstable_auth_methods")]
757#[expect(clippy::trivially_copy_pass_by_ref)]
758fn is_true(v: &bool) -> bool {
759 *v
760}
761
762#[cfg(feature = "unstable_auth_methods")]
763#[expect(clippy::trivially_copy_pass_by_ref)]
764fn is_false(v: &bool) -> bool {
765 !*v
766}
767
768#[cfg(feature = "unstable_auth_methods")]
769impl AuthEnvVar {
770 #[must_use]
772 pub fn new(name: impl Into<String>) -> Self {
773 Self {
774 name: name.into(),
775 label: None,
776 secret: true,
777 optional: false,
778 meta: None,
779 }
780 }
781
782 #[must_use]
784 pub fn label(mut self, label: impl IntoOption<String>) -> Self {
785 self.label = label.into_option();
786 self
787 }
788
789 #[must_use]
792 pub fn secret(mut self, secret: bool) -> Self {
793 self.secret = secret;
794 self
795 }
796
797 #[must_use]
799 pub fn optional(mut self, optional: bool) -> Self {
800 self.optional = optional;
801 self
802 }
803
804 #[must_use]
810 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
811 self.meta = meta.into_option();
812 self
813 }
814}
815
816#[cfg(feature = "unstable_auth_methods")]
824#[skip_serializing_none]
825#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
826#[serde(rename_all = "camelCase")]
827#[non_exhaustive]
828pub struct AuthMethodTerminal {
829 pub id: AuthMethodId,
831 pub name: String,
833 pub description: Option<String>,
835 #[serde(default, skip_serializing_if = "Vec::is_empty")]
837 pub args: Vec<String>,
838 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
840 pub env: HashMap<String, String>,
841 #[serde(rename = "_meta")]
847 pub meta: Option<Meta>,
848}
849
850#[cfg(feature = "unstable_auth_methods")]
851impl AuthMethodTerminal {
852 #[must_use]
853 pub fn new(id: impl Into<AuthMethodId>, name: impl Into<String>) -> Self {
854 Self {
855 id: id.into(),
856 name: name.into(),
857 description: None,
858 args: Vec::new(),
859 env: HashMap::new(),
860 meta: None,
861 }
862 }
863
864 #[must_use]
866 pub fn args(mut self, args: Vec<String>) -> Self {
867 self.args = args;
868 self
869 }
870
871 #[must_use]
873 pub fn env(mut self, env: HashMap<String, String>) -> Self {
874 self.env = env;
875 self
876 }
877
878 #[must_use]
880 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
881 self.description = description.into_option();
882 self
883 }
884
885 #[must_use]
891 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
892 self.meta = meta.into_option();
893 self
894 }
895}
896
897#[skip_serializing_none]
903#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
904#[schemars(extend("x-side" = "agent", "x-method" = SESSION_NEW_METHOD_NAME))]
905#[serde(rename_all = "camelCase")]
906#[non_exhaustive]
907pub struct NewSessionRequest {
908 pub cwd: PathBuf,
910 #[cfg(feature = "unstable_session_additional_directories")]
920 #[serde(default, skip_serializing_if = "Vec::is_empty")]
921 pub additional_directories: Vec<PathBuf>,
922 pub mcp_servers: Vec<McpServer>,
924 #[serde(rename = "_meta")]
930 pub meta: Option<Meta>,
931}
932
933impl NewSessionRequest {
934 #[must_use]
935 pub fn new(cwd: impl Into<PathBuf>) -> Self {
936 Self {
937 cwd: cwd.into(),
938 #[cfg(feature = "unstable_session_additional_directories")]
939 additional_directories: vec![],
940 mcp_servers: vec![],
941 meta: None,
942 }
943 }
944
945 #[cfg(feature = "unstable_session_additional_directories")]
951 #[must_use]
952 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
953 self.additional_directories = additional_directories;
954 self
955 }
956
957 #[must_use]
959 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
960 self.mcp_servers = mcp_servers;
961 self
962 }
963
964 #[must_use]
970 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
971 self.meta = meta.into_option();
972 self
973 }
974}
975
976#[serde_as]
980#[skip_serializing_none]
981#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
982#[schemars(extend("x-side" = "agent", "x-method" = SESSION_NEW_METHOD_NAME))]
983#[serde(rename_all = "camelCase")]
984#[non_exhaustive]
985pub struct NewSessionResponse {
986 pub session_id: SessionId,
990 #[serde_as(deserialize_as = "DefaultOnError")]
994 #[serde(default)]
995 pub modes: Option<SessionModeState>,
996 #[cfg(feature = "unstable_session_model")]
1002 #[serde_as(deserialize_as = "DefaultOnError")]
1003 #[serde(default)]
1004 pub models: Option<SessionModelState>,
1005 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1007 #[serde(default)]
1008 pub config_options: Option<Vec<SessionConfigOption>>,
1009 #[serde(rename = "_meta")]
1015 pub meta: Option<Meta>,
1016}
1017
1018impl NewSessionResponse {
1019 #[must_use]
1020 pub fn new(session_id: impl Into<SessionId>) -> Self {
1021 Self {
1022 session_id: session_id.into(),
1023 modes: None,
1024 #[cfg(feature = "unstable_session_model")]
1025 models: None,
1026 config_options: None,
1027 meta: None,
1028 }
1029 }
1030
1031 #[must_use]
1035 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1036 self.modes = modes.into_option();
1037 self
1038 }
1039
1040 #[cfg(feature = "unstable_session_model")]
1046 #[must_use]
1047 pub fn models(mut self, models: impl IntoOption<SessionModelState>) -> Self {
1048 self.models = models.into_option();
1049 self
1050 }
1051
1052 #[must_use]
1054 pub fn config_options(
1055 mut self,
1056 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1057 ) -> Self {
1058 self.config_options = config_options.into_option();
1059 self
1060 }
1061
1062 #[must_use]
1068 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1069 self.meta = meta.into_option();
1070 self
1071 }
1072}
1073
1074#[skip_serializing_none]
1082#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1083#[schemars(extend("x-side" = "agent", "x-method" = SESSION_LOAD_METHOD_NAME))]
1084#[serde(rename_all = "camelCase")]
1085#[non_exhaustive]
1086pub struct LoadSessionRequest {
1087 pub mcp_servers: Vec<McpServer>,
1089 pub cwd: PathBuf,
1091 #[cfg(feature = "unstable_session_additional_directories")]
1102 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1103 pub additional_directories: Vec<PathBuf>,
1104 pub session_id: SessionId,
1106 #[serde(rename = "_meta")]
1112 pub meta: Option<Meta>,
1113}
1114
1115impl LoadSessionRequest {
1116 #[must_use]
1117 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1118 Self {
1119 mcp_servers: vec![],
1120 cwd: cwd.into(),
1121 #[cfg(feature = "unstable_session_additional_directories")]
1122 additional_directories: vec![],
1123 session_id: session_id.into(),
1124 meta: None,
1125 }
1126 }
1127
1128 #[cfg(feature = "unstable_session_additional_directories")]
1134 #[must_use]
1135 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1136 self.additional_directories = additional_directories;
1137 self
1138 }
1139
1140 #[must_use]
1142 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1143 self.mcp_servers = mcp_servers;
1144 self
1145 }
1146
1147 #[must_use]
1153 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1154 self.meta = meta.into_option();
1155 self
1156 }
1157}
1158
1159#[serde_as]
1161#[skip_serializing_none]
1162#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1163#[schemars(extend("x-side" = "agent", "x-method" = SESSION_LOAD_METHOD_NAME))]
1164#[serde(rename_all = "camelCase")]
1165#[non_exhaustive]
1166pub struct LoadSessionResponse {
1167 #[serde_as(deserialize_as = "DefaultOnError")]
1171 #[serde(default)]
1172 pub modes: Option<SessionModeState>,
1173 #[cfg(feature = "unstable_session_model")]
1179 #[serde_as(deserialize_as = "DefaultOnError")]
1180 #[serde(default)]
1181 pub models: Option<SessionModelState>,
1182 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1184 #[serde(default)]
1185 pub config_options: Option<Vec<SessionConfigOption>>,
1186 #[serde(rename = "_meta")]
1192 pub meta: Option<Meta>,
1193}
1194
1195impl LoadSessionResponse {
1196 #[must_use]
1197 pub fn new() -> Self {
1198 Self::default()
1199 }
1200
1201 #[must_use]
1205 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1206 self.modes = modes.into_option();
1207 self
1208 }
1209
1210 #[cfg(feature = "unstable_session_model")]
1216 #[must_use]
1217 pub fn models(mut self, models: impl IntoOption<SessionModelState>) -> Self {
1218 self.models = models.into_option();
1219 self
1220 }
1221
1222 #[must_use]
1224 pub fn config_options(
1225 mut self,
1226 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1227 ) -> Self {
1228 self.config_options = config_options.into_option();
1229 self
1230 }
1231
1232 #[must_use]
1238 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1239 self.meta = meta.into_option();
1240 self
1241 }
1242}
1243
1244#[cfg(feature = "unstable_session_fork")]
1257#[skip_serializing_none]
1258#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1259#[schemars(extend("x-side" = "agent", "x-method" = SESSION_FORK_METHOD_NAME))]
1260#[serde(rename_all = "camelCase")]
1261#[non_exhaustive]
1262pub struct ForkSessionRequest {
1263 pub session_id: SessionId,
1265 pub cwd: PathBuf,
1267 #[cfg(feature = "unstable_session_additional_directories")]
1277 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1278 pub additional_directories: Vec<PathBuf>,
1279 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1281 pub mcp_servers: Vec<McpServer>,
1282 #[serde(rename = "_meta")]
1288 pub meta: Option<Meta>,
1289}
1290
1291#[cfg(feature = "unstable_session_fork")]
1292impl ForkSessionRequest {
1293 #[must_use]
1294 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1295 Self {
1296 session_id: session_id.into(),
1297 cwd: cwd.into(),
1298 #[cfg(feature = "unstable_session_additional_directories")]
1299 additional_directories: vec![],
1300 mcp_servers: vec![],
1301 meta: None,
1302 }
1303 }
1304
1305 #[cfg(feature = "unstable_session_additional_directories")]
1311 #[must_use]
1312 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1313 self.additional_directories = additional_directories;
1314 self
1315 }
1316
1317 #[must_use]
1319 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1320 self.mcp_servers = mcp_servers;
1321 self
1322 }
1323
1324 #[must_use]
1330 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1331 self.meta = meta.into_option();
1332 self
1333 }
1334}
1335
1336#[cfg(feature = "unstable_session_fork")]
1342#[serde_as]
1343#[skip_serializing_none]
1344#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1345#[schemars(extend("x-side" = "agent", "x-method" = SESSION_FORK_METHOD_NAME))]
1346#[serde(rename_all = "camelCase")]
1347#[non_exhaustive]
1348pub struct ForkSessionResponse {
1349 pub session_id: SessionId,
1351 #[serde_as(deserialize_as = "DefaultOnError")]
1355 #[serde(default)]
1356 pub modes: Option<SessionModeState>,
1357 #[cfg(feature = "unstable_session_model")]
1363 #[serde_as(deserialize_as = "DefaultOnError")]
1364 #[serde(default)]
1365 pub models: Option<SessionModelState>,
1366 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1368 #[serde(default)]
1369 pub config_options: Option<Vec<SessionConfigOption>>,
1370 #[serde(rename = "_meta")]
1376 pub meta: Option<Meta>,
1377}
1378
1379#[cfg(feature = "unstable_session_fork")]
1380impl ForkSessionResponse {
1381 #[must_use]
1382 pub fn new(session_id: impl Into<SessionId>) -> Self {
1383 Self {
1384 session_id: session_id.into(),
1385 modes: None,
1386 #[cfg(feature = "unstable_session_model")]
1387 models: None,
1388 config_options: None,
1389 meta: None,
1390 }
1391 }
1392
1393 #[must_use]
1397 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1398 self.modes = modes.into_option();
1399 self
1400 }
1401
1402 #[cfg(feature = "unstable_session_model")]
1408 #[must_use]
1409 pub fn models(mut self, models: impl IntoOption<SessionModelState>) -> Self {
1410 self.models = models.into_option();
1411 self
1412 }
1413
1414 #[must_use]
1416 pub fn config_options(
1417 mut self,
1418 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1419 ) -> Self {
1420 self.config_options = config_options.into_option();
1421 self
1422 }
1423
1424 #[must_use]
1430 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1431 self.meta = meta.into_option();
1432 self
1433 }
1434}
1435
1436#[skip_serializing_none]
1445#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1446#[schemars(extend("x-side" = "agent", "x-method" = SESSION_RESUME_METHOD_NAME))]
1447#[serde(rename_all = "camelCase")]
1448#[non_exhaustive]
1449pub struct ResumeSessionRequest {
1450 pub session_id: SessionId,
1452 pub cwd: PathBuf,
1454 #[cfg(feature = "unstable_session_additional_directories")]
1465 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1466 pub additional_directories: Vec<PathBuf>,
1467 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1469 pub mcp_servers: Vec<McpServer>,
1470 #[serde(rename = "_meta")]
1476 pub meta: Option<Meta>,
1477}
1478
1479impl ResumeSessionRequest {
1480 #[must_use]
1481 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1482 Self {
1483 session_id: session_id.into(),
1484 cwd: cwd.into(),
1485 #[cfg(feature = "unstable_session_additional_directories")]
1486 additional_directories: vec![],
1487 mcp_servers: vec![],
1488 meta: None,
1489 }
1490 }
1491
1492 #[cfg(feature = "unstable_session_additional_directories")]
1498 #[must_use]
1499 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1500 self.additional_directories = additional_directories;
1501 self
1502 }
1503
1504 #[must_use]
1506 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1507 self.mcp_servers = mcp_servers;
1508 self
1509 }
1510
1511 #[must_use]
1517 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1518 self.meta = meta.into_option();
1519 self
1520 }
1521}
1522
1523#[serde_as]
1525#[skip_serializing_none]
1526#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1527#[schemars(extend("x-side" = "agent", "x-method" = SESSION_RESUME_METHOD_NAME))]
1528#[serde(rename_all = "camelCase")]
1529#[non_exhaustive]
1530pub struct ResumeSessionResponse {
1531 #[serde_as(deserialize_as = "DefaultOnError")]
1535 #[serde(default)]
1536 pub modes: Option<SessionModeState>,
1537 #[cfg(feature = "unstable_session_model")]
1543 #[serde_as(deserialize_as = "DefaultOnError")]
1544 #[serde(default)]
1545 pub models: Option<SessionModelState>,
1546 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1548 #[serde(default)]
1549 pub config_options: Option<Vec<SessionConfigOption>>,
1550 #[serde(rename = "_meta")]
1556 pub meta: Option<Meta>,
1557}
1558
1559impl ResumeSessionResponse {
1560 #[must_use]
1561 pub fn new() -> Self {
1562 Self::default()
1563 }
1564
1565 #[must_use]
1569 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1570 self.modes = modes.into_option();
1571 self
1572 }
1573
1574 #[cfg(feature = "unstable_session_model")]
1580 #[must_use]
1581 pub fn models(mut self, models: impl IntoOption<SessionModelState>) -> Self {
1582 self.models = models.into_option();
1583 self
1584 }
1585
1586 #[must_use]
1588 pub fn config_options(
1589 mut self,
1590 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1591 ) -> Self {
1592 self.config_options = config_options.into_option();
1593 self
1594 }
1595
1596 #[must_use]
1602 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1603 self.meta = meta.into_option();
1604 self
1605 }
1606}
1607
1608#[skip_serializing_none]
1618#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1619#[schemars(extend("x-side" = "agent", "x-method" = SESSION_CLOSE_METHOD_NAME))]
1620#[serde(rename_all = "camelCase")]
1621#[non_exhaustive]
1622pub struct CloseSessionRequest {
1623 pub session_id: SessionId,
1625 #[serde(rename = "_meta")]
1631 pub meta: Option<Meta>,
1632}
1633
1634impl CloseSessionRequest {
1635 #[must_use]
1636 pub fn new(session_id: impl Into<SessionId>) -> Self {
1637 Self {
1638 session_id: session_id.into(),
1639 meta: None,
1640 }
1641 }
1642
1643 #[must_use]
1649 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1650 self.meta = meta.into_option();
1651 self
1652 }
1653}
1654
1655#[skip_serializing_none]
1657#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1658#[schemars(extend("x-side" = "agent", "x-method" = SESSION_CLOSE_METHOD_NAME))]
1659#[serde(rename_all = "camelCase")]
1660#[non_exhaustive]
1661pub struct CloseSessionResponse {
1662 #[serde(rename = "_meta")]
1668 pub meta: Option<Meta>,
1669}
1670
1671impl CloseSessionResponse {
1672 #[must_use]
1673 pub fn new() -> Self {
1674 Self::default()
1675 }
1676
1677 #[must_use]
1683 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1684 self.meta = meta.into_option();
1685 self
1686 }
1687}
1688
1689#[skip_serializing_none]
1695#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1696#[schemars(extend("x-side" = "agent", "x-method" = SESSION_LIST_METHOD_NAME))]
1697#[serde(rename_all = "camelCase")]
1698#[non_exhaustive]
1699pub struct ListSessionsRequest {
1700 pub cwd: Option<PathBuf>,
1702 pub cursor: Option<String>,
1704 #[serde(rename = "_meta")]
1710 pub meta: Option<Meta>,
1711}
1712
1713impl ListSessionsRequest {
1714 #[must_use]
1715 pub fn new() -> Self {
1716 Self::default()
1717 }
1718
1719 #[must_use]
1721 pub fn cwd(mut self, cwd: impl IntoOption<PathBuf>) -> Self {
1722 self.cwd = cwd.into_option();
1723 self
1724 }
1725
1726 #[must_use]
1728 pub fn cursor(mut self, cursor: impl IntoOption<String>) -> Self {
1729 self.cursor = cursor.into_option();
1730 self
1731 }
1732
1733 #[must_use]
1739 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1740 self.meta = meta.into_option();
1741 self
1742 }
1743}
1744
1745#[serde_as]
1747#[skip_serializing_none]
1748#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1749#[schemars(extend("x-side" = "agent", "x-method" = SESSION_LIST_METHOD_NAME))]
1750#[serde(rename_all = "camelCase")]
1751#[non_exhaustive]
1752pub struct ListSessionsResponse {
1753 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1755 pub sessions: Vec<SessionInfo>,
1756 pub next_cursor: Option<String>,
1759 #[serde(rename = "_meta")]
1765 pub meta: Option<Meta>,
1766}
1767
1768impl ListSessionsResponse {
1769 #[must_use]
1770 pub fn new(sessions: Vec<SessionInfo>) -> Self {
1771 Self {
1772 sessions,
1773 next_cursor: None,
1774 meta: None,
1775 }
1776 }
1777
1778 #[must_use]
1779 pub fn next_cursor(mut self, next_cursor: impl IntoOption<String>) -> Self {
1780 self.next_cursor = next_cursor.into_option();
1781 self
1782 }
1783
1784 #[must_use]
1790 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1791 self.meta = meta.into_option();
1792 self
1793 }
1794}
1795
1796#[cfg(feature = "unstable_session_delete")]
1806#[skip_serializing_none]
1807#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1808#[schemars(extend("x-side" = "agent", "x-method" = SESSION_DELETE_METHOD_NAME))]
1809#[serde(rename_all = "camelCase")]
1810#[non_exhaustive]
1811pub struct DeleteSessionRequest {
1812 pub session_id: SessionId,
1814 #[serde(rename = "_meta")]
1820 pub meta: Option<Meta>,
1821}
1822
1823#[cfg(feature = "unstable_session_delete")]
1824impl DeleteSessionRequest {
1825 #[must_use]
1826 pub fn new(session_id: impl Into<SessionId>) -> Self {
1827 Self {
1828 session_id: session_id.into(),
1829 meta: None,
1830 }
1831 }
1832
1833 #[must_use]
1839 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1840 self.meta = meta.into_option();
1841 self
1842 }
1843}
1844
1845#[cfg(feature = "unstable_session_delete")]
1851#[skip_serializing_none]
1852#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1853#[schemars(extend("x-side" = "agent", "x-method" = SESSION_DELETE_METHOD_NAME))]
1854#[serde(rename_all = "camelCase")]
1855#[non_exhaustive]
1856pub struct DeleteSessionResponse {
1857 #[serde(rename = "_meta")]
1863 pub meta: Option<Meta>,
1864}
1865
1866#[cfg(feature = "unstable_session_delete")]
1867impl DeleteSessionResponse {
1868 #[must_use]
1869 pub fn new() -> Self {
1870 Self::default()
1871 }
1872
1873 #[must_use]
1879 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1880 self.meta = meta.into_option();
1881 self
1882 }
1883}
1884
1885#[serde_as]
1887#[skip_serializing_none]
1888#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1889#[serde(rename_all = "camelCase")]
1890#[non_exhaustive]
1891pub struct SessionInfo {
1892 pub session_id: SessionId,
1894 pub cwd: PathBuf,
1896 #[cfg(feature = "unstable_session_additional_directories")]
1906 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1907 pub additional_directories: Vec<PathBuf>,
1908
1909 #[serde_as(deserialize_as = "DefaultOnError")]
1911 #[serde(default)]
1912 pub title: Option<String>,
1913 #[serde_as(deserialize_as = "DefaultOnError")]
1915 #[serde(default)]
1916 pub updated_at: Option<String>,
1917 #[serde(rename = "_meta")]
1923 pub meta: Option<Meta>,
1924}
1925
1926impl SessionInfo {
1927 #[must_use]
1928 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1929 Self {
1930 session_id: session_id.into(),
1931 cwd: cwd.into(),
1932 #[cfg(feature = "unstable_session_additional_directories")]
1933 additional_directories: vec![],
1934 title: None,
1935 updated_at: None,
1936 meta: None,
1937 }
1938 }
1939
1940 #[cfg(feature = "unstable_session_additional_directories")]
1946 #[must_use]
1947 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1948 self.additional_directories = additional_directories;
1949 self
1950 }
1951
1952 #[must_use]
1954 pub fn title(mut self, title: impl IntoOption<String>) -> Self {
1955 self.title = title.into_option();
1956 self
1957 }
1958
1959 #[must_use]
1961 pub fn updated_at(mut self, updated_at: impl IntoOption<String>) -> Self {
1962 self.updated_at = updated_at.into_option();
1963 self
1964 }
1965
1966 #[must_use]
1972 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1973 self.meta = meta.into_option();
1974 self
1975 }
1976}
1977
1978#[serde_as]
1982#[skip_serializing_none]
1983#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1984#[serde(rename_all = "camelCase")]
1985#[non_exhaustive]
1986pub struct SessionModeState {
1987 pub current_mode_id: SessionModeId,
1989 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1991 pub available_modes: Vec<SessionMode>,
1992 #[serde(rename = "_meta")]
1998 pub meta: Option<Meta>,
1999}
2000
2001impl SessionModeState {
2002 #[must_use]
2003 pub fn new(
2004 current_mode_id: impl Into<SessionModeId>,
2005 available_modes: Vec<SessionMode>,
2006 ) -> Self {
2007 Self {
2008 current_mode_id: current_mode_id.into(),
2009 available_modes,
2010 meta: None,
2011 }
2012 }
2013
2014 #[must_use]
2020 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2021 self.meta = meta.into_option();
2022 self
2023 }
2024}
2025
2026#[skip_serializing_none]
2030#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2031#[serde(rename_all = "camelCase")]
2032#[non_exhaustive]
2033pub struct SessionMode {
2034 pub id: SessionModeId,
2035 pub name: String,
2036 #[serde(default)]
2037 pub description: Option<String>,
2038 #[serde(rename = "_meta")]
2044 pub meta: Option<Meta>,
2045}
2046
2047impl SessionMode {
2048 #[must_use]
2049 pub fn new(id: impl Into<SessionModeId>, name: impl Into<String>) -> Self {
2050 Self {
2051 id: id.into(),
2052 name: name.into(),
2053 description: None,
2054 meta: None,
2055 }
2056 }
2057
2058 #[must_use]
2059 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
2060 self.description = description.into_option();
2061 self
2062 }
2063
2064 #[must_use]
2070 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2071 self.meta = meta.into_option();
2072 self
2073 }
2074}
2075
2076#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, From, Display)]
2078#[serde(transparent)]
2079#[from(Arc<str>, String, &'static str)]
2080#[non_exhaustive]
2081pub struct SessionModeId(pub Arc<str>);
2082
2083impl SessionModeId {
2084 #[must_use]
2085 pub fn new(id: impl Into<Arc<str>>) -> Self {
2086 Self(id.into())
2087 }
2088}
2089
2090#[skip_serializing_none]
2092#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2093#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODE_METHOD_NAME))]
2094#[serde(rename_all = "camelCase")]
2095#[non_exhaustive]
2096pub struct SetSessionModeRequest {
2097 pub session_id: SessionId,
2099 pub mode_id: SessionModeId,
2101 #[serde(rename = "_meta")]
2107 pub meta: Option<Meta>,
2108}
2109
2110impl SetSessionModeRequest {
2111 #[must_use]
2112 pub fn new(session_id: impl Into<SessionId>, mode_id: impl Into<SessionModeId>) -> Self {
2113 Self {
2114 session_id: session_id.into(),
2115 mode_id: mode_id.into(),
2116 meta: None,
2117 }
2118 }
2119
2120 #[must_use]
2121 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2122 self.meta = meta.into_option();
2123 self
2124 }
2125}
2126
2127#[skip_serializing_none]
2129#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2130#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODE_METHOD_NAME))]
2131#[serde(rename_all = "camelCase")]
2132#[non_exhaustive]
2133pub struct SetSessionModeResponse {
2134 #[serde(rename = "_meta")]
2140 pub meta: Option<Meta>,
2141}
2142
2143impl SetSessionModeResponse {
2144 #[must_use]
2145 pub fn new() -> Self {
2146 Self::default()
2147 }
2148
2149 #[must_use]
2155 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2156 self.meta = meta.into_option();
2157 self
2158 }
2159}
2160
2161#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, From, Display)]
2165#[serde(transparent)]
2166#[from(Arc<str>, String, &'static str)]
2167#[non_exhaustive]
2168pub struct SessionConfigId(pub Arc<str>);
2169
2170impl SessionConfigId {
2171 #[must_use]
2172 pub fn new(id: impl Into<Arc<str>>) -> Self {
2173 Self(id.into())
2174 }
2175}
2176
2177#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, From, Display)]
2179#[serde(transparent)]
2180#[from(Arc<str>, String, &'static str)]
2181#[non_exhaustive]
2182pub struct SessionConfigValueId(pub Arc<str>);
2183
2184impl SessionConfigValueId {
2185 #[must_use]
2186 pub fn new(id: impl Into<Arc<str>>) -> Self {
2187 Self(id.into())
2188 }
2189}
2190
2191#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, From, Display)]
2193#[serde(transparent)]
2194#[from(Arc<str>, String, &'static str)]
2195#[non_exhaustive]
2196pub struct SessionConfigGroupId(pub Arc<str>);
2197
2198impl SessionConfigGroupId {
2199 #[must_use]
2200 pub fn new(id: impl Into<Arc<str>>) -> Self {
2201 Self(id.into())
2202 }
2203}
2204
2205#[skip_serializing_none]
2207#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2208#[serde(rename_all = "camelCase")]
2209#[non_exhaustive]
2210pub struct SessionConfigSelectOption {
2211 pub value: SessionConfigValueId,
2213 pub name: String,
2215 #[serde(default)]
2217 pub description: Option<String>,
2218 #[serde(rename = "_meta")]
2224 pub meta: Option<Meta>,
2225}
2226
2227impl SessionConfigSelectOption {
2228 #[must_use]
2229 pub fn new(value: impl Into<SessionConfigValueId>, name: impl Into<String>) -> Self {
2230 Self {
2231 value: value.into(),
2232 name: name.into(),
2233 description: None,
2234 meta: None,
2235 }
2236 }
2237
2238 #[must_use]
2239 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
2240 self.description = description.into_option();
2241 self
2242 }
2243
2244 #[must_use]
2250 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2251 self.meta = meta.into_option();
2252 self
2253 }
2254}
2255
2256#[skip_serializing_none]
2258#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2259#[serde(rename_all = "camelCase")]
2260#[non_exhaustive]
2261pub struct SessionConfigSelectGroup {
2262 pub group: SessionConfigGroupId,
2264 pub name: String,
2266 pub options: Vec<SessionConfigSelectOption>,
2268 #[serde(rename = "_meta")]
2274 pub meta: Option<Meta>,
2275}
2276
2277impl SessionConfigSelectGroup {
2278 #[must_use]
2279 pub fn new(
2280 group: impl Into<SessionConfigGroupId>,
2281 name: impl Into<String>,
2282 options: Vec<SessionConfigSelectOption>,
2283 ) -> Self {
2284 Self {
2285 group: group.into(),
2286 name: name.into(),
2287 options,
2288 meta: None,
2289 }
2290 }
2291
2292 #[must_use]
2298 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2299 self.meta = meta.into_option();
2300 self
2301 }
2302}
2303
2304#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2306#[serde(untagged)]
2307#[non_exhaustive]
2308pub enum SessionConfigSelectOptions {
2309 Ungrouped(Vec<SessionConfigSelectOption>),
2311 Grouped(Vec<SessionConfigSelectGroup>),
2313}
2314
2315impl From<Vec<SessionConfigSelectOption>> for SessionConfigSelectOptions {
2316 fn from(options: Vec<SessionConfigSelectOption>) -> Self {
2317 SessionConfigSelectOptions::Ungrouped(options)
2318 }
2319}
2320
2321impl From<Vec<SessionConfigSelectGroup>> for SessionConfigSelectOptions {
2322 fn from(groups: Vec<SessionConfigSelectGroup>) -> Self {
2323 SessionConfigSelectOptions::Grouped(groups)
2324 }
2325}
2326
2327#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2329#[serde(rename_all = "camelCase")]
2330#[non_exhaustive]
2331pub struct SessionConfigSelect {
2332 pub current_value: SessionConfigValueId,
2334 pub options: SessionConfigSelectOptions,
2336}
2337
2338impl SessionConfigSelect {
2339 #[must_use]
2340 pub fn new(
2341 current_value: impl Into<SessionConfigValueId>,
2342 options: impl Into<SessionConfigSelectOptions>,
2343 ) -> Self {
2344 Self {
2345 current_value: current_value.into(),
2346 options: options.into(),
2347 }
2348 }
2349}
2350
2351#[cfg(feature = "unstable_boolean_config")]
2357#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2358#[serde(rename_all = "camelCase")]
2359#[non_exhaustive]
2360pub struct SessionConfigBoolean {
2361 pub current_value: bool,
2363}
2364
2365#[cfg(feature = "unstable_boolean_config")]
2366impl SessionConfigBoolean {
2367 #[must_use]
2368 pub fn new(current_value: bool) -> Self {
2369 Self { current_value }
2370 }
2371}
2372
2373#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2383#[serde(rename_all = "snake_case")]
2384#[non_exhaustive]
2385pub enum SessionConfigOptionCategory {
2386 Mode,
2388 Model,
2390 ThoughtLevel,
2392 #[serde(untagged)]
2394 Other(String),
2395}
2396
2397#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2399#[serde(tag = "type", rename_all = "snake_case")]
2400#[schemars(extend("discriminator" = {"propertyName": "type"}))]
2401#[non_exhaustive]
2402pub enum SessionConfigKind {
2403 Select(SessionConfigSelect),
2405 #[cfg(feature = "unstable_boolean_config")]
2411 Boolean(SessionConfigBoolean),
2412}
2413
2414#[serde_as]
2416#[skip_serializing_none]
2417#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2418#[serde(rename_all = "camelCase")]
2419#[non_exhaustive]
2420pub struct SessionConfigOption {
2421 pub id: SessionConfigId,
2423 pub name: String,
2425 #[serde(default)]
2427 pub description: Option<String>,
2428 #[serde_as(deserialize_as = "DefaultOnError")]
2430 #[serde(default)]
2431 pub category: Option<SessionConfigOptionCategory>,
2432 #[serde(flatten)]
2434 pub kind: SessionConfigKind,
2435 #[serde(rename = "_meta")]
2441 pub meta: Option<Meta>,
2442}
2443
2444impl SessionConfigOption {
2445 #[must_use]
2446 pub fn new(
2447 id: impl Into<SessionConfigId>,
2448 name: impl Into<String>,
2449 kind: SessionConfigKind,
2450 ) -> Self {
2451 Self {
2452 id: id.into(),
2453 name: name.into(),
2454 description: None,
2455 category: None,
2456 kind,
2457 meta: None,
2458 }
2459 }
2460
2461 #[must_use]
2462 pub fn select(
2463 id: impl Into<SessionConfigId>,
2464 name: impl Into<String>,
2465 current_value: impl Into<SessionConfigValueId>,
2466 options: impl Into<SessionConfigSelectOptions>,
2467 ) -> Self {
2468 Self::new(
2469 id,
2470 name,
2471 SessionConfigKind::Select(SessionConfigSelect::new(current_value, options)),
2472 )
2473 }
2474
2475 #[cfg(feature = "unstable_boolean_config")]
2479 #[must_use]
2480 pub fn boolean(
2481 id: impl Into<SessionConfigId>,
2482 name: impl Into<String>,
2483 current_value: bool,
2484 ) -> Self {
2485 Self::new(
2486 id,
2487 name,
2488 SessionConfigKind::Boolean(SessionConfigBoolean::new(current_value)),
2489 )
2490 }
2491
2492 #[must_use]
2493 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
2494 self.description = description.into_option();
2495 self
2496 }
2497
2498 #[must_use]
2499 pub fn category(mut self, category: impl IntoOption<SessionConfigOptionCategory>) -> Self {
2500 self.category = category.into_option();
2501 self
2502 }
2503
2504 #[must_use]
2510 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2511 self.meta = meta.into_option();
2512 self
2513 }
2514}
2515
2516#[cfg(feature = "unstable_boolean_config")]
2531#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2532#[serde(tag = "type", rename_all = "snake_case")]
2533#[non_exhaustive]
2534pub enum SessionConfigOptionValue {
2535 Boolean {
2537 value: bool,
2539 },
2540 #[serde(untagged)]
2546 ValueId {
2547 value: SessionConfigValueId,
2549 },
2550}
2551
2552#[cfg(feature = "unstable_boolean_config")]
2553impl SessionConfigOptionValue {
2554 #[must_use]
2556 pub fn value_id(id: impl Into<SessionConfigValueId>) -> Self {
2557 Self::ValueId { value: id.into() }
2558 }
2559
2560 #[must_use]
2562 pub fn boolean(val: bool) -> Self {
2563 Self::Boolean { value: val }
2564 }
2565
2566 #[must_use]
2569 pub fn as_value_id(&self) -> Option<&SessionConfigValueId> {
2570 match self {
2571 Self::ValueId { value } => Some(value),
2572 _ => None,
2573 }
2574 }
2575
2576 #[must_use]
2578 pub fn as_bool(&self) -> Option<bool> {
2579 match self {
2580 Self::Boolean { value } => Some(*value),
2581 _ => None,
2582 }
2583 }
2584}
2585
2586#[cfg(feature = "unstable_boolean_config")]
2587impl From<SessionConfigValueId> for SessionConfigOptionValue {
2588 fn from(value: SessionConfigValueId) -> Self {
2589 Self::ValueId { value }
2590 }
2591}
2592
2593#[cfg(feature = "unstable_boolean_config")]
2594impl From<bool> for SessionConfigOptionValue {
2595 fn from(value: bool) -> Self {
2596 Self::Boolean { value }
2597 }
2598}
2599
2600#[cfg(feature = "unstable_boolean_config")]
2601impl From<&str> for SessionConfigOptionValue {
2602 fn from(value: &str) -> Self {
2603 Self::ValueId {
2604 value: SessionConfigValueId::new(value),
2605 }
2606 }
2607}
2608
2609#[skip_serializing_none]
2611#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2612#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_CONFIG_OPTION_METHOD_NAME))]
2613#[serde(rename_all = "camelCase")]
2614#[non_exhaustive]
2615pub struct SetSessionConfigOptionRequest {
2616 pub session_id: SessionId,
2618 pub config_id: SessionConfigId,
2620 #[cfg(feature = "unstable_boolean_config")]
2625 #[serde(flatten)]
2626 pub value: SessionConfigOptionValue,
2627 #[cfg(not(feature = "unstable_boolean_config"))]
2629 pub value: SessionConfigValueId,
2630 #[serde(rename = "_meta")]
2636 pub meta: Option<Meta>,
2637}
2638
2639impl SetSessionConfigOptionRequest {
2640 #[cfg(feature = "unstable_boolean_config")]
2641 #[must_use]
2642 pub fn new(
2643 session_id: impl Into<SessionId>,
2644 config_id: impl Into<SessionConfigId>,
2645 value: impl Into<SessionConfigOptionValue>,
2646 ) -> Self {
2647 Self {
2648 session_id: session_id.into(),
2649 config_id: config_id.into(),
2650 value: value.into(),
2651 meta: None,
2652 }
2653 }
2654
2655 #[cfg(not(feature = "unstable_boolean_config"))]
2656 #[must_use]
2657 pub fn new(
2658 session_id: impl Into<SessionId>,
2659 config_id: impl Into<SessionConfigId>,
2660 value: impl Into<SessionConfigValueId>,
2661 ) -> Self {
2662 Self {
2663 session_id: session_id.into(),
2664 config_id: config_id.into(),
2665 value: value.into(),
2666 meta: None,
2667 }
2668 }
2669
2670 #[must_use]
2676 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2677 self.meta = meta.into_option();
2678 self
2679 }
2680}
2681
2682#[serde_as]
2684#[skip_serializing_none]
2685#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2686#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_CONFIG_OPTION_METHOD_NAME))]
2687#[serde(rename_all = "camelCase")]
2688#[non_exhaustive]
2689pub struct SetSessionConfigOptionResponse {
2690 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
2692 pub config_options: Vec<SessionConfigOption>,
2693 #[serde(rename = "_meta")]
2699 pub meta: Option<Meta>,
2700}
2701
2702impl SetSessionConfigOptionResponse {
2703 #[must_use]
2704 pub fn new(config_options: Vec<SessionConfigOption>) -> Self {
2705 Self {
2706 config_options,
2707 meta: None,
2708 }
2709 }
2710
2711 #[must_use]
2717 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2718 self.meta = meta.into_option();
2719 self
2720 }
2721}
2722
2723#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2732#[serde(tag = "type", rename_all = "snake_case")]
2733#[non_exhaustive]
2734pub enum McpServer {
2735 Http(McpServerHttp),
2739 Sse(McpServerSse),
2743 #[cfg(feature = "unstable_mcp_over_acp")]
2752 Acp(McpServerAcp),
2753 #[serde(untagged)]
2757 Stdio(McpServerStdio),
2758}
2759
2760#[skip_serializing_none]
2762#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2763#[serde(rename_all = "camelCase")]
2764#[non_exhaustive]
2765pub struct McpServerHttp {
2766 pub name: String,
2768 pub url: String,
2770 pub headers: Vec<HttpHeader>,
2772 #[serde(rename = "_meta")]
2778 pub meta: Option<Meta>,
2779}
2780
2781impl McpServerHttp {
2782 #[must_use]
2783 pub fn new(name: impl Into<String>, url: impl Into<String>) -> Self {
2784 Self {
2785 name: name.into(),
2786 url: url.into(),
2787 headers: Vec::new(),
2788 meta: None,
2789 }
2790 }
2791
2792 #[must_use]
2794 pub fn headers(mut self, headers: Vec<HttpHeader>) -> Self {
2795 self.headers = headers;
2796 self
2797 }
2798
2799 #[must_use]
2805 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2806 self.meta = meta.into_option();
2807 self
2808 }
2809}
2810
2811#[skip_serializing_none]
2813#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2814#[serde(rename_all = "camelCase")]
2815#[non_exhaustive]
2816pub struct McpServerSse {
2817 pub name: String,
2819 pub url: String,
2821 pub headers: Vec<HttpHeader>,
2823 #[serde(rename = "_meta")]
2829 pub meta: Option<Meta>,
2830}
2831
2832impl McpServerSse {
2833 #[must_use]
2834 pub fn new(name: impl Into<String>, url: impl Into<String>) -> Self {
2835 Self {
2836 name: name.into(),
2837 url: url.into(),
2838 headers: Vec::new(),
2839 meta: None,
2840 }
2841 }
2842
2843 #[must_use]
2845 pub fn headers(mut self, headers: Vec<HttpHeader>) -> Self {
2846 self.headers = headers;
2847 self
2848 }
2849
2850 #[must_use]
2856 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2857 self.meta = meta.into_option();
2858 self
2859 }
2860}
2861
2862#[cfg(feature = "unstable_mcp_over_acp")]
2872#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
2873#[serde(transparent)]
2874#[from(Arc<str>, String, &'static str)]
2875#[non_exhaustive]
2876pub struct McpServerAcpId(pub Arc<str>);
2877
2878#[cfg(feature = "unstable_mcp_over_acp")]
2879impl McpServerAcpId {
2880 #[must_use]
2881 pub fn new(id: impl Into<Arc<str>>) -> Self {
2882 Self(id.into())
2883 }
2884}
2885
2886#[skip_serializing_none]
2895#[cfg(feature = "unstable_mcp_over_acp")]
2896#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2897#[serde(rename_all = "camelCase")]
2898#[non_exhaustive]
2899pub struct McpServerAcp {
2900 pub name: String,
2902 pub id: McpServerAcpId,
2907 #[serde(rename = "_meta")]
2913 pub meta: Option<Meta>,
2914}
2915
2916#[cfg(feature = "unstable_mcp_over_acp")]
2917impl McpServerAcp {
2918 #[must_use]
2919 pub fn new(name: impl Into<String>, id: impl Into<McpServerAcpId>) -> Self {
2920 Self {
2921 name: name.into(),
2922 id: id.into(),
2923 meta: None,
2924 }
2925 }
2926
2927 #[must_use]
2933 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2934 self.meta = meta.into_option();
2935 self
2936 }
2937}
2938
2939#[skip_serializing_none]
2941#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2942#[serde(rename_all = "camelCase")]
2943#[non_exhaustive]
2944pub struct McpServerStdio {
2945 pub name: String,
2947 pub command: PathBuf,
2949 pub args: Vec<String>,
2951 pub env: Vec<EnvVariable>,
2953 #[serde(rename = "_meta")]
2959 pub meta: Option<Meta>,
2960}
2961
2962impl McpServerStdio {
2963 #[must_use]
2964 pub fn new(name: impl Into<String>, command: impl Into<PathBuf>) -> Self {
2965 Self {
2966 name: name.into(),
2967 command: command.into(),
2968 args: Vec::new(),
2969 env: Vec::new(),
2970 meta: None,
2971 }
2972 }
2973
2974 #[must_use]
2976 pub fn args(mut self, args: Vec<String>) -> Self {
2977 self.args = args;
2978 self
2979 }
2980
2981 #[must_use]
2983 pub fn env(mut self, env: Vec<EnvVariable>) -> Self {
2984 self.env = env;
2985 self
2986 }
2987
2988 #[must_use]
2994 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2995 self.meta = meta.into_option();
2996 self
2997 }
2998}
2999
3000#[skip_serializing_none]
3002#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3003#[serde(rename_all = "camelCase")]
3004#[non_exhaustive]
3005pub struct EnvVariable {
3006 pub name: String,
3008 pub value: String,
3010 #[serde(rename = "_meta")]
3016 pub meta: Option<Meta>,
3017}
3018
3019impl EnvVariable {
3020 #[must_use]
3021 pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
3022 Self {
3023 name: name.into(),
3024 value: value.into(),
3025 meta: None,
3026 }
3027 }
3028
3029 #[must_use]
3035 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3036 self.meta = meta.into_option();
3037 self
3038 }
3039}
3040
3041#[skip_serializing_none]
3043#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3044#[serde(rename_all = "camelCase")]
3045#[non_exhaustive]
3046pub struct HttpHeader {
3047 pub name: String,
3049 pub value: String,
3051 #[serde(rename = "_meta")]
3057 pub meta: Option<Meta>,
3058}
3059
3060impl HttpHeader {
3061 #[must_use]
3062 pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
3063 Self {
3064 name: name.into(),
3065 value: value.into(),
3066 meta: None,
3067 }
3068 }
3069
3070 #[must_use]
3076 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3077 self.meta = meta.into_option();
3078 self
3079 }
3080}
3081
3082#[skip_serializing_none]
3090#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
3091#[schemars(extend("x-side" = "agent", "x-method" = SESSION_PROMPT_METHOD_NAME))]
3092#[serde(rename_all = "camelCase")]
3093#[non_exhaustive]
3094pub struct PromptRequest {
3095 pub session_id: SessionId,
3097 #[cfg(feature = "unstable_message_id")]
3107 pub message_id: Option<String>,
3108 pub prompt: Vec<ContentBlock>,
3122 #[serde(rename = "_meta")]
3128 pub meta: Option<Meta>,
3129}
3130
3131impl PromptRequest {
3132 #[must_use]
3133 pub fn new(session_id: impl Into<SessionId>, prompt: Vec<ContentBlock>) -> Self {
3134 Self {
3135 session_id: session_id.into(),
3136 #[cfg(feature = "unstable_message_id")]
3137 message_id: None,
3138 prompt,
3139 meta: None,
3140 }
3141 }
3142
3143 #[cfg(feature = "unstable_message_id")]
3153 #[must_use]
3154 pub fn message_id(mut self, message_id: impl IntoOption<String>) -> Self {
3155 self.message_id = message_id.into_option();
3156 self
3157 }
3158
3159 #[must_use]
3165 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3166 self.meta = meta.into_option();
3167 self
3168 }
3169}
3170
3171#[serde_as]
3175#[skip_serializing_none]
3176#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3177#[schemars(extend("x-side" = "agent", "x-method" = SESSION_PROMPT_METHOD_NAME))]
3178#[serde(rename_all = "camelCase")]
3179#[non_exhaustive]
3180pub struct PromptResponse {
3181 #[cfg(feature = "unstable_message_id")]
3191 pub user_message_id: Option<String>,
3192 pub stop_reason: StopReason,
3194 #[cfg(feature = "unstable_session_usage")]
3200 #[serde_as(deserialize_as = "DefaultOnError")]
3201 #[serde(default)]
3202 pub usage: Option<Usage>,
3203 #[serde(rename = "_meta")]
3209 pub meta: Option<Meta>,
3210}
3211
3212impl PromptResponse {
3213 #[must_use]
3214 pub fn new(stop_reason: StopReason) -> Self {
3215 Self {
3216 #[cfg(feature = "unstable_message_id")]
3217 user_message_id: None,
3218 stop_reason,
3219 #[cfg(feature = "unstable_session_usage")]
3220 usage: None,
3221 meta: None,
3222 }
3223 }
3224
3225 #[cfg(feature = "unstable_message_id")]
3235 #[must_use]
3236 pub fn user_message_id(mut self, user_message_id: impl IntoOption<String>) -> Self {
3237 self.user_message_id = user_message_id.into_option();
3238 self
3239 }
3240
3241 #[cfg(feature = "unstable_session_usage")]
3247 #[must_use]
3248 pub fn usage(mut self, usage: impl IntoOption<Usage>) -> Self {
3249 self.usage = usage.into_option();
3250 self
3251 }
3252
3253 #[must_use]
3259 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3260 self.meta = meta.into_option();
3261 self
3262 }
3263}
3264
3265#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
3269#[serde(rename_all = "snake_case")]
3270#[non_exhaustive]
3271pub enum StopReason {
3272 EndTurn,
3274 MaxTokens,
3276 MaxTurnRequests,
3279 Refusal,
3283 Cancelled,
3290}
3291
3292#[cfg(feature = "unstable_session_usage")]
3298#[skip_serializing_none]
3299#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3300#[serde(rename_all = "camelCase")]
3301#[non_exhaustive]
3302pub struct Usage {
3303 pub total_tokens: u64,
3305 pub input_tokens: u64,
3307 pub output_tokens: u64,
3309 pub thought_tokens: Option<u64>,
3311 pub cached_read_tokens: Option<u64>,
3313 pub cached_write_tokens: Option<u64>,
3315}
3316
3317#[cfg(feature = "unstable_session_usage")]
3318impl Usage {
3319 #[must_use]
3320 pub fn new(total_tokens: u64, input_tokens: u64, output_tokens: u64) -> Self {
3321 Self {
3322 total_tokens,
3323 input_tokens,
3324 output_tokens,
3325 thought_tokens: None,
3326 cached_read_tokens: None,
3327 cached_write_tokens: None,
3328 }
3329 }
3330
3331 #[must_use]
3333 pub fn thought_tokens(mut self, thought_tokens: impl IntoOption<u64>) -> Self {
3334 self.thought_tokens = thought_tokens.into_option();
3335 self
3336 }
3337
3338 #[must_use]
3340 pub fn cached_read_tokens(mut self, cached_read_tokens: impl IntoOption<u64>) -> Self {
3341 self.cached_read_tokens = cached_read_tokens.into_option();
3342 self
3343 }
3344
3345 #[must_use]
3347 pub fn cached_write_tokens(mut self, cached_write_tokens: impl IntoOption<u64>) -> Self {
3348 self.cached_write_tokens = cached_write_tokens.into_option();
3349 self
3350 }
3351}
3352
3353#[cfg(feature = "unstable_session_model")]
3361#[serde_as]
3362#[skip_serializing_none]
3363#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3364#[serde(rename_all = "camelCase")]
3365#[non_exhaustive]
3366pub struct SessionModelState {
3367 pub current_model_id: ModelId,
3369 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
3371 pub available_models: Vec<ModelInfo>,
3372 #[serde(rename = "_meta")]
3378 pub meta: Option<Meta>,
3379}
3380
3381#[cfg(feature = "unstable_session_model")]
3382impl SessionModelState {
3383 #[must_use]
3384 pub fn new(current_model_id: impl Into<ModelId>, available_models: Vec<ModelInfo>) -> Self {
3385 Self {
3386 current_model_id: current_model_id.into(),
3387 available_models,
3388 meta: None,
3389 }
3390 }
3391
3392 #[must_use]
3398 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3399 self.meta = meta.into_option();
3400 self
3401 }
3402}
3403
3404#[cfg(feature = "unstable_session_model")]
3410#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
3411#[serde(transparent)]
3412#[from(Arc<str>, String, &'static str)]
3413#[non_exhaustive]
3414pub struct ModelId(pub Arc<str>);
3415
3416#[cfg(feature = "unstable_session_model")]
3417impl ModelId {
3418 #[must_use]
3419 pub fn new(id: impl Into<Arc<str>>) -> Self {
3420 Self(id.into())
3421 }
3422}
3423
3424#[cfg(feature = "unstable_session_model")]
3430#[skip_serializing_none]
3431#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3432#[serde(rename_all = "camelCase")]
3433#[non_exhaustive]
3434pub struct ModelInfo {
3435 pub model_id: ModelId,
3437 pub name: String,
3439 #[serde(default)]
3441 pub description: Option<String>,
3442 #[serde(rename = "_meta")]
3448 pub meta: Option<Meta>,
3449}
3450
3451#[cfg(feature = "unstable_session_model")]
3452impl ModelInfo {
3453 #[must_use]
3454 pub fn new(model_id: impl Into<ModelId>, name: impl Into<String>) -> Self {
3455 Self {
3456 model_id: model_id.into(),
3457 name: name.into(),
3458 description: None,
3459 meta: None,
3460 }
3461 }
3462
3463 #[must_use]
3465 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
3466 self.description = description.into_option();
3467 self
3468 }
3469
3470 #[must_use]
3476 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3477 self.meta = meta.into_option();
3478 self
3479 }
3480}
3481
3482#[cfg(feature = "unstable_session_model")]
3488#[skip_serializing_none]
3489#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3490#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODEL_METHOD_NAME))]
3491#[serde(rename_all = "camelCase")]
3492#[non_exhaustive]
3493pub struct SetSessionModelRequest {
3494 pub session_id: SessionId,
3496 pub model_id: ModelId,
3498 #[serde(rename = "_meta")]
3504 pub meta: Option<Meta>,
3505}
3506
3507#[cfg(feature = "unstable_session_model")]
3508impl SetSessionModelRequest {
3509 #[must_use]
3510 pub fn new(session_id: impl Into<SessionId>, model_id: impl Into<ModelId>) -> Self {
3511 Self {
3512 session_id: session_id.into(),
3513 model_id: model_id.into(),
3514 meta: None,
3515 }
3516 }
3517
3518 #[must_use]
3524 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3525 self.meta = meta.into_option();
3526 self
3527 }
3528}
3529
3530#[cfg(feature = "unstable_session_model")]
3536#[skip_serializing_none]
3537#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3538#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODEL_METHOD_NAME))]
3539#[serde(rename_all = "camelCase")]
3540#[non_exhaustive]
3541pub struct SetSessionModelResponse {
3542 #[serde(rename = "_meta")]
3548 pub meta: Option<Meta>,
3549}
3550
3551#[cfg(feature = "unstable_session_model")]
3552impl SetSessionModelResponse {
3553 #[must_use]
3554 pub fn new() -> Self {
3555 Self::default()
3556 }
3557
3558 #[must_use]
3564 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3565 self.meta = meta.into_option();
3566 self
3567 }
3568}
3569
3570#[cfg(feature = "unstable_llm_providers")]
3583#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3584#[serde(rename_all = "snake_case")]
3585#[non_exhaustive]
3586#[expect(clippy::doc_markdown)]
3587pub enum LlmProtocol {
3588 Anthropic,
3590 #[serde(rename = "openai")]
3592 OpenAi,
3593 Azure,
3595 Vertex,
3597 Bedrock,
3599 #[serde(untagged)]
3601 Other(String),
3602}
3603
3604#[cfg(feature = "unstable_llm_providers")]
3610#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3611#[serde(rename_all = "camelCase")]
3612#[non_exhaustive]
3613pub struct ProviderCurrentConfig {
3614 pub api_type: LlmProtocol,
3616 pub base_url: String,
3618}
3619
3620#[cfg(feature = "unstable_llm_providers")]
3621impl ProviderCurrentConfig {
3622 #[must_use]
3623 pub fn new(api_type: LlmProtocol, base_url: impl Into<String>) -> Self {
3624 Self {
3625 api_type,
3626 base_url: base_url.into(),
3627 }
3628 }
3629}
3630
3631#[cfg(feature = "unstable_llm_providers")]
3637#[serde_as]
3638#[skip_serializing_none]
3639#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3640#[serde(rename_all = "camelCase")]
3641#[non_exhaustive]
3642pub struct ProviderInfo {
3643 pub id: String,
3645 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
3647 pub supported: Vec<LlmProtocol>,
3648 pub required: bool,
3651 pub current: Option<ProviderCurrentConfig>,
3654 #[serde(rename = "_meta")]
3660 pub meta: Option<Meta>,
3661}
3662
3663#[cfg(feature = "unstable_llm_providers")]
3664impl ProviderInfo {
3665 #[must_use]
3666 pub fn new(
3667 id: impl Into<String>,
3668 supported: Vec<LlmProtocol>,
3669 required: bool,
3670 current: impl IntoOption<ProviderCurrentConfig>,
3671 ) -> Self {
3672 Self {
3673 id: id.into(),
3674 supported,
3675 required,
3676 current: current.into_option(),
3677 meta: None,
3678 }
3679 }
3680
3681 #[must_use]
3687 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3688 self.meta = meta.into_option();
3689 self
3690 }
3691}
3692
3693#[cfg(feature = "unstable_llm_providers")]
3699#[skip_serializing_none]
3700#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3701#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_LIST_METHOD_NAME))]
3702#[serde(rename_all = "camelCase")]
3703#[non_exhaustive]
3704pub struct ListProvidersRequest {
3705 #[serde(rename = "_meta")]
3711 pub meta: Option<Meta>,
3712}
3713
3714#[cfg(feature = "unstable_llm_providers")]
3715impl ListProvidersRequest {
3716 #[must_use]
3717 pub fn new() -> Self {
3718 Self::default()
3719 }
3720
3721 #[must_use]
3727 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3728 self.meta = meta.into_option();
3729 self
3730 }
3731}
3732
3733#[cfg(feature = "unstable_llm_providers")]
3739#[serde_as]
3740#[skip_serializing_none]
3741#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3742#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_LIST_METHOD_NAME))]
3743#[serde(rename_all = "camelCase")]
3744#[non_exhaustive]
3745pub struct ListProvidersResponse {
3746 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
3748 pub providers: Vec<ProviderInfo>,
3749 #[serde(rename = "_meta")]
3755 pub meta: Option<Meta>,
3756}
3757
3758#[cfg(feature = "unstable_llm_providers")]
3759impl ListProvidersResponse {
3760 #[must_use]
3761 pub fn new(providers: Vec<ProviderInfo>) -> Self {
3762 Self {
3763 providers,
3764 meta: None,
3765 }
3766 }
3767
3768 #[must_use]
3774 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3775 self.meta = meta.into_option();
3776 self
3777 }
3778}
3779
3780#[cfg(feature = "unstable_llm_providers")]
3788#[skip_serializing_none]
3789#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3790#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_SET_METHOD_NAME))]
3791#[serde(rename_all = "camelCase")]
3792#[non_exhaustive]
3793pub struct SetProviderRequest {
3794 pub id: String,
3796 pub api_type: LlmProtocol,
3798 pub base_url: String,
3800 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
3803 pub headers: HashMap<String, String>,
3804 #[serde(rename = "_meta")]
3810 pub meta: Option<Meta>,
3811}
3812
3813#[cfg(feature = "unstable_llm_providers")]
3814impl SetProviderRequest {
3815 #[must_use]
3816 pub fn new(id: impl Into<String>, api_type: LlmProtocol, base_url: impl Into<String>) -> Self {
3817 Self {
3818 id: id.into(),
3819 api_type,
3820 base_url: base_url.into(),
3821 headers: HashMap::new(),
3822 meta: None,
3823 }
3824 }
3825
3826 #[must_use]
3829 pub fn headers(mut self, headers: HashMap<String, String>) -> Self {
3830 self.headers = headers;
3831 self
3832 }
3833
3834 #[must_use]
3840 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3841 self.meta = meta.into_option();
3842 self
3843 }
3844}
3845
3846#[cfg(feature = "unstable_llm_providers")]
3852#[skip_serializing_none]
3853#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3854#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_SET_METHOD_NAME))]
3855#[serde(rename_all = "camelCase")]
3856#[non_exhaustive]
3857pub struct SetProviderResponse {
3858 #[serde(rename = "_meta")]
3864 pub meta: Option<Meta>,
3865}
3866
3867#[cfg(feature = "unstable_llm_providers")]
3868impl SetProviderResponse {
3869 #[must_use]
3870 pub fn new() -> Self {
3871 Self::default()
3872 }
3873
3874 #[must_use]
3880 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3881 self.meta = meta.into_option();
3882 self
3883 }
3884}
3885
3886#[cfg(feature = "unstable_llm_providers")]
3892#[skip_serializing_none]
3893#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3894#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_DISABLE_METHOD_NAME))]
3895#[serde(rename_all = "camelCase")]
3896#[non_exhaustive]
3897pub struct DisableProviderRequest {
3898 pub id: String,
3900 #[serde(rename = "_meta")]
3906 pub meta: Option<Meta>,
3907}
3908
3909#[cfg(feature = "unstable_llm_providers")]
3910impl DisableProviderRequest {
3911 #[must_use]
3912 pub fn new(id: impl Into<String>) -> Self {
3913 Self {
3914 id: id.into(),
3915 meta: None,
3916 }
3917 }
3918
3919 #[must_use]
3925 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3926 self.meta = meta.into_option();
3927 self
3928 }
3929}
3930
3931#[cfg(feature = "unstable_llm_providers")]
3937#[skip_serializing_none]
3938#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3939#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_DISABLE_METHOD_NAME))]
3940#[serde(rename_all = "camelCase")]
3941#[non_exhaustive]
3942pub struct DisableProviderResponse {
3943 #[serde(rename = "_meta")]
3949 pub meta: Option<Meta>,
3950}
3951
3952#[cfg(feature = "unstable_llm_providers")]
3953impl DisableProviderResponse {
3954 #[must_use]
3955 pub fn new() -> Self {
3956 Self::default()
3957 }
3958
3959 #[must_use]
3965 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3966 self.meta = meta.into_option();
3967 self
3968 }
3969}
3970
3971#[serde_as]
3980#[skip_serializing_none]
3981#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3982#[serde(rename_all = "camelCase")]
3983#[non_exhaustive]
3984pub struct AgentCapabilities {
3985 #[serde(default)]
3987 pub load_session: bool,
3988 #[serde(default)]
3990 pub prompt_capabilities: PromptCapabilities,
3991 #[serde(default)]
3993 pub mcp_capabilities: McpCapabilities,
3994 #[serde(default)]
3995 pub session_capabilities: SessionCapabilities,
3996 #[serde(default)]
3998 pub auth: AgentAuthCapabilities,
3999 #[cfg(feature = "unstable_llm_providers")]
4007 #[serde_as(deserialize_as = "DefaultOnError")]
4008 #[serde(default)]
4009 pub providers: Option<ProvidersCapabilities>,
4010 #[cfg(feature = "unstable_nes")]
4016 #[serde_as(deserialize_as = "DefaultOnError")]
4017 #[serde(default)]
4018 pub nes: Option<NesCapabilities>,
4019 #[cfg(feature = "unstable_nes")]
4025 #[serde_as(deserialize_as = "DefaultOnError")]
4026 #[serde(default)]
4027 pub position_encoding: Option<PositionEncodingKind>,
4028 #[serde(rename = "_meta")]
4034 pub meta: Option<Meta>,
4035}
4036
4037impl AgentCapabilities {
4038 #[must_use]
4039 pub fn new() -> Self {
4040 Self::default()
4041 }
4042
4043 #[must_use]
4045 pub fn load_session(mut self, load_session: bool) -> Self {
4046 self.load_session = load_session;
4047 self
4048 }
4049
4050 #[must_use]
4052 pub fn prompt_capabilities(mut self, prompt_capabilities: PromptCapabilities) -> Self {
4053 self.prompt_capabilities = prompt_capabilities;
4054 self
4055 }
4056
4057 #[must_use]
4059 pub fn mcp_capabilities(mut self, mcp_capabilities: McpCapabilities) -> Self {
4060 self.mcp_capabilities = mcp_capabilities;
4061 self
4062 }
4063
4064 #[must_use]
4066 pub fn session_capabilities(mut self, session_capabilities: SessionCapabilities) -> Self {
4067 self.session_capabilities = session_capabilities;
4068 self
4069 }
4070
4071 #[must_use]
4073 pub fn auth(mut self, auth: AgentAuthCapabilities) -> Self {
4074 self.auth = auth;
4075 self
4076 }
4077
4078 #[cfg(feature = "unstable_llm_providers")]
4084 #[must_use]
4085 pub fn providers(mut self, providers: impl IntoOption<ProvidersCapabilities>) -> Self {
4086 self.providers = providers.into_option();
4087 self
4088 }
4089
4090 #[cfg(feature = "unstable_nes")]
4096 #[must_use]
4097 pub fn nes(mut self, nes: impl IntoOption<NesCapabilities>) -> Self {
4098 self.nes = nes.into_option();
4099 self
4100 }
4101
4102 #[cfg(feature = "unstable_nes")]
4106 #[must_use]
4107 pub fn position_encoding(
4108 mut self,
4109 position_encoding: impl IntoOption<PositionEncodingKind>,
4110 ) -> Self {
4111 self.position_encoding = position_encoding.into_option();
4112 self
4113 }
4114
4115 #[must_use]
4121 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4122 self.meta = meta.into_option();
4123 self
4124 }
4125}
4126
4127#[cfg(feature = "unstable_llm_providers")]
4135#[skip_serializing_none]
4136#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4137#[non_exhaustive]
4138pub struct ProvidersCapabilities {
4139 #[serde(rename = "_meta")]
4145 pub meta: Option<Meta>,
4146}
4147
4148#[cfg(feature = "unstable_llm_providers")]
4149impl ProvidersCapabilities {
4150 #[must_use]
4151 pub fn new() -> Self {
4152 Self::default()
4153 }
4154
4155 #[must_use]
4161 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4162 self.meta = meta.into_option();
4163 self
4164 }
4165}
4166
4167#[serde_as]
4177#[skip_serializing_none]
4178#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4179#[serde(rename_all = "camelCase")]
4180#[non_exhaustive]
4181pub struct SessionCapabilities {
4182 #[serde_as(deserialize_as = "DefaultOnError")]
4184 #[serde(default)]
4185 pub list: Option<SessionListCapabilities>,
4186 #[cfg(feature = "unstable_session_delete")]
4195 #[serde_as(deserialize_as = "DefaultOnError")]
4196 #[serde(default)]
4197 pub delete: Option<SessionDeleteCapabilities>,
4198 #[cfg(feature = "unstable_session_additional_directories")]
4208 #[serde_as(deserialize_as = "DefaultOnError")]
4209 #[serde(default)]
4210 pub additional_directories: Option<SessionAdditionalDirectoriesCapabilities>,
4211 #[cfg(feature = "unstable_session_fork")]
4217 #[serde_as(deserialize_as = "DefaultOnError")]
4218 #[serde(default)]
4219 pub fork: Option<SessionForkCapabilities>,
4220 #[serde_as(deserialize_as = "DefaultOnError")]
4222 #[serde(default)]
4223 pub resume: Option<SessionResumeCapabilities>,
4224 #[serde_as(deserialize_as = "DefaultOnError")]
4226 #[serde(default)]
4227 pub close: Option<SessionCloseCapabilities>,
4228 #[serde(rename = "_meta")]
4234 pub meta: Option<Meta>,
4235}
4236
4237impl SessionCapabilities {
4238 #[must_use]
4239 pub fn new() -> Self {
4240 Self::default()
4241 }
4242
4243 #[must_use]
4245 pub fn list(mut self, list: impl IntoOption<SessionListCapabilities>) -> Self {
4246 self.list = list.into_option();
4247 self
4248 }
4249
4250 #[cfg(feature = "unstable_session_delete")]
4259 #[must_use]
4260 pub fn delete(mut self, delete: impl IntoOption<SessionDeleteCapabilities>) -> Self {
4261 self.delete = delete.into_option();
4262 self
4263 }
4264
4265 #[cfg(feature = "unstable_session_additional_directories")]
4275 #[must_use]
4276 pub fn additional_directories(
4277 mut self,
4278 additional_directories: impl IntoOption<SessionAdditionalDirectoriesCapabilities>,
4279 ) -> Self {
4280 self.additional_directories = additional_directories.into_option();
4281 self
4282 }
4283
4284 #[cfg(feature = "unstable_session_fork")]
4285 #[must_use]
4287 pub fn fork(mut self, fork: impl IntoOption<SessionForkCapabilities>) -> Self {
4288 self.fork = fork.into_option();
4289 self
4290 }
4291
4292 #[must_use]
4294 pub fn resume(mut self, resume: impl IntoOption<SessionResumeCapabilities>) -> Self {
4295 self.resume = resume.into_option();
4296 self
4297 }
4298
4299 #[must_use]
4301 pub fn close(mut self, close: impl IntoOption<SessionCloseCapabilities>) -> Self {
4302 self.close = close.into_option();
4303 self
4304 }
4305
4306 #[must_use]
4312 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4313 self.meta = meta.into_option();
4314 self
4315 }
4316}
4317
4318#[skip_serializing_none]
4322#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4323#[non_exhaustive]
4324pub struct SessionListCapabilities {
4325 #[serde(rename = "_meta")]
4331 pub meta: Option<Meta>,
4332}
4333
4334impl SessionListCapabilities {
4335 #[must_use]
4336 pub fn new() -> Self {
4337 Self::default()
4338 }
4339
4340 #[must_use]
4346 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4347 self.meta = meta.into_option();
4348 self
4349 }
4350}
4351
4352#[cfg(feature = "unstable_session_delete")]
4360#[skip_serializing_none]
4361#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4362#[non_exhaustive]
4363pub struct SessionDeleteCapabilities {
4364 #[serde(rename = "_meta")]
4370 pub meta: Option<Meta>,
4371}
4372
4373#[cfg(feature = "unstable_session_delete")]
4374impl SessionDeleteCapabilities {
4375 #[must_use]
4376 pub fn new() -> Self {
4377 Self::default()
4378 }
4379
4380 #[must_use]
4386 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4387 self.meta = meta.into_option();
4388 self
4389 }
4390}
4391
4392#[cfg(feature = "unstable_session_additional_directories")]
4403#[skip_serializing_none]
4404#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4405#[non_exhaustive]
4406pub struct SessionAdditionalDirectoriesCapabilities {
4407 #[serde(rename = "_meta")]
4413 pub meta: Option<Meta>,
4414}
4415
4416#[cfg(feature = "unstable_session_additional_directories")]
4417impl SessionAdditionalDirectoriesCapabilities {
4418 #[must_use]
4419 pub fn new() -> Self {
4420 Self::default()
4421 }
4422
4423 #[must_use]
4429 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4430 self.meta = meta.into_option();
4431 self
4432 }
4433}
4434
4435#[cfg(feature = "unstable_session_fork")]
4443#[skip_serializing_none]
4444#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4445#[non_exhaustive]
4446pub struct SessionForkCapabilities {
4447 #[serde(rename = "_meta")]
4453 pub meta: Option<Meta>,
4454}
4455
4456#[cfg(feature = "unstable_session_fork")]
4457impl SessionForkCapabilities {
4458 #[must_use]
4459 pub fn new() -> Self {
4460 Self::default()
4461 }
4462
4463 #[must_use]
4469 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4470 self.meta = meta.into_option();
4471 self
4472 }
4473}
4474
4475#[skip_serializing_none]
4479#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4480#[non_exhaustive]
4481pub struct SessionResumeCapabilities {
4482 #[serde(rename = "_meta")]
4488 pub meta: Option<Meta>,
4489}
4490
4491impl SessionResumeCapabilities {
4492 #[must_use]
4493 pub fn new() -> Self {
4494 Self::default()
4495 }
4496
4497 #[must_use]
4503 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4504 self.meta = meta.into_option();
4505 self
4506 }
4507}
4508
4509#[skip_serializing_none]
4513#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4514#[non_exhaustive]
4515pub struct SessionCloseCapabilities {
4516 #[serde(rename = "_meta")]
4522 pub meta: Option<Meta>,
4523}
4524
4525impl SessionCloseCapabilities {
4526 #[must_use]
4527 pub fn new() -> Self {
4528 Self::default()
4529 }
4530
4531 #[must_use]
4537 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4538 self.meta = meta.into_option();
4539 self
4540 }
4541}
4542
4543#[skip_serializing_none]
4556#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4557#[serde(rename_all = "camelCase")]
4558#[non_exhaustive]
4559pub struct PromptCapabilities {
4560 #[serde(default)]
4562 pub image: bool,
4563 #[serde(default)]
4565 pub audio: bool,
4566 #[serde(default)]
4571 pub embedded_context: bool,
4572 #[serde(rename = "_meta")]
4578 pub meta: Option<Meta>,
4579}
4580
4581impl PromptCapabilities {
4582 #[must_use]
4583 pub fn new() -> Self {
4584 Self::default()
4585 }
4586
4587 #[must_use]
4589 pub fn image(mut self, image: bool) -> Self {
4590 self.image = image;
4591 self
4592 }
4593
4594 #[must_use]
4596 pub fn audio(mut self, audio: bool) -> Self {
4597 self.audio = audio;
4598 self
4599 }
4600
4601 #[must_use]
4606 pub fn embedded_context(mut self, embedded_context: bool) -> Self {
4607 self.embedded_context = embedded_context;
4608 self
4609 }
4610
4611 #[must_use]
4617 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4618 self.meta = meta.into_option();
4619 self
4620 }
4621}
4622
4623#[skip_serializing_none]
4625#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4626#[serde(rename_all = "camelCase")]
4627#[non_exhaustive]
4628pub struct McpCapabilities {
4629 #[serde(default)]
4631 pub http: bool,
4632 #[serde(default)]
4634 pub sse: bool,
4635 #[cfg(feature = "unstable_mcp_over_acp")]
4641 #[serde(default)]
4642 pub acp: bool,
4643 #[serde(rename = "_meta")]
4649 pub meta: Option<Meta>,
4650}
4651
4652impl McpCapabilities {
4653 #[must_use]
4654 pub fn new() -> Self {
4655 Self::default()
4656 }
4657
4658 #[must_use]
4660 pub fn http(mut self, http: bool) -> Self {
4661 self.http = http;
4662 self
4663 }
4664
4665 #[must_use]
4667 pub fn sse(mut self, sse: bool) -> Self {
4668 self.sse = sse;
4669 self
4670 }
4671
4672 #[cfg(feature = "unstable_mcp_over_acp")]
4678 #[must_use]
4679 pub fn acp(mut self, acp: bool) -> Self {
4680 self.acp = acp;
4681 self
4682 }
4683
4684 #[must_use]
4690 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4691 self.meta = meta.into_option();
4692 self
4693 }
4694}
4695
4696#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4702#[non_exhaustive]
4703pub struct AgentMethodNames {
4704 pub initialize: &'static str,
4706 pub authenticate: &'static str,
4708 #[cfg(feature = "unstable_llm_providers")]
4710 pub providers_list: &'static str,
4711 #[cfg(feature = "unstable_llm_providers")]
4713 pub providers_set: &'static str,
4714 #[cfg(feature = "unstable_llm_providers")]
4716 pub providers_disable: &'static str,
4717 pub session_new: &'static str,
4719 pub session_load: &'static str,
4721 pub session_set_mode: &'static str,
4723 pub session_set_config_option: &'static str,
4725 pub session_prompt: &'static str,
4727 pub session_cancel: &'static str,
4729 #[cfg(feature = "unstable_mcp_over_acp")]
4731 pub mcp_message: &'static str,
4732 #[cfg(feature = "unstable_session_model")]
4734 pub session_set_model: &'static str,
4735 pub session_list: &'static str,
4737 #[cfg(feature = "unstable_session_delete")]
4739 pub session_delete: &'static str,
4740 #[cfg(feature = "unstable_session_fork")]
4742 pub session_fork: &'static str,
4743 pub session_resume: &'static str,
4745 pub session_close: &'static str,
4747 pub logout: &'static str,
4749 #[cfg(feature = "unstable_nes")]
4751 pub nes_start: &'static str,
4752 #[cfg(feature = "unstable_nes")]
4754 pub nes_suggest: &'static str,
4755 #[cfg(feature = "unstable_nes")]
4757 pub nes_accept: &'static str,
4758 #[cfg(feature = "unstable_nes")]
4760 pub nes_reject: &'static str,
4761 #[cfg(feature = "unstable_nes")]
4763 pub nes_close: &'static str,
4764 #[cfg(feature = "unstable_nes")]
4766 pub document_did_open: &'static str,
4767 #[cfg(feature = "unstable_nes")]
4769 pub document_did_change: &'static str,
4770 #[cfg(feature = "unstable_nes")]
4772 pub document_did_close: &'static str,
4773 #[cfg(feature = "unstable_nes")]
4775 pub document_did_save: &'static str,
4776 #[cfg(feature = "unstable_nes")]
4778 pub document_did_focus: &'static str,
4779}
4780
4781pub const AGENT_METHOD_NAMES: AgentMethodNames = AgentMethodNames {
4783 initialize: INITIALIZE_METHOD_NAME,
4784 authenticate: AUTHENTICATE_METHOD_NAME,
4785 #[cfg(feature = "unstable_llm_providers")]
4786 providers_list: PROVIDERS_LIST_METHOD_NAME,
4787 #[cfg(feature = "unstable_llm_providers")]
4788 providers_set: PROVIDERS_SET_METHOD_NAME,
4789 #[cfg(feature = "unstable_llm_providers")]
4790 providers_disable: PROVIDERS_DISABLE_METHOD_NAME,
4791 session_new: SESSION_NEW_METHOD_NAME,
4792 session_load: SESSION_LOAD_METHOD_NAME,
4793 session_set_mode: SESSION_SET_MODE_METHOD_NAME,
4794 session_set_config_option: SESSION_SET_CONFIG_OPTION_METHOD_NAME,
4795 session_prompt: SESSION_PROMPT_METHOD_NAME,
4796 session_cancel: SESSION_CANCEL_METHOD_NAME,
4797 #[cfg(feature = "unstable_mcp_over_acp")]
4798 mcp_message: MCP_MESSAGE_METHOD_NAME,
4799 #[cfg(feature = "unstable_session_model")]
4800 session_set_model: SESSION_SET_MODEL_METHOD_NAME,
4801 session_list: SESSION_LIST_METHOD_NAME,
4802 #[cfg(feature = "unstable_session_delete")]
4803 session_delete: SESSION_DELETE_METHOD_NAME,
4804 #[cfg(feature = "unstable_session_fork")]
4805 session_fork: SESSION_FORK_METHOD_NAME,
4806 session_resume: SESSION_RESUME_METHOD_NAME,
4807 session_close: SESSION_CLOSE_METHOD_NAME,
4808 logout: LOGOUT_METHOD_NAME,
4809 #[cfg(feature = "unstable_nes")]
4810 nes_start: NES_START_METHOD_NAME,
4811 #[cfg(feature = "unstable_nes")]
4812 nes_suggest: NES_SUGGEST_METHOD_NAME,
4813 #[cfg(feature = "unstable_nes")]
4814 nes_accept: NES_ACCEPT_METHOD_NAME,
4815 #[cfg(feature = "unstable_nes")]
4816 nes_reject: NES_REJECT_METHOD_NAME,
4817 #[cfg(feature = "unstable_nes")]
4818 nes_close: NES_CLOSE_METHOD_NAME,
4819 #[cfg(feature = "unstable_nes")]
4820 document_did_open: DOCUMENT_DID_OPEN_METHOD_NAME,
4821 #[cfg(feature = "unstable_nes")]
4822 document_did_change: DOCUMENT_DID_CHANGE_METHOD_NAME,
4823 #[cfg(feature = "unstable_nes")]
4824 document_did_close: DOCUMENT_DID_CLOSE_METHOD_NAME,
4825 #[cfg(feature = "unstable_nes")]
4826 document_did_save: DOCUMENT_DID_SAVE_METHOD_NAME,
4827 #[cfg(feature = "unstable_nes")]
4828 document_did_focus: DOCUMENT_DID_FOCUS_METHOD_NAME,
4829};
4830
4831pub(crate) const INITIALIZE_METHOD_NAME: &str = "initialize";
4833pub(crate) const AUTHENTICATE_METHOD_NAME: &str = "authenticate";
4835#[cfg(feature = "unstable_llm_providers")]
4837pub(crate) const PROVIDERS_LIST_METHOD_NAME: &str = "providers/list";
4838#[cfg(feature = "unstable_llm_providers")]
4840pub(crate) const PROVIDERS_SET_METHOD_NAME: &str = "providers/set";
4841#[cfg(feature = "unstable_llm_providers")]
4843pub(crate) const PROVIDERS_DISABLE_METHOD_NAME: &str = "providers/disable";
4844pub(crate) const SESSION_NEW_METHOD_NAME: &str = "session/new";
4846pub(crate) const SESSION_LOAD_METHOD_NAME: &str = "session/load";
4848pub(crate) const SESSION_SET_MODE_METHOD_NAME: &str = "session/set_mode";
4850pub(crate) const SESSION_SET_CONFIG_OPTION_METHOD_NAME: &str = "session/set_config_option";
4852pub(crate) const SESSION_PROMPT_METHOD_NAME: &str = "session/prompt";
4854pub(crate) const SESSION_CANCEL_METHOD_NAME: &str = "session/cancel";
4856#[cfg(feature = "unstable_session_model")]
4858pub(crate) const SESSION_SET_MODEL_METHOD_NAME: &str = "session/set_model";
4859pub(crate) const SESSION_LIST_METHOD_NAME: &str = "session/list";
4861#[cfg(feature = "unstable_session_delete")]
4863pub(crate) const SESSION_DELETE_METHOD_NAME: &str = "session/delete";
4864#[cfg(feature = "unstable_session_fork")]
4866pub(crate) const SESSION_FORK_METHOD_NAME: &str = "session/fork";
4867pub(crate) const SESSION_RESUME_METHOD_NAME: &str = "session/resume";
4869pub(crate) const SESSION_CLOSE_METHOD_NAME: &str = "session/close";
4871pub(crate) const LOGOUT_METHOD_NAME: &str = "logout";
4873
4874#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
4881#[serde(untagged)]
4882#[schemars(inline)]
4883#[non_exhaustive]
4884#[allow(clippy::large_enum_variant)]
4885pub enum ClientRequest {
4886 InitializeRequest(InitializeRequest),
4897 AuthenticateRequest(AuthenticateRequest),
4907 #[cfg(feature = "unstable_llm_providers")]
4913 ListProvidersRequest(ListProvidersRequest),
4914 #[cfg(feature = "unstable_llm_providers")]
4920 SetProviderRequest(SetProviderRequest),
4921 #[cfg(feature = "unstable_llm_providers")]
4927 DisableProviderRequest(DisableProviderRequest),
4928 LogoutRequest(LogoutRequest),
4933 NewSessionRequest(NewSessionRequest),
4946 LoadSessionRequest(LoadSessionRequest),
4957 ListSessionsRequest(ListSessionsRequest),
4963 #[cfg(feature = "unstable_session_delete")]
4971 DeleteSessionRequest(DeleteSessionRequest),
4972 #[cfg(feature = "unstable_session_fork")]
4973 ForkSessionRequest(ForkSessionRequest),
4985 ResumeSessionRequest(ResumeSessionRequest),
4992 CloseSessionRequest(CloseSessionRequest),
4999 SetSessionModeRequest(SetSessionModeRequest),
5013 SetSessionConfigOptionRequest(SetSessionConfigOptionRequest),
5015 PromptRequest(PromptRequest),
5027 #[cfg(feature = "unstable_session_model")]
5028 SetSessionModelRequest(SetSessionModelRequest),
5034 #[cfg(feature = "unstable_nes")]
5035 StartNesRequest(StartNesRequest),
5041 #[cfg(feature = "unstable_nes")]
5042 SuggestNesRequest(SuggestNesRequest),
5048 #[cfg(feature = "unstable_nes")]
5049 CloseNesRequest(CloseNesRequest),
5058 #[cfg(feature = "unstable_mcp_over_acp")]
5064 MessageMcpRequest(MessageMcpRequest),
5065 ExtMethodRequest(ExtRequest),
5072}
5073
5074impl ClientRequest {
5075 #[must_use]
5077 pub fn method(&self) -> &str {
5078 match self {
5079 Self::InitializeRequest(_) => AGENT_METHOD_NAMES.initialize,
5080 Self::AuthenticateRequest(_) => AGENT_METHOD_NAMES.authenticate,
5081 #[cfg(feature = "unstable_llm_providers")]
5082 Self::ListProvidersRequest(_) => AGENT_METHOD_NAMES.providers_list,
5083 #[cfg(feature = "unstable_llm_providers")]
5084 Self::SetProviderRequest(_) => AGENT_METHOD_NAMES.providers_set,
5085 #[cfg(feature = "unstable_llm_providers")]
5086 Self::DisableProviderRequest(_) => AGENT_METHOD_NAMES.providers_disable,
5087 Self::LogoutRequest(_) => AGENT_METHOD_NAMES.logout,
5088 Self::NewSessionRequest(_) => AGENT_METHOD_NAMES.session_new,
5089 Self::LoadSessionRequest(_) => AGENT_METHOD_NAMES.session_load,
5090 Self::ListSessionsRequest(_) => AGENT_METHOD_NAMES.session_list,
5091 #[cfg(feature = "unstable_session_delete")]
5092 Self::DeleteSessionRequest(_) => AGENT_METHOD_NAMES.session_delete,
5093 #[cfg(feature = "unstable_session_fork")]
5094 Self::ForkSessionRequest(_) => AGENT_METHOD_NAMES.session_fork,
5095 Self::ResumeSessionRequest(_) => AGENT_METHOD_NAMES.session_resume,
5096 Self::CloseSessionRequest(_) => AGENT_METHOD_NAMES.session_close,
5097 Self::SetSessionModeRequest(_) => AGENT_METHOD_NAMES.session_set_mode,
5098 Self::SetSessionConfigOptionRequest(_) => AGENT_METHOD_NAMES.session_set_config_option,
5099 Self::PromptRequest(_) => AGENT_METHOD_NAMES.session_prompt,
5100 #[cfg(feature = "unstable_session_model")]
5101 Self::SetSessionModelRequest(_) => AGENT_METHOD_NAMES.session_set_model,
5102 #[cfg(feature = "unstable_nes")]
5103 Self::StartNesRequest(_) => AGENT_METHOD_NAMES.nes_start,
5104 #[cfg(feature = "unstable_nes")]
5105 Self::SuggestNesRequest(_) => AGENT_METHOD_NAMES.nes_suggest,
5106 #[cfg(feature = "unstable_nes")]
5107 Self::CloseNesRequest(_) => AGENT_METHOD_NAMES.nes_close,
5108 #[cfg(feature = "unstable_mcp_over_acp")]
5109 Self::MessageMcpRequest(_) => AGENT_METHOD_NAMES.mcp_message,
5110 Self::ExtMethodRequest(ext_request) => &ext_request.method,
5111 }
5112 }
5113}
5114
5115#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
5122#[serde(untagged)]
5123#[schemars(inline)]
5124#[non_exhaustive]
5125#[allow(clippy::large_enum_variant)]
5126pub enum AgentResponse {
5127 InitializeResponse(InitializeResponse),
5128 AuthenticateResponse(#[serde(default)] AuthenticateResponse),
5129 #[cfg(feature = "unstable_llm_providers")]
5130 ListProvidersResponse(ListProvidersResponse),
5131 #[cfg(feature = "unstable_llm_providers")]
5132 SetProviderResponse(#[serde(default)] SetProviderResponse),
5133 #[cfg(feature = "unstable_llm_providers")]
5134 DisableProviderResponse(#[serde(default)] DisableProviderResponse),
5135 LogoutResponse(#[serde(default)] LogoutResponse),
5136 NewSessionResponse(NewSessionResponse),
5137 LoadSessionResponse(#[serde(default)] LoadSessionResponse),
5138 ListSessionsResponse(ListSessionsResponse),
5139 #[cfg(feature = "unstable_session_delete")]
5140 DeleteSessionResponse(#[serde(default)] DeleteSessionResponse),
5141 #[cfg(feature = "unstable_session_fork")]
5142 ForkSessionResponse(ForkSessionResponse),
5143 ResumeSessionResponse(#[serde(default)] ResumeSessionResponse),
5144 CloseSessionResponse(#[serde(default)] CloseSessionResponse),
5145 SetSessionModeResponse(#[serde(default)] SetSessionModeResponse),
5146 SetSessionConfigOptionResponse(SetSessionConfigOptionResponse),
5147 PromptResponse(PromptResponse),
5148 #[cfg(feature = "unstable_session_model")]
5149 SetSessionModelResponse(#[serde(default)] SetSessionModelResponse),
5150 #[cfg(feature = "unstable_nes")]
5151 StartNesResponse(StartNesResponse),
5152 #[cfg(feature = "unstable_nes")]
5153 SuggestNesResponse(SuggestNesResponse),
5154 #[cfg(feature = "unstable_nes")]
5155 CloseNesResponse(#[serde(default)] CloseNesResponse),
5156 ExtMethodResponse(ExtResponse),
5157 #[cfg(feature = "unstable_mcp_over_acp")]
5158 MessageMcpResponse(MessageMcpResponse),
5159}
5160
5161#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
5168#[serde(untagged)]
5169#[schemars(inline)]
5170#[non_exhaustive]
5171pub enum ClientNotification {
5172 CancelNotification(CancelNotification),
5184 #[cfg(feature = "unstable_nes")]
5185 DidOpenDocumentNotification(DidOpenDocumentNotification),
5189 #[cfg(feature = "unstable_nes")]
5190 DidChangeDocumentNotification(DidChangeDocumentNotification),
5194 #[cfg(feature = "unstable_nes")]
5195 DidCloseDocumentNotification(DidCloseDocumentNotification),
5199 #[cfg(feature = "unstable_nes")]
5200 DidSaveDocumentNotification(DidSaveDocumentNotification),
5204 #[cfg(feature = "unstable_nes")]
5205 DidFocusDocumentNotification(DidFocusDocumentNotification),
5209 #[cfg(feature = "unstable_nes")]
5210 AcceptNesNotification(AcceptNesNotification),
5214 #[cfg(feature = "unstable_nes")]
5215 RejectNesNotification(RejectNesNotification),
5219 #[cfg(feature = "unstable_mcp_over_acp")]
5225 MessageMcpNotification(MessageMcpNotification),
5226 ExtNotification(ExtNotification),
5233}
5234
5235impl ClientNotification {
5236 #[must_use]
5238 pub fn method(&self) -> &str {
5239 match self {
5240 Self::CancelNotification(_) => AGENT_METHOD_NAMES.session_cancel,
5241 #[cfg(feature = "unstable_nes")]
5242 Self::DidOpenDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_open,
5243 #[cfg(feature = "unstable_nes")]
5244 Self::DidChangeDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_change,
5245 #[cfg(feature = "unstable_nes")]
5246 Self::DidCloseDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_close,
5247 #[cfg(feature = "unstable_nes")]
5248 Self::DidSaveDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_save,
5249 #[cfg(feature = "unstable_nes")]
5250 Self::DidFocusDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_focus,
5251 #[cfg(feature = "unstable_nes")]
5252 Self::AcceptNesNotification(_) => AGENT_METHOD_NAMES.nes_accept,
5253 #[cfg(feature = "unstable_nes")]
5254 Self::RejectNesNotification(_) => AGENT_METHOD_NAMES.nes_reject,
5255 #[cfg(feature = "unstable_mcp_over_acp")]
5256 Self::MessageMcpNotification(_) => AGENT_METHOD_NAMES.mcp_message,
5257 Self::ExtNotification(ext_notification) => &ext_notification.method,
5258 }
5259 }
5260}
5261
5262#[skip_serializing_none]
5266#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
5267#[schemars(extend("x-side" = "agent", "x-method" = SESSION_CANCEL_METHOD_NAME))]
5268#[serde(rename_all = "camelCase")]
5269#[non_exhaustive]
5270pub struct CancelNotification {
5271 pub session_id: SessionId,
5273 #[serde(rename = "_meta")]
5279 pub meta: Option<Meta>,
5280}
5281
5282impl CancelNotification {
5283 #[must_use]
5284 pub fn new(session_id: impl Into<SessionId>) -> Self {
5285 Self {
5286 session_id: session_id.into(),
5287 meta: None,
5288 }
5289 }
5290
5291 #[must_use]
5297 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5298 self.meta = meta.into_option();
5299 self
5300 }
5301}
5302
5303#[cfg(test)]
5304mod test_serialization {
5305 use super::*;
5306 use serde_json::json;
5307
5308 #[test]
5309 fn test_mcp_server_stdio_serialization() {
5310 let server = McpServer::Stdio(
5311 McpServerStdio::new("test-server", "/usr/bin/server")
5312 .args(vec!["--port".to_string(), "3000".to_string()])
5313 .env(vec![EnvVariable::new("API_KEY", "secret123")]),
5314 );
5315
5316 let json = serde_json::to_value(&server).unwrap();
5317 assert_eq!(
5318 json,
5319 json!({
5320 "name": "test-server",
5321 "command": "/usr/bin/server",
5322 "args": ["--port", "3000"],
5323 "env": [
5324 {
5325 "name": "API_KEY",
5326 "value": "secret123"
5327 }
5328 ]
5329 })
5330 );
5331
5332 let deserialized: McpServer = serde_json::from_value(json).unwrap();
5333 match deserialized {
5334 McpServer::Stdio(McpServerStdio {
5335 name,
5336 command,
5337 args,
5338 env,
5339 meta: _,
5340 }) => {
5341 assert_eq!(name, "test-server");
5342 assert_eq!(command, PathBuf::from("/usr/bin/server"));
5343 assert_eq!(args, vec!["--port", "3000"]);
5344 assert_eq!(env.len(), 1);
5345 assert_eq!(env[0].name, "API_KEY");
5346 assert_eq!(env[0].value, "secret123");
5347 }
5348 _ => panic!("Expected Stdio variant"),
5349 }
5350 }
5351
5352 #[test]
5353 fn test_mcp_server_http_serialization() {
5354 let server = McpServer::Http(
5355 McpServerHttp::new("http-server", "https://api.example.com").headers(vec![
5356 HttpHeader::new("Authorization", "Bearer token123"),
5357 HttpHeader::new("Content-Type", "application/json"),
5358 ]),
5359 );
5360
5361 let json = serde_json::to_value(&server).unwrap();
5362 assert_eq!(
5363 json,
5364 json!({
5365 "type": "http",
5366 "name": "http-server",
5367 "url": "https://api.example.com",
5368 "headers": [
5369 {
5370 "name": "Authorization",
5371 "value": "Bearer token123"
5372 },
5373 {
5374 "name": "Content-Type",
5375 "value": "application/json"
5376 }
5377 ]
5378 })
5379 );
5380
5381 let deserialized: McpServer = serde_json::from_value(json).unwrap();
5382 match deserialized {
5383 McpServer::Http(McpServerHttp {
5384 name,
5385 url,
5386 headers,
5387 meta: _,
5388 }) => {
5389 assert_eq!(name, "http-server");
5390 assert_eq!(url, "https://api.example.com");
5391 assert_eq!(headers.len(), 2);
5392 assert_eq!(headers[0].name, "Authorization");
5393 assert_eq!(headers[0].value, "Bearer token123");
5394 assert_eq!(headers[1].name, "Content-Type");
5395 assert_eq!(headers[1].value, "application/json");
5396 }
5397 _ => panic!("Expected Http variant"),
5398 }
5399 }
5400
5401 #[cfg(feature = "unstable_mcp_over_acp")]
5402 #[test]
5403 fn test_mcp_server_acp_serialization() {
5404 let server = McpServer::Acp(McpServerAcp::new("project-tools", "project-tools-id"));
5405
5406 let json = serde_json::to_value(&server).unwrap();
5407 assert_eq!(
5408 json,
5409 json!({
5410 "type": "acp",
5411 "name": "project-tools",
5412 "id": "project-tools-id"
5413 })
5414 );
5415
5416 let deserialized: McpServer = serde_json::from_value(json).unwrap();
5417 match deserialized {
5418 McpServer::Acp(McpServerAcp { name, id, meta: _ }) => {
5419 assert_eq!(name, "project-tools");
5420 assert_eq!(id, McpServerAcpId::new("project-tools-id"));
5421 }
5422 _ => panic!("Expected Acp variant"),
5423 }
5424 }
5425
5426 #[cfg(feature = "unstable_mcp_over_acp")]
5427 #[test]
5428 fn test_client_mcp_message_method_names() {
5429 assert_eq!(AGENT_METHOD_NAMES.mcp_message, "mcp/message");
5430
5431 assert_eq!(
5432 ClientRequest::MessageMcpRequest(MessageMcpRequest::new("conn-1", "tools/list"))
5433 .method(),
5434 "mcp/message"
5435 );
5436 assert_eq!(
5437 ClientNotification::MessageMcpNotification(MessageMcpNotification::new(
5438 "conn-1",
5439 "notifications/progress"
5440 ))
5441 .method(),
5442 "mcp/message"
5443 );
5444 }
5445
5446 #[cfg(feature = "unstable_mcp_over_acp")]
5447 #[test]
5448 fn test_mcp_server_acp_schema() {
5449 let mcp_server_schema = serde_json::to_value(schemars::schema_for!(McpServer)).unwrap();
5450 assert!(json_contains_entry(
5451 &mcp_server_schema,
5452 "const",
5453 &json!("acp")
5454 ));
5455 assert!(json_contains_entry(
5456 &mcp_server_schema,
5457 "$ref",
5458 &json!("#/$defs/McpServerAcp")
5459 ));
5460
5461 let capabilities_schema =
5462 serde_json::to_value(schemars::schema_for!(McpCapabilities)).unwrap();
5463 assert!(json_contains_key(&capabilities_schema, "acp"));
5464 }
5465
5466 #[cfg(feature = "unstable_mcp_over_acp")]
5467 fn json_contains_entry(
5468 value: &serde_json::Value,
5469 key: &str,
5470 expected: &serde_json::Value,
5471 ) -> bool {
5472 match value {
5473 serde_json::Value::Object(map) => {
5474 map.get(key) == Some(expected)
5475 || map
5476 .values()
5477 .any(|value| json_contains_entry(value, key, expected))
5478 }
5479 serde_json::Value::Array(values) => values
5480 .iter()
5481 .any(|value| json_contains_entry(value, key, expected)),
5482 _ => false,
5483 }
5484 }
5485
5486 #[cfg(feature = "unstable_mcp_over_acp")]
5487 fn json_contains_key(value: &serde_json::Value, key: &str) -> bool {
5488 match value {
5489 serde_json::Value::Object(map) => {
5490 map.contains_key(key) || map.values().any(|value| json_contains_key(value, key))
5491 }
5492 serde_json::Value::Array(values) => {
5493 values.iter().any(|value| json_contains_key(value, key))
5494 }
5495 _ => false,
5496 }
5497 }
5498
5499 #[test]
5500 fn test_mcp_server_sse_serialization() {
5501 let server = McpServer::Sse(
5502 McpServerSse::new("sse-server", "https://sse.example.com/events")
5503 .headers(vec![HttpHeader::new("X-API-Key", "apikey456")]),
5504 );
5505
5506 let json = serde_json::to_value(&server).unwrap();
5507 assert_eq!(
5508 json,
5509 json!({
5510 "type": "sse",
5511 "name": "sse-server",
5512 "url": "https://sse.example.com/events",
5513 "headers": [
5514 {
5515 "name": "X-API-Key",
5516 "value": "apikey456"
5517 }
5518 ]
5519 })
5520 );
5521
5522 let deserialized: McpServer = serde_json::from_value(json).unwrap();
5523 match deserialized {
5524 McpServer::Sse(McpServerSse {
5525 name,
5526 url,
5527 headers,
5528 meta: _,
5529 }) => {
5530 assert_eq!(name, "sse-server");
5531 assert_eq!(url, "https://sse.example.com/events");
5532 assert_eq!(headers.len(), 1);
5533 assert_eq!(headers[0].name, "X-API-Key");
5534 assert_eq!(headers[0].value, "apikey456");
5535 }
5536 _ => panic!("Expected Sse variant"),
5537 }
5538 }
5539
5540 #[test]
5541 fn test_session_config_option_category_known_variants() {
5542 assert_eq!(
5544 serde_json::to_value(&SessionConfigOptionCategory::Mode).unwrap(),
5545 json!("mode")
5546 );
5547 assert_eq!(
5548 serde_json::to_value(&SessionConfigOptionCategory::Model).unwrap(),
5549 json!("model")
5550 );
5551 assert_eq!(
5552 serde_json::to_value(&SessionConfigOptionCategory::ThoughtLevel).unwrap(),
5553 json!("thought_level")
5554 );
5555
5556 assert_eq!(
5558 serde_json::from_str::<SessionConfigOptionCategory>("\"mode\"").unwrap(),
5559 SessionConfigOptionCategory::Mode
5560 );
5561 assert_eq!(
5562 serde_json::from_str::<SessionConfigOptionCategory>("\"model\"").unwrap(),
5563 SessionConfigOptionCategory::Model
5564 );
5565 assert_eq!(
5566 serde_json::from_str::<SessionConfigOptionCategory>("\"thought_level\"").unwrap(),
5567 SessionConfigOptionCategory::ThoughtLevel
5568 );
5569 }
5570
5571 #[test]
5572 fn test_session_config_option_category_unknown_variants() {
5573 let unknown: SessionConfigOptionCategory =
5575 serde_json::from_str("\"some_future_category\"").unwrap();
5576 assert_eq!(
5577 unknown,
5578 SessionConfigOptionCategory::Other("some_future_category".to_string())
5579 );
5580
5581 let json = serde_json::to_value(&unknown).unwrap();
5583 assert_eq!(json, json!("some_future_category"));
5584 }
5585
5586 #[test]
5587 fn test_session_config_option_category_custom_categories() {
5588 let custom: SessionConfigOptionCategory =
5590 serde_json::from_str("\"_my_custom_category\"").unwrap();
5591 assert_eq!(
5592 custom,
5593 SessionConfigOptionCategory::Other("_my_custom_category".to_string())
5594 );
5595
5596 let json = serde_json::to_value(&custom).unwrap();
5598 assert_eq!(json, json!("_my_custom_category"));
5599
5600 let deserialized: SessionConfigOptionCategory = serde_json::from_value(json).unwrap();
5602 assert_eq!(
5603 deserialized,
5604 SessionConfigOptionCategory::Other("_my_custom_category".to_string()),
5605 );
5606 }
5607
5608 #[test]
5609 fn test_auth_method_agent_serialization() {
5610 let method = AuthMethod::Agent(AuthMethodAgent::new("default-auth", "Default Auth"));
5611
5612 let json = serde_json::to_value(&method).unwrap();
5613 assert_eq!(
5614 json,
5615 json!({
5616 "id": "default-auth",
5617 "name": "Default Auth"
5618 })
5619 );
5620 assert!(!json.as_object().unwrap().contains_key("description"));
5622 assert!(!json.as_object().unwrap().contains_key("type"));
5624
5625 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5626 match deserialized {
5627 AuthMethod::Agent(AuthMethodAgent { id, name, .. }) => {
5628 assert_eq!(id.0.as_ref(), "default-auth");
5629 assert_eq!(name, "Default Auth");
5630 }
5631 #[cfg(feature = "unstable_auth_methods")]
5632 _ => panic!("Expected Agent variant"),
5633 }
5634 }
5635
5636 #[test]
5637 fn test_auth_method_explicit_agent_deserialization() {
5638 let json = json!({
5640 "id": "agent-auth",
5641 "name": "Agent Auth",
5642 "type": "agent"
5643 });
5644
5645 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5646 assert!(matches!(deserialized, AuthMethod::Agent(_)));
5647 }
5648
5649 #[cfg(feature = "unstable_session_delete")]
5650 #[test]
5651 fn test_session_delete_serialization() {
5652 assert_eq!(AGENT_METHOD_NAMES.session_delete, "session/delete");
5653 assert_eq!(
5654 ClientRequest::DeleteSessionRequest(DeleteSessionRequest::new("sess_abc123")).method(),
5655 "session/delete"
5656 );
5657 assert_eq!(
5658 serde_json::to_value(DeleteSessionRequest::new("sess_abc123")).unwrap(),
5659 json!({
5660 "sessionId": "sess_abc123"
5661 })
5662 );
5663 assert_eq!(
5664 serde_json::to_value(DeleteSessionResponse::new()).unwrap(),
5665 json!({})
5666 );
5667 assert_eq!(
5668 serde_json::to_value(
5669 SessionCapabilities::new().delete(SessionDeleteCapabilities::new())
5670 )
5671 .unwrap(),
5672 json!({
5673 "delete": {}
5674 })
5675 );
5676 }
5677
5678 #[cfg(feature = "unstable_session_additional_directories")]
5679 #[test]
5680 fn test_session_additional_directories_serialization() {
5681 assert_eq!(
5682 serde_json::to_value(NewSessionRequest::new("/home/user/project")).unwrap(),
5683 json!({
5684 "cwd": "/home/user/project",
5685 "mcpServers": []
5686 })
5687 );
5688 assert_eq!(
5689 serde_json::to_value(
5690 NewSessionRequest::new("/home/user/project").additional_directories(vec![
5691 PathBuf::from("/home/user/shared-lib"),
5692 PathBuf::from("/home/user/product-docs"),
5693 ])
5694 )
5695 .unwrap(),
5696 json!({
5697 "cwd": "/home/user/project",
5698 "additionalDirectories": [
5699 "/home/user/shared-lib",
5700 "/home/user/product-docs"
5701 ],
5702 "mcpServers": []
5703 })
5704 );
5705 assert_eq!(
5706 serde_json::to_value(SessionInfo::new("sess_abc123", "/home/user/project")).unwrap(),
5707 json!({
5708 "sessionId": "sess_abc123",
5709 "cwd": "/home/user/project"
5710 })
5711 );
5712 assert_eq!(
5713 serde_json::to_value(
5714 SessionInfo::new("sess_abc123", "/home/user/project").additional_directories(vec![
5715 PathBuf::from("/home/user/shared-lib"),
5716 PathBuf::from("/home/user/product-docs"),
5717 ])
5718 )
5719 .unwrap(),
5720 json!({
5721 "sessionId": "sess_abc123",
5722 "cwd": "/home/user/project",
5723 "additionalDirectories": [
5724 "/home/user/shared-lib",
5725 "/home/user/product-docs"
5726 ]
5727 })
5728 );
5729 assert_eq!(
5730 serde_json::from_value::<SessionInfo>(json!({
5731 "sessionId": "sess_abc123",
5732 "cwd": "/home/user/project"
5733 }))
5734 .unwrap()
5735 .additional_directories,
5736 Vec::<PathBuf>::new()
5737 );
5738 }
5739
5740 #[cfg(feature = "unstable_session_additional_directories")]
5741 #[test]
5742 fn test_session_additional_directories_capabilities_serialization() {
5743 assert_eq!(
5744 serde_json::to_value(
5745 SessionCapabilities::new()
5746 .additional_directories(SessionAdditionalDirectoriesCapabilities::new())
5747 )
5748 .unwrap(),
5749 json!({
5750 "additionalDirectories": {}
5751 })
5752 );
5753 }
5754
5755 #[cfg(feature = "unstable_auth_methods")]
5756 #[test]
5757 fn test_auth_method_env_var_serialization() {
5758 let method = AuthMethod::EnvVar(AuthMethodEnvVar::new(
5759 "api-key",
5760 "API Key",
5761 vec![AuthEnvVar::new("API_KEY")],
5762 ));
5763
5764 let json = serde_json::to_value(&method).unwrap();
5765 assert_eq!(
5766 json,
5767 json!({
5768 "id": "api-key",
5769 "name": "API Key",
5770 "type": "env_var",
5771 "vars": [{"name": "API_KEY"}]
5772 })
5773 );
5774 assert!(!json["vars"][0].as_object().unwrap().contains_key("secret"));
5776 assert!(
5777 !json["vars"][0]
5778 .as_object()
5779 .unwrap()
5780 .contains_key("optional")
5781 );
5782
5783 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5784 match deserialized {
5785 AuthMethod::EnvVar(AuthMethodEnvVar {
5786 id,
5787 name: method_name,
5788 vars,
5789 link,
5790 ..
5791 }) => {
5792 assert_eq!(id.0.as_ref(), "api-key");
5793 assert_eq!(method_name, "API Key");
5794 assert_eq!(vars.len(), 1);
5795 assert_eq!(vars[0].name, "API_KEY");
5796 assert!(vars[0].secret);
5797 assert!(!vars[0].optional);
5798 assert!(link.is_none());
5799 }
5800 _ => panic!("Expected EnvVar variant"),
5801 }
5802 }
5803
5804 #[cfg(feature = "unstable_auth_methods")]
5805 #[test]
5806 fn test_auth_method_env_var_with_link_serialization() {
5807 let method = AuthMethod::EnvVar(
5808 AuthMethodEnvVar::new("api-key", "API Key", vec![AuthEnvVar::new("API_KEY")])
5809 .link("https://example.com/keys"),
5810 );
5811
5812 let json = serde_json::to_value(&method).unwrap();
5813 assert_eq!(
5814 json,
5815 json!({
5816 "id": "api-key",
5817 "name": "API Key",
5818 "type": "env_var",
5819 "vars": [{"name": "API_KEY"}],
5820 "link": "https://example.com/keys"
5821 })
5822 );
5823
5824 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5825 match deserialized {
5826 AuthMethod::EnvVar(AuthMethodEnvVar { link, .. }) => {
5827 assert_eq!(link.as_deref(), Some("https://example.com/keys"));
5828 }
5829 _ => panic!("Expected EnvVar variant"),
5830 }
5831 }
5832
5833 #[cfg(feature = "unstable_auth_methods")]
5834 #[test]
5835 fn test_auth_method_env_var_multiple_vars() {
5836 let method = AuthMethod::EnvVar(AuthMethodEnvVar::new(
5837 "azure-openai",
5838 "Azure OpenAI",
5839 vec![
5840 AuthEnvVar::new("AZURE_OPENAI_API_KEY").label("API Key"),
5841 AuthEnvVar::new("AZURE_OPENAI_ENDPOINT")
5842 .label("Endpoint URL")
5843 .secret(false),
5844 AuthEnvVar::new("AZURE_OPENAI_API_VERSION")
5845 .label("API Version")
5846 .secret(false)
5847 .optional(true),
5848 ],
5849 ));
5850
5851 let json = serde_json::to_value(&method).unwrap();
5852 assert_eq!(
5853 json,
5854 json!({
5855 "id": "azure-openai",
5856 "name": "Azure OpenAI",
5857 "type": "env_var",
5858 "vars": [
5859 {"name": "AZURE_OPENAI_API_KEY", "label": "API Key"},
5860 {"name": "AZURE_OPENAI_ENDPOINT", "label": "Endpoint URL", "secret": false},
5861 {"name": "AZURE_OPENAI_API_VERSION", "label": "API Version", "secret": false, "optional": true}
5862 ]
5863 })
5864 );
5865
5866 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5867 match deserialized {
5868 AuthMethod::EnvVar(AuthMethodEnvVar { vars, .. }) => {
5869 assert_eq!(vars.len(), 3);
5870 assert_eq!(vars[0].name, "AZURE_OPENAI_API_KEY");
5872 assert_eq!(vars[0].label.as_deref(), Some("API Key"));
5873 assert!(vars[0].secret);
5874 assert!(!vars[0].optional);
5875 assert_eq!(vars[1].name, "AZURE_OPENAI_ENDPOINT");
5877 assert!(!vars[1].secret);
5878 assert!(!vars[1].optional);
5879 assert_eq!(vars[2].name, "AZURE_OPENAI_API_VERSION");
5881 assert!(!vars[2].secret);
5882 assert!(vars[2].optional);
5883 }
5884 _ => panic!("Expected EnvVar variant"),
5885 }
5886 }
5887
5888 #[cfg(feature = "unstable_auth_methods")]
5889 #[test]
5890 fn test_auth_method_terminal_serialization() {
5891 let method = AuthMethod::Terminal(AuthMethodTerminal::new("tui-auth", "Terminal Auth"));
5892
5893 let json = serde_json::to_value(&method).unwrap();
5894 assert_eq!(
5895 json,
5896 json!({
5897 "id": "tui-auth",
5898 "name": "Terminal Auth",
5899 "type": "terminal"
5900 })
5901 );
5902 assert!(!json.as_object().unwrap().contains_key("args"));
5904 assert!(!json.as_object().unwrap().contains_key("env"));
5905
5906 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5907 match deserialized {
5908 AuthMethod::Terminal(AuthMethodTerminal { args, env, .. }) => {
5909 assert!(args.is_empty());
5910 assert!(env.is_empty());
5911 }
5912 _ => panic!("Expected Terminal variant"),
5913 }
5914 }
5915
5916 #[cfg(feature = "unstable_auth_methods")]
5917 #[test]
5918 fn test_auth_method_terminal_with_args_and_env_serialization() {
5919 use std::collections::HashMap;
5920
5921 let mut env = HashMap::new();
5922 env.insert("TERM".to_string(), "xterm-256color".to_string());
5923
5924 let method = AuthMethod::Terminal(
5925 AuthMethodTerminal::new("tui-auth", "Terminal Auth")
5926 .args(vec!["--interactive".to_string(), "--color".to_string()])
5927 .env(env),
5928 );
5929
5930 let json = serde_json::to_value(&method).unwrap();
5931 assert_eq!(
5932 json,
5933 json!({
5934 "id": "tui-auth",
5935 "name": "Terminal Auth",
5936 "type": "terminal",
5937 "args": ["--interactive", "--color"],
5938 "env": {
5939 "TERM": "xterm-256color"
5940 }
5941 })
5942 );
5943
5944 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5945 match deserialized {
5946 AuthMethod::Terminal(AuthMethodTerminal { args, env, .. }) => {
5947 assert_eq!(args, vec!["--interactive", "--color"]);
5948 assert_eq!(env.len(), 1);
5949 assert_eq!(env.get("TERM").unwrap(), "xterm-256color");
5950 }
5951 _ => panic!("Expected Terminal variant"),
5952 }
5953 }
5954
5955 #[cfg(feature = "unstable_boolean_config")]
5956 #[test]
5957 fn test_session_config_option_value_id_serialize() {
5958 let val = SessionConfigOptionValue::value_id("model-1");
5959 let json = serde_json::to_value(&val).unwrap();
5960 assert_eq!(json, json!({ "value": "model-1" }));
5962 assert!(!json.as_object().unwrap().contains_key("type"));
5963 }
5964
5965 #[cfg(feature = "unstable_boolean_config")]
5966 #[test]
5967 fn test_session_config_option_value_boolean_serialize() {
5968 let val = SessionConfigOptionValue::boolean(true);
5969 let json = serde_json::to_value(&val).unwrap();
5970 assert_eq!(json, json!({ "type": "boolean", "value": true }));
5971 }
5972
5973 #[cfg(feature = "unstable_boolean_config")]
5974 #[test]
5975 fn test_session_config_option_value_deserialize_no_type() {
5976 let json = json!({ "value": "model-1" });
5978 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
5979 assert_eq!(val, SessionConfigOptionValue::value_id("model-1"));
5980 assert_eq!(val.as_value_id().unwrap().to_string(), "model-1");
5981 }
5982
5983 #[cfg(feature = "unstable_boolean_config")]
5984 #[test]
5985 fn test_session_config_option_value_deserialize_boolean() {
5986 let json = json!({ "type": "boolean", "value": true });
5987 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
5988 assert_eq!(val, SessionConfigOptionValue::boolean(true));
5989 assert_eq!(val.as_bool(), Some(true));
5990 }
5991
5992 #[cfg(feature = "unstable_boolean_config")]
5993 #[test]
5994 fn test_session_config_option_value_deserialize_boolean_false() {
5995 let json = json!({ "type": "boolean", "value": false });
5996 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
5997 assert_eq!(val, SessionConfigOptionValue::boolean(false));
5998 assert_eq!(val.as_bool(), Some(false));
5999 }
6000
6001 #[cfg(feature = "unstable_boolean_config")]
6002 #[test]
6003 fn test_session_config_option_value_deserialize_unknown_type_with_string_value() {
6004 let json = json!({ "type": "text", "value": "freeform input" });
6006 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
6007 assert_eq!(val.as_value_id().unwrap().to_string(), "freeform input");
6008 }
6009
6010 #[cfg(feature = "unstable_boolean_config")]
6011 #[test]
6012 fn test_session_config_option_value_roundtrip_value_id() {
6013 let original = SessionConfigOptionValue::value_id("option-a");
6014 let json = serde_json::to_value(&original).unwrap();
6015 let roundtripped: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
6016 assert_eq!(original, roundtripped);
6017 }
6018
6019 #[cfg(feature = "unstable_boolean_config")]
6020 #[test]
6021 fn test_session_config_option_value_roundtrip_boolean() {
6022 let original = SessionConfigOptionValue::boolean(false);
6023 let json = serde_json::to_value(&original).unwrap();
6024 let roundtripped: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
6025 assert_eq!(original, roundtripped);
6026 }
6027
6028 #[cfg(feature = "unstable_boolean_config")]
6029 #[test]
6030 fn test_session_config_option_value_type_mismatch_boolean_with_string() {
6031 let json = json!({ "type": "boolean", "value": "not a bool" });
6033 let result = serde_json::from_value::<SessionConfigOptionValue>(json);
6034 assert!(result.is_ok());
6036 assert_eq!(
6037 result.unwrap().as_value_id().unwrap().to_string(),
6038 "not a bool"
6039 );
6040 }
6041
6042 #[cfg(feature = "unstable_boolean_config")]
6043 #[test]
6044 fn test_session_config_option_value_from_impls() {
6045 let from_str: SessionConfigOptionValue = "model-1".into();
6046 assert_eq!(from_str.as_value_id().unwrap().to_string(), "model-1");
6047
6048 let from_id: SessionConfigOptionValue = SessionConfigValueId::new("model-2").into();
6049 assert_eq!(from_id.as_value_id().unwrap().to_string(), "model-2");
6050
6051 let from_bool: SessionConfigOptionValue = true.into();
6052 assert_eq!(from_bool.as_bool(), Some(true));
6053 }
6054
6055 #[cfg(feature = "unstable_boolean_config")]
6056 #[test]
6057 fn test_set_session_config_option_request_value_id() {
6058 let req = SetSessionConfigOptionRequest::new("sess_1", "model", "model-1");
6059 let json = serde_json::to_value(&req).unwrap();
6060 assert_eq!(
6061 json,
6062 json!({
6063 "sessionId": "sess_1",
6064 "configId": "model",
6065 "value": "model-1"
6066 })
6067 );
6068 assert!(!json.as_object().unwrap().contains_key("type"));
6070 }
6071
6072 #[cfg(feature = "unstable_boolean_config")]
6073 #[test]
6074 fn test_set_session_config_option_request_boolean() {
6075 let req = SetSessionConfigOptionRequest::new("sess_1", "brave_mode", true);
6076 let json = serde_json::to_value(&req).unwrap();
6077 assert_eq!(
6078 json,
6079 json!({
6080 "sessionId": "sess_1",
6081 "configId": "brave_mode",
6082 "type": "boolean",
6083 "value": true
6084 })
6085 );
6086 }
6087
6088 #[cfg(feature = "unstable_boolean_config")]
6089 #[test]
6090 fn test_set_session_config_option_request_deserialize_no_type() {
6091 let json = json!({
6093 "sessionId": "sess_1",
6094 "configId": "model",
6095 "value": "model-1"
6096 });
6097 let req: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
6098 assert_eq!(req.session_id.to_string(), "sess_1");
6099 assert_eq!(req.config_id.to_string(), "model");
6100 assert_eq!(req.value.as_value_id().unwrap().to_string(), "model-1");
6101 }
6102
6103 #[cfg(feature = "unstable_boolean_config")]
6104 #[test]
6105 fn test_set_session_config_option_request_deserialize_boolean() {
6106 let json = json!({
6107 "sessionId": "sess_1",
6108 "configId": "brave_mode",
6109 "type": "boolean",
6110 "value": true
6111 });
6112 let req: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
6113 assert_eq!(req.value.as_bool(), Some(true));
6114 }
6115
6116 #[cfg(feature = "unstable_boolean_config")]
6117 #[test]
6118 fn test_set_session_config_option_request_roundtrip_value_id() {
6119 let original = SetSessionConfigOptionRequest::new("s", "c", "v");
6120 let json = serde_json::to_value(&original).unwrap();
6121 let roundtripped: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
6122 assert_eq!(original, roundtripped);
6123 }
6124
6125 #[cfg(feature = "unstable_boolean_config")]
6126 #[test]
6127 fn test_set_session_config_option_request_roundtrip_boolean() {
6128 let original = SetSessionConfigOptionRequest::new("s", "c", false);
6129 let json = serde_json::to_value(&original).unwrap();
6130 let roundtripped: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
6131 assert_eq!(original, roundtripped);
6132 }
6133
6134 #[cfg(feature = "unstable_boolean_config")]
6135 #[test]
6136 fn test_session_config_boolean_serialization() {
6137 let cfg = SessionConfigBoolean::new(true);
6138 let json = serde_json::to_value(&cfg).unwrap();
6139 assert_eq!(json, json!({ "currentValue": true }));
6140
6141 let deserialized: SessionConfigBoolean = serde_json::from_value(json).unwrap();
6142 assert!(deserialized.current_value);
6143 }
6144
6145 #[cfg(feature = "unstable_boolean_config")]
6146 #[test]
6147 fn test_session_config_option_boolean_variant() {
6148 let opt = SessionConfigOption::boolean("brave_mode", "Brave Mode", false)
6149 .description("Skip confirmation prompts");
6150 let json = serde_json::to_value(&opt).unwrap();
6151 assert_eq!(
6152 json,
6153 json!({
6154 "id": "brave_mode",
6155 "name": "Brave Mode",
6156 "description": "Skip confirmation prompts",
6157 "type": "boolean",
6158 "currentValue": false
6159 })
6160 );
6161
6162 let deserialized: SessionConfigOption = serde_json::from_value(json).unwrap();
6163 assert_eq!(deserialized.id.to_string(), "brave_mode");
6164 assert_eq!(deserialized.name, "Brave Mode");
6165 match deserialized.kind {
6166 SessionConfigKind::Boolean(ref b) => assert!(!b.current_value),
6167 _ => panic!("Expected Boolean kind"),
6168 }
6169 }
6170
6171 #[cfg(feature = "unstable_boolean_config")]
6172 #[test]
6173 fn test_session_config_option_select_still_works() {
6174 let opt = SessionConfigOption::select(
6176 "model",
6177 "Model",
6178 "model-1",
6179 vec![
6180 SessionConfigSelectOption::new("model-1", "Model 1"),
6181 SessionConfigSelectOption::new("model-2", "Model 2"),
6182 ],
6183 );
6184 let json = serde_json::to_value(&opt).unwrap();
6185 assert_eq!(json["type"], "select");
6186 assert_eq!(json["currentValue"], "model-1");
6187 assert_eq!(json["options"].as_array().unwrap().len(), 2);
6188
6189 let deserialized: SessionConfigOption = serde_json::from_value(json).unwrap();
6190 match deserialized.kind {
6191 SessionConfigKind::Select(ref s) => {
6192 assert_eq!(s.current_value.to_string(), "model-1");
6193 }
6194 _ => panic!("Expected Select kind"),
6195 }
6196 }
6197
6198 #[cfg(feature = "unstable_llm_providers")]
6199 #[test]
6200 fn test_llm_protocol_known_variants() {
6201 assert_eq!(
6202 serde_json::to_value(&LlmProtocol::Anthropic).unwrap(),
6203 json!("anthropic")
6204 );
6205 assert_eq!(
6206 serde_json::to_value(&LlmProtocol::OpenAi).unwrap(),
6207 json!("openai")
6208 );
6209 assert_eq!(
6210 serde_json::to_value(&LlmProtocol::Azure).unwrap(),
6211 json!("azure")
6212 );
6213 assert_eq!(
6214 serde_json::to_value(&LlmProtocol::Vertex).unwrap(),
6215 json!("vertex")
6216 );
6217 assert_eq!(
6218 serde_json::to_value(&LlmProtocol::Bedrock).unwrap(),
6219 json!("bedrock")
6220 );
6221
6222 assert_eq!(
6223 serde_json::from_str::<LlmProtocol>("\"anthropic\"").unwrap(),
6224 LlmProtocol::Anthropic
6225 );
6226 assert_eq!(
6227 serde_json::from_str::<LlmProtocol>("\"openai\"").unwrap(),
6228 LlmProtocol::OpenAi
6229 );
6230 assert_eq!(
6231 serde_json::from_str::<LlmProtocol>("\"azure\"").unwrap(),
6232 LlmProtocol::Azure
6233 );
6234 assert_eq!(
6235 serde_json::from_str::<LlmProtocol>("\"vertex\"").unwrap(),
6236 LlmProtocol::Vertex
6237 );
6238 assert_eq!(
6239 serde_json::from_str::<LlmProtocol>("\"bedrock\"").unwrap(),
6240 LlmProtocol::Bedrock
6241 );
6242 }
6243
6244 #[cfg(feature = "unstable_llm_providers")]
6245 #[test]
6246 fn test_llm_protocol_unknown_variant() {
6247 let unknown: LlmProtocol = serde_json::from_str("\"cohere\"").unwrap();
6248 assert_eq!(unknown, LlmProtocol::Other("cohere".to_string()));
6249
6250 let json = serde_json::to_value(&unknown).unwrap();
6251 assert_eq!(json, json!("cohere"));
6252 }
6253
6254 #[cfg(feature = "unstable_llm_providers")]
6255 #[test]
6256 fn test_provider_current_config_serialization() {
6257 let config =
6258 ProviderCurrentConfig::new(LlmProtocol::Anthropic, "https://api.anthropic.com");
6259
6260 let json = serde_json::to_value(&config).unwrap();
6261 assert_eq!(
6262 json,
6263 json!({
6264 "apiType": "anthropic",
6265 "baseUrl": "https://api.anthropic.com"
6266 })
6267 );
6268
6269 let deserialized: ProviderCurrentConfig = serde_json::from_value(json).unwrap();
6270 assert_eq!(deserialized.api_type, LlmProtocol::Anthropic);
6271 assert_eq!(deserialized.base_url, "https://api.anthropic.com");
6272 }
6273
6274 #[cfg(feature = "unstable_llm_providers")]
6275 #[test]
6276 fn test_provider_info_with_current_config() {
6277 let info = ProviderInfo::new(
6278 "main",
6279 vec![LlmProtocol::Anthropic, LlmProtocol::OpenAi],
6280 true,
6281 Some(ProviderCurrentConfig::new(
6282 LlmProtocol::Anthropic,
6283 "https://api.anthropic.com",
6284 )),
6285 );
6286
6287 let json = serde_json::to_value(&info).unwrap();
6288 assert_eq!(
6289 json,
6290 json!({
6291 "id": "main",
6292 "supported": ["anthropic", "openai"],
6293 "required": true,
6294 "current": {
6295 "apiType": "anthropic",
6296 "baseUrl": "https://api.anthropic.com"
6297 }
6298 })
6299 );
6300
6301 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6302 assert_eq!(deserialized.id, "main");
6303 assert_eq!(deserialized.supported.len(), 2);
6304 assert!(deserialized.required);
6305 assert!(deserialized.current.is_some());
6306 assert_eq!(
6307 deserialized.current.as_ref().unwrap().api_type,
6308 LlmProtocol::Anthropic
6309 );
6310 }
6311
6312 #[cfg(feature = "unstable_llm_providers")]
6313 #[test]
6314 fn test_provider_info_disabled() {
6315 let info = ProviderInfo::new(
6316 "secondary",
6317 vec![LlmProtocol::OpenAi],
6318 false,
6319 None::<ProviderCurrentConfig>,
6320 );
6321
6322 let json = serde_json::to_value(&info).unwrap();
6323 assert_eq!(
6324 json,
6325 json!({
6326 "id": "secondary",
6327 "supported": ["openai"],
6328 "required": false
6329 })
6330 );
6331
6332 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6333 assert_eq!(deserialized.id, "secondary");
6334 assert!(!deserialized.required);
6335 assert!(deserialized.current.is_none());
6336 }
6337
6338 #[cfg(feature = "unstable_llm_providers")]
6339 #[test]
6340 fn test_provider_info_missing_current_defaults_to_none() {
6341 let json = json!({
6343 "id": "main",
6344 "supported": ["anthropic"],
6345 "required": true
6346 });
6347 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6348 assert!(deserialized.current.is_none());
6349 }
6350
6351 #[cfg(feature = "unstable_llm_providers")]
6352 #[test]
6353 fn test_provider_info_explicit_null_current_decodes_to_none() {
6354 let json = json!({
6358 "id": "main",
6359 "supported": ["anthropic"],
6360 "required": true,
6361 "current": null
6362 });
6363 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6364 assert!(deserialized.current.is_none());
6365 }
6366
6367 #[cfg(feature = "unstable_llm_providers")]
6368 #[test]
6369 fn test_list_providers_response_serialization() {
6370 let response = ListProvidersResponse::new(vec![ProviderInfo::new(
6371 "main",
6372 vec![LlmProtocol::Anthropic],
6373 true,
6374 Some(ProviderCurrentConfig::new(
6375 LlmProtocol::Anthropic,
6376 "https://api.anthropic.com",
6377 )),
6378 )]);
6379
6380 let json = serde_json::to_value(&response).unwrap();
6381 assert_eq!(json["providers"].as_array().unwrap().len(), 1);
6382 assert_eq!(json["providers"][0]["id"], "main");
6383
6384 let deserialized: ListProvidersResponse = serde_json::from_value(json).unwrap();
6385 assert_eq!(deserialized.providers.len(), 1);
6386 }
6387
6388 #[cfg(feature = "unstable_llm_providers")]
6389 #[test]
6390 fn test_set_provider_request_serialization() {
6391 use std::collections::HashMap;
6392
6393 let mut headers = HashMap::new();
6394 headers.insert("Authorization".to_string(), "Bearer sk-test".to_string());
6395
6396 let request =
6397 SetProviderRequest::new("main", LlmProtocol::OpenAi, "https://api.openai.com/v1")
6398 .headers(headers);
6399
6400 let json = serde_json::to_value(&request).unwrap();
6401 assert_eq!(
6402 json,
6403 json!({
6404 "id": "main",
6405 "apiType": "openai",
6406 "baseUrl": "https://api.openai.com/v1",
6407 "headers": {
6408 "Authorization": "Bearer sk-test"
6409 }
6410 })
6411 );
6412
6413 let deserialized: SetProviderRequest = serde_json::from_value(json).unwrap();
6414 assert_eq!(deserialized.id, "main");
6415 assert_eq!(deserialized.api_type, LlmProtocol::OpenAi);
6416 assert_eq!(deserialized.base_url, "https://api.openai.com/v1");
6417 assert_eq!(deserialized.headers.len(), 1);
6418 assert_eq!(
6419 deserialized.headers.get("Authorization").unwrap(),
6420 "Bearer sk-test"
6421 );
6422 }
6423
6424 #[cfg(feature = "unstable_llm_providers")]
6425 #[test]
6426 fn test_set_provider_request_omits_empty_headers() {
6427 let request =
6428 SetProviderRequest::new("main", LlmProtocol::Anthropic, "https://api.anthropic.com");
6429
6430 let json = serde_json::to_value(&request).unwrap();
6431 assert!(!json.as_object().unwrap().contains_key("headers"));
6433 }
6434
6435 #[cfg(feature = "unstable_llm_providers")]
6436 #[test]
6437 fn test_disable_provider_request_serialization() {
6438 let request = DisableProviderRequest::new("secondary");
6439
6440 let json = serde_json::to_value(&request).unwrap();
6441 assert_eq!(json, json!({ "id": "secondary" }));
6442
6443 let deserialized: DisableProviderRequest = serde_json::from_value(json).unwrap();
6444 assert_eq!(deserialized.id, "secondary");
6445 }
6446
6447 #[cfg(feature = "unstable_llm_providers")]
6448 #[test]
6449 fn test_providers_capabilities_serialization() {
6450 let caps = ProvidersCapabilities::new();
6451
6452 let json = serde_json::to_value(&caps).unwrap();
6453 assert_eq!(json, json!({}));
6454
6455 let deserialized: ProvidersCapabilities = serde_json::from_value(json).unwrap();
6456 assert!(deserialized.meta.is_none());
6457 }
6458
6459 #[cfg(feature = "unstable_llm_providers")]
6460 #[test]
6461 fn test_agent_capabilities_with_providers() {
6462 let caps = AgentCapabilities::new().providers(ProvidersCapabilities::new());
6463
6464 let json = serde_json::to_value(&caps).unwrap();
6465 assert_eq!(json["providers"], json!({}));
6466
6467 let deserialized: AgentCapabilities = serde_json::from_value(json).unwrap();
6468 assert!(deserialized.providers.is_some());
6469 }
6470}