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#[cfg(feature = "unstable_logout")]
346#[skip_serializing_none]
347#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
348#[schemars(extend("x-side" = "agent", "x-method" = LOGOUT_METHOD_NAME))]
349#[serde(rename_all = "camelCase")]
350#[non_exhaustive]
351pub struct LogoutRequest {
352 #[serde(rename = "_meta")]
358 pub meta: Option<Meta>,
359}
360
361#[cfg(feature = "unstable_logout")]
362impl LogoutRequest {
363 #[must_use]
364 pub fn new() -> Self {
365 Self::default()
366 }
367
368 #[must_use]
374 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
375 self.meta = meta.into_option();
376 self
377 }
378}
379
380#[cfg(feature = "unstable_logout")]
386#[skip_serializing_none]
387#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
388#[schemars(extend("x-side" = "agent", "x-method" = LOGOUT_METHOD_NAME))]
389#[serde(rename_all = "camelCase")]
390#[non_exhaustive]
391pub struct LogoutResponse {
392 #[serde(rename = "_meta")]
398 pub meta: Option<Meta>,
399}
400
401#[cfg(feature = "unstable_logout")]
402impl LogoutResponse {
403 #[must_use]
404 pub fn new() -> Self {
405 Self::default()
406 }
407
408 #[must_use]
414 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
415 self.meta = meta.into_option();
416 self
417 }
418}
419
420#[cfg(feature = "unstable_logout")]
426#[serde_as]
427#[skip_serializing_none]
428#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
429#[serde(rename_all = "camelCase")]
430#[non_exhaustive]
431pub struct AgentAuthCapabilities {
432 #[serde_as(deserialize_as = "DefaultOnError")]
436 #[serde(default)]
437 pub logout: Option<LogoutCapabilities>,
438 #[serde(rename = "_meta")]
444 pub meta: Option<Meta>,
445}
446
447#[cfg(feature = "unstable_logout")]
448impl AgentAuthCapabilities {
449 #[must_use]
450 pub fn new() -> Self {
451 Self::default()
452 }
453
454 #[must_use]
456 pub fn logout(mut self, logout: impl IntoOption<LogoutCapabilities>) -> Self {
457 self.logout = logout.into_option();
458 self
459 }
460
461 #[must_use]
467 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
468 self.meta = meta.into_option();
469 self
470 }
471}
472
473#[cfg(feature = "unstable_logout")]
481#[skip_serializing_none]
482#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
483#[non_exhaustive]
484pub struct LogoutCapabilities {
485 #[serde(rename = "_meta")]
491 pub meta: Option<Meta>,
492}
493
494#[cfg(feature = "unstable_logout")]
495impl LogoutCapabilities {
496 #[must_use]
497 pub fn new() -> Self {
498 Self::default()
499 }
500
501 #[must_use]
507 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
508 self.meta = meta.into_option();
509 self
510 }
511}
512
513#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
514#[serde(transparent)]
515#[from(Arc<str>, String, &'static str)]
516#[non_exhaustive]
517pub struct AuthMethodId(pub Arc<str>);
518
519impl AuthMethodId {
520 #[must_use]
521 pub fn new(id: impl Into<Arc<str>>) -> Self {
522 Self(id.into())
523 }
524}
525
526#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
531#[serde(tag = "type", rename_all = "snake_case")]
532#[non_exhaustive]
533pub enum AuthMethod {
534 #[cfg(feature = "unstable_auth_methods")]
540 EnvVar(AuthMethodEnvVar),
541 #[cfg(feature = "unstable_auth_methods")]
547 Terminal(AuthMethodTerminal),
548 #[serde(untagged)]
552 Agent(AuthMethodAgent),
553}
554
555impl AuthMethod {
556 #[must_use]
558 pub fn id(&self) -> &AuthMethodId {
559 match self {
560 Self::Agent(a) => &a.id,
561 #[cfg(feature = "unstable_auth_methods")]
562 Self::EnvVar(e) => &e.id,
563 #[cfg(feature = "unstable_auth_methods")]
564 Self::Terminal(t) => &t.id,
565 }
566 }
567
568 #[must_use]
570 pub fn name(&self) -> &str {
571 match self {
572 Self::Agent(a) => &a.name,
573 #[cfg(feature = "unstable_auth_methods")]
574 Self::EnvVar(e) => &e.name,
575 #[cfg(feature = "unstable_auth_methods")]
576 Self::Terminal(t) => &t.name,
577 }
578 }
579
580 #[must_use]
582 pub fn description(&self) -> Option<&str> {
583 match self {
584 Self::Agent(a) => a.description.as_deref(),
585 #[cfg(feature = "unstable_auth_methods")]
586 Self::EnvVar(e) => e.description.as_deref(),
587 #[cfg(feature = "unstable_auth_methods")]
588 Self::Terminal(t) => t.description.as_deref(),
589 }
590 }
591
592 #[must_use]
598 pub fn meta(&self) -> Option<&Meta> {
599 match self {
600 Self::Agent(a) => a.meta.as_ref(),
601 #[cfg(feature = "unstable_auth_methods")]
602 Self::EnvVar(e) => e.meta.as_ref(),
603 #[cfg(feature = "unstable_auth_methods")]
604 Self::Terminal(t) => t.meta.as_ref(),
605 }
606 }
607}
608
609#[skip_serializing_none]
613#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
614#[serde(rename_all = "camelCase")]
615#[non_exhaustive]
616pub struct AuthMethodAgent {
617 pub id: AuthMethodId,
619 pub name: String,
621 pub description: Option<String>,
623 #[serde(rename = "_meta")]
629 pub meta: Option<Meta>,
630}
631
632impl AuthMethodAgent {
633 #[must_use]
634 pub fn new(id: impl Into<AuthMethodId>, name: impl Into<String>) -> Self {
635 Self {
636 id: id.into(),
637 name: name.into(),
638 description: None,
639 meta: None,
640 }
641 }
642
643 #[must_use]
645 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
646 self.description = description.into_option();
647 self
648 }
649
650 #[must_use]
656 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
657 self.meta = meta.into_option();
658 self
659 }
660}
661
662#[cfg(feature = "unstable_auth_methods")]
670#[skip_serializing_none]
671#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
672#[serde(rename_all = "camelCase")]
673#[non_exhaustive]
674pub struct AuthMethodEnvVar {
675 pub id: AuthMethodId,
677 pub name: String,
679 pub description: Option<String>,
681 pub vars: Vec<AuthEnvVar>,
683 pub link: Option<String>,
685 #[serde(rename = "_meta")]
691 pub meta: Option<Meta>,
692}
693
694#[cfg(feature = "unstable_auth_methods")]
695impl AuthMethodEnvVar {
696 #[must_use]
697 pub fn new(
698 id: impl Into<AuthMethodId>,
699 name: impl Into<String>,
700 vars: Vec<AuthEnvVar>,
701 ) -> Self {
702 Self {
703 id: id.into(),
704 name: name.into(),
705 description: None,
706 vars,
707 link: None,
708 meta: None,
709 }
710 }
711
712 #[must_use]
714 pub fn link(mut self, link: impl IntoOption<String>) -> Self {
715 self.link = link.into_option();
716 self
717 }
718
719 #[must_use]
721 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
722 self.description = description.into_option();
723 self
724 }
725
726 #[must_use]
732 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
733 self.meta = meta.into_option();
734 self
735 }
736}
737
738#[cfg(feature = "unstable_auth_methods")]
744#[skip_serializing_none]
745#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
746#[serde(rename_all = "camelCase")]
747#[non_exhaustive]
748pub struct AuthEnvVar {
749 pub name: String,
751 pub label: Option<String>,
753 #[serde(default = "default_true", skip_serializing_if = "is_true")]
758 #[schemars(extend("default" = true))]
759 pub secret: bool,
760 #[serde(default, skip_serializing_if = "is_false")]
764 #[schemars(extend("default" = false))]
765 pub optional: bool,
766 #[serde(rename = "_meta")]
772 pub meta: Option<Meta>,
773}
774
775#[cfg(feature = "unstable_auth_methods")]
776fn default_true() -> bool {
777 true
778}
779
780#[cfg(feature = "unstable_auth_methods")]
781#[expect(clippy::trivially_copy_pass_by_ref)]
782fn is_true(v: &bool) -> bool {
783 *v
784}
785
786#[cfg(feature = "unstable_auth_methods")]
787#[expect(clippy::trivially_copy_pass_by_ref)]
788fn is_false(v: &bool) -> bool {
789 !*v
790}
791
792#[cfg(feature = "unstable_auth_methods")]
793impl AuthEnvVar {
794 #[must_use]
796 pub fn new(name: impl Into<String>) -> Self {
797 Self {
798 name: name.into(),
799 label: None,
800 secret: true,
801 optional: false,
802 meta: None,
803 }
804 }
805
806 #[must_use]
808 pub fn label(mut self, label: impl IntoOption<String>) -> Self {
809 self.label = label.into_option();
810 self
811 }
812
813 #[must_use]
816 pub fn secret(mut self, secret: bool) -> Self {
817 self.secret = secret;
818 self
819 }
820
821 #[must_use]
823 pub fn optional(mut self, optional: bool) -> Self {
824 self.optional = optional;
825 self
826 }
827
828 #[must_use]
834 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
835 self.meta = meta.into_option();
836 self
837 }
838}
839
840#[cfg(feature = "unstable_auth_methods")]
848#[skip_serializing_none]
849#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
850#[serde(rename_all = "camelCase")]
851#[non_exhaustive]
852pub struct AuthMethodTerminal {
853 pub id: AuthMethodId,
855 pub name: String,
857 pub description: Option<String>,
859 #[serde(default, skip_serializing_if = "Vec::is_empty")]
861 pub args: Vec<String>,
862 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
864 pub env: HashMap<String, String>,
865 #[serde(rename = "_meta")]
871 pub meta: Option<Meta>,
872}
873
874#[cfg(feature = "unstable_auth_methods")]
875impl AuthMethodTerminal {
876 #[must_use]
877 pub fn new(id: impl Into<AuthMethodId>, name: impl Into<String>) -> Self {
878 Self {
879 id: id.into(),
880 name: name.into(),
881 description: None,
882 args: Vec::new(),
883 env: HashMap::new(),
884 meta: None,
885 }
886 }
887
888 #[must_use]
890 pub fn args(mut self, args: Vec<String>) -> Self {
891 self.args = args;
892 self
893 }
894
895 #[must_use]
897 pub fn env(mut self, env: HashMap<String, String>) -> Self {
898 self.env = env;
899 self
900 }
901
902 #[must_use]
904 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
905 self.description = description.into_option();
906 self
907 }
908
909 #[must_use]
915 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
916 self.meta = meta.into_option();
917 self
918 }
919}
920
921#[skip_serializing_none]
927#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
928#[schemars(extend("x-side" = "agent", "x-method" = SESSION_NEW_METHOD_NAME))]
929#[serde(rename_all = "camelCase")]
930#[non_exhaustive]
931pub struct NewSessionRequest {
932 pub cwd: PathBuf,
934 #[cfg(feature = "unstable_session_additional_directories")]
944 #[serde(default, skip_serializing_if = "Vec::is_empty")]
945 pub additional_directories: Vec<PathBuf>,
946 pub mcp_servers: Vec<McpServer>,
948 #[serde(rename = "_meta")]
954 pub meta: Option<Meta>,
955}
956
957impl NewSessionRequest {
958 #[must_use]
959 pub fn new(cwd: impl Into<PathBuf>) -> Self {
960 Self {
961 cwd: cwd.into(),
962 #[cfg(feature = "unstable_session_additional_directories")]
963 additional_directories: vec![],
964 mcp_servers: vec![],
965 meta: None,
966 }
967 }
968
969 #[cfg(feature = "unstable_session_additional_directories")]
975 #[must_use]
976 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
977 self.additional_directories = additional_directories;
978 self
979 }
980
981 #[must_use]
983 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
984 self.mcp_servers = mcp_servers;
985 self
986 }
987
988 #[must_use]
994 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
995 self.meta = meta.into_option();
996 self
997 }
998}
999
1000#[serde_as]
1004#[skip_serializing_none]
1005#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1006#[schemars(extend("x-side" = "agent", "x-method" = SESSION_NEW_METHOD_NAME))]
1007#[serde(rename_all = "camelCase")]
1008#[non_exhaustive]
1009pub struct NewSessionResponse {
1010 pub session_id: SessionId,
1014 #[serde_as(deserialize_as = "DefaultOnError")]
1018 #[serde(default)]
1019 pub modes: Option<SessionModeState>,
1020 #[cfg(feature = "unstable_session_model")]
1026 #[serde_as(deserialize_as = "DefaultOnError")]
1027 #[serde(default)]
1028 pub models: Option<SessionModelState>,
1029 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1031 #[serde(default)]
1032 pub config_options: Option<Vec<SessionConfigOption>>,
1033 #[serde(rename = "_meta")]
1039 pub meta: Option<Meta>,
1040}
1041
1042impl NewSessionResponse {
1043 #[must_use]
1044 pub fn new(session_id: impl Into<SessionId>) -> Self {
1045 Self {
1046 session_id: session_id.into(),
1047 modes: None,
1048 #[cfg(feature = "unstable_session_model")]
1049 models: None,
1050 config_options: None,
1051 meta: None,
1052 }
1053 }
1054
1055 #[must_use]
1059 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1060 self.modes = modes.into_option();
1061 self
1062 }
1063
1064 #[cfg(feature = "unstable_session_model")]
1070 #[must_use]
1071 pub fn models(mut self, models: impl IntoOption<SessionModelState>) -> Self {
1072 self.models = models.into_option();
1073 self
1074 }
1075
1076 #[must_use]
1078 pub fn config_options(
1079 mut self,
1080 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1081 ) -> Self {
1082 self.config_options = config_options.into_option();
1083 self
1084 }
1085
1086 #[must_use]
1092 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1093 self.meta = meta.into_option();
1094 self
1095 }
1096}
1097
1098#[skip_serializing_none]
1106#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1107#[schemars(extend("x-side" = "agent", "x-method" = SESSION_LOAD_METHOD_NAME))]
1108#[serde(rename_all = "camelCase")]
1109#[non_exhaustive]
1110pub struct LoadSessionRequest {
1111 pub mcp_servers: Vec<McpServer>,
1113 pub cwd: PathBuf,
1115 #[cfg(feature = "unstable_session_additional_directories")]
1126 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1127 pub additional_directories: Vec<PathBuf>,
1128 pub session_id: SessionId,
1130 #[serde(rename = "_meta")]
1136 pub meta: Option<Meta>,
1137}
1138
1139impl LoadSessionRequest {
1140 #[must_use]
1141 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1142 Self {
1143 mcp_servers: vec![],
1144 cwd: cwd.into(),
1145 #[cfg(feature = "unstable_session_additional_directories")]
1146 additional_directories: vec![],
1147 session_id: session_id.into(),
1148 meta: None,
1149 }
1150 }
1151
1152 #[cfg(feature = "unstable_session_additional_directories")]
1158 #[must_use]
1159 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1160 self.additional_directories = additional_directories;
1161 self
1162 }
1163
1164 #[must_use]
1166 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1167 self.mcp_servers = mcp_servers;
1168 self
1169 }
1170
1171 #[must_use]
1177 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1178 self.meta = meta.into_option();
1179 self
1180 }
1181}
1182
1183#[serde_as]
1185#[skip_serializing_none]
1186#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1187#[schemars(extend("x-side" = "agent", "x-method" = SESSION_LOAD_METHOD_NAME))]
1188#[serde(rename_all = "camelCase")]
1189#[non_exhaustive]
1190pub struct LoadSessionResponse {
1191 #[serde_as(deserialize_as = "DefaultOnError")]
1195 #[serde(default)]
1196 pub modes: Option<SessionModeState>,
1197 #[cfg(feature = "unstable_session_model")]
1203 #[serde_as(deserialize_as = "DefaultOnError")]
1204 #[serde(default)]
1205 pub models: Option<SessionModelState>,
1206 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1208 #[serde(default)]
1209 pub config_options: Option<Vec<SessionConfigOption>>,
1210 #[serde(rename = "_meta")]
1216 pub meta: Option<Meta>,
1217}
1218
1219impl LoadSessionResponse {
1220 #[must_use]
1221 pub fn new() -> Self {
1222 Self::default()
1223 }
1224
1225 #[must_use]
1229 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1230 self.modes = modes.into_option();
1231 self
1232 }
1233
1234 #[cfg(feature = "unstable_session_model")]
1240 #[must_use]
1241 pub fn models(mut self, models: impl IntoOption<SessionModelState>) -> Self {
1242 self.models = models.into_option();
1243 self
1244 }
1245
1246 #[must_use]
1248 pub fn config_options(
1249 mut self,
1250 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1251 ) -> Self {
1252 self.config_options = config_options.into_option();
1253 self
1254 }
1255
1256 #[must_use]
1262 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1263 self.meta = meta.into_option();
1264 self
1265 }
1266}
1267
1268#[cfg(feature = "unstable_session_fork")]
1281#[skip_serializing_none]
1282#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1283#[schemars(extend("x-side" = "agent", "x-method" = SESSION_FORK_METHOD_NAME))]
1284#[serde(rename_all = "camelCase")]
1285#[non_exhaustive]
1286pub struct ForkSessionRequest {
1287 pub session_id: SessionId,
1289 pub cwd: PathBuf,
1291 #[cfg(feature = "unstable_session_additional_directories")]
1301 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1302 pub additional_directories: Vec<PathBuf>,
1303 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1305 pub mcp_servers: Vec<McpServer>,
1306 #[serde(rename = "_meta")]
1312 pub meta: Option<Meta>,
1313}
1314
1315#[cfg(feature = "unstable_session_fork")]
1316impl ForkSessionRequest {
1317 #[must_use]
1318 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1319 Self {
1320 session_id: session_id.into(),
1321 cwd: cwd.into(),
1322 #[cfg(feature = "unstable_session_additional_directories")]
1323 additional_directories: vec![],
1324 mcp_servers: vec![],
1325 meta: None,
1326 }
1327 }
1328
1329 #[cfg(feature = "unstable_session_additional_directories")]
1335 #[must_use]
1336 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1337 self.additional_directories = additional_directories;
1338 self
1339 }
1340
1341 #[must_use]
1343 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1344 self.mcp_servers = mcp_servers;
1345 self
1346 }
1347
1348 #[must_use]
1354 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1355 self.meta = meta.into_option();
1356 self
1357 }
1358}
1359
1360#[cfg(feature = "unstable_session_fork")]
1366#[serde_as]
1367#[skip_serializing_none]
1368#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1369#[schemars(extend("x-side" = "agent", "x-method" = SESSION_FORK_METHOD_NAME))]
1370#[serde(rename_all = "camelCase")]
1371#[non_exhaustive]
1372pub struct ForkSessionResponse {
1373 pub session_id: SessionId,
1375 #[serde_as(deserialize_as = "DefaultOnError")]
1379 #[serde(default)]
1380 pub modes: Option<SessionModeState>,
1381 #[cfg(feature = "unstable_session_model")]
1387 #[serde_as(deserialize_as = "DefaultOnError")]
1388 #[serde(default)]
1389 pub models: Option<SessionModelState>,
1390 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1392 #[serde(default)]
1393 pub config_options: Option<Vec<SessionConfigOption>>,
1394 #[serde(rename = "_meta")]
1400 pub meta: Option<Meta>,
1401}
1402
1403#[cfg(feature = "unstable_session_fork")]
1404impl ForkSessionResponse {
1405 #[must_use]
1406 pub fn new(session_id: impl Into<SessionId>) -> Self {
1407 Self {
1408 session_id: session_id.into(),
1409 modes: None,
1410 #[cfg(feature = "unstable_session_model")]
1411 models: None,
1412 config_options: None,
1413 meta: None,
1414 }
1415 }
1416
1417 #[must_use]
1421 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1422 self.modes = modes.into_option();
1423 self
1424 }
1425
1426 #[cfg(feature = "unstable_session_model")]
1432 #[must_use]
1433 pub fn models(mut self, models: impl IntoOption<SessionModelState>) -> Self {
1434 self.models = models.into_option();
1435 self
1436 }
1437
1438 #[must_use]
1440 pub fn config_options(
1441 mut self,
1442 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1443 ) -> Self {
1444 self.config_options = config_options.into_option();
1445 self
1446 }
1447
1448 #[must_use]
1454 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1455 self.meta = meta.into_option();
1456 self
1457 }
1458}
1459
1460#[skip_serializing_none]
1469#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1470#[schemars(extend("x-side" = "agent", "x-method" = SESSION_RESUME_METHOD_NAME))]
1471#[serde(rename_all = "camelCase")]
1472#[non_exhaustive]
1473pub struct ResumeSessionRequest {
1474 pub session_id: SessionId,
1476 pub cwd: PathBuf,
1478 #[cfg(feature = "unstable_session_additional_directories")]
1489 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1490 pub additional_directories: Vec<PathBuf>,
1491 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1493 pub mcp_servers: Vec<McpServer>,
1494 #[serde(rename = "_meta")]
1500 pub meta: Option<Meta>,
1501}
1502
1503impl ResumeSessionRequest {
1504 #[must_use]
1505 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1506 Self {
1507 session_id: session_id.into(),
1508 cwd: cwd.into(),
1509 #[cfg(feature = "unstable_session_additional_directories")]
1510 additional_directories: vec![],
1511 mcp_servers: vec![],
1512 meta: None,
1513 }
1514 }
1515
1516 #[cfg(feature = "unstable_session_additional_directories")]
1522 #[must_use]
1523 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1524 self.additional_directories = additional_directories;
1525 self
1526 }
1527
1528 #[must_use]
1530 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1531 self.mcp_servers = mcp_servers;
1532 self
1533 }
1534
1535 #[must_use]
1541 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1542 self.meta = meta.into_option();
1543 self
1544 }
1545}
1546
1547#[serde_as]
1549#[skip_serializing_none]
1550#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1551#[schemars(extend("x-side" = "agent", "x-method" = SESSION_RESUME_METHOD_NAME))]
1552#[serde(rename_all = "camelCase")]
1553#[non_exhaustive]
1554pub struct ResumeSessionResponse {
1555 #[serde_as(deserialize_as = "DefaultOnError")]
1559 #[serde(default)]
1560 pub modes: Option<SessionModeState>,
1561 #[cfg(feature = "unstable_session_model")]
1567 #[serde_as(deserialize_as = "DefaultOnError")]
1568 #[serde(default)]
1569 pub models: Option<SessionModelState>,
1570 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1572 #[serde(default)]
1573 pub config_options: Option<Vec<SessionConfigOption>>,
1574 #[serde(rename = "_meta")]
1580 pub meta: Option<Meta>,
1581}
1582
1583impl ResumeSessionResponse {
1584 #[must_use]
1585 pub fn new() -> Self {
1586 Self::default()
1587 }
1588
1589 #[must_use]
1593 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1594 self.modes = modes.into_option();
1595 self
1596 }
1597
1598 #[cfg(feature = "unstable_session_model")]
1604 #[must_use]
1605 pub fn models(mut self, models: impl IntoOption<SessionModelState>) -> Self {
1606 self.models = models.into_option();
1607 self
1608 }
1609
1610 #[must_use]
1612 pub fn config_options(
1613 mut self,
1614 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1615 ) -> Self {
1616 self.config_options = config_options.into_option();
1617 self
1618 }
1619
1620 #[must_use]
1626 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1627 self.meta = meta.into_option();
1628 self
1629 }
1630}
1631
1632#[skip_serializing_none]
1642#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1643#[schemars(extend("x-side" = "agent", "x-method" = SESSION_CLOSE_METHOD_NAME))]
1644#[serde(rename_all = "camelCase")]
1645#[non_exhaustive]
1646pub struct CloseSessionRequest {
1647 pub session_id: SessionId,
1649 #[serde(rename = "_meta")]
1655 pub meta: Option<Meta>,
1656}
1657
1658impl CloseSessionRequest {
1659 #[must_use]
1660 pub fn new(session_id: impl Into<SessionId>) -> Self {
1661 Self {
1662 session_id: session_id.into(),
1663 meta: None,
1664 }
1665 }
1666
1667 #[must_use]
1673 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1674 self.meta = meta.into_option();
1675 self
1676 }
1677}
1678
1679#[skip_serializing_none]
1681#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1682#[schemars(extend("x-side" = "agent", "x-method" = SESSION_CLOSE_METHOD_NAME))]
1683#[serde(rename_all = "camelCase")]
1684#[non_exhaustive]
1685pub struct CloseSessionResponse {
1686 #[serde(rename = "_meta")]
1692 pub meta: Option<Meta>,
1693}
1694
1695impl CloseSessionResponse {
1696 #[must_use]
1697 pub fn new() -> Self {
1698 Self::default()
1699 }
1700
1701 #[must_use]
1707 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1708 self.meta = meta.into_option();
1709 self
1710 }
1711}
1712
1713#[skip_serializing_none]
1719#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1720#[schemars(extend("x-side" = "agent", "x-method" = SESSION_LIST_METHOD_NAME))]
1721#[serde(rename_all = "camelCase")]
1722#[non_exhaustive]
1723pub struct ListSessionsRequest {
1724 pub cwd: Option<PathBuf>,
1726 pub cursor: Option<String>,
1728 #[serde(rename = "_meta")]
1734 pub meta: Option<Meta>,
1735}
1736
1737impl ListSessionsRequest {
1738 #[must_use]
1739 pub fn new() -> Self {
1740 Self::default()
1741 }
1742
1743 #[must_use]
1745 pub fn cwd(mut self, cwd: impl IntoOption<PathBuf>) -> Self {
1746 self.cwd = cwd.into_option();
1747 self
1748 }
1749
1750 #[must_use]
1752 pub fn cursor(mut self, cursor: impl IntoOption<String>) -> Self {
1753 self.cursor = cursor.into_option();
1754 self
1755 }
1756
1757 #[must_use]
1763 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1764 self.meta = meta.into_option();
1765 self
1766 }
1767}
1768
1769#[serde_as]
1771#[skip_serializing_none]
1772#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1773#[schemars(extend("x-side" = "agent", "x-method" = SESSION_LIST_METHOD_NAME))]
1774#[serde(rename_all = "camelCase")]
1775#[non_exhaustive]
1776pub struct ListSessionsResponse {
1777 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1779 pub sessions: Vec<SessionInfo>,
1780 pub next_cursor: Option<String>,
1783 #[serde(rename = "_meta")]
1789 pub meta: Option<Meta>,
1790}
1791
1792impl ListSessionsResponse {
1793 #[must_use]
1794 pub fn new(sessions: Vec<SessionInfo>) -> Self {
1795 Self {
1796 sessions,
1797 next_cursor: None,
1798 meta: None,
1799 }
1800 }
1801
1802 #[must_use]
1803 pub fn next_cursor(mut self, next_cursor: impl IntoOption<String>) -> Self {
1804 self.next_cursor = next_cursor.into_option();
1805 self
1806 }
1807
1808 #[must_use]
1814 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1815 self.meta = meta.into_option();
1816 self
1817 }
1818}
1819
1820#[cfg(feature = "unstable_session_delete")]
1830#[skip_serializing_none]
1831#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1832#[schemars(extend("x-side" = "agent", "x-method" = SESSION_DELETE_METHOD_NAME))]
1833#[serde(rename_all = "camelCase")]
1834#[non_exhaustive]
1835pub struct DeleteSessionRequest {
1836 pub session_id: SessionId,
1838 #[serde(rename = "_meta")]
1844 pub meta: Option<Meta>,
1845}
1846
1847#[cfg(feature = "unstable_session_delete")]
1848impl DeleteSessionRequest {
1849 #[must_use]
1850 pub fn new(session_id: impl Into<SessionId>) -> Self {
1851 Self {
1852 session_id: session_id.into(),
1853 meta: None,
1854 }
1855 }
1856
1857 #[must_use]
1863 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1864 self.meta = meta.into_option();
1865 self
1866 }
1867}
1868
1869#[cfg(feature = "unstable_session_delete")]
1875#[skip_serializing_none]
1876#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1877#[schemars(extend("x-side" = "agent", "x-method" = SESSION_DELETE_METHOD_NAME))]
1878#[serde(rename_all = "camelCase")]
1879#[non_exhaustive]
1880pub struct DeleteSessionResponse {
1881 #[serde(rename = "_meta")]
1887 pub meta: Option<Meta>,
1888}
1889
1890#[cfg(feature = "unstable_session_delete")]
1891impl DeleteSessionResponse {
1892 #[must_use]
1893 pub fn new() -> Self {
1894 Self::default()
1895 }
1896
1897 #[must_use]
1903 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1904 self.meta = meta.into_option();
1905 self
1906 }
1907}
1908
1909#[serde_as]
1911#[skip_serializing_none]
1912#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1913#[serde(rename_all = "camelCase")]
1914#[non_exhaustive]
1915pub struct SessionInfo {
1916 pub session_id: SessionId,
1918 pub cwd: PathBuf,
1920 #[cfg(feature = "unstable_session_additional_directories")]
1930 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1931 pub additional_directories: Vec<PathBuf>,
1932
1933 #[serde_as(deserialize_as = "DefaultOnError")]
1935 #[serde(default)]
1936 pub title: Option<String>,
1937 #[serde_as(deserialize_as = "DefaultOnError")]
1939 #[serde(default)]
1940 pub updated_at: Option<String>,
1941 #[serde(rename = "_meta")]
1947 pub meta: Option<Meta>,
1948}
1949
1950impl SessionInfo {
1951 #[must_use]
1952 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1953 Self {
1954 session_id: session_id.into(),
1955 cwd: cwd.into(),
1956 #[cfg(feature = "unstable_session_additional_directories")]
1957 additional_directories: vec![],
1958 title: None,
1959 updated_at: None,
1960 meta: None,
1961 }
1962 }
1963
1964 #[cfg(feature = "unstable_session_additional_directories")]
1970 #[must_use]
1971 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1972 self.additional_directories = additional_directories;
1973 self
1974 }
1975
1976 #[must_use]
1978 pub fn title(mut self, title: impl IntoOption<String>) -> Self {
1979 self.title = title.into_option();
1980 self
1981 }
1982
1983 #[must_use]
1985 pub fn updated_at(mut self, updated_at: impl IntoOption<String>) -> Self {
1986 self.updated_at = updated_at.into_option();
1987 self
1988 }
1989
1990 #[must_use]
1996 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1997 self.meta = meta.into_option();
1998 self
1999 }
2000}
2001
2002#[serde_as]
2006#[skip_serializing_none]
2007#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2008#[serde(rename_all = "camelCase")]
2009#[non_exhaustive]
2010pub struct SessionModeState {
2011 pub current_mode_id: SessionModeId,
2013 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
2015 pub available_modes: Vec<SessionMode>,
2016 #[serde(rename = "_meta")]
2022 pub meta: Option<Meta>,
2023}
2024
2025impl SessionModeState {
2026 #[must_use]
2027 pub fn new(
2028 current_mode_id: impl Into<SessionModeId>,
2029 available_modes: Vec<SessionMode>,
2030 ) -> Self {
2031 Self {
2032 current_mode_id: current_mode_id.into(),
2033 available_modes,
2034 meta: None,
2035 }
2036 }
2037
2038 #[must_use]
2044 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2045 self.meta = meta.into_option();
2046 self
2047 }
2048}
2049
2050#[skip_serializing_none]
2054#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2055#[serde(rename_all = "camelCase")]
2056#[non_exhaustive]
2057pub struct SessionMode {
2058 pub id: SessionModeId,
2059 pub name: String,
2060 #[serde(default)]
2061 pub description: Option<String>,
2062 #[serde(rename = "_meta")]
2068 pub meta: Option<Meta>,
2069}
2070
2071impl SessionMode {
2072 #[must_use]
2073 pub fn new(id: impl Into<SessionModeId>, name: impl Into<String>) -> Self {
2074 Self {
2075 id: id.into(),
2076 name: name.into(),
2077 description: None,
2078 meta: None,
2079 }
2080 }
2081
2082 #[must_use]
2083 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
2084 self.description = description.into_option();
2085 self
2086 }
2087
2088 #[must_use]
2094 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2095 self.meta = meta.into_option();
2096 self
2097 }
2098}
2099
2100#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, From, Display)]
2102#[serde(transparent)]
2103#[from(Arc<str>, String, &'static str)]
2104#[non_exhaustive]
2105pub struct SessionModeId(pub Arc<str>);
2106
2107impl SessionModeId {
2108 #[must_use]
2109 pub fn new(id: impl Into<Arc<str>>) -> Self {
2110 Self(id.into())
2111 }
2112}
2113
2114#[skip_serializing_none]
2116#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2117#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODE_METHOD_NAME))]
2118#[serde(rename_all = "camelCase")]
2119#[non_exhaustive]
2120pub struct SetSessionModeRequest {
2121 pub session_id: SessionId,
2123 pub mode_id: SessionModeId,
2125 #[serde(rename = "_meta")]
2131 pub meta: Option<Meta>,
2132}
2133
2134impl SetSessionModeRequest {
2135 #[must_use]
2136 pub fn new(session_id: impl Into<SessionId>, mode_id: impl Into<SessionModeId>) -> Self {
2137 Self {
2138 session_id: session_id.into(),
2139 mode_id: mode_id.into(),
2140 meta: None,
2141 }
2142 }
2143
2144 #[must_use]
2145 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2146 self.meta = meta.into_option();
2147 self
2148 }
2149}
2150
2151#[skip_serializing_none]
2153#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2154#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODE_METHOD_NAME))]
2155#[serde(rename_all = "camelCase")]
2156#[non_exhaustive]
2157pub struct SetSessionModeResponse {
2158 #[serde(rename = "_meta")]
2164 pub meta: Option<Meta>,
2165}
2166
2167impl SetSessionModeResponse {
2168 #[must_use]
2169 pub fn new() -> Self {
2170 Self::default()
2171 }
2172
2173 #[must_use]
2179 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2180 self.meta = meta.into_option();
2181 self
2182 }
2183}
2184
2185#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, From, Display)]
2189#[serde(transparent)]
2190#[from(Arc<str>, String, &'static str)]
2191#[non_exhaustive]
2192pub struct SessionConfigId(pub Arc<str>);
2193
2194impl SessionConfigId {
2195 #[must_use]
2196 pub fn new(id: impl Into<Arc<str>>) -> Self {
2197 Self(id.into())
2198 }
2199}
2200
2201#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, From, Display)]
2203#[serde(transparent)]
2204#[from(Arc<str>, String, &'static str)]
2205#[non_exhaustive]
2206pub struct SessionConfigValueId(pub Arc<str>);
2207
2208impl SessionConfigValueId {
2209 #[must_use]
2210 pub fn new(id: impl Into<Arc<str>>) -> Self {
2211 Self(id.into())
2212 }
2213}
2214
2215#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, From, Display)]
2217#[serde(transparent)]
2218#[from(Arc<str>, String, &'static str)]
2219#[non_exhaustive]
2220pub struct SessionConfigGroupId(pub Arc<str>);
2221
2222impl SessionConfigGroupId {
2223 #[must_use]
2224 pub fn new(id: impl Into<Arc<str>>) -> Self {
2225 Self(id.into())
2226 }
2227}
2228
2229#[skip_serializing_none]
2231#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2232#[serde(rename_all = "camelCase")]
2233#[non_exhaustive]
2234pub struct SessionConfigSelectOption {
2235 pub value: SessionConfigValueId,
2237 pub name: String,
2239 #[serde(default)]
2241 pub description: Option<String>,
2242 #[serde(rename = "_meta")]
2248 pub meta: Option<Meta>,
2249}
2250
2251impl SessionConfigSelectOption {
2252 #[must_use]
2253 pub fn new(value: impl Into<SessionConfigValueId>, name: impl Into<String>) -> Self {
2254 Self {
2255 value: value.into(),
2256 name: name.into(),
2257 description: None,
2258 meta: None,
2259 }
2260 }
2261
2262 #[must_use]
2263 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
2264 self.description = description.into_option();
2265 self
2266 }
2267
2268 #[must_use]
2274 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2275 self.meta = meta.into_option();
2276 self
2277 }
2278}
2279
2280#[skip_serializing_none]
2282#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2283#[serde(rename_all = "camelCase")]
2284#[non_exhaustive]
2285pub struct SessionConfigSelectGroup {
2286 pub group: SessionConfigGroupId,
2288 pub name: String,
2290 pub options: Vec<SessionConfigSelectOption>,
2292 #[serde(rename = "_meta")]
2298 pub meta: Option<Meta>,
2299}
2300
2301impl SessionConfigSelectGroup {
2302 #[must_use]
2303 pub fn new(
2304 group: impl Into<SessionConfigGroupId>,
2305 name: impl Into<String>,
2306 options: Vec<SessionConfigSelectOption>,
2307 ) -> Self {
2308 Self {
2309 group: group.into(),
2310 name: name.into(),
2311 options,
2312 meta: None,
2313 }
2314 }
2315
2316 #[must_use]
2322 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2323 self.meta = meta.into_option();
2324 self
2325 }
2326}
2327
2328#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2330#[serde(untagged)]
2331#[non_exhaustive]
2332pub enum SessionConfigSelectOptions {
2333 Ungrouped(Vec<SessionConfigSelectOption>),
2335 Grouped(Vec<SessionConfigSelectGroup>),
2337}
2338
2339impl From<Vec<SessionConfigSelectOption>> for SessionConfigSelectOptions {
2340 fn from(options: Vec<SessionConfigSelectOption>) -> Self {
2341 SessionConfigSelectOptions::Ungrouped(options)
2342 }
2343}
2344
2345impl From<Vec<SessionConfigSelectGroup>> for SessionConfigSelectOptions {
2346 fn from(groups: Vec<SessionConfigSelectGroup>) -> Self {
2347 SessionConfigSelectOptions::Grouped(groups)
2348 }
2349}
2350
2351#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2353#[serde(rename_all = "camelCase")]
2354#[non_exhaustive]
2355pub struct SessionConfigSelect {
2356 pub current_value: SessionConfigValueId,
2358 pub options: SessionConfigSelectOptions,
2360}
2361
2362impl SessionConfigSelect {
2363 #[must_use]
2364 pub fn new(
2365 current_value: impl Into<SessionConfigValueId>,
2366 options: impl Into<SessionConfigSelectOptions>,
2367 ) -> Self {
2368 Self {
2369 current_value: current_value.into(),
2370 options: options.into(),
2371 }
2372 }
2373}
2374
2375#[cfg(feature = "unstable_boolean_config")]
2381#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2382#[serde(rename_all = "camelCase")]
2383#[non_exhaustive]
2384pub struct SessionConfigBoolean {
2385 pub current_value: bool,
2387}
2388
2389#[cfg(feature = "unstable_boolean_config")]
2390impl SessionConfigBoolean {
2391 #[must_use]
2392 pub fn new(current_value: bool) -> Self {
2393 Self { current_value }
2394 }
2395}
2396
2397#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2407#[serde(rename_all = "snake_case")]
2408#[non_exhaustive]
2409pub enum SessionConfigOptionCategory {
2410 Mode,
2412 Model,
2414 ThoughtLevel,
2416 #[serde(untagged)]
2418 Other(String),
2419}
2420
2421#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2423#[serde(tag = "type", rename_all = "snake_case")]
2424#[schemars(extend("discriminator" = {"propertyName": "type"}))]
2425#[non_exhaustive]
2426pub enum SessionConfigKind {
2427 Select(SessionConfigSelect),
2429 #[cfg(feature = "unstable_boolean_config")]
2435 Boolean(SessionConfigBoolean),
2436}
2437
2438#[serde_as]
2440#[skip_serializing_none]
2441#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2442#[serde(rename_all = "camelCase")]
2443#[non_exhaustive]
2444pub struct SessionConfigOption {
2445 pub id: SessionConfigId,
2447 pub name: String,
2449 #[serde(default)]
2451 pub description: Option<String>,
2452 #[serde_as(deserialize_as = "DefaultOnError")]
2454 #[serde(default)]
2455 pub category: Option<SessionConfigOptionCategory>,
2456 #[serde(flatten)]
2458 pub kind: SessionConfigKind,
2459 #[serde(rename = "_meta")]
2465 pub meta: Option<Meta>,
2466}
2467
2468impl SessionConfigOption {
2469 #[must_use]
2470 pub fn new(
2471 id: impl Into<SessionConfigId>,
2472 name: impl Into<String>,
2473 kind: SessionConfigKind,
2474 ) -> Self {
2475 Self {
2476 id: id.into(),
2477 name: name.into(),
2478 description: None,
2479 category: None,
2480 kind,
2481 meta: None,
2482 }
2483 }
2484
2485 #[must_use]
2486 pub fn select(
2487 id: impl Into<SessionConfigId>,
2488 name: impl Into<String>,
2489 current_value: impl Into<SessionConfigValueId>,
2490 options: impl Into<SessionConfigSelectOptions>,
2491 ) -> Self {
2492 Self::new(
2493 id,
2494 name,
2495 SessionConfigKind::Select(SessionConfigSelect::new(current_value, options)),
2496 )
2497 }
2498
2499 #[cfg(feature = "unstable_boolean_config")]
2503 #[must_use]
2504 pub fn boolean(
2505 id: impl Into<SessionConfigId>,
2506 name: impl Into<String>,
2507 current_value: bool,
2508 ) -> Self {
2509 Self::new(
2510 id,
2511 name,
2512 SessionConfigKind::Boolean(SessionConfigBoolean::new(current_value)),
2513 )
2514 }
2515
2516 #[must_use]
2517 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
2518 self.description = description.into_option();
2519 self
2520 }
2521
2522 #[must_use]
2523 pub fn category(mut self, category: impl IntoOption<SessionConfigOptionCategory>) -> Self {
2524 self.category = category.into_option();
2525 self
2526 }
2527
2528 #[must_use]
2534 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2535 self.meta = meta.into_option();
2536 self
2537 }
2538}
2539
2540#[cfg(feature = "unstable_boolean_config")]
2555#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2556#[serde(tag = "type", rename_all = "snake_case")]
2557#[non_exhaustive]
2558pub enum SessionConfigOptionValue {
2559 Boolean {
2561 value: bool,
2563 },
2564 #[serde(untagged)]
2570 ValueId {
2571 value: SessionConfigValueId,
2573 },
2574}
2575
2576#[cfg(feature = "unstable_boolean_config")]
2577impl SessionConfigOptionValue {
2578 #[must_use]
2580 pub fn value_id(id: impl Into<SessionConfigValueId>) -> Self {
2581 Self::ValueId { value: id.into() }
2582 }
2583
2584 #[must_use]
2586 pub fn boolean(val: bool) -> Self {
2587 Self::Boolean { value: val }
2588 }
2589
2590 #[must_use]
2593 pub fn as_value_id(&self) -> Option<&SessionConfigValueId> {
2594 match self {
2595 Self::ValueId { value } => Some(value),
2596 _ => None,
2597 }
2598 }
2599
2600 #[must_use]
2602 pub fn as_bool(&self) -> Option<bool> {
2603 match self {
2604 Self::Boolean { value } => Some(*value),
2605 _ => None,
2606 }
2607 }
2608}
2609
2610#[cfg(feature = "unstable_boolean_config")]
2611impl From<SessionConfigValueId> for SessionConfigOptionValue {
2612 fn from(value: SessionConfigValueId) -> Self {
2613 Self::ValueId { value }
2614 }
2615}
2616
2617#[cfg(feature = "unstable_boolean_config")]
2618impl From<bool> for SessionConfigOptionValue {
2619 fn from(value: bool) -> Self {
2620 Self::Boolean { value }
2621 }
2622}
2623
2624#[cfg(feature = "unstable_boolean_config")]
2625impl From<&str> for SessionConfigOptionValue {
2626 fn from(value: &str) -> Self {
2627 Self::ValueId {
2628 value: SessionConfigValueId::new(value),
2629 }
2630 }
2631}
2632
2633#[skip_serializing_none]
2635#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2636#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_CONFIG_OPTION_METHOD_NAME))]
2637#[serde(rename_all = "camelCase")]
2638#[non_exhaustive]
2639pub struct SetSessionConfigOptionRequest {
2640 pub session_id: SessionId,
2642 pub config_id: SessionConfigId,
2644 #[cfg(feature = "unstable_boolean_config")]
2649 #[serde(flatten)]
2650 pub value: SessionConfigOptionValue,
2651 #[cfg(not(feature = "unstable_boolean_config"))]
2653 pub value: SessionConfigValueId,
2654 #[serde(rename = "_meta")]
2660 pub meta: Option<Meta>,
2661}
2662
2663impl SetSessionConfigOptionRequest {
2664 #[cfg(feature = "unstable_boolean_config")]
2665 #[must_use]
2666 pub fn new(
2667 session_id: impl Into<SessionId>,
2668 config_id: impl Into<SessionConfigId>,
2669 value: impl Into<SessionConfigOptionValue>,
2670 ) -> Self {
2671 Self {
2672 session_id: session_id.into(),
2673 config_id: config_id.into(),
2674 value: value.into(),
2675 meta: None,
2676 }
2677 }
2678
2679 #[cfg(not(feature = "unstable_boolean_config"))]
2680 #[must_use]
2681 pub fn new(
2682 session_id: impl Into<SessionId>,
2683 config_id: impl Into<SessionConfigId>,
2684 value: impl Into<SessionConfigValueId>,
2685 ) -> Self {
2686 Self {
2687 session_id: session_id.into(),
2688 config_id: config_id.into(),
2689 value: value.into(),
2690 meta: None,
2691 }
2692 }
2693
2694 #[must_use]
2700 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2701 self.meta = meta.into_option();
2702 self
2703 }
2704}
2705
2706#[serde_as]
2708#[skip_serializing_none]
2709#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2710#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_CONFIG_OPTION_METHOD_NAME))]
2711#[serde(rename_all = "camelCase")]
2712#[non_exhaustive]
2713pub struct SetSessionConfigOptionResponse {
2714 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
2716 pub config_options: Vec<SessionConfigOption>,
2717 #[serde(rename = "_meta")]
2723 pub meta: Option<Meta>,
2724}
2725
2726impl SetSessionConfigOptionResponse {
2727 #[must_use]
2728 pub fn new(config_options: Vec<SessionConfigOption>) -> Self {
2729 Self {
2730 config_options,
2731 meta: None,
2732 }
2733 }
2734
2735 #[must_use]
2741 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2742 self.meta = meta.into_option();
2743 self
2744 }
2745}
2746
2747#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2756#[serde(tag = "type", rename_all = "snake_case")]
2757#[non_exhaustive]
2758pub enum McpServer {
2759 Http(McpServerHttp),
2763 Sse(McpServerSse),
2767 #[cfg(feature = "unstable_mcp_over_acp")]
2776 Acp(McpServerAcp),
2777 #[serde(untagged)]
2781 Stdio(McpServerStdio),
2782}
2783
2784#[skip_serializing_none]
2786#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2787#[serde(rename_all = "camelCase")]
2788#[non_exhaustive]
2789pub struct McpServerHttp {
2790 pub name: String,
2792 pub url: String,
2794 pub headers: Vec<HttpHeader>,
2796 #[serde(rename = "_meta")]
2802 pub meta: Option<Meta>,
2803}
2804
2805impl McpServerHttp {
2806 #[must_use]
2807 pub fn new(name: impl Into<String>, url: impl Into<String>) -> Self {
2808 Self {
2809 name: name.into(),
2810 url: url.into(),
2811 headers: Vec::new(),
2812 meta: None,
2813 }
2814 }
2815
2816 #[must_use]
2818 pub fn headers(mut self, headers: Vec<HttpHeader>) -> Self {
2819 self.headers = headers;
2820 self
2821 }
2822
2823 #[must_use]
2829 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2830 self.meta = meta.into_option();
2831 self
2832 }
2833}
2834
2835#[skip_serializing_none]
2837#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2838#[serde(rename_all = "camelCase")]
2839#[non_exhaustive]
2840pub struct McpServerSse {
2841 pub name: String,
2843 pub url: String,
2845 pub headers: Vec<HttpHeader>,
2847 #[serde(rename = "_meta")]
2853 pub meta: Option<Meta>,
2854}
2855
2856impl McpServerSse {
2857 #[must_use]
2858 pub fn new(name: impl Into<String>, url: impl Into<String>) -> Self {
2859 Self {
2860 name: name.into(),
2861 url: url.into(),
2862 headers: Vec::new(),
2863 meta: None,
2864 }
2865 }
2866
2867 #[must_use]
2869 pub fn headers(mut self, headers: Vec<HttpHeader>) -> Self {
2870 self.headers = headers;
2871 self
2872 }
2873
2874 #[must_use]
2880 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2881 self.meta = meta.into_option();
2882 self
2883 }
2884}
2885
2886#[cfg(feature = "unstable_mcp_over_acp")]
2896#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
2897#[serde(transparent)]
2898#[from(Arc<str>, String, &'static str)]
2899#[non_exhaustive]
2900pub struct McpServerAcpId(pub Arc<str>);
2901
2902#[cfg(feature = "unstable_mcp_over_acp")]
2903impl McpServerAcpId {
2904 #[must_use]
2905 pub fn new(id: impl Into<Arc<str>>) -> Self {
2906 Self(id.into())
2907 }
2908}
2909
2910#[skip_serializing_none]
2919#[cfg(feature = "unstable_mcp_over_acp")]
2920#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2921#[serde(rename_all = "camelCase")]
2922#[non_exhaustive]
2923pub struct McpServerAcp {
2924 pub name: String,
2926 pub id: McpServerAcpId,
2931 #[serde(rename = "_meta")]
2937 pub meta: Option<Meta>,
2938}
2939
2940#[cfg(feature = "unstable_mcp_over_acp")]
2941impl McpServerAcp {
2942 #[must_use]
2943 pub fn new(name: impl Into<String>, id: impl Into<McpServerAcpId>) -> Self {
2944 Self {
2945 name: name.into(),
2946 id: id.into(),
2947 meta: None,
2948 }
2949 }
2950
2951 #[must_use]
2957 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2958 self.meta = meta.into_option();
2959 self
2960 }
2961}
2962
2963#[skip_serializing_none]
2965#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2966#[serde(rename_all = "camelCase")]
2967#[non_exhaustive]
2968pub struct McpServerStdio {
2969 pub name: String,
2971 pub command: PathBuf,
2973 pub args: Vec<String>,
2975 pub env: Vec<EnvVariable>,
2977 #[serde(rename = "_meta")]
2983 pub meta: Option<Meta>,
2984}
2985
2986impl McpServerStdio {
2987 #[must_use]
2988 pub fn new(name: impl Into<String>, command: impl Into<PathBuf>) -> Self {
2989 Self {
2990 name: name.into(),
2991 command: command.into(),
2992 args: Vec::new(),
2993 env: Vec::new(),
2994 meta: None,
2995 }
2996 }
2997
2998 #[must_use]
3000 pub fn args(mut self, args: Vec<String>) -> Self {
3001 self.args = args;
3002 self
3003 }
3004
3005 #[must_use]
3007 pub fn env(mut self, env: Vec<EnvVariable>) -> Self {
3008 self.env = env;
3009 self
3010 }
3011
3012 #[must_use]
3018 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3019 self.meta = meta.into_option();
3020 self
3021 }
3022}
3023
3024#[skip_serializing_none]
3026#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3027#[serde(rename_all = "camelCase")]
3028#[non_exhaustive]
3029pub struct EnvVariable {
3030 pub name: String,
3032 pub value: String,
3034 #[serde(rename = "_meta")]
3040 pub meta: Option<Meta>,
3041}
3042
3043impl EnvVariable {
3044 #[must_use]
3045 pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
3046 Self {
3047 name: name.into(),
3048 value: value.into(),
3049 meta: None,
3050 }
3051 }
3052
3053 #[must_use]
3059 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3060 self.meta = meta.into_option();
3061 self
3062 }
3063}
3064
3065#[skip_serializing_none]
3067#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3068#[serde(rename_all = "camelCase")]
3069#[non_exhaustive]
3070pub struct HttpHeader {
3071 pub name: String,
3073 pub value: String,
3075 #[serde(rename = "_meta")]
3081 pub meta: Option<Meta>,
3082}
3083
3084impl HttpHeader {
3085 #[must_use]
3086 pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
3087 Self {
3088 name: name.into(),
3089 value: value.into(),
3090 meta: None,
3091 }
3092 }
3093
3094 #[must_use]
3100 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3101 self.meta = meta.into_option();
3102 self
3103 }
3104}
3105
3106#[skip_serializing_none]
3114#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
3115#[schemars(extend("x-side" = "agent", "x-method" = SESSION_PROMPT_METHOD_NAME))]
3116#[serde(rename_all = "camelCase")]
3117#[non_exhaustive]
3118pub struct PromptRequest {
3119 pub session_id: SessionId,
3121 #[cfg(feature = "unstable_message_id")]
3131 pub message_id: Option<String>,
3132 pub prompt: Vec<ContentBlock>,
3146 #[serde(rename = "_meta")]
3152 pub meta: Option<Meta>,
3153}
3154
3155impl PromptRequest {
3156 #[must_use]
3157 pub fn new(session_id: impl Into<SessionId>, prompt: Vec<ContentBlock>) -> Self {
3158 Self {
3159 session_id: session_id.into(),
3160 #[cfg(feature = "unstable_message_id")]
3161 message_id: None,
3162 prompt,
3163 meta: None,
3164 }
3165 }
3166
3167 #[cfg(feature = "unstable_message_id")]
3177 #[must_use]
3178 pub fn message_id(mut self, message_id: impl IntoOption<String>) -> Self {
3179 self.message_id = message_id.into_option();
3180 self
3181 }
3182
3183 #[must_use]
3189 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3190 self.meta = meta.into_option();
3191 self
3192 }
3193}
3194
3195#[serde_as]
3199#[skip_serializing_none]
3200#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3201#[schemars(extend("x-side" = "agent", "x-method" = SESSION_PROMPT_METHOD_NAME))]
3202#[serde(rename_all = "camelCase")]
3203#[non_exhaustive]
3204pub struct PromptResponse {
3205 #[cfg(feature = "unstable_message_id")]
3215 pub user_message_id: Option<String>,
3216 pub stop_reason: StopReason,
3218 #[cfg(feature = "unstable_session_usage")]
3224 #[serde_as(deserialize_as = "DefaultOnError")]
3225 #[serde(default)]
3226 pub usage: Option<Usage>,
3227 #[serde(rename = "_meta")]
3233 pub meta: Option<Meta>,
3234}
3235
3236impl PromptResponse {
3237 #[must_use]
3238 pub fn new(stop_reason: StopReason) -> Self {
3239 Self {
3240 #[cfg(feature = "unstable_message_id")]
3241 user_message_id: None,
3242 stop_reason,
3243 #[cfg(feature = "unstable_session_usage")]
3244 usage: None,
3245 meta: None,
3246 }
3247 }
3248
3249 #[cfg(feature = "unstable_message_id")]
3259 #[must_use]
3260 pub fn user_message_id(mut self, user_message_id: impl IntoOption<String>) -> Self {
3261 self.user_message_id = user_message_id.into_option();
3262 self
3263 }
3264
3265 #[cfg(feature = "unstable_session_usage")]
3271 #[must_use]
3272 pub fn usage(mut self, usage: impl IntoOption<Usage>) -> Self {
3273 self.usage = usage.into_option();
3274 self
3275 }
3276
3277 #[must_use]
3283 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3284 self.meta = meta.into_option();
3285 self
3286 }
3287}
3288
3289#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
3293#[serde(rename_all = "snake_case")]
3294#[non_exhaustive]
3295pub enum StopReason {
3296 EndTurn,
3298 MaxTokens,
3300 MaxTurnRequests,
3303 Refusal,
3307 Cancelled,
3314}
3315
3316#[cfg(feature = "unstable_session_usage")]
3322#[skip_serializing_none]
3323#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3324#[serde(rename_all = "camelCase")]
3325#[non_exhaustive]
3326pub struct Usage {
3327 pub total_tokens: u64,
3329 pub input_tokens: u64,
3331 pub output_tokens: u64,
3333 pub thought_tokens: Option<u64>,
3335 pub cached_read_tokens: Option<u64>,
3337 pub cached_write_tokens: Option<u64>,
3339}
3340
3341#[cfg(feature = "unstable_session_usage")]
3342impl Usage {
3343 #[must_use]
3344 pub fn new(total_tokens: u64, input_tokens: u64, output_tokens: u64) -> Self {
3345 Self {
3346 total_tokens,
3347 input_tokens,
3348 output_tokens,
3349 thought_tokens: None,
3350 cached_read_tokens: None,
3351 cached_write_tokens: None,
3352 }
3353 }
3354
3355 #[must_use]
3357 pub fn thought_tokens(mut self, thought_tokens: impl IntoOption<u64>) -> Self {
3358 self.thought_tokens = thought_tokens.into_option();
3359 self
3360 }
3361
3362 #[must_use]
3364 pub fn cached_read_tokens(mut self, cached_read_tokens: impl IntoOption<u64>) -> Self {
3365 self.cached_read_tokens = cached_read_tokens.into_option();
3366 self
3367 }
3368
3369 #[must_use]
3371 pub fn cached_write_tokens(mut self, cached_write_tokens: impl IntoOption<u64>) -> Self {
3372 self.cached_write_tokens = cached_write_tokens.into_option();
3373 self
3374 }
3375}
3376
3377#[cfg(feature = "unstable_session_model")]
3385#[serde_as]
3386#[skip_serializing_none]
3387#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3388#[serde(rename_all = "camelCase")]
3389#[non_exhaustive]
3390pub struct SessionModelState {
3391 pub current_model_id: ModelId,
3393 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
3395 pub available_models: Vec<ModelInfo>,
3396 #[serde(rename = "_meta")]
3402 pub meta: Option<Meta>,
3403}
3404
3405#[cfg(feature = "unstable_session_model")]
3406impl SessionModelState {
3407 #[must_use]
3408 pub fn new(current_model_id: impl Into<ModelId>, available_models: Vec<ModelInfo>) -> Self {
3409 Self {
3410 current_model_id: current_model_id.into(),
3411 available_models,
3412 meta: None,
3413 }
3414 }
3415
3416 #[must_use]
3422 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3423 self.meta = meta.into_option();
3424 self
3425 }
3426}
3427
3428#[cfg(feature = "unstable_session_model")]
3434#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
3435#[serde(transparent)]
3436#[from(Arc<str>, String, &'static str)]
3437#[non_exhaustive]
3438pub struct ModelId(pub Arc<str>);
3439
3440#[cfg(feature = "unstable_session_model")]
3441impl ModelId {
3442 #[must_use]
3443 pub fn new(id: impl Into<Arc<str>>) -> Self {
3444 Self(id.into())
3445 }
3446}
3447
3448#[cfg(feature = "unstable_session_model")]
3454#[skip_serializing_none]
3455#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3456#[serde(rename_all = "camelCase")]
3457#[non_exhaustive]
3458pub struct ModelInfo {
3459 pub model_id: ModelId,
3461 pub name: String,
3463 #[serde(default)]
3465 pub description: Option<String>,
3466 #[serde(rename = "_meta")]
3472 pub meta: Option<Meta>,
3473}
3474
3475#[cfg(feature = "unstable_session_model")]
3476impl ModelInfo {
3477 #[must_use]
3478 pub fn new(model_id: impl Into<ModelId>, name: impl Into<String>) -> Self {
3479 Self {
3480 model_id: model_id.into(),
3481 name: name.into(),
3482 description: None,
3483 meta: None,
3484 }
3485 }
3486
3487 #[must_use]
3489 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
3490 self.description = description.into_option();
3491 self
3492 }
3493
3494 #[must_use]
3500 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3501 self.meta = meta.into_option();
3502 self
3503 }
3504}
3505
3506#[cfg(feature = "unstable_session_model")]
3512#[skip_serializing_none]
3513#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3514#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODEL_METHOD_NAME))]
3515#[serde(rename_all = "camelCase")]
3516#[non_exhaustive]
3517pub struct SetSessionModelRequest {
3518 pub session_id: SessionId,
3520 pub model_id: ModelId,
3522 #[serde(rename = "_meta")]
3528 pub meta: Option<Meta>,
3529}
3530
3531#[cfg(feature = "unstable_session_model")]
3532impl SetSessionModelRequest {
3533 #[must_use]
3534 pub fn new(session_id: impl Into<SessionId>, model_id: impl Into<ModelId>) -> Self {
3535 Self {
3536 session_id: session_id.into(),
3537 model_id: model_id.into(),
3538 meta: None,
3539 }
3540 }
3541
3542 #[must_use]
3548 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3549 self.meta = meta.into_option();
3550 self
3551 }
3552}
3553
3554#[cfg(feature = "unstable_session_model")]
3560#[skip_serializing_none]
3561#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3562#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODEL_METHOD_NAME))]
3563#[serde(rename_all = "camelCase")]
3564#[non_exhaustive]
3565pub struct SetSessionModelResponse {
3566 #[serde(rename = "_meta")]
3572 pub meta: Option<Meta>,
3573}
3574
3575#[cfg(feature = "unstable_session_model")]
3576impl SetSessionModelResponse {
3577 #[must_use]
3578 pub fn new() -> Self {
3579 Self::default()
3580 }
3581
3582 #[must_use]
3588 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3589 self.meta = meta.into_option();
3590 self
3591 }
3592}
3593
3594#[cfg(feature = "unstable_llm_providers")]
3607#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3608#[serde(rename_all = "snake_case")]
3609#[non_exhaustive]
3610#[expect(clippy::doc_markdown)]
3611pub enum LlmProtocol {
3612 Anthropic,
3614 #[serde(rename = "openai")]
3616 OpenAi,
3617 Azure,
3619 Vertex,
3621 Bedrock,
3623 #[serde(untagged)]
3625 Other(String),
3626}
3627
3628#[cfg(feature = "unstable_llm_providers")]
3634#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3635#[serde(rename_all = "camelCase")]
3636#[non_exhaustive]
3637pub struct ProviderCurrentConfig {
3638 pub api_type: LlmProtocol,
3640 pub base_url: String,
3642}
3643
3644#[cfg(feature = "unstable_llm_providers")]
3645impl ProviderCurrentConfig {
3646 #[must_use]
3647 pub fn new(api_type: LlmProtocol, base_url: impl Into<String>) -> Self {
3648 Self {
3649 api_type,
3650 base_url: base_url.into(),
3651 }
3652 }
3653}
3654
3655#[cfg(feature = "unstable_llm_providers")]
3661#[serde_as]
3662#[skip_serializing_none]
3663#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3664#[serde(rename_all = "camelCase")]
3665#[non_exhaustive]
3666pub struct ProviderInfo {
3667 pub id: String,
3669 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
3671 pub supported: Vec<LlmProtocol>,
3672 pub required: bool,
3675 pub current: Option<ProviderCurrentConfig>,
3678 #[serde(rename = "_meta")]
3684 pub meta: Option<Meta>,
3685}
3686
3687#[cfg(feature = "unstable_llm_providers")]
3688impl ProviderInfo {
3689 #[must_use]
3690 pub fn new(
3691 id: impl Into<String>,
3692 supported: Vec<LlmProtocol>,
3693 required: bool,
3694 current: impl IntoOption<ProviderCurrentConfig>,
3695 ) -> Self {
3696 Self {
3697 id: id.into(),
3698 supported,
3699 required,
3700 current: current.into_option(),
3701 meta: None,
3702 }
3703 }
3704
3705 #[must_use]
3711 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3712 self.meta = meta.into_option();
3713 self
3714 }
3715}
3716
3717#[cfg(feature = "unstable_llm_providers")]
3723#[skip_serializing_none]
3724#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3725#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_LIST_METHOD_NAME))]
3726#[serde(rename_all = "camelCase")]
3727#[non_exhaustive]
3728pub struct ListProvidersRequest {
3729 #[serde(rename = "_meta")]
3735 pub meta: Option<Meta>,
3736}
3737
3738#[cfg(feature = "unstable_llm_providers")]
3739impl ListProvidersRequest {
3740 #[must_use]
3741 pub fn new() -> Self {
3742 Self::default()
3743 }
3744
3745 #[must_use]
3751 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3752 self.meta = meta.into_option();
3753 self
3754 }
3755}
3756
3757#[cfg(feature = "unstable_llm_providers")]
3763#[serde_as]
3764#[skip_serializing_none]
3765#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3766#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_LIST_METHOD_NAME))]
3767#[serde(rename_all = "camelCase")]
3768#[non_exhaustive]
3769pub struct ListProvidersResponse {
3770 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
3772 pub providers: Vec<ProviderInfo>,
3773 #[serde(rename = "_meta")]
3779 pub meta: Option<Meta>,
3780}
3781
3782#[cfg(feature = "unstable_llm_providers")]
3783impl ListProvidersResponse {
3784 #[must_use]
3785 pub fn new(providers: Vec<ProviderInfo>) -> Self {
3786 Self {
3787 providers,
3788 meta: None,
3789 }
3790 }
3791
3792 #[must_use]
3798 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3799 self.meta = meta.into_option();
3800 self
3801 }
3802}
3803
3804#[cfg(feature = "unstable_llm_providers")]
3812#[skip_serializing_none]
3813#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3814#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_SET_METHOD_NAME))]
3815#[serde(rename_all = "camelCase")]
3816#[non_exhaustive]
3817pub struct SetProvidersRequest {
3818 pub id: String,
3820 pub api_type: LlmProtocol,
3822 pub base_url: String,
3824 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
3827 pub headers: HashMap<String, String>,
3828 #[serde(rename = "_meta")]
3834 pub meta: Option<Meta>,
3835}
3836
3837#[cfg(feature = "unstable_llm_providers")]
3838impl SetProvidersRequest {
3839 #[must_use]
3840 pub fn new(id: impl Into<String>, api_type: LlmProtocol, base_url: impl Into<String>) -> Self {
3841 Self {
3842 id: id.into(),
3843 api_type,
3844 base_url: base_url.into(),
3845 headers: HashMap::new(),
3846 meta: None,
3847 }
3848 }
3849
3850 #[must_use]
3853 pub fn headers(mut self, headers: HashMap<String, String>) -> Self {
3854 self.headers = headers;
3855 self
3856 }
3857
3858 #[must_use]
3864 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3865 self.meta = meta.into_option();
3866 self
3867 }
3868}
3869
3870#[cfg(feature = "unstable_llm_providers")]
3876#[skip_serializing_none]
3877#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3878#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_SET_METHOD_NAME))]
3879#[serde(rename_all = "camelCase")]
3880#[non_exhaustive]
3881pub struct SetProvidersResponse {
3882 #[serde(rename = "_meta")]
3888 pub meta: Option<Meta>,
3889}
3890
3891#[cfg(feature = "unstable_llm_providers")]
3892impl SetProvidersResponse {
3893 #[must_use]
3894 pub fn new() -> Self {
3895 Self::default()
3896 }
3897
3898 #[must_use]
3904 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3905 self.meta = meta.into_option();
3906 self
3907 }
3908}
3909
3910#[cfg(feature = "unstable_llm_providers")]
3916#[skip_serializing_none]
3917#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3918#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_DISABLE_METHOD_NAME))]
3919#[serde(rename_all = "camelCase")]
3920#[non_exhaustive]
3921pub struct DisableProvidersRequest {
3922 pub id: String,
3924 #[serde(rename = "_meta")]
3930 pub meta: Option<Meta>,
3931}
3932
3933#[cfg(feature = "unstable_llm_providers")]
3934impl DisableProvidersRequest {
3935 #[must_use]
3936 pub fn new(id: impl Into<String>) -> Self {
3937 Self {
3938 id: id.into(),
3939 meta: None,
3940 }
3941 }
3942
3943 #[must_use]
3949 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3950 self.meta = meta.into_option();
3951 self
3952 }
3953}
3954
3955#[cfg(feature = "unstable_llm_providers")]
3961#[skip_serializing_none]
3962#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3963#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_DISABLE_METHOD_NAME))]
3964#[serde(rename_all = "camelCase")]
3965#[non_exhaustive]
3966pub struct DisableProvidersResponse {
3967 #[serde(rename = "_meta")]
3973 pub meta: Option<Meta>,
3974}
3975
3976#[cfg(feature = "unstable_llm_providers")]
3977impl DisableProvidersResponse {
3978 #[must_use]
3979 pub fn new() -> Self {
3980 Self::default()
3981 }
3982
3983 #[must_use]
3989 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3990 self.meta = meta.into_option();
3991 self
3992 }
3993}
3994
3995#[serde_as]
4004#[skip_serializing_none]
4005#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4006#[serde(rename_all = "camelCase")]
4007#[non_exhaustive]
4008pub struct AgentCapabilities {
4009 #[serde(default)]
4011 pub load_session: bool,
4012 #[serde(default)]
4014 pub prompt_capabilities: PromptCapabilities,
4015 #[serde(default)]
4017 pub mcp_capabilities: McpCapabilities,
4018 #[serde(default)]
4019 pub session_capabilities: SessionCapabilities,
4020 #[cfg(feature = "unstable_logout")]
4026 #[serde(default)]
4027 pub auth: AgentAuthCapabilities,
4028 #[cfg(feature = "unstable_llm_providers")]
4036 #[serde_as(deserialize_as = "DefaultOnError")]
4037 #[serde(default)]
4038 pub providers: Option<ProvidersCapabilities>,
4039 #[cfg(feature = "unstable_nes")]
4045 #[serde_as(deserialize_as = "DefaultOnError")]
4046 #[serde(default)]
4047 pub nes: Option<NesCapabilities>,
4048 #[cfg(feature = "unstable_nes")]
4054 #[serde_as(deserialize_as = "DefaultOnError")]
4055 #[serde(default)]
4056 pub position_encoding: Option<PositionEncodingKind>,
4057 #[serde(rename = "_meta")]
4063 pub meta: Option<Meta>,
4064}
4065
4066impl AgentCapabilities {
4067 #[must_use]
4068 pub fn new() -> Self {
4069 Self::default()
4070 }
4071
4072 #[must_use]
4074 pub fn load_session(mut self, load_session: bool) -> Self {
4075 self.load_session = load_session;
4076 self
4077 }
4078
4079 #[must_use]
4081 pub fn prompt_capabilities(mut self, prompt_capabilities: PromptCapabilities) -> Self {
4082 self.prompt_capabilities = prompt_capabilities;
4083 self
4084 }
4085
4086 #[must_use]
4088 pub fn mcp_capabilities(mut self, mcp_capabilities: McpCapabilities) -> Self {
4089 self.mcp_capabilities = mcp_capabilities;
4090 self
4091 }
4092
4093 #[must_use]
4095 pub fn session_capabilities(mut self, session_capabilities: SessionCapabilities) -> Self {
4096 self.session_capabilities = session_capabilities;
4097 self
4098 }
4099
4100 #[cfg(feature = "unstable_logout")]
4106 #[must_use]
4107 pub fn auth(mut self, auth: AgentAuthCapabilities) -> Self {
4108 self.auth = auth;
4109 self
4110 }
4111
4112 #[cfg(feature = "unstable_llm_providers")]
4118 #[must_use]
4119 pub fn providers(mut self, providers: impl IntoOption<ProvidersCapabilities>) -> Self {
4120 self.providers = providers.into_option();
4121 self
4122 }
4123
4124 #[cfg(feature = "unstable_nes")]
4130 #[must_use]
4131 pub fn nes(mut self, nes: impl IntoOption<NesCapabilities>) -> Self {
4132 self.nes = nes.into_option();
4133 self
4134 }
4135
4136 #[cfg(feature = "unstable_nes")]
4140 #[must_use]
4141 pub fn position_encoding(
4142 mut self,
4143 position_encoding: impl IntoOption<PositionEncodingKind>,
4144 ) -> Self {
4145 self.position_encoding = position_encoding.into_option();
4146 self
4147 }
4148
4149 #[must_use]
4155 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4156 self.meta = meta.into_option();
4157 self
4158 }
4159}
4160
4161#[cfg(feature = "unstable_llm_providers")]
4169#[skip_serializing_none]
4170#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4171#[non_exhaustive]
4172pub struct ProvidersCapabilities {
4173 #[serde(rename = "_meta")]
4179 pub meta: Option<Meta>,
4180}
4181
4182#[cfg(feature = "unstable_llm_providers")]
4183impl ProvidersCapabilities {
4184 #[must_use]
4185 pub fn new() -> Self {
4186 Self::default()
4187 }
4188
4189 #[must_use]
4195 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4196 self.meta = meta.into_option();
4197 self
4198 }
4199}
4200
4201#[serde_as]
4211#[skip_serializing_none]
4212#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4213#[serde(rename_all = "camelCase")]
4214#[non_exhaustive]
4215pub struct SessionCapabilities {
4216 #[serde_as(deserialize_as = "DefaultOnError")]
4218 #[serde(default)]
4219 pub list: Option<SessionListCapabilities>,
4220 #[cfg(feature = "unstable_session_delete")]
4229 #[serde_as(deserialize_as = "DefaultOnError")]
4230 #[serde(default)]
4231 pub delete: Option<SessionDeleteCapabilities>,
4232 #[cfg(feature = "unstable_session_additional_directories")]
4241 #[serde_as(deserialize_as = "DefaultOnError")]
4242 #[serde(default)]
4243 pub additional_directories: Option<SessionAdditionalDirectoriesCapabilities>,
4244 #[cfg(feature = "unstable_session_fork")]
4250 #[serde_as(deserialize_as = "DefaultOnError")]
4251 #[serde(default)]
4252 pub fork: Option<SessionForkCapabilities>,
4253 #[serde_as(deserialize_as = "DefaultOnError")]
4255 #[serde(default)]
4256 pub resume: Option<SessionResumeCapabilities>,
4257 #[serde_as(deserialize_as = "DefaultOnError")]
4259 #[serde(default)]
4260 pub close: Option<SessionCloseCapabilities>,
4261 #[serde(rename = "_meta")]
4267 pub meta: Option<Meta>,
4268}
4269
4270impl SessionCapabilities {
4271 #[must_use]
4272 pub fn new() -> Self {
4273 Self::default()
4274 }
4275
4276 #[must_use]
4278 pub fn list(mut self, list: impl IntoOption<SessionListCapabilities>) -> Self {
4279 self.list = list.into_option();
4280 self
4281 }
4282
4283 #[cfg(feature = "unstable_session_delete")]
4292 #[must_use]
4293 pub fn delete(mut self, delete: impl IntoOption<SessionDeleteCapabilities>) -> Self {
4294 self.delete = delete.into_option();
4295 self
4296 }
4297
4298 #[cfg(feature = "unstable_session_additional_directories")]
4307 #[must_use]
4308 pub fn additional_directories(
4309 mut self,
4310 additional_directories: impl IntoOption<SessionAdditionalDirectoriesCapabilities>,
4311 ) -> Self {
4312 self.additional_directories = additional_directories.into_option();
4313 self
4314 }
4315
4316 #[cfg(feature = "unstable_session_fork")]
4317 #[must_use]
4319 pub fn fork(mut self, fork: impl IntoOption<SessionForkCapabilities>) -> Self {
4320 self.fork = fork.into_option();
4321 self
4322 }
4323
4324 #[must_use]
4326 pub fn resume(mut self, resume: impl IntoOption<SessionResumeCapabilities>) -> Self {
4327 self.resume = resume.into_option();
4328 self
4329 }
4330
4331 #[must_use]
4333 pub fn close(mut self, close: impl IntoOption<SessionCloseCapabilities>) -> Self {
4334 self.close = close.into_option();
4335 self
4336 }
4337
4338 #[must_use]
4344 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4345 self.meta = meta.into_option();
4346 self
4347 }
4348}
4349
4350#[skip_serializing_none]
4354#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4355#[non_exhaustive]
4356pub struct SessionListCapabilities {
4357 #[serde(rename = "_meta")]
4363 pub meta: Option<Meta>,
4364}
4365
4366impl SessionListCapabilities {
4367 #[must_use]
4368 pub fn new() -> Self {
4369 Self::default()
4370 }
4371
4372 #[must_use]
4378 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4379 self.meta = meta.into_option();
4380 self
4381 }
4382}
4383
4384#[cfg(feature = "unstable_session_delete")]
4392#[skip_serializing_none]
4393#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4394#[non_exhaustive]
4395pub struct SessionDeleteCapabilities {
4396 #[serde(rename = "_meta")]
4402 pub meta: Option<Meta>,
4403}
4404
4405#[cfg(feature = "unstable_session_delete")]
4406impl SessionDeleteCapabilities {
4407 #[must_use]
4408 pub fn new() -> Self {
4409 Self::default()
4410 }
4411
4412 #[must_use]
4418 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4419 self.meta = meta.into_option();
4420 self
4421 }
4422}
4423
4424#[cfg(feature = "unstable_session_additional_directories")]
4435#[skip_serializing_none]
4436#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4437#[non_exhaustive]
4438pub struct SessionAdditionalDirectoriesCapabilities {
4439 #[serde(rename = "_meta")]
4445 pub meta: Option<Meta>,
4446}
4447
4448#[cfg(feature = "unstable_session_additional_directories")]
4449impl SessionAdditionalDirectoriesCapabilities {
4450 #[must_use]
4451 pub fn new() -> Self {
4452 Self::default()
4453 }
4454
4455 #[must_use]
4461 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4462 self.meta = meta.into_option();
4463 self
4464 }
4465}
4466
4467#[cfg(feature = "unstable_session_fork")]
4475#[skip_serializing_none]
4476#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4477#[non_exhaustive]
4478pub struct SessionForkCapabilities {
4479 #[serde(rename = "_meta")]
4485 pub meta: Option<Meta>,
4486}
4487
4488#[cfg(feature = "unstable_session_fork")]
4489impl SessionForkCapabilities {
4490 #[must_use]
4491 pub fn new() -> Self {
4492 Self::default()
4493 }
4494
4495 #[must_use]
4501 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4502 self.meta = meta.into_option();
4503 self
4504 }
4505}
4506
4507#[skip_serializing_none]
4511#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4512#[non_exhaustive]
4513pub struct SessionResumeCapabilities {
4514 #[serde(rename = "_meta")]
4520 pub meta: Option<Meta>,
4521}
4522
4523impl SessionResumeCapabilities {
4524 #[must_use]
4525 pub fn new() -> Self {
4526 Self::default()
4527 }
4528
4529 #[must_use]
4535 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4536 self.meta = meta.into_option();
4537 self
4538 }
4539}
4540
4541#[skip_serializing_none]
4545#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4546#[non_exhaustive]
4547pub struct SessionCloseCapabilities {
4548 #[serde(rename = "_meta")]
4554 pub meta: Option<Meta>,
4555}
4556
4557impl SessionCloseCapabilities {
4558 #[must_use]
4559 pub fn new() -> Self {
4560 Self::default()
4561 }
4562
4563 #[must_use]
4569 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4570 self.meta = meta.into_option();
4571 self
4572 }
4573}
4574
4575#[skip_serializing_none]
4588#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4589#[serde(rename_all = "camelCase")]
4590#[non_exhaustive]
4591pub struct PromptCapabilities {
4592 #[serde(default)]
4594 pub image: bool,
4595 #[serde(default)]
4597 pub audio: bool,
4598 #[serde(default)]
4603 pub embedded_context: bool,
4604 #[serde(rename = "_meta")]
4610 pub meta: Option<Meta>,
4611}
4612
4613impl PromptCapabilities {
4614 #[must_use]
4615 pub fn new() -> Self {
4616 Self::default()
4617 }
4618
4619 #[must_use]
4621 pub fn image(mut self, image: bool) -> Self {
4622 self.image = image;
4623 self
4624 }
4625
4626 #[must_use]
4628 pub fn audio(mut self, audio: bool) -> Self {
4629 self.audio = audio;
4630 self
4631 }
4632
4633 #[must_use]
4638 pub fn embedded_context(mut self, embedded_context: bool) -> Self {
4639 self.embedded_context = embedded_context;
4640 self
4641 }
4642
4643 #[must_use]
4649 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4650 self.meta = meta.into_option();
4651 self
4652 }
4653}
4654
4655#[skip_serializing_none]
4657#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4658#[serde(rename_all = "camelCase")]
4659#[non_exhaustive]
4660pub struct McpCapabilities {
4661 #[serde(default)]
4663 pub http: bool,
4664 #[serde(default)]
4666 pub sse: bool,
4667 #[cfg(feature = "unstable_mcp_over_acp")]
4673 #[serde(default)]
4674 pub acp: bool,
4675 #[serde(rename = "_meta")]
4681 pub meta: Option<Meta>,
4682}
4683
4684impl McpCapabilities {
4685 #[must_use]
4686 pub fn new() -> Self {
4687 Self::default()
4688 }
4689
4690 #[must_use]
4692 pub fn http(mut self, http: bool) -> Self {
4693 self.http = http;
4694 self
4695 }
4696
4697 #[must_use]
4699 pub fn sse(mut self, sse: bool) -> Self {
4700 self.sse = sse;
4701 self
4702 }
4703
4704 #[cfg(feature = "unstable_mcp_over_acp")]
4710 #[must_use]
4711 pub fn acp(mut self, acp: bool) -> Self {
4712 self.acp = acp;
4713 self
4714 }
4715
4716 #[must_use]
4722 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4723 self.meta = meta.into_option();
4724 self
4725 }
4726}
4727
4728#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4734#[non_exhaustive]
4735pub struct AgentMethodNames {
4736 pub initialize: &'static str,
4738 pub authenticate: &'static str,
4740 #[cfg(feature = "unstable_llm_providers")]
4742 pub providers_list: &'static str,
4743 #[cfg(feature = "unstable_llm_providers")]
4745 pub providers_set: &'static str,
4746 #[cfg(feature = "unstable_llm_providers")]
4748 pub providers_disable: &'static str,
4749 pub session_new: &'static str,
4751 pub session_load: &'static str,
4753 pub session_set_mode: &'static str,
4755 pub session_set_config_option: &'static str,
4757 pub session_prompt: &'static str,
4759 pub session_cancel: &'static str,
4761 #[cfg(feature = "unstable_mcp_over_acp")]
4763 pub mcp_message: &'static str,
4764 #[cfg(feature = "unstable_session_model")]
4766 pub session_set_model: &'static str,
4767 pub session_list: &'static str,
4769 #[cfg(feature = "unstable_session_delete")]
4771 pub session_delete: &'static str,
4772 #[cfg(feature = "unstable_session_fork")]
4774 pub session_fork: &'static str,
4775 pub session_resume: &'static str,
4777 pub session_close: &'static str,
4779 #[cfg(feature = "unstable_logout")]
4781 pub logout: &'static str,
4782 #[cfg(feature = "unstable_nes")]
4784 pub nes_start: &'static str,
4785 #[cfg(feature = "unstable_nes")]
4787 pub nes_suggest: &'static str,
4788 #[cfg(feature = "unstable_nes")]
4790 pub nes_accept: &'static str,
4791 #[cfg(feature = "unstable_nes")]
4793 pub nes_reject: &'static str,
4794 #[cfg(feature = "unstable_nes")]
4796 pub nes_close: &'static str,
4797 #[cfg(feature = "unstable_nes")]
4799 pub document_did_open: &'static str,
4800 #[cfg(feature = "unstable_nes")]
4802 pub document_did_change: &'static str,
4803 #[cfg(feature = "unstable_nes")]
4805 pub document_did_close: &'static str,
4806 #[cfg(feature = "unstable_nes")]
4808 pub document_did_save: &'static str,
4809 #[cfg(feature = "unstable_nes")]
4811 pub document_did_focus: &'static str,
4812}
4813
4814pub const AGENT_METHOD_NAMES: AgentMethodNames = AgentMethodNames {
4816 initialize: INITIALIZE_METHOD_NAME,
4817 authenticate: AUTHENTICATE_METHOD_NAME,
4818 #[cfg(feature = "unstable_llm_providers")]
4819 providers_list: PROVIDERS_LIST_METHOD_NAME,
4820 #[cfg(feature = "unstable_llm_providers")]
4821 providers_set: PROVIDERS_SET_METHOD_NAME,
4822 #[cfg(feature = "unstable_llm_providers")]
4823 providers_disable: PROVIDERS_DISABLE_METHOD_NAME,
4824 session_new: SESSION_NEW_METHOD_NAME,
4825 session_load: SESSION_LOAD_METHOD_NAME,
4826 session_set_mode: SESSION_SET_MODE_METHOD_NAME,
4827 session_set_config_option: SESSION_SET_CONFIG_OPTION_METHOD_NAME,
4828 session_prompt: SESSION_PROMPT_METHOD_NAME,
4829 session_cancel: SESSION_CANCEL_METHOD_NAME,
4830 #[cfg(feature = "unstable_mcp_over_acp")]
4831 mcp_message: MCP_MESSAGE_METHOD_NAME,
4832 #[cfg(feature = "unstable_session_model")]
4833 session_set_model: SESSION_SET_MODEL_METHOD_NAME,
4834 session_list: SESSION_LIST_METHOD_NAME,
4835 #[cfg(feature = "unstable_session_delete")]
4836 session_delete: SESSION_DELETE_METHOD_NAME,
4837 #[cfg(feature = "unstable_session_fork")]
4838 session_fork: SESSION_FORK_METHOD_NAME,
4839 session_resume: SESSION_RESUME_METHOD_NAME,
4840 session_close: SESSION_CLOSE_METHOD_NAME,
4841 #[cfg(feature = "unstable_logout")]
4842 logout: LOGOUT_METHOD_NAME,
4843 #[cfg(feature = "unstable_nes")]
4844 nes_start: NES_START_METHOD_NAME,
4845 #[cfg(feature = "unstable_nes")]
4846 nes_suggest: NES_SUGGEST_METHOD_NAME,
4847 #[cfg(feature = "unstable_nes")]
4848 nes_accept: NES_ACCEPT_METHOD_NAME,
4849 #[cfg(feature = "unstable_nes")]
4850 nes_reject: NES_REJECT_METHOD_NAME,
4851 #[cfg(feature = "unstable_nes")]
4852 nes_close: NES_CLOSE_METHOD_NAME,
4853 #[cfg(feature = "unstable_nes")]
4854 document_did_open: DOCUMENT_DID_OPEN_METHOD_NAME,
4855 #[cfg(feature = "unstable_nes")]
4856 document_did_change: DOCUMENT_DID_CHANGE_METHOD_NAME,
4857 #[cfg(feature = "unstable_nes")]
4858 document_did_close: DOCUMENT_DID_CLOSE_METHOD_NAME,
4859 #[cfg(feature = "unstable_nes")]
4860 document_did_save: DOCUMENT_DID_SAVE_METHOD_NAME,
4861 #[cfg(feature = "unstable_nes")]
4862 document_did_focus: DOCUMENT_DID_FOCUS_METHOD_NAME,
4863};
4864
4865pub(crate) const INITIALIZE_METHOD_NAME: &str = "initialize";
4867pub(crate) const AUTHENTICATE_METHOD_NAME: &str = "authenticate";
4869#[cfg(feature = "unstable_llm_providers")]
4871pub(crate) const PROVIDERS_LIST_METHOD_NAME: &str = "providers/list";
4872#[cfg(feature = "unstable_llm_providers")]
4874pub(crate) const PROVIDERS_SET_METHOD_NAME: &str = "providers/set";
4875#[cfg(feature = "unstable_llm_providers")]
4877pub(crate) const PROVIDERS_DISABLE_METHOD_NAME: &str = "providers/disable";
4878pub(crate) const SESSION_NEW_METHOD_NAME: &str = "session/new";
4880pub(crate) const SESSION_LOAD_METHOD_NAME: &str = "session/load";
4882pub(crate) const SESSION_SET_MODE_METHOD_NAME: &str = "session/set_mode";
4884pub(crate) const SESSION_SET_CONFIG_OPTION_METHOD_NAME: &str = "session/set_config_option";
4886pub(crate) const SESSION_PROMPT_METHOD_NAME: &str = "session/prompt";
4888pub(crate) const SESSION_CANCEL_METHOD_NAME: &str = "session/cancel";
4890#[cfg(feature = "unstable_session_model")]
4892pub(crate) const SESSION_SET_MODEL_METHOD_NAME: &str = "session/set_model";
4893pub(crate) const SESSION_LIST_METHOD_NAME: &str = "session/list";
4895#[cfg(feature = "unstable_session_delete")]
4897pub(crate) const SESSION_DELETE_METHOD_NAME: &str = "session/delete";
4898#[cfg(feature = "unstable_session_fork")]
4900pub(crate) const SESSION_FORK_METHOD_NAME: &str = "session/fork";
4901pub(crate) const SESSION_RESUME_METHOD_NAME: &str = "session/resume";
4903pub(crate) const SESSION_CLOSE_METHOD_NAME: &str = "session/close";
4905#[cfg(feature = "unstable_logout")]
4907pub(crate) const LOGOUT_METHOD_NAME: &str = "logout";
4908
4909#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
4916#[serde(untagged)]
4917#[schemars(inline)]
4918#[non_exhaustive]
4919#[allow(clippy::large_enum_variant)]
4920pub enum ClientRequest {
4921 InitializeRequest(InitializeRequest),
4932 AuthenticateRequest(AuthenticateRequest),
4942 #[cfg(feature = "unstable_llm_providers")]
4948 ListProvidersRequest(ListProvidersRequest),
4949 #[cfg(feature = "unstable_llm_providers")]
4955 SetProvidersRequest(SetProvidersRequest),
4956 #[cfg(feature = "unstable_llm_providers")]
4962 DisableProvidersRequest(DisableProvidersRequest),
4963 #[cfg(feature = "unstable_logout")]
4972 LogoutRequest(LogoutRequest),
4973 NewSessionRequest(NewSessionRequest),
4986 LoadSessionRequest(LoadSessionRequest),
4997 ListSessionsRequest(ListSessionsRequest),
5003 #[cfg(feature = "unstable_session_delete")]
5011 DeleteSessionRequest(DeleteSessionRequest),
5012 #[cfg(feature = "unstable_session_fork")]
5013 ForkSessionRequest(ForkSessionRequest),
5025 ResumeSessionRequest(ResumeSessionRequest),
5032 CloseSessionRequest(CloseSessionRequest),
5039 SetSessionModeRequest(SetSessionModeRequest),
5053 SetSessionConfigOptionRequest(SetSessionConfigOptionRequest),
5055 PromptRequest(PromptRequest),
5067 #[cfg(feature = "unstable_session_model")]
5068 SetSessionModelRequest(SetSessionModelRequest),
5074 #[cfg(feature = "unstable_nes")]
5075 StartNesRequest(StartNesRequest),
5081 #[cfg(feature = "unstable_nes")]
5082 SuggestNesRequest(SuggestNesRequest),
5088 #[cfg(feature = "unstable_nes")]
5089 CloseNesRequest(CloseNesRequest),
5098 #[cfg(feature = "unstable_mcp_over_acp")]
5104 MessageMcpRequest(MessageMcpRequest),
5105 ExtMethodRequest(ExtRequest),
5112}
5113
5114impl ClientRequest {
5115 #[must_use]
5117 pub fn method(&self) -> &str {
5118 match self {
5119 Self::InitializeRequest(_) => AGENT_METHOD_NAMES.initialize,
5120 Self::AuthenticateRequest(_) => AGENT_METHOD_NAMES.authenticate,
5121 #[cfg(feature = "unstable_llm_providers")]
5122 Self::ListProvidersRequest(_) => AGENT_METHOD_NAMES.providers_list,
5123 #[cfg(feature = "unstable_llm_providers")]
5124 Self::SetProvidersRequest(_) => AGENT_METHOD_NAMES.providers_set,
5125 #[cfg(feature = "unstable_llm_providers")]
5126 Self::DisableProvidersRequest(_) => AGENT_METHOD_NAMES.providers_disable,
5127 #[cfg(feature = "unstable_logout")]
5128 Self::LogoutRequest(_) => AGENT_METHOD_NAMES.logout,
5129 Self::NewSessionRequest(_) => AGENT_METHOD_NAMES.session_new,
5130 Self::LoadSessionRequest(_) => AGENT_METHOD_NAMES.session_load,
5131 Self::ListSessionsRequest(_) => AGENT_METHOD_NAMES.session_list,
5132 #[cfg(feature = "unstable_session_delete")]
5133 Self::DeleteSessionRequest(_) => AGENT_METHOD_NAMES.session_delete,
5134 #[cfg(feature = "unstable_session_fork")]
5135 Self::ForkSessionRequest(_) => AGENT_METHOD_NAMES.session_fork,
5136 Self::ResumeSessionRequest(_) => AGENT_METHOD_NAMES.session_resume,
5137 Self::CloseSessionRequest(_) => AGENT_METHOD_NAMES.session_close,
5138 Self::SetSessionModeRequest(_) => AGENT_METHOD_NAMES.session_set_mode,
5139 Self::SetSessionConfigOptionRequest(_) => AGENT_METHOD_NAMES.session_set_config_option,
5140 Self::PromptRequest(_) => AGENT_METHOD_NAMES.session_prompt,
5141 #[cfg(feature = "unstable_session_model")]
5142 Self::SetSessionModelRequest(_) => AGENT_METHOD_NAMES.session_set_model,
5143 #[cfg(feature = "unstable_nes")]
5144 Self::StartNesRequest(_) => AGENT_METHOD_NAMES.nes_start,
5145 #[cfg(feature = "unstable_nes")]
5146 Self::SuggestNesRequest(_) => AGENT_METHOD_NAMES.nes_suggest,
5147 #[cfg(feature = "unstable_nes")]
5148 Self::CloseNesRequest(_) => AGENT_METHOD_NAMES.nes_close,
5149 #[cfg(feature = "unstable_mcp_over_acp")]
5150 Self::MessageMcpRequest(_) => AGENT_METHOD_NAMES.mcp_message,
5151 Self::ExtMethodRequest(ext_request) => &ext_request.method,
5152 }
5153 }
5154}
5155
5156#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
5163#[serde(untagged)]
5164#[schemars(inline)]
5165#[non_exhaustive]
5166#[allow(clippy::large_enum_variant)]
5167pub enum AgentResponse {
5168 InitializeResponse(InitializeResponse),
5169 AuthenticateResponse(#[serde(default)] AuthenticateResponse),
5170 #[cfg(feature = "unstable_llm_providers")]
5171 ListProvidersResponse(ListProvidersResponse),
5172 #[cfg(feature = "unstable_llm_providers")]
5173 SetProvidersResponse(#[serde(default)] SetProvidersResponse),
5174 #[cfg(feature = "unstable_llm_providers")]
5175 DisableProvidersResponse(#[serde(default)] DisableProvidersResponse),
5176 #[cfg(feature = "unstable_logout")]
5177 LogoutResponse(#[serde(default)] LogoutResponse),
5178 NewSessionResponse(NewSessionResponse),
5179 LoadSessionResponse(#[serde(default)] LoadSessionResponse),
5180 ListSessionsResponse(ListSessionsResponse),
5181 #[cfg(feature = "unstable_session_delete")]
5182 DeleteSessionResponse(#[serde(default)] DeleteSessionResponse),
5183 #[cfg(feature = "unstable_session_fork")]
5184 ForkSessionResponse(ForkSessionResponse),
5185 ResumeSessionResponse(#[serde(default)] ResumeSessionResponse),
5186 CloseSessionResponse(#[serde(default)] CloseSessionResponse),
5187 SetSessionModeResponse(#[serde(default)] SetSessionModeResponse),
5188 SetSessionConfigOptionResponse(SetSessionConfigOptionResponse),
5189 PromptResponse(PromptResponse),
5190 #[cfg(feature = "unstable_session_model")]
5191 SetSessionModelResponse(#[serde(default)] SetSessionModelResponse),
5192 #[cfg(feature = "unstable_nes")]
5193 StartNesResponse(StartNesResponse),
5194 #[cfg(feature = "unstable_nes")]
5195 SuggestNesResponse(SuggestNesResponse),
5196 #[cfg(feature = "unstable_nes")]
5197 CloseNesResponse(#[serde(default)] CloseNesResponse),
5198 ExtMethodResponse(ExtResponse),
5199 #[cfg(feature = "unstable_mcp_over_acp")]
5200 MessageMcpResponse(MessageMcpResponse),
5201}
5202
5203#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
5210#[serde(untagged)]
5211#[schemars(inline)]
5212#[non_exhaustive]
5213pub enum ClientNotification {
5214 CancelNotification(CancelNotification),
5226 #[cfg(feature = "unstable_nes")]
5227 DidOpenDocumentNotification(DidOpenDocumentNotification),
5231 #[cfg(feature = "unstable_nes")]
5232 DidChangeDocumentNotification(DidChangeDocumentNotification),
5236 #[cfg(feature = "unstable_nes")]
5237 DidCloseDocumentNotification(DidCloseDocumentNotification),
5241 #[cfg(feature = "unstable_nes")]
5242 DidSaveDocumentNotification(DidSaveDocumentNotification),
5246 #[cfg(feature = "unstable_nes")]
5247 DidFocusDocumentNotification(DidFocusDocumentNotification),
5251 #[cfg(feature = "unstable_nes")]
5252 AcceptNesNotification(AcceptNesNotification),
5256 #[cfg(feature = "unstable_nes")]
5257 RejectNesNotification(RejectNesNotification),
5261 #[cfg(feature = "unstable_mcp_over_acp")]
5267 MessageMcpNotification(MessageMcpNotification),
5268 ExtNotification(ExtNotification),
5275}
5276
5277impl ClientNotification {
5278 #[must_use]
5280 pub fn method(&self) -> &str {
5281 match self {
5282 Self::CancelNotification(_) => AGENT_METHOD_NAMES.session_cancel,
5283 #[cfg(feature = "unstable_nes")]
5284 Self::DidOpenDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_open,
5285 #[cfg(feature = "unstable_nes")]
5286 Self::DidChangeDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_change,
5287 #[cfg(feature = "unstable_nes")]
5288 Self::DidCloseDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_close,
5289 #[cfg(feature = "unstable_nes")]
5290 Self::DidSaveDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_save,
5291 #[cfg(feature = "unstable_nes")]
5292 Self::DidFocusDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_focus,
5293 #[cfg(feature = "unstable_nes")]
5294 Self::AcceptNesNotification(_) => AGENT_METHOD_NAMES.nes_accept,
5295 #[cfg(feature = "unstable_nes")]
5296 Self::RejectNesNotification(_) => AGENT_METHOD_NAMES.nes_reject,
5297 #[cfg(feature = "unstable_mcp_over_acp")]
5298 Self::MessageMcpNotification(_) => AGENT_METHOD_NAMES.mcp_message,
5299 Self::ExtNotification(ext_notification) => &ext_notification.method,
5300 }
5301 }
5302}
5303
5304#[skip_serializing_none]
5308#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
5309#[schemars(extend("x-side" = "agent", "x-method" = SESSION_CANCEL_METHOD_NAME))]
5310#[serde(rename_all = "camelCase")]
5311#[non_exhaustive]
5312pub struct CancelNotification {
5313 pub session_id: SessionId,
5315 #[serde(rename = "_meta")]
5321 pub meta: Option<Meta>,
5322}
5323
5324impl CancelNotification {
5325 #[must_use]
5326 pub fn new(session_id: impl Into<SessionId>) -> Self {
5327 Self {
5328 session_id: session_id.into(),
5329 meta: None,
5330 }
5331 }
5332
5333 #[must_use]
5339 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5340 self.meta = meta.into_option();
5341 self
5342 }
5343}
5344
5345#[cfg(test)]
5346mod test_serialization {
5347 use super::*;
5348 use serde_json::json;
5349
5350 #[test]
5351 fn test_mcp_server_stdio_serialization() {
5352 let server = McpServer::Stdio(
5353 McpServerStdio::new("test-server", "/usr/bin/server")
5354 .args(vec!["--port".to_string(), "3000".to_string()])
5355 .env(vec![EnvVariable::new("API_KEY", "secret123")]),
5356 );
5357
5358 let json = serde_json::to_value(&server).unwrap();
5359 assert_eq!(
5360 json,
5361 json!({
5362 "name": "test-server",
5363 "command": "/usr/bin/server",
5364 "args": ["--port", "3000"],
5365 "env": [
5366 {
5367 "name": "API_KEY",
5368 "value": "secret123"
5369 }
5370 ]
5371 })
5372 );
5373
5374 let deserialized: McpServer = serde_json::from_value(json).unwrap();
5375 match deserialized {
5376 McpServer::Stdio(McpServerStdio {
5377 name,
5378 command,
5379 args,
5380 env,
5381 meta: _,
5382 }) => {
5383 assert_eq!(name, "test-server");
5384 assert_eq!(command, PathBuf::from("/usr/bin/server"));
5385 assert_eq!(args, vec!["--port", "3000"]);
5386 assert_eq!(env.len(), 1);
5387 assert_eq!(env[0].name, "API_KEY");
5388 assert_eq!(env[0].value, "secret123");
5389 }
5390 _ => panic!("Expected Stdio variant"),
5391 }
5392 }
5393
5394 #[test]
5395 fn test_mcp_server_http_serialization() {
5396 let server = McpServer::Http(
5397 McpServerHttp::new("http-server", "https://api.example.com").headers(vec![
5398 HttpHeader::new("Authorization", "Bearer token123"),
5399 HttpHeader::new("Content-Type", "application/json"),
5400 ]),
5401 );
5402
5403 let json = serde_json::to_value(&server).unwrap();
5404 assert_eq!(
5405 json,
5406 json!({
5407 "type": "http",
5408 "name": "http-server",
5409 "url": "https://api.example.com",
5410 "headers": [
5411 {
5412 "name": "Authorization",
5413 "value": "Bearer token123"
5414 },
5415 {
5416 "name": "Content-Type",
5417 "value": "application/json"
5418 }
5419 ]
5420 })
5421 );
5422
5423 let deserialized: McpServer = serde_json::from_value(json).unwrap();
5424 match deserialized {
5425 McpServer::Http(McpServerHttp {
5426 name,
5427 url,
5428 headers,
5429 meta: _,
5430 }) => {
5431 assert_eq!(name, "http-server");
5432 assert_eq!(url, "https://api.example.com");
5433 assert_eq!(headers.len(), 2);
5434 assert_eq!(headers[0].name, "Authorization");
5435 assert_eq!(headers[0].value, "Bearer token123");
5436 assert_eq!(headers[1].name, "Content-Type");
5437 assert_eq!(headers[1].value, "application/json");
5438 }
5439 _ => panic!("Expected Http variant"),
5440 }
5441 }
5442
5443 #[cfg(feature = "unstable_mcp_over_acp")]
5444 #[test]
5445 fn test_mcp_server_acp_serialization() {
5446 let server = McpServer::Acp(McpServerAcp::new("project-tools", "project-tools-id"));
5447
5448 let json = serde_json::to_value(&server).unwrap();
5449 assert_eq!(
5450 json,
5451 json!({
5452 "type": "acp",
5453 "name": "project-tools",
5454 "id": "project-tools-id"
5455 })
5456 );
5457
5458 let deserialized: McpServer = serde_json::from_value(json).unwrap();
5459 match deserialized {
5460 McpServer::Acp(McpServerAcp { name, id, meta: _ }) => {
5461 assert_eq!(name, "project-tools");
5462 assert_eq!(id, McpServerAcpId::new("project-tools-id"));
5463 }
5464 _ => panic!("Expected Acp variant"),
5465 }
5466 }
5467
5468 #[cfg(feature = "unstable_mcp_over_acp")]
5469 #[test]
5470 fn test_client_mcp_message_method_names() {
5471 assert_eq!(AGENT_METHOD_NAMES.mcp_message, "mcp/message");
5472
5473 assert_eq!(
5474 ClientRequest::MessageMcpRequest(MessageMcpRequest::new("conn-1", "tools/list"))
5475 .method(),
5476 "mcp/message"
5477 );
5478 assert_eq!(
5479 ClientNotification::MessageMcpNotification(MessageMcpNotification::new(
5480 "conn-1",
5481 "notifications/progress"
5482 ))
5483 .method(),
5484 "mcp/message"
5485 );
5486 }
5487
5488 #[cfg(feature = "unstable_mcp_over_acp")]
5489 #[test]
5490 fn test_mcp_server_acp_schema() {
5491 let mcp_server_schema = serde_json::to_value(schemars::schema_for!(McpServer)).unwrap();
5492 assert!(json_contains_entry(
5493 &mcp_server_schema,
5494 "const",
5495 &json!("acp")
5496 ));
5497 assert!(json_contains_entry(
5498 &mcp_server_schema,
5499 "$ref",
5500 &json!("#/$defs/McpServerAcp")
5501 ));
5502
5503 let capabilities_schema =
5504 serde_json::to_value(schemars::schema_for!(McpCapabilities)).unwrap();
5505 assert!(json_contains_key(&capabilities_schema, "acp"));
5506 }
5507
5508 #[cfg(feature = "unstable_mcp_over_acp")]
5509 fn json_contains_entry(
5510 value: &serde_json::Value,
5511 key: &str,
5512 expected: &serde_json::Value,
5513 ) -> bool {
5514 match value {
5515 serde_json::Value::Object(map) => {
5516 map.get(key) == Some(expected)
5517 || map
5518 .values()
5519 .any(|value| json_contains_entry(value, key, expected))
5520 }
5521 serde_json::Value::Array(values) => values
5522 .iter()
5523 .any(|value| json_contains_entry(value, key, expected)),
5524 _ => false,
5525 }
5526 }
5527
5528 #[cfg(feature = "unstable_mcp_over_acp")]
5529 fn json_contains_key(value: &serde_json::Value, key: &str) -> bool {
5530 match value {
5531 serde_json::Value::Object(map) => {
5532 map.contains_key(key) || map.values().any(|value| json_contains_key(value, key))
5533 }
5534 serde_json::Value::Array(values) => {
5535 values.iter().any(|value| json_contains_key(value, key))
5536 }
5537 _ => false,
5538 }
5539 }
5540
5541 #[test]
5542 fn test_mcp_server_sse_serialization() {
5543 let server = McpServer::Sse(
5544 McpServerSse::new("sse-server", "https://sse.example.com/events")
5545 .headers(vec![HttpHeader::new("X-API-Key", "apikey456")]),
5546 );
5547
5548 let json = serde_json::to_value(&server).unwrap();
5549 assert_eq!(
5550 json,
5551 json!({
5552 "type": "sse",
5553 "name": "sse-server",
5554 "url": "https://sse.example.com/events",
5555 "headers": [
5556 {
5557 "name": "X-API-Key",
5558 "value": "apikey456"
5559 }
5560 ]
5561 })
5562 );
5563
5564 let deserialized: McpServer = serde_json::from_value(json).unwrap();
5565 match deserialized {
5566 McpServer::Sse(McpServerSse {
5567 name,
5568 url,
5569 headers,
5570 meta: _,
5571 }) => {
5572 assert_eq!(name, "sse-server");
5573 assert_eq!(url, "https://sse.example.com/events");
5574 assert_eq!(headers.len(), 1);
5575 assert_eq!(headers[0].name, "X-API-Key");
5576 assert_eq!(headers[0].value, "apikey456");
5577 }
5578 _ => panic!("Expected Sse variant"),
5579 }
5580 }
5581
5582 #[test]
5583 fn test_session_config_option_category_known_variants() {
5584 assert_eq!(
5586 serde_json::to_value(&SessionConfigOptionCategory::Mode).unwrap(),
5587 json!("mode")
5588 );
5589 assert_eq!(
5590 serde_json::to_value(&SessionConfigOptionCategory::Model).unwrap(),
5591 json!("model")
5592 );
5593 assert_eq!(
5594 serde_json::to_value(&SessionConfigOptionCategory::ThoughtLevel).unwrap(),
5595 json!("thought_level")
5596 );
5597
5598 assert_eq!(
5600 serde_json::from_str::<SessionConfigOptionCategory>("\"mode\"").unwrap(),
5601 SessionConfigOptionCategory::Mode
5602 );
5603 assert_eq!(
5604 serde_json::from_str::<SessionConfigOptionCategory>("\"model\"").unwrap(),
5605 SessionConfigOptionCategory::Model
5606 );
5607 assert_eq!(
5608 serde_json::from_str::<SessionConfigOptionCategory>("\"thought_level\"").unwrap(),
5609 SessionConfigOptionCategory::ThoughtLevel
5610 );
5611 }
5612
5613 #[test]
5614 fn test_session_config_option_category_unknown_variants() {
5615 let unknown: SessionConfigOptionCategory =
5617 serde_json::from_str("\"some_future_category\"").unwrap();
5618 assert_eq!(
5619 unknown,
5620 SessionConfigOptionCategory::Other("some_future_category".to_string())
5621 );
5622
5623 let json = serde_json::to_value(&unknown).unwrap();
5625 assert_eq!(json, json!("some_future_category"));
5626 }
5627
5628 #[test]
5629 fn test_session_config_option_category_custom_categories() {
5630 let custom: SessionConfigOptionCategory =
5632 serde_json::from_str("\"_my_custom_category\"").unwrap();
5633 assert_eq!(
5634 custom,
5635 SessionConfigOptionCategory::Other("_my_custom_category".to_string())
5636 );
5637
5638 let json = serde_json::to_value(&custom).unwrap();
5640 assert_eq!(json, json!("_my_custom_category"));
5641
5642 let deserialized: SessionConfigOptionCategory = serde_json::from_value(json).unwrap();
5644 assert_eq!(
5645 deserialized,
5646 SessionConfigOptionCategory::Other("_my_custom_category".to_string()),
5647 );
5648 }
5649
5650 #[test]
5651 fn test_auth_method_agent_serialization() {
5652 let method = AuthMethod::Agent(AuthMethodAgent::new("default-auth", "Default Auth"));
5653
5654 let json = serde_json::to_value(&method).unwrap();
5655 assert_eq!(
5656 json,
5657 json!({
5658 "id": "default-auth",
5659 "name": "Default Auth"
5660 })
5661 );
5662 assert!(!json.as_object().unwrap().contains_key("description"));
5664 assert!(!json.as_object().unwrap().contains_key("type"));
5666
5667 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5668 match deserialized {
5669 AuthMethod::Agent(AuthMethodAgent { id, name, .. }) => {
5670 assert_eq!(id.0.as_ref(), "default-auth");
5671 assert_eq!(name, "Default Auth");
5672 }
5673 #[cfg(feature = "unstable_auth_methods")]
5674 _ => panic!("Expected Agent variant"),
5675 }
5676 }
5677
5678 #[test]
5679 fn test_auth_method_explicit_agent_deserialization() {
5680 let json = json!({
5682 "id": "agent-auth",
5683 "name": "Agent Auth",
5684 "type": "agent"
5685 });
5686
5687 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5688 assert!(matches!(deserialized, AuthMethod::Agent(_)));
5689 }
5690
5691 #[cfg(feature = "unstable_session_delete")]
5692 #[test]
5693 fn test_session_delete_serialization() {
5694 assert_eq!(AGENT_METHOD_NAMES.session_delete, "session/delete");
5695 assert_eq!(
5696 ClientRequest::DeleteSessionRequest(DeleteSessionRequest::new("sess_abc123")).method(),
5697 "session/delete"
5698 );
5699 assert_eq!(
5700 serde_json::to_value(DeleteSessionRequest::new("sess_abc123")).unwrap(),
5701 json!({
5702 "sessionId": "sess_abc123"
5703 })
5704 );
5705 assert_eq!(
5706 serde_json::to_value(DeleteSessionResponse::new()).unwrap(),
5707 json!({})
5708 );
5709 assert_eq!(
5710 serde_json::to_value(
5711 SessionCapabilities::new().delete(SessionDeleteCapabilities::new())
5712 )
5713 .unwrap(),
5714 json!({
5715 "delete": {}
5716 })
5717 );
5718 }
5719
5720 #[cfg(feature = "unstable_session_additional_directories")]
5721 #[test]
5722 fn test_session_additional_directories_serialization() {
5723 assert_eq!(
5724 serde_json::to_value(NewSessionRequest::new("/home/user/project")).unwrap(),
5725 json!({
5726 "cwd": "/home/user/project",
5727 "mcpServers": []
5728 })
5729 );
5730 assert_eq!(
5731 serde_json::to_value(
5732 NewSessionRequest::new("/home/user/project").additional_directories(vec![
5733 PathBuf::from("/home/user/shared-lib"),
5734 PathBuf::from("/home/user/product-docs"),
5735 ])
5736 )
5737 .unwrap(),
5738 json!({
5739 "cwd": "/home/user/project",
5740 "additionalDirectories": [
5741 "/home/user/shared-lib",
5742 "/home/user/product-docs"
5743 ],
5744 "mcpServers": []
5745 })
5746 );
5747 assert_eq!(
5748 serde_json::to_value(SessionInfo::new("sess_abc123", "/home/user/project")).unwrap(),
5749 json!({
5750 "sessionId": "sess_abc123",
5751 "cwd": "/home/user/project"
5752 })
5753 );
5754 assert_eq!(
5755 serde_json::to_value(
5756 SessionInfo::new("sess_abc123", "/home/user/project").additional_directories(vec![
5757 PathBuf::from("/home/user/shared-lib"),
5758 PathBuf::from("/home/user/product-docs"),
5759 ])
5760 )
5761 .unwrap(),
5762 json!({
5763 "sessionId": "sess_abc123",
5764 "cwd": "/home/user/project",
5765 "additionalDirectories": [
5766 "/home/user/shared-lib",
5767 "/home/user/product-docs"
5768 ]
5769 })
5770 );
5771 assert_eq!(
5772 serde_json::from_value::<SessionInfo>(json!({
5773 "sessionId": "sess_abc123",
5774 "cwd": "/home/user/project"
5775 }))
5776 .unwrap()
5777 .additional_directories,
5778 Vec::<PathBuf>::new()
5779 );
5780 }
5781
5782 #[cfg(feature = "unstable_session_additional_directories")]
5783 #[test]
5784 fn test_session_additional_directories_capabilities_serialization() {
5785 assert_eq!(
5786 serde_json::to_value(
5787 SessionCapabilities::new()
5788 .additional_directories(SessionAdditionalDirectoriesCapabilities::new())
5789 )
5790 .unwrap(),
5791 json!({
5792 "additionalDirectories": {}
5793 })
5794 );
5795 }
5796
5797 #[cfg(feature = "unstable_auth_methods")]
5798 #[test]
5799 fn test_auth_method_env_var_serialization() {
5800 let method = AuthMethod::EnvVar(AuthMethodEnvVar::new(
5801 "api-key",
5802 "API Key",
5803 vec![AuthEnvVar::new("API_KEY")],
5804 ));
5805
5806 let json = serde_json::to_value(&method).unwrap();
5807 assert_eq!(
5808 json,
5809 json!({
5810 "id": "api-key",
5811 "name": "API Key",
5812 "type": "env_var",
5813 "vars": [{"name": "API_KEY"}]
5814 })
5815 );
5816 assert!(!json["vars"][0].as_object().unwrap().contains_key("secret"));
5818 assert!(
5819 !json["vars"][0]
5820 .as_object()
5821 .unwrap()
5822 .contains_key("optional")
5823 );
5824
5825 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5826 match deserialized {
5827 AuthMethod::EnvVar(AuthMethodEnvVar {
5828 id,
5829 name: method_name,
5830 vars,
5831 link,
5832 ..
5833 }) => {
5834 assert_eq!(id.0.as_ref(), "api-key");
5835 assert_eq!(method_name, "API Key");
5836 assert_eq!(vars.len(), 1);
5837 assert_eq!(vars[0].name, "API_KEY");
5838 assert!(vars[0].secret);
5839 assert!(!vars[0].optional);
5840 assert!(link.is_none());
5841 }
5842 _ => panic!("Expected EnvVar variant"),
5843 }
5844 }
5845
5846 #[cfg(feature = "unstable_auth_methods")]
5847 #[test]
5848 fn test_auth_method_env_var_with_link_serialization() {
5849 let method = AuthMethod::EnvVar(
5850 AuthMethodEnvVar::new("api-key", "API Key", vec![AuthEnvVar::new("API_KEY")])
5851 .link("https://example.com/keys"),
5852 );
5853
5854 let json = serde_json::to_value(&method).unwrap();
5855 assert_eq!(
5856 json,
5857 json!({
5858 "id": "api-key",
5859 "name": "API Key",
5860 "type": "env_var",
5861 "vars": [{"name": "API_KEY"}],
5862 "link": "https://example.com/keys"
5863 })
5864 );
5865
5866 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5867 match deserialized {
5868 AuthMethod::EnvVar(AuthMethodEnvVar { link, .. }) => {
5869 assert_eq!(link.as_deref(), Some("https://example.com/keys"));
5870 }
5871 _ => panic!("Expected EnvVar variant"),
5872 }
5873 }
5874
5875 #[cfg(feature = "unstable_auth_methods")]
5876 #[test]
5877 fn test_auth_method_env_var_multiple_vars() {
5878 let method = AuthMethod::EnvVar(AuthMethodEnvVar::new(
5879 "azure-openai",
5880 "Azure OpenAI",
5881 vec![
5882 AuthEnvVar::new("AZURE_OPENAI_API_KEY").label("API Key"),
5883 AuthEnvVar::new("AZURE_OPENAI_ENDPOINT")
5884 .label("Endpoint URL")
5885 .secret(false),
5886 AuthEnvVar::new("AZURE_OPENAI_API_VERSION")
5887 .label("API Version")
5888 .secret(false)
5889 .optional(true),
5890 ],
5891 ));
5892
5893 let json = serde_json::to_value(&method).unwrap();
5894 assert_eq!(
5895 json,
5896 json!({
5897 "id": "azure-openai",
5898 "name": "Azure OpenAI",
5899 "type": "env_var",
5900 "vars": [
5901 {"name": "AZURE_OPENAI_API_KEY", "label": "API Key"},
5902 {"name": "AZURE_OPENAI_ENDPOINT", "label": "Endpoint URL", "secret": false},
5903 {"name": "AZURE_OPENAI_API_VERSION", "label": "API Version", "secret": false, "optional": true}
5904 ]
5905 })
5906 );
5907
5908 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5909 match deserialized {
5910 AuthMethod::EnvVar(AuthMethodEnvVar { vars, .. }) => {
5911 assert_eq!(vars.len(), 3);
5912 assert_eq!(vars[0].name, "AZURE_OPENAI_API_KEY");
5914 assert_eq!(vars[0].label.as_deref(), Some("API Key"));
5915 assert!(vars[0].secret);
5916 assert!(!vars[0].optional);
5917 assert_eq!(vars[1].name, "AZURE_OPENAI_ENDPOINT");
5919 assert!(!vars[1].secret);
5920 assert!(!vars[1].optional);
5921 assert_eq!(vars[2].name, "AZURE_OPENAI_API_VERSION");
5923 assert!(!vars[2].secret);
5924 assert!(vars[2].optional);
5925 }
5926 _ => panic!("Expected EnvVar variant"),
5927 }
5928 }
5929
5930 #[cfg(feature = "unstable_auth_methods")]
5931 #[test]
5932 fn test_auth_method_terminal_serialization() {
5933 let method = AuthMethod::Terminal(AuthMethodTerminal::new("tui-auth", "Terminal Auth"));
5934
5935 let json = serde_json::to_value(&method).unwrap();
5936 assert_eq!(
5937 json,
5938 json!({
5939 "id": "tui-auth",
5940 "name": "Terminal Auth",
5941 "type": "terminal"
5942 })
5943 );
5944 assert!(!json.as_object().unwrap().contains_key("args"));
5946 assert!(!json.as_object().unwrap().contains_key("env"));
5947
5948 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5949 match deserialized {
5950 AuthMethod::Terminal(AuthMethodTerminal { args, env, .. }) => {
5951 assert!(args.is_empty());
5952 assert!(env.is_empty());
5953 }
5954 _ => panic!("Expected Terminal variant"),
5955 }
5956 }
5957
5958 #[cfg(feature = "unstable_auth_methods")]
5959 #[test]
5960 fn test_auth_method_terminal_with_args_and_env_serialization() {
5961 use std::collections::HashMap;
5962
5963 let mut env = HashMap::new();
5964 env.insert("TERM".to_string(), "xterm-256color".to_string());
5965
5966 let method = AuthMethod::Terminal(
5967 AuthMethodTerminal::new("tui-auth", "Terminal Auth")
5968 .args(vec!["--interactive".to_string(), "--color".to_string()])
5969 .env(env),
5970 );
5971
5972 let json = serde_json::to_value(&method).unwrap();
5973 assert_eq!(
5974 json,
5975 json!({
5976 "id": "tui-auth",
5977 "name": "Terminal Auth",
5978 "type": "terminal",
5979 "args": ["--interactive", "--color"],
5980 "env": {
5981 "TERM": "xterm-256color"
5982 }
5983 })
5984 );
5985
5986 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5987 match deserialized {
5988 AuthMethod::Terminal(AuthMethodTerminal { args, env, .. }) => {
5989 assert_eq!(args, vec!["--interactive", "--color"]);
5990 assert_eq!(env.len(), 1);
5991 assert_eq!(env.get("TERM").unwrap(), "xterm-256color");
5992 }
5993 _ => panic!("Expected Terminal variant"),
5994 }
5995 }
5996
5997 #[cfg(feature = "unstable_boolean_config")]
5998 #[test]
5999 fn test_session_config_option_value_id_serialize() {
6000 let val = SessionConfigOptionValue::value_id("model-1");
6001 let json = serde_json::to_value(&val).unwrap();
6002 assert_eq!(json, json!({ "value": "model-1" }));
6004 assert!(!json.as_object().unwrap().contains_key("type"));
6005 }
6006
6007 #[cfg(feature = "unstable_boolean_config")]
6008 #[test]
6009 fn test_session_config_option_value_boolean_serialize() {
6010 let val = SessionConfigOptionValue::boolean(true);
6011 let json = serde_json::to_value(&val).unwrap();
6012 assert_eq!(json, json!({ "type": "boolean", "value": true }));
6013 }
6014
6015 #[cfg(feature = "unstable_boolean_config")]
6016 #[test]
6017 fn test_session_config_option_value_deserialize_no_type() {
6018 let json = json!({ "value": "model-1" });
6020 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
6021 assert_eq!(val, SessionConfigOptionValue::value_id("model-1"));
6022 assert_eq!(val.as_value_id().unwrap().to_string(), "model-1");
6023 }
6024
6025 #[cfg(feature = "unstable_boolean_config")]
6026 #[test]
6027 fn test_session_config_option_value_deserialize_boolean() {
6028 let json = json!({ "type": "boolean", "value": true });
6029 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
6030 assert_eq!(val, SessionConfigOptionValue::boolean(true));
6031 assert_eq!(val.as_bool(), Some(true));
6032 }
6033
6034 #[cfg(feature = "unstable_boolean_config")]
6035 #[test]
6036 fn test_session_config_option_value_deserialize_boolean_false() {
6037 let json = json!({ "type": "boolean", "value": false });
6038 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
6039 assert_eq!(val, SessionConfigOptionValue::boolean(false));
6040 assert_eq!(val.as_bool(), Some(false));
6041 }
6042
6043 #[cfg(feature = "unstable_boolean_config")]
6044 #[test]
6045 fn test_session_config_option_value_deserialize_unknown_type_with_string_value() {
6046 let json = json!({ "type": "text", "value": "freeform input" });
6048 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
6049 assert_eq!(val.as_value_id().unwrap().to_string(), "freeform input");
6050 }
6051
6052 #[cfg(feature = "unstable_boolean_config")]
6053 #[test]
6054 fn test_session_config_option_value_roundtrip_value_id() {
6055 let original = SessionConfigOptionValue::value_id("option-a");
6056 let json = serde_json::to_value(&original).unwrap();
6057 let roundtripped: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
6058 assert_eq!(original, roundtripped);
6059 }
6060
6061 #[cfg(feature = "unstable_boolean_config")]
6062 #[test]
6063 fn test_session_config_option_value_roundtrip_boolean() {
6064 let original = SessionConfigOptionValue::boolean(false);
6065 let json = serde_json::to_value(&original).unwrap();
6066 let roundtripped: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
6067 assert_eq!(original, roundtripped);
6068 }
6069
6070 #[cfg(feature = "unstable_boolean_config")]
6071 #[test]
6072 fn test_session_config_option_value_type_mismatch_boolean_with_string() {
6073 let json = json!({ "type": "boolean", "value": "not a bool" });
6075 let result = serde_json::from_value::<SessionConfigOptionValue>(json);
6076 assert!(result.is_ok());
6078 assert_eq!(
6079 result.unwrap().as_value_id().unwrap().to_string(),
6080 "not a bool"
6081 );
6082 }
6083
6084 #[cfg(feature = "unstable_boolean_config")]
6085 #[test]
6086 fn test_session_config_option_value_from_impls() {
6087 let from_str: SessionConfigOptionValue = "model-1".into();
6088 assert_eq!(from_str.as_value_id().unwrap().to_string(), "model-1");
6089
6090 let from_id: SessionConfigOptionValue = SessionConfigValueId::new("model-2").into();
6091 assert_eq!(from_id.as_value_id().unwrap().to_string(), "model-2");
6092
6093 let from_bool: SessionConfigOptionValue = true.into();
6094 assert_eq!(from_bool.as_bool(), Some(true));
6095 }
6096
6097 #[cfg(feature = "unstable_boolean_config")]
6098 #[test]
6099 fn test_set_session_config_option_request_value_id() {
6100 let req = SetSessionConfigOptionRequest::new("sess_1", "model", "model-1");
6101 let json = serde_json::to_value(&req).unwrap();
6102 assert_eq!(
6103 json,
6104 json!({
6105 "sessionId": "sess_1",
6106 "configId": "model",
6107 "value": "model-1"
6108 })
6109 );
6110 assert!(!json.as_object().unwrap().contains_key("type"));
6112 }
6113
6114 #[cfg(feature = "unstable_boolean_config")]
6115 #[test]
6116 fn test_set_session_config_option_request_boolean() {
6117 let req = SetSessionConfigOptionRequest::new("sess_1", "brave_mode", true);
6118 let json = serde_json::to_value(&req).unwrap();
6119 assert_eq!(
6120 json,
6121 json!({
6122 "sessionId": "sess_1",
6123 "configId": "brave_mode",
6124 "type": "boolean",
6125 "value": true
6126 })
6127 );
6128 }
6129
6130 #[cfg(feature = "unstable_boolean_config")]
6131 #[test]
6132 fn test_set_session_config_option_request_deserialize_no_type() {
6133 let json = json!({
6135 "sessionId": "sess_1",
6136 "configId": "model",
6137 "value": "model-1"
6138 });
6139 let req: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
6140 assert_eq!(req.session_id.to_string(), "sess_1");
6141 assert_eq!(req.config_id.to_string(), "model");
6142 assert_eq!(req.value.as_value_id().unwrap().to_string(), "model-1");
6143 }
6144
6145 #[cfg(feature = "unstable_boolean_config")]
6146 #[test]
6147 fn test_set_session_config_option_request_deserialize_boolean() {
6148 let json = json!({
6149 "sessionId": "sess_1",
6150 "configId": "brave_mode",
6151 "type": "boolean",
6152 "value": true
6153 });
6154 let req: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
6155 assert_eq!(req.value.as_bool(), Some(true));
6156 }
6157
6158 #[cfg(feature = "unstable_boolean_config")]
6159 #[test]
6160 fn test_set_session_config_option_request_roundtrip_value_id() {
6161 let original = SetSessionConfigOptionRequest::new("s", "c", "v");
6162 let json = serde_json::to_value(&original).unwrap();
6163 let roundtripped: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
6164 assert_eq!(original, roundtripped);
6165 }
6166
6167 #[cfg(feature = "unstable_boolean_config")]
6168 #[test]
6169 fn test_set_session_config_option_request_roundtrip_boolean() {
6170 let original = SetSessionConfigOptionRequest::new("s", "c", false);
6171 let json = serde_json::to_value(&original).unwrap();
6172 let roundtripped: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
6173 assert_eq!(original, roundtripped);
6174 }
6175
6176 #[cfg(feature = "unstable_boolean_config")]
6177 #[test]
6178 fn test_session_config_boolean_serialization() {
6179 let cfg = SessionConfigBoolean::new(true);
6180 let json = serde_json::to_value(&cfg).unwrap();
6181 assert_eq!(json, json!({ "currentValue": true }));
6182
6183 let deserialized: SessionConfigBoolean = serde_json::from_value(json).unwrap();
6184 assert!(deserialized.current_value);
6185 }
6186
6187 #[cfg(feature = "unstable_boolean_config")]
6188 #[test]
6189 fn test_session_config_option_boolean_variant() {
6190 let opt = SessionConfigOption::boolean("brave_mode", "Brave Mode", false)
6191 .description("Skip confirmation prompts");
6192 let json = serde_json::to_value(&opt).unwrap();
6193 assert_eq!(
6194 json,
6195 json!({
6196 "id": "brave_mode",
6197 "name": "Brave Mode",
6198 "description": "Skip confirmation prompts",
6199 "type": "boolean",
6200 "currentValue": false
6201 })
6202 );
6203
6204 let deserialized: SessionConfigOption = serde_json::from_value(json).unwrap();
6205 assert_eq!(deserialized.id.to_string(), "brave_mode");
6206 assert_eq!(deserialized.name, "Brave Mode");
6207 match deserialized.kind {
6208 SessionConfigKind::Boolean(ref b) => assert!(!b.current_value),
6209 _ => panic!("Expected Boolean kind"),
6210 }
6211 }
6212
6213 #[cfg(feature = "unstable_boolean_config")]
6214 #[test]
6215 fn test_session_config_option_select_still_works() {
6216 let opt = SessionConfigOption::select(
6218 "model",
6219 "Model",
6220 "model-1",
6221 vec![
6222 SessionConfigSelectOption::new("model-1", "Model 1"),
6223 SessionConfigSelectOption::new("model-2", "Model 2"),
6224 ],
6225 );
6226 let json = serde_json::to_value(&opt).unwrap();
6227 assert_eq!(json["type"], "select");
6228 assert_eq!(json["currentValue"], "model-1");
6229 assert_eq!(json["options"].as_array().unwrap().len(), 2);
6230
6231 let deserialized: SessionConfigOption = serde_json::from_value(json).unwrap();
6232 match deserialized.kind {
6233 SessionConfigKind::Select(ref s) => {
6234 assert_eq!(s.current_value.to_string(), "model-1");
6235 }
6236 _ => panic!("Expected Select kind"),
6237 }
6238 }
6239
6240 #[cfg(feature = "unstable_llm_providers")]
6241 #[test]
6242 fn test_llm_protocol_known_variants() {
6243 assert_eq!(
6244 serde_json::to_value(&LlmProtocol::Anthropic).unwrap(),
6245 json!("anthropic")
6246 );
6247 assert_eq!(
6248 serde_json::to_value(&LlmProtocol::OpenAi).unwrap(),
6249 json!("openai")
6250 );
6251 assert_eq!(
6252 serde_json::to_value(&LlmProtocol::Azure).unwrap(),
6253 json!("azure")
6254 );
6255 assert_eq!(
6256 serde_json::to_value(&LlmProtocol::Vertex).unwrap(),
6257 json!("vertex")
6258 );
6259 assert_eq!(
6260 serde_json::to_value(&LlmProtocol::Bedrock).unwrap(),
6261 json!("bedrock")
6262 );
6263
6264 assert_eq!(
6265 serde_json::from_str::<LlmProtocol>("\"anthropic\"").unwrap(),
6266 LlmProtocol::Anthropic
6267 );
6268 assert_eq!(
6269 serde_json::from_str::<LlmProtocol>("\"openai\"").unwrap(),
6270 LlmProtocol::OpenAi
6271 );
6272 assert_eq!(
6273 serde_json::from_str::<LlmProtocol>("\"azure\"").unwrap(),
6274 LlmProtocol::Azure
6275 );
6276 assert_eq!(
6277 serde_json::from_str::<LlmProtocol>("\"vertex\"").unwrap(),
6278 LlmProtocol::Vertex
6279 );
6280 assert_eq!(
6281 serde_json::from_str::<LlmProtocol>("\"bedrock\"").unwrap(),
6282 LlmProtocol::Bedrock
6283 );
6284 }
6285
6286 #[cfg(feature = "unstable_llm_providers")]
6287 #[test]
6288 fn test_llm_protocol_unknown_variant() {
6289 let unknown: LlmProtocol = serde_json::from_str("\"cohere\"").unwrap();
6290 assert_eq!(unknown, LlmProtocol::Other("cohere".to_string()));
6291
6292 let json = serde_json::to_value(&unknown).unwrap();
6293 assert_eq!(json, json!("cohere"));
6294 }
6295
6296 #[cfg(feature = "unstable_llm_providers")]
6297 #[test]
6298 fn test_provider_current_config_serialization() {
6299 let config =
6300 ProviderCurrentConfig::new(LlmProtocol::Anthropic, "https://api.anthropic.com");
6301
6302 let json = serde_json::to_value(&config).unwrap();
6303 assert_eq!(
6304 json,
6305 json!({
6306 "apiType": "anthropic",
6307 "baseUrl": "https://api.anthropic.com"
6308 })
6309 );
6310
6311 let deserialized: ProviderCurrentConfig = serde_json::from_value(json).unwrap();
6312 assert_eq!(deserialized.api_type, LlmProtocol::Anthropic);
6313 assert_eq!(deserialized.base_url, "https://api.anthropic.com");
6314 }
6315
6316 #[cfg(feature = "unstable_llm_providers")]
6317 #[test]
6318 fn test_provider_info_with_current_config() {
6319 let info = ProviderInfo::new(
6320 "main",
6321 vec![LlmProtocol::Anthropic, LlmProtocol::OpenAi],
6322 true,
6323 Some(ProviderCurrentConfig::new(
6324 LlmProtocol::Anthropic,
6325 "https://api.anthropic.com",
6326 )),
6327 );
6328
6329 let json = serde_json::to_value(&info).unwrap();
6330 assert_eq!(
6331 json,
6332 json!({
6333 "id": "main",
6334 "supported": ["anthropic", "openai"],
6335 "required": true,
6336 "current": {
6337 "apiType": "anthropic",
6338 "baseUrl": "https://api.anthropic.com"
6339 }
6340 })
6341 );
6342
6343 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6344 assert_eq!(deserialized.id, "main");
6345 assert_eq!(deserialized.supported.len(), 2);
6346 assert!(deserialized.required);
6347 assert!(deserialized.current.is_some());
6348 assert_eq!(
6349 deserialized.current.as_ref().unwrap().api_type,
6350 LlmProtocol::Anthropic
6351 );
6352 }
6353
6354 #[cfg(feature = "unstable_llm_providers")]
6355 #[test]
6356 fn test_provider_info_disabled() {
6357 let info = ProviderInfo::new(
6358 "secondary",
6359 vec![LlmProtocol::OpenAi],
6360 false,
6361 None::<ProviderCurrentConfig>,
6362 );
6363
6364 let json = serde_json::to_value(&info).unwrap();
6365 assert_eq!(
6366 json,
6367 json!({
6368 "id": "secondary",
6369 "supported": ["openai"],
6370 "required": false
6371 })
6372 );
6373
6374 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6375 assert_eq!(deserialized.id, "secondary");
6376 assert!(!deserialized.required);
6377 assert!(deserialized.current.is_none());
6378 }
6379
6380 #[cfg(feature = "unstable_llm_providers")]
6381 #[test]
6382 fn test_provider_info_missing_current_defaults_to_none() {
6383 let json = json!({
6385 "id": "main",
6386 "supported": ["anthropic"],
6387 "required": true
6388 });
6389 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6390 assert!(deserialized.current.is_none());
6391 }
6392
6393 #[cfg(feature = "unstable_llm_providers")]
6394 #[test]
6395 fn test_provider_info_explicit_null_current_decodes_to_none() {
6396 let json = json!({
6400 "id": "main",
6401 "supported": ["anthropic"],
6402 "required": true,
6403 "current": null
6404 });
6405 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6406 assert!(deserialized.current.is_none());
6407 }
6408
6409 #[cfg(feature = "unstable_llm_providers")]
6410 #[test]
6411 fn test_list_providers_response_serialization() {
6412 let response = ListProvidersResponse::new(vec![ProviderInfo::new(
6413 "main",
6414 vec![LlmProtocol::Anthropic],
6415 true,
6416 Some(ProviderCurrentConfig::new(
6417 LlmProtocol::Anthropic,
6418 "https://api.anthropic.com",
6419 )),
6420 )]);
6421
6422 let json = serde_json::to_value(&response).unwrap();
6423 assert_eq!(json["providers"].as_array().unwrap().len(), 1);
6424 assert_eq!(json["providers"][0]["id"], "main");
6425
6426 let deserialized: ListProvidersResponse = serde_json::from_value(json).unwrap();
6427 assert_eq!(deserialized.providers.len(), 1);
6428 }
6429
6430 #[cfg(feature = "unstable_llm_providers")]
6431 #[test]
6432 fn test_set_providers_request_serialization() {
6433 use std::collections::HashMap;
6434
6435 let mut headers = HashMap::new();
6436 headers.insert("Authorization".to_string(), "Bearer sk-test".to_string());
6437
6438 let request =
6439 SetProvidersRequest::new("main", LlmProtocol::OpenAi, "https://api.openai.com/v1")
6440 .headers(headers);
6441
6442 let json = serde_json::to_value(&request).unwrap();
6443 assert_eq!(
6444 json,
6445 json!({
6446 "id": "main",
6447 "apiType": "openai",
6448 "baseUrl": "https://api.openai.com/v1",
6449 "headers": {
6450 "Authorization": "Bearer sk-test"
6451 }
6452 })
6453 );
6454
6455 let deserialized: SetProvidersRequest = serde_json::from_value(json).unwrap();
6456 assert_eq!(deserialized.id, "main");
6457 assert_eq!(deserialized.api_type, LlmProtocol::OpenAi);
6458 assert_eq!(deserialized.base_url, "https://api.openai.com/v1");
6459 assert_eq!(deserialized.headers.len(), 1);
6460 assert_eq!(
6461 deserialized.headers.get("Authorization").unwrap(),
6462 "Bearer sk-test"
6463 );
6464 }
6465
6466 #[cfg(feature = "unstable_llm_providers")]
6467 #[test]
6468 fn test_set_providers_request_omits_empty_headers() {
6469 let request =
6470 SetProvidersRequest::new("main", LlmProtocol::Anthropic, "https://api.anthropic.com");
6471
6472 let json = serde_json::to_value(&request).unwrap();
6473 assert!(!json.as_object().unwrap().contains_key("headers"));
6475 }
6476
6477 #[cfg(feature = "unstable_llm_providers")]
6478 #[test]
6479 fn test_disable_providers_request_serialization() {
6480 let request = DisableProvidersRequest::new("secondary");
6481
6482 let json = serde_json::to_value(&request).unwrap();
6483 assert_eq!(json, json!({ "id": "secondary" }));
6484
6485 let deserialized: DisableProvidersRequest = serde_json::from_value(json).unwrap();
6486 assert_eq!(deserialized.id, "secondary");
6487 }
6488
6489 #[cfg(feature = "unstable_llm_providers")]
6490 #[test]
6491 fn test_providers_capabilities_serialization() {
6492 let caps = ProvidersCapabilities::new();
6493
6494 let json = serde_json::to_value(&caps).unwrap();
6495 assert_eq!(json, json!({}));
6496
6497 let deserialized: ProvidersCapabilities = serde_json::from_value(json).unwrap();
6498 assert!(deserialized.meta.is_none());
6499 }
6500
6501 #[cfg(feature = "unstable_llm_providers")]
6502 #[test]
6503 fn test_agent_capabilities_with_providers() {
6504 let caps = AgentCapabilities::new().providers(ProvidersCapabilities::new());
6505
6506 let json = serde_json::to_value(&caps).unwrap();
6507 assert_eq!(json["providers"], json!({}));
6508
6509 let deserialized: AgentCapabilities = serde_json::from_value(json).unwrap();
6510 assert!(deserialized.providers.is_some());
6511 }
6512}