1use std::{path::PathBuf, sync::Arc};
7
8use std::collections::HashMap;
9
10use derive_more::{Display, From};
11use serde::{Deserialize, Serialize};
12use serde_with::{DefaultOnError, VecSkipError, serde_as, skip_serializing_none};
13
14use crate::{IntoOption, ProtocolVersion};
15
16use super::{
17 ClientCapabilities, ContentBlock, ExtNotification, ExtRequest, ExtResponse, Meta, SessionId,
18};
19
20#[cfg(feature = "unstable_mcp_over_acp")]
21use super::mcp::{MCP_MESSAGE_METHOD_NAME, MessageMcpNotification};
22
23#[cfg(feature = "unstable_nes")]
24use super::{
25 AcceptNesNotification, CloseNesRequest, CloseNesResponse, DidChangeDocumentNotification,
26 DidCloseDocumentNotification, DidFocusDocumentNotification, DidOpenDocumentNotification,
27 DidSaveDocumentNotification, NesCapabilities, PositionEncodingKind, RejectNesNotification,
28 StartNesRequest, StartNesResponse, SuggestNesRequest, SuggestNesResponse,
29};
30
31#[cfg(feature = "unstable_nes")]
32use super::{
33 DOCUMENT_DID_CHANGE_METHOD_NAME, DOCUMENT_DID_CLOSE_METHOD_NAME,
34 DOCUMENT_DID_FOCUS_METHOD_NAME, DOCUMENT_DID_OPEN_METHOD_NAME, DOCUMENT_DID_SAVE_METHOD_NAME,
35 NES_ACCEPT_METHOD_NAME, NES_CLOSE_METHOD_NAME, NES_REJECT_METHOD_NAME, NES_START_METHOD_NAME,
36 NES_SUGGEST_METHOD_NAME,
37};
38
39#[serde_as]
47#[skip_serializing_none]
48#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
49#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
50#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = INITIALIZE_METHOD_NAME)))]
51#[serde(rename_all = "camelCase")]
52#[non_exhaustive]
53pub struct InitializeRequest {
54 pub protocol_version: ProtocolVersion,
56 #[serde_as(deserialize_as = "DefaultOnError")]
58 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
59 #[serde(default)]
60 pub client_capabilities: ClientCapabilities,
61 #[serde_as(deserialize_as = "DefaultOnError")]
65 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
66 #[serde(default)]
67 pub client_info: Option<Implementation>,
68 #[serde_as(deserialize_as = "DefaultOnError")]
74 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
75 #[serde(default)]
76 #[serde(rename = "_meta")]
77 pub meta: Option<Meta>,
78}
79
80impl InitializeRequest {
81 #[must_use]
83 pub fn new(protocol_version: ProtocolVersion) -> Self {
84 Self {
85 protocol_version,
86 client_capabilities: ClientCapabilities::default(),
87 client_info: None,
88 meta: None,
89 }
90 }
91
92 #[must_use]
94 pub fn client_capabilities(mut self, client_capabilities: ClientCapabilities) -> Self {
95 self.client_capabilities = client_capabilities;
96 self
97 }
98
99 #[must_use]
101 pub fn client_info(mut self, client_info: impl IntoOption<Implementation>) -> Self {
102 self.client_info = client_info.into_option();
103 self
104 }
105
106 #[must_use]
112 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
113 self.meta = meta.into_option();
114 self
115 }
116}
117
118#[serde_as]
124#[skip_serializing_none]
125#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
126#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
127#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = INITIALIZE_METHOD_NAME)))]
128#[serde(rename_all = "camelCase")]
129#[non_exhaustive]
130pub struct InitializeResponse {
131 pub protocol_version: ProtocolVersion,
136 #[serde_as(deserialize_as = "DefaultOnError")]
138 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
139 #[serde(default)]
140 pub agent_capabilities: AgentCapabilities,
141 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_>>")]
143 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
144 #[serde(default)]
145 pub auth_methods: Vec<AuthMethod>,
146 #[serde_as(deserialize_as = "DefaultOnError")]
150 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
151 #[serde(default)]
152 pub agent_info: Option<Implementation>,
153 #[serde_as(deserialize_as = "DefaultOnError")]
159 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
160 #[serde(default)]
161 #[serde(rename = "_meta")]
162 pub meta: Option<Meta>,
163}
164
165impl InitializeResponse {
166 #[must_use]
168 pub fn new(protocol_version: ProtocolVersion) -> Self {
169 Self {
170 protocol_version,
171 agent_capabilities: AgentCapabilities::default(),
172 auth_methods: vec![],
173 agent_info: None,
174 meta: None,
175 }
176 }
177
178 #[must_use]
180 pub fn agent_capabilities(mut self, agent_capabilities: AgentCapabilities) -> Self {
181 self.agent_capabilities = agent_capabilities;
182 self
183 }
184
185 #[must_use]
187 pub fn auth_methods(mut self, auth_methods: Vec<AuthMethod>) -> Self {
188 self.auth_methods = auth_methods;
189 self
190 }
191
192 #[must_use]
194 pub fn agent_info(mut self, agent_info: impl IntoOption<Implementation>) -> Self {
195 self.agent_info = agent_info.into_option();
196 self
197 }
198
199 #[must_use]
205 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
206 self.meta = meta.into_option();
207 self
208 }
209}
210
211#[serde_as]
215#[skip_serializing_none]
216#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
217#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
218#[serde(rename_all = "camelCase")]
219#[non_exhaustive]
220pub struct Implementation {
221 pub name: String,
224 #[serde_as(deserialize_as = "DefaultOnError")]
229 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
230 #[serde(default)]
231 pub title: Option<String>,
232 pub version: String,
235 #[serde_as(deserialize_as = "DefaultOnError")]
241 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
242 #[serde(default)]
243 #[serde(rename = "_meta")]
244 pub meta: Option<Meta>,
245}
246
247impl Implementation {
248 #[must_use]
250 pub fn new(name: impl Into<String>, version: impl Into<String>) -> Self {
251 Self {
252 name: name.into(),
253 title: None,
254 version: version.into(),
255 meta: None,
256 }
257 }
258
259 #[must_use]
264 pub fn title(mut self, title: impl IntoOption<String>) -> Self {
265 self.title = title.into_option();
266 self
267 }
268
269 #[must_use]
275 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
276 self.meta = meta.into_option();
277 self
278 }
279}
280
281#[serde_as]
287#[skip_serializing_none]
288#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
289#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
290#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = AUTHENTICATE_METHOD_NAME)))]
291#[serde(rename_all = "camelCase")]
292#[non_exhaustive]
293pub struct AuthenticateRequest {
294 pub method_id: AuthMethodId,
297 #[serde_as(deserialize_as = "DefaultOnError")]
303 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
304 #[serde(default)]
305 #[serde(rename = "_meta")]
306 pub meta: Option<Meta>,
307}
308
309impl AuthenticateRequest {
310 #[must_use]
312 pub fn new(method_id: impl Into<AuthMethodId>) -> Self {
313 Self {
314 method_id: method_id.into(),
315 meta: None,
316 }
317 }
318
319 #[must_use]
325 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
326 self.meta = meta.into_option();
327 self
328 }
329}
330
331crate::serde_util::default_on_null! {
332 #[serde_as]
334 #[skip_serializing_none]
335 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
336 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
337 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = AUTHENTICATE_METHOD_NAME)))]
338 #[serde(rename_all = "camelCase")]
339 #[non_exhaustive]
340 pub struct AuthenticateResponse {
341 #[serde_as(deserialize_as = "DefaultOnError")]
347 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
348 #[serde(default)]
349 #[serde(rename = "_meta")]
350 pub meta: Option<Meta>,
351 }
352}
353
354impl AuthenticateResponse {
355 #[must_use]
357 pub fn new() -> Self {
358 Self::default()
359 }
360
361 #[must_use]
367 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
368 self.meta = meta.into_option();
369 self
370 }
371}
372
373crate::serde_util::default_on_null! {
376 #[serde_as]
380 #[skip_serializing_none]
381 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
382 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
383 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = LOGOUT_METHOD_NAME)))]
384 #[serde(rename_all = "camelCase")]
385 #[non_exhaustive]
386 pub struct LogoutRequest {
387 #[serde_as(deserialize_as = "DefaultOnError")]
393 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
394 #[serde(default)]
395 #[serde(rename = "_meta")]
396 pub meta: Option<Meta>,
397 }
398}
399
400impl LogoutRequest {
401 #[must_use]
403 pub fn new() -> Self {
404 Self::default()
405 }
406
407 #[must_use]
413 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
414 self.meta = meta.into_option();
415 self
416 }
417}
418
419crate::serde_util::default_on_null! {
420 #[serde_as]
422 #[skip_serializing_none]
423 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
424 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
425 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = LOGOUT_METHOD_NAME)))]
426 #[serde(rename_all = "camelCase")]
427 #[non_exhaustive]
428 pub struct LogoutResponse {
429 #[serde_as(deserialize_as = "DefaultOnError")]
435 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
436 #[serde(default)]
437 #[serde(rename = "_meta")]
438 pub meta: Option<Meta>,
439 }
440}
441
442impl LogoutResponse {
443 #[must_use]
445 pub fn new() -> Self {
446 Self::default()
447 }
448
449 #[must_use]
455 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
456 self.meta = meta.into_option();
457 self
458 }
459}
460
461#[serde_as]
463#[skip_serializing_none]
464#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
465#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
466#[serde(rename_all = "camelCase")]
467#[non_exhaustive]
468pub struct AgentAuthCapabilities {
469 #[serde_as(deserialize_as = "DefaultOnError")]
474 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
475 #[serde(default)]
476 pub logout: Option<LogoutCapabilities>,
477 #[serde_as(deserialize_as = "DefaultOnError")]
483 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
484 #[serde(default)]
485 #[serde(rename = "_meta")]
486 pub meta: Option<Meta>,
487}
488
489impl AgentAuthCapabilities {
490 #[must_use]
492 pub fn new() -> Self {
493 Self::default()
494 }
495
496 #[must_use]
498 pub fn logout(mut self, logout: impl IntoOption<LogoutCapabilities>) -> Self {
499 self.logout = logout.into_option();
500 self
501 }
502
503 #[must_use]
509 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
510 self.meta = meta.into_option();
511 self
512 }
513}
514
515#[serde_as]
519#[skip_serializing_none]
520#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
521#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
522#[non_exhaustive]
523pub struct LogoutCapabilities {
524 #[serde_as(deserialize_as = "DefaultOnError")]
530 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
531 #[serde(default)]
532 #[serde(rename = "_meta")]
533 pub meta: Option<Meta>,
534}
535
536impl LogoutCapabilities {
537 #[must_use]
539 pub fn new() -> Self {
540 Self::default()
541 }
542
543 #[must_use]
549 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
550 self.meta = meta.into_option();
551 self
552 }
553}
554
555#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
557#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Display, From)]
558#[serde(transparent)]
559#[from(Arc<str>, String, &'static str)]
560#[non_exhaustive]
561pub struct AuthMethodId(pub Arc<str>);
562
563impl AuthMethodId {
564 #[must_use]
566 pub fn new(id: impl Into<Arc<str>>) -> Self {
567 Self(id.into())
568 }
569}
570
571#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
576#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
577#[serde(tag = "type", rename_all = "snake_case")]
578#[non_exhaustive]
579pub enum AuthMethod {
580 Terminal(AuthMethodTerminal),
583 #[serde(untagged)]
587 Agent(AuthMethodAgent),
588}
589
590impl AuthMethod {
591 #[must_use]
593 pub fn id(&self) -> &AuthMethodId {
594 match self {
595 Self::Agent(a) => &a.id,
596 Self::Terminal(t) => &t.id,
597 }
598 }
599
600 #[must_use]
602 pub fn name(&self) -> &str {
603 match self {
604 Self::Agent(a) => &a.name,
605 Self::Terminal(t) => &t.name,
606 }
607 }
608
609 #[must_use]
611 pub fn description(&self) -> Option<&str> {
612 match self {
613 Self::Agent(a) => a.description.as_deref(),
614 Self::Terminal(t) => t.description.as_deref(),
615 }
616 }
617
618 #[must_use]
624 pub fn meta(&self) -> Option<&Meta> {
625 match self {
626 Self::Agent(a) => a.meta.as_ref(),
627 Self::Terminal(t) => t.meta.as_ref(),
628 }
629 }
630}
631
632#[serde_as]
636#[skip_serializing_none]
637#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
638#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
639#[serde(rename_all = "camelCase")]
640#[non_exhaustive]
641pub struct AuthMethodAgent {
642 pub id: AuthMethodId,
644 pub name: String,
646 #[serde_as(deserialize_as = "DefaultOnError")]
648 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
649 #[serde(default)]
650 pub description: Option<String>,
651 #[serde_as(deserialize_as = "DefaultOnError")]
657 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
658 #[serde(default)]
659 #[serde(rename = "_meta")]
660 pub meta: Option<Meta>,
661}
662
663impl AuthMethodAgent {
664 #[must_use]
666 pub fn new(id: impl Into<AuthMethodId>, name: impl Into<String>) -> Self {
667 Self {
668 id: id.into(),
669 name: name.into(),
670 description: None,
671 meta: None,
672 }
673 }
674
675 #[must_use]
677 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
678 self.description = description.into_option();
679 self
680 }
681
682 #[must_use]
688 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
689 self.meta = meta.into_option();
690 self
691 }
692}
693
694#[serde_as]
702#[skip_serializing_none]
703#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
704#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
705#[serde(rename_all = "camelCase")]
706#[non_exhaustive]
707pub struct AuthMethodTerminal {
708 pub id: AuthMethodId,
710 pub name: String,
712 #[serde_as(deserialize_as = "DefaultOnError")]
714 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
715 #[serde(default)]
716 pub description: Option<String>,
717 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_>>")]
719 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
720 #[serde(default, skip_serializing_if = "Vec::is_empty")]
721 pub args: Vec<String>,
722 #[serde_as(deserialize_as = "DefaultOnError")]
725 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
726 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
727 pub env: HashMap<String, String>,
728 #[serde_as(deserialize_as = "DefaultOnError")]
734 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
735 #[serde(default)]
736 #[serde(rename = "_meta")]
737 pub meta: Option<Meta>,
738}
739
740impl AuthMethodTerminal {
741 #[must_use]
743 pub fn new(id: impl Into<AuthMethodId>, name: impl Into<String>) -> Self {
744 Self {
745 id: id.into(),
746 name: name.into(),
747 description: None,
748 args: Vec::new(),
749 env: HashMap::new(),
750 meta: None,
751 }
752 }
753
754 #[must_use]
756 pub fn args(mut self, args: Vec<String>) -> Self {
757 self.args = args;
758 self
759 }
760
761 #[must_use]
764 pub fn env(mut self, env: HashMap<String, String>) -> Self {
765 self.env = env;
766 self
767 }
768
769 #[must_use]
771 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
772 self.description = description.into_option();
773 self
774 }
775
776 #[must_use]
782 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
783 self.meta = meta.into_option();
784 self
785 }
786}
787
788#[serde_as]
794#[skip_serializing_none]
795#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
796#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
797#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_NEW_METHOD_NAME)))]
798#[serde(rename_all = "camelCase")]
799#[non_exhaustive]
800pub struct NewSessionRequest {
801 pub cwd: PathBuf,
803 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_>>")]
809 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
810 #[serde(default, skip_serializing_if = "Vec::is_empty")]
811 pub additional_directories: Vec<PathBuf>,
812 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_>>")]
814 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
815 pub mcp_servers: Vec<McpServer>,
816 #[serde_as(deserialize_as = "DefaultOnError")]
822 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
823 #[serde(default)]
824 #[serde(rename = "_meta")]
825 pub meta: Option<Meta>,
826}
827
828impl NewSessionRequest {
829 #[must_use]
831 pub fn new(cwd: impl Into<PathBuf>) -> Self {
832 Self {
833 cwd: cwd.into(),
834 additional_directories: vec![],
835 mcp_servers: vec![],
836 meta: None,
837 }
838 }
839
840 #[must_use]
842 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
843 self.additional_directories = additional_directories;
844 self
845 }
846
847 #[must_use]
849 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
850 self.mcp_servers = mcp_servers;
851 self
852 }
853
854 #[must_use]
860 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
861 self.meta = meta.into_option();
862 self
863 }
864}
865
866#[serde_as]
870#[skip_serializing_none]
871#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
872#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
873#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_NEW_METHOD_NAME)))]
874#[serde(rename_all = "camelCase")]
875#[non_exhaustive]
876pub struct NewSessionResponse {
877 pub session_id: SessionId,
881 #[serde_as(deserialize_as = "DefaultOnError")]
885 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
886 #[serde(default)]
887 pub modes: Option<SessionModeState>,
888 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_>>>")]
890 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
891 #[serde(default)]
892 pub config_options: Option<Vec<SessionConfigOption>>,
893 #[serde_as(deserialize_as = "DefaultOnError")]
899 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
900 #[serde(default)]
901 #[serde(rename = "_meta")]
902 pub meta: Option<Meta>,
903}
904
905impl NewSessionResponse {
906 #[must_use]
908 pub fn new(session_id: impl Into<SessionId>) -> Self {
909 Self {
910 session_id: session_id.into(),
911 modes: None,
912 config_options: None,
913 meta: None,
914 }
915 }
916
917 #[must_use]
921 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
922 self.modes = modes.into_option();
923 self
924 }
925
926 #[must_use]
928 pub fn config_options(
929 mut self,
930 config_options: impl IntoOption<Vec<SessionConfigOption>>,
931 ) -> Self {
932 self.config_options = config_options.into_option();
933 self
934 }
935
936 #[must_use]
942 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
943 self.meta = meta.into_option();
944 self
945 }
946}
947
948#[serde_as]
956#[skip_serializing_none]
957#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
958#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
959#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_LOAD_METHOD_NAME)))]
960#[serde(rename_all = "camelCase")]
961#[non_exhaustive]
962pub struct LoadSessionRequest {
963 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_>>")]
965 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
966 pub mcp_servers: Vec<McpServer>,
967 pub cwd: PathBuf,
969 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_>>")]
976 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
977 #[serde(default, skip_serializing_if = "Vec::is_empty")]
978 pub additional_directories: Vec<PathBuf>,
979 pub session_id: SessionId,
981 #[serde_as(deserialize_as = "DefaultOnError")]
987 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
988 #[serde(default)]
989 #[serde(rename = "_meta")]
990 pub meta: Option<Meta>,
991}
992
993impl LoadSessionRequest {
994 #[must_use]
996 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
997 Self {
998 mcp_servers: vec![],
999 cwd: cwd.into(),
1000 additional_directories: vec![],
1001 session_id: session_id.into(),
1002 meta: None,
1003 }
1004 }
1005
1006 #[must_use]
1008 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1009 self.additional_directories = additional_directories;
1010 self
1011 }
1012
1013 #[must_use]
1015 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1016 self.mcp_servers = mcp_servers;
1017 self
1018 }
1019
1020 #[must_use]
1026 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1027 self.meta = meta.into_option();
1028 self
1029 }
1030}
1031
1032crate::serde_util::default_on_null! {
1033 #[serde_as]
1035 #[skip_serializing_none]
1036 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1037 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
1038 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_LOAD_METHOD_NAME)))]
1039 #[serde(rename_all = "camelCase")]
1040 #[non_exhaustive]
1041 pub struct LoadSessionResponse {
1042 #[serde_as(deserialize_as = "DefaultOnError")]
1046 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1047 #[serde(default)]
1048 pub modes: Option<SessionModeState>,
1049 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_>>>")]
1051 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1052 #[serde(default)]
1053 pub config_options: Option<Vec<SessionConfigOption>>,
1054 #[serde_as(deserialize_as = "DefaultOnError")]
1060 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1061 #[serde(default)]
1062 #[serde(rename = "_meta")]
1063 pub meta: Option<Meta>,
1064 }
1065}
1066
1067impl LoadSessionResponse {
1068 #[must_use]
1070 pub fn new() -> Self {
1071 Self::default()
1072 }
1073
1074 #[must_use]
1078 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1079 self.modes = modes.into_option();
1080 self
1081 }
1082
1083 #[must_use]
1085 pub fn config_options(
1086 mut self,
1087 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1088 ) -> Self {
1089 self.config_options = config_options.into_option();
1090 self
1091 }
1092
1093 #[must_use]
1099 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1100 self.meta = meta.into_option();
1101 self
1102 }
1103}
1104
1105#[cfg(feature = "unstable_session_fork")]
1118#[serde_as]
1119#[skip_serializing_none]
1120#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1121#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1122#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_FORK_METHOD_NAME)))]
1123#[serde(rename_all = "camelCase")]
1124#[non_exhaustive]
1125pub struct ForkSessionRequest {
1126 pub session_id: SessionId,
1128 pub cwd: PathBuf,
1130 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_>>")]
1136 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1137 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1138 pub additional_directories: Vec<PathBuf>,
1139 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_>>")]
1141 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1142 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1143 pub mcp_servers: Vec<McpServer>,
1144 #[serde_as(deserialize_as = "DefaultOnError")]
1150 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1151 #[serde(default)]
1152 #[serde(rename = "_meta")]
1153 pub meta: Option<Meta>,
1154}
1155
1156#[cfg(feature = "unstable_session_fork")]
1157impl ForkSessionRequest {
1158 #[must_use]
1160 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1161 Self {
1162 session_id: session_id.into(),
1163 cwd: cwd.into(),
1164 additional_directories: vec![],
1165 mcp_servers: vec![],
1166 meta: None,
1167 }
1168 }
1169
1170 #[must_use]
1172 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1173 self.additional_directories = additional_directories;
1174 self
1175 }
1176
1177 #[must_use]
1179 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1180 self.mcp_servers = mcp_servers;
1181 self
1182 }
1183
1184 #[must_use]
1190 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1191 self.meta = meta.into_option();
1192 self
1193 }
1194}
1195
1196#[cfg(feature = "unstable_session_fork")]
1202#[serde_as]
1203#[skip_serializing_none]
1204#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1205#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1206#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_FORK_METHOD_NAME)))]
1207#[serde(rename_all = "camelCase")]
1208#[non_exhaustive]
1209pub struct ForkSessionResponse {
1210 pub session_id: SessionId,
1212 #[serde_as(deserialize_as = "DefaultOnError")]
1216 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1217 #[serde(default)]
1218 pub modes: Option<SessionModeState>,
1219 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_>>>")]
1221 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1222 #[serde(default)]
1223 pub config_options: Option<Vec<SessionConfigOption>>,
1224 #[serde_as(deserialize_as = "DefaultOnError")]
1230 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1231 #[serde(default)]
1232 #[serde(rename = "_meta")]
1233 pub meta: Option<Meta>,
1234}
1235
1236#[cfg(feature = "unstable_session_fork")]
1237impl ForkSessionResponse {
1238 #[must_use]
1240 pub fn new(session_id: impl Into<SessionId>) -> Self {
1241 Self {
1242 session_id: session_id.into(),
1243 modes: None,
1244 config_options: None,
1245 meta: None,
1246 }
1247 }
1248
1249 #[must_use]
1253 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1254 self.modes = modes.into_option();
1255 self
1256 }
1257
1258 #[must_use]
1260 pub fn config_options(
1261 mut self,
1262 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1263 ) -> Self {
1264 self.config_options = config_options.into_option();
1265 self
1266 }
1267
1268 #[must_use]
1274 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1275 self.meta = meta.into_option();
1276 self
1277 }
1278}
1279
1280#[serde_as]
1289#[skip_serializing_none]
1290#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1291#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1292#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_RESUME_METHOD_NAME)))]
1293#[serde(rename_all = "camelCase")]
1294#[non_exhaustive]
1295pub struct ResumeSessionRequest {
1296 pub session_id: SessionId,
1298 pub cwd: PathBuf,
1300 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_>>")]
1307 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1308 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1309 pub additional_directories: Vec<PathBuf>,
1310 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_>>")]
1312 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1313 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1314 pub mcp_servers: Vec<McpServer>,
1315 #[serde_as(deserialize_as = "DefaultOnError")]
1321 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1322 #[serde(default)]
1323 #[serde(rename = "_meta")]
1324 pub meta: Option<Meta>,
1325}
1326
1327impl ResumeSessionRequest {
1328 #[must_use]
1330 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1331 Self {
1332 session_id: session_id.into(),
1333 cwd: cwd.into(),
1334 additional_directories: vec![],
1335 mcp_servers: vec![],
1336 meta: None,
1337 }
1338 }
1339
1340 #[must_use]
1342 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1343 self.additional_directories = additional_directories;
1344 self
1345 }
1346
1347 #[must_use]
1349 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1350 self.mcp_servers = mcp_servers;
1351 self
1352 }
1353
1354 #[must_use]
1360 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1361 self.meta = meta.into_option();
1362 self
1363 }
1364}
1365
1366crate::serde_util::default_on_null! {
1367 #[serde_as]
1369 #[skip_serializing_none]
1370 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1371 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
1372 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_RESUME_METHOD_NAME)))]
1373 #[serde(rename_all = "camelCase")]
1374 #[non_exhaustive]
1375 pub struct ResumeSessionResponse {
1376 #[serde_as(deserialize_as = "DefaultOnError")]
1380 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1381 #[serde(default)]
1382 pub modes: Option<SessionModeState>,
1383 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_>>>")]
1385 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1386 #[serde(default)]
1387 pub config_options: Option<Vec<SessionConfigOption>>,
1388 #[serde_as(deserialize_as = "DefaultOnError")]
1394 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1395 #[serde(default)]
1396 #[serde(rename = "_meta")]
1397 pub meta: Option<Meta>,
1398 }
1399}
1400
1401impl ResumeSessionResponse {
1402 #[must_use]
1404 pub fn new() -> Self {
1405 Self::default()
1406 }
1407
1408 #[must_use]
1412 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1413 self.modes = modes.into_option();
1414 self
1415 }
1416
1417 #[must_use]
1419 pub fn config_options(
1420 mut self,
1421 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1422 ) -> Self {
1423 self.config_options = config_options.into_option();
1424 self
1425 }
1426
1427 #[must_use]
1433 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1434 self.meta = meta.into_option();
1435 self
1436 }
1437}
1438
1439#[serde_as]
1449#[skip_serializing_none]
1450#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1451#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1452#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_CLOSE_METHOD_NAME)))]
1453#[serde(rename_all = "camelCase")]
1454#[non_exhaustive]
1455pub struct CloseSessionRequest {
1456 pub session_id: SessionId,
1458 #[serde_as(deserialize_as = "DefaultOnError")]
1464 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1465 #[serde(default)]
1466 #[serde(rename = "_meta")]
1467 pub meta: Option<Meta>,
1468}
1469
1470impl CloseSessionRequest {
1471 #[must_use]
1473 pub fn new(session_id: impl Into<SessionId>) -> Self {
1474 Self {
1475 session_id: session_id.into(),
1476 meta: None,
1477 }
1478 }
1479
1480 #[must_use]
1486 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1487 self.meta = meta.into_option();
1488 self
1489 }
1490}
1491
1492crate::serde_util::default_on_null! {
1493 #[serde_as]
1495 #[skip_serializing_none]
1496 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1497 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
1498 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_CLOSE_METHOD_NAME)))]
1499 #[serde(rename_all = "camelCase")]
1500 #[non_exhaustive]
1501 pub struct CloseSessionResponse {
1502 #[serde_as(deserialize_as = "DefaultOnError")]
1508 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1509 #[serde(default)]
1510 #[serde(rename = "_meta")]
1511 pub meta: Option<Meta>,
1512 }
1513}
1514
1515impl CloseSessionResponse {
1516 #[must_use]
1518 pub fn new() -> Self {
1519 Self::default()
1520 }
1521
1522 #[must_use]
1528 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1529 self.meta = meta.into_option();
1530 self
1531 }
1532}
1533
1534crate::serde_util::default_on_null! {
1537 #[serde_as]
1541 #[skip_serializing_none]
1542 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1543 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
1544 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_LIST_METHOD_NAME)))]
1545 #[serde(rename_all = "camelCase")]
1546 #[non_exhaustive]
1547 pub struct ListSessionsRequest {
1548 #[serde(default)]
1550 pub cwd: Option<PathBuf>,
1551 #[serde(default)]
1553 pub cursor: Option<String>,
1554 #[serde_as(deserialize_as = "DefaultOnError")]
1560 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1561 #[serde(default)]
1562 #[serde(rename = "_meta")]
1563 pub meta: Option<Meta>,
1564 }
1565}
1566
1567impl ListSessionsRequest {
1568 #[must_use]
1570 pub fn new() -> Self {
1571 Self::default()
1572 }
1573
1574 #[must_use]
1576 pub fn cwd(mut self, cwd: impl IntoOption<PathBuf>) -> Self {
1577 self.cwd = cwd.into_option();
1578 self
1579 }
1580
1581 #[must_use]
1583 pub fn cursor(mut self, cursor: impl IntoOption<String>) -> Self {
1584 self.cursor = cursor.into_option();
1585 self
1586 }
1587
1588 #[must_use]
1594 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1595 self.meta = meta.into_option();
1596 self
1597 }
1598}
1599
1600#[serde_as]
1602#[skip_serializing_none]
1603#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1604#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1605#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_LIST_METHOD_NAME)))]
1606#[serde(rename_all = "camelCase")]
1607#[non_exhaustive]
1608pub struct ListSessionsResponse {
1609 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_>>")]
1611 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1612 pub sessions: Vec<SessionInfo>,
1613 #[serde_as(deserialize_as = "DefaultOnError")]
1616 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1617 #[serde(default)]
1618 pub next_cursor: Option<String>,
1619 #[serde_as(deserialize_as = "DefaultOnError")]
1625 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1626 #[serde(default)]
1627 #[serde(rename = "_meta")]
1628 pub meta: Option<Meta>,
1629}
1630
1631impl ListSessionsResponse {
1632 #[must_use]
1634 pub fn new(sessions: Vec<SessionInfo>) -> Self {
1635 Self {
1636 sessions,
1637 next_cursor: None,
1638 meta: None,
1639 }
1640 }
1641
1642 #[must_use]
1644 pub fn next_cursor(mut self, next_cursor: impl IntoOption<String>) -> Self {
1645 self.next_cursor = next_cursor.into_option();
1646 self
1647 }
1648
1649 #[must_use]
1655 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1656 self.meta = meta.into_option();
1657 self
1658 }
1659}
1660
1661#[serde_as]
1667#[skip_serializing_none]
1668#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1669#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1670#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_DELETE_METHOD_NAME)))]
1671#[serde(rename_all = "camelCase")]
1672#[non_exhaustive]
1673pub struct DeleteSessionRequest {
1674 pub session_id: SessionId,
1676 #[serde_as(deserialize_as = "DefaultOnError")]
1682 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1683 #[serde(default)]
1684 #[serde(rename = "_meta")]
1685 pub meta: Option<Meta>,
1686}
1687
1688impl DeleteSessionRequest {
1689 #[must_use]
1691 pub fn new(session_id: impl Into<SessionId>) -> Self {
1692 Self {
1693 session_id: session_id.into(),
1694 meta: None,
1695 }
1696 }
1697
1698 #[must_use]
1704 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1705 self.meta = meta.into_option();
1706 self
1707 }
1708}
1709
1710crate::serde_util::default_on_null! {
1711 #[serde_as]
1713 #[skip_serializing_none]
1714 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1715 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
1716 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_DELETE_METHOD_NAME)))]
1717 #[serde(rename_all = "camelCase")]
1718 #[non_exhaustive]
1719 pub struct DeleteSessionResponse {
1720 #[serde_as(deserialize_as = "DefaultOnError")]
1726 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1727 #[serde(default)]
1728 #[serde(rename = "_meta")]
1729 pub meta: Option<Meta>,
1730 }
1731}
1732
1733impl DeleteSessionResponse {
1734 #[must_use]
1736 pub fn new() -> Self {
1737 Self::default()
1738 }
1739
1740 #[must_use]
1746 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1747 self.meta = meta.into_option();
1748 self
1749 }
1750}
1751
1752#[serde_as]
1754#[skip_serializing_none]
1755#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1756#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1757#[serde(rename_all = "camelCase")]
1758#[non_exhaustive]
1759pub struct SessionInfo {
1760 pub session_id: SessionId,
1762 pub cwd: PathBuf,
1764 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_>>")]
1770 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1771 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1772 pub additional_directories: Vec<PathBuf>,
1773
1774 #[serde_as(deserialize_as = "DefaultOnError")]
1776 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1777 #[serde(default)]
1778 pub title: Option<String>,
1779 #[serde_as(deserialize_as = "DefaultOnError")]
1781 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1782 #[serde(default)]
1783 pub updated_at: Option<String>,
1784 #[serde_as(deserialize_as = "DefaultOnError")]
1790 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1791 #[serde(default)]
1792 #[serde(rename = "_meta")]
1793 pub meta: Option<Meta>,
1794}
1795
1796impl SessionInfo {
1797 #[must_use]
1799 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1800 Self {
1801 session_id: session_id.into(),
1802 cwd: cwd.into(),
1803 additional_directories: vec![],
1804 title: None,
1805 updated_at: None,
1806 meta: None,
1807 }
1808 }
1809
1810 #[must_use]
1812 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1813 self.additional_directories = additional_directories;
1814 self
1815 }
1816
1817 #[must_use]
1819 pub fn title(mut self, title: impl IntoOption<String>) -> Self {
1820 self.title = title.into_option();
1821 self
1822 }
1823
1824 #[must_use]
1826 pub fn updated_at(mut self, updated_at: impl IntoOption<String>) -> Self {
1827 self.updated_at = updated_at.into_option();
1828 self
1829 }
1830
1831 #[must_use]
1837 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1838 self.meta = meta.into_option();
1839 self
1840 }
1841}
1842
1843#[serde_as]
1847#[skip_serializing_none]
1848#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1849#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1850#[serde(rename_all = "camelCase")]
1851#[non_exhaustive]
1852pub struct SessionModeState {
1853 pub current_mode_id: SessionModeId,
1855 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_>>")]
1857 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1858 pub available_modes: Vec<SessionMode>,
1859 #[serde_as(deserialize_as = "DefaultOnError")]
1865 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1866 #[serde(default)]
1867 #[serde(rename = "_meta")]
1868 pub meta: Option<Meta>,
1869}
1870
1871impl SessionModeState {
1872 #[must_use]
1874 pub fn new(
1875 current_mode_id: impl Into<SessionModeId>,
1876 available_modes: Vec<SessionMode>,
1877 ) -> Self {
1878 Self {
1879 current_mode_id: current_mode_id.into(),
1880 available_modes,
1881 meta: None,
1882 }
1883 }
1884
1885 #[must_use]
1891 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1892 self.meta = meta.into_option();
1893 self
1894 }
1895}
1896
1897#[serde_as]
1901#[skip_serializing_none]
1902#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1903#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1904#[serde(rename_all = "camelCase")]
1905#[non_exhaustive]
1906pub struct SessionMode {
1907 pub id: SessionModeId,
1909 pub name: String,
1911 #[serde_as(deserialize_as = "DefaultOnError")]
1913 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1914 #[serde(default)]
1915 pub description: Option<String>,
1916 #[serde_as(deserialize_as = "DefaultOnError")]
1922 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1923 #[serde(default)]
1924 #[serde(rename = "_meta")]
1925 pub meta: Option<Meta>,
1926}
1927
1928impl SessionMode {
1929 #[must_use]
1931 pub fn new(id: impl Into<SessionModeId>, name: impl Into<String>) -> Self {
1932 Self {
1933 id: id.into(),
1934 name: name.into(),
1935 description: None,
1936 meta: None,
1937 }
1938 }
1939
1940 #[must_use]
1942 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
1943 self.description = description.into_option();
1944 self
1945 }
1946
1947 #[must_use]
1953 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1954 self.meta = meta.into_option();
1955 self
1956 }
1957}
1958
1959#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1961#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, From, Display)]
1962#[serde(transparent)]
1963#[from(Arc<str>, String, &'static str)]
1964#[non_exhaustive]
1965pub struct SessionModeId(pub Arc<str>);
1966
1967impl SessionModeId {
1968 #[must_use]
1970 pub fn new(id: impl Into<Arc<str>>) -> Self {
1971 Self(id.into())
1972 }
1973}
1974
1975#[serde_as]
1977#[skip_serializing_none]
1978#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1979#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1980#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODE_METHOD_NAME)))]
1981#[serde(rename_all = "camelCase")]
1982#[non_exhaustive]
1983pub struct SetSessionModeRequest {
1984 pub session_id: SessionId,
1986 pub mode_id: SessionModeId,
1988 #[serde_as(deserialize_as = "DefaultOnError")]
1994 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1995 #[serde(default)]
1996 #[serde(rename = "_meta")]
1997 pub meta: Option<Meta>,
1998}
1999
2000impl SetSessionModeRequest {
2001 #[must_use]
2003 pub fn new(session_id: impl Into<SessionId>, mode_id: impl Into<SessionModeId>) -> Self {
2004 Self {
2005 session_id: session_id.into(),
2006 mode_id: mode_id.into(),
2007 meta: None,
2008 }
2009 }
2010
2011 #[must_use]
2013 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2014 self.meta = meta.into_option();
2015 self
2016 }
2017}
2018
2019crate::serde_util::default_on_null! {
2020 #[serde_as]
2022 #[skip_serializing_none]
2023 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2024 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
2025 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODE_METHOD_NAME)))]
2026 #[serde(rename_all = "camelCase")]
2027 #[non_exhaustive]
2028 pub struct SetSessionModeResponse {
2029 #[serde_as(deserialize_as = "DefaultOnError")]
2035 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2036 #[serde(default)]
2037 #[serde(rename = "_meta")]
2038 pub meta: Option<Meta>,
2039 }
2040}
2041
2042impl SetSessionModeResponse {
2043 #[must_use]
2045 pub fn new() -> Self {
2046 Self::default()
2047 }
2048
2049 #[must_use]
2055 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2056 self.meta = meta.into_option();
2057 self
2058 }
2059}
2060
2061#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2065#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, From, Display)]
2066#[serde(transparent)]
2067#[from(Arc<str>, String, &'static str)]
2068#[non_exhaustive]
2069pub struct SessionConfigId(pub Arc<str>);
2070
2071impl SessionConfigId {
2072 #[must_use]
2074 pub fn new(id: impl Into<Arc<str>>) -> Self {
2075 Self(id.into())
2076 }
2077}
2078
2079#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2081#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, From, Display)]
2082#[serde(transparent)]
2083#[from(Arc<str>, String, &'static str)]
2084#[non_exhaustive]
2085pub struct SessionConfigValueId(pub Arc<str>);
2086
2087impl SessionConfigValueId {
2088 #[must_use]
2090 pub fn new(id: impl Into<Arc<str>>) -> Self {
2091 Self(id.into())
2092 }
2093}
2094
2095#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2097#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, From, Display)]
2098#[serde(transparent)]
2099#[from(Arc<str>, String, &'static str)]
2100#[non_exhaustive]
2101pub struct SessionConfigGroupId(pub Arc<str>);
2102
2103impl SessionConfigGroupId {
2104 #[must_use]
2106 pub fn new(id: impl Into<Arc<str>>) -> Self {
2107 Self(id.into())
2108 }
2109}
2110
2111#[serde_as]
2113#[skip_serializing_none]
2114#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2115#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2116#[serde(rename_all = "camelCase")]
2117#[non_exhaustive]
2118pub struct SessionConfigSelectOption {
2119 pub value: SessionConfigValueId,
2121 pub name: String,
2123 #[serde_as(deserialize_as = "DefaultOnError")]
2125 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2126 #[serde(default)]
2127 pub description: Option<String>,
2128 #[serde_as(deserialize_as = "DefaultOnError")]
2134 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2135 #[serde(default)]
2136 #[serde(rename = "_meta")]
2137 pub meta: Option<Meta>,
2138}
2139
2140impl SessionConfigSelectOption {
2141 #[must_use]
2143 pub fn new(value: impl Into<SessionConfigValueId>, name: impl Into<String>) -> Self {
2144 Self {
2145 value: value.into(),
2146 name: name.into(),
2147 description: None,
2148 meta: None,
2149 }
2150 }
2151
2152 #[must_use]
2154 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
2155 self.description = description.into_option();
2156 self
2157 }
2158
2159 #[must_use]
2165 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2166 self.meta = meta.into_option();
2167 self
2168 }
2169}
2170
2171#[serde_as]
2173#[skip_serializing_none]
2174#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2175#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2176#[serde(rename_all = "camelCase")]
2177#[non_exhaustive]
2178pub struct SessionConfigSelectGroup {
2179 pub group: SessionConfigGroupId,
2181 pub name: String,
2183 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_>>")]
2185 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
2186 pub options: Vec<SessionConfigSelectOption>,
2187 #[serde_as(deserialize_as = "DefaultOnError")]
2193 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2194 #[serde(default)]
2195 #[serde(rename = "_meta")]
2196 pub meta: Option<Meta>,
2197}
2198
2199impl SessionConfigSelectGroup {
2200 #[must_use]
2202 pub fn new(
2203 group: impl Into<SessionConfigGroupId>,
2204 name: impl Into<String>,
2205 options: Vec<SessionConfigSelectOption>,
2206 ) -> Self {
2207 Self {
2208 group: group.into(),
2209 name: name.into(),
2210 options,
2211 meta: None,
2212 }
2213 }
2214
2215 #[must_use]
2221 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2222 self.meta = meta.into_option();
2223 self
2224 }
2225}
2226
2227#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2229#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2230#[serde(untagged)]
2231#[non_exhaustive]
2232pub enum SessionConfigSelectOptions {
2233 Ungrouped(Vec<SessionConfigSelectOption>),
2235 Grouped(Vec<SessionConfigSelectGroup>),
2237}
2238
2239impl From<Vec<SessionConfigSelectOption>> for SessionConfigSelectOptions {
2240 fn from(options: Vec<SessionConfigSelectOption>) -> Self {
2241 SessionConfigSelectOptions::Ungrouped(options)
2242 }
2243}
2244
2245impl From<Vec<SessionConfigSelectGroup>> for SessionConfigSelectOptions {
2246 fn from(groups: Vec<SessionConfigSelectGroup>) -> Self {
2247 SessionConfigSelectOptions::Grouped(groups)
2248 }
2249}
2250
2251#[skip_serializing_none]
2253#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2254#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2255#[serde(rename_all = "camelCase")]
2256#[non_exhaustive]
2257pub struct SessionConfigSelect {
2258 pub current_value: SessionConfigValueId,
2260 pub options: SessionConfigSelectOptions,
2262}
2263
2264impl SessionConfigSelect {
2265 #[must_use]
2267 pub fn new(
2268 current_value: impl Into<SessionConfigValueId>,
2269 options: impl Into<SessionConfigSelectOptions>,
2270 ) -> Self {
2271 Self {
2272 current_value: current_value.into(),
2273 options: options.into(),
2274 }
2275 }
2276}
2277
2278#[skip_serializing_none]
2280#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2281#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2282#[serde(rename_all = "camelCase")]
2283#[non_exhaustive]
2284pub struct SessionConfigBoolean {
2285 pub current_value: bool,
2287}
2288
2289impl SessionConfigBoolean {
2290 #[must_use]
2292 pub fn new(current_value: bool) -> Self {
2293 Self { current_value }
2294 }
2295}
2296
2297#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2307#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2308#[serde(rename_all = "snake_case")]
2309#[non_exhaustive]
2310pub enum SessionConfigOptionCategory {
2311 Mode,
2313 Model,
2315 ModelConfig,
2317 ThoughtLevel,
2319 #[serde(untagged)]
2321 Other(String),
2322}
2323
2324#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2326#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2327#[serde(tag = "type", rename_all = "snake_case")]
2328#[cfg_attr(feature = "schemars", schemars(extend("discriminator" = {"propertyName": "type"})))]
2329#[non_exhaustive]
2330pub enum SessionConfigKind {
2331 Select(SessionConfigSelect),
2333 Boolean(SessionConfigBoolean),
2335}
2336
2337#[serde_as]
2339#[skip_serializing_none]
2340#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2341#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2342#[serde(rename_all = "camelCase")]
2343#[non_exhaustive]
2344pub struct SessionConfigOption {
2345 pub id: SessionConfigId,
2347 pub name: String,
2349 #[serde_as(deserialize_as = "DefaultOnError")]
2351 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2352 #[serde(default)]
2353 pub description: Option<String>,
2354 #[serde_as(deserialize_as = "DefaultOnError")]
2356 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2357 #[serde(default)]
2358 pub category: Option<SessionConfigOptionCategory>,
2359 #[serde(flatten)]
2361 pub kind: SessionConfigKind,
2362 #[serde_as(deserialize_as = "DefaultOnError")]
2368 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2369 #[serde(default)]
2370 #[serde(rename = "_meta")]
2371 pub meta: Option<Meta>,
2372}
2373
2374impl SessionConfigOption {
2375 #[must_use]
2377 pub fn new(
2378 id: impl Into<SessionConfigId>,
2379 name: impl Into<String>,
2380 kind: SessionConfigKind,
2381 ) -> Self {
2382 Self {
2383 id: id.into(),
2384 name: name.into(),
2385 description: None,
2386 category: None,
2387 kind,
2388 meta: None,
2389 }
2390 }
2391
2392 #[must_use]
2394 pub fn select(
2395 id: impl Into<SessionConfigId>,
2396 name: impl Into<String>,
2397 current_value: impl Into<SessionConfigValueId>,
2398 options: impl Into<SessionConfigSelectOptions>,
2399 ) -> Self {
2400 Self::new(
2401 id,
2402 name,
2403 SessionConfigKind::Select(SessionConfigSelect::new(current_value, options)),
2404 )
2405 }
2406
2407 #[must_use]
2409 pub fn boolean(
2410 id: impl Into<SessionConfigId>,
2411 name: impl Into<String>,
2412 current_value: bool,
2413 ) -> Self {
2414 Self::new(
2415 id,
2416 name,
2417 SessionConfigKind::Boolean(SessionConfigBoolean::new(current_value)),
2418 )
2419 }
2420
2421 #[must_use]
2423 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
2424 self.description = description.into_option();
2425 self
2426 }
2427
2428 #[must_use]
2430 pub fn category(mut self, category: impl IntoOption<SessionConfigOptionCategory>) -> Self {
2431 self.category = category.into_option();
2432 self
2433 }
2434
2435 #[must_use]
2441 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2442 self.meta = meta.into_option();
2443 self
2444 }
2445}
2446
2447#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2458#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2459#[serde(tag = "type", rename_all = "snake_case")]
2460#[non_exhaustive]
2461pub enum SessionConfigOptionValue {
2462 Boolean {
2464 value: bool,
2466 },
2467 #[serde(untagged)]
2473 ValueId {
2474 value: SessionConfigValueId,
2476 },
2477}
2478
2479impl SessionConfigOptionValue {
2480 #[must_use]
2482 pub fn value_id(id: impl Into<SessionConfigValueId>) -> Self {
2483 Self::ValueId { value: id.into() }
2484 }
2485
2486 #[must_use]
2488 pub fn boolean(val: bool) -> Self {
2489 Self::Boolean { value: val }
2490 }
2491
2492 #[must_use]
2495 pub fn as_value_id(&self) -> Option<&SessionConfigValueId> {
2496 match self {
2497 Self::ValueId { value } => Some(value),
2498 _ => None,
2499 }
2500 }
2501
2502 #[must_use]
2504 pub fn as_bool(&self) -> Option<bool> {
2505 match self {
2506 Self::Boolean { value } => Some(*value),
2507 _ => None,
2508 }
2509 }
2510}
2511
2512impl From<SessionConfigValueId> for SessionConfigOptionValue {
2513 fn from(value: SessionConfigValueId) -> Self {
2514 Self::ValueId { value }
2515 }
2516}
2517
2518impl From<bool> for SessionConfigOptionValue {
2519 fn from(value: bool) -> Self {
2520 Self::Boolean { value }
2521 }
2522}
2523
2524impl From<&str> for SessionConfigOptionValue {
2525 fn from(value: &str) -> Self {
2526 Self::ValueId {
2527 value: SessionConfigValueId::new(value),
2528 }
2529 }
2530}
2531
2532#[serde_as]
2534#[skip_serializing_none]
2535#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2536#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2537#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_CONFIG_OPTION_METHOD_NAME)))]
2538#[serde(rename_all = "camelCase")]
2539#[non_exhaustive]
2540pub struct SetSessionConfigOptionRequest {
2541 pub session_id: SessionId,
2543 pub config_id: SessionConfigId,
2545 #[serde(flatten)]
2550 pub value: SessionConfigOptionValue,
2551 #[serde_as(deserialize_as = "DefaultOnError")]
2557 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2558 #[serde(default)]
2559 #[serde(rename = "_meta")]
2560 pub meta: Option<Meta>,
2561}
2562
2563impl SetSessionConfigOptionRequest {
2564 #[must_use]
2566 pub fn new(
2567 session_id: impl Into<SessionId>,
2568 config_id: impl Into<SessionConfigId>,
2569 value: impl Into<SessionConfigOptionValue>,
2570 ) -> Self {
2571 Self {
2572 session_id: session_id.into(),
2573 config_id: config_id.into(),
2574 value: value.into(),
2575 meta: None,
2576 }
2577 }
2578
2579 #[must_use]
2585 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2586 self.meta = meta.into_option();
2587 self
2588 }
2589}
2590
2591#[serde_as]
2593#[skip_serializing_none]
2594#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2595#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2596#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_CONFIG_OPTION_METHOD_NAME)))]
2597#[serde(rename_all = "camelCase")]
2598#[non_exhaustive]
2599pub struct SetSessionConfigOptionResponse {
2600 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_>>")]
2602 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
2603 pub config_options: Vec<SessionConfigOption>,
2604 #[serde_as(deserialize_as = "DefaultOnError")]
2610 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2611 #[serde(default)]
2612 #[serde(rename = "_meta")]
2613 pub meta: Option<Meta>,
2614}
2615
2616impl SetSessionConfigOptionResponse {
2617 #[must_use]
2619 pub fn new(config_options: Vec<SessionConfigOption>) -> Self {
2620 Self {
2621 config_options,
2622 meta: None,
2623 }
2624 }
2625
2626 #[must_use]
2632 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2633 self.meta = meta.into_option();
2634 self
2635 }
2636}
2637
2638#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2647#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2648#[serde(tag = "type", rename_all = "snake_case")]
2649#[non_exhaustive]
2650pub enum McpServer {
2651 Http(McpServerHttp),
2655 Sse(McpServerSse),
2659 #[cfg(feature = "unstable_mcp_over_acp")]
2668 Acp(McpServerAcp),
2669 #[serde(untagged)]
2673 Stdio(McpServerStdio),
2674}
2675
2676#[serde_as]
2678#[skip_serializing_none]
2679#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2680#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2681#[serde(rename_all = "camelCase")]
2682#[non_exhaustive]
2683pub struct McpServerHttp {
2684 pub name: String,
2686 pub url: String,
2688 pub headers: Vec<HttpHeader>,
2690 #[serde_as(deserialize_as = "DefaultOnError")]
2696 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2697 #[serde(default)]
2698 #[serde(rename = "_meta")]
2699 pub meta: Option<Meta>,
2700}
2701
2702impl McpServerHttp {
2703 #[must_use]
2705 pub fn new(name: impl Into<String>, url: impl Into<String>) -> Self {
2706 Self {
2707 name: name.into(),
2708 url: url.into(),
2709 headers: Vec::new(),
2710 meta: None,
2711 }
2712 }
2713
2714 #[must_use]
2716 pub fn headers(mut self, headers: Vec<HttpHeader>) -> Self {
2717 self.headers = headers;
2718 self
2719 }
2720
2721 #[must_use]
2727 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2728 self.meta = meta.into_option();
2729 self
2730 }
2731}
2732
2733#[serde_as]
2735#[skip_serializing_none]
2736#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2737#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2738#[serde(rename_all = "camelCase")]
2739#[non_exhaustive]
2740pub struct McpServerSse {
2741 pub name: String,
2743 pub url: String,
2745 pub headers: Vec<HttpHeader>,
2747 #[serde_as(deserialize_as = "DefaultOnError")]
2753 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2754 #[serde(default)]
2755 #[serde(rename = "_meta")]
2756 pub meta: Option<Meta>,
2757}
2758
2759impl McpServerSse {
2760 #[must_use]
2762 pub fn new(name: impl Into<String>, url: impl Into<String>) -> Self {
2763 Self {
2764 name: name.into(),
2765 url: url.into(),
2766 headers: Vec::new(),
2767 meta: None,
2768 }
2769 }
2770
2771 #[must_use]
2773 pub fn headers(mut self, headers: Vec<HttpHeader>) -> Self {
2774 self.headers = headers;
2775 self
2776 }
2777
2778 #[must_use]
2784 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2785 self.meta = meta.into_option();
2786 self
2787 }
2788}
2789
2790#[cfg(feature = "unstable_mcp_over_acp")]
2799#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2800#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Display, From)]
2801#[serde(transparent)]
2802#[from(Arc<str>, String, &'static str)]
2803#[non_exhaustive]
2804pub struct McpServerAcpId(pub Arc<str>);
2805
2806#[cfg(feature = "unstable_mcp_over_acp")]
2807impl McpServerAcpId {
2808 #[must_use]
2810 pub fn new(id: impl Into<Arc<str>>) -> Self {
2811 Self(id.into())
2812 }
2813}
2814
2815#[serde_as]
2824#[skip_serializing_none]
2825#[cfg(feature = "unstable_mcp_over_acp")]
2826#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2827#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2828#[serde(rename_all = "camelCase")]
2829#[non_exhaustive]
2830pub struct McpServerAcp {
2831 pub name: String,
2833 pub server_id: McpServerAcpId,
2838 #[serde_as(deserialize_as = "DefaultOnError")]
2844 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2845 #[serde(default)]
2846 #[serde(rename = "_meta")]
2847 pub meta: Option<Meta>,
2848}
2849
2850#[cfg(feature = "unstable_mcp_over_acp")]
2851impl McpServerAcp {
2852 #[must_use]
2854 pub fn new(name: impl Into<String>, id: impl Into<McpServerAcpId>) -> Self {
2855 Self {
2856 name: name.into(),
2857 server_id: id.into(),
2858 meta: None,
2859 }
2860 }
2861
2862 #[must_use]
2868 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2869 self.meta = meta.into_option();
2870 self
2871 }
2872}
2873
2874#[serde_as]
2876#[skip_serializing_none]
2877#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2878#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2879#[serde(rename_all = "camelCase")]
2880#[non_exhaustive]
2881pub struct McpServerStdio {
2882 pub name: String,
2884 pub command: PathBuf,
2886 pub args: Vec<String>,
2888 pub env: Vec<EnvVariable>,
2890 #[serde_as(deserialize_as = "DefaultOnError")]
2896 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2897 #[serde(default)]
2898 #[serde(rename = "_meta")]
2899 pub meta: Option<Meta>,
2900}
2901
2902impl McpServerStdio {
2903 #[must_use]
2905 pub fn new(name: impl Into<String>, command: impl Into<PathBuf>) -> Self {
2906 Self {
2907 name: name.into(),
2908 command: command.into(),
2909 args: Vec::new(),
2910 env: Vec::new(),
2911 meta: None,
2912 }
2913 }
2914
2915 #[must_use]
2917 pub fn args(mut self, args: Vec<String>) -> Self {
2918 self.args = args;
2919 self
2920 }
2921
2922 #[must_use]
2924 pub fn env(mut self, env: Vec<EnvVariable>) -> Self {
2925 self.env = env;
2926 self
2927 }
2928
2929 #[must_use]
2935 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2936 self.meta = meta.into_option();
2937 self
2938 }
2939}
2940
2941#[serde_as]
2943#[skip_serializing_none]
2944#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2945#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2946#[serde(rename_all = "camelCase")]
2947#[non_exhaustive]
2948pub struct EnvVariable {
2949 pub name: String,
2951 pub value: String,
2953 #[serde_as(deserialize_as = "DefaultOnError")]
2959 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2960 #[serde(default)]
2961 #[serde(rename = "_meta")]
2962 pub meta: Option<Meta>,
2963}
2964
2965impl EnvVariable {
2966 #[must_use]
2968 pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
2969 Self {
2970 name: name.into(),
2971 value: value.into(),
2972 meta: None,
2973 }
2974 }
2975
2976 #[must_use]
2982 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2983 self.meta = meta.into_option();
2984 self
2985 }
2986}
2987
2988#[serde_as]
2990#[skip_serializing_none]
2991#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2992#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2993#[serde(rename_all = "camelCase")]
2994#[non_exhaustive]
2995pub struct HttpHeader {
2996 pub name: String,
2998 pub value: String,
3000 #[serde_as(deserialize_as = "DefaultOnError")]
3006 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3007 #[serde(default)]
3008 #[serde(rename = "_meta")]
3009 pub meta: Option<Meta>,
3010}
3011
3012impl HttpHeader {
3013 #[must_use]
3015 pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
3016 Self {
3017 name: name.into(),
3018 value: value.into(),
3019 meta: None,
3020 }
3021 }
3022
3023 #[must_use]
3029 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3030 self.meta = meta.into_option();
3031 self
3032 }
3033}
3034
3035#[serde_as]
3043#[skip_serializing_none]
3044#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3045#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
3046#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_PROMPT_METHOD_NAME)))]
3047#[serde(rename_all = "camelCase")]
3048#[non_exhaustive]
3049pub struct PromptRequest {
3050 pub session_id: SessionId,
3052 pub prompt: Vec<ContentBlock>,
3066 #[serde_as(deserialize_as = "DefaultOnError")]
3072 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3073 #[serde(default)]
3074 #[serde(rename = "_meta")]
3075 pub meta: Option<Meta>,
3076}
3077
3078impl PromptRequest {
3079 #[must_use]
3081 pub fn new(session_id: impl Into<SessionId>, prompt: Vec<ContentBlock>) -> Self {
3082 Self {
3083 session_id: session_id.into(),
3084 prompt,
3085 meta: None,
3086 }
3087 }
3088
3089 #[must_use]
3095 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3096 self.meta = meta.into_option();
3097 self
3098 }
3099}
3100
3101#[serde_as]
3105#[skip_serializing_none]
3106#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3107#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3108#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_PROMPT_METHOD_NAME)))]
3109#[serde(rename_all = "camelCase")]
3110#[non_exhaustive]
3111pub struct PromptResponse {
3112 pub stop_reason: StopReason,
3114 #[cfg(feature = "unstable_end_turn_token_usage")]
3120 #[serde_as(deserialize_as = "DefaultOnError")]
3121 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3122 #[serde(default)]
3123 pub usage: Option<Usage>,
3124 #[serde_as(deserialize_as = "DefaultOnError")]
3130 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3131 #[serde(default)]
3132 #[serde(rename = "_meta")]
3133 pub meta: Option<Meta>,
3134}
3135
3136impl PromptResponse {
3137 #[must_use]
3139 pub fn new(stop_reason: StopReason) -> Self {
3140 Self {
3141 stop_reason,
3142 #[cfg(feature = "unstable_end_turn_token_usage")]
3143 usage: None,
3144 meta: None,
3145 }
3146 }
3147
3148 #[cfg(feature = "unstable_end_turn_token_usage")]
3154 #[must_use]
3155 pub fn usage(mut self, usage: impl IntoOption<Usage>) -> Self {
3156 self.usage = usage.into_option();
3157 self
3158 }
3159
3160 #[must_use]
3166 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3167 self.meta = meta.into_option();
3168 self
3169 }
3170}
3171
3172#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3176#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize)]
3177#[serde(rename_all = "snake_case")]
3178#[non_exhaustive]
3179pub enum StopReason {
3180 EndTurn,
3182 MaxTokens,
3184 MaxTurnRequests,
3187 Refusal,
3191 Cancelled,
3198}
3199
3200#[cfg(feature = "unstable_end_turn_token_usage")]
3206#[serde_as]
3207#[skip_serializing_none]
3208#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3209#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3210#[serde(rename_all = "camelCase")]
3211#[non_exhaustive]
3212pub struct Usage {
3213 pub total_tokens: u64,
3215 pub input_tokens: u64,
3217 pub output_tokens: u64,
3219 #[serde_as(deserialize_as = "DefaultOnError")]
3221 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3222 #[serde(default)]
3223 pub thought_tokens: Option<u64>,
3224 #[serde_as(deserialize_as = "DefaultOnError")]
3226 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3227 #[serde(default)]
3228 pub cached_read_tokens: Option<u64>,
3229 #[serde_as(deserialize_as = "DefaultOnError")]
3231 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3232 #[serde(default)]
3233 pub cached_write_tokens: Option<u64>,
3234 #[serde_as(deserialize_as = "DefaultOnError")]
3240 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3241 #[serde(default)]
3242 #[serde(rename = "_meta")]
3243 pub meta: Option<Meta>,
3244}
3245
3246#[cfg(feature = "unstable_end_turn_token_usage")]
3247impl Usage {
3248 #[must_use]
3250 pub fn new(total_tokens: u64, input_tokens: u64, output_tokens: u64) -> Self {
3251 Self {
3252 total_tokens,
3253 input_tokens,
3254 output_tokens,
3255 thought_tokens: None,
3256 cached_read_tokens: None,
3257 cached_write_tokens: None,
3258 meta: None,
3259 }
3260 }
3261
3262 #[must_use]
3264 pub fn thought_tokens(mut self, thought_tokens: impl IntoOption<u64>) -> Self {
3265 self.thought_tokens = thought_tokens.into_option();
3266 self
3267 }
3268
3269 #[must_use]
3271 pub fn cached_read_tokens(mut self, cached_read_tokens: impl IntoOption<u64>) -> Self {
3272 self.cached_read_tokens = cached_read_tokens.into_option();
3273 self
3274 }
3275
3276 #[must_use]
3278 pub fn cached_write_tokens(mut self, cached_write_tokens: impl IntoOption<u64>) -> Self {
3279 self.cached_write_tokens = cached_write_tokens.into_option();
3280 self
3281 }
3282
3283 #[must_use]
3289 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3290 self.meta = meta.into_option();
3291 self
3292 }
3293}
3294
3295#[cfg(feature = "unstable_llm_providers")]
3308#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3309#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3310#[serde(rename_all = "snake_case")]
3311#[non_exhaustive]
3312#[expect(clippy::doc_markdown)]
3313pub enum LlmProtocol {
3314 Anthropic,
3316 #[serde(rename = "openai")]
3318 OpenAi,
3319 Azure,
3321 Vertex,
3323 Bedrock,
3325 #[serde(untagged)]
3327 Other(String),
3328}
3329
3330#[cfg(feature = "unstable_llm_providers")]
3336#[serde_as]
3337#[skip_serializing_none]
3338#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3339#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3340#[serde(rename_all = "camelCase")]
3341#[non_exhaustive]
3342pub struct ProviderCurrentConfig {
3343 pub api_type: LlmProtocol,
3345 pub base_url: String,
3347 #[serde_as(deserialize_as = "DefaultOnError")]
3353 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3354 #[serde(default)]
3355 #[serde(rename = "_meta")]
3356 pub meta: Option<Meta>,
3357}
3358
3359#[cfg(feature = "unstable_llm_providers")]
3360impl ProviderCurrentConfig {
3361 #[must_use]
3363 pub fn new(api_type: LlmProtocol, base_url: impl Into<String>) -> Self {
3364 Self {
3365 api_type,
3366 base_url: base_url.into(),
3367 meta: None,
3368 }
3369 }
3370
3371 #[must_use]
3377 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3378 self.meta = meta.into_option();
3379 self
3380 }
3381}
3382
3383#[cfg(feature = "unstable_llm_providers")]
3389#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3390#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Display, From)]
3391#[serde(transparent)]
3392#[from(Arc<str>, String, &'static str)]
3393#[non_exhaustive]
3394pub struct ProviderId(pub Arc<str>);
3395
3396#[cfg(feature = "unstable_llm_providers")]
3397impl ProviderId {
3398 #[must_use]
3400 pub fn new(id: impl Into<Arc<str>>) -> Self {
3401 Self(id.into())
3402 }
3403}
3404
3405#[cfg(feature = "unstable_llm_providers")]
3411#[serde_as]
3412#[skip_serializing_none]
3413#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3414#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3415#[serde(rename_all = "camelCase")]
3416#[non_exhaustive]
3417pub struct ProviderInfo {
3418 pub provider_id: ProviderId,
3420 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_>>")]
3422 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
3423 pub supported: Vec<LlmProtocol>,
3424 pub required: bool,
3427 #[serde(default)]
3430 pub current: Option<ProviderCurrentConfig>,
3431 #[serde_as(deserialize_as = "DefaultOnError")]
3437 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3438 #[serde(default)]
3439 #[serde(rename = "_meta")]
3440 pub meta: Option<Meta>,
3441}
3442
3443#[cfg(feature = "unstable_llm_providers")]
3444impl ProviderInfo {
3445 #[must_use]
3447 pub fn new(
3448 provider_id: impl Into<ProviderId>,
3449 supported: Vec<LlmProtocol>,
3450 required: bool,
3451 current: impl IntoOption<ProviderCurrentConfig>,
3452 ) -> Self {
3453 Self {
3454 provider_id: provider_id.into(),
3455 supported,
3456 required,
3457 current: current.into_option(),
3458 meta: None,
3459 }
3460 }
3461
3462 #[must_use]
3468 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3469 self.meta = meta.into_option();
3470 self
3471 }
3472}
3473
3474#[cfg(feature = "unstable_llm_providers")]
3475crate::serde_util::default_on_null! {
3476 #[serde_as]
3482 #[skip_serializing_none]
3483 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3484 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
3485 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_LIST_METHOD_NAME)))]
3486 #[serde(rename_all = "camelCase")]
3487 #[non_exhaustive]
3488 pub struct ListProvidersRequest {
3489 #[serde_as(deserialize_as = "DefaultOnError")]
3495 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3496 #[serde(default)]
3497 #[serde(rename = "_meta")]
3498 pub meta: Option<Meta>,
3499 }
3500}
3501
3502#[cfg(feature = "unstable_llm_providers")]
3503impl ListProvidersRequest {
3504 #[must_use]
3506 pub fn new() -> Self {
3507 Self::default()
3508 }
3509
3510 #[must_use]
3516 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3517 self.meta = meta.into_option();
3518 self
3519 }
3520}
3521
3522#[cfg(feature = "unstable_llm_providers")]
3528#[serde_as]
3529#[skip_serializing_none]
3530#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3531#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3532#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_LIST_METHOD_NAME)))]
3533#[serde(rename_all = "camelCase")]
3534#[non_exhaustive]
3535pub struct ListProvidersResponse {
3536 pub providers: Vec<ProviderInfo>,
3538 #[serde_as(deserialize_as = "DefaultOnError")]
3544 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3545 #[serde(default)]
3546 #[serde(rename = "_meta")]
3547 pub meta: Option<Meta>,
3548}
3549
3550#[cfg(feature = "unstable_llm_providers")]
3551impl ListProvidersResponse {
3552 #[must_use]
3554 pub fn new(providers: Vec<ProviderInfo>) -> Self {
3555 Self {
3556 providers,
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_llm_providers")]
3581#[serde_as]
3582#[skip_serializing_none]
3583#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3584#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
3585#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_SET_METHOD_NAME)))]
3586#[serde(rename_all = "camelCase")]
3587#[non_exhaustive]
3588pub struct SetProviderRequest {
3589 pub provider_id: ProviderId,
3591 pub api_type: LlmProtocol,
3593 pub base_url: String,
3595 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
3598 pub headers: HashMap<String, String>,
3599 #[serde_as(deserialize_as = "DefaultOnError")]
3605 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3606 #[serde(default)]
3607 #[serde(rename = "_meta")]
3608 pub meta: Option<Meta>,
3609}
3610
3611#[cfg(feature = "unstable_llm_providers")]
3612impl SetProviderRequest {
3613 #[must_use]
3615 pub fn new(
3616 provider_id: impl Into<ProviderId>,
3617 api_type: LlmProtocol,
3618 base_url: impl Into<String>,
3619 ) -> Self {
3620 Self {
3621 provider_id: provider_id.into(),
3622 api_type,
3623 base_url: base_url.into(),
3624 headers: HashMap::new(),
3625 meta: None,
3626 }
3627 }
3628
3629 #[must_use]
3632 pub fn headers(mut self, headers: HashMap<String, String>) -> Self {
3633 self.headers = headers;
3634 self
3635 }
3636
3637 #[must_use]
3643 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3644 self.meta = meta.into_option();
3645 self
3646 }
3647}
3648
3649#[cfg(feature = "unstable_llm_providers")]
3650crate::serde_util::default_on_null! {
3651 #[serde_as]
3657 #[skip_serializing_none]
3658 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3659 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
3660 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_SET_METHOD_NAME)))]
3661 #[serde(rename_all = "camelCase")]
3662 #[non_exhaustive]
3663 pub struct SetProviderResponse {
3664 #[serde_as(deserialize_as = "DefaultOnError")]
3670 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3671 #[serde(default)]
3672 #[serde(rename = "_meta")]
3673 pub meta: Option<Meta>,
3674 }
3675}
3676
3677#[cfg(feature = "unstable_llm_providers")]
3678impl SetProviderResponse {
3679 #[must_use]
3681 pub fn new() -> Self {
3682 Self::default()
3683 }
3684
3685 #[must_use]
3691 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3692 self.meta = meta.into_option();
3693 self
3694 }
3695}
3696
3697#[cfg(feature = "unstable_llm_providers")]
3703#[serde_as]
3704#[skip_serializing_none]
3705#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3706#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3707#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_DISABLE_METHOD_NAME)))]
3708#[serde(rename_all = "camelCase")]
3709#[non_exhaustive]
3710pub struct DisableProviderRequest {
3711 pub provider_id: ProviderId,
3713 #[serde_as(deserialize_as = "DefaultOnError")]
3719 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3720 #[serde(default)]
3721 #[serde(rename = "_meta")]
3722 pub meta: Option<Meta>,
3723}
3724
3725#[cfg(feature = "unstable_llm_providers")]
3726impl DisableProviderRequest {
3727 #[must_use]
3729 pub fn new(provider_id: impl Into<ProviderId>) -> Self {
3730 Self {
3731 provider_id: provider_id.into(),
3732 meta: None,
3733 }
3734 }
3735
3736 #[must_use]
3742 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3743 self.meta = meta.into_option();
3744 self
3745 }
3746}
3747
3748#[cfg(feature = "unstable_llm_providers")]
3749crate::serde_util::default_on_null! {
3750 #[serde_as]
3756 #[skip_serializing_none]
3757 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3758 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
3759 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_DISABLE_METHOD_NAME)))]
3760 #[serde(rename_all = "camelCase")]
3761 #[non_exhaustive]
3762 pub struct DisableProviderResponse {
3763 #[serde_as(deserialize_as = "DefaultOnError")]
3769 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3770 #[serde(default)]
3771 #[serde(rename = "_meta")]
3772 pub meta: Option<Meta>,
3773 }
3774}
3775
3776#[cfg(feature = "unstable_llm_providers")]
3777impl DisableProviderResponse {
3778 #[must_use]
3780 pub fn new() -> Self {
3781 Self::default()
3782 }
3783
3784 #[must_use]
3790 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3791 self.meta = meta.into_option();
3792 self
3793 }
3794}
3795
3796#[serde_as]
3805#[skip_serializing_none]
3806#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3807#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3808#[serde(rename_all = "camelCase")]
3809#[non_exhaustive]
3810pub struct AgentCapabilities {
3811 #[serde_as(deserialize_as = "DefaultOnError")]
3813 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3814 #[serde(default)]
3815 pub load_session: bool,
3816 #[serde_as(deserialize_as = "DefaultOnError")]
3818 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3819 #[serde(default)]
3820 pub prompt_capabilities: PromptCapabilities,
3821 #[serde_as(deserialize_as = "DefaultOnError")]
3823 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3824 #[serde(default)]
3825 pub mcp_capabilities: McpCapabilities,
3826 #[serde_as(deserialize_as = "DefaultOnError")]
3828 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3829 #[serde(default)]
3830 pub session_capabilities: SessionCapabilities,
3831 #[serde_as(deserialize_as = "DefaultOnError")]
3833 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3834 #[serde(default)]
3835 pub auth: AgentAuthCapabilities,
3836 #[cfg(feature = "unstable_llm_providers")]
3845 #[serde_as(deserialize_as = "DefaultOnError")]
3846 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3847 #[serde(default)]
3848 pub providers: Option<ProvidersCapabilities>,
3849 #[cfg(feature = "unstable_nes")]
3858 #[serde_as(deserialize_as = "DefaultOnError")]
3859 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3860 #[serde(default)]
3861 pub nes: Option<NesCapabilities>,
3862 #[cfg(feature = "unstable_nes")]
3868 #[serde_as(deserialize_as = "DefaultOnError")]
3869 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3870 #[serde(default)]
3871 pub position_encoding: Option<PositionEncodingKind>,
3872 #[serde_as(deserialize_as = "DefaultOnError")]
3878 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3879 #[serde(default)]
3880 #[serde(rename = "_meta")]
3881 pub meta: Option<Meta>,
3882}
3883
3884impl AgentCapabilities {
3885 #[must_use]
3887 pub fn new() -> Self {
3888 Self::default()
3889 }
3890
3891 #[must_use]
3893 pub fn load_session(mut self, load_session: bool) -> Self {
3894 self.load_session = load_session;
3895 self
3896 }
3897
3898 #[must_use]
3900 pub fn prompt_capabilities(mut self, prompt_capabilities: PromptCapabilities) -> Self {
3901 self.prompt_capabilities = prompt_capabilities;
3902 self
3903 }
3904
3905 #[must_use]
3907 pub fn mcp_capabilities(mut self, mcp_capabilities: McpCapabilities) -> Self {
3908 self.mcp_capabilities = mcp_capabilities;
3909 self
3910 }
3911
3912 #[must_use]
3914 pub fn session_capabilities(mut self, session_capabilities: SessionCapabilities) -> Self {
3915 self.session_capabilities = session_capabilities;
3916 self
3917 }
3918
3919 #[must_use]
3921 pub fn auth(mut self, auth: AgentAuthCapabilities) -> Self {
3922 self.auth = auth;
3923 self
3924 }
3925
3926 #[cfg(feature = "unstable_llm_providers")]
3932 #[must_use]
3933 pub fn providers(mut self, providers: impl IntoOption<ProvidersCapabilities>) -> Self {
3934 self.providers = providers.into_option();
3935 self
3936 }
3937
3938 #[cfg(feature = "unstable_nes")]
3944 #[must_use]
3945 pub fn nes(mut self, nes: impl IntoOption<NesCapabilities>) -> Self {
3946 self.nes = nes.into_option();
3947 self
3948 }
3949
3950 #[cfg(feature = "unstable_nes")]
3954 #[must_use]
3955 pub fn position_encoding(
3956 mut self,
3957 position_encoding: impl IntoOption<PositionEncodingKind>,
3958 ) -> Self {
3959 self.position_encoding = position_encoding.into_option();
3960 self
3961 }
3962
3963 #[must_use]
3969 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3970 self.meta = meta.into_option();
3971 self
3972 }
3973}
3974
3975#[cfg(feature = "unstable_llm_providers")]
3983#[serde_as]
3984#[skip_serializing_none]
3985#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3986#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3987#[non_exhaustive]
3988pub struct ProvidersCapabilities {
3989 #[serde_as(deserialize_as = "DefaultOnError")]
3995 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3996 #[serde(default)]
3997 #[serde(rename = "_meta")]
3998 pub meta: Option<Meta>,
3999}
4000
4001#[cfg(feature = "unstable_llm_providers")]
4002impl ProvidersCapabilities {
4003 #[must_use]
4005 pub fn new() -> Self {
4006 Self::default()
4007 }
4008
4009 #[must_use]
4015 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4016 self.meta = meta.into_option();
4017 self
4018 }
4019}
4020
4021#[serde_as]
4031#[skip_serializing_none]
4032#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4033#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4034#[serde(rename_all = "camelCase")]
4035#[non_exhaustive]
4036pub struct SessionCapabilities {
4037 #[serde_as(deserialize_as = "DefaultOnError")]
4042 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4043 #[serde(default)]
4044 pub list: Option<SessionListCapabilities>,
4045 #[serde_as(deserialize_as = "DefaultOnError")]
4050 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4051 #[serde(default)]
4052 pub delete: Option<SessionDeleteCapabilities>,
4053 #[serde_as(deserialize_as = "DefaultOnError")]
4063 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4064 #[serde(default)]
4065 pub additional_directories: Option<SessionAdditionalDirectoriesCapabilities>,
4066 #[cfg(feature = "unstable_session_fork")]
4075 #[serde_as(deserialize_as = "DefaultOnError")]
4076 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4077 #[serde(default)]
4078 pub fork: Option<SessionForkCapabilities>,
4079 #[serde_as(deserialize_as = "DefaultOnError")]
4084 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4085 #[serde(default)]
4086 pub resume: Option<SessionResumeCapabilities>,
4087 #[serde_as(deserialize_as = "DefaultOnError")]
4092 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4093 #[serde(default)]
4094 pub close: Option<SessionCloseCapabilities>,
4095 #[serde_as(deserialize_as = "DefaultOnError")]
4101 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4102 #[serde(default)]
4103 #[serde(rename = "_meta")]
4104 pub meta: Option<Meta>,
4105}
4106
4107impl SessionCapabilities {
4108 #[must_use]
4110 pub fn new() -> Self {
4111 Self::default()
4112 }
4113
4114 #[must_use]
4119 pub fn list(mut self, list: impl IntoOption<SessionListCapabilities>) -> Self {
4120 self.list = list.into_option();
4121 self
4122 }
4123
4124 #[must_use]
4129 pub fn delete(mut self, delete: impl IntoOption<SessionDeleteCapabilities>) -> Self {
4130 self.delete = delete.into_option();
4131 self
4132 }
4133
4134 #[must_use]
4144 pub fn additional_directories(
4145 mut self,
4146 additional_directories: impl IntoOption<SessionAdditionalDirectoriesCapabilities>,
4147 ) -> Self {
4148 self.additional_directories = additional_directories.into_option();
4149 self
4150 }
4151
4152 #[cfg(feature = "unstable_session_fork")]
4153 #[must_use]
4158 pub fn fork(mut self, fork: impl IntoOption<SessionForkCapabilities>) -> Self {
4159 self.fork = fork.into_option();
4160 self
4161 }
4162
4163 #[must_use]
4168 pub fn resume(mut self, resume: impl IntoOption<SessionResumeCapabilities>) -> Self {
4169 self.resume = resume.into_option();
4170 self
4171 }
4172
4173 #[must_use]
4178 pub fn close(mut self, close: impl IntoOption<SessionCloseCapabilities>) -> Self {
4179 self.close = close.into_option();
4180 self
4181 }
4182
4183 #[must_use]
4189 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4190 self.meta = meta.into_option();
4191 self
4192 }
4193}
4194
4195#[serde_as]
4199#[skip_serializing_none]
4200#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4201#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4202#[non_exhaustive]
4203pub struct SessionListCapabilities {
4204 #[serde_as(deserialize_as = "DefaultOnError")]
4210 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4211 #[serde(default)]
4212 #[serde(rename = "_meta")]
4213 pub meta: Option<Meta>,
4214}
4215
4216impl SessionListCapabilities {
4217 #[must_use]
4219 pub fn new() -> Self {
4220 Self::default()
4221 }
4222
4223 #[must_use]
4229 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4230 self.meta = meta.into_option();
4231 self
4232 }
4233}
4234
4235#[serde_as]
4239#[skip_serializing_none]
4240#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4241#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4242#[non_exhaustive]
4243pub struct SessionDeleteCapabilities {
4244 #[serde_as(deserialize_as = "DefaultOnError")]
4250 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4251 #[serde(default)]
4252 #[serde(rename = "_meta")]
4253 pub meta: Option<Meta>,
4254}
4255
4256impl SessionDeleteCapabilities {
4257 #[must_use]
4259 pub fn new() -> Self {
4260 Self::default()
4261 }
4262
4263 #[must_use]
4269 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4270 self.meta = meta.into_option();
4271 self
4272 }
4273}
4274
4275#[serde_as]
4282#[skip_serializing_none]
4283#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4284#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4285#[non_exhaustive]
4286pub struct SessionAdditionalDirectoriesCapabilities {
4287 #[serde_as(deserialize_as = "DefaultOnError")]
4293 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4294 #[serde(default)]
4295 #[serde(rename = "_meta")]
4296 pub meta: Option<Meta>,
4297}
4298
4299impl SessionAdditionalDirectoriesCapabilities {
4300 #[must_use]
4302 pub fn new() -> Self {
4303 Self::default()
4304 }
4305
4306 #[must_use]
4312 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4313 self.meta = meta.into_option();
4314 self
4315 }
4316}
4317
4318#[cfg(feature = "unstable_session_fork")]
4326#[serde_as]
4327#[skip_serializing_none]
4328#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4329#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4330#[non_exhaustive]
4331pub struct SessionForkCapabilities {
4332 #[serde_as(deserialize_as = "DefaultOnError")]
4338 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4339 #[serde(default)]
4340 #[serde(rename = "_meta")]
4341 pub meta: Option<Meta>,
4342}
4343
4344#[cfg(feature = "unstable_session_fork")]
4345impl SessionForkCapabilities {
4346 #[must_use]
4348 pub fn new() -> Self {
4349 Self::default()
4350 }
4351
4352 #[must_use]
4358 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4359 self.meta = meta.into_option();
4360 self
4361 }
4362}
4363
4364#[serde_as]
4368#[skip_serializing_none]
4369#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4370#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4371#[non_exhaustive]
4372pub struct SessionResumeCapabilities {
4373 #[serde_as(deserialize_as = "DefaultOnError")]
4379 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4380 #[serde(default)]
4381 #[serde(rename = "_meta")]
4382 pub meta: Option<Meta>,
4383}
4384
4385impl SessionResumeCapabilities {
4386 #[must_use]
4388 pub fn new() -> Self {
4389 Self::default()
4390 }
4391
4392 #[must_use]
4398 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4399 self.meta = meta.into_option();
4400 self
4401 }
4402}
4403
4404#[serde_as]
4408#[skip_serializing_none]
4409#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4410#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4411#[non_exhaustive]
4412pub struct SessionCloseCapabilities {
4413 #[serde_as(deserialize_as = "DefaultOnError")]
4419 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4420 #[serde(default)]
4421 #[serde(rename = "_meta")]
4422 pub meta: Option<Meta>,
4423}
4424
4425impl SessionCloseCapabilities {
4426 #[must_use]
4428 pub fn new() -> Self {
4429 Self::default()
4430 }
4431
4432 #[must_use]
4438 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4439 self.meta = meta.into_option();
4440 self
4441 }
4442}
4443
4444#[serde_as]
4457#[skip_serializing_none]
4458#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4459#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4460#[serde(rename_all = "camelCase")]
4461#[non_exhaustive]
4462pub struct PromptCapabilities {
4463 #[serde_as(deserialize_as = "DefaultOnError")]
4465 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4466 #[serde(default)]
4467 pub image: bool,
4468 #[serde_as(deserialize_as = "DefaultOnError")]
4470 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4471 #[serde(default)]
4472 pub audio: bool,
4473 #[serde_as(deserialize_as = "DefaultOnError")]
4478 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4479 #[serde(default)]
4480 pub embedded_context: bool,
4481 #[serde_as(deserialize_as = "DefaultOnError")]
4487 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4488 #[serde(default)]
4489 #[serde(rename = "_meta")]
4490 pub meta: Option<Meta>,
4491}
4492
4493impl PromptCapabilities {
4494 #[must_use]
4496 pub fn new() -> Self {
4497 Self::default()
4498 }
4499
4500 #[must_use]
4502 pub fn image(mut self, image: bool) -> Self {
4503 self.image = image;
4504 self
4505 }
4506
4507 #[must_use]
4509 pub fn audio(mut self, audio: bool) -> Self {
4510 self.audio = audio;
4511 self
4512 }
4513
4514 #[must_use]
4519 pub fn embedded_context(mut self, embedded_context: bool) -> Self {
4520 self.embedded_context = embedded_context;
4521 self
4522 }
4523
4524 #[must_use]
4530 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4531 self.meta = meta.into_option();
4532 self
4533 }
4534}
4535
4536#[serde_as]
4538#[skip_serializing_none]
4539#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4540#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4541#[serde(rename_all = "camelCase")]
4542#[non_exhaustive]
4543pub struct McpCapabilities {
4544 #[serde_as(deserialize_as = "DefaultOnError")]
4546 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4547 #[serde(default)]
4548 pub http: bool,
4549 #[serde_as(deserialize_as = "DefaultOnError")]
4551 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4552 #[serde(default)]
4553 pub sse: bool,
4554 #[cfg(feature = "unstable_mcp_over_acp")]
4560 #[serde_as(deserialize_as = "DefaultOnError")]
4561 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4562 #[serde(default)]
4563 pub acp: bool,
4564 #[serde_as(deserialize_as = "DefaultOnError")]
4570 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4571 #[serde(default)]
4572 #[serde(rename = "_meta")]
4573 pub meta: Option<Meta>,
4574}
4575
4576impl McpCapabilities {
4577 #[must_use]
4579 pub fn new() -> Self {
4580 Self::default()
4581 }
4582
4583 #[must_use]
4585 pub fn http(mut self, http: bool) -> Self {
4586 self.http = http;
4587 self
4588 }
4589
4590 #[must_use]
4592 pub fn sse(mut self, sse: bool) -> Self {
4593 self.sse = sse;
4594 self
4595 }
4596
4597 #[cfg(feature = "unstable_mcp_over_acp")]
4603 #[must_use]
4604 pub fn acp(mut self, acp: bool) -> Self {
4605 self.acp = acp;
4606 self
4607 }
4608
4609 #[must_use]
4615 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4616 self.meta = meta.into_option();
4617 self
4618 }
4619}
4620
4621#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4627#[non_exhaustive]
4628pub struct AgentMethodNames {
4629 pub initialize: &'static str,
4631 pub authenticate: &'static str,
4633 #[cfg(feature = "unstable_llm_providers")]
4635 pub providers_list: &'static str,
4636 #[cfg(feature = "unstable_llm_providers")]
4638 pub providers_set: &'static str,
4639 #[cfg(feature = "unstable_llm_providers")]
4641 pub providers_disable: &'static str,
4642 pub session_new: &'static str,
4644 pub session_load: &'static str,
4646 pub session_set_mode: &'static str,
4648 pub session_set_config_option: &'static str,
4650 pub session_prompt: &'static str,
4652 pub session_cancel: &'static str,
4654 #[cfg(feature = "unstable_mcp_over_acp")]
4656 pub mcp_message: &'static str,
4657 pub session_list: &'static str,
4659 pub session_delete: &'static str,
4661 #[cfg(feature = "unstable_session_fork")]
4663 pub session_fork: &'static str,
4664 pub session_resume: &'static str,
4666 pub session_close: &'static str,
4668 pub logout: &'static str,
4670 #[cfg(feature = "unstable_nes")]
4672 pub nes_start: &'static str,
4673 #[cfg(feature = "unstable_nes")]
4675 pub nes_suggest: &'static str,
4676 #[cfg(feature = "unstable_nes")]
4678 pub nes_accept: &'static str,
4679 #[cfg(feature = "unstable_nes")]
4681 pub nes_reject: &'static str,
4682 #[cfg(feature = "unstable_nes")]
4684 pub nes_close: &'static str,
4685 #[cfg(feature = "unstable_nes")]
4687 pub document_did_open: &'static str,
4688 #[cfg(feature = "unstable_nes")]
4690 pub document_did_change: &'static str,
4691 #[cfg(feature = "unstable_nes")]
4693 pub document_did_close: &'static str,
4694 #[cfg(feature = "unstable_nes")]
4696 pub document_did_save: &'static str,
4697 #[cfg(feature = "unstable_nes")]
4699 pub document_did_focus: &'static str,
4700}
4701
4702pub const AGENT_METHOD_NAMES: AgentMethodNames = AgentMethodNames {
4704 initialize: INITIALIZE_METHOD_NAME,
4705 authenticate: AUTHENTICATE_METHOD_NAME,
4706 #[cfg(feature = "unstable_llm_providers")]
4707 providers_list: PROVIDERS_LIST_METHOD_NAME,
4708 #[cfg(feature = "unstable_llm_providers")]
4709 providers_set: PROVIDERS_SET_METHOD_NAME,
4710 #[cfg(feature = "unstable_llm_providers")]
4711 providers_disable: PROVIDERS_DISABLE_METHOD_NAME,
4712 session_new: SESSION_NEW_METHOD_NAME,
4713 session_load: SESSION_LOAD_METHOD_NAME,
4714 session_set_mode: SESSION_SET_MODE_METHOD_NAME,
4715 session_set_config_option: SESSION_SET_CONFIG_OPTION_METHOD_NAME,
4716 session_prompt: SESSION_PROMPT_METHOD_NAME,
4717 session_cancel: SESSION_CANCEL_METHOD_NAME,
4718 #[cfg(feature = "unstable_mcp_over_acp")]
4719 mcp_message: MCP_MESSAGE_METHOD_NAME,
4720 session_list: SESSION_LIST_METHOD_NAME,
4721 session_delete: SESSION_DELETE_METHOD_NAME,
4722 #[cfg(feature = "unstable_session_fork")]
4723 session_fork: SESSION_FORK_METHOD_NAME,
4724 session_resume: SESSION_RESUME_METHOD_NAME,
4725 session_close: SESSION_CLOSE_METHOD_NAME,
4726 logout: LOGOUT_METHOD_NAME,
4727 #[cfg(feature = "unstable_nes")]
4728 nes_start: NES_START_METHOD_NAME,
4729 #[cfg(feature = "unstable_nes")]
4730 nes_suggest: NES_SUGGEST_METHOD_NAME,
4731 #[cfg(feature = "unstable_nes")]
4732 nes_accept: NES_ACCEPT_METHOD_NAME,
4733 #[cfg(feature = "unstable_nes")]
4734 nes_reject: NES_REJECT_METHOD_NAME,
4735 #[cfg(feature = "unstable_nes")]
4736 nes_close: NES_CLOSE_METHOD_NAME,
4737 #[cfg(feature = "unstable_nes")]
4738 document_did_open: DOCUMENT_DID_OPEN_METHOD_NAME,
4739 #[cfg(feature = "unstable_nes")]
4740 document_did_change: DOCUMENT_DID_CHANGE_METHOD_NAME,
4741 #[cfg(feature = "unstable_nes")]
4742 document_did_close: DOCUMENT_DID_CLOSE_METHOD_NAME,
4743 #[cfg(feature = "unstable_nes")]
4744 document_did_save: DOCUMENT_DID_SAVE_METHOD_NAME,
4745 #[cfg(feature = "unstable_nes")]
4746 document_did_focus: DOCUMENT_DID_FOCUS_METHOD_NAME,
4747};
4748
4749pub(crate) const INITIALIZE_METHOD_NAME: &str = "initialize";
4751pub(crate) const AUTHENTICATE_METHOD_NAME: &str = "authenticate";
4753#[cfg(feature = "unstable_llm_providers")]
4755pub(crate) const PROVIDERS_LIST_METHOD_NAME: &str = "providers/list";
4756#[cfg(feature = "unstable_llm_providers")]
4758pub(crate) const PROVIDERS_SET_METHOD_NAME: &str = "providers/set";
4759#[cfg(feature = "unstable_llm_providers")]
4761pub(crate) const PROVIDERS_DISABLE_METHOD_NAME: &str = "providers/disable";
4762pub(crate) const SESSION_NEW_METHOD_NAME: &str = "session/new";
4764pub(crate) const SESSION_LOAD_METHOD_NAME: &str = "session/load";
4766pub(crate) const SESSION_SET_MODE_METHOD_NAME: &str = "session/set_mode";
4768pub(crate) const SESSION_SET_CONFIG_OPTION_METHOD_NAME: &str = "session/set_config_option";
4770pub(crate) const SESSION_PROMPT_METHOD_NAME: &str = "session/prompt";
4772pub(crate) const SESSION_CANCEL_METHOD_NAME: &str = "session/cancel";
4774pub(crate) const SESSION_LIST_METHOD_NAME: &str = "session/list";
4776pub(crate) const SESSION_DELETE_METHOD_NAME: &str = "session/delete";
4778#[cfg(feature = "unstable_session_fork")]
4780pub(crate) const SESSION_FORK_METHOD_NAME: &str = "session/fork";
4781pub(crate) const SESSION_RESUME_METHOD_NAME: &str = "session/resume";
4783pub(crate) const SESSION_CLOSE_METHOD_NAME: &str = "session/close";
4785pub(crate) const LOGOUT_METHOD_NAME: &str = "logout";
4787
4788#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4795#[derive(Clone, Debug, Serialize, Deserialize)]
4796#[serde(untagged)]
4797#[cfg_attr(feature = "schemars", schemars(inline))]
4798#[non_exhaustive]
4799#[allow(clippy::large_enum_variant)]
4800pub enum ClientRequest {
4801 InitializeRequest(InitializeRequest),
4812 AuthenticateRequest(AuthenticateRequest),
4823 #[cfg(feature = "unstable_llm_providers")]
4829 ListProvidersRequest(ListProvidersRequest),
4830 #[cfg(feature = "unstable_llm_providers")]
4836 SetProviderRequest(SetProviderRequest),
4837 #[cfg(feature = "unstable_llm_providers")]
4843 DisableProviderRequest(DisableProviderRequest),
4844 LogoutRequest(LogoutRequest),
4849 NewSessionRequest(NewSessionRequest),
4862 LoadSessionRequest(LoadSessionRequest),
4873 ListSessionsRequest(ListSessionsRequest),
4879 DeleteSessionRequest(DeleteSessionRequest),
4883 #[cfg(feature = "unstable_session_fork")]
4884 ForkSessionRequest(ForkSessionRequest),
4896 ResumeSessionRequest(ResumeSessionRequest),
4903 CloseSessionRequest(CloseSessionRequest),
4910 SetSessionModeRequest(SetSessionModeRequest),
4924 SetSessionConfigOptionRequest(SetSessionConfigOptionRequest),
4926 PromptRequest(PromptRequest),
4938 #[cfg(feature = "unstable_nes")]
4939 StartNesRequest(StartNesRequest),
4945 #[cfg(feature = "unstable_nes")]
4946 SuggestNesRequest(SuggestNesRequest),
4952 #[cfg(feature = "unstable_nes")]
4953 CloseNesRequest(CloseNesRequest),
4962 ExtMethodRequest(ExtRequest),
4969}
4970
4971impl ClientRequest {
4972 #[must_use]
4974 pub fn method(&self) -> &str {
4975 match self {
4976 Self::InitializeRequest(_) => AGENT_METHOD_NAMES.initialize,
4977 Self::AuthenticateRequest(_) => AGENT_METHOD_NAMES.authenticate,
4978 #[cfg(feature = "unstable_llm_providers")]
4979 Self::ListProvidersRequest(_) => AGENT_METHOD_NAMES.providers_list,
4980 #[cfg(feature = "unstable_llm_providers")]
4981 Self::SetProviderRequest(_) => AGENT_METHOD_NAMES.providers_set,
4982 #[cfg(feature = "unstable_llm_providers")]
4983 Self::DisableProviderRequest(_) => AGENT_METHOD_NAMES.providers_disable,
4984 Self::LogoutRequest(_) => AGENT_METHOD_NAMES.logout,
4985 Self::NewSessionRequest(_) => AGENT_METHOD_NAMES.session_new,
4986 Self::LoadSessionRequest(_) => AGENT_METHOD_NAMES.session_load,
4987 Self::ListSessionsRequest(_) => AGENT_METHOD_NAMES.session_list,
4988 Self::DeleteSessionRequest(_) => AGENT_METHOD_NAMES.session_delete,
4989 #[cfg(feature = "unstable_session_fork")]
4990 Self::ForkSessionRequest(_) => AGENT_METHOD_NAMES.session_fork,
4991 Self::ResumeSessionRequest(_) => AGENT_METHOD_NAMES.session_resume,
4992 Self::CloseSessionRequest(_) => AGENT_METHOD_NAMES.session_close,
4993 Self::SetSessionModeRequest(_) => AGENT_METHOD_NAMES.session_set_mode,
4994 Self::SetSessionConfigOptionRequest(_) => AGENT_METHOD_NAMES.session_set_config_option,
4995 Self::PromptRequest(_) => AGENT_METHOD_NAMES.session_prompt,
4996 #[cfg(feature = "unstable_nes")]
4997 Self::StartNesRequest(_) => AGENT_METHOD_NAMES.nes_start,
4998 #[cfg(feature = "unstable_nes")]
4999 Self::SuggestNesRequest(_) => AGENT_METHOD_NAMES.nes_suggest,
5000 #[cfg(feature = "unstable_nes")]
5001 Self::CloseNesRequest(_) => AGENT_METHOD_NAMES.nes_close,
5002 Self::ExtMethodRequest(ext_request) => &ext_request.method,
5003 }
5004 }
5005}
5006
5007#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5014#[derive(Clone, Debug, Serialize, Deserialize)]
5015#[serde(untagged)]
5016#[cfg_attr(feature = "schemars", schemars(inline))]
5017#[non_exhaustive]
5018#[allow(clippy::large_enum_variant)]
5019pub enum AgentResponse {
5020 InitializeResponse(InitializeResponse),
5022 AuthenticateResponse(#[serde(default)] AuthenticateResponse),
5024 #[cfg(feature = "unstable_llm_providers")]
5026 ListProvidersResponse(ListProvidersResponse),
5027 #[cfg(feature = "unstable_llm_providers")]
5029 SetProviderResponse(#[serde(default)] SetProviderResponse),
5030 #[cfg(feature = "unstable_llm_providers")]
5032 DisableProviderResponse(#[serde(default)] DisableProviderResponse),
5033 LogoutResponse(#[serde(default)] LogoutResponse),
5035 NewSessionResponse(NewSessionResponse),
5037 LoadSessionResponse(#[serde(default)] LoadSessionResponse),
5039 ListSessionsResponse(ListSessionsResponse),
5041 DeleteSessionResponse(#[serde(default)] DeleteSessionResponse),
5043 #[cfg(feature = "unstable_session_fork")]
5045 ForkSessionResponse(ForkSessionResponse),
5046 ResumeSessionResponse(#[serde(default)] ResumeSessionResponse),
5048 CloseSessionResponse(#[serde(default)] CloseSessionResponse),
5050 SetSessionModeResponse(#[serde(default)] SetSessionModeResponse),
5052 SetSessionConfigOptionResponse(SetSessionConfigOptionResponse),
5054 PromptResponse(PromptResponse),
5056 #[cfg(feature = "unstable_nes")]
5058 StartNesResponse(StartNesResponse),
5059 #[cfg(feature = "unstable_nes")]
5061 SuggestNesResponse(SuggestNesResponse),
5062 #[cfg(feature = "unstable_nes")]
5064 CloseNesResponse(#[serde(default)] CloseNesResponse),
5065 ExtMethodResponse(ExtResponse),
5067}
5068
5069#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5076#[derive(Clone, Debug, Serialize, Deserialize)]
5077#[serde(untagged)]
5078#[cfg_attr(feature = "schemars", schemars(inline))]
5079#[non_exhaustive]
5080#[allow(clippy::large_enum_variant)]
5081pub enum ClientNotification {
5082 CancelNotification(CancelNotification),
5094 #[cfg(feature = "unstable_nes")]
5095 DidOpenDocumentNotification(DidOpenDocumentNotification),
5099 #[cfg(feature = "unstable_nes")]
5100 DidChangeDocumentNotification(DidChangeDocumentNotification),
5104 #[cfg(feature = "unstable_nes")]
5105 DidCloseDocumentNotification(DidCloseDocumentNotification),
5109 #[cfg(feature = "unstable_nes")]
5110 DidSaveDocumentNotification(DidSaveDocumentNotification),
5114 #[cfg(feature = "unstable_nes")]
5115 DidFocusDocumentNotification(DidFocusDocumentNotification),
5119 #[cfg(feature = "unstable_nes")]
5120 AcceptNesNotification(AcceptNesNotification),
5124 #[cfg(feature = "unstable_nes")]
5125 RejectNesNotification(RejectNesNotification),
5129 #[cfg(feature = "unstable_mcp_over_acp")]
5135 MessageMcpNotification(MessageMcpNotification),
5136 ExtNotification(ExtNotification),
5143}
5144
5145impl ClientNotification {
5146 #[must_use]
5148 pub fn method(&self) -> &str {
5149 match self {
5150 Self::CancelNotification(_) => AGENT_METHOD_NAMES.session_cancel,
5151 #[cfg(feature = "unstable_nes")]
5152 Self::DidOpenDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_open,
5153 #[cfg(feature = "unstable_nes")]
5154 Self::DidChangeDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_change,
5155 #[cfg(feature = "unstable_nes")]
5156 Self::DidCloseDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_close,
5157 #[cfg(feature = "unstable_nes")]
5158 Self::DidSaveDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_save,
5159 #[cfg(feature = "unstable_nes")]
5160 Self::DidFocusDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_focus,
5161 #[cfg(feature = "unstable_nes")]
5162 Self::AcceptNesNotification(_) => AGENT_METHOD_NAMES.nes_accept,
5163 #[cfg(feature = "unstable_nes")]
5164 Self::RejectNesNotification(_) => AGENT_METHOD_NAMES.nes_reject,
5165 #[cfg(feature = "unstable_mcp_over_acp")]
5166 Self::MessageMcpNotification(_) => AGENT_METHOD_NAMES.mcp_message,
5167 Self::ExtNotification(ext_notification) => &ext_notification.method,
5168 }
5169 }
5170}
5171
5172#[serde_as]
5176#[skip_serializing_none]
5177#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5178#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5179#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_CANCEL_METHOD_NAME)))]
5180#[serde(rename_all = "camelCase")]
5181#[non_exhaustive]
5182pub struct CancelNotification {
5183 pub session_id: SessionId,
5185 #[serde_as(deserialize_as = "DefaultOnError")]
5191 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5192 #[serde(default)]
5193 #[serde(rename = "_meta")]
5194 pub meta: Option<Meta>,
5195}
5196
5197impl CancelNotification {
5198 #[must_use]
5200 pub fn new(session_id: impl Into<SessionId>) -> Self {
5201 Self {
5202 session_id: session_id.into(),
5203 meta: None,
5204 }
5205 }
5206
5207 #[must_use]
5213 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5214 self.meta = meta.into_option();
5215 self
5216 }
5217}
5218
5219#[cfg(test)]
5220mod test_serialization {
5221 use super::*;
5222 use serde_json::json;
5223
5224 fn test_meta() -> Meta {
5225 json!({ "source": "test" }).as_object().unwrap().clone()
5226 }
5227
5228 fn serialized_meta_key_count(value: &impl serde::Serialize) -> usize {
5229 serde_json::to_string(value)
5230 .unwrap()
5231 .matches("\"_meta\"")
5232 .count()
5233 }
5234
5235 #[test]
5236 fn test_initialize_capabilities_default_on_malformed_values() {
5237 let request: InitializeRequest = serde_json::from_value(json!({
5238 "protocolVersion": 1,
5239 "clientCapabilities": false
5240 }))
5241 .unwrap();
5242 assert_eq!(request.client_capabilities, ClientCapabilities::default());
5243
5244 let response: InitializeResponse = serde_json::from_value(json!({
5245 "protocolVersion": 1,
5246 "agentCapabilities": false
5247 }))
5248 .unwrap();
5249 assert_eq!(response.agent_capabilities, AgentCapabilities::default());
5250 }
5251
5252 #[test]
5253 fn test_agent_capabilities_default_on_malformed_values() {
5254 let capabilities: AgentCapabilities = serde_json::from_value(json!({
5255 "loadSession": "yes",
5256 "promptCapabilities": {
5257 "image": "yes",
5258 "audio": true,
5259 "embeddedContext": {}
5260 },
5261 "mcpCapabilities": {
5262 "http": "yes",
5263 "sse": true
5264 },
5265 "sessionCapabilities": false,
5266 "auth": false
5267 }))
5268 .unwrap();
5269
5270 assert!(!capabilities.load_session);
5271 assert!(!capabilities.prompt_capabilities.image);
5272 assert!(capabilities.prompt_capabilities.audio);
5273 assert!(!capabilities.prompt_capabilities.embedded_context);
5274 assert!(!capabilities.mcp_capabilities.http);
5275 assert!(capabilities.mcp_capabilities.sse);
5276 assert_eq!(
5277 capabilities.session_capabilities,
5278 SessionCapabilities::default()
5279 );
5280 assert_eq!(capabilities.auth, AgentAuthCapabilities::default());
5281 }
5282
5283 #[test]
5284 fn test_mcp_server_stdio_serialization() {
5285 let server = McpServer::Stdio(
5286 McpServerStdio::new("test-server", "/usr/bin/server")
5287 .args(vec!["--port".to_string(), "3000".to_string()])
5288 .env(vec![EnvVariable::new("API_KEY", "secret123")]),
5289 );
5290
5291 let json = serde_json::to_value(&server).unwrap();
5292 assert_eq!(
5293 json,
5294 json!({
5295 "name": "test-server",
5296 "command": "/usr/bin/server",
5297 "args": ["--port", "3000"],
5298 "env": [
5299 {
5300 "name": "API_KEY",
5301 "value": "secret123"
5302 }
5303 ]
5304 })
5305 );
5306
5307 let deserialized: McpServer = serde_json::from_value(json).unwrap();
5308 match deserialized {
5309 McpServer::Stdio(McpServerStdio {
5310 name,
5311 command,
5312 args,
5313 env,
5314 meta: _,
5315 }) => {
5316 assert_eq!(name, "test-server");
5317 assert_eq!(command, PathBuf::from("/usr/bin/server"));
5318 assert_eq!(args, vec!["--port", "3000"]);
5319 assert_eq!(env.len(), 1);
5320 assert_eq!(env[0].name, "API_KEY");
5321 assert_eq!(env[0].value, "secret123");
5322 }
5323 _ => panic!("Expected Stdio variant"),
5324 }
5325 }
5326
5327 #[test]
5328 fn test_mcp_server_http_serialization() {
5329 let server = McpServer::Http(
5330 McpServerHttp::new("http-server", "https://api.example.com").headers(vec![
5331 HttpHeader::new("Authorization", "Bearer token123"),
5332 HttpHeader::new("Content-Type", "application/json"),
5333 ]),
5334 );
5335
5336 let json = serde_json::to_value(&server).unwrap();
5337 assert_eq!(
5338 json,
5339 json!({
5340 "type": "http",
5341 "name": "http-server",
5342 "url": "https://api.example.com",
5343 "headers": [
5344 {
5345 "name": "Authorization",
5346 "value": "Bearer token123"
5347 },
5348 {
5349 "name": "Content-Type",
5350 "value": "application/json"
5351 }
5352 ]
5353 })
5354 );
5355
5356 let deserialized: McpServer = serde_json::from_value(json).unwrap();
5357 match deserialized {
5358 McpServer::Http(McpServerHttp {
5359 name,
5360 url,
5361 headers,
5362 meta: _,
5363 }) => {
5364 assert_eq!(name, "http-server");
5365 assert_eq!(url, "https://api.example.com");
5366 assert_eq!(headers.len(), 2);
5367 assert_eq!(headers[0].name, "Authorization");
5368 assert_eq!(headers[0].value, "Bearer token123");
5369 assert_eq!(headers[1].name, "Content-Type");
5370 assert_eq!(headers[1].value, "application/json");
5371 }
5372 _ => panic!("Expected Http variant"),
5373 }
5374 }
5375
5376 #[cfg(feature = "unstable_mcp_over_acp")]
5377 #[test]
5378 fn test_mcp_server_acp_serialization() {
5379 let server = McpServer::Acp(McpServerAcp::new("project-tools", "project-tools-id"));
5380
5381 let json = serde_json::to_value(&server).unwrap();
5382 assert_eq!(
5383 json,
5384 json!({
5385 "type": "acp",
5386 "name": "project-tools",
5387 "serverId": "project-tools-id"
5388 })
5389 );
5390
5391 let deserialized: McpServer = serde_json::from_value(json).unwrap();
5392 match deserialized {
5393 McpServer::Acp(McpServerAcp {
5394 name,
5395 server_id: id,
5396 meta: _,
5397 }) => {
5398 assert_eq!(name, "project-tools");
5399 assert_eq!(id, McpServerAcpId::new("project-tools-id"));
5400 }
5401 _ => panic!("Expected Acp variant"),
5402 }
5403 }
5404
5405 #[cfg(feature = "unstable_mcp_over_acp")]
5406 #[test]
5407 fn test_client_mcp_message_method_names() {
5408 use serde_json::json;
5409
5410 assert_eq!(AGENT_METHOD_NAMES.mcp_message, "mcp/message");
5411
5412 let notification =
5413 MessageMcpNotification::new("server-1", "req-1", "notifications/progress");
5414 assert_eq!(
5415 ClientNotification::MessageMcpNotification(notification.clone()).method(),
5416 "mcp/message"
5417 );
5418 assert_eq!(
5419 serde_json::to_value(notification).unwrap(),
5420 json!({
5421 "serverId": "server-1",
5422 "requestId": "req-1",
5423 "method": "notifications/progress"
5424 })
5425 );
5426 let notification: MessageMcpNotification = serde_json::from_value(json!({
5427 "serverId": "server-1", "requestId": "req-1", "method": "notifications/progress",
5428 "params": null, "_meta": null
5429 }))
5430 .unwrap();
5431 assert_eq!(notification.params, None);
5432 assert_eq!(notification.meta, None);
5433 for key in ["serverId", "requestId", "method"] {
5434 let mut value = json!({"serverId":"server-1", "requestId":"req-1", "method":"notifications/progress"});
5435 value.as_object_mut().unwrap().remove(key);
5436 assert!(serde_json::from_value::<MessageMcpNotification>(value).is_err());
5437 }
5438 }
5439
5440 #[cfg(all(feature = "unstable_mcp_over_acp", feature = "schemars"))]
5441 #[test]
5442 fn test_mcp_server_acp_schema() {
5443 let mcp_server_schema = serde_json::to_value(schemars::schema_for!(McpServer)).unwrap();
5444 assert!(json_contains_entry(
5445 &mcp_server_schema,
5446 "const",
5447 &json!("acp")
5448 ));
5449 assert!(json_contains_entry(
5450 &mcp_server_schema,
5451 "$ref",
5452 &json!("#/$defs/McpServerAcp")
5453 ));
5454
5455 let capabilities_schema =
5456 serde_json::to_value(schemars::schema_for!(McpCapabilities)).unwrap();
5457 assert!(json_contains_key(&capabilities_schema, "acp"));
5458 }
5459
5460 #[cfg(all(feature = "unstable_mcp_over_acp", feature = "schemars"))]
5461 fn json_contains_entry(
5462 value: &serde_json::Value,
5463 key: &str,
5464 expected: &serde_json::Value,
5465 ) -> bool {
5466 match value {
5467 serde_json::Value::Object(map) => {
5468 map.get(key) == Some(expected)
5469 || map
5470 .values()
5471 .any(|value| json_contains_entry(value, key, expected))
5472 }
5473 serde_json::Value::Array(values) => values
5474 .iter()
5475 .any(|value| json_contains_entry(value, key, expected)),
5476 _ => false,
5477 }
5478 }
5479
5480 #[cfg(all(feature = "unstable_mcp_over_acp", feature = "schemars"))]
5481 fn json_contains_key(value: &serde_json::Value, key: &str) -> bool {
5482 match value {
5483 serde_json::Value::Object(map) => {
5484 map.contains_key(key) || map.values().any(|value| json_contains_key(value, key))
5485 }
5486 serde_json::Value::Array(values) => {
5487 values.iter().any(|value| json_contains_key(value, key))
5488 }
5489 _ => false,
5490 }
5491 }
5492
5493 #[test]
5494 fn test_mcp_server_sse_serialization() {
5495 let server = McpServer::Sse(
5496 McpServerSse::new("sse-server", "https://sse.example.com/events")
5497 .headers(vec![HttpHeader::new("X-API-Key", "apikey456")]),
5498 );
5499
5500 let json = serde_json::to_value(&server).unwrap();
5501 assert_eq!(
5502 json,
5503 json!({
5504 "type": "sse",
5505 "name": "sse-server",
5506 "url": "https://sse.example.com/events",
5507 "headers": [
5508 {
5509 "name": "X-API-Key",
5510 "value": "apikey456"
5511 }
5512 ]
5513 })
5514 );
5515
5516 let deserialized: McpServer = serde_json::from_value(json).unwrap();
5517 match deserialized {
5518 McpServer::Sse(McpServerSse {
5519 name,
5520 url,
5521 headers,
5522 meta: _,
5523 }) => {
5524 assert_eq!(name, "sse-server");
5525 assert_eq!(url, "https://sse.example.com/events");
5526 assert_eq!(headers.len(), 1);
5527 assert_eq!(headers[0].name, "X-API-Key");
5528 assert_eq!(headers[0].value, "apikey456");
5529 }
5530 _ => panic!("Expected Sse variant"),
5531 }
5532 }
5533
5534 #[test]
5535 fn test_session_config_option_category_known_variants() {
5536 assert_eq!(
5538 serde_json::to_value(&SessionConfigOptionCategory::Mode).unwrap(),
5539 json!("mode")
5540 );
5541 assert_eq!(
5542 serde_json::to_value(&SessionConfigOptionCategory::Model).unwrap(),
5543 json!("model")
5544 );
5545 assert_eq!(
5546 serde_json::to_value(&SessionConfigOptionCategory::ModelConfig).unwrap(),
5547 json!("model_config")
5548 );
5549 assert_eq!(
5550 serde_json::to_value(&SessionConfigOptionCategory::ThoughtLevel).unwrap(),
5551 json!("thought_level")
5552 );
5553
5554 assert_eq!(
5556 serde_json::from_str::<SessionConfigOptionCategory>("\"mode\"").unwrap(),
5557 SessionConfigOptionCategory::Mode
5558 );
5559 assert_eq!(
5560 serde_json::from_str::<SessionConfigOptionCategory>("\"model\"").unwrap(),
5561 SessionConfigOptionCategory::Model
5562 );
5563 assert_eq!(
5564 serde_json::from_str::<SessionConfigOptionCategory>("\"model_config\"").unwrap(),
5565 SessionConfigOptionCategory::ModelConfig
5566 );
5567 assert_eq!(
5568 serde_json::from_str::<SessionConfigOptionCategory>("\"thought_level\"").unwrap(),
5569 SessionConfigOptionCategory::ThoughtLevel
5570 );
5571 }
5572
5573 #[test]
5574 fn test_session_config_option_category_unknown_variants() {
5575 let unknown: SessionConfigOptionCategory =
5577 serde_json::from_str("\"some_future_category\"").unwrap();
5578 assert_eq!(
5579 unknown,
5580 SessionConfigOptionCategory::Other("some_future_category".to_string())
5581 );
5582
5583 let json = serde_json::to_value(&unknown).unwrap();
5585 assert_eq!(json, json!("some_future_category"));
5586 }
5587
5588 #[test]
5589 fn test_session_config_option_category_custom_categories() {
5590 let custom: SessionConfigOptionCategory =
5592 serde_json::from_str("\"_my_custom_category\"").unwrap();
5593 assert_eq!(
5594 custom,
5595 SessionConfigOptionCategory::Other("_my_custom_category".to_string())
5596 );
5597
5598 let json = serde_json::to_value(&custom).unwrap();
5600 assert_eq!(json, json!("_my_custom_category"));
5601
5602 let deserialized: SessionConfigOptionCategory = serde_json::from_value(json).unwrap();
5604 assert_eq!(
5605 deserialized,
5606 SessionConfigOptionCategory::Other("_my_custom_category".to_string()),
5607 );
5608 }
5609
5610 #[test]
5611 fn test_auth_method_agent_serialization() {
5612 let method = AuthMethod::Agent(AuthMethodAgent::new("default-auth", "Default Auth"));
5613
5614 let json = serde_json::to_value(&method).unwrap();
5615 assert_eq!(
5616 json,
5617 json!({
5618 "id": "default-auth",
5619 "name": "Default Auth"
5620 })
5621 );
5622 assert!(!json.as_object().unwrap().contains_key("description"));
5624 assert!(!json.as_object().unwrap().contains_key("type"));
5626
5627 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5628 match deserialized {
5629 AuthMethod::Agent(AuthMethodAgent { id, name, .. }) => {
5630 assert_eq!(id.0.as_ref(), "default-auth");
5631 assert_eq!(name, "Default Auth");
5632 }
5633 _ => panic!("Expected Agent variant"),
5634 }
5635 }
5636
5637 #[test]
5638 fn test_auth_method_explicit_agent_deserialization() {
5639 let json = json!({
5641 "id": "agent-auth",
5642 "name": "Agent Auth",
5643 "type": "agent"
5644 });
5645
5646 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5647 assert!(matches!(deserialized, AuthMethod::Agent(_)));
5648 }
5649
5650 #[test]
5651 fn test_session_delete_serialization() {
5652 assert_eq!(AGENT_METHOD_NAMES.session_delete, "session/delete");
5653 assert_eq!(
5654 ClientRequest::DeleteSessionRequest(DeleteSessionRequest::new("sess_abc123")).method(),
5655 "session/delete"
5656 );
5657 assert_eq!(
5658 serde_json::to_value(DeleteSessionRequest::new("sess_abc123")).unwrap(),
5659 json!({
5660 "sessionId": "sess_abc123"
5661 })
5662 );
5663 assert_eq!(
5664 serde_json::to_value(DeleteSessionResponse::new()).unwrap(),
5665 json!({})
5666 );
5667 assert_eq!(
5668 serde_json::to_value(
5669 SessionCapabilities::new().delete(SessionDeleteCapabilities::new())
5670 )
5671 .unwrap(),
5672 json!({
5673 "delete": {}
5674 })
5675 );
5676 }
5677 #[test]
5678 fn test_session_additional_directories_serialization() {
5679 assert_eq!(
5680 serde_json::to_value(NewSessionRequest::new("/home/user/project")).unwrap(),
5681 json!({
5682 "cwd": "/home/user/project",
5683 "mcpServers": []
5684 })
5685 );
5686 assert_eq!(
5687 serde_json::to_value(
5688 NewSessionRequest::new("/home/user/project").additional_directories(vec![
5689 PathBuf::from("/home/user/shared-lib"),
5690 PathBuf::from("/home/user/product-docs"),
5691 ])
5692 )
5693 .unwrap(),
5694 json!({
5695 "cwd": "/home/user/project",
5696 "additionalDirectories": [
5697 "/home/user/shared-lib",
5698 "/home/user/product-docs"
5699 ],
5700 "mcpServers": []
5701 })
5702 );
5703 assert_eq!(
5704 serde_json::to_value(SessionInfo::new("sess_abc123", "/home/user/project")).unwrap(),
5705 json!({
5706 "sessionId": "sess_abc123",
5707 "cwd": "/home/user/project"
5708 })
5709 );
5710 assert_eq!(
5711 serde_json::to_value(
5712 SessionInfo::new("sess_abc123", "/home/user/project").additional_directories(vec![
5713 PathBuf::from("/home/user/shared-lib"),
5714 PathBuf::from("/home/user/product-docs"),
5715 ])
5716 )
5717 .unwrap(),
5718 json!({
5719 "sessionId": "sess_abc123",
5720 "cwd": "/home/user/project",
5721 "additionalDirectories": [
5722 "/home/user/shared-lib",
5723 "/home/user/product-docs"
5724 ]
5725 })
5726 );
5727 assert_eq!(
5728 serde_json::from_value::<SessionInfo>(json!({
5729 "sessionId": "sess_abc123",
5730 "cwd": "/home/user/project"
5731 }))
5732 .unwrap()
5733 .additional_directories,
5734 Vec::<PathBuf>::new()
5735 );
5736 }
5737 #[test]
5738 fn test_session_additional_directories_capabilities_serialization() {
5739 assert_eq!(
5740 serde_json::to_value(
5741 SessionCapabilities::new()
5742 .additional_directories(SessionAdditionalDirectoriesCapabilities::new())
5743 )
5744 .unwrap(),
5745 json!({
5746 "additionalDirectories": {}
5747 })
5748 );
5749 }
5750
5751 #[test]
5752 fn test_auth_method_terminal_serialization() {
5753 let method = AuthMethod::Terminal(AuthMethodTerminal::new("tui-auth", "Terminal Auth"));
5754
5755 let json = serde_json::to_value(&method).unwrap();
5756 assert_eq!(
5757 json,
5758 json!({
5759 "id": "tui-auth",
5760 "name": "Terminal Auth",
5761 "type": "terminal"
5762 })
5763 );
5764 assert!(!json.as_object().unwrap().contains_key("args"));
5766 assert!(!json.as_object().unwrap().contains_key("env"));
5767
5768 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5769 match deserialized {
5770 AuthMethod::Terminal(AuthMethodTerminal { args, env, .. }) => {
5771 assert!(args.is_empty());
5772 assert!(env.is_empty());
5773 }
5774 _ => panic!("Expected Terminal variant"),
5775 }
5776 }
5777
5778 #[test]
5779 fn test_auth_method_terminal_with_args_and_env_serialization() {
5780 use std::collections::HashMap;
5781
5782 let mut env = HashMap::new();
5783 env.insert("TERM".to_string(), "xterm-256color".to_string());
5784
5785 let method = AuthMethod::Terminal(
5786 AuthMethodTerminal::new("tui-auth", "Terminal Auth")
5787 .args(vec!["--interactive".to_string(), "--color".to_string()])
5788 .env(env),
5789 );
5790
5791 let json = serde_json::to_value(&method).unwrap();
5792 assert_eq!(
5793 json,
5794 json!({
5795 "id": "tui-auth",
5796 "name": "Terminal Auth",
5797 "type": "terminal",
5798 "args": ["--interactive", "--color"],
5799 "env": {
5800 "TERM": "xterm-256color"
5801 }
5802 })
5803 );
5804
5805 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5806 match deserialized {
5807 AuthMethod::Terminal(AuthMethodTerminal { args, env, .. }) => {
5808 assert_eq!(args, vec!["--interactive", "--color"]);
5809 assert_eq!(env.len(), 1);
5810 assert_eq!(env.get("TERM").unwrap(), "xterm-256color");
5811 }
5812 _ => panic!("Expected Terminal variant"),
5813 }
5814 }
5815
5816 #[test]
5817 fn test_session_config_option_value_id_serialize() {
5818 let val = SessionConfigOptionValue::value_id("model-1");
5819 let json = serde_json::to_value(&val).unwrap();
5820 assert_eq!(json, json!({ "value": "model-1" }));
5822 assert!(!json.as_object().unwrap().contains_key("type"));
5823 }
5824
5825 #[test]
5826 fn test_session_config_option_value_boolean_serialize() {
5827 let val = SessionConfigOptionValue::boolean(true);
5828 let json = serde_json::to_value(&val).unwrap();
5829 assert_eq!(json, json!({ "type": "boolean", "value": true }));
5830 }
5831
5832 #[test]
5833 fn test_session_config_option_value_deserialize_no_type() {
5834 let json = json!({ "value": "model-1" });
5836 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
5837 assert_eq!(val, SessionConfigOptionValue::value_id("model-1"));
5838 assert_eq!(val.as_value_id().unwrap().to_string(), "model-1");
5839 }
5840
5841 #[test]
5842 fn test_session_config_option_value_deserialize_boolean() {
5843 let json = json!({ "type": "boolean", "value": true });
5844 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
5845 assert_eq!(val, SessionConfigOptionValue::boolean(true));
5846 assert_eq!(val.as_bool(), Some(true));
5847 }
5848
5849 #[test]
5850 fn test_session_config_option_value_deserialize_boolean_false() {
5851 let json = json!({ "type": "boolean", "value": false });
5852 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
5853 assert_eq!(val, SessionConfigOptionValue::boolean(false));
5854 assert_eq!(val.as_bool(), Some(false));
5855 }
5856
5857 #[test]
5858 fn test_session_config_option_value_deserialize_unknown_type_with_string_value() {
5859 let json = json!({ "type": "text", "value": "freeform input" });
5861 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
5862 assert_eq!(val.as_value_id().unwrap().to_string(), "freeform input");
5863 }
5864
5865 #[test]
5866 fn test_session_config_option_value_roundtrip_value_id() {
5867 let original = SessionConfigOptionValue::value_id("option-a");
5868 let json = serde_json::to_value(&original).unwrap();
5869 let roundtripped: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
5870 assert_eq!(original, roundtripped);
5871 }
5872
5873 #[test]
5874 fn test_session_config_option_value_roundtrip_boolean() {
5875 let original = SessionConfigOptionValue::boolean(false);
5876 let json = serde_json::to_value(&original).unwrap();
5877 let roundtripped: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
5878 assert_eq!(original, roundtripped);
5879 }
5880
5881 #[test]
5882 fn test_session_config_option_value_type_mismatch_boolean_with_string() {
5883 let json = json!({ "type": "boolean", "value": "not a bool" });
5885 let result = serde_json::from_value::<SessionConfigOptionValue>(json);
5886 assert!(result.is_ok());
5888 assert_eq!(
5889 result.unwrap().as_value_id().unwrap().to_string(),
5890 "not a bool"
5891 );
5892 }
5893
5894 #[test]
5895 fn test_session_config_option_value_from_impls() {
5896 let from_str: SessionConfigOptionValue = "model-1".into();
5897 assert_eq!(from_str.as_value_id().unwrap().to_string(), "model-1");
5898
5899 let from_id: SessionConfigOptionValue = SessionConfigValueId::new("model-2").into();
5900 assert_eq!(from_id.as_value_id().unwrap().to_string(), "model-2");
5901
5902 let from_bool: SessionConfigOptionValue = true.into();
5903 assert_eq!(from_bool.as_bool(), Some(true));
5904 }
5905
5906 #[test]
5907 fn test_set_session_config_option_request_value_id() {
5908 let req = SetSessionConfigOptionRequest::new("sess_1", "model", "model-1");
5909 let json = serde_json::to_value(&req).unwrap();
5910 assert_eq!(
5911 json,
5912 json!({
5913 "sessionId": "sess_1",
5914 "configId": "model",
5915 "value": "model-1"
5916 })
5917 );
5918 assert!(!json.as_object().unwrap().contains_key("type"));
5920 }
5921
5922 #[test]
5923 fn test_set_session_config_option_request_boolean() {
5924 let req = SetSessionConfigOptionRequest::new("sess_1", "brave_mode", true);
5925 let json = serde_json::to_value(&req).unwrap();
5926 assert_eq!(
5927 json,
5928 json!({
5929 "sessionId": "sess_1",
5930 "configId": "brave_mode",
5931 "type": "boolean",
5932 "value": true
5933 })
5934 );
5935 }
5936
5937 #[test]
5938 fn test_set_session_config_option_request_deserialize_no_type() {
5939 let json = json!({
5941 "sessionId": "sess_1",
5942 "configId": "model",
5943 "value": "model-1"
5944 });
5945 let req: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
5946 assert_eq!(req.session_id.to_string(), "sess_1");
5947 assert_eq!(req.config_id.to_string(), "model");
5948 assert_eq!(req.value.as_value_id().unwrap().to_string(), "model-1");
5949 }
5950
5951 #[test]
5952 fn test_set_session_config_option_request_deserialize_boolean() {
5953 let json = json!({
5954 "sessionId": "sess_1",
5955 "configId": "brave_mode",
5956 "type": "boolean",
5957 "value": true
5958 });
5959 let req: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
5960 assert_eq!(req.value.as_bool(), Some(true));
5961 }
5962
5963 #[test]
5964 fn test_set_session_config_option_request_roundtrip_value_id() {
5965 let original = SetSessionConfigOptionRequest::new("s", "c", "v");
5966 let json = serde_json::to_value(&original).unwrap();
5967 let roundtripped: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
5968 assert_eq!(original, roundtripped);
5969 }
5970
5971 #[test]
5972 fn test_set_session_config_option_request_roundtrip_boolean() {
5973 let original = SetSessionConfigOptionRequest::new("s", "c", false);
5974 let json = serde_json::to_value(&original).unwrap();
5975 let roundtripped: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
5976 assert_eq!(original, roundtripped);
5977 }
5978
5979 #[test]
5980 fn test_session_config_boolean_serialization() {
5981 let cfg = SessionConfigBoolean::new(true);
5982 let json = serde_json::to_value(&cfg).unwrap();
5983 assert_eq!(json, json!({ "currentValue": true }));
5984
5985 let deserialized: SessionConfigBoolean = serde_json::from_value(json).unwrap();
5986 assert!(deserialized.current_value);
5987 }
5988
5989 #[test]
5990 fn test_session_config_option_boolean_variant() {
5991 let opt = SessionConfigOption::boolean("brave_mode", "Brave Mode", false)
5992 .description("Skip confirmation prompts")
5993 .meta(test_meta());
5994 assert_eq!(serialized_meta_key_count(&opt), 1);
5995
5996 let json = serde_json::to_value(&opt).unwrap();
5997 assert_eq!(
5998 json,
5999 json!({
6000 "id": "brave_mode",
6001 "name": "Brave Mode",
6002 "description": "Skip confirmation prompts",
6003 "type": "boolean",
6004 "currentValue": false,
6005 "_meta": {
6006 "source": "test"
6007 }
6008 })
6009 );
6010
6011 let deserialized: SessionConfigOption = serde_json::from_value(json).unwrap();
6012 assert_eq!(deserialized.id.to_string(), "brave_mode");
6013 assert_eq!(deserialized.name, "Brave Mode");
6014 match deserialized.kind {
6015 SessionConfigKind::Boolean(ref b) => assert!(!b.current_value),
6016 _ => panic!("Expected Boolean kind"),
6017 }
6018 }
6019
6020 #[test]
6021 fn test_session_config_option_select_still_works() {
6022 let opt = SessionConfigOption::select(
6024 "model",
6025 "Model",
6026 "model-1",
6027 vec![
6028 SessionConfigSelectOption::new("model-1", "Model 1"),
6029 SessionConfigSelectOption::new("model-2", "Model 2"),
6030 ],
6031 )
6032 .meta(test_meta());
6033 assert_eq!(serialized_meta_key_count(&opt), 1);
6034
6035 let json = serde_json::to_value(&opt).unwrap();
6036 assert_eq!(json["type"], "select");
6037 assert_eq!(json["currentValue"], "model-1");
6038 assert_eq!(json["options"].as_array().unwrap().len(), 2);
6039 assert_eq!(json["_meta"]["source"], "test");
6040
6041 let deserialized: SessionConfigOption = serde_json::from_value(json).unwrap();
6042 match deserialized.kind {
6043 SessionConfigKind::Select(ref s) => {
6044 assert_eq!(s.current_value.to_string(), "model-1");
6045 }
6046 _ => panic!("Expected Select kind"),
6047 }
6048 }
6049
6050 #[cfg(feature = "unstable_llm_providers")]
6051 #[test]
6052 fn test_llm_protocol_known_variants() {
6053 assert_eq!(
6054 serde_json::to_value(&LlmProtocol::Anthropic).unwrap(),
6055 json!("anthropic")
6056 );
6057 assert_eq!(
6058 serde_json::to_value(&LlmProtocol::OpenAi).unwrap(),
6059 json!("openai")
6060 );
6061 assert_eq!(
6062 serde_json::to_value(&LlmProtocol::Azure).unwrap(),
6063 json!("azure")
6064 );
6065 assert_eq!(
6066 serde_json::to_value(&LlmProtocol::Vertex).unwrap(),
6067 json!("vertex")
6068 );
6069 assert_eq!(
6070 serde_json::to_value(&LlmProtocol::Bedrock).unwrap(),
6071 json!("bedrock")
6072 );
6073
6074 assert_eq!(
6075 serde_json::from_str::<LlmProtocol>("\"anthropic\"").unwrap(),
6076 LlmProtocol::Anthropic
6077 );
6078 assert_eq!(
6079 serde_json::from_str::<LlmProtocol>("\"openai\"").unwrap(),
6080 LlmProtocol::OpenAi
6081 );
6082 assert_eq!(
6083 serde_json::from_str::<LlmProtocol>("\"azure\"").unwrap(),
6084 LlmProtocol::Azure
6085 );
6086 assert_eq!(
6087 serde_json::from_str::<LlmProtocol>("\"vertex\"").unwrap(),
6088 LlmProtocol::Vertex
6089 );
6090 assert_eq!(
6091 serde_json::from_str::<LlmProtocol>("\"bedrock\"").unwrap(),
6092 LlmProtocol::Bedrock
6093 );
6094 }
6095
6096 #[cfg(feature = "unstable_llm_providers")]
6097 #[test]
6098 fn test_llm_protocol_unknown_variant() {
6099 let unknown: LlmProtocol = serde_json::from_str("\"cohere\"").unwrap();
6100 assert_eq!(unknown, LlmProtocol::Other("cohere".to_string()));
6101
6102 let json = serde_json::to_value(&unknown).unwrap();
6103 assert_eq!(json, json!("cohere"));
6104 }
6105
6106 #[cfg(feature = "unstable_llm_providers")]
6107 #[test]
6108 fn test_provider_current_config_serialization() {
6109 let config =
6110 ProviderCurrentConfig::new(LlmProtocol::Anthropic, "https://api.anthropic.com");
6111
6112 let json = serde_json::to_value(&config).unwrap();
6113 assert_eq!(
6114 json,
6115 json!({
6116 "apiType": "anthropic",
6117 "baseUrl": "https://api.anthropic.com"
6118 })
6119 );
6120
6121 let deserialized: ProviderCurrentConfig = serde_json::from_value(json).unwrap();
6122 assert_eq!(deserialized.api_type, LlmProtocol::Anthropic);
6123 assert_eq!(deserialized.base_url, "https://api.anthropic.com");
6124 }
6125
6126 #[cfg(feature = "unstable_llm_providers")]
6127 #[test]
6128 fn test_provider_info_with_current_config() {
6129 let info = ProviderInfo::new(
6130 "main",
6131 vec![LlmProtocol::Anthropic, LlmProtocol::OpenAi],
6132 true,
6133 Some(ProviderCurrentConfig::new(
6134 LlmProtocol::Anthropic,
6135 "https://api.anthropic.com",
6136 )),
6137 );
6138
6139 let json = serde_json::to_value(&info).unwrap();
6140 assert_eq!(
6141 json,
6142 json!({
6143 "providerId": "main",
6144 "supported": ["anthropic", "openai"],
6145 "required": true,
6146 "current": {
6147 "apiType": "anthropic",
6148 "baseUrl": "https://api.anthropic.com"
6149 }
6150 })
6151 );
6152
6153 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6154 assert_eq!(deserialized.provider_id.to_string(), "main");
6155 assert_eq!(deserialized.supported.len(), 2);
6156 assert!(deserialized.required);
6157 assert!(deserialized.current.is_some());
6158 assert_eq!(
6159 deserialized.current.as_ref().unwrap().api_type,
6160 LlmProtocol::Anthropic
6161 );
6162 }
6163
6164 #[cfg(feature = "unstable_llm_providers")]
6165 #[test]
6166 fn test_provider_info_disabled() {
6167 let info = ProviderInfo::new(
6168 "secondary",
6169 vec![LlmProtocol::OpenAi],
6170 false,
6171 None::<ProviderCurrentConfig>,
6172 );
6173
6174 let json = serde_json::to_value(&info).unwrap();
6175 assert_eq!(
6176 json,
6177 json!({
6178 "providerId": "secondary",
6179 "supported": ["openai"],
6180 "required": false
6181 })
6182 );
6183
6184 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6185 assert_eq!(deserialized.provider_id.to_string(), "secondary");
6186 assert!(!deserialized.required);
6187 assert!(deserialized.current.is_none());
6188 }
6189
6190 #[cfg(feature = "unstable_llm_providers")]
6191 #[test]
6192 fn test_provider_info_missing_current_defaults_to_none() {
6193 let json = json!({
6195 "providerId": "main",
6196 "supported": ["anthropic"],
6197 "required": true
6198 });
6199 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6200 assert!(deserialized.current.is_none());
6201 }
6202
6203 #[cfg(feature = "unstable_llm_providers")]
6204 #[test]
6205 fn test_provider_info_explicit_null_current_decodes_to_none() {
6206 let json = json!({
6210 "providerId": "main",
6211 "supported": ["anthropic"],
6212 "required": true,
6213 "current": null
6214 });
6215 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6216 assert!(deserialized.current.is_none());
6217 }
6218
6219 #[cfg(feature = "unstable_llm_providers")]
6220 #[test]
6221 fn test_list_providers_response_serialization() {
6222 let response = ListProvidersResponse::new(vec![ProviderInfo::new(
6223 "main",
6224 vec![LlmProtocol::Anthropic],
6225 true,
6226 Some(ProviderCurrentConfig::new(
6227 LlmProtocol::Anthropic,
6228 "https://api.anthropic.com",
6229 )),
6230 )]);
6231
6232 let json = serde_json::to_value(&response).unwrap();
6233 assert_eq!(json["providers"].as_array().unwrap().len(), 1);
6234 assert_eq!(json["providers"][0]["providerId"], "main");
6235
6236 let deserialized: ListProvidersResponse = serde_json::from_value(json).unwrap();
6237 assert_eq!(deserialized.providers.len(), 1);
6238 }
6239
6240 #[cfg(feature = "unstable_llm_providers")]
6241 #[test]
6242 fn test_set_provider_request_serialization() {
6243 use std::collections::HashMap;
6244
6245 let mut headers = HashMap::new();
6246 headers.insert("Authorization".to_string(), "Bearer sk-test".to_string());
6247
6248 let request =
6249 SetProviderRequest::new("main", LlmProtocol::OpenAi, "https://api.openai.com/v1")
6250 .headers(headers);
6251
6252 let json = serde_json::to_value(&request).unwrap();
6253 assert_eq!(
6254 json,
6255 json!({
6256 "providerId": "main",
6257 "apiType": "openai",
6258 "baseUrl": "https://api.openai.com/v1",
6259 "headers": {
6260 "Authorization": "Bearer sk-test"
6261 }
6262 })
6263 );
6264
6265 let deserialized: SetProviderRequest = serde_json::from_value(json).unwrap();
6266 assert_eq!(deserialized.provider_id.to_string(), "main");
6267 assert_eq!(deserialized.api_type, LlmProtocol::OpenAi);
6268 assert_eq!(deserialized.base_url, "https://api.openai.com/v1");
6269 assert_eq!(deserialized.headers.len(), 1);
6270 assert_eq!(
6271 deserialized.headers.get("Authorization").unwrap(),
6272 "Bearer sk-test"
6273 );
6274 }
6275
6276 #[cfg(feature = "unstable_llm_providers")]
6277 #[test]
6278 fn test_set_provider_request_omits_empty_headers() {
6279 let request =
6280 SetProviderRequest::new("main", LlmProtocol::Anthropic, "https://api.anthropic.com");
6281
6282 let json = serde_json::to_value(&request).unwrap();
6283 assert!(!json.as_object().unwrap().contains_key("headers"));
6285 }
6286
6287 #[cfg(feature = "unstable_llm_providers")]
6288 #[test]
6289 fn test_disable_provider_request_serialization() {
6290 let request = DisableProviderRequest::new("secondary");
6291
6292 let json = serde_json::to_value(&request).unwrap();
6293 assert_eq!(json, json!({ "providerId": "secondary" }));
6294
6295 let deserialized: DisableProviderRequest = serde_json::from_value(json).unwrap();
6296 assert_eq!(deserialized.provider_id.to_string(), "secondary");
6297 }
6298
6299 #[cfg(feature = "unstable_llm_providers")]
6300 #[test]
6301 fn test_providers_capabilities_serialization() {
6302 let caps = ProvidersCapabilities::new();
6303
6304 let json = serde_json::to_value(&caps).unwrap();
6305 assert_eq!(json, json!({}));
6306
6307 let deserialized: ProvidersCapabilities = serde_json::from_value(json).unwrap();
6308 assert!(deserialized.meta.is_none());
6309 }
6310
6311 #[cfg(feature = "unstable_llm_providers")]
6312 #[test]
6313 fn test_agent_capabilities_with_providers() {
6314 let caps = AgentCapabilities::new().providers(ProvidersCapabilities::new());
6315
6316 let json = serde_json::to_value(&caps).unwrap();
6317 assert_eq!(json["providers"], json!({}));
6318
6319 let deserialized: AgentCapabilities = serde_json::from_value(json).unwrap();
6320 assert!(deserialized.providers.is_some());
6321 }
6322
6323 #[test]
6324 fn prompt_request_rejects_malformed_content_block() {
6325 use serde_json::json;
6326
6327 assert!(
6328 serde_json::from_value::<PromptRequest>(json!({
6329 "sessionId": "sess-1",
6330 "prompt": [{"type": "text"}]
6331 }))
6332 .is_err()
6333 );
6334 }
6335
6336 #[test]
6337 fn prompt_request_rejects_non_array_prompt() {
6338 use serde_json::json;
6339
6340 assert!(
6341 serde_json::from_value::<PromptRequest>(json!({
6342 "sessionId": "sess-1",
6343 "prompt": "hello"
6344 }))
6345 .is_err()
6346 );
6347 }
6348}