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")]
1125 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1126 pub additional_directories: Vec<PathBuf>,
1127 pub session_id: SessionId,
1129 #[serde(rename = "_meta")]
1135 pub meta: Option<Meta>,
1136}
1137
1138impl LoadSessionRequest {
1139 #[must_use]
1140 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1141 Self {
1142 mcp_servers: vec![],
1143 cwd: cwd.into(),
1144 #[cfg(feature = "unstable_session_additional_directories")]
1145 additional_directories: vec![],
1146 session_id: session_id.into(),
1147 meta: None,
1148 }
1149 }
1150
1151 #[cfg(feature = "unstable_session_additional_directories")]
1157 #[must_use]
1158 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1159 self.additional_directories = additional_directories;
1160 self
1161 }
1162
1163 #[must_use]
1165 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1166 self.mcp_servers = mcp_servers;
1167 self
1168 }
1169
1170 #[must_use]
1176 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1177 self.meta = meta.into_option();
1178 self
1179 }
1180}
1181
1182#[serde_as]
1184#[skip_serializing_none]
1185#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1186#[schemars(extend("x-side" = "agent", "x-method" = SESSION_LOAD_METHOD_NAME))]
1187#[serde(rename_all = "camelCase")]
1188#[non_exhaustive]
1189pub struct LoadSessionResponse {
1190 #[serde_as(deserialize_as = "DefaultOnError")]
1194 #[serde(default)]
1195 pub modes: Option<SessionModeState>,
1196 #[cfg(feature = "unstable_session_model")]
1202 #[serde_as(deserialize_as = "DefaultOnError")]
1203 #[serde(default)]
1204 pub models: Option<SessionModelState>,
1205 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1207 #[serde(default)]
1208 pub config_options: Option<Vec<SessionConfigOption>>,
1209 #[serde(rename = "_meta")]
1215 pub meta: Option<Meta>,
1216}
1217
1218impl LoadSessionResponse {
1219 #[must_use]
1220 pub fn new() -> Self {
1221 Self::default()
1222 }
1223
1224 #[must_use]
1228 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1229 self.modes = modes.into_option();
1230 self
1231 }
1232
1233 #[cfg(feature = "unstable_session_model")]
1239 #[must_use]
1240 pub fn models(mut self, models: impl IntoOption<SessionModelState>) -> Self {
1241 self.models = models.into_option();
1242 self
1243 }
1244
1245 #[must_use]
1247 pub fn config_options(
1248 mut self,
1249 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1250 ) -> Self {
1251 self.config_options = config_options.into_option();
1252 self
1253 }
1254
1255 #[must_use]
1261 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1262 self.meta = meta.into_option();
1263 self
1264 }
1265}
1266
1267#[cfg(feature = "unstable_session_fork")]
1280#[skip_serializing_none]
1281#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1282#[schemars(extend("x-side" = "agent", "x-method" = SESSION_FORK_METHOD_NAME))]
1283#[serde(rename_all = "camelCase")]
1284#[non_exhaustive]
1285pub struct ForkSessionRequest {
1286 pub session_id: SessionId,
1288 pub cwd: PathBuf,
1290 #[cfg(feature = "unstable_session_additional_directories")]
1300 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1301 pub additional_directories: Vec<PathBuf>,
1302 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1304 pub mcp_servers: Vec<McpServer>,
1305 #[serde(rename = "_meta")]
1311 pub meta: Option<Meta>,
1312}
1313
1314#[cfg(feature = "unstable_session_fork")]
1315impl ForkSessionRequest {
1316 #[must_use]
1317 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1318 Self {
1319 session_id: session_id.into(),
1320 cwd: cwd.into(),
1321 #[cfg(feature = "unstable_session_additional_directories")]
1322 additional_directories: vec![],
1323 mcp_servers: vec![],
1324 meta: None,
1325 }
1326 }
1327
1328 #[cfg(feature = "unstable_session_additional_directories")]
1334 #[must_use]
1335 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1336 self.additional_directories = additional_directories;
1337 self
1338 }
1339
1340 #[must_use]
1342 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1343 self.mcp_servers = mcp_servers;
1344 self
1345 }
1346
1347 #[must_use]
1353 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1354 self.meta = meta.into_option();
1355 self
1356 }
1357}
1358
1359#[cfg(feature = "unstable_session_fork")]
1365#[serde_as]
1366#[skip_serializing_none]
1367#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1368#[schemars(extend("x-side" = "agent", "x-method" = SESSION_FORK_METHOD_NAME))]
1369#[serde(rename_all = "camelCase")]
1370#[non_exhaustive]
1371pub struct ForkSessionResponse {
1372 pub session_id: SessionId,
1374 #[serde_as(deserialize_as = "DefaultOnError")]
1378 #[serde(default)]
1379 pub modes: Option<SessionModeState>,
1380 #[cfg(feature = "unstable_session_model")]
1386 #[serde_as(deserialize_as = "DefaultOnError")]
1387 #[serde(default)]
1388 pub models: Option<SessionModelState>,
1389 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1391 #[serde(default)]
1392 pub config_options: Option<Vec<SessionConfigOption>>,
1393 #[serde(rename = "_meta")]
1399 pub meta: Option<Meta>,
1400}
1401
1402#[cfg(feature = "unstable_session_fork")]
1403impl ForkSessionResponse {
1404 #[must_use]
1405 pub fn new(session_id: impl Into<SessionId>) -> Self {
1406 Self {
1407 session_id: session_id.into(),
1408 modes: None,
1409 #[cfg(feature = "unstable_session_model")]
1410 models: None,
1411 config_options: None,
1412 meta: None,
1413 }
1414 }
1415
1416 #[must_use]
1420 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1421 self.modes = modes.into_option();
1422 self
1423 }
1424
1425 #[cfg(feature = "unstable_session_model")]
1431 #[must_use]
1432 pub fn models(mut self, models: impl IntoOption<SessionModelState>) -> Self {
1433 self.models = models.into_option();
1434 self
1435 }
1436
1437 #[must_use]
1439 pub fn config_options(
1440 mut self,
1441 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1442 ) -> Self {
1443 self.config_options = config_options.into_option();
1444 self
1445 }
1446
1447 #[must_use]
1453 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1454 self.meta = meta.into_option();
1455 self
1456 }
1457}
1458
1459#[skip_serializing_none]
1468#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1469#[schemars(extend("x-side" = "agent", "x-method" = SESSION_RESUME_METHOD_NAME))]
1470#[serde(rename_all = "camelCase")]
1471#[non_exhaustive]
1472pub struct ResumeSessionRequest {
1473 pub session_id: SessionId,
1475 pub cwd: PathBuf,
1477 #[cfg(feature = "unstable_session_additional_directories")]
1487 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1488 pub additional_directories: Vec<PathBuf>,
1489 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1491 pub mcp_servers: Vec<McpServer>,
1492 #[serde(rename = "_meta")]
1498 pub meta: Option<Meta>,
1499}
1500
1501impl ResumeSessionRequest {
1502 #[must_use]
1503 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1504 Self {
1505 session_id: session_id.into(),
1506 cwd: cwd.into(),
1507 #[cfg(feature = "unstable_session_additional_directories")]
1508 additional_directories: vec![],
1509 mcp_servers: vec![],
1510 meta: None,
1511 }
1512 }
1513
1514 #[cfg(feature = "unstable_session_additional_directories")]
1520 #[must_use]
1521 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1522 self.additional_directories = additional_directories;
1523 self
1524 }
1525
1526 #[must_use]
1528 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1529 self.mcp_servers = mcp_servers;
1530 self
1531 }
1532
1533 #[must_use]
1539 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1540 self.meta = meta.into_option();
1541 self
1542 }
1543}
1544
1545#[serde_as]
1547#[skip_serializing_none]
1548#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1549#[schemars(extend("x-side" = "agent", "x-method" = SESSION_RESUME_METHOD_NAME))]
1550#[serde(rename_all = "camelCase")]
1551#[non_exhaustive]
1552pub struct ResumeSessionResponse {
1553 #[serde_as(deserialize_as = "DefaultOnError")]
1557 #[serde(default)]
1558 pub modes: Option<SessionModeState>,
1559 #[cfg(feature = "unstable_session_model")]
1565 #[serde_as(deserialize_as = "DefaultOnError")]
1566 #[serde(default)]
1567 pub models: Option<SessionModelState>,
1568 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1570 #[serde(default)]
1571 pub config_options: Option<Vec<SessionConfigOption>>,
1572 #[serde(rename = "_meta")]
1578 pub meta: Option<Meta>,
1579}
1580
1581impl ResumeSessionResponse {
1582 #[must_use]
1583 pub fn new() -> Self {
1584 Self::default()
1585 }
1586
1587 #[must_use]
1591 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1592 self.modes = modes.into_option();
1593 self
1594 }
1595
1596 #[cfg(feature = "unstable_session_model")]
1602 #[must_use]
1603 pub fn models(mut self, models: impl IntoOption<SessionModelState>) -> Self {
1604 self.models = models.into_option();
1605 self
1606 }
1607
1608 #[must_use]
1610 pub fn config_options(
1611 mut self,
1612 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1613 ) -> Self {
1614 self.config_options = config_options.into_option();
1615 self
1616 }
1617
1618 #[must_use]
1624 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1625 self.meta = meta.into_option();
1626 self
1627 }
1628}
1629
1630#[skip_serializing_none]
1640#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1641#[schemars(extend("x-side" = "agent", "x-method" = SESSION_CLOSE_METHOD_NAME))]
1642#[serde(rename_all = "camelCase")]
1643#[non_exhaustive]
1644pub struct CloseSessionRequest {
1645 pub session_id: SessionId,
1647 #[serde(rename = "_meta")]
1653 pub meta: Option<Meta>,
1654}
1655
1656impl CloseSessionRequest {
1657 #[must_use]
1658 pub fn new(session_id: impl Into<SessionId>) -> Self {
1659 Self {
1660 session_id: session_id.into(),
1661 meta: None,
1662 }
1663 }
1664
1665 #[must_use]
1671 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1672 self.meta = meta.into_option();
1673 self
1674 }
1675}
1676
1677#[skip_serializing_none]
1679#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1680#[schemars(extend("x-side" = "agent", "x-method" = SESSION_CLOSE_METHOD_NAME))]
1681#[serde(rename_all = "camelCase")]
1682#[non_exhaustive]
1683pub struct CloseSessionResponse {
1684 #[serde(rename = "_meta")]
1690 pub meta: Option<Meta>,
1691}
1692
1693impl CloseSessionResponse {
1694 #[must_use]
1695 pub fn new() -> Self {
1696 Self::default()
1697 }
1698
1699 #[must_use]
1705 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1706 self.meta = meta.into_option();
1707 self
1708 }
1709}
1710
1711#[skip_serializing_none]
1717#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1718#[schemars(extend("x-side" = "agent", "x-method" = SESSION_LIST_METHOD_NAME))]
1719#[serde(rename_all = "camelCase")]
1720#[non_exhaustive]
1721pub struct ListSessionsRequest {
1722 pub cwd: Option<PathBuf>,
1724 #[cfg(feature = "unstable_session_additional_directories")]
1733 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1734 pub additional_directories: Vec<PathBuf>,
1735 pub cursor: Option<String>,
1737 #[serde(rename = "_meta")]
1743 pub meta: Option<Meta>,
1744}
1745
1746impl ListSessionsRequest {
1747 #[must_use]
1748 pub fn new() -> Self {
1749 Self::default()
1750 }
1751
1752 #[must_use]
1754 pub fn cwd(mut self, cwd: impl IntoOption<PathBuf>) -> Self {
1755 self.cwd = cwd.into_option();
1756 self
1757 }
1758
1759 #[cfg(feature = "unstable_session_additional_directories")]
1765 #[must_use]
1766 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1767 self.additional_directories = additional_directories;
1768 self
1769 }
1770
1771 #[must_use]
1773 pub fn cursor(mut self, cursor: impl IntoOption<String>) -> Self {
1774 self.cursor = cursor.into_option();
1775 self
1776 }
1777
1778 #[must_use]
1784 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1785 self.meta = meta.into_option();
1786 self
1787 }
1788}
1789
1790#[serde_as]
1792#[skip_serializing_none]
1793#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1794#[schemars(extend("x-side" = "agent", "x-method" = SESSION_LIST_METHOD_NAME))]
1795#[serde(rename_all = "camelCase")]
1796#[non_exhaustive]
1797pub struct ListSessionsResponse {
1798 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1800 pub sessions: Vec<SessionInfo>,
1801 pub next_cursor: Option<String>,
1804 #[serde(rename = "_meta")]
1810 pub meta: Option<Meta>,
1811}
1812
1813impl ListSessionsResponse {
1814 #[must_use]
1815 pub fn new(sessions: Vec<SessionInfo>) -> Self {
1816 Self {
1817 sessions,
1818 next_cursor: None,
1819 meta: None,
1820 }
1821 }
1822
1823 #[must_use]
1824 pub fn next_cursor(mut self, next_cursor: impl IntoOption<String>) -> Self {
1825 self.next_cursor = next_cursor.into_option();
1826 self
1827 }
1828
1829 #[must_use]
1835 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1836 self.meta = meta.into_option();
1837 self
1838 }
1839}
1840
1841#[cfg(feature = "unstable_session_delete")]
1851#[skip_serializing_none]
1852#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1853#[schemars(extend("x-side" = "agent", "x-method" = SESSION_DELETE_METHOD_NAME))]
1854#[serde(rename_all = "camelCase")]
1855#[non_exhaustive]
1856pub struct DeleteSessionRequest {
1857 pub session_id: SessionId,
1859 #[serde(rename = "_meta")]
1865 pub meta: Option<Meta>,
1866}
1867
1868#[cfg(feature = "unstable_session_delete")]
1869impl DeleteSessionRequest {
1870 #[must_use]
1871 pub fn new(session_id: impl Into<SessionId>) -> Self {
1872 Self {
1873 session_id: session_id.into(),
1874 meta: None,
1875 }
1876 }
1877
1878 #[must_use]
1884 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1885 self.meta = meta.into_option();
1886 self
1887 }
1888}
1889
1890#[cfg(feature = "unstable_session_delete")]
1896#[skip_serializing_none]
1897#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1898#[schemars(extend("x-side" = "agent", "x-method" = SESSION_DELETE_METHOD_NAME))]
1899#[serde(rename_all = "camelCase")]
1900#[non_exhaustive]
1901pub struct DeleteSessionResponse {
1902 #[serde(rename = "_meta")]
1908 pub meta: Option<Meta>,
1909}
1910
1911#[cfg(feature = "unstable_session_delete")]
1912impl DeleteSessionResponse {
1913 #[must_use]
1914 pub fn new() -> Self {
1915 Self::default()
1916 }
1917
1918 #[must_use]
1924 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1925 self.meta = meta.into_option();
1926 self
1927 }
1928}
1929
1930#[serde_as]
1932#[skip_serializing_none]
1933#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1934#[serde(rename_all = "camelCase")]
1935#[non_exhaustive]
1936pub struct SessionInfo {
1937 pub session_id: SessionId,
1939 pub cwd: PathBuf,
1941 #[cfg(feature = "unstable_session_additional_directories")]
1949 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1950 pub additional_directories: Vec<PathBuf>,
1951
1952 #[serde_as(deserialize_as = "DefaultOnError")]
1954 #[serde(default)]
1955 pub title: Option<String>,
1956 #[serde_as(deserialize_as = "DefaultOnError")]
1958 #[serde(default)]
1959 pub updated_at: Option<String>,
1960 #[serde(rename = "_meta")]
1966 pub meta: Option<Meta>,
1967}
1968
1969impl SessionInfo {
1970 #[must_use]
1971 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1972 Self {
1973 session_id: session_id.into(),
1974 cwd: cwd.into(),
1975 #[cfg(feature = "unstable_session_additional_directories")]
1976 additional_directories: vec![],
1977 title: None,
1978 updated_at: None,
1979 meta: None,
1980 }
1981 }
1982
1983 #[cfg(feature = "unstable_session_additional_directories")]
1989 #[must_use]
1990 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1991 self.additional_directories = additional_directories;
1992 self
1993 }
1994
1995 #[must_use]
1997 pub fn title(mut self, title: impl IntoOption<String>) -> Self {
1998 self.title = title.into_option();
1999 self
2000 }
2001
2002 #[must_use]
2004 pub fn updated_at(mut self, updated_at: impl IntoOption<String>) -> Self {
2005 self.updated_at = updated_at.into_option();
2006 self
2007 }
2008
2009 #[must_use]
2015 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2016 self.meta = meta.into_option();
2017 self
2018 }
2019}
2020
2021#[serde_as]
2025#[skip_serializing_none]
2026#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2027#[serde(rename_all = "camelCase")]
2028#[non_exhaustive]
2029pub struct SessionModeState {
2030 pub current_mode_id: SessionModeId,
2032 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
2034 pub available_modes: Vec<SessionMode>,
2035 #[serde(rename = "_meta")]
2041 pub meta: Option<Meta>,
2042}
2043
2044impl SessionModeState {
2045 #[must_use]
2046 pub fn new(
2047 current_mode_id: impl Into<SessionModeId>,
2048 available_modes: Vec<SessionMode>,
2049 ) -> Self {
2050 Self {
2051 current_mode_id: current_mode_id.into(),
2052 available_modes,
2053 meta: None,
2054 }
2055 }
2056
2057 #[must_use]
2063 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2064 self.meta = meta.into_option();
2065 self
2066 }
2067}
2068
2069#[skip_serializing_none]
2073#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2074#[serde(rename_all = "camelCase")]
2075#[non_exhaustive]
2076pub struct SessionMode {
2077 pub id: SessionModeId,
2078 pub name: String,
2079 #[serde(default)]
2080 pub description: Option<String>,
2081 #[serde(rename = "_meta")]
2087 pub meta: Option<Meta>,
2088}
2089
2090impl SessionMode {
2091 #[must_use]
2092 pub fn new(id: impl Into<SessionModeId>, name: impl Into<String>) -> Self {
2093 Self {
2094 id: id.into(),
2095 name: name.into(),
2096 description: None,
2097 meta: None,
2098 }
2099 }
2100
2101 #[must_use]
2102 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
2103 self.description = description.into_option();
2104 self
2105 }
2106
2107 #[must_use]
2113 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2114 self.meta = meta.into_option();
2115 self
2116 }
2117}
2118
2119#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, From, Display)]
2121#[serde(transparent)]
2122#[from(Arc<str>, String, &'static str)]
2123#[non_exhaustive]
2124pub struct SessionModeId(pub Arc<str>);
2125
2126impl SessionModeId {
2127 #[must_use]
2128 pub fn new(id: impl Into<Arc<str>>) -> Self {
2129 Self(id.into())
2130 }
2131}
2132
2133#[skip_serializing_none]
2135#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2136#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODE_METHOD_NAME))]
2137#[serde(rename_all = "camelCase")]
2138#[non_exhaustive]
2139pub struct SetSessionModeRequest {
2140 pub session_id: SessionId,
2142 pub mode_id: SessionModeId,
2144 #[serde(rename = "_meta")]
2150 pub meta: Option<Meta>,
2151}
2152
2153impl SetSessionModeRequest {
2154 #[must_use]
2155 pub fn new(session_id: impl Into<SessionId>, mode_id: impl Into<SessionModeId>) -> Self {
2156 Self {
2157 session_id: session_id.into(),
2158 mode_id: mode_id.into(),
2159 meta: None,
2160 }
2161 }
2162
2163 #[must_use]
2164 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2165 self.meta = meta.into_option();
2166 self
2167 }
2168}
2169
2170#[skip_serializing_none]
2172#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2173#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODE_METHOD_NAME))]
2174#[serde(rename_all = "camelCase")]
2175#[non_exhaustive]
2176pub struct SetSessionModeResponse {
2177 #[serde(rename = "_meta")]
2183 pub meta: Option<Meta>,
2184}
2185
2186impl SetSessionModeResponse {
2187 #[must_use]
2188 pub fn new() -> Self {
2189 Self::default()
2190 }
2191
2192 #[must_use]
2198 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2199 self.meta = meta.into_option();
2200 self
2201 }
2202}
2203
2204#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, From, Display)]
2208#[serde(transparent)]
2209#[from(Arc<str>, String, &'static str)]
2210#[non_exhaustive]
2211pub struct SessionConfigId(pub Arc<str>);
2212
2213impl SessionConfigId {
2214 #[must_use]
2215 pub fn new(id: impl Into<Arc<str>>) -> Self {
2216 Self(id.into())
2217 }
2218}
2219
2220#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, From, Display)]
2222#[serde(transparent)]
2223#[from(Arc<str>, String, &'static str)]
2224#[non_exhaustive]
2225pub struct SessionConfigValueId(pub Arc<str>);
2226
2227impl SessionConfigValueId {
2228 #[must_use]
2229 pub fn new(id: impl Into<Arc<str>>) -> Self {
2230 Self(id.into())
2231 }
2232}
2233
2234#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, From, Display)]
2236#[serde(transparent)]
2237#[from(Arc<str>, String, &'static str)]
2238#[non_exhaustive]
2239pub struct SessionConfigGroupId(pub Arc<str>);
2240
2241impl SessionConfigGroupId {
2242 #[must_use]
2243 pub fn new(id: impl Into<Arc<str>>) -> Self {
2244 Self(id.into())
2245 }
2246}
2247
2248#[skip_serializing_none]
2250#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2251#[serde(rename_all = "camelCase")]
2252#[non_exhaustive]
2253pub struct SessionConfigSelectOption {
2254 pub value: SessionConfigValueId,
2256 pub name: String,
2258 #[serde(default)]
2260 pub description: Option<String>,
2261 #[serde(rename = "_meta")]
2267 pub meta: Option<Meta>,
2268}
2269
2270impl SessionConfigSelectOption {
2271 #[must_use]
2272 pub fn new(value: impl Into<SessionConfigValueId>, name: impl Into<String>) -> Self {
2273 Self {
2274 value: value.into(),
2275 name: name.into(),
2276 description: None,
2277 meta: None,
2278 }
2279 }
2280
2281 #[must_use]
2282 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
2283 self.description = description.into_option();
2284 self
2285 }
2286
2287 #[must_use]
2293 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2294 self.meta = meta.into_option();
2295 self
2296 }
2297}
2298
2299#[skip_serializing_none]
2301#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2302#[serde(rename_all = "camelCase")]
2303#[non_exhaustive]
2304pub struct SessionConfigSelectGroup {
2305 pub group: SessionConfigGroupId,
2307 pub name: String,
2309 pub options: Vec<SessionConfigSelectOption>,
2311 #[serde(rename = "_meta")]
2317 pub meta: Option<Meta>,
2318}
2319
2320impl SessionConfigSelectGroup {
2321 #[must_use]
2322 pub fn new(
2323 group: impl Into<SessionConfigGroupId>,
2324 name: impl Into<String>,
2325 options: Vec<SessionConfigSelectOption>,
2326 ) -> Self {
2327 Self {
2328 group: group.into(),
2329 name: name.into(),
2330 options,
2331 meta: None,
2332 }
2333 }
2334
2335 #[must_use]
2341 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2342 self.meta = meta.into_option();
2343 self
2344 }
2345}
2346
2347#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2349#[serde(untagged)]
2350#[non_exhaustive]
2351pub enum SessionConfigSelectOptions {
2352 Ungrouped(Vec<SessionConfigSelectOption>),
2354 Grouped(Vec<SessionConfigSelectGroup>),
2356}
2357
2358impl From<Vec<SessionConfigSelectOption>> for SessionConfigSelectOptions {
2359 fn from(options: Vec<SessionConfigSelectOption>) -> Self {
2360 SessionConfigSelectOptions::Ungrouped(options)
2361 }
2362}
2363
2364impl From<Vec<SessionConfigSelectGroup>> for SessionConfigSelectOptions {
2365 fn from(groups: Vec<SessionConfigSelectGroup>) -> Self {
2366 SessionConfigSelectOptions::Grouped(groups)
2367 }
2368}
2369
2370#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2372#[serde(rename_all = "camelCase")]
2373#[non_exhaustive]
2374pub struct SessionConfigSelect {
2375 pub current_value: SessionConfigValueId,
2377 pub options: SessionConfigSelectOptions,
2379}
2380
2381impl SessionConfigSelect {
2382 #[must_use]
2383 pub fn new(
2384 current_value: impl Into<SessionConfigValueId>,
2385 options: impl Into<SessionConfigSelectOptions>,
2386 ) -> Self {
2387 Self {
2388 current_value: current_value.into(),
2389 options: options.into(),
2390 }
2391 }
2392}
2393
2394#[cfg(feature = "unstable_boolean_config")]
2400#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2401#[serde(rename_all = "camelCase")]
2402#[non_exhaustive]
2403pub struct SessionConfigBoolean {
2404 pub current_value: bool,
2406}
2407
2408#[cfg(feature = "unstable_boolean_config")]
2409impl SessionConfigBoolean {
2410 #[must_use]
2411 pub fn new(current_value: bool) -> Self {
2412 Self { current_value }
2413 }
2414}
2415
2416#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2426#[serde(rename_all = "snake_case")]
2427#[non_exhaustive]
2428pub enum SessionConfigOptionCategory {
2429 Mode,
2431 Model,
2433 ThoughtLevel,
2435 #[serde(untagged)]
2437 Other(String),
2438}
2439
2440#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2442#[serde(tag = "type", rename_all = "snake_case")]
2443#[schemars(extend("discriminator" = {"propertyName": "type"}))]
2444#[non_exhaustive]
2445pub enum SessionConfigKind {
2446 Select(SessionConfigSelect),
2448 #[cfg(feature = "unstable_boolean_config")]
2454 Boolean(SessionConfigBoolean),
2455}
2456
2457#[serde_as]
2459#[skip_serializing_none]
2460#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2461#[serde(rename_all = "camelCase")]
2462#[non_exhaustive]
2463pub struct SessionConfigOption {
2464 pub id: SessionConfigId,
2466 pub name: String,
2468 #[serde(default)]
2470 pub description: Option<String>,
2471 #[serde_as(deserialize_as = "DefaultOnError")]
2473 #[serde(default)]
2474 pub category: Option<SessionConfigOptionCategory>,
2475 #[serde(flatten)]
2477 pub kind: SessionConfigKind,
2478 #[serde(rename = "_meta")]
2484 pub meta: Option<Meta>,
2485}
2486
2487impl SessionConfigOption {
2488 #[must_use]
2489 pub fn new(
2490 id: impl Into<SessionConfigId>,
2491 name: impl Into<String>,
2492 kind: SessionConfigKind,
2493 ) -> Self {
2494 Self {
2495 id: id.into(),
2496 name: name.into(),
2497 description: None,
2498 category: None,
2499 kind,
2500 meta: None,
2501 }
2502 }
2503
2504 #[must_use]
2505 pub fn select(
2506 id: impl Into<SessionConfigId>,
2507 name: impl Into<String>,
2508 current_value: impl Into<SessionConfigValueId>,
2509 options: impl Into<SessionConfigSelectOptions>,
2510 ) -> Self {
2511 Self::new(
2512 id,
2513 name,
2514 SessionConfigKind::Select(SessionConfigSelect::new(current_value, options)),
2515 )
2516 }
2517
2518 #[cfg(feature = "unstable_boolean_config")]
2522 #[must_use]
2523 pub fn boolean(
2524 id: impl Into<SessionConfigId>,
2525 name: impl Into<String>,
2526 current_value: bool,
2527 ) -> Self {
2528 Self::new(
2529 id,
2530 name,
2531 SessionConfigKind::Boolean(SessionConfigBoolean::new(current_value)),
2532 )
2533 }
2534
2535 #[must_use]
2536 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
2537 self.description = description.into_option();
2538 self
2539 }
2540
2541 #[must_use]
2542 pub fn category(mut self, category: impl IntoOption<SessionConfigOptionCategory>) -> Self {
2543 self.category = category.into_option();
2544 self
2545 }
2546
2547 #[must_use]
2553 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2554 self.meta = meta.into_option();
2555 self
2556 }
2557}
2558
2559#[cfg(feature = "unstable_boolean_config")]
2574#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2575#[serde(tag = "type", rename_all = "snake_case")]
2576#[non_exhaustive]
2577pub enum SessionConfigOptionValue {
2578 Boolean {
2580 value: bool,
2582 },
2583 #[serde(untagged)]
2589 ValueId {
2590 value: SessionConfigValueId,
2592 },
2593}
2594
2595#[cfg(feature = "unstable_boolean_config")]
2596impl SessionConfigOptionValue {
2597 #[must_use]
2599 pub fn value_id(id: impl Into<SessionConfigValueId>) -> Self {
2600 Self::ValueId { value: id.into() }
2601 }
2602
2603 #[must_use]
2605 pub fn boolean(val: bool) -> Self {
2606 Self::Boolean { value: val }
2607 }
2608
2609 #[must_use]
2612 pub fn as_value_id(&self) -> Option<&SessionConfigValueId> {
2613 match self {
2614 Self::ValueId { value } => Some(value),
2615 _ => None,
2616 }
2617 }
2618
2619 #[must_use]
2621 pub fn as_bool(&self) -> Option<bool> {
2622 match self {
2623 Self::Boolean { value } => Some(*value),
2624 _ => None,
2625 }
2626 }
2627}
2628
2629#[cfg(feature = "unstable_boolean_config")]
2630impl From<SessionConfigValueId> for SessionConfigOptionValue {
2631 fn from(value: SessionConfigValueId) -> Self {
2632 Self::ValueId { value }
2633 }
2634}
2635
2636#[cfg(feature = "unstable_boolean_config")]
2637impl From<bool> for SessionConfigOptionValue {
2638 fn from(value: bool) -> Self {
2639 Self::Boolean { value }
2640 }
2641}
2642
2643#[cfg(feature = "unstable_boolean_config")]
2644impl From<&str> for SessionConfigOptionValue {
2645 fn from(value: &str) -> Self {
2646 Self::ValueId {
2647 value: SessionConfigValueId::new(value),
2648 }
2649 }
2650}
2651
2652#[skip_serializing_none]
2654#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2655#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_CONFIG_OPTION_METHOD_NAME))]
2656#[serde(rename_all = "camelCase")]
2657#[non_exhaustive]
2658pub struct SetSessionConfigOptionRequest {
2659 pub session_id: SessionId,
2661 pub config_id: SessionConfigId,
2663 #[cfg(feature = "unstable_boolean_config")]
2668 #[serde(flatten)]
2669 pub value: SessionConfigOptionValue,
2670 #[cfg(not(feature = "unstable_boolean_config"))]
2672 pub value: SessionConfigValueId,
2673 #[serde(rename = "_meta")]
2679 pub meta: Option<Meta>,
2680}
2681
2682impl SetSessionConfigOptionRequest {
2683 #[cfg(feature = "unstable_boolean_config")]
2684 #[must_use]
2685 pub fn new(
2686 session_id: impl Into<SessionId>,
2687 config_id: impl Into<SessionConfigId>,
2688 value: impl Into<SessionConfigOptionValue>,
2689 ) -> Self {
2690 Self {
2691 session_id: session_id.into(),
2692 config_id: config_id.into(),
2693 value: value.into(),
2694 meta: None,
2695 }
2696 }
2697
2698 #[cfg(not(feature = "unstable_boolean_config"))]
2699 #[must_use]
2700 pub fn new(
2701 session_id: impl Into<SessionId>,
2702 config_id: impl Into<SessionConfigId>,
2703 value: impl Into<SessionConfigValueId>,
2704 ) -> Self {
2705 Self {
2706 session_id: session_id.into(),
2707 config_id: config_id.into(),
2708 value: value.into(),
2709 meta: None,
2710 }
2711 }
2712
2713 #[must_use]
2719 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2720 self.meta = meta.into_option();
2721 self
2722 }
2723}
2724
2725#[serde_as]
2727#[skip_serializing_none]
2728#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2729#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_CONFIG_OPTION_METHOD_NAME))]
2730#[serde(rename_all = "camelCase")]
2731#[non_exhaustive]
2732pub struct SetSessionConfigOptionResponse {
2733 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
2735 pub config_options: Vec<SessionConfigOption>,
2736 #[serde(rename = "_meta")]
2742 pub meta: Option<Meta>,
2743}
2744
2745impl SetSessionConfigOptionResponse {
2746 #[must_use]
2747 pub fn new(config_options: Vec<SessionConfigOption>) -> Self {
2748 Self {
2749 config_options,
2750 meta: None,
2751 }
2752 }
2753
2754 #[must_use]
2760 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2761 self.meta = meta.into_option();
2762 self
2763 }
2764}
2765
2766#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2775#[serde(tag = "type", rename_all = "snake_case")]
2776#[non_exhaustive]
2777pub enum McpServer {
2778 Http(McpServerHttp),
2782 Sse(McpServerSse),
2786 #[cfg(feature = "unstable_mcp_over_acp")]
2795 Acp(McpServerAcp),
2796 #[serde(untagged)]
2800 Stdio(McpServerStdio),
2801}
2802
2803#[skip_serializing_none]
2805#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2806#[serde(rename_all = "camelCase")]
2807#[non_exhaustive]
2808pub struct McpServerHttp {
2809 pub name: String,
2811 pub url: String,
2813 pub headers: Vec<HttpHeader>,
2815 #[serde(rename = "_meta")]
2821 pub meta: Option<Meta>,
2822}
2823
2824impl McpServerHttp {
2825 #[must_use]
2826 pub fn new(name: impl Into<String>, url: impl Into<String>) -> Self {
2827 Self {
2828 name: name.into(),
2829 url: url.into(),
2830 headers: Vec::new(),
2831 meta: None,
2832 }
2833 }
2834
2835 #[must_use]
2837 pub fn headers(mut self, headers: Vec<HttpHeader>) -> Self {
2838 self.headers = headers;
2839 self
2840 }
2841
2842 #[must_use]
2848 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2849 self.meta = meta.into_option();
2850 self
2851 }
2852}
2853
2854#[skip_serializing_none]
2856#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2857#[serde(rename_all = "camelCase")]
2858#[non_exhaustive]
2859pub struct McpServerSse {
2860 pub name: String,
2862 pub url: String,
2864 pub headers: Vec<HttpHeader>,
2866 #[serde(rename = "_meta")]
2872 pub meta: Option<Meta>,
2873}
2874
2875impl McpServerSse {
2876 #[must_use]
2877 pub fn new(name: impl Into<String>, url: impl Into<String>) -> Self {
2878 Self {
2879 name: name.into(),
2880 url: url.into(),
2881 headers: Vec::new(),
2882 meta: None,
2883 }
2884 }
2885
2886 #[must_use]
2888 pub fn headers(mut self, headers: Vec<HttpHeader>) -> Self {
2889 self.headers = headers;
2890 self
2891 }
2892
2893 #[must_use]
2899 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2900 self.meta = meta.into_option();
2901 self
2902 }
2903}
2904
2905#[cfg(feature = "unstable_mcp_over_acp")]
2915#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
2916#[serde(transparent)]
2917#[from(Arc<str>, String, &'static str)]
2918#[non_exhaustive]
2919pub struct McpServerAcpId(pub Arc<str>);
2920
2921#[cfg(feature = "unstable_mcp_over_acp")]
2922impl McpServerAcpId {
2923 #[must_use]
2924 pub fn new(id: impl Into<Arc<str>>) -> Self {
2925 Self(id.into())
2926 }
2927}
2928
2929#[skip_serializing_none]
2938#[cfg(feature = "unstable_mcp_over_acp")]
2939#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2940#[serde(rename_all = "camelCase")]
2941#[non_exhaustive]
2942pub struct McpServerAcp {
2943 pub name: String,
2945 pub id: McpServerAcpId,
2950 #[serde(rename = "_meta")]
2956 pub meta: Option<Meta>,
2957}
2958
2959#[cfg(feature = "unstable_mcp_over_acp")]
2960impl McpServerAcp {
2961 #[must_use]
2962 pub fn new(name: impl Into<String>, id: impl Into<McpServerAcpId>) -> Self {
2963 Self {
2964 name: name.into(),
2965 id: id.into(),
2966 meta: None,
2967 }
2968 }
2969
2970 #[must_use]
2976 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2977 self.meta = meta.into_option();
2978 self
2979 }
2980}
2981
2982#[skip_serializing_none]
2984#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2985#[serde(rename_all = "camelCase")]
2986#[non_exhaustive]
2987pub struct McpServerStdio {
2988 pub name: String,
2990 pub command: PathBuf,
2992 pub args: Vec<String>,
2994 pub env: Vec<EnvVariable>,
2996 #[serde(rename = "_meta")]
3002 pub meta: Option<Meta>,
3003}
3004
3005impl McpServerStdio {
3006 #[must_use]
3007 pub fn new(name: impl Into<String>, command: impl Into<PathBuf>) -> Self {
3008 Self {
3009 name: name.into(),
3010 command: command.into(),
3011 args: Vec::new(),
3012 env: Vec::new(),
3013 meta: None,
3014 }
3015 }
3016
3017 #[must_use]
3019 pub fn args(mut self, args: Vec<String>) -> Self {
3020 self.args = args;
3021 self
3022 }
3023
3024 #[must_use]
3026 pub fn env(mut self, env: Vec<EnvVariable>) -> Self {
3027 self.env = env;
3028 self
3029 }
3030
3031 #[must_use]
3037 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3038 self.meta = meta.into_option();
3039 self
3040 }
3041}
3042
3043#[skip_serializing_none]
3045#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3046#[serde(rename_all = "camelCase")]
3047#[non_exhaustive]
3048pub struct EnvVariable {
3049 pub name: String,
3051 pub value: String,
3053 #[serde(rename = "_meta")]
3059 pub meta: Option<Meta>,
3060}
3061
3062impl EnvVariable {
3063 #[must_use]
3064 pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
3065 Self {
3066 name: name.into(),
3067 value: value.into(),
3068 meta: None,
3069 }
3070 }
3071
3072 #[must_use]
3078 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3079 self.meta = meta.into_option();
3080 self
3081 }
3082}
3083
3084#[skip_serializing_none]
3086#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3087#[serde(rename_all = "camelCase")]
3088#[non_exhaustive]
3089pub struct HttpHeader {
3090 pub name: String,
3092 pub value: String,
3094 #[serde(rename = "_meta")]
3100 pub meta: Option<Meta>,
3101}
3102
3103impl HttpHeader {
3104 #[must_use]
3105 pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
3106 Self {
3107 name: name.into(),
3108 value: value.into(),
3109 meta: None,
3110 }
3111 }
3112
3113 #[must_use]
3119 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3120 self.meta = meta.into_option();
3121 self
3122 }
3123}
3124
3125#[skip_serializing_none]
3133#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
3134#[schemars(extend("x-side" = "agent", "x-method" = SESSION_PROMPT_METHOD_NAME))]
3135#[serde(rename_all = "camelCase")]
3136#[non_exhaustive]
3137pub struct PromptRequest {
3138 pub session_id: SessionId,
3140 #[cfg(feature = "unstable_message_id")]
3150 pub message_id: Option<String>,
3151 pub prompt: Vec<ContentBlock>,
3165 #[serde(rename = "_meta")]
3171 pub meta: Option<Meta>,
3172}
3173
3174impl PromptRequest {
3175 #[must_use]
3176 pub fn new(session_id: impl Into<SessionId>, prompt: Vec<ContentBlock>) -> Self {
3177 Self {
3178 session_id: session_id.into(),
3179 #[cfg(feature = "unstable_message_id")]
3180 message_id: None,
3181 prompt,
3182 meta: None,
3183 }
3184 }
3185
3186 #[cfg(feature = "unstable_message_id")]
3196 #[must_use]
3197 pub fn message_id(mut self, message_id: impl IntoOption<String>) -> Self {
3198 self.message_id = message_id.into_option();
3199 self
3200 }
3201
3202 #[must_use]
3208 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3209 self.meta = meta.into_option();
3210 self
3211 }
3212}
3213
3214#[serde_as]
3218#[skip_serializing_none]
3219#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3220#[schemars(extend("x-side" = "agent", "x-method" = SESSION_PROMPT_METHOD_NAME))]
3221#[serde(rename_all = "camelCase")]
3222#[non_exhaustive]
3223pub struct PromptResponse {
3224 #[cfg(feature = "unstable_message_id")]
3234 pub user_message_id: Option<String>,
3235 pub stop_reason: StopReason,
3237 #[cfg(feature = "unstable_session_usage")]
3243 #[serde_as(deserialize_as = "DefaultOnError")]
3244 #[serde(default)]
3245 pub usage: Option<Usage>,
3246 #[serde(rename = "_meta")]
3252 pub meta: Option<Meta>,
3253}
3254
3255impl PromptResponse {
3256 #[must_use]
3257 pub fn new(stop_reason: StopReason) -> Self {
3258 Self {
3259 #[cfg(feature = "unstable_message_id")]
3260 user_message_id: None,
3261 stop_reason,
3262 #[cfg(feature = "unstable_session_usage")]
3263 usage: None,
3264 meta: None,
3265 }
3266 }
3267
3268 #[cfg(feature = "unstable_message_id")]
3278 #[must_use]
3279 pub fn user_message_id(mut self, user_message_id: impl IntoOption<String>) -> Self {
3280 self.user_message_id = user_message_id.into_option();
3281 self
3282 }
3283
3284 #[cfg(feature = "unstable_session_usage")]
3290 #[must_use]
3291 pub fn usage(mut self, usage: impl IntoOption<Usage>) -> Self {
3292 self.usage = usage.into_option();
3293 self
3294 }
3295
3296 #[must_use]
3302 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3303 self.meta = meta.into_option();
3304 self
3305 }
3306}
3307
3308#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
3312#[serde(rename_all = "snake_case")]
3313#[non_exhaustive]
3314pub enum StopReason {
3315 EndTurn,
3317 MaxTokens,
3319 MaxTurnRequests,
3322 Refusal,
3326 Cancelled,
3333}
3334
3335#[cfg(feature = "unstable_session_usage")]
3341#[skip_serializing_none]
3342#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3343#[serde(rename_all = "camelCase")]
3344#[non_exhaustive]
3345pub struct Usage {
3346 pub total_tokens: u64,
3348 pub input_tokens: u64,
3350 pub output_tokens: u64,
3352 pub thought_tokens: Option<u64>,
3354 pub cached_read_tokens: Option<u64>,
3356 pub cached_write_tokens: Option<u64>,
3358}
3359
3360#[cfg(feature = "unstable_session_usage")]
3361impl Usage {
3362 #[must_use]
3363 pub fn new(total_tokens: u64, input_tokens: u64, output_tokens: u64) -> Self {
3364 Self {
3365 total_tokens,
3366 input_tokens,
3367 output_tokens,
3368 thought_tokens: None,
3369 cached_read_tokens: None,
3370 cached_write_tokens: None,
3371 }
3372 }
3373
3374 #[must_use]
3376 pub fn thought_tokens(mut self, thought_tokens: impl IntoOption<u64>) -> Self {
3377 self.thought_tokens = thought_tokens.into_option();
3378 self
3379 }
3380
3381 #[must_use]
3383 pub fn cached_read_tokens(mut self, cached_read_tokens: impl IntoOption<u64>) -> Self {
3384 self.cached_read_tokens = cached_read_tokens.into_option();
3385 self
3386 }
3387
3388 #[must_use]
3390 pub fn cached_write_tokens(mut self, cached_write_tokens: impl IntoOption<u64>) -> Self {
3391 self.cached_write_tokens = cached_write_tokens.into_option();
3392 self
3393 }
3394}
3395
3396#[cfg(feature = "unstable_session_model")]
3404#[serde_as]
3405#[skip_serializing_none]
3406#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3407#[serde(rename_all = "camelCase")]
3408#[non_exhaustive]
3409pub struct SessionModelState {
3410 pub current_model_id: ModelId,
3412 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
3414 pub available_models: Vec<ModelInfo>,
3415 #[serde(rename = "_meta")]
3421 pub meta: Option<Meta>,
3422}
3423
3424#[cfg(feature = "unstable_session_model")]
3425impl SessionModelState {
3426 #[must_use]
3427 pub fn new(current_model_id: impl Into<ModelId>, available_models: Vec<ModelInfo>) -> Self {
3428 Self {
3429 current_model_id: current_model_id.into(),
3430 available_models,
3431 meta: None,
3432 }
3433 }
3434
3435 #[must_use]
3441 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3442 self.meta = meta.into_option();
3443 self
3444 }
3445}
3446
3447#[cfg(feature = "unstable_session_model")]
3453#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
3454#[serde(transparent)]
3455#[from(Arc<str>, String, &'static str)]
3456#[non_exhaustive]
3457pub struct ModelId(pub Arc<str>);
3458
3459#[cfg(feature = "unstable_session_model")]
3460impl ModelId {
3461 #[must_use]
3462 pub fn new(id: impl Into<Arc<str>>) -> Self {
3463 Self(id.into())
3464 }
3465}
3466
3467#[cfg(feature = "unstable_session_model")]
3473#[skip_serializing_none]
3474#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3475#[serde(rename_all = "camelCase")]
3476#[non_exhaustive]
3477pub struct ModelInfo {
3478 pub model_id: ModelId,
3480 pub name: String,
3482 #[serde(default)]
3484 pub description: Option<String>,
3485 #[serde(rename = "_meta")]
3491 pub meta: Option<Meta>,
3492}
3493
3494#[cfg(feature = "unstable_session_model")]
3495impl ModelInfo {
3496 #[must_use]
3497 pub fn new(model_id: impl Into<ModelId>, name: impl Into<String>) -> Self {
3498 Self {
3499 model_id: model_id.into(),
3500 name: name.into(),
3501 description: None,
3502 meta: None,
3503 }
3504 }
3505
3506 #[must_use]
3508 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
3509 self.description = description.into_option();
3510 self
3511 }
3512
3513 #[must_use]
3519 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3520 self.meta = meta.into_option();
3521 self
3522 }
3523}
3524
3525#[cfg(feature = "unstable_session_model")]
3531#[skip_serializing_none]
3532#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3533#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODEL_METHOD_NAME))]
3534#[serde(rename_all = "camelCase")]
3535#[non_exhaustive]
3536pub struct SetSessionModelRequest {
3537 pub session_id: SessionId,
3539 pub model_id: ModelId,
3541 #[serde(rename = "_meta")]
3547 pub meta: Option<Meta>,
3548}
3549
3550#[cfg(feature = "unstable_session_model")]
3551impl SetSessionModelRequest {
3552 #[must_use]
3553 pub fn new(session_id: impl Into<SessionId>, model_id: impl Into<ModelId>) -> Self {
3554 Self {
3555 session_id: session_id.into(),
3556 model_id: model_id.into(),
3557 meta: None,
3558 }
3559 }
3560
3561 #[must_use]
3567 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3568 self.meta = meta.into_option();
3569 self
3570 }
3571}
3572
3573#[cfg(feature = "unstable_session_model")]
3579#[skip_serializing_none]
3580#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3581#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODEL_METHOD_NAME))]
3582#[serde(rename_all = "camelCase")]
3583#[non_exhaustive]
3584pub struct SetSessionModelResponse {
3585 #[serde(rename = "_meta")]
3591 pub meta: Option<Meta>,
3592}
3593
3594#[cfg(feature = "unstable_session_model")]
3595impl SetSessionModelResponse {
3596 #[must_use]
3597 pub fn new() -> Self {
3598 Self::default()
3599 }
3600
3601 #[must_use]
3607 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3608 self.meta = meta.into_option();
3609 self
3610 }
3611}
3612
3613#[cfg(feature = "unstable_llm_providers")]
3626#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3627#[serde(rename_all = "snake_case")]
3628#[non_exhaustive]
3629#[expect(clippy::doc_markdown)]
3630pub enum LlmProtocol {
3631 Anthropic,
3633 #[serde(rename = "openai")]
3635 OpenAi,
3636 Azure,
3638 Vertex,
3640 Bedrock,
3642 #[serde(untagged)]
3644 Other(String),
3645}
3646
3647#[cfg(feature = "unstable_llm_providers")]
3653#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3654#[serde(rename_all = "camelCase")]
3655#[non_exhaustive]
3656pub struct ProviderCurrentConfig {
3657 pub api_type: LlmProtocol,
3659 pub base_url: String,
3661}
3662
3663#[cfg(feature = "unstable_llm_providers")]
3664impl ProviderCurrentConfig {
3665 #[must_use]
3666 pub fn new(api_type: LlmProtocol, base_url: impl Into<String>) -> Self {
3667 Self {
3668 api_type,
3669 base_url: base_url.into(),
3670 }
3671 }
3672}
3673
3674#[cfg(feature = "unstable_llm_providers")]
3680#[serde_as]
3681#[skip_serializing_none]
3682#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3683#[serde(rename_all = "camelCase")]
3684#[non_exhaustive]
3685pub struct ProviderInfo {
3686 pub id: String,
3688 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
3690 pub supported: Vec<LlmProtocol>,
3691 pub required: bool,
3694 pub current: Option<ProviderCurrentConfig>,
3697 #[serde(rename = "_meta")]
3703 pub meta: Option<Meta>,
3704}
3705
3706#[cfg(feature = "unstable_llm_providers")]
3707impl ProviderInfo {
3708 #[must_use]
3709 pub fn new(
3710 id: impl Into<String>,
3711 supported: Vec<LlmProtocol>,
3712 required: bool,
3713 current: impl IntoOption<ProviderCurrentConfig>,
3714 ) -> Self {
3715 Self {
3716 id: id.into(),
3717 supported,
3718 required,
3719 current: current.into_option(),
3720 meta: None,
3721 }
3722 }
3723
3724 #[must_use]
3730 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3731 self.meta = meta.into_option();
3732 self
3733 }
3734}
3735
3736#[cfg(feature = "unstable_llm_providers")]
3742#[skip_serializing_none]
3743#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3744#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_LIST_METHOD_NAME))]
3745#[serde(rename_all = "camelCase")]
3746#[non_exhaustive]
3747pub struct ListProvidersRequest {
3748 #[serde(rename = "_meta")]
3754 pub meta: Option<Meta>,
3755}
3756
3757#[cfg(feature = "unstable_llm_providers")]
3758impl ListProvidersRequest {
3759 #[must_use]
3760 pub fn new() -> Self {
3761 Self::default()
3762 }
3763
3764 #[must_use]
3770 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3771 self.meta = meta.into_option();
3772 self
3773 }
3774}
3775
3776#[cfg(feature = "unstable_llm_providers")]
3782#[serde_as]
3783#[skip_serializing_none]
3784#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3785#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_LIST_METHOD_NAME))]
3786#[serde(rename_all = "camelCase")]
3787#[non_exhaustive]
3788pub struct ListProvidersResponse {
3789 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
3791 pub providers: Vec<ProviderInfo>,
3792 #[serde(rename = "_meta")]
3798 pub meta: Option<Meta>,
3799}
3800
3801#[cfg(feature = "unstable_llm_providers")]
3802impl ListProvidersResponse {
3803 #[must_use]
3804 pub fn new(providers: Vec<ProviderInfo>) -> Self {
3805 Self {
3806 providers,
3807 meta: None,
3808 }
3809 }
3810
3811 #[must_use]
3817 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3818 self.meta = meta.into_option();
3819 self
3820 }
3821}
3822
3823#[cfg(feature = "unstable_llm_providers")]
3831#[skip_serializing_none]
3832#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3833#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_SET_METHOD_NAME))]
3834#[serde(rename_all = "camelCase")]
3835#[non_exhaustive]
3836pub struct SetProvidersRequest {
3837 pub id: String,
3839 pub api_type: LlmProtocol,
3841 pub base_url: String,
3843 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
3846 pub headers: HashMap<String, String>,
3847 #[serde(rename = "_meta")]
3853 pub meta: Option<Meta>,
3854}
3855
3856#[cfg(feature = "unstable_llm_providers")]
3857impl SetProvidersRequest {
3858 #[must_use]
3859 pub fn new(id: impl Into<String>, api_type: LlmProtocol, base_url: impl Into<String>) -> Self {
3860 Self {
3861 id: id.into(),
3862 api_type,
3863 base_url: base_url.into(),
3864 headers: HashMap::new(),
3865 meta: None,
3866 }
3867 }
3868
3869 #[must_use]
3872 pub fn headers(mut self, headers: HashMap<String, String>) -> Self {
3873 self.headers = headers;
3874 self
3875 }
3876
3877 #[must_use]
3883 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3884 self.meta = meta.into_option();
3885 self
3886 }
3887}
3888
3889#[cfg(feature = "unstable_llm_providers")]
3895#[skip_serializing_none]
3896#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3897#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_SET_METHOD_NAME))]
3898#[serde(rename_all = "camelCase")]
3899#[non_exhaustive]
3900pub struct SetProvidersResponse {
3901 #[serde(rename = "_meta")]
3907 pub meta: Option<Meta>,
3908}
3909
3910#[cfg(feature = "unstable_llm_providers")]
3911impl SetProvidersResponse {
3912 #[must_use]
3913 pub fn new() -> Self {
3914 Self::default()
3915 }
3916
3917 #[must_use]
3923 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3924 self.meta = meta.into_option();
3925 self
3926 }
3927}
3928
3929#[cfg(feature = "unstable_llm_providers")]
3935#[skip_serializing_none]
3936#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3937#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_DISABLE_METHOD_NAME))]
3938#[serde(rename_all = "camelCase")]
3939#[non_exhaustive]
3940pub struct DisableProvidersRequest {
3941 pub id: String,
3943 #[serde(rename = "_meta")]
3949 pub meta: Option<Meta>,
3950}
3951
3952#[cfg(feature = "unstable_llm_providers")]
3953impl DisableProvidersRequest {
3954 #[must_use]
3955 pub fn new(id: impl Into<String>) -> Self {
3956 Self {
3957 id: id.into(),
3958 meta: None,
3959 }
3960 }
3961
3962 #[must_use]
3968 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3969 self.meta = meta.into_option();
3970 self
3971 }
3972}
3973
3974#[cfg(feature = "unstable_llm_providers")]
3980#[skip_serializing_none]
3981#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3982#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_DISABLE_METHOD_NAME))]
3983#[serde(rename_all = "camelCase")]
3984#[non_exhaustive]
3985pub struct DisableProvidersResponse {
3986 #[serde(rename = "_meta")]
3992 pub meta: Option<Meta>,
3993}
3994
3995#[cfg(feature = "unstable_llm_providers")]
3996impl DisableProvidersResponse {
3997 #[must_use]
3998 pub fn new() -> Self {
3999 Self::default()
4000 }
4001
4002 #[must_use]
4008 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4009 self.meta = meta.into_option();
4010 self
4011 }
4012}
4013
4014#[serde_as]
4023#[skip_serializing_none]
4024#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4025#[serde(rename_all = "camelCase")]
4026#[non_exhaustive]
4027pub struct AgentCapabilities {
4028 #[serde(default)]
4030 pub load_session: bool,
4031 #[serde(default)]
4033 pub prompt_capabilities: PromptCapabilities,
4034 #[serde(default)]
4036 pub mcp_capabilities: McpCapabilities,
4037 #[serde(default)]
4038 pub session_capabilities: SessionCapabilities,
4039 #[cfg(feature = "unstable_logout")]
4045 #[serde(default)]
4046 pub auth: AgentAuthCapabilities,
4047 #[cfg(feature = "unstable_llm_providers")]
4055 #[serde_as(deserialize_as = "DefaultOnError")]
4056 #[serde(default)]
4057 pub providers: Option<ProvidersCapabilities>,
4058 #[cfg(feature = "unstable_nes")]
4064 #[serde_as(deserialize_as = "DefaultOnError")]
4065 #[serde(default)]
4066 pub nes: Option<NesCapabilities>,
4067 #[cfg(feature = "unstable_nes")]
4073 #[serde_as(deserialize_as = "DefaultOnError")]
4074 #[serde(default)]
4075 pub position_encoding: Option<PositionEncodingKind>,
4076 #[serde(rename = "_meta")]
4082 pub meta: Option<Meta>,
4083}
4084
4085impl AgentCapabilities {
4086 #[must_use]
4087 pub fn new() -> Self {
4088 Self::default()
4089 }
4090
4091 #[must_use]
4093 pub fn load_session(mut self, load_session: bool) -> Self {
4094 self.load_session = load_session;
4095 self
4096 }
4097
4098 #[must_use]
4100 pub fn prompt_capabilities(mut self, prompt_capabilities: PromptCapabilities) -> Self {
4101 self.prompt_capabilities = prompt_capabilities;
4102 self
4103 }
4104
4105 #[must_use]
4107 pub fn mcp_capabilities(mut self, mcp_capabilities: McpCapabilities) -> Self {
4108 self.mcp_capabilities = mcp_capabilities;
4109 self
4110 }
4111
4112 #[must_use]
4114 pub fn session_capabilities(mut self, session_capabilities: SessionCapabilities) -> Self {
4115 self.session_capabilities = session_capabilities;
4116 self
4117 }
4118
4119 #[cfg(feature = "unstable_logout")]
4125 #[must_use]
4126 pub fn auth(mut self, auth: AgentAuthCapabilities) -> Self {
4127 self.auth = auth;
4128 self
4129 }
4130
4131 #[cfg(feature = "unstable_llm_providers")]
4137 #[must_use]
4138 pub fn providers(mut self, providers: impl IntoOption<ProvidersCapabilities>) -> Self {
4139 self.providers = providers.into_option();
4140 self
4141 }
4142
4143 #[cfg(feature = "unstable_nes")]
4149 #[must_use]
4150 pub fn nes(mut self, nes: impl IntoOption<NesCapabilities>) -> Self {
4151 self.nes = nes.into_option();
4152 self
4153 }
4154
4155 #[cfg(feature = "unstable_nes")]
4159 #[must_use]
4160 pub fn position_encoding(
4161 mut self,
4162 position_encoding: impl IntoOption<PositionEncodingKind>,
4163 ) -> Self {
4164 self.position_encoding = position_encoding.into_option();
4165 self
4166 }
4167
4168 #[must_use]
4174 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4175 self.meta = meta.into_option();
4176 self
4177 }
4178}
4179
4180#[cfg(feature = "unstable_llm_providers")]
4188#[skip_serializing_none]
4189#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4190#[non_exhaustive]
4191pub struct ProvidersCapabilities {
4192 #[serde(rename = "_meta")]
4198 pub meta: Option<Meta>,
4199}
4200
4201#[cfg(feature = "unstable_llm_providers")]
4202impl ProvidersCapabilities {
4203 #[must_use]
4204 pub fn new() -> Self {
4205 Self::default()
4206 }
4207
4208 #[must_use]
4214 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4215 self.meta = meta.into_option();
4216 self
4217 }
4218}
4219
4220#[serde_as]
4230#[skip_serializing_none]
4231#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4232#[serde(rename_all = "camelCase")]
4233#[non_exhaustive]
4234pub struct SessionCapabilities {
4235 #[serde_as(deserialize_as = "DefaultOnError")]
4237 #[serde(default)]
4238 pub list: Option<SessionListCapabilities>,
4239 #[cfg(feature = "unstable_session_delete")]
4248 #[serde_as(deserialize_as = "DefaultOnError")]
4249 #[serde(default)]
4250 pub delete: Option<SessionDeleteCapabilities>,
4251 #[cfg(feature = "unstable_session_additional_directories")]
4257 #[serde_as(deserialize_as = "DefaultOnError")]
4258 #[serde(default)]
4259 pub additional_directories: Option<SessionAdditionalDirectoriesCapabilities>,
4260 #[cfg(feature = "unstable_session_fork")]
4266 #[serde_as(deserialize_as = "DefaultOnError")]
4267 #[serde(default)]
4268 pub fork: Option<SessionForkCapabilities>,
4269 #[serde_as(deserialize_as = "DefaultOnError")]
4271 #[serde(default)]
4272 pub resume: Option<SessionResumeCapabilities>,
4273 #[serde_as(deserialize_as = "DefaultOnError")]
4275 #[serde(default)]
4276 pub close: Option<SessionCloseCapabilities>,
4277 #[serde(rename = "_meta")]
4283 pub meta: Option<Meta>,
4284}
4285
4286impl SessionCapabilities {
4287 #[must_use]
4288 pub fn new() -> Self {
4289 Self::default()
4290 }
4291
4292 #[must_use]
4294 pub fn list(mut self, list: impl IntoOption<SessionListCapabilities>) -> Self {
4295 self.list = list.into_option();
4296 self
4297 }
4298
4299 #[cfg(feature = "unstable_session_delete")]
4308 #[must_use]
4309 pub fn delete(mut self, delete: impl IntoOption<SessionDeleteCapabilities>) -> Self {
4310 self.delete = delete.into_option();
4311 self
4312 }
4313
4314 #[cfg(feature = "unstable_session_additional_directories")]
4320 #[must_use]
4321 pub fn additional_directories(
4322 mut self,
4323 additional_directories: impl IntoOption<SessionAdditionalDirectoriesCapabilities>,
4324 ) -> Self {
4325 self.additional_directories = additional_directories.into_option();
4326 self
4327 }
4328
4329 #[cfg(feature = "unstable_session_fork")]
4330 #[must_use]
4332 pub fn fork(mut self, fork: impl IntoOption<SessionForkCapabilities>) -> Self {
4333 self.fork = fork.into_option();
4334 self
4335 }
4336
4337 #[must_use]
4339 pub fn resume(mut self, resume: impl IntoOption<SessionResumeCapabilities>) -> Self {
4340 self.resume = resume.into_option();
4341 self
4342 }
4343
4344 #[must_use]
4346 pub fn close(mut self, close: impl IntoOption<SessionCloseCapabilities>) -> Self {
4347 self.close = close.into_option();
4348 self
4349 }
4350
4351 #[must_use]
4357 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4358 self.meta = meta.into_option();
4359 self
4360 }
4361}
4362
4363#[skip_serializing_none]
4367#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4368#[non_exhaustive]
4369pub struct SessionListCapabilities {
4370 #[serde(rename = "_meta")]
4376 pub meta: Option<Meta>,
4377}
4378
4379impl SessionListCapabilities {
4380 #[must_use]
4381 pub fn new() -> Self {
4382 Self::default()
4383 }
4384
4385 #[must_use]
4391 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4392 self.meta = meta.into_option();
4393 self
4394 }
4395}
4396
4397#[cfg(feature = "unstable_session_delete")]
4405#[skip_serializing_none]
4406#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4407#[non_exhaustive]
4408pub struct SessionDeleteCapabilities {
4409 #[serde(rename = "_meta")]
4415 pub meta: Option<Meta>,
4416}
4417
4418#[cfg(feature = "unstable_session_delete")]
4419impl SessionDeleteCapabilities {
4420 #[must_use]
4421 pub fn new() -> Self {
4422 Self::default()
4423 }
4424
4425 #[must_use]
4431 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4432 self.meta = meta.into_option();
4433 self
4434 }
4435}
4436
4437#[cfg(feature = "unstable_session_additional_directories")]
4446#[skip_serializing_none]
4447#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4448#[non_exhaustive]
4449pub struct SessionAdditionalDirectoriesCapabilities {
4450 #[serde(rename = "_meta")]
4456 pub meta: Option<Meta>,
4457}
4458
4459#[cfg(feature = "unstable_session_additional_directories")]
4460impl SessionAdditionalDirectoriesCapabilities {
4461 #[must_use]
4462 pub fn new() -> Self {
4463 Self::default()
4464 }
4465
4466 #[must_use]
4472 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4473 self.meta = meta.into_option();
4474 self
4475 }
4476}
4477
4478#[cfg(feature = "unstable_session_fork")]
4486#[skip_serializing_none]
4487#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4488#[non_exhaustive]
4489pub struct SessionForkCapabilities {
4490 #[serde(rename = "_meta")]
4496 pub meta: Option<Meta>,
4497}
4498
4499#[cfg(feature = "unstable_session_fork")]
4500impl SessionForkCapabilities {
4501 #[must_use]
4502 pub fn new() -> Self {
4503 Self::default()
4504 }
4505
4506 #[must_use]
4512 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4513 self.meta = meta.into_option();
4514 self
4515 }
4516}
4517
4518#[skip_serializing_none]
4522#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4523#[non_exhaustive]
4524pub struct SessionResumeCapabilities {
4525 #[serde(rename = "_meta")]
4531 pub meta: Option<Meta>,
4532}
4533
4534impl SessionResumeCapabilities {
4535 #[must_use]
4536 pub fn new() -> Self {
4537 Self::default()
4538 }
4539
4540 #[must_use]
4546 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4547 self.meta = meta.into_option();
4548 self
4549 }
4550}
4551
4552#[skip_serializing_none]
4556#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4557#[non_exhaustive]
4558pub struct SessionCloseCapabilities {
4559 #[serde(rename = "_meta")]
4565 pub meta: Option<Meta>,
4566}
4567
4568impl SessionCloseCapabilities {
4569 #[must_use]
4570 pub fn new() -> Self {
4571 Self::default()
4572 }
4573
4574 #[must_use]
4580 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4581 self.meta = meta.into_option();
4582 self
4583 }
4584}
4585
4586#[skip_serializing_none]
4599#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4600#[serde(rename_all = "camelCase")]
4601#[non_exhaustive]
4602pub struct PromptCapabilities {
4603 #[serde(default)]
4605 pub image: bool,
4606 #[serde(default)]
4608 pub audio: bool,
4609 #[serde(default)]
4614 pub embedded_context: bool,
4615 #[serde(rename = "_meta")]
4621 pub meta: Option<Meta>,
4622}
4623
4624impl PromptCapabilities {
4625 #[must_use]
4626 pub fn new() -> Self {
4627 Self::default()
4628 }
4629
4630 #[must_use]
4632 pub fn image(mut self, image: bool) -> Self {
4633 self.image = image;
4634 self
4635 }
4636
4637 #[must_use]
4639 pub fn audio(mut self, audio: bool) -> Self {
4640 self.audio = audio;
4641 self
4642 }
4643
4644 #[must_use]
4649 pub fn embedded_context(mut self, embedded_context: bool) -> Self {
4650 self.embedded_context = embedded_context;
4651 self
4652 }
4653
4654 #[must_use]
4660 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4661 self.meta = meta.into_option();
4662 self
4663 }
4664}
4665
4666#[skip_serializing_none]
4668#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4669#[serde(rename_all = "camelCase")]
4670#[non_exhaustive]
4671pub struct McpCapabilities {
4672 #[serde(default)]
4674 pub http: bool,
4675 #[serde(default)]
4677 pub sse: bool,
4678 #[cfg(feature = "unstable_mcp_over_acp")]
4684 #[serde(default)]
4685 pub acp: bool,
4686 #[serde(rename = "_meta")]
4692 pub meta: Option<Meta>,
4693}
4694
4695impl McpCapabilities {
4696 #[must_use]
4697 pub fn new() -> Self {
4698 Self::default()
4699 }
4700
4701 #[must_use]
4703 pub fn http(mut self, http: bool) -> Self {
4704 self.http = http;
4705 self
4706 }
4707
4708 #[must_use]
4710 pub fn sse(mut self, sse: bool) -> Self {
4711 self.sse = sse;
4712 self
4713 }
4714
4715 #[cfg(feature = "unstable_mcp_over_acp")]
4721 #[must_use]
4722 pub fn acp(mut self, acp: bool) -> Self {
4723 self.acp = acp;
4724 self
4725 }
4726
4727 #[must_use]
4733 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4734 self.meta = meta.into_option();
4735 self
4736 }
4737}
4738
4739#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4745#[non_exhaustive]
4746pub struct AgentMethodNames {
4747 pub initialize: &'static str,
4749 pub authenticate: &'static str,
4751 #[cfg(feature = "unstable_llm_providers")]
4753 pub providers_list: &'static str,
4754 #[cfg(feature = "unstable_llm_providers")]
4756 pub providers_set: &'static str,
4757 #[cfg(feature = "unstable_llm_providers")]
4759 pub providers_disable: &'static str,
4760 pub session_new: &'static str,
4762 pub session_load: &'static str,
4764 pub session_set_mode: &'static str,
4766 pub session_set_config_option: &'static str,
4768 pub session_prompt: &'static str,
4770 pub session_cancel: &'static str,
4772 #[cfg(feature = "unstable_mcp_over_acp")]
4774 pub mcp_message: &'static str,
4775 #[cfg(feature = "unstable_session_model")]
4777 pub session_set_model: &'static str,
4778 pub session_list: &'static str,
4780 #[cfg(feature = "unstable_session_delete")]
4782 pub session_delete: &'static str,
4783 #[cfg(feature = "unstable_session_fork")]
4785 pub session_fork: &'static str,
4786 pub session_resume: &'static str,
4788 pub session_close: &'static str,
4790 #[cfg(feature = "unstable_logout")]
4792 pub logout: &'static str,
4793 #[cfg(feature = "unstable_nes")]
4795 pub nes_start: &'static str,
4796 #[cfg(feature = "unstable_nes")]
4798 pub nes_suggest: &'static str,
4799 #[cfg(feature = "unstable_nes")]
4801 pub nes_accept: &'static str,
4802 #[cfg(feature = "unstable_nes")]
4804 pub nes_reject: &'static str,
4805 #[cfg(feature = "unstable_nes")]
4807 pub nes_close: &'static str,
4808 #[cfg(feature = "unstable_nes")]
4810 pub document_did_open: &'static str,
4811 #[cfg(feature = "unstable_nes")]
4813 pub document_did_change: &'static str,
4814 #[cfg(feature = "unstable_nes")]
4816 pub document_did_close: &'static str,
4817 #[cfg(feature = "unstable_nes")]
4819 pub document_did_save: &'static str,
4820 #[cfg(feature = "unstable_nes")]
4822 pub document_did_focus: &'static str,
4823}
4824
4825pub const AGENT_METHOD_NAMES: AgentMethodNames = AgentMethodNames {
4827 initialize: INITIALIZE_METHOD_NAME,
4828 authenticate: AUTHENTICATE_METHOD_NAME,
4829 #[cfg(feature = "unstable_llm_providers")]
4830 providers_list: PROVIDERS_LIST_METHOD_NAME,
4831 #[cfg(feature = "unstable_llm_providers")]
4832 providers_set: PROVIDERS_SET_METHOD_NAME,
4833 #[cfg(feature = "unstable_llm_providers")]
4834 providers_disable: PROVIDERS_DISABLE_METHOD_NAME,
4835 session_new: SESSION_NEW_METHOD_NAME,
4836 session_load: SESSION_LOAD_METHOD_NAME,
4837 session_set_mode: SESSION_SET_MODE_METHOD_NAME,
4838 session_set_config_option: SESSION_SET_CONFIG_OPTION_METHOD_NAME,
4839 session_prompt: SESSION_PROMPT_METHOD_NAME,
4840 session_cancel: SESSION_CANCEL_METHOD_NAME,
4841 #[cfg(feature = "unstable_mcp_over_acp")]
4842 mcp_message: MCP_MESSAGE_METHOD_NAME,
4843 #[cfg(feature = "unstable_session_model")]
4844 session_set_model: SESSION_SET_MODEL_METHOD_NAME,
4845 session_list: SESSION_LIST_METHOD_NAME,
4846 #[cfg(feature = "unstable_session_delete")]
4847 session_delete: SESSION_DELETE_METHOD_NAME,
4848 #[cfg(feature = "unstable_session_fork")]
4849 session_fork: SESSION_FORK_METHOD_NAME,
4850 session_resume: SESSION_RESUME_METHOD_NAME,
4851 session_close: SESSION_CLOSE_METHOD_NAME,
4852 #[cfg(feature = "unstable_logout")]
4853 logout: LOGOUT_METHOD_NAME,
4854 #[cfg(feature = "unstable_nes")]
4855 nes_start: NES_START_METHOD_NAME,
4856 #[cfg(feature = "unstable_nes")]
4857 nes_suggest: NES_SUGGEST_METHOD_NAME,
4858 #[cfg(feature = "unstable_nes")]
4859 nes_accept: NES_ACCEPT_METHOD_NAME,
4860 #[cfg(feature = "unstable_nes")]
4861 nes_reject: NES_REJECT_METHOD_NAME,
4862 #[cfg(feature = "unstable_nes")]
4863 nes_close: NES_CLOSE_METHOD_NAME,
4864 #[cfg(feature = "unstable_nes")]
4865 document_did_open: DOCUMENT_DID_OPEN_METHOD_NAME,
4866 #[cfg(feature = "unstable_nes")]
4867 document_did_change: DOCUMENT_DID_CHANGE_METHOD_NAME,
4868 #[cfg(feature = "unstable_nes")]
4869 document_did_close: DOCUMENT_DID_CLOSE_METHOD_NAME,
4870 #[cfg(feature = "unstable_nes")]
4871 document_did_save: DOCUMENT_DID_SAVE_METHOD_NAME,
4872 #[cfg(feature = "unstable_nes")]
4873 document_did_focus: DOCUMENT_DID_FOCUS_METHOD_NAME,
4874};
4875
4876pub(crate) const INITIALIZE_METHOD_NAME: &str = "initialize";
4878pub(crate) const AUTHENTICATE_METHOD_NAME: &str = "authenticate";
4880#[cfg(feature = "unstable_llm_providers")]
4882pub(crate) const PROVIDERS_LIST_METHOD_NAME: &str = "providers/list";
4883#[cfg(feature = "unstable_llm_providers")]
4885pub(crate) const PROVIDERS_SET_METHOD_NAME: &str = "providers/set";
4886#[cfg(feature = "unstable_llm_providers")]
4888pub(crate) const PROVIDERS_DISABLE_METHOD_NAME: &str = "providers/disable";
4889pub(crate) const SESSION_NEW_METHOD_NAME: &str = "session/new";
4891pub(crate) const SESSION_LOAD_METHOD_NAME: &str = "session/load";
4893pub(crate) const SESSION_SET_MODE_METHOD_NAME: &str = "session/set_mode";
4895pub(crate) const SESSION_SET_CONFIG_OPTION_METHOD_NAME: &str = "session/set_config_option";
4897pub(crate) const SESSION_PROMPT_METHOD_NAME: &str = "session/prompt";
4899pub(crate) const SESSION_CANCEL_METHOD_NAME: &str = "session/cancel";
4901#[cfg(feature = "unstable_session_model")]
4903pub(crate) const SESSION_SET_MODEL_METHOD_NAME: &str = "session/set_model";
4904pub(crate) const SESSION_LIST_METHOD_NAME: &str = "session/list";
4906#[cfg(feature = "unstable_session_delete")]
4908pub(crate) const SESSION_DELETE_METHOD_NAME: &str = "session/delete";
4909#[cfg(feature = "unstable_session_fork")]
4911pub(crate) const SESSION_FORK_METHOD_NAME: &str = "session/fork";
4912pub(crate) const SESSION_RESUME_METHOD_NAME: &str = "session/resume";
4914pub(crate) const SESSION_CLOSE_METHOD_NAME: &str = "session/close";
4916#[cfg(feature = "unstable_logout")]
4918pub(crate) const LOGOUT_METHOD_NAME: &str = "logout";
4919
4920#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
4927#[serde(untagged)]
4928#[schemars(inline)]
4929#[non_exhaustive]
4930#[allow(clippy::large_enum_variant)]
4931pub enum ClientRequest {
4932 InitializeRequest(InitializeRequest),
4943 AuthenticateRequest(AuthenticateRequest),
4953 #[cfg(feature = "unstable_llm_providers")]
4959 ListProvidersRequest(ListProvidersRequest),
4960 #[cfg(feature = "unstable_llm_providers")]
4966 SetProvidersRequest(SetProvidersRequest),
4967 #[cfg(feature = "unstable_llm_providers")]
4973 DisableProvidersRequest(DisableProvidersRequest),
4974 #[cfg(feature = "unstable_logout")]
4983 LogoutRequest(LogoutRequest),
4984 NewSessionRequest(NewSessionRequest),
4997 LoadSessionRequest(LoadSessionRequest),
5008 ListSessionsRequest(ListSessionsRequest),
5014 #[cfg(feature = "unstable_session_delete")]
5022 DeleteSessionRequest(DeleteSessionRequest),
5023 #[cfg(feature = "unstable_session_fork")]
5024 ForkSessionRequest(ForkSessionRequest),
5036 ResumeSessionRequest(ResumeSessionRequest),
5043 CloseSessionRequest(CloseSessionRequest),
5050 SetSessionModeRequest(SetSessionModeRequest),
5064 SetSessionConfigOptionRequest(SetSessionConfigOptionRequest),
5066 PromptRequest(PromptRequest),
5078 #[cfg(feature = "unstable_session_model")]
5079 SetSessionModelRequest(SetSessionModelRequest),
5085 #[cfg(feature = "unstable_nes")]
5086 StartNesRequest(StartNesRequest),
5092 #[cfg(feature = "unstable_nes")]
5093 SuggestNesRequest(SuggestNesRequest),
5099 #[cfg(feature = "unstable_nes")]
5100 CloseNesRequest(CloseNesRequest),
5109 #[cfg(feature = "unstable_mcp_over_acp")]
5115 MessageMcpRequest(MessageMcpRequest),
5116 ExtMethodRequest(ExtRequest),
5123}
5124
5125impl ClientRequest {
5126 #[must_use]
5128 pub fn method(&self) -> &str {
5129 match self {
5130 Self::InitializeRequest(_) => AGENT_METHOD_NAMES.initialize,
5131 Self::AuthenticateRequest(_) => AGENT_METHOD_NAMES.authenticate,
5132 #[cfg(feature = "unstable_llm_providers")]
5133 Self::ListProvidersRequest(_) => AGENT_METHOD_NAMES.providers_list,
5134 #[cfg(feature = "unstable_llm_providers")]
5135 Self::SetProvidersRequest(_) => AGENT_METHOD_NAMES.providers_set,
5136 #[cfg(feature = "unstable_llm_providers")]
5137 Self::DisableProvidersRequest(_) => AGENT_METHOD_NAMES.providers_disable,
5138 #[cfg(feature = "unstable_logout")]
5139 Self::LogoutRequest(_) => AGENT_METHOD_NAMES.logout,
5140 Self::NewSessionRequest(_) => AGENT_METHOD_NAMES.session_new,
5141 Self::LoadSessionRequest(_) => AGENT_METHOD_NAMES.session_load,
5142 Self::ListSessionsRequest(_) => AGENT_METHOD_NAMES.session_list,
5143 #[cfg(feature = "unstable_session_delete")]
5144 Self::DeleteSessionRequest(_) => AGENT_METHOD_NAMES.session_delete,
5145 #[cfg(feature = "unstable_session_fork")]
5146 Self::ForkSessionRequest(_) => AGENT_METHOD_NAMES.session_fork,
5147 Self::ResumeSessionRequest(_) => AGENT_METHOD_NAMES.session_resume,
5148 Self::CloseSessionRequest(_) => AGENT_METHOD_NAMES.session_close,
5149 Self::SetSessionModeRequest(_) => AGENT_METHOD_NAMES.session_set_mode,
5150 Self::SetSessionConfigOptionRequest(_) => AGENT_METHOD_NAMES.session_set_config_option,
5151 Self::PromptRequest(_) => AGENT_METHOD_NAMES.session_prompt,
5152 #[cfg(feature = "unstable_session_model")]
5153 Self::SetSessionModelRequest(_) => AGENT_METHOD_NAMES.session_set_model,
5154 #[cfg(feature = "unstable_nes")]
5155 Self::StartNesRequest(_) => AGENT_METHOD_NAMES.nes_start,
5156 #[cfg(feature = "unstable_nes")]
5157 Self::SuggestNesRequest(_) => AGENT_METHOD_NAMES.nes_suggest,
5158 #[cfg(feature = "unstable_nes")]
5159 Self::CloseNesRequest(_) => AGENT_METHOD_NAMES.nes_close,
5160 #[cfg(feature = "unstable_mcp_over_acp")]
5161 Self::MessageMcpRequest(_) => AGENT_METHOD_NAMES.mcp_message,
5162 Self::ExtMethodRequest(ext_request) => &ext_request.method,
5163 }
5164 }
5165}
5166
5167#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
5174#[serde(untagged)]
5175#[schemars(inline)]
5176#[non_exhaustive]
5177#[allow(clippy::large_enum_variant)]
5178pub enum AgentResponse {
5179 InitializeResponse(InitializeResponse),
5180 AuthenticateResponse(#[serde(default)] AuthenticateResponse),
5181 #[cfg(feature = "unstable_llm_providers")]
5182 ListProvidersResponse(ListProvidersResponse),
5183 #[cfg(feature = "unstable_llm_providers")]
5184 SetProvidersResponse(#[serde(default)] SetProvidersResponse),
5185 #[cfg(feature = "unstable_llm_providers")]
5186 DisableProvidersResponse(#[serde(default)] DisableProvidersResponse),
5187 #[cfg(feature = "unstable_logout")]
5188 LogoutResponse(#[serde(default)] LogoutResponse),
5189 NewSessionResponse(NewSessionResponse),
5190 LoadSessionResponse(#[serde(default)] LoadSessionResponse),
5191 ListSessionsResponse(ListSessionsResponse),
5192 #[cfg(feature = "unstable_session_delete")]
5193 DeleteSessionResponse(#[serde(default)] DeleteSessionResponse),
5194 #[cfg(feature = "unstable_session_fork")]
5195 ForkSessionResponse(ForkSessionResponse),
5196 ResumeSessionResponse(#[serde(default)] ResumeSessionResponse),
5197 CloseSessionResponse(#[serde(default)] CloseSessionResponse),
5198 SetSessionModeResponse(#[serde(default)] SetSessionModeResponse),
5199 SetSessionConfigOptionResponse(SetSessionConfigOptionResponse),
5200 PromptResponse(PromptResponse),
5201 #[cfg(feature = "unstable_session_model")]
5202 SetSessionModelResponse(#[serde(default)] SetSessionModelResponse),
5203 #[cfg(feature = "unstable_nes")]
5204 StartNesResponse(StartNesResponse),
5205 #[cfg(feature = "unstable_nes")]
5206 SuggestNesResponse(SuggestNesResponse),
5207 #[cfg(feature = "unstable_nes")]
5208 CloseNesResponse(#[serde(default)] CloseNesResponse),
5209 ExtMethodResponse(ExtResponse),
5210 #[cfg(feature = "unstable_mcp_over_acp")]
5211 MessageMcpResponse(MessageMcpResponse),
5212}
5213
5214#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
5221#[serde(untagged)]
5222#[schemars(inline)]
5223#[non_exhaustive]
5224pub enum ClientNotification {
5225 CancelNotification(CancelNotification),
5237 #[cfg(feature = "unstable_nes")]
5238 DidOpenDocumentNotification(DidOpenDocumentNotification),
5242 #[cfg(feature = "unstable_nes")]
5243 DidChangeDocumentNotification(DidChangeDocumentNotification),
5247 #[cfg(feature = "unstable_nes")]
5248 DidCloseDocumentNotification(DidCloseDocumentNotification),
5252 #[cfg(feature = "unstable_nes")]
5253 DidSaveDocumentNotification(DidSaveDocumentNotification),
5257 #[cfg(feature = "unstable_nes")]
5258 DidFocusDocumentNotification(DidFocusDocumentNotification),
5262 #[cfg(feature = "unstable_nes")]
5263 AcceptNesNotification(AcceptNesNotification),
5267 #[cfg(feature = "unstable_nes")]
5268 RejectNesNotification(RejectNesNotification),
5272 #[cfg(feature = "unstable_mcp_over_acp")]
5278 MessageMcpNotification(MessageMcpNotification),
5279 ExtNotification(ExtNotification),
5286}
5287
5288impl ClientNotification {
5289 #[must_use]
5291 pub fn method(&self) -> &str {
5292 match self {
5293 Self::CancelNotification(_) => AGENT_METHOD_NAMES.session_cancel,
5294 #[cfg(feature = "unstable_nes")]
5295 Self::DidOpenDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_open,
5296 #[cfg(feature = "unstable_nes")]
5297 Self::DidChangeDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_change,
5298 #[cfg(feature = "unstable_nes")]
5299 Self::DidCloseDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_close,
5300 #[cfg(feature = "unstable_nes")]
5301 Self::DidSaveDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_save,
5302 #[cfg(feature = "unstable_nes")]
5303 Self::DidFocusDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_focus,
5304 #[cfg(feature = "unstable_nes")]
5305 Self::AcceptNesNotification(_) => AGENT_METHOD_NAMES.nes_accept,
5306 #[cfg(feature = "unstable_nes")]
5307 Self::RejectNesNotification(_) => AGENT_METHOD_NAMES.nes_reject,
5308 #[cfg(feature = "unstable_mcp_over_acp")]
5309 Self::MessageMcpNotification(_) => AGENT_METHOD_NAMES.mcp_message,
5310 Self::ExtNotification(ext_notification) => &ext_notification.method,
5311 }
5312 }
5313}
5314
5315#[skip_serializing_none]
5319#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
5320#[schemars(extend("x-side" = "agent", "x-method" = SESSION_CANCEL_METHOD_NAME))]
5321#[serde(rename_all = "camelCase")]
5322#[non_exhaustive]
5323pub struct CancelNotification {
5324 pub session_id: SessionId,
5326 #[serde(rename = "_meta")]
5332 pub meta: Option<Meta>,
5333}
5334
5335impl CancelNotification {
5336 #[must_use]
5337 pub fn new(session_id: impl Into<SessionId>) -> Self {
5338 Self {
5339 session_id: session_id.into(),
5340 meta: None,
5341 }
5342 }
5343
5344 #[must_use]
5350 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5351 self.meta = meta.into_option();
5352 self
5353 }
5354}
5355
5356#[cfg(test)]
5357mod test_serialization {
5358 use super::*;
5359 use serde_json::json;
5360
5361 #[test]
5362 fn test_mcp_server_stdio_serialization() {
5363 let server = McpServer::Stdio(
5364 McpServerStdio::new("test-server", "/usr/bin/server")
5365 .args(vec!["--port".to_string(), "3000".to_string()])
5366 .env(vec![EnvVariable::new("API_KEY", "secret123")]),
5367 );
5368
5369 let json = serde_json::to_value(&server).unwrap();
5370 assert_eq!(
5371 json,
5372 json!({
5373 "name": "test-server",
5374 "command": "/usr/bin/server",
5375 "args": ["--port", "3000"],
5376 "env": [
5377 {
5378 "name": "API_KEY",
5379 "value": "secret123"
5380 }
5381 ]
5382 })
5383 );
5384
5385 let deserialized: McpServer = serde_json::from_value(json).unwrap();
5386 match deserialized {
5387 McpServer::Stdio(McpServerStdio {
5388 name,
5389 command,
5390 args,
5391 env,
5392 meta: _,
5393 }) => {
5394 assert_eq!(name, "test-server");
5395 assert_eq!(command, PathBuf::from("/usr/bin/server"));
5396 assert_eq!(args, vec!["--port", "3000"]);
5397 assert_eq!(env.len(), 1);
5398 assert_eq!(env[0].name, "API_KEY");
5399 assert_eq!(env[0].value, "secret123");
5400 }
5401 _ => panic!("Expected Stdio variant"),
5402 }
5403 }
5404
5405 #[test]
5406 fn test_mcp_server_http_serialization() {
5407 let server = McpServer::Http(
5408 McpServerHttp::new("http-server", "https://api.example.com").headers(vec![
5409 HttpHeader::new("Authorization", "Bearer token123"),
5410 HttpHeader::new("Content-Type", "application/json"),
5411 ]),
5412 );
5413
5414 let json = serde_json::to_value(&server).unwrap();
5415 assert_eq!(
5416 json,
5417 json!({
5418 "type": "http",
5419 "name": "http-server",
5420 "url": "https://api.example.com",
5421 "headers": [
5422 {
5423 "name": "Authorization",
5424 "value": "Bearer token123"
5425 },
5426 {
5427 "name": "Content-Type",
5428 "value": "application/json"
5429 }
5430 ]
5431 })
5432 );
5433
5434 let deserialized: McpServer = serde_json::from_value(json).unwrap();
5435 match deserialized {
5436 McpServer::Http(McpServerHttp {
5437 name,
5438 url,
5439 headers,
5440 meta: _,
5441 }) => {
5442 assert_eq!(name, "http-server");
5443 assert_eq!(url, "https://api.example.com");
5444 assert_eq!(headers.len(), 2);
5445 assert_eq!(headers[0].name, "Authorization");
5446 assert_eq!(headers[0].value, "Bearer token123");
5447 assert_eq!(headers[1].name, "Content-Type");
5448 assert_eq!(headers[1].value, "application/json");
5449 }
5450 _ => panic!("Expected Http variant"),
5451 }
5452 }
5453
5454 #[cfg(feature = "unstable_mcp_over_acp")]
5455 #[test]
5456 fn test_mcp_server_acp_serialization() {
5457 let server = McpServer::Acp(McpServerAcp::new("project-tools", "project-tools-id"));
5458
5459 let json = serde_json::to_value(&server).unwrap();
5460 assert_eq!(
5461 json,
5462 json!({
5463 "type": "acp",
5464 "name": "project-tools",
5465 "id": "project-tools-id"
5466 })
5467 );
5468
5469 let deserialized: McpServer = serde_json::from_value(json).unwrap();
5470 match deserialized {
5471 McpServer::Acp(McpServerAcp { name, id, meta: _ }) => {
5472 assert_eq!(name, "project-tools");
5473 assert_eq!(id, McpServerAcpId::new("project-tools-id"));
5474 }
5475 _ => panic!("Expected Acp variant"),
5476 }
5477 }
5478
5479 #[cfg(feature = "unstable_mcp_over_acp")]
5480 #[test]
5481 fn test_client_mcp_message_method_names() {
5482 assert_eq!(AGENT_METHOD_NAMES.mcp_message, "mcp/message");
5483
5484 assert_eq!(
5485 ClientRequest::MessageMcpRequest(MessageMcpRequest::new("conn-1", "tools/list"))
5486 .method(),
5487 "mcp/message"
5488 );
5489 assert_eq!(
5490 ClientNotification::MessageMcpNotification(MessageMcpNotification::new(
5491 "conn-1",
5492 "notifications/progress"
5493 ))
5494 .method(),
5495 "mcp/message"
5496 );
5497 }
5498
5499 #[cfg(feature = "unstable_mcp_over_acp")]
5500 #[test]
5501 fn test_mcp_server_acp_schema() {
5502 let mcp_server_schema = serde_json::to_value(schemars::schema_for!(McpServer)).unwrap();
5503 assert!(json_contains_entry(
5504 &mcp_server_schema,
5505 "const",
5506 &json!("acp")
5507 ));
5508 assert!(json_contains_entry(
5509 &mcp_server_schema,
5510 "$ref",
5511 &json!("#/$defs/McpServerAcp")
5512 ));
5513
5514 let capabilities_schema =
5515 serde_json::to_value(schemars::schema_for!(McpCapabilities)).unwrap();
5516 assert!(json_contains_key(&capabilities_schema, "acp"));
5517 }
5518
5519 #[cfg(feature = "unstable_mcp_over_acp")]
5520 fn json_contains_entry(
5521 value: &serde_json::Value,
5522 key: &str,
5523 expected: &serde_json::Value,
5524 ) -> bool {
5525 match value {
5526 serde_json::Value::Object(map) => {
5527 map.get(key) == Some(expected)
5528 || map
5529 .values()
5530 .any(|value| json_contains_entry(value, key, expected))
5531 }
5532 serde_json::Value::Array(values) => values
5533 .iter()
5534 .any(|value| json_contains_entry(value, key, expected)),
5535 _ => false,
5536 }
5537 }
5538
5539 #[cfg(feature = "unstable_mcp_over_acp")]
5540 fn json_contains_key(value: &serde_json::Value, key: &str) -> bool {
5541 match value {
5542 serde_json::Value::Object(map) => {
5543 map.contains_key(key) || map.values().any(|value| json_contains_key(value, key))
5544 }
5545 serde_json::Value::Array(values) => {
5546 values.iter().any(|value| json_contains_key(value, key))
5547 }
5548 _ => false,
5549 }
5550 }
5551
5552 #[test]
5553 fn test_mcp_server_sse_serialization() {
5554 let server = McpServer::Sse(
5555 McpServerSse::new("sse-server", "https://sse.example.com/events")
5556 .headers(vec![HttpHeader::new("X-API-Key", "apikey456")]),
5557 );
5558
5559 let json = serde_json::to_value(&server).unwrap();
5560 assert_eq!(
5561 json,
5562 json!({
5563 "type": "sse",
5564 "name": "sse-server",
5565 "url": "https://sse.example.com/events",
5566 "headers": [
5567 {
5568 "name": "X-API-Key",
5569 "value": "apikey456"
5570 }
5571 ]
5572 })
5573 );
5574
5575 let deserialized: McpServer = serde_json::from_value(json).unwrap();
5576 match deserialized {
5577 McpServer::Sse(McpServerSse {
5578 name,
5579 url,
5580 headers,
5581 meta: _,
5582 }) => {
5583 assert_eq!(name, "sse-server");
5584 assert_eq!(url, "https://sse.example.com/events");
5585 assert_eq!(headers.len(), 1);
5586 assert_eq!(headers[0].name, "X-API-Key");
5587 assert_eq!(headers[0].value, "apikey456");
5588 }
5589 _ => panic!("Expected Sse variant"),
5590 }
5591 }
5592
5593 #[test]
5594 fn test_session_config_option_category_known_variants() {
5595 assert_eq!(
5597 serde_json::to_value(&SessionConfigOptionCategory::Mode).unwrap(),
5598 json!("mode")
5599 );
5600 assert_eq!(
5601 serde_json::to_value(&SessionConfigOptionCategory::Model).unwrap(),
5602 json!("model")
5603 );
5604 assert_eq!(
5605 serde_json::to_value(&SessionConfigOptionCategory::ThoughtLevel).unwrap(),
5606 json!("thought_level")
5607 );
5608
5609 assert_eq!(
5611 serde_json::from_str::<SessionConfigOptionCategory>("\"mode\"").unwrap(),
5612 SessionConfigOptionCategory::Mode
5613 );
5614 assert_eq!(
5615 serde_json::from_str::<SessionConfigOptionCategory>("\"model\"").unwrap(),
5616 SessionConfigOptionCategory::Model
5617 );
5618 assert_eq!(
5619 serde_json::from_str::<SessionConfigOptionCategory>("\"thought_level\"").unwrap(),
5620 SessionConfigOptionCategory::ThoughtLevel
5621 );
5622 }
5623
5624 #[test]
5625 fn test_session_config_option_category_unknown_variants() {
5626 let unknown: SessionConfigOptionCategory =
5628 serde_json::from_str("\"some_future_category\"").unwrap();
5629 assert_eq!(
5630 unknown,
5631 SessionConfigOptionCategory::Other("some_future_category".to_string())
5632 );
5633
5634 let json = serde_json::to_value(&unknown).unwrap();
5636 assert_eq!(json, json!("some_future_category"));
5637 }
5638
5639 #[test]
5640 fn test_session_config_option_category_custom_categories() {
5641 let custom: SessionConfigOptionCategory =
5643 serde_json::from_str("\"_my_custom_category\"").unwrap();
5644 assert_eq!(
5645 custom,
5646 SessionConfigOptionCategory::Other("_my_custom_category".to_string())
5647 );
5648
5649 let json = serde_json::to_value(&custom).unwrap();
5651 assert_eq!(json, json!("_my_custom_category"));
5652
5653 let deserialized: SessionConfigOptionCategory = serde_json::from_value(json).unwrap();
5655 assert_eq!(
5656 deserialized,
5657 SessionConfigOptionCategory::Other("_my_custom_category".to_string()),
5658 );
5659 }
5660
5661 #[test]
5662 fn test_auth_method_agent_serialization() {
5663 let method = AuthMethod::Agent(AuthMethodAgent::new("default-auth", "Default Auth"));
5664
5665 let json = serde_json::to_value(&method).unwrap();
5666 assert_eq!(
5667 json,
5668 json!({
5669 "id": "default-auth",
5670 "name": "Default Auth"
5671 })
5672 );
5673 assert!(!json.as_object().unwrap().contains_key("description"));
5675 assert!(!json.as_object().unwrap().contains_key("type"));
5677
5678 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5679 match deserialized {
5680 AuthMethod::Agent(AuthMethodAgent { id, name, .. }) => {
5681 assert_eq!(id.0.as_ref(), "default-auth");
5682 assert_eq!(name, "Default Auth");
5683 }
5684 #[cfg(feature = "unstable_auth_methods")]
5685 _ => panic!("Expected Agent variant"),
5686 }
5687 }
5688
5689 #[test]
5690 fn test_auth_method_explicit_agent_deserialization() {
5691 let json = json!({
5693 "id": "agent-auth",
5694 "name": "Agent Auth",
5695 "type": "agent"
5696 });
5697
5698 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5699 assert!(matches!(deserialized, AuthMethod::Agent(_)));
5700 }
5701
5702 #[cfg(feature = "unstable_session_delete")]
5703 #[test]
5704 fn test_session_delete_serialization() {
5705 assert_eq!(AGENT_METHOD_NAMES.session_delete, "session/delete");
5706 assert_eq!(
5707 ClientRequest::DeleteSessionRequest(DeleteSessionRequest::new("sess_abc123")).method(),
5708 "session/delete"
5709 );
5710 assert_eq!(
5711 serde_json::to_value(DeleteSessionRequest::new("sess_abc123")).unwrap(),
5712 json!({
5713 "sessionId": "sess_abc123"
5714 })
5715 );
5716 assert_eq!(
5717 serde_json::to_value(DeleteSessionResponse::new()).unwrap(),
5718 json!({})
5719 );
5720 assert_eq!(
5721 serde_json::to_value(
5722 SessionCapabilities::new().delete(SessionDeleteCapabilities::new())
5723 )
5724 .unwrap(),
5725 json!({
5726 "delete": {}
5727 })
5728 );
5729 }
5730
5731 #[cfg(feature = "unstable_session_additional_directories")]
5732 #[test]
5733 fn test_session_additional_directories_serialization() {
5734 assert_eq!(
5735 serde_json::to_value(NewSessionRequest::new("/home/user/project")).unwrap(),
5736 json!({
5737 "cwd": "/home/user/project",
5738 "mcpServers": []
5739 })
5740 );
5741 assert_eq!(
5742 serde_json::to_value(
5743 NewSessionRequest::new("/home/user/project").additional_directories(vec![
5744 PathBuf::from("/home/user/shared-lib"),
5745 PathBuf::from("/home/user/product-docs"),
5746 ])
5747 )
5748 .unwrap(),
5749 json!({
5750 "cwd": "/home/user/project",
5751 "additionalDirectories": [
5752 "/home/user/shared-lib",
5753 "/home/user/product-docs"
5754 ],
5755 "mcpServers": []
5756 })
5757 );
5758 assert_eq!(
5759 serde_json::to_value(
5760 ListSessionsRequest::new().additional_directories(Vec::<PathBuf>::new())
5761 )
5762 .unwrap(),
5763 json!({})
5764 );
5765 assert_eq!(
5766 serde_json::to_value(SessionInfo::new("sess_abc123", "/home/user/project")).unwrap(),
5767 json!({
5768 "sessionId": "sess_abc123",
5769 "cwd": "/home/user/project"
5770 })
5771 );
5772 assert_eq!(
5773 serde_json::to_value(
5774 SessionInfo::new("sess_abc123", "/home/user/project").additional_directories(vec![
5775 PathBuf::from("/home/user/shared-lib"),
5776 PathBuf::from("/home/user/product-docs"),
5777 ])
5778 )
5779 .unwrap(),
5780 json!({
5781 "sessionId": "sess_abc123",
5782 "cwd": "/home/user/project",
5783 "additionalDirectories": [
5784 "/home/user/shared-lib",
5785 "/home/user/product-docs"
5786 ]
5787 })
5788 );
5789 assert_eq!(
5790 serde_json::from_value::<SessionInfo>(json!({
5791 "sessionId": "sess_abc123",
5792 "cwd": "/home/user/project"
5793 }))
5794 .unwrap()
5795 .additional_directories,
5796 Vec::<PathBuf>::new()
5797 );
5798
5799 assert_eq!(
5800 serde_json::from_value::<ListSessionsRequest>(json!({}))
5801 .unwrap()
5802 .additional_directories,
5803 Vec::<PathBuf>::new()
5804 );
5805
5806 assert_eq!(
5807 serde_json::from_value::<ListSessionsRequest>(json!({
5808 "additionalDirectories": []
5809 }))
5810 .unwrap()
5811 .additional_directories,
5812 Vec::<PathBuf>::new()
5813 );
5814 }
5815
5816 #[cfg(feature = "unstable_session_additional_directories")]
5817 #[test]
5818 fn test_session_additional_directories_capabilities_serialization() {
5819 assert_eq!(
5820 serde_json::to_value(
5821 SessionCapabilities::new()
5822 .additional_directories(SessionAdditionalDirectoriesCapabilities::new())
5823 )
5824 .unwrap(),
5825 json!({
5826 "additionalDirectories": {}
5827 })
5828 );
5829 }
5830
5831 #[cfg(feature = "unstable_auth_methods")]
5832 #[test]
5833 fn test_auth_method_env_var_serialization() {
5834 let method = AuthMethod::EnvVar(AuthMethodEnvVar::new(
5835 "api-key",
5836 "API Key",
5837 vec![AuthEnvVar::new("API_KEY")],
5838 ));
5839
5840 let json = serde_json::to_value(&method).unwrap();
5841 assert_eq!(
5842 json,
5843 json!({
5844 "id": "api-key",
5845 "name": "API Key",
5846 "type": "env_var",
5847 "vars": [{"name": "API_KEY"}]
5848 })
5849 );
5850 assert!(!json["vars"][0].as_object().unwrap().contains_key("secret"));
5852 assert!(
5853 !json["vars"][0]
5854 .as_object()
5855 .unwrap()
5856 .contains_key("optional")
5857 );
5858
5859 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5860 match deserialized {
5861 AuthMethod::EnvVar(AuthMethodEnvVar {
5862 id,
5863 name: method_name,
5864 vars,
5865 link,
5866 ..
5867 }) => {
5868 assert_eq!(id.0.as_ref(), "api-key");
5869 assert_eq!(method_name, "API Key");
5870 assert_eq!(vars.len(), 1);
5871 assert_eq!(vars[0].name, "API_KEY");
5872 assert!(vars[0].secret);
5873 assert!(!vars[0].optional);
5874 assert!(link.is_none());
5875 }
5876 _ => panic!("Expected EnvVar variant"),
5877 }
5878 }
5879
5880 #[cfg(feature = "unstable_auth_methods")]
5881 #[test]
5882 fn test_auth_method_env_var_with_link_serialization() {
5883 let method = AuthMethod::EnvVar(
5884 AuthMethodEnvVar::new("api-key", "API Key", vec![AuthEnvVar::new("API_KEY")])
5885 .link("https://example.com/keys"),
5886 );
5887
5888 let json = serde_json::to_value(&method).unwrap();
5889 assert_eq!(
5890 json,
5891 json!({
5892 "id": "api-key",
5893 "name": "API Key",
5894 "type": "env_var",
5895 "vars": [{"name": "API_KEY"}],
5896 "link": "https://example.com/keys"
5897 })
5898 );
5899
5900 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5901 match deserialized {
5902 AuthMethod::EnvVar(AuthMethodEnvVar { link, .. }) => {
5903 assert_eq!(link.as_deref(), Some("https://example.com/keys"));
5904 }
5905 _ => panic!("Expected EnvVar variant"),
5906 }
5907 }
5908
5909 #[cfg(feature = "unstable_auth_methods")]
5910 #[test]
5911 fn test_auth_method_env_var_multiple_vars() {
5912 let method = AuthMethod::EnvVar(AuthMethodEnvVar::new(
5913 "azure-openai",
5914 "Azure OpenAI",
5915 vec![
5916 AuthEnvVar::new("AZURE_OPENAI_API_KEY").label("API Key"),
5917 AuthEnvVar::new("AZURE_OPENAI_ENDPOINT")
5918 .label("Endpoint URL")
5919 .secret(false),
5920 AuthEnvVar::new("AZURE_OPENAI_API_VERSION")
5921 .label("API Version")
5922 .secret(false)
5923 .optional(true),
5924 ],
5925 ));
5926
5927 let json = serde_json::to_value(&method).unwrap();
5928 assert_eq!(
5929 json,
5930 json!({
5931 "id": "azure-openai",
5932 "name": "Azure OpenAI",
5933 "type": "env_var",
5934 "vars": [
5935 {"name": "AZURE_OPENAI_API_KEY", "label": "API Key"},
5936 {"name": "AZURE_OPENAI_ENDPOINT", "label": "Endpoint URL", "secret": false},
5937 {"name": "AZURE_OPENAI_API_VERSION", "label": "API Version", "secret": false, "optional": true}
5938 ]
5939 })
5940 );
5941
5942 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5943 match deserialized {
5944 AuthMethod::EnvVar(AuthMethodEnvVar { vars, .. }) => {
5945 assert_eq!(vars.len(), 3);
5946 assert_eq!(vars[0].name, "AZURE_OPENAI_API_KEY");
5948 assert_eq!(vars[0].label.as_deref(), Some("API Key"));
5949 assert!(vars[0].secret);
5950 assert!(!vars[0].optional);
5951 assert_eq!(vars[1].name, "AZURE_OPENAI_ENDPOINT");
5953 assert!(!vars[1].secret);
5954 assert!(!vars[1].optional);
5955 assert_eq!(vars[2].name, "AZURE_OPENAI_API_VERSION");
5957 assert!(!vars[2].secret);
5958 assert!(vars[2].optional);
5959 }
5960 _ => panic!("Expected EnvVar variant"),
5961 }
5962 }
5963
5964 #[cfg(feature = "unstable_auth_methods")]
5965 #[test]
5966 fn test_auth_method_terminal_serialization() {
5967 let method = AuthMethod::Terminal(AuthMethodTerminal::new("tui-auth", "Terminal Auth"));
5968
5969 let json = serde_json::to_value(&method).unwrap();
5970 assert_eq!(
5971 json,
5972 json!({
5973 "id": "tui-auth",
5974 "name": "Terminal Auth",
5975 "type": "terminal"
5976 })
5977 );
5978 assert!(!json.as_object().unwrap().contains_key("args"));
5980 assert!(!json.as_object().unwrap().contains_key("env"));
5981
5982 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5983 match deserialized {
5984 AuthMethod::Terminal(AuthMethodTerminal { args, env, .. }) => {
5985 assert!(args.is_empty());
5986 assert!(env.is_empty());
5987 }
5988 _ => panic!("Expected Terminal variant"),
5989 }
5990 }
5991
5992 #[cfg(feature = "unstable_auth_methods")]
5993 #[test]
5994 fn test_auth_method_terminal_with_args_and_env_serialization() {
5995 use std::collections::HashMap;
5996
5997 let mut env = HashMap::new();
5998 env.insert("TERM".to_string(), "xterm-256color".to_string());
5999
6000 let method = AuthMethod::Terminal(
6001 AuthMethodTerminal::new("tui-auth", "Terminal Auth")
6002 .args(vec!["--interactive".to_string(), "--color".to_string()])
6003 .env(env),
6004 );
6005
6006 let json = serde_json::to_value(&method).unwrap();
6007 assert_eq!(
6008 json,
6009 json!({
6010 "id": "tui-auth",
6011 "name": "Terminal Auth",
6012 "type": "terminal",
6013 "args": ["--interactive", "--color"],
6014 "env": {
6015 "TERM": "xterm-256color"
6016 }
6017 })
6018 );
6019
6020 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
6021 match deserialized {
6022 AuthMethod::Terminal(AuthMethodTerminal { args, env, .. }) => {
6023 assert_eq!(args, vec!["--interactive", "--color"]);
6024 assert_eq!(env.len(), 1);
6025 assert_eq!(env.get("TERM").unwrap(), "xterm-256color");
6026 }
6027 _ => panic!("Expected Terminal variant"),
6028 }
6029 }
6030
6031 #[cfg(feature = "unstable_boolean_config")]
6032 #[test]
6033 fn test_session_config_option_value_id_serialize() {
6034 let val = SessionConfigOptionValue::value_id("model-1");
6035 let json = serde_json::to_value(&val).unwrap();
6036 assert_eq!(json, json!({ "value": "model-1" }));
6038 assert!(!json.as_object().unwrap().contains_key("type"));
6039 }
6040
6041 #[cfg(feature = "unstable_boolean_config")]
6042 #[test]
6043 fn test_session_config_option_value_boolean_serialize() {
6044 let val = SessionConfigOptionValue::boolean(true);
6045 let json = serde_json::to_value(&val).unwrap();
6046 assert_eq!(json, json!({ "type": "boolean", "value": true }));
6047 }
6048
6049 #[cfg(feature = "unstable_boolean_config")]
6050 #[test]
6051 fn test_session_config_option_value_deserialize_no_type() {
6052 let json = json!({ "value": "model-1" });
6054 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
6055 assert_eq!(val, SessionConfigOptionValue::value_id("model-1"));
6056 assert_eq!(val.as_value_id().unwrap().to_string(), "model-1");
6057 }
6058
6059 #[cfg(feature = "unstable_boolean_config")]
6060 #[test]
6061 fn test_session_config_option_value_deserialize_boolean() {
6062 let json = json!({ "type": "boolean", "value": true });
6063 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
6064 assert_eq!(val, SessionConfigOptionValue::boolean(true));
6065 assert_eq!(val.as_bool(), Some(true));
6066 }
6067
6068 #[cfg(feature = "unstable_boolean_config")]
6069 #[test]
6070 fn test_session_config_option_value_deserialize_boolean_false() {
6071 let json = json!({ "type": "boolean", "value": false });
6072 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
6073 assert_eq!(val, SessionConfigOptionValue::boolean(false));
6074 assert_eq!(val.as_bool(), Some(false));
6075 }
6076
6077 #[cfg(feature = "unstable_boolean_config")]
6078 #[test]
6079 fn test_session_config_option_value_deserialize_unknown_type_with_string_value() {
6080 let json = json!({ "type": "text", "value": "freeform input" });
6082 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
6083 assert_eq!(val.as_value_id().unwrap().to_string(), "freeform input");
6084 }
6085
6086 #[cfg(feature = "unstable_boolean_config")]
6087 #[test]
6088 fn test_session_config_option_value_roundtrip_value_id() {
6089 let original = SessionConfigOptionValue::value_id("option-a");
6090 let json = serde_json::to_value(&original).unwrap();
6091 let roundtripped: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
6092 assert_eq!(original, roundtripped);
6093 }
6094
6095 #[cfg(feature = "unstable_boolean_config")]
6096 #[test]
6097 fn test_session_config_option_value_roundtrip_boolean() {
6098 let original = SessionConfigOptionValue::boolean(false);
6099 let json = serde_json::to_value(&original).unwrap();
6100 let roundtripped: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
6101 assert_eq!(original, roundtripped);
6102 }
6103
6104 #[cfg(feature = "unstable_boolean_config")]
6105 #[test]
6106 fn test_session_config_option_value_type_mismatch_boolean_with_string() {
6107 let json = json!({ "type": "boolean", "value": "not a bool" });
6109 let result = serde_json::from_value::<SessionConfigOptionValue>(json);
6110 assert!(result.is_ok());
6112 assert_eq!(
6113 result.unwrap().as_value_id().unwrap().to_string(),
6114 "not a bool"
6115 );
6116 }
6117
6118 #[cfg(feature = "unstable_boolean_config")]
6119 #[test]
6120 fn test_session_config_option_value_from_impls() {
6121 let from_str: SessionConfigOptionValue = "model-1".into();
6122 assert_eq!(from_str.as_value_id().unwrap().to_string(), "model-1");
6123
6124 let from_id: SessionConfigOptionValue = SessionConfigValueId::new("model-2").into();
6125 assert_eq!(from_id.as_value_id().unwrap().to_string(), "model-2");
6126
6127 let from_bool: SessionConfigOptionValue = true.into();
6128 assert_eq!(from_bool.as_bool(), Some(true));
6129 }
6130
6131 #[cfg(feature = "unstable_boolean_config")]
6132 #[test]
6133 fn test_set_session_config_option_request_value_id() {
6134 let req = SetSessionConfigOptionRequest::new("sess_1", "model", "model-1");
6135 let json = serde_json::to_value(&req).unwrap();
6136 assert_eq!(
6137 json,
6138 json!({
6139 "sessionId": "sess_1",
6140 "configId": "model",
6141 "value": "model-1"
6142 })
6143 );
6144 assert!(!json.as_object().unwrap().contains_key("type"));
6146 }
6147
6148 #[cfg(feature = "unstable_boolean_config")]
6149 #[test]
6150 fn test_set_session_config_option_request_boolean() {
6151 let req = SetSessionConfigOptionRequest::new("sess_1", "brave_mode", true);
6152 let json = serde_json::to_value(&req).unwrap();
6153 assert_eq!(
6154 json,
6155 json!({
6156 "sessionId": "sess_1",
6157 "configId": "brave_mode",
6158 "type": "boolean",
6159 "value": true
6160 })
6161 );
6162 }
6163
6164 #[cfg(feature = "unstable_boolean_config")]
6165 #[test]
6166 fn test_set_session_config_option_request_deserialize_no_type() {
6167 let json = json!({
6169 "sessionId": "sess_1",
6170 "configId": "model",
6171 "value": "model-1"
6172 });
6173 let req: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
6174 assert_eq!(req.session_id.to_string(), "sess_1");
6175 assert_eq!(req.config_id.to_string(), "model");
6176 assert_eq!(req.value.as_value_id().unwrap().to_string(), "model-1");
6177 }
6178
6179 #[cfg(feature = "unstable_boolean_config")]
6180 #[test]
6181 fn test_set_session_config_option_request_deserialize_boolean() {
6182 let json = json!({
6183 "sessionId": "sess_1",
6184 "configId": "brave_mode",
6185 "type": "boolean",
6186 "value": true
6187 });
6188 let req: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
6189 assert_eq!(req.value.as_bool(), Some(true));
6190 }
6191
6192 #[cfg(feature = "unstable_boolean_config")]
6193 #[test]
6194 fn test_set_session_config_option_request_roundtrip_value_id() {
6195 let original = SetSessionConfigOptionRequest::new("s", "c", "v");
6196 let json = serde_json::to_value(&original).unwrap();
6197 let roundtripped: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
6198 assert_eq!(original, roundtripped);
6199 }
6200
6201 #[cfg(feature = "unstable_boolean_config")]
6202 #[test]
6203 fn test_set_session_config_option_request_roundtrip_boolean() {
6204 let original = SetSessionConfigOptionRequest::new("s", "c", false);
6205 let json = serde_json::to_value(&original).unwrap();
6206 let roundtripped: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
6207 assert_eq!(original, roundtripped);
6208 }
6209
6210 #[cfg(feature = "unstable_boolean_config")]
6211 #[test]
6212 fn test_session_config_boolean_serialization() {
6213 let cfg = SessionConfigBoolean::new(true);
6214 let json = serde_json::to_value(&cfg).unwrap();
6215 assert_eq!(json, json!({ "currentValue": true }));
6216
6217 let deserialized: SessionConfigBoolean = serde_json::from_value(json).unwrap();
6218 assert!(deserialized.current_value);
6219 }
6220
6221 #[cfg(feature = "unstable_boolean_config")]
6222 #[test]
6223 fn test_session_config_option_boolean_variant() {
6224 let opt = SessionConfigOption::boolean("brave_mode", "Brave Mode", false)
6225 .description("Skip confirmation prompts");
6226 let json = serde_json::to_value(&opt).unwrap();
6227 assert_eq!(
6228 json,
6229 json!({
6230 "id": "brave_mode",
6231 "name": "Brave Mode",
6232 "description": "Skip confirmation prompts",
6233 "type": "boolean",
6234 "currentValue": false
6235 })
6236 );
6237
6238 let deserialized: SessionConfigOption = serde_json::from_value(json).unwrap();
6239 assert_eq!(deserialized.id.to_string(), "brave_mode");
6240 assert_eq!(deserialized.name, "Brave Mode");
6241 match deserialized.kind {
6242 SessionConfigKind::Boolean(ref b) => assert!(!b.current_value),
6243 _ => panic!("Expected Boolean kind"),
6244 }
6245 }
6246
6247 #[cfg(feature = "unstable_boolean_config")]
6248 #[test]
6249 fn test_session_config_option_select_still_works() {
6250 let opt = SessionConfigOption::select(
6252 "model",
6253 "Model",
6254 "model-1",
6255 vec![
6256 SessionConfigSelectOption::new("model-1", "Model 1"),
6257 SessionConfigSelectOption::new("model-2", "Model 2"),
6258 ],
6259 );
6260 let json = serde_json::to_value(&opt).unwrap();
6261 assert_eq!(json["type"], "select");
6262 assert_eq!(json["currentValue"], "model-1");
6263 assert_eq!(json["options"].as_array().unwrap().len(), 2);
6264
6265 let deserialized: SessionConfigOption = serde_json::from_value(json).unwrap();
6266 match deserialized.kind {
6267 SessionConfigKind::Select(ref s) => {
6268 assert_eq!(s.current_value.to_string(), "model-1");
6269 }
6270 _ => panic!("Expected Select kind"),
6271 }
6272 }
6273
6274 #[cfg(feature = "unstable_llm_providers")]
6275 #[test]
6276 fn test_llm_protocol_known_variants() {
6277 assert_eq!(
6278 serde_json::to_value(&LlmProtocol::Anthropic).unwrap(),
6279 json!("anthropic")
6280 );
6281 assert_eq!(
6282 serde_json::to_value(&LlmProtocol::OpenAi).unwrap(),
6283 json!("openai")
6284 );
6285 assert_eq!(
6286 serde_json::to_value(&LlmProtocol::Azure).unwrap(),
6287 json!("azure")
6288 );
6289 assert_eq!(
6290 serde_json::to_value(&LlmProtocol::Vertex).unwrap(),
6291 json!("vertex")
6292 );
6293 assert_eq!(
6294 serde_json::to_value(&LlmProtocol::Bedrock).unwrap(),
6295 json!("bedrock")
6296 );
6297
6298 assert_eq!(
6299 serde_json::from_str::<LlmProtocol>("\"anthropic\"").unwrap(),
6300 LlmProtocol::Anthropic
6301 );
6302 assert_eq!(
6303 serde_json::from_str::<LlmProtocol>("\"openai\"").unwrap(),
6304 LlmProtocol::OpenAi
6305 );
6306 assert_eq!(
6307 serde_json::from_str::<LlmProtocol>("\"azure\"").unwrap(),
6308 LlmProtocol::Azure
6309 );
6310 assert_eq!(
6311 serde_json::from_str::<LlmProtocol>("\"vertex\"").unwrap(),
6312 LlmProtocol::Vertex
6313 );
6314 assert_eq!(
6315 serde_json::from_str::<LlmProtocol>("\"bedrock\"").unwrap(),
6316 LlmProtocol::Bedrock
6317 );
6318 }
6319
6320 #[cfg(feature = "unstable_llm_providers")]
6321 #[test]
6322 fn test_llm_protocol_unknown_variant() {
6323 let unknown: LlmProtocol = serde_json::from_str("\"cohere\"").unwrap();
6324 assert_eq!(unknown, LlmProtocol::Other("cohere".to_string()));
6325
6326 let json = serde_json::to_value(&unknown).unwrap();
6327 assert_eq!(json, json!("cohere"));
6328 }
6329
6330 #[cfg(feature = "unstable_llm_providers")]
6331 #[test]
6332 fn test_provider_current_config_serialization() {
6333 let config =
6334 ProviderCurrentConfig::new(LlmProtocol::Anthropic, "https://api.anthropic.com");
6335
6336 let json = serde_json::to_value(&config).unwrap();
6337 assert_eq!(
6338 json,
6339 json!({
6340 "apiType": "anthropic",
6341 "baseUrl": "https://api.anthropic.com"
6342 })
6343 );
6344
6345 let deserialized: ProviderCurrentConfig = serde_json::from_value(json).unwrap();
6346 assert_eq!(deserialized.api_type, LlmProtocol::Anthropic);
6347 assert_eq!(deserialized.base_url, "https://api.anthropic.com");
6348 }
6349
6350 #[cfg(feature = "unstable_llm_providers")]
6351 #[test]
6352 fn test_provider_info_with_current_config() {
6353 let info = ProviderInfo::new(
6354 "main",
6355 vec![LlmProtocol::Anthropic, LlmProtocol::OpenAi],
6356 true,
6357 Some(ProviderCurrentConfig::new(
6358 LlmProtocol::Anthropic,
6359 "https://api.anthropic.com",
6360 )),
6361 );
6362
6363 let json = serde_json::to_value(&info).unwrap();
6364 assert_eq!(
6365 json,
6366 json!({
6367 "id": "main",
6368 "supported": ["anthropic", "openai"],
6369 "required": true,
6370 "current": {
6371 "apiType": "anthropic",
6372 "baseUrl": "https://api.anthropic.com"
6373 }
6374 })
6375 );
6376
6377 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6378 assert_eq!(deserialized.id, "main");
6379 assert_eq!(deserialized.supported.len(), 2);
6380 assert!(deserialized.required);
6381 assert!(deserialized.current.is_some());
6382 assert_eq!(
6383 deserialized.current.as_ref().unwrap().api_type,
6384 LlmProtocol::Anthropic
6385 );
6386 }
6387
6388 #[cfg(feature = "unstable_llm_providers")]
6389 #[test]
6390 fn test_provider_info_disabled() {
6391 let info = ProviderInfo::new(
6392 "secondary",
6393 vec![LlmProtocol::OpenAi],
6394 false,
6395 None::<ProviderCurrentConfig>,
6396 );
6397
6398 let json = serde_json::to_value(&info).unwrap();
6399 assert_eq!(
6400 json,
6401 json!({
6402 "id": "secondary",
6403 "supported": ["openai"],
6404 "required": false
6405 })
6406 );
6407
6408 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6409 assert_eq!(deserialized.id, "secondary");
6410 assert!(!deserialized.required);
6411 assert!(deserialized.current.is_none());
6412 }
6413
6414 #[cfg(feature = "unstable_llm_providers")]
6415 #[test]
6416 fn test_provider_info_missing_current_defaults_to_none() {
6417 let json = json!({
6419 "id": "main",
6420 "supported": ["anthropic"],
6421 "required": true
6422 });
6423 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6424 assert!(deserialized.current.is_none());
6425 }
6426
6427 #[cfg(feature = "unstable_llm_providers")]
6428 #[test]
6429 fn test_provider_info_explicit_null_current_decodes_to_none() {
6430 let json = json!({
6434 "id": "main",
6435 "supported": ["anthropic"],
6436 "required": true,
6437 "current": null
6438 });
6439 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6440 assert!(deserialized.current.is_none());
6441 }
6442
6443 #[cfg(feature = "unstable_llm_providers")]
6444 #[test]
6445 fn test_list_providers_response_serialization() {
6446 let response = ListProvidersResponse::new(vec![ProviderInfo::new(
6447 "main",
6448 vec![LlmProtocol::Anthropic],
6449 true,
6450 Some(ProviderCurrentConfig::new(
6451 LlmProtocol::Anthropic,
6452 "https://api.anthropic.com",
6453 )),
6454 )]);
6455
6456 let json = serde_json::to_value(&response).unwrap();
6457 assert_eq!(json["providers"].as_array().unwrap().len(), 1);
6458 assert_eq!(json["providers"][0]["id"], "main");
6459
6460 let deserialized: ListProvidersResponse = serde_json::from_value(json).unwrap();
6461 assert_eq!(deserialized.providers.len(), 1);
6462 }
6463
6464 #[cfg(feature = "unstable_llm_providers")]
6465 #[test]
6466 fn test_set_providers_request_serialization() {
6467 use std::collections::HashMap;
6468
6469 let mut headers = HashMap::new();
6470 headers.insert("Authorization".to_string(), "Bearer sk-test".to_string());
6471
6472 let request =
6473 SetProvidersRequest::new("main", LlmProtocol::OpenAi, "https://api.openai.com/v1")
6474 .headers(headers);
6475
6476 let json = serde_json::to_value(&request).unwrap();
6477 assert_eq!(
6478 json,
6479 json!({
6480 "id": "main",
6481 "apiType": "openai",
6482 "baseUrl": "https://api.openai.com/v1",
6483 "headers": {
6484 "Authorization": "Bearer sk-test"
6485 }
6486 })
6487 );
6488
6489 let deserialized: SetProvidersRequest = serde_json::from_value(json).unwrap();
6490 assert_eq!(deserialized.id, "main");
6491 assert_eq!(deserialized.api_type, LlmProtocol::OpenAi);
6492 assert_eq!(deserialized.base_url, "https://api.openai.com/v1");
6493 assert_eq!(deserialized.headers.len(), 1);
6494 assert_eq!(
6495 deserialized.headers.get("Authorization").unwrap(),
6496 "Bearer sk-test"
6497 );
6498 }
6499
6500 #[cfg(feature = "unstable_llm_providers")]
6501 #[test]
6502 fn test_set_providers_request_omits_empty_headers() {
6503 let request =
6504 SetProvidersRequest::new("main", LlmProtocol::Anthropic, "https://api.anthropic.com");
6505
6506 let json = serde_json::to_value(&request).unwrap();
6507 assert!(!json.as_object().unwrap().contains_key("headers"));
6509 }
6510
6511 #[cfg(feature = "unstable_llm_providers")]
6512 #[test]
6513 fn test_disable_providers_request_serialization() {
6514 let request = DisableProvidersRequest::new("secondary");
6515
6516 let json = serde_json::to_value(&request).unwrap();
6517 assert_eq!(json, json!({ "id": "secondary" }));
6518
6519 let deserialized: DisableProvidersRequest = serde_json::from_value(json).unwrap();
6520 assert_eq!(deserialized.id, "secondary");
6521 }
6522
6523 #[cfg(feature = "unstable_llm_providers")]
6524 #[test]
6525 fn test_providers_capabilities_serialization() {
6526 let caps = ProvidersCapabilities::new();
6527
6528 let json = serde_json::to_value(&caps).unwrap();
6529 assert_eq!(json, json!({}));
6530
6531 let deserialized: ProvidersCapabilities = serde_json::from_value(json).unwrap();
6532 assert!(deserialized.meta.is_none());
6533 }
6534
6535 #[cfg(feature = "unstable_llm_providers")]
6536 #[test]
6537 fn test_agent_capabilities_with_providers() {
6538 let caps = AgentCapabilities::new().providers(ProvidersCapabilities::new());
6539
6540 let json = serde_json::to_value(&caps).unwrap();
6541 assert_eq!(json["providers"], json!({}));
6542
6543 let deserialized: AgentCapabilities = serde_json::from_value(json).unwrap();
6544 assert!(deserialized.providers.is_some());
6545 }
6546}