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, DefaultOnNull, 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(all(feature = "unstable_auth_status", feature = "schemars"))]
21use super::AUTH_STATUS_UPDATE_NOTIFICATION;
22#[cfg(feature = "unstable_mcp_over_acp")]
23use super::mcp::{MCP_MESSAGE_METHOD_NAME, MessageMcpNotification};
24
25#[serde_as]
33#[skip_serializing_none]
34#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
35#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
36#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = INITIALIZE_METHOD_NAME)))]
37#[serde(rename_all = "camelCase")]
38#[non_exhaustive]
39pub struct InitializeRequest {
40 pub protocol_version: ProtocolVersion,
42 #[serde_as(deserialize_as = "DefaultOnError")]
44 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
45 #[serde(default)]
46 pub client_capabilities: ClientCapabilities,
47 #[serde_as(deserialize_as = "DefaultOnError")]
51 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
52 #[serde(default)]
53 pub client_info: Option<Implementation>,
54 #[serde_as(deserialize_as = "DefaultOnError")]
60 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
61 #[serde(default)]
62 #[serde(rename = "_meta")]
63 pub meta: Option<Meta>,
64}
65
66impl InitializeRequest {
67 #[must_use]
69 pub fn new(protocol_version: ProtocolVersion) -> Self {
70 Self {
71 protocol_version,
72 client_capabilities: ClientCapabilities::default(),
73 client_info: None,
74 meta: None,
75 }
76 }
77
78 #[must_use]
80 pub fn client_capabilities(mut self, client_capabilities: ClientCapabilities) -> Self {
81 self.client_capabilities = client_capabilities;
82 self
83 }
84
85 #[must_use]
87 pub fn client_info(mut self, client_info: impl IntoOption<Implementation>) -> Self {
88 self.client_info = client_info.into_option();
89 self
90 }
91
92 #[must_use]
98 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
99 self.meta = meta.into_option();
100 self
101 }
102}
103
104#[serde_as]
110#[skip_serializing_none]
111#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
112#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
113#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = INITIALIZE_METHOD_NAME)))]
114#[serde(rename_all = "camelCase")]
115#[non_exhaustive]
116pub struct InitializeResponse {
117 pub protocol_version: ProtocolVersion,
122 #[serde_as(deserialize_as = "DefaultOnError")]
124 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
125 #[serde(default)]
126 pub agent_capabilities: AgentCapabilities,
127 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_>>")]
129 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
130 #[serde(default)]
131 pub auth_methods: Vec<AuthMethod>,
132 #[serde_as(deserialize_as = "DefaultOnError")]
136 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
137 #[serde(default)]
138 pub agent_info: Option<Implementation>,
139 #[serde_as(deserialize_as = "DefaultOnError")]
145 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
146 #[serde(default)]
147 #[serde(rename = "_meta")]
148 pub meta: Option<Meta>,
149}
150
151impl InitializeResponse {
152 #[must_use]
154 pub fn new(protocol_version: ProtocolVersion) -> Self {
155 Self {
156 protocol_version,
157 agent_capabilities: AgentCapabilities::default(),
158 auth_methods: vec![],
159 agent_info: None,
160 meta: None,
161 }
162 }
163
164 #[must_use]
166 pub fn agent_capabilities(mut self, agent_capabilities: AgentCapabilities) -> Self {
167 self.agent_capabilities = agent_capabilities;
168 self
169 }
170
171 #[must_use]
173 pub fn auth_methods(mut self, auth_methods: Vec<AuthMethod>) -> Self {
174 self.auth_methods = auth_methods;
175 self
176 }
177
178 #[must_use]
180 pub fn agent_info(mut self, agent_info: impl IntoOption<Implementation>) -> Self {
181 self.agent_info = agent_info.into_option();
182 self
183 }
184
185 #[must_use]
191 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
192 self.meta = meta.into_option();
193 self
194 }
195}
196
197#[serde_as]
201#[skip_serializing_none]
202#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
203#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
204#[serde(rename_all = "camelCase")]
205#[non_exhaustive]
206pub struct Implementation {
207 pub name: String,
210 #[serde_as(deserialize_as = "DefaultOnError")]
214 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
215 #[serde(default)]
216 pub title: Option<String>,
217 pub version: String,
220 #[serde_as(deserialize_as = "DefaultOnError")]
226 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
227 #[serde(default)]
228 #[serde(rename = "_meta")]
229 pub meta: Option<Meta>,
230}
231
232impl Implementation {
233 #[must_use]
235 pub fn new(name: impl Into<String>, version: impl Into<String>) -> Self {
236 Self {
237 name: name.into(),
238 title: None,
239 version: version.into(),
240 meta: None,
241 }
242 }
243
244 #[must_use]
248 pub fn title(mut self, title: impl IntoOption<String>) -> Self {
249 self.title = title.into_option();
250 self
251 }
252
253 #[must_use]
259 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
260 self.meta = meta.into_option();
261 self
262 }
263}
264
265#[serde_as]
271#[skip_serializing_none]
272#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
273#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
274#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = AUTHENTICATE_METHOD_NAME)))]
275#[serde(rename_all = "camelCase")]
276#[non_exhaustive]
277pub struct AuthenticateRequest {
278 pub method_id: AuthMethodId,
281 #[serde_as(deserialize_as = "DefaultOnError")]
287 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
288 #[serde(default)]
289 #[serde(rename = "_meta")]
290 pub meta: Option<Meta>,
291}
292
293impl AuthenticateRequest {
294 #[must_use]
296 pub fn new(method_id: impl Into<AuthMethodId>) -> Self {
297 Self {
298 method_id: method_id.into(),
299 meta: None,
300 }
301 }
302
303 #[must_use]
309 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
310 self.meta = meta.into_option();
311 self
312 }
313}
314
315crate::serde_util::default_on_null! {
316 #[serde_as]
318 #[skip_serializing_none]
319 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
320 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
321 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = AUTHENTICATE_METHOD_NAME)))]
322 #[serde(rename_all = "camelCase")]
323 #[non_exhaustive]
324 pub struct AuthenticateResponse {
325 #[serde_as(deserialize_as = "DefaultOnError")]
331 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
332 #[serde(default)]
333 #[serde(rename = "_meta")]
334 pub meta: Option<Meta>,
335 }
336}
337
338impl AuthenticateResponse {
339 #[must_use]
341 pub fn new() -> Self {
342 Self::default()
343 }
344
345 #[must_use]
351 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
352 self.meta = meta.into_option();
353 self
354 }
355}
356
357crate::serde_util::default_on_null! {
360 #[serde_as]
364 #[skip_serializing_none]
365 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
366 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
367 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = LOGOUT_METHOD_NAME)))]
368 #[serde(rename_all = "camelCase")]
369 #[non_exhaustive]
370 pub struct LogoutRequest {
371 #[serde_as(deserialize_as = "DefaultOnError")]
377 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
378 #[serde(default)]
379 #[serde(rename = "_meta")]
380 pub meta: Option<Meta>,
381 }
382}
383
384impl LogoutRequest {
385 #[must_use]
387 pub fn new() -> Self {
388 Self::default()
389 }
390
391 #[must_use]
397 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
398 self.meta = meta.into_option();
399 self
400 }
401}
402
403crate::serde_util::default_on_null! {
404 #[serde_as]
406 #[skip_serializing_none]
407 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
408 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
409 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = LOGOUT_METHOD_NAME)))]
410 #[serde(rename_all = "camelCase")]
411 #[non_exhaustive]
412 pub struct LogoutResponse {
413 #[serde_as(deserialize_as = "DefaultOnError")]
419 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
420 #[serde(default)]
421 #[serde(rename = "_meta")]
422 pub meta: Option<Meta>,
423 }
424}
425
426impl LogoutResponse {
427 #[must_use]
429 pub fn new() -> Self {
430 Self::default()
431 }
432
433 #[must_use]
439 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
440 self.meta = meta.into_option();
441 self
442 }
443}
444
445#[cfg(feature = "unstable_auth_status")]
448crate::serde_util::default_on_null! {
449 #[serde_as]
457 #[skip_serializing_none]
458 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
459 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
460 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = AUTH_STATUS_METHOD_NAME)))]
461 #[serde(rename_all = "camelCase")]
462 #[non_exhaustive]
463 pub struct AuthStatusRequest {
464 #[serde_as(deserialize_as = "DefaultOnError")]
470 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
471 #[serde(default)]
472 #[serde(rename = "_meta")]
473 pub meta: Option<Meta>,
474 }
475}
476
477#[cfg(feature = "unstable_auth_status")]
478impl AuthStatusRequest {
479 #[must_use]
481 pub fn new() -> Self {
482 Self::default()
483 }
484
485 #[must_use]
491 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
492 self.meta = meta.into_option();
493 self
494 }
495}
496
497#[cfg(feature = "unstable_auth_status")]
503#[serde_as]
504#[skip_serializing_none]
505#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
506#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
507#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = AUTH_STATUS_METHOD_NAME)))]
508#[serde(rename_all = "camelCase")]
509#[non_exhaustive]
510pub struct AuthStatusResponse {
511 pub state: AuthState,
516 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_>>")]
522 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
523 #[serde(default, skip_serializing_if = "Vec::is_empty")]
524 pub accounts: Vec<AuthAccount>,
525 #[serde_as(deserialize_as = "DefaultOnError")]
531 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
532 #[serde(default)]
533 #[serde(rename = "_meta")]
534 pub meta: Option<Meta>,
535}
536
537#[cfg(feature = "unstable_auth_status")]
538impl AuthStatusResponse {
539 #[must_use]
541 pub fn new(state: AuthState) -> Self {
542 Self {
543 state,
544 accounts: vec![],
545 meta: None,
546 }
547 }
548
549 #[must_use]
551 pub fn accounts(mut self, accounts: Vec<AuthAccount>) -> Self {
552 self.accounts = accounts;
553 self
554 }
555
556 #[must_use]
562 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
563 self.meta = meta.into_option();
564 self
565 }
566}
567
568#[cfg(feature = "unstable_auth_status")]
578#[serde_as]
579#[skip_serializing_none]
580#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
581#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
582#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "client", "x-method" = AUTH_STATUS_UPDATE_NOTIFICATION)))]
583#[serde(rename_all = "camelCase")]
584#[non_exhaustive]
585pub struct AuthStatusUpdateNotification {
586 pub state: AuthState,
591 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_>>")]
597 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
598 #[serde(default, skip_serializing_if = "Vec::is_empty")]
599 pub accounts: Vec<AuthAccount>,
600 #[serde_as(deserialize_as = "DefaultOnError")]
606 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
607 #[serde(default)]
608 #[serde(rename = "_meta")]
609 pub meta: Option<Meta>,
610}
611
612#[cfg(feature = "unstable_auth_status")]
613impl AuthStatusUpdateNotification {
614 #[must_use]
616 pub fn new(state: AuthState) -> Self {
617 Self {
618 state,
619 accounts: vec![],
620 meta: None,
621 }
622 }
623
624 #[must_use]
626 pub fn accounts(mut self, accounts: Vec<AuthAccount>) -> Self {
627 self.accounts = accounts;
628 self
629 }
630
631 #[must_use]
637 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
638 self.meta = meta.into_option();
639 self
640 }
641}
642
643#[cfg(feature = "unstable_auth_status")]
649#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
650#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
651#[serde(rename_all = "snake_case")]
652#[non_exhaustive]
653pub enum AuthState {
654 Authenticated,
656 Unauthenticated,
659 NotRequired,
661 Unknown,
663 #[serde(untagged)]
669 Other(String),
670}
671
672#[cfg(feature = "unstable_auth_status")]
683#[serde_as]
684#[skip_serializing_none]
685#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
686#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
687#[serde(rename_all = "camelCase")]
688#[non_exhaustive]
689pub struct AuthAccount {
690 pub label: String,
693 #[serde_as(deserialize_as = "DefaultOnError")]
699 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
700 #[serde(default)]
701 pub active: Option<bool>,
702 #[serde_as(deserialize_as = "DefaultOnError")]
706 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
707 #[serde(default)]
708 pub name: Option<String>,
709 #[serde_as(deserialize_as = "DefaultOnError")]
713 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
714 #[serde(default)]
715 pub email: Option<String>,
716 #[serde_as(deserialize_as = "DefaultOnError")]
720 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
721 #[serde(default)]
722 pub organization: Option<String>,
723 #[serde_as(deserialize_as = "DefaultOnError")]
729 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
730 #[serde(default)]
731 #[serde(rename = "_meta")]
732 pub meta: Option<Meta>,
733}
734
735#[cfg(feature = "unstable_auth_status")]
736impl AuthAccount {
737 #[must_use]
739 pub fn new(label: impl Into<String>) -> Self {
740 Self {
741 label: label.into(),
742 active: None,
743 name: None,
744 email: None,
745 organization: None,
746 meta: None,
747 }
748 }
749
750 #[must_use]
752 pub fn active(mut self, active: impl IntoOption<bool>) -> Self {
753 self.active = active.into_option();
754 self
755 }
756
757 #[must_use]
759 pub fn name(mut self, name: impl IntoOption<String>) -> Self {
760 self.name = name.into_option();
761 self
762 }
763
764 #[must_use]
766 pub fn email(mut self, email: impl IntoOption<String>) -> Self {
767 self.email = email.into_option();
768 self
769 }
770
771 #[must_use]
773 pub fn organization(mut self, organization: impl IntoOption<String>) -> Self {
774 self.organization = organization.into_option();
775 self
776 }
777
778 #[must_use]
784 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
785 self.meta = meta.into_option();
786 self
787 }
788}
789
790#[cfg(feature = "unstable_auth_status")]
798#[serde_as]
799#[skip_serializing_none]
800#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
801#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
802#[non_exhaustive]
803pub struct AuthStatusCapabilities {
804 #[serde_as(deserialize_as = "DefaultOnError")]
810 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
811 #[serde(default)]
812 #[serde(rename = "_meta")]
813 pub meta: Option<Meta>,
814}
815
816#[cfg(feature = "unstable_auth_status")]
817impl AuthStatusCapabilities {
818 #[must_use]
820 pub fn new() -> Self {
821 Self::default()
822 }
823
824 #[must_use]
830 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
831 self.meta = meta.into_option();
832 self
833 }
834}
835
836#[serde_as]
838#[skip_serializing_none]
839#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
840#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
841#[serde(rename_all = "camelCase")]
842#[non_exhaustive]
843pub struct AgentAuthCapabilities {
844 #[cfg(feature = "unstable_auth_status")]
853 #[serde_as(deserialize_as = "DefaultOnError")]
854 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
855 #[serde(default)]
856 pub status: Option<AuthStatusCapabilities>,
857 #[serde_as(deserialize_as = "DefaultOnError")]
862 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
863 #[serde(default)]
864 pub logout: Option<LogoutCapabilities>,
865 #[serde_as(deserialize_as = "DefaultOnError")]
871 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
872 #[serde(default)]
873 #[serde(rename = "_meta")]
874 pub meta: Option<Meta>,
875}
876
877impl AgentAuthCapabilities {
878 #[must_use]
880 pub fn new() -> Self {
881 Self::default()
882 }
883
884 #[cfg(feature = "unstable_auth_status")]
890 #[must_use]
891 pub fn status(mut self, status: impl IntoOption<AuthStatusCapabilities>) -> Self {
892 self.status = status.into_option();
893 self
894 }
895
896 #[must_use]
898 pub fn logout(mut self, logout: impl IntoOption<LogoutCapabilities>) -> Self {
899 self.logout = logout.into_option();
900 self
901 }
902
903 #[must_use]
909 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
910 self.meta = meta.into_option();
911 self
912 }
913}
914
915#[serde_as]
919#[skip_serializing_none]
920#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
921#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
922#[non_exhaustive]
923pub struct LogoutCapabilities {
924 #[serde_as(deserialize_as = "DefaultOnError")]
930 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
931 #[serde(default)]
932 #[serde(rename = "_meta")]
933 pub meta: Option<Meta>,
934}
935
936impl LogoutCapabilities {
937 #[must_use]
939 pub fn new() -> Self {
940 Self::default()
941 }
942
943 #[must_use]
949 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
950 self.meta = meta.into_option();
951 self
952 }
953}
954
955#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
957#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Display, From)]
958#[serde(transparent)]
959#[from(Arc<str>, String, &'static str)]
960#[non_exhaustive]
961pub struct AuthMethodId(pub Arc<str>);
962
963impl AuthMethodId {
964 #[must_use]
966 pub fn new(id: impl Into<Arc<str>>) -> Self {
967 Self(id.into())
968 }
969}
970
971#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
976#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
977#[serde(tag = "type", rename_all = "snake_case")]
978#[non_exhaustive]
979pub enum AuthMethod {
980 Terminal(AuthMethodTerminal),
983 #[serde(untagged, deserialize_with = "deserialize_agent_auth_method_fallback")]
987 Agent(AuthMethodAgent),
988}
989
990fn deserialize_agent_auth_method_fallback<'de, D>(
995 deserializer: D,
996) -> Result<AuthMethodAgent, D::Error>
997where
998 D: serde::Deserializer<'de>,
999{
1000 let value = serde_json::Value::deserialize(deserializer)?;
1001 if value.get("type").and_then(serde_json::Value::as_str) == Some("terminal") {
1002 return Err(serde::de::Error::custom(
1003 "known authentication method `terminal` did not match its schema",
1004 ));
1005 }
1006 AuthMethodAgent::deserialize(value).map_err(serde::de::Error::custom)
1007}
1008
1009impl AuthMethod {
1010 #[must_use]
1012 pub fn id(&self) -> &AuthMethodId {
1013 match self {
1014 Self::Agent(a) => &a.id,
1015 Self::Terminal(t) => &t.id,
1016 }
1017 }
1018
1019 #[must_use]
1021 pub fn name(&self) -> &str {
1022 match self {
1023 Self::Agent(a) => &a.name,
1024 Self::Terminal(t) => &t.name,
1025 }
1026 }
1027
1028 #[must_use]
1030 pub fn description(&self) -> Option<&str> {
1031 match self {
1032 Self::Agent(a) => a.description.as_deref(),
1033 Self::Terminal(t) => t.description.as_deref(),
1034 }
1035 }
1036
1037 #[must_use]
1043 pub fn meta(&self) -> Option<&Meta> {
1044 match self {
1045 Self::Agent(a) => a.meta.as_ref(),
1046 Self::Terminal(t) => t.meta.as_ref(),
1047 }
1048 }
1049}
1050
1051#[serde_as]
1055#[skip_serializing_none]
1056#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1057#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1058#[serde(rename_all = "camelCase")]
1059#[non_exhaustive]
1060pub struct AuthMethodAgent {
1061 pub id: AuthMethodId,
1063 pub name: String,
1065 #[serde_as(deserialize_as = "DefaultOnError")]
1067 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1068 #[serde(default)]
1069 pub description: Option<String>,
1070 #[serde_as(deserialize_as = "DefaultOnError")]
1076 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1077 #[serde(default)]
1078 #[serde(rename = "_meta")]
1079 pub meta: Option<Meta>,
1080}
1081
1082impl AuthMethodAgent {
1083 #[must_use]
1085 pub fn new(id: impl Into<AuthMethodId>, name: impl Into<String>) -> Self {
1086 Self {
1087 id: id.into(),
1088 name: name.into(),
1089 description: None,
1090 meta: None,
1091 }
1092 }
1093
1094 #[must_use]
1096 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
1097 self.description = description.into_option();
1098 self
1099 }
1100
1101 #[must_use]
1107 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1108 self.meta = meta.into_option();
1109 self
1110 }
1111}
1112
1113#[serde_as]
1121#[skip_serializing_none]
1122#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1123#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1124#[serde(rename_all = "camelCase")]
1125#[non_exhaustive]
1126pub struct AuthMethodTerminal {
1127 pub id: AuthMethodId,
1129 pub name: String,
1131 #[serde_as(deserialize_as = "DefaultOnError")]
1133 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1134 #[serde(default)]
1135 pub description: Option<String>,
1136 #[serde_as(deserialize_as = "DefaultOnNull")]
1138 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-null" = true)))]
1139 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1140 pub args: Vec<String>,
1141 #[serde_as(deserialize_as = "DefaultOnNull")]
1144 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-null" = true)))]
1145 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
1146 pub env: HashMap<String, String>,
1147 #[serde_as(deserialize_as = "DefaultOnError")]
1153 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1154 #[serde(default)]
1155 #[serde(rename = "_meta")]
1156 pub meta: Option<Meta>,
1157}
1158
1159impl AuthMethodTerminal {
1160 #[must_use]
1162 pub fn new(id: impl Into<AuthMethodId>, name: impl Into<String>) -> Self {
1163 Self {
1164 id: id.into(),
1165 name: name.into(),
1166 description: None,
1167 args: Vec::new(),
1168 env: HashMap::new(),
1169 meta: None,
1170 }
1171 }
1172
1173 #[must_use]
1175 pub fn args(mut self, args: Vec<String>) -> Self {
1176 self.args = args;
1177 self
1178 }
1179
1180 #[must_use]
1183 pub fn env(mut self, env: HashMap<String, String>) -> Self {
1184 self.env = env;
1185 self
1186 }
1187
1188 #[must_use]
1190 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
1191 self.description = description.into_option();
1192 self
1193 }
1194
1195 #[must_use]
1201 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1202 self.meta = meta.into_option();
1203 self
1204 }
1205}
1206
1207#[serde_as]
1213#[skip_serializing_none]
1214#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1215#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1216#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_NEW_METHOD_NAME)))]
1217#[serde(rename_all = "camelCase")]
1218#[non_exhaustive]
1219pub struct NewSessionRequest {
1220 pub cwd: PathBuf,
1222 #[serde_as(deserialize_as = "DefaultOnNull")]
1228 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-null" = true)))]
1229 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1230 pub additional_directories: Vec<PathBuf>,
1231 #[serde_as(deserialize_as = "DefaultOnNull")]
1233 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-null" = true)))]
1234 pub mcp_servers: Vec<McpServer>,
1235 #[cfg(feature = "unstable_session_system_prompt")]
1245 #[serde(default)]
1246 pub system_prompt: Option<SystemPrompt>,
1247 #[serde_as(deserialize_as = "DefaultOnError")]
1253 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1254 #[serde(default)]
1255 #[serde(rename = "_meta")]
1256 pub meta: Option<Meta>,
1257}
1258
1259impl NewSessionRequest {
1260 #[must_use]
1262 pub fn new(cwd: impl Into<PathBuf>) -> Self {
1263 Self {
1264 cwd: cwd.into(),
1265 additional_directories: vec![],
1266 mcp_servers: vec![],
1267 #[cfg(feature = "unstable_session_system_prompt")]
1268 system_prompt: None,
1269 meta: None,
1270 }
1271 }
1272
1273 #[must_use]
1275 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1276 self.additional_directories = additional_directories;
1277 self
1278 }
1279
1280 #[must_use]
1282 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1283 self.mcp_servers = mcp_servers;
1284 self
1285 }
1286
1287 #[cfg(feature = "unstable_session_system_prompt")]
1293 #[must_use]
1294 pub fn system_prompt(mut self, system_prompt: impl IntoOption<SystemPrompt>) -> Self {
1295 self.system_prompt = system_prompt.into_option();
1296 self
1297 }
1298
1299 #[must_use]
1305 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1306 self.meta = meta.into_option();
1307 self
1308 }
1309}
1310
1311#[serde_as]
1315#[skip_serializing_none]
1316#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1317#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1318#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_NEW_METHOD_NAME)))]
1319#[serde(rename_all = "camelCase")]
1320#[non_exhaustive]
1321pub struct NewSessionResponse {
1322 pub session_id: SessionId,
1326 #[serde_as(deserialize_as = "DefaultOnError")]
1330 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1331 #[serde(default)]
1332 pub modes: Option<SessionModeState>,
1333 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_>>>")]
1335 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1336 #[serde(default)]
1337 pub config_options: Option<Vec<SessionConfigOption>>,
1338 #[serde_as(deserialize_as = "DefaultOnError")]
1344 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1345 #[serde(default)]
1346 #[serde(rename = "_meta")]
1347 pub meta: Option<Meta>,
1348}
1349
1350impl NewSessionResponse {
1351 #[must_use]
1353 pub fn new(session_id: impl Into<SessionId>) -> Self {
1354 Self {
1355 session_id: session_id.into(),
1356 modes: None,
1357 config_options: None,
1358 meta: None,
1359 }
1360 }
1361
1362 #[must_use]
1366 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1367 self.modes = modes.into_option();
1368 self
1369 }
1370
1371 #[must_use]
1373 pub fn config_options(
1374 mut self,
1375 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1376 ) -> Self {
1377 self.config_options = config_options.into_option();
1378 self
1379 }
1380
1381 #[must_use]
1387 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1388 self.meta = meta.into_option();
1389 self
1390 }
1391}
1392
1393#[serde_as]
1401#[skip_serializing_none]
1402#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1403#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1404#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_LOAD_METHOD_NAME)))]
1405#[serde(rename_all = "camelCase")]
1406#[non_exhaustive]
1407pub struct LoadSessionRequest {
1408 #[serde_as(deserialize_as = "DefaultOnNull")]
1410 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-null" = true)))]
1411 pub mcp_servers: Vec<McpServer>,
1412 pub cwd: PathBuf,
1414 #[serde_as(deserialize_as = "DefaultOnNull")]
1421 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-null" = true)))]
1422 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1423 pub additional_directories: Vec<PathBuf>,
1424 pub session_id: SessionId,
1426 #[cfg(feature = "unstable_session_system_prompt")]
1438 #[serde(default)]
1439 pub system_prompt: Option<SystemPrompt>,
1440 #[serde_as(deserialize_as = "DefaultOnError")]
1446 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1447 #[serde(default)]
1448 #[serde(rename = "_meta")]
1449 pub meta: Option<Meta>,
1450}
1451
1452impl LoadSessionRequest {
1453 #[must_use]
1455 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1456 Self {
1457 mcp_servers: vec![],
1458 cwd: cwd.into(),
1459 additional_directories: vec![],
1460 session_id: session_id.into(),
1461 #[cfg(feature = "unstable_session_system_prompt")]
1462 system_prompt: None,
1463 meta: None,
1464 }
1465 }
1466
1467 #[must_use]
1469 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1470 self.additional_directories = additional_directories;
1471 self
1472 }
1473
1474 #[must_use]
1476 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1477 self.mcp_servers = mcp_servers;
1478 self
1479 }
1480
1481 #[cfg(feature = "unstable_session_system_prompt")]
1487 #[must_use]
1488 pub fn system_prompt(mut self, system_prompt: impl IntoOption<SystemPrompt>) -> Self {
1489 self.system_prompt = system_prompt.into_option();
1490 self
1491 }
1492
1493 #[must_use]
1499 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1500 self.meta = meta.into_option();
1501 self
1502 }
1503}
1504
1505crate::serde_util::default_on_null! {
1506 #[serde_as]
1508 #[skip_serializing_none]
1509 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1510 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
1511 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_LOAD_METHOD_NAME)))]
1512 #[serde(rename_all = "camelCase")]
1513 #[non_exhaustive]
1514 pub struct LoadSessionResponse {
1515 #[serde_as(deserialize_as = "DefaultOnError")]
1519 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1520 #[serde(default)]
1521 pub modes: Option<SessionModeState>,
1522 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_>>>")]
1524 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1525 #[serde(default)]
1526 pub config_options: Option<Vec<SessionConfigOption>>,
1527 #[serde_as(deserialize_as = "DefaultOnError")]
1533 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1534 #[serde(default)]
1535 #[serde(rename = "_meta")]
1536 pub meta: Option<Meta>,
1537 }
1538}
1539
1540impl LoadSessionResponse {
1541 #[must_use]
1543 pub fn new() -> Self {
1544 Self::default()
1545 }
1546
1547 #[must_use]
1551 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1552 self.modes = modes.into_option();
1553 self
1554 }
1555
1556 #[must_use]
1558 pub fn config_options(
1559 mut self,
1560 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1561 ) -> Self {
1562 self.config_options = config_options.into_option();
1563 self
1564 }
1565
1566 #[must_use]
1572 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1573 self.meta = meta.into_option();
1574 self
1575 }
1576}
1577
1578#[cfg(feature = "unstable_session_fork")]
1591#[serde_as]
1592#[skip_serializing_none]
1593#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1594#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1595#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_FORK_METHOD_NAME)))]
1596#[serde(rename_all = "camelCase")]
1597#[non_exhaustive]
1598pub struct ForkSessionRequest {
1599 pub session_id: SessionId,
1601 pub cwd: PathBuf,
1603 #[serde_as(deserialize_as = "DefaultOnNull")]
1609 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-null" = true)))]
1610 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1611 pub additional_directories: Vec<PathBuf>,
1612 #[serde_as(deserialize_as = "DefaultOnNull")]
1614 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-null" = true)))]
1615 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1616 pub mcp_servers: Vec<McpServer>,
1617 #[cfg(feature = "unstable_session_system_prompt")]
1629 #[serde(default)]
1630 pub system_prompt: Option<SystemPrompt>,
1631 #[serde_as(deserialize_as = "DefaultOnError")]
1637 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1638 #[serde(default)]
1639 #[serde(rename = "_meta")]
1640 pub meta: Option<Meta>,
1641}
1642
1643#[cfg(feature = "unstable_session_fork")]
1644impl ForkSessionRequest {
1645 #[must_use]
1647 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1648 Self {
1649 session_id: session_id.into(),
1650 cwd: cwd.into(),
1651 additional_directories: vec![],
1652 mcp_servers: vec![],
1653 #[cfg(feature = "unstable_session_system_prompt")]
1654 system_prompt: None,
1655 meta: None,
1656 }
1657 }
1658
1659 #[must_use]
1661 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1662 self.additional_directories = additional_directories;
1663 self
1664 }
1665
1666 #[must_use]
1668 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1669 self.mcp_servers = mcp_servers;
1670 self
1671 }
1672
1673 #[cfg(feature = "unstable_session_system_prompt")]
1679 #[must_use]
1680 pub fn system_prompt(mut self, system_prompt: impl IntoOption<SystemPrompt>) -> Self {
1681 self.system_prompt = system_prompt.into_option();
1682 self
1683 }
1684
1685 #[must_use]
1691 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1692 self.meta = meta.into_option();
1693 self
1694 }
1695}
1696
1697#[cfg(feature = "unstable_session_fork")]
1703#[serde_as]
1704#[skip_serializing_none]
1705#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1706#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1707#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_FORK_METHOD_NAME)))]
1708#[serde(rename_all = "camelCase")]
1709#[non_exhaustive]
1710pub struct ForkSessionResponse {
1711 pub session_id: SessionId,
1713 #[serde_as(deserialize_as = "DefaultOnError")]
1717 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1718 #[serde(default)]
1719 pub modes: Option<SessionModeState>,
1720 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_>>>")]
1722 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1723 #[serde(default)]
1724 pub config_options: Option<Vec<SessionConfigOption>>,
1725 #[serde_as(deserialize_as = "DefaultOnError")]
1731 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1732 #[serde(default)]
1733 #[serde(rename = "_meta")]
1734 pub meta: Option<Meta>,
1735}
1736
1737#[cfg(feature = "unstable_session_fork")]
1738impl ForkSessionResponse {
1739 #[must_use]
1741 pub fn new(session_id: impl Into<SessionId>) -> Self {
1742 Self {
1743 session_id: session_id.into(),
1744 modes: None,
1745 config_options: None,
1746 meta: None,
1747 }
1748 }
1749
1750 #[must_use]
1754 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1755 self.modes = modes.into_option();
1756 self
1757 }
1758
1759 #[must_use]
1761 pub fn config_options(
1762 mut self,
1763 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1764 ) -> Self {
1765 self.config_options = config_options.into_option();
1766 self
1767 }
1768
1769 #[must_use]
1775 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1776 self.meta = meta.into_option();
1777 self
1778 }
1779}
1780
1781#[serde_as]
1790#[skip_serializing_none]
1791#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1792#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1793#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_RESUME_METHOD_NAME)))]
1794#[serde(rename_all = "camelCase")]
1795#[non_exhaustive]
1796pub struct ResumeSessionRequest {
1797 pub session_id: SessionId,
1799 pub cwd: PathBuf,
1801 #[serde_as(deserialize_as = "DefaultOnNull")]
1808 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-null" = true)))]
1809 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1810 pub additional_directories: Vec<PathBuf>,
1811 #[serde_as(deserialize_as = "DefaultOnNull")]
1813 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-null" = true)))]
1814 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1815 pub mcp_servers: Vec<McpServer>,
1816 #[cfg(feature = "unstable_session_system_prompt")]
1828 #[serde(default)]
1829 pub system_prompt: Option<SystemPrompt>,
1830 #[serde_as(deserialize_as = "DefaultOnError")]
1836 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1837 #[serde(default)]
1838 #[serde(rename = "_meta")]
1839 pub meta: Option<Meta>,
1840}
1841
1842impl ResumeSessionRequest {
1843 #[must_use]
1845 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1846 Self {
1847 session_id: session_id.into(),
1848 cwd: cwd.into(),
1849 additional_directories: vec![],
1850 mcp_servers: vec![],
1851 #[cfg(feature = "unstable_session_system_prompt")]
1852 system_prompt: None,
1853 meta: None,
1854 }
1855 }
1856
1857 #[must_use]
1859 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1860 self.additional_directories = additional_directories;
1861 self
1862 }
1863
1864 #[must_use]
1866 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1867 self.mcp_servers = mcp_servers;
1868 self
1869 }
1870
1871 #[cfg(feature = "unstable_session_system_prompt")]
1877 #[must_use]
1878 pub fn system_prompt(mut self, system_prompt: impl IntoOption<SystemPrompt>) -> Self {
1879 self.system_prompt = system_prompt.into_option();
1880 self
1881 }
1882
1883 #[must_use]
1889 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1890 self.meta = meta.into_option();
1891 self
1892 }
1893}
1894
1895crate::serde_util::default_on_null! {
1896 #[serde_as]
1898 #[skip_serializing_none]
1899 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1900 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
1901 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_RESUME_METHOD_NAME)))]
1902 #[serde(rename_all = "camelCase")]
1903 #[non_exhaustive]
1904 pub struct ResumeSessionResponse {
1905 #[serde_as(deserialize_as = "DefaultOnError")]
1909 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1910 #[serde(default)]
1911 pub modes: Option<SessionModeState>,
1912 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_>>>")]
1914 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1915 #[serde(default)]
1916 pub config_options: Option<Vec<SessionConfigOption>>,
1917 #[serde_as(deserialize_as = "DefaultOnError")]
1923 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1924 #[serde(default)]
1925 #[serde(rename = "_meta")]
1926 pub meta: Option<Meta>,
1927 }
1928}
1929
1930impl ResumeSessionResponse {
1931 #[must_use]
1933 pub fn new() -> Self {
1934 Self::default()
1935 }
1936
1937 #[must_use]
1941 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1942 self.modes = modes.into_option();
1943 self
1944 }
1945
1946 #[must_use]
1948 pub fn config_options(
1949 mut self,
1950 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1951 ) -> Self {
1952 self.config_options = config_options.into_option();
1953 self
1954 }
1955
1956 #[must_use]
1962 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1963 self.meta = meta.into_option();
1964 self
1965 }
1966}
1967
1968#[serde_as]
1978#[skip_serializing_none]
1979#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1980#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1981#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_CLOSE_METHOD_NAME)))]
1982#[serde(rename_all = "camelCase")]
1983#[non_exhaustive]
1984pub struct CloseSessionRequest {
1985 pub session_id: SessionId,
1987 #[serde_as(deserialize_as = "DefaultOnError")]
1993 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1994 #[serde(default)]
1995 #[serde(rename = "_meta")]
1996 pub meta: Option<Meta>,
1997}
1998
1999impl CloseSessionRequest {
2000 #[must_use]
2002 pub fn new(session_id: impl Into<SessionId>) -> Self {
2003 Self {
2004 session_id: session_id.into(),
2005 meta: None,
2006 }
2007 }
2008
2009 #[must_use]
2015 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2016 self.meta = meta.into_option();
2017 self
2018 }
2019}
2020
2021crate::serde_util::default_on_null! {
2022 #[serde_as]
2024 #[skip_serializing_none]
2025 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2026 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
2027 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_CLOSE_METHOD_NAME)))]
2028 #[serde(rename_all = "camelCase")]
2029 #[non_exhaustive]
2030 pub struct CloseSessionResponse {
2031 #[serde_as(deserialize_as = "DefaultOnError")]
2037 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2038 #[serde(default)]
2039 #[serde(rename = "_meta")]
2040 pub meta: Option<Meta>,
2041 }
2042}
2043
2044impl CloseSessionResponse {
2045 #[must_use]
2047 pub fn new() -> Self {
2048 Self::default()
2049 }
2050
2051 #[must_use]
2057 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2058 self.meta = meta.into_option();
2059 self
2060 }
2061}
2062
2063#[cfg(feature = "unstable_session_status")]
2077#[serde_as]
2078#[skip_serializing_none]
2079#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2080#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2081#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_STATUS_METHOD_NAME)))]
2082#[serde(rename_all = "camelCase")]
2083#[non_exhaustive]
2084pub struct SessionStatusRequest {
2085 pub session_id: SessionId,
2087 #[serde_as(deserialize_as = "DefaultOnError")]
2093 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2094 #[serde(default)]
2095 #[serde(rename = "_meta")]
2096 pub meta: Option<Meta>,
2097}
2098
2099#[cfg(feature = "unstable_session_status")]
2100impl SessionStatusRequest {
2101 #[must_use]
2103 pub fn new(session_id: impl Into<SessionId>) -> Self {
2104 Self {
2105 session_id: session_id.into(),
2106 meta: None,
2107 }
2108 }
2109
2110 #[must_use]
2116 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2117 self.meta = meta.into_option();
2118 self
2119 }
2120}
2121
2122#[cfg(feature = "unstable_session_status")]
2131#[serde_as]
2132#[skip_serializing_none]
2133#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2134#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2135#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_STATUS_METHOD_NAME)))]
2136#[serde(rename_all = "camelCase")]
2137#[non_exhaustive]
2138pub struct SessionStatusResponse {
2139 pub status: SessionStatus,
2143 #[serde_as(deserialize_as = "DefaultOnError")]
2149 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2150 #[serde(default)]
2151 #[serde(rename = "_meta")]
2152 pub meta: Option<Meta>,
2153}
2154
2155#[cfg(feature = "unstable_session_status")]
2156impl SessionStatusResponse {
2157 #[must_use]
2159 pub fn new(status: SessionStatus) -> Self {
2160 Self { status, meta: None }
2161 }
2162
2163 #[must_use]
2169 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2170 self.meta = meta.into_option();
2171 self
2172 }
2173}
2174
2175#[cfg(feature = "unstable_session_status")]
2181#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2182#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
2183#[serde(rename_all = "snake_case")]
2184#[non_exhaustive]
2185pub enum SessionStatus {
2186 Open,
2193 Saved,
2197 #[serde(untagged)]
2204 Other(String),
2205}
2206
2207crate::serde_util::default_on_null! {
2210 #[serde_as]
2214 #[skip_serializing_none]
2215 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2216 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
2217 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_LIST_METHOD_NAME)))]
2218 #[serde(rename_all = "camelCase")]
2219 #[non_exhaustive]
2220 pub struct ListSessionsRequest {
2221 #[serde(default)]
2223 pub cwd: Option<PathBuf>,
2224 #[serde(default)]
2226 pub cursor: Option<String>,
2227 #[cfg(feature = "unstable_session_archive")]
2237 #[serde(default)]
2238 pub archived: Option<SessionArchiveFilter>,
2239 #[serde_as(deserialize_as = "DefaultOnError")]
2245 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2246 #[serde(default)]
2247 #[serde(rename = "_meta")]
2248 pub meta: Option<Meta>,
2249 }
2250}
2251
2252impl ListSessionsRequest {
2253 #[must_use]
2255 pub fn new() -> Self {
2256 Self::default()
2257 }
2258
2259 #[must_use]
2261 pub fn cwd(mut self, cwd: impl IntoOption<PathBuf>) -> Self {
2262 self.cwd = cwd.into_option();
2263 self
2264 }
2265
2266 #[must_use]
2268 pub fn cursor(mut self, cursor: impl IntoOption<String>) -> Self {
2269 self.cursor = cursor.into_option();
2270 self
2271 }
2272
2273 #[cfg(feature = "unstable_session_archive")]
2279 #[must_use]
2280 pub fn archived(mut self, archived: impl IntoOption<SessionArchiveFilter>) -> Self {
2281 self.archived = archived.into_option();
2282 self
2283 }
2284
2285 #[must_use]
2291 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2292 self.meta = meta.into_option();
2293 self
2294 }
2295}
2296
2297#[serde_as]
2299#[skip_serializing_none]
2300#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2301#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2302#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_LIST_METHOD_NAME)))]
2303#[serde(rename_all = "camelCase")]
2304#[non_exhaustive]
2305pub struct ListSessionsResponse {
2306 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_>>")]
2308 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
2309 pub sessions: Vec<SessionInfo>,
2310 #[serde_as(deserialize_as = "DefaultOnError")]
2313 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2314 #[serde(default)]
2315 pub next_cursor: Option<String>,
2316 #[serde_as(deserialize_as = "DefaultOnError")]
2322 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2323 #[serde(default)]
2324 #[serde(rename = "_meta")]
2325 pub meta: Option<Meta>,
2326}
2327
2328impl ListSessionsResponse {
2329 #[must_use]
2331 pub fn new(sessions: Vec<SessionInfo>) -> Self {
2332 Self {
2333 sessions,
2334 next_cursor: None,
2335 meta: None,
2336 }
2337 }
2338
2339 #[must_use]
2341 pub fn next_cursor(mut self, next_cursor: impl IntoOption<String>) -> Self {
2342 self.next_cursor = next_cursor.into_option();
2343 self
2344 }
2345
2346 #[must_use]
2352 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2353 self.meta = meta.into_option();
2354 self
2355 }
2356}
2357
2358#[serde_as]
2364#[skip_serializing_none]
2365#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2366#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2367#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_DELETE_METHOD_NAME)))]
2368#[serde(rename_all = "camelCase")]
2369#[non_exhaustive]
2370pub struct DeleteSessionRequest {
2371 pub session_id: SessionId,
2373 #[serde_as(deserialize_as = "DefaultOnError")]
2379 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2380 #[serde(default)]
2381 #[serde(rename = "_meta")]
2382 pub meta: Option<Meta>,
2383}
2384
2385impl DeleteSessionRequest {
2386 #[must_use]
2388 pub fn new(session_id: impl Into<SessionId>) -> Self {
2389 Self {
2390 session_id: session_id.into(),
2391 meta: None,
2392 }
2393 }
2394
2395 #[must_use]
2401 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2402 self.meta = meta.into_option();
2403 self
2404 }
2405}
2406
2407crate::serde_util::default_on_null! {
2408 #[serde_as]
2410 #[skip_serializing_none]
2411 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2412 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
2413 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_DELETE_METHOD_NAME)))]
2414 #[serde(rename_all = "camelCase")]
2415 #[non_exhaustive]
2416 pub struct DeleteSessionResponse {
2417 #[serde_as(deserialize_as = "DefaultOnError")]
2423 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2424 #[serde(default)]
2425 #[serde(rename = "_meta")]
2426 pub meta: Option<Meta>,
2427 }
2428}
2429
2430impl DeleteSessionResponse {
2431 #[must_use]
2433 pub fn new() -> Self {
2434 Self::default()
2435 }
2436
2437 #[must_use]
2443 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2444 self.meta = meta.into_option();
2445 self
2446 }
2447}
2448
2449#[cfg(feature = "unstable_session_archive")]
2465#[serde_as]
2466#[skip_serializing_none]
2467#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2468#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2469#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_ARCHIVE_METHOD_NAME)))]
2470#[serde(rename_all = "camelCase")]
2471#[non_exhaustive]
2472pub struct ArchiveSessionRequest {
2473 pub session_id: SessionId,
2475 #[serde_as(deserialize_as = "DefaultOnError")]
2481 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2482 #[serde(default)]
2483 #[serde(rename = "_meta")]
2484 pub meta: Option<Meta>,
2485}
2486
2487#[cfg(feature = "unstable_session_archive")]
2488impl ArchiveSessionRequest {
2489 #[must_use]
2491 pub fn new(session_id: impl Into<SessionId>) -> Self {
2492 Self {
2493 session_id: session_id.into(),
2494 meta: None,
2495 }
2496 }
2497
2498 #[must_use]
2504 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2505 self.meta = meta.into_option();
2506 self
2507 }
2508}
2509
2510#[cfg(feature = "unstable_session_archive")]
2511crate::serde_util::default_on_null! {
2512 #[serde_as]
2518 #[skip_serializing_none]
2519 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2520 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
2521 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_ARCHIVE_METHOD_NAME)))]
2522 #[serde(rename_all = "camelCase")]
2523 #[non_exhaustive]
2524 pub struct ArchiveSessionResponse {
2525 #[serde_as(deserialize_as = "DefaultOnError")]
2531 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2532 #[serde(default)]
2533 #[serde(rename = "_meta")]
2534 pub meta: Option<Meta>,
2535 }
2536}
2537
2538#[cfg(feature = "unstable_session_archive")]
2539impl ArchiveSessionResponse {
2540 #[must_use]
2542 pub fn new() -> Self {
2543 Self::default()
2544 }
2545
2546 #[must_use]
2552 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2553 self.meta = meta.into_option();
2554 self
2555 }
2556}
2557
2558#[cfg(feature = "unstable_session_archive")]
2573#[serde_as]
2574#[skip_serializing_none]
2575#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2576#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2577#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_UNARCHIVE_METHOD_NAME)))]
2578#[serde(rename_all = "camelCase")]
2579#[non_exhaustive]
2580pub struct UnarchiveSessionRequest {
2581 pub session_id: SessionId,
2583 #[serde_as(deserialize_as = "DefaultOnError")]
2589 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2590 #[serde(default)]
2591 #[serde(rename = "_meta")]
2592 pub meta: Option<Meta>,
2593}
2594
2595#[cfg(feature = "unstable_session_archive")]
2596impl UnarchiveSessionRequest {
2597 #[must_use]
2599 pub fn new(session_id: impl Into<SessionId>) -> Self {
2600 Self {
2601 session_id: session_id.into(),
2602 meta: None,
2603 }
2604 }
2605
2606 #[must_use]
2612 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2613 self.meta = meta.into_option();
2614 self
2615 }
2616}
2617
2618#[cfg(feature = "unstable_session_archive")]
2619crate::serde_util::default_on_null! {
2620 #[serde_as]
2626 #[skip_serializing_none]
2627 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2628 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
2629 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_UNARCHIVE_METHOD_NAME)))]
2630 #[serde(rename_all = "camelCase")]
2631 #[non_exhaustive]
2632 pub struct UnarchiveSessionResponse {
2633 #[serde_as(deserialize_as = "DefaultOnError")]
2639 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2640 #[serde(default)]
2641 #[serde(rename = "_meta")]
2642 pub meta: Option<Meta>,
2643 }
2644}
2645
2646#[cfg(feature = "unstable_session_archive")]
2647impl UnarchiveSessionResponse {
2648 #[must_use]
2650 pub fn new() -> Self {
2651 Self::default()
2652 }
2653
2654 #[must_use]
2660 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2661 self.meta = meta.into_option();
2662 self
2663 }
2664}
2665
2666#[cfg(feature = "unstable_session_archive")]
2675#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2676#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
2677#[serde(rename_all = "snake_case")]
2678#[non_exhaustive]
2679pub enum SessionArchiveFilter {
2680 #[default]
2682 Exclude,
2683 Include,
2685 Only,
2687 #[serde(untagged)]
2693 Other(String),
2694}
2695
2696#[serde_as]
2698#[skip_serializing_none]
2699#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2700#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2701#[serde(rename_all = "camelCase")]
2702#[non_exhaustive]
2703pub struct SessionInfo {
2704 pub session_id: SessionId,
2706 pub cwd: PathBuf,
2708 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_>>")]
2714 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
2715 #[serde(default, skip_serializing_if = "Vec::is_empty")]
2716 pub additional_directories: Vec<PathBuf>,
2717
2718 #[serde_as(deserialize_as = "DefaultOnError")]
2720 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2721 #[serde(default)]
2722 pub title: Option<String>,
2723 #[serde_as(deserialize_as = "DefaultOnError")]
2725 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2726 #[serde(default)]
2727 pub updated_at: Option<String>,
2728 #[cfg(feature = "unstable_session_archive")]
2737 #[serde_as(deserialize_as = "DefaultOnError")]
2738 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2739 #[serde(default)]
2740 pub archived: Option<bool>,
2741 #[serde_as(deserialize_as = "DefaultOnError")]
2747 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2748 #[serde(default)]
2749 #[serde(rename = "_meta")]
2750 pub meta: Option<Meta>,
2751}
2752
2753impl SessionInfo {
2754 #[must_use]
2756 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
2757 Self {
2758 session_id: session_id.into(),
2759 cwd: cwd.into(),
2760 additional_directories: vec![],
2761 title: None,
2762 updated_at: None,
2763 #[cfg(feature = "unstable_session_archive")]
2764 archived: None,
2765 meta: None,
2766 }
2767 }
2768
2769 #[must_use]
2771 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
2772 self.additional_directories = additional_directories;
2773 self
2774 }
2775
2776 #[must_use]
2778 pub fn title(mut self, title: impl IntoOption<String>) -> Self {
2779 self.title = title.into_option();
2780 self
2781 }
2782
2783 #[must_use]
2785 pub fn updated_at(mut self, updated_at: impl IntoOption<String>) -> Self {
2786 self.updated_at = updated_at.into_option();
2787 self
2788 }
2789
2790 #[cfg(feature = "unstable_session_archive")]
2796 #[must_use]
2797 pub fn archived(mut self, archived: impl IntoOption<bool>) -> Self {
2798 self.archived = archived.into_option();
2799 self
2800 }
2801
2802 #[must_use]
2808 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2809 self.meta = meta.into_option();
2810 self
2811 }
2812}
2813
2814#[cfg(feature = "unstable_session_set_title")]
2830#[serde_as]
2831#[skip_serializing_none]
2832#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2833#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2834#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_TITLE_METHOD_NAME)))]
2835#[serde(rename_all = "camelCase")]
2836#[non_exhaustive]
2837pub struct SetSessionTitleRequest {
2838 pub session_id: SessionId,
2840 pub title: String,
2847 #[serde_as(deserialize_as = "DefaultOnError")]
2853 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2854 #[serde(default)]
2855 #[serde(rename = "_meta")]
2856 pub meta: Option<Meta>,
2857}
2858
2859#[cfg(feature = "unstable_session_set_title")]
2860impl SetSessionTitleRequest {
2861 #[must_use]
2863 pub fn new(session_id: impl Into<SessionId>, title: impl Into<String>) -> Self {
2864 Self {
2865 session_id: session_id.into(),
2866 title: title.into(),
2867 meta: None,
2868 }
2869 }
2870
2871 #[must_use]
2877 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2878 self.meta = meta.into_option();
2879 self
2880 }
2881}
2882
2883#[cfg(feature = "unstable_session_set_title")]
2889#[serde_as]
2890#[skip_serializing_none]
2891#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2892#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2893#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_TITLE_METHOD_NAME)))]
2894#[serde(rename_all = "camelCase")]
2895#[non_exhaustive]
2896pub struct SetSessionTitleResponse {
2897 pub title: String,
2902 #[serde_as(deserialize_as = "DefaultOnError")]
2908 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2909 #[serde(default)]
2910 #[serde(rename = "_meta")]
2911 pub meta: Option<Meta>,
2912}
2913
2914#[cfg(feature = "unstable_session_set_title")]
2915impl SetSessionTitleResponse {
2916 #[must_use]
2918 pub fn new(title: impl Into<String>) -> Self {
2919 Self {
2920 title: title.into(),
2921 meta: None,
2922 }
2923 }
2924
2925 #[must_use]
2931 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2932 self.meta = meta.into_option();
2933 self
2934 }
2935}
2936
2937#[serde_as]
2941#[skip_serializing_none]
2942#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2943#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2944#[serde(rename_all = "camelCase")]
2945#[non_exhaustive]
2946pub struct SessionModeState {
2947 pub current_mode_id: SessionModeId,
2949 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_>>")]
2951 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
2952 pub available_modes: Vec<SessionMode>,
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 SessionModeState {
2966 #[must_use]
2968 pub fn new(
2969 current_mode_id: impl Into<SessionModeId>,
2970 available_modes: Vec<SessionMode>,
2971 ) -> Self {
2972 Self {
2973 current_mode_id: current_mode_id.into(),
2974 available_modes,
2975 meta: None,
2976 }
2977 }
2978
2979 #[must_use]
2985 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2986 self.meta = meta.into_option();
2987 self
2988 }
2989}
2990
2991#[serde_as]
2995#[skip_serializing_none]
2996#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2997#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2998#[serde(rename_all = "camelCase")]
2999#[non_exhaustive]
3000pub struct SessionMode {
3001 pub id: SessionModeId,
3003 pub name: String,
3005 #[serde_as(deserialize_as = "DefaultOnError")]
3007 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3008 #[serde(default)]
3009 pub description: Option<String>,
3010 #[serde_as(deserialize_as = "DefaultOnError")]
3016 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3017 #[serde(default)]
3018 #[serde(rename = "_meta")]
3019 pub meta: Option<Meta>,
3020}
3021
3022impl SessionMode {
3023 #[must_use]
3025 pub fn new(id: impl Into<SessionModeId>, name: impl Into<String>) -> Self {
3026 Self {
3027 id: id.into(),
3028 name: name.into(),
3029 description: None,
3030 meta: None,
3031 }
3032 }
3033
3034 #[must_use]
3036 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
3037 self.description = description.into_option();
3038 self
3039 }
3040
3041 #[must_use]
3047 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3048 self.meta = meta.into_option();
3049 self
3050 }
3051}
3052
3053#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3055#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, From, Display)]
3056#[serde(transparent)]
3057#[from(Arc<str>, String, &'static str)]
3058#[non_exhaustive]
3059pub struct SessionModeId(pub Arc<str>);
3060
3061impl SessionModeId {
3062 #[must_use]
3064 pub fn new(id: impl Into<Arc<str>>) -> Self {
3065 Self(id.into())
3066 }
3067}
3068
3069#[serde_as]
3071#[skip_serializing_none]
3072#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3073#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3074#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODE_METHOD_NAME)))]
3075#[serde(rename_all = "camelCase")]
3076#[non_exhaustive]
3077pub struct SetSessionModeRequest {
3078 pub session_id: SessionId,
3080 pub mode_id: SessionModeId,
3082 #[serde_as(deserialize_as = "DefaultOnError")]
3088 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3089 #[serde(default)]
3090 #[serde(rename = "_meta")]
3091 pub meta: Option<Meta>,
3092}
3093
3094impl SetSessionModeRequest {
3095 #[must_use]
3097 pub fn new(session_id: impl Into<SessionId>, mode_id: impl Into<SessionModeId>) -> Self {
3098 Self {
3099 session_id: session_id.into(),
3100 mode_id: mode_id.into(),
3101 meta: None,
3102 }
3103 }
3104
3105 #[must_use]
3107 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3108 self.meta = meta.into_option();
3109 self
3110 }
3111}
3112
3113crate::serde_util::default_on_null! {
3114 #[serde_as]
3116 #[skip_serializing_none]
3117 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3118 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
3119 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODE_METHOD_NAME)))]
3120 #[serde(rename_all = "camelCase")]
3121 #[non_exhaustive]
3122 pub struct SetSessionModeResponse {
3123 #[serde_as(deserialize_as = "DefaultOnError")]
3129 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3130 #[serde(default)]
3131 #[serde(rename = "_meta")]
3132 pub meta: Option<Meta>,
3133 }
3134}
3135
3136impl SetSessionModeResponse {
3137 #[must_use]
3139 pub fn new() -> Self {
3140 Self::default()
3141 }
3142
3143 #[must_use]
3149 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3150 self.meta = meta.into_option();
3151 self
3152 }
3153}
3154
3155#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3159#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, From, Display)]
3160#[serde(transparent)]
3161#[from(Arc<str>, String, &'static str)]
3162#[non_exhaustive]
3163pub struct SessionConfigId(pub Arc<str>);
3164
3165impl SessionConfigId {
3166 #[must_use]
3168 pub fn new(id: impl Into<Arc<str>>) -> Self {
3169 Self(id.into())
3170 }
3171}
3172
3173#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3175#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, From, Display)]
3176#[serde(transparent)]
3177#[from(Arc<str>, String, &'static str)]
3178#[non_exhaustive]
3179pub struct SessionConfigValueId(pub Arc<str>);
3180
3181impl SessionConfigValueId {
3182 #[must_use]
3184 pub fn new(id: impl Into<Arc<str>>) -> Self {
3185 Self(id.into())
3186 }
3187}
3188
3189#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3191#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, From, Display)]
3192#[serde(transparent)]
3193#[from(Arc<str>, String, &'static str)]
3194#[non_exhaustive]
3195pub struct SessionConfigGroupId(pub Arc<str>);
3196
3197impl SessionConfigGroupId {
3198 #[must_use]
3200 pub fn new(id: impl Into<Arc<str>>) -> Self {
3201 Self(id.into())
3202 }
3203}
3204
3205#[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 SessionConfigSelectOption {
3213 pub value: SessionConfigValueId,
3215 pub name: String,
3217 #[serde_as(deserialize_as = "DefaultOnError")]
3219 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3220 #[serde(default)]
3221 pub description: Option<String>,
3222 #[serde_as(deserialize_as = "DefaultOnError")]
3228 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3229 #[serde(default)]
3230 #[serde(rename = "_meta")]
3231 pub meta: Option<Meta>,
3232}
3233
3234impl SessionConfigSelectOption {
3235 #[must_use]
3237 pub fn new(value: impl Into<SessionConfigValueId>, name: impl Into<String>) -> Self {
3238 Self {
3239 value: value.into(),
3240 name: name.into(),
3241 description: None,
3242 meta: None,
3243 }
3244 }
3245
3246 #[must_use]
3248 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
3249 self.description = description.into_option();
3250 self
3251 }
3252
3253 #[must_use]
3259 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3260 self.meta = meta.into_option();
3261 self
3262 }
3263}
3264
3265#[serde_as]
3267#[skip_serializing_none]
3268#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3269#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3270#[serde(rename_all = "camelCase")]
3271#[non_exhaustive]
3272pub struct SessionConfigSelectGroup {
3273 pub group: SessionConfigGroupId,
3275 pub name: String,
3277 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_>>")]
3279 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
3280 pub options: Vec<SessionConfigSelectOption>,
3281 #[serde_as(deserialize_as = "DefaultOnError")]
3287 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3288 #[serde(default)]
3289 #[serde(rename = "_meta")]
3290 pub meta: Option<Meta>,
3291}
3292
3293impl SessionConfigSelectGroup {
3294 #[must_use]
3296 pub fn new(
3297 group: impl Into<SessionConfigGroupId>,
3298 name: impl Into<String>,
3299 options: Vec<SessionConfigSelectOption>,
3300 ) -> Self {
3301 Self {
3302 group: group.into(),
3303 name: name.into(),
3304 options,
3305 meta: None,
3306 }
3307 }
3308
3309 #[must_use]
3315 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3316 self.meta = meta.into_option();
3317 self
3318 }
3319}
3320
3321#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3323#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3324#[serde(untagged)]
3325#[non_exhaustive]
3326pub enum SessionConfigSelectOptions {
3327 Ungrouped(Vec<SessionConfigSelectOption>),
3329 Grouped(Vec<SessionConfigSelectGroup>),
3331}
3332
3333impl From<Vec<SessionConfigSelectOption>> for SessionConfigSelectOptions {
3334 fn from(options: Vec<SessionConfigSelectOption>) -> Self {
3335 SessionConfigSelectOptions::Ungrouped(options)
3336 }
3337}
3338
3339impl From<Vec<SessionConfigSelectGroup>> for SessionConfigSelectOptions {
3340 fn from(groups: Vec<SessionConfigSelectGroup>) -> Self {
3341 SessionConfigSelectOptions::Grouped(groups)
3342 }
3343}
3344
3345#[skip_serializing_none]
3347#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3348#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3349#[serde(rename_all = "camelCase")]
3350#[non_exhaustive]
3351pub struct SessionConfigSelect {
3352 pub current_value: SessionConfigValueId,
3354 pub options: SessionConfigSelectOptions,
3356}
3357
3358impl SessionConfigSelect {
3359 #[must_use]
3361 pub fn new(
3362 current_value: impl Into<SessionConfigValueId>,
3363 options: impl Into<SessionConfigSelectOptions>,
3364 ) -> Self {
3365 Self {
3366 current_value: current_value.into(),
3367 options: options.into(),
3368 }
3369 }
3370}
3371
3372#[skip_serializing_none]
3374#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3375#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3376#[serde(rename_all = "camelCase")]
3377#[non_exhaustive]
3378pub struct SessionConfigBoolean {
3379 pub current_value: bool,
3381}
3382
3383impl SessionConfigBoolean {
3384 #[must_use]
3386 pub fn new(current_value: bool) -> Self {
3387 Self { current_value }
3388 }
3389}
3390
3391#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3401#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3402#[serde(rename_all = "snake_case")]
3403#[non_exhaustive]
3404pub enum SessionConfigOptionCategory {
3405 Mode,
3407 Model,
3409 ModelConfig,
3411 ThoughtLevel,
3413 #[serde(untagged)]
3415 Other(String),
3416}
3417
3418#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3420#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3421#[serde(tag = "type", rename_all = "snake_case")]
3422#[cfg_attr(feature = "schemars", schemars(extend("discriminator" = {"propertyName": "type"})))]
3423#[non_exhaustive]
3424pub enum SessionConfigKind {
3425 Select(SessionConfigSelect),
3427 Boolean(SessionConfigBoolean),
3429}
3430
3431#[serde_as]
3433#[skip_serializing_none]
3434#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3435#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3436#[serde(rename_all = "camelCase")]
3437#[non_exhaustive]
3438pub struct SessionConfigOption {
3439 pub id: SessionConfigId,
3441 pub name: String,
3443 #[serde_as(deserialize_as = "DefaultOnError")]
3445 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3446 #[serde(default)]
3447 pub description: Option<String>,
3448 #[serde_as(deserialize_as = "DefaultOnError")]
3450 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3451 #[serde(default)]
3452 pub category: Option<SessionConfigOptionCategory>,
3453 #[serde(flatten)]
3455 pub kind: SessionConfigKind,
3456 #[serde_as(deserialize_as = "DefaultOnError")]
3462 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3463 #[serde(default)]
3464 #[serde(rename = "_meta")]
3465 pub meta: Option<Meta>,
3466}
3467
3468impl SessionConfigOption {
3469 #[must_use]
3471 pub fn new(
3472 id: impl Into<SessionConfigId>,
3473 name: impl Into<String>,
3474 kind: SessionConfigKind,
3475 ) -> Self {
3476 Self {
3477 id: id.into(),
3478 name: name.into(),
3479 description: None,
3480 category: None,
3481 kind,
3482 meta: None,
3483 }
3484 }
3485
3486 #[must_use]
3488 pub fn select(
3489 id: impl Into<SessionConfigId>,
3490 name: impl Into<String>,
3491 current_value: impl Into<SessionConfigValueId>,
3492 options: impl Into<SessionConfigSelectOptions>,
3493 ) -> Self {
3494 Self::new(
3495 id,
3496 name,
3497 SessionConfigKind::Select(SessionConfigSelect::new(current_value, options)),
3498 )
3499 }
3500
3501 #[must_use]
3503 pub fn boolean(
3504 id: impl Into<SessionConfigId>,
3505 name: impl Into<String>,
3506 current_value: bool,
3507 ) -> Self {
3508 Self::new(
3509 id,
3510 name,
3511 SessionConfigKind::Boolean(SessionConfigBoolean::new(current_value)),
3512 )
3513 }
3514
3515 #[must_use]
3517 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
3518 self.description = description.into_option();
3519 self
3520 }
3521
3522 #[must_use]
3524 pub fn category(mut self, category: impl IntoOption<SessionConfigOptionCategory>) -> Self {
3525 self.category = category.into_option();
3526 self
3527 }
3528
3529 #[must_use]
3535 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3536 self.meta = meta.into_option();
3537 self
3538 }
3539}
3540
3541#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3552#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3553#[serde(tag = "type", rename_all = "snake_case")]
3554#[non_exhaustive]
3555pub enum SessionConfigOptionValue {
3556 Boolean {
3558 value: bool,
3560 },
3561 #[serde(untagged)]
3567 ValueId {
3568 value: SessionConfigValueId,
3570 },
3571}
3572
3573impl SessionConfigOptionValue {
3574 #[must_use]
3576 pub fn value_id(id: impl Into<SessionConfigValueId>) -> Self {
3577 Self::ValueId { value: id.into() }
3578 }
3579
3580 #[must_use]
3582 pub fn boolean(val: bool) -> Self {
3583 Self::Boolean { value: val }
3584 }
3585
3586 #[must_use]
3589 pub fn as_value_id(&self) -> Option<&SessionConfigValueId> {
3590 match self {
3591 Self::ValueId { value } => Some(value),
3592 _ => None,
3593 }
3594 }
3595
3596 #[must_use]
3598 pub fn as_bool(&self) -> Option<bool> {
3599 match self {
3600 Self::Boolean { value } => Some(*value),
3601 _ => None,
3602 }
3603 }
3604}
3605
3606impl From<SessionConfigValueId> for SessionConfigOptionValue {
3607 fn from(value: SessionConfigValueId) -> Self {
3608 Self::ValueId { value }
3609 }
3610}
3611
3612impl From<bool> for SessionConfigOptionValue {
3613 fn from(value: bool) -> Self {
3614 Self::Boolean { value }
3615 }
3616}
3617
3618impl From<&str> for SessionConfigOptionValue {
3619 fn from(value: &str) -> Self {
3620 Self::ValueId {
3621 value: SessionConfigValueId::new(value),
3622 }
3623 }
3624}
3625
3626#[serde_as]
3628#[skip_serializing_none]
3629#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3630#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3631#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_CONFIG_OPTION_METHOD_NAME)))]
3632#[serde(rename_all = "camelCase")]
3633#[non_exhaustive]
3634pub struct SetSessionConfigOptionRequest {
3635 pub session_id: SessionId,
3637 pub config_id: SessionConfigId,
3639 #[serde(flatten)]
3644 pub value: SessionConfigOptionValue,
3645 #[serde_as(deserialize_as = "DefaultOnError")]
3651 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3652 #[serde(default)]
3653 #[serde(rename = "_meta")]
3654 pub meta: Option<Meta>,
3655}
3656
3657impl SetSessionConfigOptionRequest {
3658 #[must_use]
3660 pub fn new(
3661 session_id: impl Into<SessionId>,
3662 config_id: impl Into<SessionConfigId>,
3663 value: impl Into<SessionConfigOptionValue>,
3664 ) -> Self {
3665 Self {
3666 session_id: session_id.into(),
3667 config_id: config_id.into(),
3668 value: value.into(),
3669 meta: None,
3670 }
3671 }
3672
3673 #[must_use]
3679 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3680 self.meta = meta.into_option();
3681 self
3682 }
3683}
3684
3685#[serde_as]
3687#[skip_serializing_none]
3688#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3689#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3690#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_CONFIG_OPTION_METHOD_NAME)))]
3691#[serde(rename_all = "camelCase")]
3692#[non_exhaustive]
3693pub struct SetSessionConfigOptionResponse {
3694 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_>>")]
3696 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
3697 pub config_options: Vec<SessionConfigOption>,
3698 #[serde_as(deserialize_as = "DefaultOnError")]
3704 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3705 #[serde(default)]
3706 #[serde(rename = "_meta")]
3707 pub meta: Option<Meta>,
3708}
3709
3710impl SetSessionConfigOptionResponse {
3711 #[must_use]
3713 pub fn new(config_options: Vec<SessionConfigOption>) -> Self {
3714 Self {
3715 config_options,
3716 meta: None,
3717 }
3718 }
3719
3720 #[must_use]
3726 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3727 self.meta = meta.into_option();
3728 self
3729 }
3730}
3731
3732#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3741#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3742#[serde(tag = "type", rename_all = "snake_case")]
3743#[non_exhaustive]
3744pub enum McpServer {
3745 Http(McpServerHttp),
3749 Sse(McpServerSse),
3753 #[cfg(feature = "unstable_mcp_over_acp")]
3762 Acp(McpServerAcp),
3763 #[serde(untagged)]
3767 Stdio(McpServerStdio),
3768}
3769
3770#[serde_as]
3772#[skip_serializing_none]
3773#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3774#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3775#[serde(rename_all = "camelCase")]
3776#[non_exhaustive]
3777pub struct McpServerHttp {
3778 pub name: String,
3780 pub url: String,
3782 #[serde_as(deserialize_as = "DefaultOnNull")]
3784 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-null" = true)))]
3785 pub headers: Vec<HttpHeader>,
3786 #[serde_as(deserialize_as = "DefaultOnError")]
3792 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3793 #[serde(default)]
3794 #[serde(rename = "_meta")]
3795 pub meta: Option<Meta>,
3796}
3797
3798impl McpServerHttp {
3799 #[must_use]
3801 pub fn new(name: impl Into<String>, url: impl Into<String>) -> Self {
3802 Self {
3803 name: name.into(),
3804 url: url.into(),
3805 headers: Vec::new(),
3806 meta: None,
3807 }
3808 }
3809
3810 #[must_use]
3812 pub fn headers(mut self, headers: Vec<HttpHeader>) -> Self {
3813 self.headers = headers;
3814 self
3815 }
3816
3817 #[must_use]
3823 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3824 self.meta = meta.into_option();
3825 self
3826 }
3827}
3828
3829#[serde_as]
3831#[skip_serializing_none]
3832#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3833#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3834#[serde(rename_all = "camelCase")]
3835#[non_exhaustive]
3836pub struct McpServerSse {
3837 pub name: String,
3839 pub url: String,
3841 #[serde_as(deserialize_as = "DefaultOnNull")]
3843 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-null" = true)))]
3844 pub headers: Vec<HttpHeader>,
3845 #[serde_as(deserialize_as = "DefaultOnError")]
3851 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3852 #[serde(default)]
3853 #[serde(rename = "_meta")]
3854 pub meta: Option<Meta>,
3855}
3856
3857impl McpServerSse {
3858 #[must_use]
3860 pub fn new(name: impl Into<String>, url: impl Into<String>) -> Self {
3861 Self {
3862 name: name.into(),
3863 url: url.into(),
3864 headers: Vec::new(),
3865 meta: None,
3866 }
3867 }
3868
3869 #[must_use]
3871 pub fn headers(mut self, headers: Vec<HttpHeader>) -> Self {
3872 self.headers = headers;
3873 self
3874 }
3875
3876 #[must_use]
3882 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3883 self.meta = meta.into_option();
3884 self
3885 }
3886}
3887
3888#[cfg(feature = "unstable_mcp_over_acp")]
3897#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3898#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Display, From)]
3899#[serde(transparent)]
3900#[from(Arc<str>, String, &'static str)]
3901#[non_exhaustive]
3902pub struct McpServerAcpId(pub Arc<str>);
3903
3904#[cfg(feature = "unstable_mcp_over_acp")]
3905impl McpServerAcpId {
3906 #[must_use]
3908 pub fn new(id: impl Into<Arc<str>>) -> Self {
3909 Self(id.into())
3910 }
3911}
3912
3913#[serde_as]
3922#[skip_serializing_none]
3923#[cfg(feature = "unstable_mcp_over_acp")]
3924#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3925#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3926#[serde(rename_all = "camelCase")]
3927#[non_exhaustive]
3928pub struct McpServerAcp {
3929 pub name: String,
3931 pub server_id: McpServerAcpId,
3936 #[serde_as(deserialize_as = "DefaultOnError")]
3942 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3943 #[serde(default)]
3944 #[serde(rename = "_meta")]
3945 pub meta: Option<Meta>,
3946}
3947
3948#[cfg(feature = "unstable_mcp_over_acp")]
3949impl McpServerAcp {
3950 #[must_use]
3952 pub fn new(name: impl Into<String>, id: impl Into<McpServerAcpId>) -> Self {
3953 Self {
3954 name: name.into(),
3955 server_id: id.into(),
3956 meta: None,
3957 }
3958 }
3959
3960 #[must_use]
3966 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3967 self.meta = meta.into_option();
3968 self
3969 }
3970}
3971
3972#[serde_as]
3974#[skip_serializing_none]
3975#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3976#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3977#[serde(rename_all = "camelCase")]
3978#[non_exhaustive]
3979pub struct McpServerStdio {
3980 pub name: String,
3982 pub command: PathBuf,
3984 #[serde_as(deserialize_as = "DefaultOnNull")]
3986 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-null" = true)))]
3987 pub args: Vec<String>,
3988 #[serde_as(deserialize_as = "DefaultOnNull")]
3990 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-null" = true)))]
3991 pub env: Vec<EnvVariable>,
3992 #[serde_as(deserialize_as = "DefaultOnError")]
3998 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3999 #[serde(default)]
4000 #[serde(rename = "_meta")]
4001 pub meta: Option<Meta>,
4002}
4003
4004impl McpServerStdio {
4005 #[must_use]
4007 pub fn new(name: impl Into<String>, command: impl Into<PathBuf>) -> Self {
4008 Self {
4009 name: name.into(),
4010 command: command.into(),
4011 args: Vec::new(),
4012 env: Vec::new(),
4013 meta: None,
4014 }
4015 }
4016
4017 #[must_use]
4019 pub fn args(mut self, args: Vec<String>) -> Self {
4020 self.args = args;
4021 self
4022 }
4023
4024 #[must_use]
4026 pub fn env(mut self, env: Vec<EnvVariable>) -> Self {
4027 self.env = env;
4028 self
4029 }
4030
4031 #[must_use]
4037 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4038 self.meta = meta.into_option();
4039 self
4040 }
4041}
4042
4043#[serde_as]
4045#[skip_serializing_none]
4046#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4047#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4048#[serde(rename_all = "camelCase")]
4049#[non_exhaustive]
4050pub struct EnvVariable {
4051 pub name: String,
4053 pub value: String,
4055 #[serde_as(deserialize_as = "DefaultOnError")]
4061 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4062 #[serde(default)]
4063 #[serde(rename = "_meta")]
4064 pub meta: Option<Meta>,
4065}
4066
4067impl EnvVariable {
4068 #[must_use]
4070 pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
4071 Self {
4072 name: name.into(),
4073 value: value.into(),
4074 meta: None,
4075 }
4076 }
4077
4078 #[must_use]
4084 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4085 self.meta = meta.into_option();
4086 self
4087 }
4088}
4089
4090#[serde_as]
4092#[skip_serializing_none]
4093#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4094#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4095#[serde(rename_all = "camelCase")]
4096#[non_exhaustive]
4097pub struct HttpHeader {
4098 pub name: String,
4100 pub value: String,
4102 #[serde_as(deserialize_as = "DefaultOnError")]
4108 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4109 #[serde(default)]
4110 #[serde(rename = "_meta")]
4111 pub meta: Option<Meta>,
4112}
4113
4114impl HttpHeader {
4115 #[must_use]
4117 pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
4118 Self {
4119 name: name.into(),
4120 value: value.into(),
4121 meta: None,
4122 }
4123 }
4124
4125 #[must_use]
4131 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4132 self.meta = meta.into_option();
4133 self
4134 }
4135}
4136
4137#[cfg(feature = "unstable_session_system_prompt")]
4151#[serde_as]
4152#[skip_serializing_none]
4153#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4154#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4155#[serde(rename_all = "camelCase")]
4156#[non_exhaustive]
4157pub struct SystemPrompt {
4158 pub mode: SystemPromptMode,
4163 pub content: Vec<ContentBlock>,
4173 #[serde_as(deserialize_as = "DefaultOnError")]
4179 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4180 #[serde(default)]
4181 #[serde(rename = "_meta")]
4182 pub meta: Option<Meta>,
4183}
4184
4185#[cfg(feature = "unstable_session_system_prompt")]
4186impl SystemPrompt {
4187 #[must_use]
4192 pub fn new(content: Vec<ContentBlock>) -> Self {
4193 Self {
4194 mode: SystemPromptMode::default(),
4195 content,
4196 meta: None,
4197 }
4198 }
4199
4200 #[must_use]
4202 pub fn mode(mut self, mode: SystemPromptMode) -> Self {
4203 self.mode = mode;
4204 self
4205 }
4206
4207 #[must_use]
4213 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4214 self.meta = meta.into_option();
4215 self
4216 }
4217}
4218
4219#[cfg(feature = "unstable_session_system_prompt")]
4229#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4230#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
4231#[serde(rename_all = "snake_case")]
4232#[non_exhaustive]
4233pub enum SystemPromptMode {
4234 #[default]
4241 Append,
4242 Override,
4251 #[serde(untagged)]
4257 Other(String),
4258}
4259
4260#[serde_as]
4268#[skip_serializing_none]
4269#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4270#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4271#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_PROMPT_METHOD_NAME)))]
4272#[serde(rename_all = "camelCase")]
4273#[non_exhaustive]
4274pub struct PromptRequest {
4275 pub session_id: SessionId,
4277 pub prompt: Vec<ContentBlock>,
4291 #[serde_as(deserialize_as = "DefaultOnError")]
4297 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4298 #[serde(default)]
4299 #[serde(rename = "_meta")]
4300 pub meta: Option<Meta>,
4301}
4302
4303impl PromptRequest {
4304 #[must_use]
4306 pub fn new(session_id: impl Into<SessionId>, prompt: Vec<ContentBlock>) -> Self {
4307 Self {
4308 session_id: session_id.into(),
4309 prompt,
4310 meta: None,
4311 }
4312 }
4313
4314 #[must_use]
4320 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4321 self.meta = meta.into_option();
4322 self
4323 }
4324}
4325
4326#[serde_as]
4330#[skip_serializing_none]
4331#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4332#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4333#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_PROMPT_METHOD_NAME)))]
4334#[serde(rename_all = "camelCase")]
4335#[non_exhaustive]
4336pub struct PromptResponse {
4337 pub stop_reason: StopReason,
4339 #[cfg(feature = "unstable_end_turn_token_usage")]
4345 #[serde_as(deserialize_as = "DefaultOnError")]
4346 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4347 #[serde(default)]
4348 pub usage: Option<Usage>,
4349 #[serde_as(deserialize_as = "DefaultOnError")]
4355 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4356 #[serde(default)]
4357 #[serde(rename = "_meta")]
4358 pub meta: Option<Meta>,
4359}
4360
4361impl PromptResponse {
4362 #[must_use]
4364 pub fn new(stop_reason: StopReason) -> Self {
4365 Self {
4366 stop_reason,
4367 #[cfg(feature = "unstable_end_turn_token_usage")]
4368 usage: None,
4369 meta: None,
4370 }
4371 }
4372
4373 #[cfg(feature = "unstable_end_turn_token_usage")]
4379 #[must_use]
4380 pub fn usage(mut self, usage: impl IntoOption<Usage>) -> Self {
4381 self.usage = usage.into_option();
4382 self
4383 }
4384
4385 #[must_use]
4391 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4392 self.meta = meta.into_option();
4393 self
4394 }
4395}
4396
4397#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4401#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize)]
4402#[serde(rename_all = "snake_case")]
4403#[non_exhaustive]
4404pub enum StopReason {
4405 EndTurn,
4407 MaxTokens,
4409 MaxTurnRequests,
4412 Refusal,
4416 Cancelled,
4423}
4424
4425#[cfg(feature = "unstable_end_turn_token_usage")]
4431#[serde_as]
4432#[skip_serializing_none]
4433#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4434#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4435#[serde(rename_all = "camelCase")]
4436#[non_exhaustive]
4437pub struct Usage {
4438 pub total_tokens: u64,
4440 pub input_tokens: u64,
4442 pub output_tokens: u64,
4444 #[serde_as(deserialize_as = "DefaultOnError")]
4446 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4447 #[serde(default)]
4448 pub thought_tokens: Option<u64>,
4449 #[serde_as(deserialize_as = "DefaultOnError")]
4451 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4452 #[serde(default)]
4453 pub cached_read_tokens: Option<u64>,
4454 #[serde_as(deserialize_as = "DefaultOnError")]
4456 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4457 #[serde(default)]
4458 pub cached_write_tokens: Option<u64>,
4459 #[serde_as(deserialize_as = "DefaultOnError")]
4465 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4466 #[serde(default)]
4467 #[serde(rename = "_meta")]
4468 pub meta: Option<Meta>,
4469}
4470
4471#[cfg(feature = "unstable_end_turn_token_usage")]
4472impl Usage {
4473 #[must_use]
4475 pub fn new(total_tokens: u64, input_tokens: u64, output_tokens: u64) -> Self {
4476 Self {
4477 total_tokens,
4478 input_tokens,
4479 output_tokens,
4480 thought_tokens: None,
4481 cached_read_tokens: None,
4482 cached_write_tokens: None,
4483 meta: None,
4484 }
4485 }
4486
4487 #[must_use]
4489 pub fn thought_tokens(mut self, thought_tokens: impl IntoOption<u64>) -> Self {
4490 self.thought_tokens = thought_tokens.into_option();
4491 self
4492 }
4493
4494 #[must_use]
4496 pub fn cached_read_tokens(mut self, cached_read_tokens: impl IntoOption<u64>) -> Self {
4497 self.cached_read_tokens = cached_read_tokens.into_option();
4498 self
4499 }
4500
4501 #[must_use]
4503 pub fn cached_write_tokens(mut self, cached_write_tokens: impl IntoOption<u64>) -> Self {
4504 self.cached_write_tokens = cached_write_tokens.into_option();
4505 self
4506 }
4507
4508 #[must_use]
4514 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4515 self.meta = meta.into_option();
4516 self
4517 }
4518}
4519
4520#[cfg(feature = "unstable_llm_providers")]
4533#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4534#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4535#[serde(rename_all = "snake_case")]
4536#[non_exhaustive]
4537#[expect(clippy::doc_markdown)]
4538pub enum LlmProtocol {
4539 Anthropic,
4541 #[serde(rename = "openai")]
4543 OpenAi,
4544 Azure,
4546 Vertex,
4548 Bedrock,
4550 #[serde(untagged)]
4552 Other(String),
4553}
4554
4555#[cfg(feature = "unstable_llm_providers")]
4561#[serde_as]
4562#[skip_serializing_none]
4563#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4564#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4565#[serde(rename_all = "camelCase")]
4566#[non_exhaustive]
4567pub struct ProviderCurrentConfig {
4568 pub api_type: LlmProtocol,
4570 pub base_url: String,
4572 #[serde_as(deserialize_as = "DefaultOnError")]
4578 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4579 #[serde(default)]
4580 #[serde(rename = "_meta")]
4581 pub meta: Option<Meta>,
4582}
4583
4584#[cfg(feature = "unstable_llm_providers")]
4585impl ProviderCurrentConfig {
4586 #[must_use]
4588 pub fn new(api_type: LlmProtocol, base_url: impl Into<String>) -> Self {
4589 Self {
4590 api_type,
4591 base_url: base_url.into(),
4592 meta: None,
4593 }
4594 }
4595
4596 #[must_use]
4602 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4603 self.meta = meta.into_option();
4604 self
4605 }
4606}
4607
4608#[cfg(feature = "unstable_llm_providers")]
4614#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4615#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Display, From)]
4616#[serde(transparent)]
4617#[from(Arc<str>, String, &'static str)]
4618#[non_exhaustive]
4619pub struct ProviderId(pub Arc<str>);
4620
4621#[cfg(feature = "unstable_llm_providers")]
4622impl ProviderId {
4623 #[must_use]
4625 pub fn new(id: impl Into<Arc<str>>) -> Self {
4626 Self(id.into())
4627 }
4628}
4629
4630#[cfg(feature = "unstable_llm_providers")]
4636#[serde_as]
4637#[skip_serializing_none]
4638#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4639#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4640#[serde(rename_all = "camelCase")]
4641#[non_exhaustive]
4642pub struct ProviderInfo {
4643 pub provider_id: ProviderId,
4645 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_>>")]
4647 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
4648 pub supported: Vec<LlmProtocol>,
4649 pub required: bool,
4652 #[serde(default)]
4655 pub current: Option<ProviderCurrentConfig>,
4656 #[serde_as(deserialize_as = "DefaultOnError")]
4662 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4663 #[serde(default)]
4664 #[serde(rename = "_meta")]
4665 pub meta: Option<Meta>,
4666}
4667
4668#[cfg(feature = "unstable_llm_providers")]
4669impl ProviderInfo {
4670 #[must_use]
4672 pub fn new(
4673 provider_id: impl Into<ProviderId>,
4674 supported: Vec<LlmProtocol>,
4675 required: bool,
4676 current: impl IntoOption<ProviderCurrentConfig>,
4677 ) -> Self {
4678 Self {
4679 provider_id: provider_id.into(),
4680 supported,
4681 required,
4682 current: current.into_option(),
4683 meta: None,
4684 }
4685 }
4686
4687 #[must_use]
4693 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4694 self.meta = meta.into_option();
4695 self
4696 }
4697}
4698
4699#[cfg(feature = "unstable_llm_providers")]
4700crate::serde_util::default_on_null! {
4701 #[serde_as]
4707 #[skip_serializing_none]
4708 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4709 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
4710 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_LIST_METHOD_NAME)))]
4711 #[serde(rename_all = "camelCase")]
4712 #[non_exhaustive]
4713 pub struct ListProvidersRequest {
4714 #[serde_as(deserialize_as = "DefaultOnError")]
4720 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4721 #[serde(default)]
4722 #[serde(rename = "_meta")]
4723 pub meta: Option<Meta>,
4724 }
4725}
4726
4727#[cfg(feature = "unstable_llm_providers")]
4728impl ListProvidersRequest {
4729 #[must_use]
4731 pub fn new() -> Self {
4732 Self::default()
4733 }
4734
4735 #[must_use]
4741 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4742 self.meta = meta.into_option();
4743 self
4744 }
4745}
4746
4747#[cfg(feature = "unstable_llm_providers")]
4753#[serde_as]
4754#[skip_serializing_none]
4755#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4756#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4757#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_LIST_METHOD_NAME)))]
4758#[serde(rename_all = "camelCase")]
4759#[non_exhaustive]
4760pub struct ListProvidersResponse {
4761 pub providers: Vec<ProviderInfo>,
4763 #[serde_as(deserialize_as = "DefaultOnError")]
4769 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4770 #[serde(default)]
4771 #[serde(rename = "_meta")]
4772 pub meta: Option<Meta>,
4773}
4774
4775#[cfg(feature = "unstable_llm_providers")]
4776impl ListProvidersResponse {
4777 #[must_use]
4779 pub fn new(providers: Vec<ProviderInfo>) -> Self {
4780 Self {
4781 providers,
4782 meta: None,
4783 }
4784 }
4785
4786 #[must_use]
4792 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4793 self.meta = meta.into_option();
4794 self
4795 }
4796}
4797
4798#[cfg(feature = "unstable_llm_providers")]
4806#[serde_as]
4807#[skip_serializing_none]
4808#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4809#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
4810#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_SET_METHOD_NAME)))]
4811#[serde(rename_all = "camelCase")]
4812#[non_exhaustive]
4813pub struct SetProviderRequest {
4814 pub provider_id: ProviderId,
4816 pub api_type: LlmProtocol,
4818 pub base_url: String,
4820 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
4823 pub headers: HashMap<String, String>,
4824 #[serde_as(deserialize_as = "DefaultOnError")]
4830 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4831 #[serde(default)]
4832 #[serde(rename = "_meta")]
4833 pub meta: Option<Meta>,
4834}
4835
4836#[cfg(feature = "unstable_llm_providers")]
4837impl SetProviderRequest {
4838 #[must_use]
4840 pub fn new(
4841 provider_id: impl Into<ProviderId>,
4842 api_type: LlmProtocol,
4843 base_url: impl Into<String>,
4844 ) -> Self {
4845 Self {
4846 provider_id: provider_id.into(),
4847 api_type,
4848 base_url: base_url.into(),
4849 headers: HashMap::new(),
4850 meta: None,
4851 }
4852 }
4853
4854 #[must_use]
4857 pub fn headers(mut self, headers: HashMap<String, String>) -> Self {
4858 self.headers = headers;
4859 self
4860 }
4861
4862 #[must_use]
4868 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4869 self.meta = meta.into_option();
4870 self
4871 }
4872}
4873
4874#[cfg(feature = "unstable_llm_providers")]
4875crate::serde_util::default_on_null! {
4876 #[serde_as]
4882 #[skip_serializing_none]
4883 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4884 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
4885 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_SET_METHOD_NAME)))]
4886 #[serde(rename_all = "camelCase")]
4887 #[non_exhaustive]
4888 pub struct SetProviderResponse {
4889 #[serde_as(deserialize_as = "DefaultOnError")]
4895 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4896 #[serde(default)]
4897 #[serde(rename = "_meta")]
4898 pub meta: Option<Meta>,
4899 }
4900}
4901
4902#[cfg(feature = "unstable_llm_providers")]
4903impl SetProviderResponse {
4904 #[must_use]
4906 pub fn new() -> Self {
4907 Self::default()
4908 }
4909
4910 #[must_use]
4916 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4917 self.meta = meta.into_option();
4918 self
4919 }
4920}
4921
4922#[cfg(feature = "unstable_llm_providers")]
4928#[serde_as]
4929#[skip_serializing_none]
4930#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4931#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4932#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_DISABLE_METHOD_NAME)))]
4933#[serde(rename_all = "camelCase")]
4934#[non_exhaustive]
4935pub struct DisableProviderRequest {
4936 pub provider_id: ProviderId,
4938 #[serde_as(deserialize_as = "DefaultOnError")]
4944 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4945 #[serde(default)]
4946 #[serde(rename = "_meta")]
4947 pub meta: Option<Meta>,
4948}
4949
4950#[cfg(feature = "unstable_llm_providers")]
4951impl DisableProviderRequest {
4952 #[must_use]
4954 pub fn new(provider_id: impl Into<ProviderId>) -> Self {
4955 Self {
4956 provider_id: provider_id.into(),
4957 meta: None,
4958 }
4959 }
4960
4961 #[must_use]
4967 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4968 self.meta = meta.into_option();
4969 self
4970 }
4971}
4972
4973#[cfg(feature = "unstable_llm_providers")]
4974crate::serde_util::default_on_null! {
4975 #[serde_as]
4981 #[skip_serializing_none]
4982 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4983 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
4984 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_DISABLE_METHOD_NAME)))]
4985 #[serde(rename_all = "camelCase")]
4986 #[non_exhaustive]
4987 pub struct DisableProviderResponse {
4988 #[serde_as(deserialize_as = "DefaultOnError")]
4994 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4995 #[serde(default)]
4996 #[serde(rename = "_meta")]
4997 pub meta: Option<Meta>,
4998 }
4999}
5000
5001#[cfg(feature = "unstable_llm_providers")]
5002impl DisableProviderResponse {
5003 #[must_use]
5005 pub fn new() -> Self {
5006 Self::default()
5007 }
5008
5009 #[must_use]
5015 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5016 self.meta = meta.into_option();
5017 self
5018 }
5019}
5020
5021#[serde_as]
5030#[skip_serializing_none]
5031#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5032#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5033#[serde(rename_all = "camelCase")]
5034#[non_exhaustive]
5035pub struct AgentCapabilities {
5036 #[serde_as(deserialize_as = "DefaultOnError")]
5038 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5039 #[serde(default)]
5040 pub load_session: bool,
5041 #[serde_as(deserialize_as = "DefaultOnError")]
5043 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5044 #[serde(default)]
5045 pub prompt_capabilities: PromptCapabilities,
5046 #[serde_as(deserialize_as = "DefaultOnError")]
5048 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5049 #[serde(default)]
5050 pub mcp_capabilities: McpCapabilities,
5051 #[serde_as(deserialize_as = "DefaultOnError")]
5053 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5054 #[serde(default)]
5055 pub session_capabilities: SessionCapabilities,
5056 #[serde_as(deserialize_as = "DefaultOnError")]
5058 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5059 #[serde(default)]
5060 pub auth: AgentAuthCapabilities,
5061 #[cfg(feature = "unstable_llm_providers")]
5070 #[serde_as(deserialize_as = "DefaultOnError")]
5071 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5072 #[serde(default)]
5073 pub providers: Option<ProvidersCapabilities>,
5074 #[serde_as(deserialize_as = "DefaultOnError")]
5080 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5081 #[serde(default)]
5082 #[serde(rename = "_meta")]
5083 pub meta: Option<Meta>,
5084}
5085
5086impl AgentCapabilities {
5087 #[must_use]
5089 pub fn new() -> Self {
5090 Self::default()
5091 }
5092
5093 #[must_use]
5095 pub fn load_session(mut self, load_session: bool) -> Self {
5096 self.load_session = load_session;
5097 self
5098 }
5099
5100 #[must_use]
5102 pub fn prompt_capabilities(mut self, prompt_capabilities: PromptCapabilities) -> Self {
5103 self.prompt_capabilities = prompt_capabilities;
5104 self
5105 }
5106
5107 #[must_use]
5109 pub fn mcp_capabilities(mut self, mcp_capabilities: McpCapabilities) -> Self {
5110 self.mcp_capabilities = mcp_capabilities;
5111 self
5112 }
5113
5114 #[must_use]
5116 pub fn session_capabilities(mut self, session_capabilities: SessionCapabilities) -> Self {
5117 self.session_capabilities = session_capabilities;
5118 self
5119 }
5120
5121 #[must_use]
5123 pub fn auth(mut self, auth: AgentAuthCapabilities) -> Self {
5124 self.auth = auth;
5125 self
5126 }
5127
5128 #[cfg(feature = "unstable_llm_providers")]
5134 #[must_use]
5135 pub fn providers(mut self, providers: impl IntoOption<ProvidersCapabilities>) -> Self {
5136 self.providers = providers.into_option();
5137 self
5138 }
5139
5140 #[must_use]
5146 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5147 self.meta = meta.into_option();
5148 self
5149 }
5150}
5151
5152#[cfg(feature = "unstable_llm_providers")]
5160#[serde_as]
5161#[skip_serializing_none]
5162#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5163#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5164#[non_exhaustive]
5165pub struct ProvidersCapabilities {
5166 #[serde_as(deserialize_as = "DefaultOnError")]
5172 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5173 #[serde(default)]
5174 #[serde(rename = "_meta")]
5175 pub meta: Option<Meta>,
5176}
5177
5178#[cfg(feature = "unstable_llm_providers")]
5179impl ProvidersCapabilities {
5180 #[must_use]
5182 pub fn new() -> Self {
5183 Self::default()
5184 }
5185
5186 #[must_use]
5192 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5193 self.meta = meta.into_option();
5194 self
5195 }
5196}
5197
5198#[serde_as]
5208#[skip_serializing_none]
5209#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5210#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5211#[serde(rename_all = "camelCase")]
5212#[non_exhaustive]
5213pub struct SessionCapabilities {
5214 #[serde_as(deserialize_as = "DefaultOnError")]
5219 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5220 #[serde(default)]
5221 pub list: Option<SessionListCapabilities>,
5222 #[serde_as(deserialize_as = "DefaultOnError")]
5227 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5228 #[serde(default)]
5229 pub delete: Option<SessionDeleteCapabilities>,
5230 #[serde_as(deserialize_as = "DefaultOnError")]
5240 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5241 #[serde(default)]
5242 pub additional_directories: Option<SessionAdditionalDirectoriesCapabilities>,
5243 #[cfg(feature = "unstable_session_system_prompt")]
5252 #[serde_as(deserialize_as = "DefaultOnError")]
5253 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5254 #[serde(default)]
5255 pub system_prompt: Option<SessionSystemPromptCapabilities>,
5256 #[cfg(feature = "unstable_session_fork")]
5265 #[serde_as(deserialize_as = "DefaultOnError")]
5266 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5267 #[serde(default)]
5268 pub fork: Option<SessionForkCapabilities>,
5269 #[cfg(feature = "unstable_session_archive")]
5279 #[serde_as(deserialize_as = "DefaultOnError")]
5280 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5281 #[serde(default)]
5282 pub archive: Option<SessionArchiveCapabilities>,
5283 #[cfg(feature = "unstable_session_status")]
5292 #[serde_as(deserialize_as = "DefaultOnError")]
5293 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5294 #[serde(default)]
5295 pub status: Option<SessionStatusCapabilities>,
5296 #[cfg(feature = "unstable_session_set_title")]
5308 #[serde_as(deserialize_as = "DefaultOnError")]
5309 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5310 #[serde(default)]
5311 pub title: Option<SessionTitleCapabilities>,
5312 #[serde_as(deserialize_as = "DefaultOnError")]
5317 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5318 #[serde(default)]
5319 pub resume: Option<SessionResumeCapabilities>,
5320 #[serde_as(deserialize_as = "DefaultOnError")]
5325 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5326 #[serde(default)]
5327 pub close: Option<SessionCloseCapabilities>,
5328 #[serde_as(deserialize_as = "DefaultOnError")]
5334 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5335 #[serde(default)]
5336 #[serde(rename = "_meta")]
5337 pub meta: Option<Meta>,
5338}
5339
5340impl SessionCapabilities {
5341 #[must_use]
5343 pub fn new() -> Self {
5344 Self::default()
5345 }
5346
5347 #[must_use]
5352 pub fn list(mut self, list: impl IntoOption<SessionListCapabilities>) -> Self {
5353 self.list = list.into_option();
5354 self
5355 }
5356
5357 #[must_use]
5362 pub fn delete(mut self, delete: impl IntoOption<SessionDeleteCapabilities>) -> Self {
5363 self.delete = delete.into_option();
5364 self
5365 }
5366
5367 #[must_use]
5377 pub fn additional_directories(
5378 mut self,
5379 additional_directories: impl IntoOption<SessionAdditionalDirectoriesCapabilities>,
5380 ) -> Self {
5381 self.additional_directories = additional_directories.into_option();
5382 self
5383 }
5384
5385 #[cfg(feature = "unstable_session_system_prompt")]
5394 #[must_use]
5395 pub fn system_prompt(
5396 mut self,
5397 system_prompt: impl IntoOption<SessionSystemPromptCapabilities>,
5398 ) -> Self {
5399 self.system_prompt = system_prompt.into_option();
5400 self
5401 }
5402
5403 #[cfg(feature = "unstable_session_fork")]
5404 #[must_use]
5409 pub fn fork(mut self, fork: impl IntoOption<SessionForkCapabilities>) -> Self {
5410 self.fork = fork.into_option();
5411 self
5412 }
5413
5414 #[cfg(feature = "unstable_session_archive")]
5424 #[must_use]
5425 pub fn archive(mut self, archive: impl IntoOption<SessionArchiveCapabilities>) -> Self {
5426 self.archive = archive.into_option();
5427 self
5428 }
5429
5430 #[cfg(feature = "unstable_session_status")]
5439 #[must_use]
5440 pub fn status(mut self, status: impl IntoOption<SessionStatusCapabilities>) -> Self {
5441 self.status = status.into_option();
5442 self
5443 }
5444
5445 #[cfg(feature = "unstable_session_set_title")]
5457 #[must_use]
5458 pub fn title(mut self, title: impl IntoOption<SessionTitleCapabilities>) -> Self {
5459 self.title = title.into_option();
5460 self
5461 }
5462
5463 #[must_use]
5468 pub fn resume(mut self, resume: impl IntoOption<SessionResumeCapabilities>) -> Self {
5469 self.resume = resume.into_option();
5470 self
5471 }
5472
5473 #[must_use]
5478 pub fn close(mut self, close: impl IntoOption<SessionCloseCapabilities>) -> Self {
5479 self.close = close.into_option();
5480 self
5481 }
5482
5483 #[must_use]
5489 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5490 self.meta = meta.into_option();
5491 self
5492 }
5493}
5494
5495#[serde_as]
5499#[skip_serializing_none]
5500#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5501#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5502#[non_exhaustive]
5503pub struct SessionListCapabilities {
5504 #[serde_as(deserialize_as = "DefaultOnError")]
5510 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5511 #[serde(default)]
5512 #[serde(rename = "_meta")]
5513 pub meta: Option<Meta>,
5514}
5515
5516impl SessionListCapabilities {
5517 #[must_use]
5519 pub fn new() -> Self {
5520 Self::default()
5521 }
5522
5523 #[must_use]
5529 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5530 self.meta = meta.into_option();
5531 self
5532 }
5533}
5534
5535#[serde_as]
5539#[skip_serializing_none]
5540#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5541#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5542#[non_exhaustive]
5543pub struct SessionDeleteCapabilities {
5544 #[serde_as(deserialize_as = "DefaultOnError")]
5550 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5551 #[serde(default)]
5552 #[serde(rename = "_meta")]
5553 pub meta: Option<Meta>,
5554}
5555
5556impl SessionDeleteCapabilities {
5557 #[must_use]
5559 pub fn new() -> Self {
5560 Self::default()
5561 }
5562
5563 #[must_use]
5569 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5570 self.meta = meta.into_option();
5571 self
5572 }
5573}
5574
5575#[serde_as]
5582#[skip_serializing_none]
5583#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5584#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5585#[non_exhaustive]
5586pub struct SessionAdditionalDirectoriesCapabilities {
5587 #[serde_as(deserialize_as = "DefaultOnError")]
5593 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5594 #[serde(default)]
5595 #[serde(rename = "_meta")]
5596 pub meta: Option<Meta>,
5597}
5598
5599impl SessionAdditionalDirectoriesCapabilities {
5600 #[must_use]
5602 pub fn new() -> Self {
5603 Self::default()
5604 }
5605
5606 #[must_use]
5612 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5613 self.meta = meta.into_option();
5614 self
5615 }
5616}
5617
5618#[cfg(feature = "unstable_session_system_prompt")]
5627#[serde_as]
5628#[skip_serializing_none]
5629#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5630#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5631#[serde(rename_all = "camelCase")]
5632#[non_exhaustive]
5633pub struct SessionSystemPromptCapabilities {
5634 #[serde_as(deserialize_as = "DefaultOnError")]
5638 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5639 #[serde(default)]
5640 pub mode: Option<SessionSystemPromptModeCapabilities>,
5641 #[serde_as(deserialize_as = "DefaultOnError")]
5647 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5648 #[serde(default)]
5649 #[serde(rename = "_meta")]
5650 pub meta: Option<Meta>,
5651}
5652
5653#[cfg(feature = "unstable_session_system_prompt")]
5654impl SessionSystemPromptCapabilities {
5655 #[must_use]
5657 pub fn new() -> Self {
5658 Self::default()
5659 }
5660
5661 #[must_use]
5665 pub fn mode(mut self, mode: impl IntoOption<SessionSystemPromptModeCapabilities>) -> Self {
5666 self.mode = mode.into_option();
5667 self
5668 }
5669
5670 #[must_use]
5676 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5677 self.meta = meta.into_option();
5678 self
5679 }
5680}
5681
5682#[cfg(feature = "unstable_session_system_prompt")]
5691#[serde_as]
5692#[skip_serializing_none]
5693#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5694#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5695#[serde(rename_all = "camelCase")]
5696#[non_exhaustive]
5697pub struct SessionSystemPromptModeCapabilities {
5698 #[serde_as(deserialize_as = "DefaultOnError")]
5704 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5705 #[serde(default, rename = "override")]
5706 pub override_: Option<SessionSystemPromptOverrideCapabilities>,
5707 #[serde_as(deserialize_as = "DefaultOnError")]
5713 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5714 #[serde(default)]
5715 #[serde(rename = "_meta")]
5716 pub meta: Option<Meta>,
5717}
5718
5719#[cfg(feature = "unstable_session_system_prompt")]
5720impl SessionSystemPromptModeCapabilities {
5721 #[must_use]
5723 pub fn new() -> Self {
5724 Self::default()
5725 }
5726
5727 #[must_use]
5733 pub fn override_(
5734 mut self,
5735 override_: impl IntoOption<SessionSystemPromptOverrideCapabilities>,
5736 ) -> Self {
5737 self.override_ = override_.into_option();
5738 self
5739 }
5740
5741 #[must_use]
5747 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5748 self.meta = meta.into_option();
5749 self
5750 }
5751}
5752
5753#[cfg(feature = "unstable_session_system_prompt")]
5762#[serde_as]
5763#[skip_serializing_none]
5764#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5765#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5766#[non_exhaustive]
5767pub struct SessionSystemPromptOverrideCapabilities {
5768 #[serde_as(deserialize_as = "DefaultOnError")]
5774 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5775 #[serde(default)]
5776 #[serde(rename = "_meta")]
5777 pub meta: Option<Meta>,
5778}
5779
5780#[cfg(feature = "unstable_session_system_prompt")]
5781impl SessionSystemPromptOverrideCapabilities {
5782 #[must_use]
5784 pub fn new() -> Self {
5785 Self::default()
5786 }
5787
5788 #[must_use]
5794 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5795 self.meta = meta.into_option();
5796 self
5797 }
5798}
5799
5800#[cfg(feature = "unstable_session_fork")]
5808#[serde_as]
5809#[skip_serializing_none]
5810#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5811#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5812#[non_exhaustive]
5813pub struct SessionForkCapabilities {
5814 #[serde_as(deserialize_as = "DefaultOnError")]
5820 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5821 #[serde(default)]
5822 #[serde(rename = "_meta")]
5823 pub meta: Option<Meta>,
5824}
5825
5826#[cfg(feature = "unstable_session_fork")]
5827impl SessionForkCapabilities {
5828 #[must_use]
5830 pub fn new() -> Self {
5831 Self::default()
5832 }
5833
5834 #[must_use]
5840 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5841 self.meta = meta.into_option();
5842 self
5843 }
5844}
5845
5846#[cfg(feature = "unstable_session_archive")]
5855#[serde_as]
5856#[skip_serializing_none]
5857#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5858#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5859#[non_exhaustive]
5860pub struct SessionArchiveCapabilities {
5861 #[serde_as(deserialize_as = "DefaultOnError")]
5867 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5868 #[serde(default)]
5869 #[serde(rename = "_meta")]
5870 pub meta: Option<Meta>,
5871}
5872
5873#[cfg(feature = "unstable_session_archive")]
5874impl SessionArchiveCapabilities {
5875 #[must_use]
5877 pub fn new() -> Self {
5878 Self::default()
5879 }
5880
5881 #[must_use]
5887 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5888 self.meta = meta.into_option();
5889 self
5890 }
5891}
5892
5893#[cfg(feature = "unstable_session_status")]
5901#[serde_as]
5902#[skip_serializing_none]
5903#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5904#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5905#[non_exhaustive]
5906pub struct SessionStatusCapabilities {
5907 #[serde_as(deserialize_as = "DefaultOnError")]
5913 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5914 #[serde(default)]
5915 #[serde(rename = "_meta")]
5916 pub meta: Option<Meta>,
5917}
5918
5919#[cfg(feature = "unstable_session_status")]
5920impl SessionStatusCapabilities {
5921 #[must_use]
5923 pub fn new() -> Self {
5924 Self::default()
5925 }
5926
5927 #[must_use]
5933 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5934 self.meta = meta.into_option();
5935 self
5936 }
5937}
5938
5939#[cfg(feature = "unstable_session_set_title")]
5948#[serde_as]
5949#[skip_serializing_none]
5950#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5951#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5952#[non_exhaustive]
5953pub struct SessionTitleCapabilities {
5954 #[serde_as(deserialize_as = "DefaultOnError")]
5960 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5961 #[serde(default)]
5962 #[serde(rename = "_meta")]
5963 pub meta: Option<Meta>,
5964}
5965
5966#[cfg(feature = "unstable_session_set_title")]
5967impl SessionTitleCapabilities {
5968 #[must_use]
5970 pub fn new() -> Self {
5971 Self::default()
5972 }
5973
5974 #[must_use]
5980 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5981 self.meta = meta.into_option();
5982 self
5983 }
5984}
5985
5986#[serde_as]
5990#[skip_serializing_none]
5991#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5992#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5993#[non_exhaustive]
5994pub struct SessionResumeCapabilities {
5995 #[serde_as(deserialize_as = "DefaultOnError")]
6001 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
6002 #[serde(default)]
6003 #[serde(rename = "_meta")]
6004 pub meta: Option<Meta>,
6005}
6006
6007impl SessionResumeCapabilities {
6008 #[must_use]
6010 pub fn new() -> Self {
6011 Self::default()
6012 }
6013
6014 #[must_use]
6020 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
6021 self.meta = meta.into_option();
6022 self
6023 }
6024}
6025
6026#[serde_as]
6030#[skip_serializing_none]
6031#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
6032#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
6033#[non_exhaustive]
6034pub struct SessionCloseCapabilities {
6035 #[serde_as(deserialize_as = "DefaultOnError")]
6041 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
6042 #[serde(default)]
6043 #[serde(rename = "_meta")]
6044 pub meta: Option<Meta>,
6045}
6046
6047impl SessionCloseCapabilities {
6048 #[must_use]
6050 pub fn new() -> Self {
6051 Self::default()
6052 }
6053
6054 #[must_use]
6060 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
6061 self.meta = meta.into_option();
6062 self
6063 }
6064}
6065
6066#[serde_as]
6079#[skip_serializing_none]
6080#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
6081#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
6082#[serde(rename_all = "camelCase")]
6083#[non_exhaustive]
6084pub struct PromptCapabilities {
6085 #[serde_as(deserialize_as = "DefaultOnError")]
6087 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
6088 #[serde(default)]
6089 pub image: bool,
6090 #[serde_as(deserialize_as = "DefaultOnError")]
6092 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
6093 #[serde(default)]
6094 pub audio: bool,
6095 #[serde_as(deserialize_as = "DefaultOnError")]
6100 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
6101 #[serde(default)]
6102 pub embedded_context: bool,
6103 #[serde_as(deserialize_as = "DefaultOnError")]
6109 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
6110 #[serde(default)]
6111 #[serde(rename = "_meta")]
6112 pub meta: Option<Meta>,
6113}
6114
6115impl PromptCapabilities {
6116 #[must_use]
6118 pub fn new() -> Self {
6119 Self::default()
6120 }
6121
6122 #[must_use]
6124 pub fn image(mut self, image: bool) -> Self {
6125 self.image = image;
6126 self
6127 }
6128
6129 #[must_use]
6131 pub fn audio(mut self, audio: bool) -> Self {
6132 self.audio = audio;
6133 self
6134 }
6135
6136 #[must_use]
6141 pub fn embedded_context(mut self, embedded_context: bool) -> Self {
6142 self.embedded_context = embedded_context;
6143 self
6144 }
6145
6146 #[must_use]
6152 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
6153 self.meta = meta.into_option();
6154 self
6155 }
6156}
6157
6158#[serde_as]
6160#[skip_serializing_none]
6161#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
6162#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
6163#[serde(rename_all = "camelCase")]
6164#[non_exhaustive]
6165pub struct McpCapabilities {
6166 #[serde_as(deserialize_as = "DefaultOnError")]
6168 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
6169 #[serde(default)]
6170 pub http: bool,
6171 #[serde_as(deserialize_as = "DefaultOnError")]
6173 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
6174 #[serde(default)]
6175 pub sse: bool,
6176 #[cfg(feature = "unstable_mcp_over_acp")]
6182 #[serde_as(deserialize_as = "DefaultOnError")]
6183 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
6184 #[serde(default)]
6185 pub acp: bool,
6186 #[serde_as(deserialize_as = "DefaultOnError")]
6192 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
6193 #[serde(default)]
6194 #[serde(rename = "_meta")]
6195 pub meta: Option<Meta>,
6196}
6197
6198impl McpCapabilities {
6199 #[must_use]
6201 pub fn new() -> Self {
6202 Self::default()
6203 }
6204
6205 #[must_use]
6207 pub fn http(mut self, http: bool) -> Self {
6208 self.http = http;
6209 self
6210 }
6211
6212 #[must_use]
6214 pub fn sse(mut self, sse: bool) -> Self {
6215 self.sse = sse;
6216 self
6217 }
6218
6219 #[cfg(feature = "unstable_mcp_over_acp")]
6225 #[must_use]
6226 pub fn acp(mut self, acp: bool) -> Self {
6227 self.acp = acp;
6228 self
6229 }
6230
6231 #[must_use]
6237 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
6238 self.meta = meta.into_option();
6239 self
6240 }
6241}
6242
6243#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
6249#[non_exhaustive]
6250pub struct AgentMethodNames {
6251 pub initialize: &'static str,
6253 pub authenticate: &'static str,
6255 #[cfg(feature = "unstable_llm_providers")]
6257 pub providers_list: &'static str,
6258 #[cfg(feature = "unstable_llm_providers")]
6260 pub providers_set: &'static str,
6261 #[cfg(feature = "unstable_llm_providers")]
6263 pub providers_disable: &'static str,
6264 pub session_new: &'static str,
6266 pub session_load: &'static str,
6268 pub session_set_mode: &'static str,
6270 pub session_set_config_option: &'static str,
6272 pub session_prompt: &'static str,
6274 pub session_cancel: &'static str,
6276 #[cfg(feature = "unstable_mcp_over_acp")]
6278 pub mcp_message: &'static str,
6279 pub session_list: &'static str,
6281 pub session_delete: &'static str,
6283 #[cfg(feature = "unstable_session_fork")]
6285 pub session_fork: &'static str,
6286 #[cfg(feature = "unstable_session_archive")]
6288 pub session_archive: &'static str,
6289 #[cfg(feature = "unstable_session_archive")]
6291 pub session_unarchive: &'static str,
6292 #[cfg(feature = "unstable_session_status")]
6294 pub session_status: &'static str,
6295 #[cfg(feature = "unstable_session_set_title")]
6297 pub session_set_title: &'static str,
6298 pub session_resume: &'static str,
6300 pub session_close: &'static str,
6302 pub logout: &'static str,
6304 #[cfg(feature = "unstable_auth_status")]
6306 pub auth_status: &'static str,
6307}
6308
6309pub const AGENT_METHOD_NAMES: AgentMethodNames = AgentMethodNames {
6311 initialize: INITIALIZE_METHOD_NAME,
6312 authenticate: AUTHENTICATE_METHOD_NAME,
6313 #[cfg(feature = "unstable_llm_providers")]
6314 providers_list: PROVIDERS_LIST_METHOD_NAME,
6315 #[cfg(feature = "unstable_llm_providers")]
6316 providers_set: PROVIDERS_SET_METHOD_NAME,
6317 #[cfg(feature = "unstable_llm_providers")]
6318 providers_disable: PROVIDERS_DISABLE_METHOD_NAME,
6319 session_new: SESSION_NEW_METHOD_NAME,
6320 session_load: SESSION_LOAD_METHOD_NAME,
6321 session_set_mode: SESSION_SET_MODE_METHOD_NAME,
6322 session_set_config_option: SESSION_SET_CONFIG_OPTION_METHOD_NAME,
6323 session_prompt: SESSION_PROMPT_METHOD_NAME,
6324 session_cancel: SESSION_CANCEL_METHOD_NAME,
6325 #[cfg(feature = "unstable_mcp_over_acp")]
6326 mcp_message: MCP_MESSAGE_METHOD_NAME,
6327 session_list: SESSION_LIST_METHOD_NAME,
6328 session_delete: SESSION_DELETE_METHOD_NAME,
6329 #[cfg(feature = "unstable_session_fork")]
6330 session_fork: SESSION_FORK_METHOD_NAME,
6331 #[cfg(feature = "unstable_session_archive")]
6332 session_archive: SESSION_ARCHIVE_METHOD_NAME,
6333 #[cfg(feature = "unstable_session_archive")]
6334 session_unarchive: SESSION_UNARCHIVE_METHOD_NAME,
6335 #[cfg(feature = "unstable_session_status")]
6336 session_status: SESSION_STATUS_METHOD_NAME,
6337 #[cfg(feature = "unstable_session_set_title")]
6338 session_set_title: SESSION_SET_TITLE_METHOD_NAME,
6339 session_resume: SESSION_RESUME_METHOD_NAME,
6340 session_close: SESSION_CLOSE_METHOD_NAME,
6341 logout: LOGOUT_METHOD_NAME,
6342 #[cfg(feature = "unstable_auth_status")]
6343 auth_status: AUTH_STATUS_METHOD_NAME,
6344};
6345
6346pub(crate) const INITIALIZE_METHOD_NAME: &str = "initialize";
6348pub(crate) const AUTHENTICATE_METHOD_NAME: &str = "authenticate";
6350#[cfg(feature = "unstable_llm_providers")]
6352pub(crate) const PROVIDERS_LIST_METHOD_NAME: &str = "providers/list";
6353#[cfg(feature = "unstable_llm_providers")]
6355pub(crate) const PROVIDERS_SET_METHOD_NAME: &str = "providers/set";
6356#[cfg(feature = "unstable_llm_providers")]
6358pub(crate) const PROVIDERS_DISABLE_METHOD_NAME: &str = "providers/disable";
6359pub(crate) const SESSION_NEW_METHOD_NAME: &str = "session/new";
6361pub(crate) const SESSION_LOAD_METHOD_NAME: &str = "session/load";
6363pub(crate) const SESSION_SET_MODE_METHOD_NAME: &str = "session/set_mode";
6365pub(crate) const SESSION_SET_CONFIG_OPTION_METHOD_NAME: &str = "session/set_config_option";
6367pub(crate) const SESSION_PROMPT_METHOD_NAME: &str = "session/prompt";
6369pub(crate) const SESSION_CANCEL_METHOD_NAME: &str = "session/cancel";
6371pub(crate) const SESSION_LIST_METHOD_NAME: &str = "session/list";
6373pub(crate) const SESSION_DELETE_METHOD_NAME: &str = "session/delete";
6375#[cfg(feature = "unstable_session_fork")]
6377pub(crate) const SESSION_FORK_METHOD_NAME: &str = "session/fork";
6378#[cfg(feature = "unstable_session_archive")]
6380pub(crate) const SESSION_ARCHIVE_METHOD_NAME: &str = "session/archive";
6381#[cfg(feature = "unstable_session_archive")]
6383pub(crate) const SESSION_UNARCHIVE_METHOD_NAME: &str = "session/unarchive";
6384#[cfg(feature = "unstable_session_status")]
6386pub(crate) const SESSION_STATUS_METHOD_NAME: &str = "session/status";
6387#[cfg(feature = "unstable_session_set_title")]
6389pub(crate) const SESSION_SET_TITLE_METHOD_NAME: &str = "session/set_title";
6390pub(crate) const SESSION_RESUME_METHOD_NAME: &str = "session/resume";
6392pub(crate) const SESSION_CLOSE_METHOD_NAME: &str = "session/close";
6394pub(crate) const LOGOUT_METHOD_NAME: &str = "logout";
6396#[cfg(feature = "unstable_auth_status")]
6398pub(crate) const AUTH_STATUS_METHOD_NAME: &str = "auth/status";
6399
6400#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
6407#[derive(Clone, Debug, Serialize, Deserialize)]
6408#[serde(untagged)]
6409#[cfg_attr(feature = "schemars", schemars(inline))]
6410#[non_exhaustive]
6411#[allow(clippy::large_enum_variant)]
6412pub enum ClientRequest {
6413 InitializeRequest(InitializeRequest),
6424 AuthenticateRequest(AuthenticateRequest),
6435 #[cfg(feature = "unstable_llm_providers")]
6441 ListProvidersRequest(ListProvidersRequest),
6442 #[cfg(feature = "unstable_llm_providers")]
6448 SetProviderRequest(SetProviderRequest),
6449 #[cfg(feature = "unstable_llm_providers")]
6455 DisableProviderRequest(DisableProviderRequest),
6456 LogoutRequest(LogoutRequest),
6461 #[cfg(feature = "unstable_auth_status")]
6470 AuthStatusRequest(AuthStatusRequest),
6471 NewSessionRequest(NewSessionRequest),
6484 LoadSessionRequest(LoadSessionRequest),
6495 ListSessionsRequest(ListSessionsRequest),
6501 DeleteSessionRequest(DeleteSessionRequest),
6505 #[cfg(feature = "unstable_session_fork")]
6506 ForkSessionRequest(ForkSessionRequest),
6522 #[cfg(feature = "unstable_session_archive")]
6523 ArchiveSessionRequest(ArchiveSessionRequest),
6531 #[cfg(feature = "unstable_session_archive")]
6532 UnarchiveSessionRequest(UnarchiveSessionRequest),
6540 #[cfg(feature = "unstable_session_status")]
6541 SessionStatusRequest(SessionStatusRequest),
6549 #[cfg(feature = "unstable_session_set_title")]
6550 SetSessionTitleRequest(SetSessionTitleRequest),
6561 ResumeSessionRequest(ResumeSessionRequest),
6568 CloseSessionRequest(CloseSessionRequest),
6575 SetSessionModeRequest(SetSessionModeRequest),
6589 SetSessionConfigOptionRequest(SetSessionConfigOptionRequest),
6591 PromptRequest(PromptRequest),
6603 ExtMethodRequest(ExtRequest),
6610}
6611
6612impl ClientRequest {
6613 #[must_use]
6615 pub fn method(&self) -> &str {
6616 match self {
6617 Self::InitializeRequest(_) => AGENT_METHOD_NAMES.initialize,
6618 Self::AuthenticateRequest(_) => AGENT_METHOD_NAMES.authenticate,
6619 #[cfg(feature = "unstable_llm_providers")]
6620 Self::ListProvidersRequest(_) => AGENT_METHOD_NAMES.providers_list,
6621 #[cfg(feature = "unstable_llm_providers")]
6622 Self::SetProviderRequest(_) => AGENT_METHOD_NAMES.providers_set,
6623 #[cfg(feature = "unstable_llm_providers")]
6624 Self::DisableProviderRequest(_) => AGENT_METHOD_NAMES.providers_disable,
6625 Self::LogoutRequest(_) => AGENT_METHOD_NAMES.logout,
6626 #[cfg(feature = "unstable_auth_status")]
6627 Self::AuthStatusRequest(_) => AGENT_METHOD_NAMES.auth_status,
6628 Self::NewSessionRequest(_) => AGENT_METHOD_NAMES.session_new,
6629 Self::LoadSessionRequest(_) => AGENT_METHOD_NAMES.session_load,
6630 Self::ListSessionsRequest(_) => AGENT_METHOD_NAMES.session_list,
6631 Self::DeleteSessionRequest(_) => AGENT_METHOD_NAMES.session_delete,
6632 #[cfg(feature = "unstable_session_fork")]
6633 Self::ForkSessionRequest(_) => AGENT_METHOD_NAMES.session_fork,
6634 #[cfg(feature = "unstable_session_archive")]
6635 Self::ArchiveSessionRequest(_) => AGENT_METHOD_NAMES.session_archive,
6636 #[cfg(feature = "unstable_session_archive")]
6637 Self::UnarchiveSessionRequest(_) => AGENT_METHOD_NAMES.session_unarchive,
6638 #[cfg(feature = "unstable_session_status")]
6639 Self::SessionStatusRequest(_) => AGENT_METHOD_NAMES.session_status,
6640 #[cfg(feature = "unstable_session_set_title")]
6641 Self::SetSessionTitleRequest(_) => AGENT_METHOD_NAMES.session_set_title,
6642 Self::ResumeSessionRequest(_) => AGENT_METHOD_NAMES.session_resume,
6643 Self::CloseSessionRequest(_) => AGENT_METHOD_NAMES.session_close,
6644 Self::SetSessionModeRequest(_) => AGENT_METHOD_NAMES.session_set_mode,
6645 Self::SetSessionConfigOptionRequest(_) => AGENT_METHOD_NAMES.session_set_config_option,
6646 Self::PromptRequest(_) => AGENT_METHOD_NAMES.session_prompt,
6647 Self::ExtMethodRequest(ext_request) => &ext_request.method,
6648 }
6649 }
6650}
6651
6652#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
6659#[derive(Clone, Debug, Serialize, Deserialize)]
6660#[serde(untagged)]
6661#[cfg_attr(feature = "schemars", schemars(inline))]
6662#[non_exhaustive]
6663#[allow(clippy::large_enum_variant)]
6664pub enum AgentResponse {
6665 InitializeResponse(InitializeResponse),
6667 AuthenticateResponse(#[serde(default)] AuthenticateResponse),
6669 #[cfg(feature = "unstable_llm_providers")]
6671 ListProvidersResponse(ListProvidersResponse),
6672 #[cfg(feature = "unstable_llm_providers")]
6674 SetProviderResponse(#[serde(default)] SetProviderResponse),
6675 #[cfg(feature = "unstable_llm_providers")]
6677 DisableProviderResponse(#[serde(default)] DisableProviderResponse),
6678 LogoutResponse(#[serde(default)] LogoutResponse),
6680 #[cfg(feature = "unstable_auth_status")]
6682 AuthStatusResponse(AuthStatusResponse),
6683 NewSessionResponse(NewSessionResponse),
6685 LoadSessionResponse(#[serde(default)] LoadSessionResponse),
6687 ListSessionsResponse(ListSessionsResponse),
6689 DeleteSessionResponse(#[serde(default)] DeleteSessionResponse),
6691 #[cfg(feature = "unstable_session_fork")]
6693 ForkSessionResponse(ForkSessionResponse),
6694 #[cfg(feature = "unstable_session_archive")]
6696 ArchiveSessionResponse(#[serde(default)] ArchiveSessionResponse),
6697 #[cfg(feature = "unstable_session_archive")]
6699 UnarchiveSessionResponse(#[serde(default)] UnarchiveSessionResponse),
6700 #[cfg(feature = "unstable_session_status")]
6702 SessionStatusResponse(SessionStatusResponse),
6703 #[cfg(feature = "unstable_session_set_title")]
6705 SetSessionTitleResponse(SetSessionTitleResponse),
6706 ResumeSessionResponse(#[serde(default)] ResumeSessionResponse),
6708 CloseSessionResponse(#[serde(default)] CloseSessionResponse),
6710 SetSessionModeResponse(#[serde(default)] SetSessionModeResponse),
6712 SetSessionConfigOptionResponse(SetSessionConfigOptionResponse),
6714 PromptResponse(PromptResponse),
6716 ExtMethodResponse(ExtResponse),
6718}
6719
6720#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
6727#[derive(Clone, Debug, Serialize, Deserialize)]
6728#[serde(untagged)]
6729#[cfg_attr(feature = "schemars", schemars(inline))]
6730#[non_exhaustive]
6731#[allow(clippy::large_enum_variant)]
6732pub enum ClientNotification {
6733 CancelNotification(CancelNotification),
6745 #[cfg(feature = "unstable_mcp_over_acp")]
6751 MessageMcpNotification(MessageMcpNotification),
6752 ExtNotification(ExtNotification),
6759}
6760
6761impl ClientNotification {
6762 #[must_use]
6764 pub fn method(&self) -> &str {
6765 match self {
6766 Self::CancelNotification(_) => AGENT_METHOD_NAMES.session_cancel,
6767 #[cfg(feature = "unstable_mcp_over_acp")]
6768 Self::MessageMcpNotification(_) => AGENT_METHOD_NAMES.mcp_message,
6769 Self::ExtNotification(ext_notification) => &ext_notification.method,
6770 }
6771 }
6772}
6773
6774#[serde_as]
6778#[skip_serializing_none]
6779#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
6780#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
6781#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_CANCEL_METHOD_NAME)))]
6782#[serde(rename_all = "camelCase")]
6783#[non_exhaustive]
6784pub struct CancelNotification {
6785 pub session_id: SessionId,
6787 #[serde_as(deserialize_as = "DefaultOnError")]
6793 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
6794 #[serde(default)]
6795 #[serde(rename = "_meta")]
6796 pub meta: Option<Meta>,
6797}
6798
6799impl CancelNotification {
6800 #[must_use]
6802 pub fn new(session_id: impl Into<SessionId>) -> Self {
6803 Self {
6804 session_id: session_id.into(),
6805 meta: None,
6806 }
6807 }
6808
6809 #[must_use]
6815 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
6816 self.meta = meta.into_option();
6817 self
6818 }
6819}
6820
6821#[cfg(test)]
6822mod test_serialization {
6823 use super::*;
6824 use serde_json::json;
6825
6826 fn test_meta() -> Meta {
6827 json!({ "source": "test" }).as_object().unwrap().clone()
6828 }
6829
6830 fn serialized_meta_key_count(value: &impl serde::Serialize) -> usize {
6831 serde_json::to_string(value)
6832 .unwrap()
6833 .matches("\"_meta\"")
6834 .count()
6835 }
6836
6837 #[test]
6840 fn prompt_response_has_no_error_stop_reason() {
6841 assert_eq!(
6842 serde_json::from_value::<PromptResponse>(json!({ "stopReason": "end_turn" }))
6843 .unwrap()
6844 .stop_reason,
6845 StopReason::EndTurn
6846 );
6847 assert!(
6848 serde_json::from_value::<PromptResponse>(json!({ "stopReason": "error" })).is_err()
6849 );
6850 }
6851
6852 #[test]
6853 fn test_initialize_capabilities_default_on_malformed_values() {
6854 let request: InitializeRequest = serde_json::from_value(json!({
6855 "protocolVersion": 1,
6856 "clientCapabilities": false
6857 }))
6858 .unwrap();
6859 assert_eq!(request.client_capabilities, ClientCapabilities::default());
6860
6861 let response: InitializeResponse = serde_json::from_value(json!({
6862 "protocolVersion": 1,
6863 "agentCapabilities": false
6864 }))
6865 .unwrap();
6866 assert_eq!(response.agent_capabilities, AgentCapabilities::default());
6867 }
6868
6869 #[test]
6870 fn test_agent_capabilities_default_on_malformed_values() {
6871 let capabilities: AgentCapabilities = serde_json::from_value(json!({
6872 "loadSession": "yes",
6873 "promptCapabilities": {
6874 "image": "yes",
6875 "audio": true,
6876 "embeddedContext": {}
6877 },
6878 "mcpCapabilities": {
6879 "http": "yes",
6880 "sse": true
6881 },
6882 "sessionCapabilities": false,
6883 "auth": false
6884 }))
6885 .unwrap();
6886
6887 assert!(!capabilities.load_session);
6888 assert!(!capabilities.prompt_capabilities.image);
6889 assert!(capabilities.prompt_capabilities.audio);
6890 assert!(!capabilities.prompt_capabilities.embedded_context);
6891 assert!(!capabilities.mcp_capabilities.http);
6892 assert!(capabilities.mcp_capabilities.sse);
6893 assert_eq!(
6894 capabilities.session_capabilities,
6895 SessionCapabilities::default()
6896 );
6897 assert_eq!(capabilities.auth, AgentAuthCapabilities::default());
6898 }
6899
6900 #[test]
6901 fn test_mcp_server_stdio_serialization() {
6902 let server = McpServer::Stdio(
6903 McpServerStdio::new("test-server", "/usr/bin/server")
6904 .args(vec!["--port".to_string(), "3000".to_string()])
6905 .env(vec![EnvVariable::new("API_KEY", "secret123")]),
6906 );
6907
6908 let json = serde_json::to_value(&server).unwrap();
6909 assert_eq!(
6910 json,
6911 json!({
6912 "name": "test-server",
6913 "command": "/usr/bin/server",
6914 "args": ["--port", "3000"],
6915 "env": [
6916 {
6917 "name": "API_KEY",
6918 "value": "secret123"
6919 }
6920 ]
6921 })
6922 );
6923
6924 let deserialized: McpServer = serde_json::from_value(json).unwrap();
6925 match deserialized {
6926 McpServer::Stdio(McpServerStdio {
6927 name,
6928 command,
6929 args,
6930 env,
6931 meta: _,
6932 }) => {
6933 assert_eq!(name, "test-server");
6934 assert_eq!(command, PathBuf::from("/usr/bin/server"));
6935 assert_eq!(args, vec!["--port", "3000"]);
6936 assert_eq!(env.len(), 1);
6937 assert_eq!(env[0].name, "API_KEY");
6938 assert_eq!(env[0].value, "secret123");
6939 }
6940 _ => panic!("Expected Stdio variant"),
6941 }
6942 }
6943
6944 #[test]
6945 fn test_mcp_server_http_serialization() {
6946 let server = McpServer::Http(
6947 McpServerHttp::new("http-server", "https://api.example.com").headers(vec![
6948 HttpHeader::new("Authorization", "Bearer token123"),
6949 HttpHeader::new("Content-Type", "application/json"),
6950 ]),
6951 );
6952
6953 let json = serde_json::to_value(&server).unwrap();
6954 assert_eq!(
6955 json,
6956 json!({
6957 "type": "http",
6958 "name": "http-server",
6959 "url": "https://api.example.com",
6960 "headers": [
6961 {
6962 "name": "Authorization",
6963 "value": "Bearer token123"
6964 },
6965 {
6966 "name": "Content-Type",
6967 "value": "application/json"
6968 }
6969 ]
6970 })
6971 );
6972
6973 let deserialized: McpServer = serde_json::from_value(json).unwrap();
6974 match deserialized {
6975 McpServer::Http(McpServerHttp {
6976 name,
6977 url,
6978 headers,
6979 meta: _,
6980 }) => {
6981 assert_eq!(name, "http-server");
6982 assert_eq!(url, "https://api.example.com");
6983 assert_eq!(headers.len(), 2);
6984 assert_eq!(headers[0].name, "Authorization");
6985 assert_eq!(headers[0].value, "Bearer token123");
6986 assert_eq!(headers[1].name, "Content-Type");
6987 assert_eq!(headers[1].value, "application/json");
6988 }
6989 _ => panic!("Expected Http variant"),
6990 }
6991 }
6992
6993 #[cfg(feature = "unstable_mcp_over_acp")]
6994 #[test]
6995 fn test_mcp_server_acp_serialization() {
6996 let server = McpServer::Acp(McpServerAcp::new("project-tools", "project-tools-id"));
6997
6998 let json = serde_json::to_value(&server).unwrap();
6999 assert_eq!(
7000 json,
7001 json!({
7002 "type": "acp",
7003 "name": "project-tools",
7004 "serverId": "project-tools-id"
7005 })
7006 );
7007
7008 let deserialized: McpServer = serde_json::from_value(json).unwrap();
7009 match deserialized {
7010 McpServer::Acp(McpServerAcp {
7011 name,
7012 server_id: id,
7013 meta: _,
7014 }) => {
7015 assert_eq!(name, "project-tools");
7016 assert_eq!(id, McpServerAcpId::new("project-tools-id"));
7017 }
7018 _ => panic!("Expected Acp variant"),
7019 }
7020 }
7021
7022 #[cfg(feature = "unstable_mcp_over_acp")]
7023 #[test]
7024 fn test_client_mcp_message_method_names() {
7025 use serde_json::json;
7026
7027 assert_eq!(AGENT_METHOD_NAMES.mcp_message, "mcp/message");
7028
7029 let notification =
7030 MessageMcpNotification::new("server-1", "req-1", "notifications/progress");
7031 assert_eq!(
7032 ClientNotification::MessageMcpNotification(notification.clone()).method(),
7033 "mcp/message"
7034 );
7035 assert_eq!(
7036 serde_json::to_value(notification).unwrap(),
7037 json!({
7038 "serverId": "server-1",
7039 "requestId": "req-1",
7040 "method": "notifications/progress"
7041 })
7042 );
7043 let notification: MessageMcpNotification = serde_json::from_value(json!({
7044 "serverId": "server-1", "requestId": "req-1", "method": "notifications/progress",
7045 "params": null, "_meta": null
7046 }))
7047 .unwrap();
7048 assert_eq!(notification.params, None);
7049 assert_eq!(notification.meta, None);
7050 for key in ["serverId", "requestId", "method"] {
7051 let mut value = json!({"serverId":"server-1", "requestId":"req-1", "method":"notifications/progress"});
7052 value.as_object_mut().unwrap().remove(key);
7053 assert!(serde_json::from_value::<MessageMcpNotification>(value).is_err());
7054 }
7055 }
7056
7057 #[cfg(all(feature = "unstable_mcp_over_acp", feature = "schemars"))]
7058 #[test]
7059 fn test_mcp_server_acp_schema() {
7060 let mcp_server_schema = serde_json::to_value(schemars::schema_for!(McpServer)).unwrap();
7061 assert!(json_contains_entry(
7062 &mcp_server_schema,
7063 "const",
7064 &json!("acp")
7065 ));
7066 assert!(json_contains_entry(
7067 &mcp_server_schema,
7068 "$ref",
7069 &json!("#/$defs/McpServerAcp")
7070 ));
7071
7072 let capabilities_schema =
7073 serde_json::to_value(schemars::schema_for!(McpCapabilities)).unwrap();
7074 assert!(json_contains_key(&capabilities_schema, "acp"));
7075 }
7076
7077 #[cfg(all(feature = "unstable_mcp_over_acp", feature = "schemars"))]
7078 fn json_contains_entry(
7079 value: &serde_json::Value,
7080 key: &str,
7081 expected: &serde_json::Value,
7082 ) -> bool {
7083 match value {
7084 serde_json::Value::Object(map) => {
7085 map.get(key) == Some(expected)
7086 || map
7087 .values()
7088 .any(|value| json_contains_entry(value, key, expected))
7089 }
7090 serde_json::Value::Array(values) => values
7091 .iter()
7092 .any(|value| json_contains_entry(value, key, expected)),
7093 _ => false,
7094 }
7095 }
7096
7097 #[cfg(all(feature = "unstable_mcp_over_acp", feature = "schemars"))]
7098 fn json_contains_key(value: &serde_json::Value, key: &str) -> bool {
7099 match value {
7100 serde_json::Value::Object(map) => {
7101 map.contains_key(key) || map.values().any(|value| json_contains_key(value, key))
7102 }
7103 serde_json::Value::Array(values) => {
7104 values.iter().any(|value| json_contains_key(value, key))
7105 }
7106 _ => false,
7107 }
7108 }
7109
7110 #[test]
7111 fn test_mcp_server_sse_serialization() {
7112 let server = McpServer::Sse(
7113 McpServerSse::new("sse-server", "https://sse.example.com/events")
7114 .headers(vec![HttpHeader::new("X-API-Key", "apikey456")]),
7115 );
7116
7117 let json = serde_json::to_value(&server).unwrap();
7118 assert_eq!(
7119 json,
7120 json!({
7121 "type": "sse",
7122 "name": "sse-server",
7123 "url": "https://sse.example.com/events",
7124 "headers": [
7125 {
7126 "name": "X-API-Key",
7127 "value": "apikey456"
7128 }
7129 ]
7130 })
7131 );
7132
7133 let deserialized: McpServer = serde_json::from_value(json).unwrap();
7134 match deserialized {
7135 McpServer::Sse(McpServerSse {
7136 name,
7137 url,
7138 headers,
7139 meta: _,
7140 }) => {
7141 assert_eq!(name, "sse-server");
7142 assert_eq!(url, "https://sse.example.com/events");
7143 assert_eq!(headers.len(), 1);
7144 assert_eq!(headers[0].name, "X-API-Key");
7145 assert_eq!(headers[0].value, "apikey456");
7146 }
7147 _ => panic!("Expected Sse variant"),
7148 }
7149 }
7150
7151 #[test]
7152 fn test_session_config_option_category_known_variants() {
7153 assert_eq!(
7155 serde_json::to_value(&SessionConfigOptionCategory::Mode).unwrap(),
7156 json!("mode")
7157 );
7158 assert_eq!(
7159 serde_json::to_value(&SessionConfigOptionCategory::Model).unwrap(),
7160 json!("model")
7161 );
7162 assert_eq!(
7163 serde_json::to_value(&SessionConfigOptionCategory::ModelConfig).unwrap(),
7164 json!("model_config")
7165 );
7166 assert_eq!(
7167 serde_json::to_value(&SessionConfigOptionCategory::ThoughtLevel).unwrap(),
7168 json!("thought_level")
7169 );
7170
7171 assert_eq!(
7173 serde_json::from_str::<SessionConfigOptionCategory>("\"mode\"").unwrap(),
7174 SessionConfigOptionCategory::Mode
7175 );
7176 assert_eq!(
7177 serde_json::from_str::<SessionConfigOptionCategory>("\"model\"").unwrap(),
7178 SessionConfigOptionCategory::Model
7179 );
7180 assert_eq!(
7181 serde_json::from_str::<SessionConfigOptionCategory>("\"model_config\"").unwrap(),
7182 SessionConfigOptionCategory::ModelConfig
7183 );
7184 assert_eq!(
7185 serde_json::from_str::<SessionConfigOptionCategory>("\"thought_level\"").unwrap(),
7186 SessionConfigOptionCategory::ThoughtLevel
7187 );
7188 }
7189
7190 #[test]
7191 fn test_session_config_option_category_unknown_variants() {
7192 let unknown: SessionConfigOptionCategory =
7194 serde_json::from_str("\"some_future_category\"").unwrap();
7195 assert_eq!(
7196 unknown,
7197 SessionConfigOptionCategory::Other("some_future_category".to_string())
7198 );
7199
7200 let json = serde_json::to_value(&unknown).unwrap();
7202 assert_eq!(json, json!("some_future_category"));
7203 }
7204
7205 #[test]
7206 fn test_session_config_option_category_custom_categories() {
7207 let custom: SessionConfigOptionCategory =
7209 serde_json::from_str("\"_my_custom_category\"").unwrap();
7210 assert_eq!(
7211 custom,
7212 SessionConfigOptionCategory::Other("_my_custom_category".to_string())
7213 );
7214
7215 let json = serde_json::to_value(&custom).unwrap();
7217 assert_eq!(json, json!("_my_custom_category"));
7218
7219 let deserialized: SessionConfigOptionCategory = serde_json::from_value(json).unwrap();
7221 assert_eq!(
7222 deserialized,
7223 SessionConfigOptionCategory::Other("_my_custom_category".to_string()),
7224 );
7225 }
7226
7227 #[test]
7228 fn test_auth_method_agent_serialization() {
7229 let method = AuthMethod::Agent(AuthMethodAgent::new("default-auth", "Default Auth"));
7230
7231 let json = serde_json::to_value(&method).unwrap();
7232 assert_eq!(
7233 json,
7234 json!({
7235 "id": "default-auth",
7236 "name": "Default Auth"
7237 })
7238 );
7239 assert!(!json.as_object().unwrap().contains_key("description"));
7241 assert!(!json.as_object().unwrap().contains_key("type"));
7243
7244 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
7245 match deserialized {
7246 AuthMethod::Agent(AuthMethodAgent { id, name, .. }) => {
7247 assert_eq!(id.0.as_ref(), "default-auth");
7248 assert_eq!(name, "Default Auth");
7249 }
7250 _ => panic!("Expected Agent variant"),
7251 }
7252 }
7253
7254 #[test]
7255 fn test_auth_method_explicit_agent_deserialization() {
7256 let json = json!({
7258 "id": "agent-auth",
7259 "name": "Agent Auth",
7260 "type": "agent"
7261 });
7262
7263 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
7264 assert!(matches!(deserialized, AuthMethod::Agent(_)));
7265 }
7266
7267 #[test]
7268 fn test_session_delete_serialization() {
7269 assert_eq!(AGENT_METHOD_NAMES.session_delete, "session/delete");
7270 assert_eq!(
7271 ClientRequest::DeleteSessionRequest(DeleteSessionRequest::new("sess_abc123")).method(),
7272 "session/delete"
7273 );
7274 assert_eq!(
7275 serde_json::to_value(DeleteSessionRequest::new("sess_abc123")).unwrap(),
7276 json!({
7277 "sessionId": "sess_abc123"
7278 })
7279 );
7280 assert_eq!(
7281 serde_json::to_value(DeleteSessionResponse::new()).unwrap(),
7282 json!({})
7283 );
7284 assert_eq!(
7285 serde_json::to_value(
7286 SessionCapabilities::new().delete(SessionDeleteCapabilities::new())
7287 )
7288 .unwrap(),
7289 json!({
7290 "delete": {}
7291 })
7292 );
7293 }
7294 #[cfg(feature = "unstable_session_set_title")]
7295 #[test]
7296 fn test_session_set_title_serialization() {
7297 assert_eq!(AGENT_METHOD_NAMES.session_set_title, "session/set_title");
7298 assert_eq!(
7299 ClientRequest::SetSessionTitleRequest(SetSessionTitleRequest::new(
7300 "sess_abc123",
7301 "Investigate OAuth timeout"
7302 ))
7303 .method(),
7304 "session/set_title"
7305 );
7306 assert_eq!(
7307 serde_json::to_value(SetSessionTitleRequest::new(
7308 "sess_abc123",
7309 "Investigate OAuth timeout"
7310 ))
7311 .unwrap(),
7312 json!({
7313 "sessionId": "sess_abc123",
7314 "title": "Investigate OAuth timeout"
7315 })
7316 );
7317 assert_eq!(
7318 serde_json::to_value(SetSessionTitleResponse::new("Investigate OAuth timeout"))
7319 .unwrap(),
7320 json!({
7321 "title": "Investigate OAuth timeout"
7322 })
7323 );
7324 assert_eq!(
7325 serde_json::to_value(SessionCapabilities::new().title(SessionTitleCapabilities::new()))
7326 .unwrap(),
7327 json!({
7328 "title": {}
7329 })
7330 );
7331 }
7332
7333 #[cfg(feature = "unstable_session_set_title")]
7334 #[test]
7335 fn test_session_set_title_requires_title() {
7336 for params in [
7337 json!({"sessionId": "sess_abc123"}),
7338 json!({"sessionId": "sess_abc123", "title": null}),
7339 json!({"sessionId": "sess_abc123", "title": 42}),
7340 ] {
7341 assert!(serde_json::from_value::<SetSessionTitleRequest>(params).is_err());
7342 }
7343 for result in [json!({}), json!({"title": null})] {
7344 assert!(serde_json::from_value::<SetSessionTitleResponse>(result).is_err());
7345 }
7346 }
7347
7348 #[cfg(feature = "unstable_session_status")]
7349 #[test]
7350 fn test_session_status_serialization() {
7351 assert_eq!(AGENT_METHOD_NAMES.session_status, "session/status");
7352 assert_eq!(
7353 ClientRequest::SessionStatusRequest(SessionStatusRequest::new("sess_abc123")).method(),
7354 "session/status"
7355 );
7356 assert_eq!(
7357 serde_json::to_value(SessionStatusRequest::new("sess_abc123")).unwrap(),
7358 json!({"sessionId": "sess_abc123"})
7359 );
7360 assert_eq!(
7361 serde_json::to_value(SessionStatusResponse::new(SessionStatus::Saved)).unwrap(),
7362 json!({"status": "saved"})
7363 );
7364 assert_eq!(
7365 serde_json::to_value(
7366 SessionCapabilities::new().status(SessionStatusCapabilities::new())
7367 )
7368 .unwrap(),
7369 json!({"status": {}})
7370 );
7371 }
7372
7373 #[cfg(feature = "unstable_session_status")]
7374 #[test]
7375 fn test_session_status_is_strict_and_open() {
7376 let custom =
7377 serde_json::from_value::<SessionStatusResponse>(json!({"status": "_suspended"}))
7378 .unwrap();
7379 assert_eq!(
7380 custom.status,
7381 SessionStatus::Other("_suspended".to_string())
7382 );
7383 assert_eq!(
7384 serde_json::to_value(&custom).unwrap(),
7385 json!({"status": "_suspended"})
7386 );
7387 for result in [json!({}), json!({"status": null}), json!({"status": 1})] {
7388 assert!(serde_json::from_value::<SessionStatusResponse>(result).is_err());
7389 }
7390 for params in [json!({}), json!({"sessionId": null})] {
7391 assert!(serde_json::from_value::<SessionStatusRequest>(params).is_err());
7392 }
7393 }
7394
7395 #[cfg(feature = "unstable_session_archive")]
7396 #[test]
7397 fn test_session_archive_serialization() {
7398 assert_eq!(AGENT_METHOD_NAMES.session_archive, "session/archive");
7399 assert_eq!(AGENT_METHOD_NAMES.session_unarchive, "session/unarchive");
7400 assert_eq!(
7401 ClientRequest::ArchiveSessionRequest(ArchiveSessionRequest::new("sess_abc123"))
7402 .method(),
7403 "session/archive"
7404 );
7405 assert_eq!(
7406 ClientRequest::UnarchiveSessionRequest(UnarchiveSessionRequest::new("sess_abc123"))
7407 .method(),
7408 "session/unarchive"
7409 );
7410 assert_eq!(
7411 serde_json::to_value(ArchiveSessionRequest::new("sess_abc123")).unwrap(),
7412 json!({"sessionId": "sess_abc123"})
7413 );
7414 assert_eq!(
7415 serde_json::to_value(UnarchiveSessionResponse::new()).unwrap(),
7416 json!({})
7417 );
7418 assert_eq!(
7419 serde_json::to_value(
7420 SessionCapabilities::new().archive(SessionArchiveCapabilities::new())
7421 )
7422 .unwrap(),
7423 json!({"archive": {}})
7424 );
7425 assert_eq!(
7426 serde_json::to_value(
7427 ListSessionsRequest::new()
7428 .cwd("/home/user/project")
7429 .archived(SessionArchiveFilter::Only)
7430 )
7431 .unwrap(),
7432 json!({"cwd": "/home/user/project", "archived": "only"})
7433 );
7434 assert_eq!(
7435 serde_json::to_value(
7436 SessionInfo::new("sess_abc123", "/home/user/project").archived(true)
7437 )
7438 .unwrap(),
7439 json!({"sessionId": "sess_abc123", "cwd": "/home/user/project", "archived": true})
7440 );
7441 }
7442
7443 #[cfg(feature = "unstable_session_archive")]
7444 #[test]
7445 fn test_session_archive_filter_is_strict_and_open() {
7446 for (value, expected) in [
7447 (json!(null), None),
7448 (json!("include"), Some(SessionArchiveFilter::Include)),
7449 (
7450 json!("_recent"),
7451 Some(SessionArchiveFilter::Other("_recent".to_string())),
7452 ),
7453 ] {
7454 let request =
7455 serde_json::from_value::<ListSessionsRequest>(json!({"archived": value})).unwrap();
7456 assert_eq!(request.archived, expected);
7457 }
7458 for value in [json!(true), json!(1), json!({})] {
7459 assert!(
7460 serde_json::from_value::<ListSessionsRequest>(json!({"archived": value})).is_err()
7461 );
7462 }
7463 let info = serde_json::from_value::<SessionInfo>(
7464 json!({"sessionId": "sess_abc123", "cwd": "/home/user/project", "archived": "yes"}),
7465 )
7466 .unwrap();
7467 assert_eq!(info.archived, None);
7468 }
7469
7470 #[test]
7471 fn test_session_additional_directories_serialization() {
7472 assert_eq!(
7473 serde_json::to_value(NewSessionRequest::new("/home/user/project")).unwrap(),
7474 json!({
7475 "cwd": "/home/user/project",
7476 "mcpServers": []
7477 })
7478 );
7479 assert_eq!(
7480 serde_json::to_value(
7481 NewSessionRequest::new("/home/user/project").additional_directories(vec![
7482 PathBuf::from("/home/user/shared-lib"),
7483 PathBuf::from("/home/user/product-docs"),
7484 ])
7485 )
7486 .unwrap(),
7487 json!({
7488 "cwd": "/home/user/project",
7489 "additionalDirectories": [
7490 "/home/user/shared-lib",
7491 "/home/user/product-docs"
7492 ],
7493 "mcpServers": []
7494 })
7495 );
7496 assert_eq!(
7497 serde_json::to_value(SessionInfo::new("sess_abc123", "/home/user/project")).unwrap(),
7498 json!({
7499 "sessionId": "sess_abc123",
7500 "cwd": "/home/user/project"
7501 })
7502 );
7503 assert_eq!(
7504 serde_json::to_value(
7505 SessionInfo::new("sess_abc123", "/home/user/project").additional_directories(vec![
7506 PathBuf::from("/home/user/shared-lib"),
7507 PathBuf::from("/home/user/product-docs"),
7508 ])
7509 )
7510 .unwrap(),
7511 json!({
7512 "sessionId": "sess_abc123",
7513 "cwd": "/home/user/project",
7514 "additionalDirectories": [
7515 "/home/user/shared-lib",
7516 "/home/user/product-docs"
7517 ]
7518 })
7519 );
7520 assert_eq!(
7521 serde_json::from_value::<SessionInfo>(json!({
7522 "sessionId": "sess_abc123",
7523 "cwd": "/home/user/project"
7524 }))
7525 .unwrap()
7526 .additional_directories,
7527 Vec::<PathBuf>::new()
7528 );
7529 }
7530 #[test]
7531 fn test_session_additional_directories_capabilities_serialization() {
7532 assert_eq!(
7533 serde_json::to_value(
7534 SessionCapabilities::new()
7535 .additional_directories(SessionAdditionalDirectoriesCapabilities::new())
7536 )
7537 .unwrap(),
7538 json!({
7539 "additionalDirectories": {}
7540 })
7541 );
7542 }
7543
7544 #[cfg(feature = "unstable_session_system_prompt")]
7545 #[test]
7546 fn test_session_system_prompt_capabilities_serialization() {
7547 assert_eq!(
7548 serde_json::to_value(
7549 SessionCapabilities::new().system_prompt(SessionSystemPromptCapabilities::new())
7550 )
7551 .unwrap(),
7552 json!({ "systemPrompt": {} })
7553 );
7554 assert_eq!(
7555 serde_json::to_value(
7556 SessionCapabilities::new().system_prompt(
7557 SessionSystemPromptCapabilities::new().mode(
7558 SessionSystemPromptModeCapabilities::new()
7559 .override_(SessionSystemPromptOverrideCapabilities::new())
7560 )
7561 )
7562 )
7563 .unwrap(),
7564 json!({ "systemPrompt": { "mode": { "override": {} } } })
7565 );
7566 assert_eq!(
7567 serde_json::from_value::<SessionCapabilities>(
7568 json!({ "systemPrompt": { "mode": { "override": {} } } })
7569 )
7570 .unwrap()
7571 .system_prompt
7572 .and_then(|capabilities| capabilities.mode)
7573 .and_then(|mode| mode.override_),
7574 Some(SessionSystemPromptOverrideCapabilities::new())
7575 );
7576
7577 assert_eq!(
7579 serde_json::from_value::<SessionCapabilities>(json!({ "systemPrompt": "yes" }))
7580 .unwrap()
7581 .system_prompt,
7582 None
7583 );
7584 assert_eq!(
7585 serde_json::from_value::<SessionCapabilities>(
7586 json!({ "systemPrompt": { "mode": { "override": true } } })
7587 )
7588 .unwrap()
7589 .system_prompt,
7590 Some(
7591 SessionSystemPromptCapabilities::new()
7592 .mode(SessionSystemPromptModeCapabilities::new())
7593 )
7594 );
7595 assert_eq!(
7596 serde_json::from_value::<SessionCapabilities>(
7597 json!({ "systemPrompt": { "mode": "override" } })
7598 )
7599 .unwrap()
7600 .system_prompt,
7601 Some(SessionSystemPromptCapabilities::new())
7602 );
7603 }
7604
7605 #[cfg(feature = "unstable_session_system_prompt")]
7606 #[test]
7607 fn test_system_prompt_lifecycle_request_serialization() {
7608 let system_prompt = SystemPrompt::new(vec![ContentBlock::from(
7609 "You are a code review specialist.",
7610 )]);
7611 let system_prompt_json = json!({
7612 "mode": "append",
7613 "content": [{ "type": "text", "text": "You are a code review specialist." }]
7614 });
7615
7616 let request =
7617 NewSessionRequest::new("/home/user/project").system_prompt(system_prompt.clone());
7618 let request_json = json!({
7619 "cwd": "/home/user/project",
7620 "mcpServers": [],
7621 "systemPrompt": system_prompt_json
7622 });
7623 assert_eq!(serde_json::to_value(&request).unwrap(), request_json);
7624 assert_eq!(
7625 serde_json::from_value::<NewSessionRequest>(request_json).unwrap(),
7626 request
7627 );
7628
7629 assert_eq!(
7630 serde_json::to_value(
7631 LoadSessionRequest::new("sess_abc123", "/home/user/project")
7632 .system_prompt(system_prompt.clone())
7633 )
7634 .unwrap()["systemPrompt"],
7635 system_prompt_json
7636 );
7637 assert_eq!(
7638 serde_json::to_value(
7639 ResumeSessionRequest::new("sess_abc123", "/home/user/project")
7640 .system_prompt(system_prompt.clone())
7641 )
7642 .unwrap()["systemPrompt"],
7643 system_prompt_json
7644 );
7645 #[cfg(feature = "unstable_session_fork")]
7646 assert_eq!(
7647 serde_json::to_value(
7648 ForkSessionRequest::new("sess_abc123", "/home/user/project")
7649 .system_prompt(system_prompt.clone())
7650 )
7651 .unwrap()["systemPrompt"],
7652 system_prompt_json
7653 );
7654
7655 let override_prompt =
7656 SystemPrompt::new(vec![ContentBlock::from("...")]).mode(SystemPromptMode::Override);
7657 let override_json = json!({
7658 "mode": "override",
7659 "content": [{ "type": "text", "text": "..." }]
7660 });
7661 assert_eq!(
7662 serde_json::to_value(&override_prompt).unwrap(),
7663 override_json
7664 );
7665 assert_eq!(
7666 serde_json::from_value::<SystemPrompt>(override_json).unwrap(),
7667 override_prompt
7668 );
7669 }
7670
7671 #[cfg(feature = "unstable_session_system_prompt")]
7674 #[test]
7675 fn test_system_prompt_new_defaults_to_append() {
7676 let system_prompt = SystemPrompt::new(vec![ContentBlock::from("...")]);
7677 assert_eq!(system_prompt.mode, SystemPromptMode::Append);
7678 assert_eq!(
7679 serde_json::to_value(&system_prompt).unwrap(),
7680 json!({ "mode": "append", "content": [{ "type": "text", "text": "..." }] })
7681 );
7682 }
7683
7684 #[cfg(feature = "unstable_session_system_prompt")]
7688 #[test]
7689 fn test_system_prompt_preserves_unknown_modes() {
7690 for mode in ["_vendor_mode", "prepend"] {
7691 let system_prompt_json =
7692 json!({ "mode": mode, "content": [{ "type": "text", "text": "..." }] });
7693 let system_prompt: SystemPrompt =
7694 serde_json::from_value(system_prompt_json.clone()).unwrap();
7695 assert_eq!(
7696 system_prompt.mode,
7697 SystemPromptMode::Other(mode.to_string())
7698 );
7699 assert_eq!(
7700 serde_json::to_value(&system_prompt).unwrap(),
7701 system_prompt_json
7702 );
7703 }
7704 }
7705
7706 #[cfg(feature = "unstable_session_system_prompt")]
7710 fn assert_system_prompt_is_strict<T>(base: &serde_json::Value)
7711 where
7712 T: serde::de::DeserializeOwned + PartialEq + std::fmt::Debug,
7713 {
7714 let name = std::any::type_name::<T>();
7715 let with = |system_prompt: serde_json::Value| {
7716 let mut request = base.clone();
7717 request["systemPrompt"] = system_prompt;
7718 serde_json::from_value::<T>(request)
7719 };
7720
7721 for system_prompt in [
7722 json!("You are a code review specialist."),
7723 json!({ "content": [{ "type": "text", "text": "..." }] }),
7724 json!({ "mode": null, "content": [{ "type": "text", "text": "..." }] }),
7725 json!({ "mode": 1, "content": [{ "type": "text", "text": "..." }] }),
7726 json!({ "mode": "append" }),
7727 json!({ "mode": "append", "content": "..." }),
7728 json!({ "mode": "append", "content": [{ "type": "text" }] }),
7729 json!({ "mode": "append", "content": [{ "type": "video", "uri": "..." }] }),
7730 ] {
7731 assert!(
7732 with(system_prompt.clone()).is_err(),
7733 "{name}.systemPrompt: {system_prompt}"
7734 );
7735 }
7736
7737 assert_eq!(
7738 with(serde_json::Value::Null).unwrap(),
7739 serde_json::from_value::<T>(base.clone()).unwrap(),
7740 "{name}.systemPrompt"
7741 );
7742 }
7743
7744 #[cfg(feature = "unstable_session_system_prompt")]
7745 #[test]
7746 fn test_session_setup_requests_reject_malformed_system_prompts() {
7747 assert!(
7748 serde_json::to_value(NewSessionRequest::new("/repo"))
7749 .unwrap()
7750 .get("systemPrompt")
7751 .is_none()
7752 );
7753 assert_system_prompt_is_strict::<NewSessionRequest>(&json!({
7754 "cwd": "/repo",
7755 "mcpServers": []
7756 }));
7757 assert_system_prompt_is_strict::<LoadSessionRequest>(&json!({
7758 "sessionId": "sess-1",
7759 "cwd": "/repo",
7760 "mcpServers": []
7761 }));
7762 assert_system_prompt_is_strict::<ResumeSessionRequest>(&json!({
7763 "sessionId": "sess-1",
7764 "cwd": "/repo"
7765 }));
7766 #[cfg(feature = "unstable_session_fork")]
7767 assert_system_prompt_is_strict::<ForkSessionRequest>(&json!({
7768 "sessionId": "sess-1",
7769 "cwd": "/repo"
7770 }));
7771 }
7772
7773 #[test]
7774 fn test_auth_method_terminal_serialization() {
7775 let method = AuthMethod::Terminal(AuthMethodTerminal::new("tui-auth", "Terminal Auth"));
7776
7777 let json = serde_json::to_value(&method).unwrap();
7778 assert_eq!(
7779 json,
7780 json!({
7781 "id": "tui-auth",
7782 "name": "Terminal Auth",
7783 "type": "terminal"
7784 })
7785 );
7786 assert!(!json.as_object().unwrap().contains_key("args"));
7788 assert!(!json.as_object().unwrap().contains_key("env"));
7789
7790 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
7791 match deserialized {
7792 AuthMethod::Terminal(AuthMethodTerminal { args, env, .. }) => {
7793 assert_eq!(args, Vec::<String>::new());
7794 assert!(env.is_empty());
7795 }
7796 _ => panic!("Expected Terminal variant"),
7797 }
7798 }
7799
7800 #[test]
7801 fn test_auth_method_terminal_with_args_and_env_serialization() {
7802 use std::collections::HashMap;
7803
7804 let mut env = HashMap::new();
7805 env.insert("TERM".to_string(), "xterm-256color".to_string());
7806
7807 let method = AuthMethod::Terminal(
7808 AuthMethodTerminal::new("tui-auth", "Terminal Auth")
7809 .args(vec!["--interactive".to_string(), "--color".to_string()])
7810 .env(env),
7811 );
7812
7813 let json = serde_json::to_value(&method).unwrap();
7814 assert_eq!(
7815 json,
7816 json!({
7817 "id": "tui-auth",
7818 "name": "Terminal Auth",
7819 "type": "terminal",
7820 "args": ["--interactive", "--color"],
7821 "env": {
7822 "TERM": "xterm-256color"
7823 }
7824 })
7825 );
7826
7827 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
7828 match deserialized {
7829 AuthMethod::Terminal(AuthMethodTerminal { args, env, .. }) => {
7830 assert_eq!(args, vec!["--interactive", "--color"]);
7831 assert_eq!(env.len(), 1);
7832 assert_eq!(env.get("TERM").unwrap(), "xterm-256color");
7833 }
7834 _ => panic!("Expected Terminal variant"),
7835 }
7836 }
7837
7838 #[test]
7839 fn test_session_config_option_value_id_serialize() {
7840 let val = SessionConfigOptionValue::value_id("model-1");
7841 let json = serde_json::to_value(&val).unwrap();
7842 assert_eq!(json, json!({ "value": "model-1" }));
7844 assert!(!json.as_object().unwrap().contains_key("type"));
7845 }
7846
7847 #[test]
7848 fn test_session_config_option_value_boolean_serialize() {
7849 let val = SessionConfigOptionValue::boolean(true);
7850 let json = serde_json::to_value(&val).unwrap();
7851 assert_eq!(json, json!({ "type": "boolean", "value": true }));
7852 }
7853
7854 #[test]
7855 fn test_session_config_option_value_deserialize_no_type() {
7856 let json = json!({ "value": "model-1" });
7858 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
7859 assert_eq!(val, SessionConfigOptionValue::value_id("model-1"));
7860 assert_eq!(val.as_value_id().unwrap().to_string(), "model-1");
7861 }
7862
7863 #[test]
7864 fn test_session_config_option_value_deserialize_boolean() {
7865 let json = json!({ "type": "boolean", "value": true });
7866 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
7867 assert_eq!(val, SessionConfigOptionValue::boolean(true));
7868 assert_eq!(val.as_bool(), Some(true));
7869 }
7870
7871 #[test]
7872 fn test_session_config_option_value_deserialize_boolean_false() {
7873 let json = json!({ "type": "boolean", "value": false });
7874 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
7875 assert_eq!(val, SessionConfigOptionValue::boolean(false));
7876 assert_eq!(val.as_bool(), Some(false));
7877 }
7878
7879 #[test]
7880 fn test_session_config_option_value_deserialize_unknown_type_with_string_value() {
7881 let json = json!({ "type": "text", "value": "freeform input" });
7883 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
7884 assert_eq!(val.as_value_id().unwrap().to_string(), "freeform input");
7885 }
7886
7887 #[test]
7888 fn test_session_config_option_value_roundtrip_value_id() {
7889 let original = SessionConfigOptionValue::value_id("option-a");
7890 let json = serde_json::to_value(&original).unwrap();
7891 let roundtripped: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
7892 assert_eq!(original, roundtripped);
7893 }
7894
7895 #[test]
7896 fn test_session_config_option_value_roundtrip_boolean() {
7897 let original = SessionConfigOptionValue::boolean(false);
7898 let json = serde_json::to_value(&original).unwrap();
7899 let roundtripped: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
7900 assert_eq!(original, roundtripped);
7901 }
7902
7903 #[test]
7904 fn test_session_config_option_value_type_mismatch_boolean_with_string() {
7905 let json = json!({ "type": "boolean", "value": "not a bool" });
7907 let result = serde_json::from_value::<SessionConfigOptionValue>(json);
7908 assert!(result.is_ok());
7910 assert_eq!(
7911 result.unwrap().as_value_id().unwrap().to_string(),
7912 "not a bool"
7913 );
7914 }
7915
7916 #[test]
7917 fn test_session_config_option_value_from_impls() {
7918 let from_str: SessionConfigOptionValue = "model-1".into();
7919 assert_eq!(from_str.as_value_id().unwrap().to_string(), "model-1");
7920
7921 let from_id: SessionConfigOptionValue = SessionConfigValueId::new("model-2").into();
7922 assert_eq!(from_id.as_value_id().unwrap().to_string(), "model-2");
7923
7924 let from_bool: SessionConfigOptionValue = true.into();
7925 assert_eq!(from_bool.as_bool(), Some(true));
7926 }
7927
7928 #[test]
7929 fn test_set_session_config_option_request_value_id() {
7930 let req = SetSessionConfigOptionRequest::new("sess_1", "model", "model-1");
7931 let json = serde_json::to_value(&req).unwrap();
7932 assert_eq!(
7933 json,
7934 json!({
7935 "sessionId": "sess_1",
7936 "configId": "model",
7937 "value": "model-1"
7938 })
7939 );
7940 assert!(!json.as_object().unwrap().contains_key("type"));
7942 }
7943
7944 #[test]
7945 fn test_set_session_config_option_request_boolean() {
7946 let req = SetSessionConfigOptionRequest::new("sess_1", "brave_mode", true);
7947 let json = serde_json::to_value(&req).unwrap();
7948 assert_eq!(
7949 json,
7950 json!({
7951 "sessionId": "sess_1",
7952 "configId": "brave_mode",
7953 "type": "boolean",
7954 "value": true
7955 })
7956 );
7957 }
7958
7959 #[test]
7960 fn test_set_session_config_option_request_deserialize_no_type() {
7961 let json = json!({
7963 "sessionId": "sess_1",
7964 "configId": "model",
7965 "value": "model-1"
7966 });
7967 let req: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
7968 assert_eq!(req.session_id.to_string(), "sess_1");
7969 assert_eq!(req.config_id.to_string(), "model");
7970 assert_eq!(req.value.as_value_id().unwrap().to_string(), "model-1");
7971 }
7972
7973 #[test]
7974 fn test_set_session_config_option_request_deserialize_boolean() {
7975 let json = json!({
7976 "sessionId": "sess_1",
7977 "configId": "brave_mode",
7978 "type": "boolean",
7979 "value": true
7980 });
7981 let req: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
7982 assert_eq!(req.value.as_bool(), Some(true));
7983 }
7984
7985 #[test]
7986 fn test_set_session_config_option_request_roundtrip_value_id() {
7987 let original = SetSessionConfigOptionRequest::new("s", "c", "v");
7988 let json = serde_json::to_value(&original).unwrap();
7989 let roundtripped: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
7990 assert_eq!(original, roundtripped);
7991 }
7992
7993 #[test]
7994 fn test_set_session_config_option_request_roundtrip_boolean() {
7995 let original = SetSessionConfigOptionRequest::new("s", "c", false);
7996 let json = serde_json::to_value(&original).unwrap();
7997 let roundtripped: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
7998 assert_eq!(original, roundtripped);
7999 }
8000
8001 #[test]
8002 fn test_session_config_boolean_serialization() {
8003 let cfg = SessionConfigBoolean::new(true);
8004 let json = serde_json::to_value(&cfg).unwrap();
8005 assert_eq!(json, json!({ "currentValue": true }));
8006
8007 let deserialized: SessionConfigBoolean = serde_json::from_value(json).unwrap();
8008 assert!(deserialized.current_value);
8009 }
8010
8011 #[test]
8012 fn test_session_config_option_boolean_variant() {
8013 let opt = SessionConfigOption::boolean("brave_mode", "Brave Mode", false)
8014 .description("Skip confirmation prompts")
8015 .meta(test_meta());
8016 assert_eq!(serialized_meta_key_count(&opt), 1);
8017
8018 let json = serde_json::to_value(&opt).unwrap();
8019 assert_eq!(
8020 json,
8021 json!({
8022 "id": "brave_mode",
8023 "name": "Brave Mode",
8024 "description": "Skip confirmation prompts",
8025 "type": "boolean",
8026 "currentValue": false,
8027 "_meta": {
8028 "source": "test"
8029 }
8030 })
8031 );
8032
8033 let deserialized: SessionConfigOption = serde_json::from_value(json).unwrap();
8034 assert_eq!(deserialized.id.to_string(), "brave_mode");
8035 assert_eq!(deserialized.name, "Brave Mode");
8036 match deserialized.kind {
8037 SessionConfigKind::Boolean(ref b) => assert!(!b.current_value),
8038 _ => panic!("Expected Boolean kind"),
8039 }
8040 }
8041
8042 #[test]
8043 fn test_session_config_option_select_still_works() {
8044 let opt = SessionConfigOption::select(
8046 "model",
8047 "Model",
8048 "model-1",
8049 vec![
8050 SessionConfigSelectOption::new("model-1", "Model 1"),
8051 SessionConfigSelectOption::new("model-2", "Model 2"),
8052 ],
8053 )
8054 .meta(test_meta());
8055 assert_eq!(serialized_meta_key_count(&opt), 1);
8056
8057 let json = serde_json::to_value(&opt).unwrap();
8058 assert_eq!(json["type"], "select");
8059 assert_eq!(json["currentValue"], "model-1");
8060 assert_eq!(json["options"].as_array().unwrap().len(), 2);
8061 assert_eq!(json["_meta"]["source"], "test");
8062
8063 let deserialized: SessionConfigOption = serde_json::from_value(json).unwrap();
8064 match deserialized.kind {
8065 SessionConfigKind::Select(ref s) => {
8066 assert_eq!(s.current_value.to_string(), "model-1");
8067 }
8068 _ => panic!("Expected Select kind"),
8069 }
8070 }
8071
8072 #[cfg(feature = "unstable_llm_providers")]
8073 #[test]
8074 fn test_llm_protocol_known_variants() {
8075 assert_eq!(
8076 serde_json::to_value(&LlmProtocol::Anthropic).unwrap(),
8077 json!("anthropic")
8078 );
8079 assert_eq!(
8080 serde_json::to_value(&LlmProtocol::OpenAi).unwrap(),
8081 json!("openai")
8082 );
8083 assert_eq!(
8084 serde_json::to_value(&LlmProtocol::Azure).unwrap(),
8085 json!("azure")
8086 );
8087 assert_eq!(
8088 serde_json::to_value(&LlmProtocol::Vertex).unwrap(),
8089 json!("vertex")
8090 );
8091 assert_eq!(
8092 serde_json::to_value(&LlmProtocol::Bedrock).unwrap(),
8093 json!("bedrock")
8094 );
8095
8096 assert_eq!(
8097 serde_json::from_str::<LlmProtocol>("\"anthropic\"").unwrap(),
8098 LlmProtocol::Anthropic
8099 );
8100 assert_eq!(
8101 serde_json::from_str::<LlmProtocol>("\"openai\"").unwrap(),
8102 LlmProtocol::OpenAi
8103 );
8104 assert_eq!(
8105 serde_json::from_str::<LlmProtocol>("\"azure\"").unwrap(),
8106 LlmProtocol::Azure
8107 );
8108 assert_eq!(
8109 serde_json::from_str::<LlmProtocol>("\"vertex\"").unwrap(),
8110 LlmProtocol::Vertex
8111 );
8112 assert_eq!(
8113 serde_json::from_str::<LlmProtocol>("\"bedrock\"").unwrap(),
8114 LlmProtocol::Bedrock
8115 );
8116 }
8117
8118 #[cfg(feature = "unstable_llm_providers")]
8119 #[test]
8120 fn test_llm_protocol_unknown_variant() {
8121 let unknown: LlmProtocol = serde_json::from_str("\"cohere\"").unwrap();
8122 assert_eq!(unknown, LlmProtocol::Other("cohere".to_string()));
8123
8124 let json = serde_json::to_value(&unknown).unwrap();
8125 assert_eq!(json, json!("cohere"));
8126 }
8127
8128 #[cfg(feature = "unstable_llm_providers")]
8129 #[test]
8130 fn test_provider_current_config_serialization() {
8131 let config =
8132 ProviderCurrentConfig::new(LlmProtocol::Anthropic, "https://api.anthropic.com");
8133
8134 let json = serde_json::to_value(&config).unwrap();
8135 assert_eq!(
8136 json,
8137 json!({
8138 "apiType": "anthropic",
8139 "baseUrl": "https://api.anthropic.com"
8140 })
8141 );
8142
8143 let deserialized: ProviderCurrentConfig = serde_json::from_value(json).unwrap();
8144 assert_eq!(deserialized.api_type, LlmProtocol::Anthropic);
8145 assert_eq!(deserialized.base_url, "https://api.anthropic.com");
8146 }
8147
8148 #[cfg(feature = "unstable_llm_providers")]
8149 #[test]
8150 fn test_provider_info_with_current_config() {
8151 let info = ProviderInfo::new(
8152 "main",
8153 vec![LlmProtocol::Anthropic, LlmProtocol::OpenAi],
8154 true,
8155 Some(ProviderCurrentConfig::new(
8156 LlmProtocol::Anthropic,
8157 "https://api.anthropic.com",
8158 )),
8159 );
8160
8161 let json = serde_json::to_value(&info).unwrap();
8162 assert_eq!(
8163 json,
8164 json!({
8165 "providerId": "main",
8166 "supported": ["anthropic", "openai"],
8167 "required": true,
8168 "current": {
8169 "apiType": "anthropic",
8170 "baseUrl": "https://api.anthropic.com"
8171 }
8172 })
8173 );
8174
8175 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
8176 assert_eq!(deserialized.provider_id.to_string(), "main");
8177 assert_eq!(deserialized.supported.len(), 2);
8178 assert!(deserialized.required);
8179 assert!(deserialized.current.is_some());
8180 assert_eq!(
8181 deserialized.current.as_ref().unwrap().api_type,
8182 LlmProtocol::Anthropic
8183 );
8184 }
8185
8186 #[cfg(feature = "unstable_llm_providers")]
8187 #[test]
8188 fn test_provider_info_disabled() {
8189 let info = ProviderInfo::new(
8190 "secondary",
8191 vec![LlmProtocol::OpenAi],
8192 false,
8193 None::<ProviderCurrentConfig>,
8194 );
8195
8196 let json = serde_json::to_value(&info).unwrap();
8197 assert_eq!(
8198 json,
8199 json!({
8200 "providerId": "secondary",
8201 "supported": ["openai"],
8202 "required": false
8203 })
8204 );
8205
8206 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
8207 assert_eq!(deserialized.provider_id.to_string(), "secondary");
8208 assert!(!deserialized.required);
8209 assert!(deserialized.current.is_none());
8210 }
8211
8212 #[cfg(feature = "unstable_llm_providers")]
8213 #[test]
8214 fn test_provider_info_missing_current_defaults_to_none() {
8215 let json = json!({
8217 "providerId": "main",
8218 "supported": ["anthropic"],
8219 "required": true
8220 });
8221 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
8222 assert!(deserialized.current.is_none());
8223 }
8224
8225 #[cfg(feature = "unstable_llm_providers")]
8226 #[test]
8227 fn test_provider_info_explicit_null_current_decodes_to_none() {
8228 let json = json!({
8232 "providerId": "main",
8233 "supported": ["anthropic"],
8234 "required": true,
8235 "current": null
8236 });
8237 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
8238 assert!(deserialized.current.is_none());
8239 }
8240
8241 #[cfg(feature = "unstable_llm_providers")]
8242 #[test]
8243 fn test_list_providers_response_serialization() {
8244 let response = ListProvidersResponse::new(vec![ProviderInfo::new(
8245 "main",
8246 vec![LlmProtocol::Anthropic],
8247 true,
8248 Some(ProviderCurrentConfig::new(
8249 LlmProtocol::Anthropic,
8250 "https://api.anthropic.com",
8251 )),
8252 )]);
8253
8254 let json = serde_json::to_value(&response).unwrap();
8255 assert_eq!(json["providers"].as_array().unwrap().len(), 1);
8256 assert_eq!(json["providers"][0]["providerId"], "main");
8257
8258 let deserialized: ListProvidersResponse = serde_json::from_value(json).unwrap();
8259 assert_eq!(deserialized.providers.len(), 1);
8260 }
8261
8262 #[cfg(feature = "unstable_llm_providers")]
8263 #[test]
8264 fn test_set_provider_request_serialization() {
8265 use std::collections::HashMap;
8266
8267 let mut headers = HashMap::new();
8268 headers.insert("Authorization".to_string(), "Bearer sk-test".to_string());
8269
8270 let request =
8271 SetProviderRequest::new("main", LlmProtocol::OpenAi, "https://api.openai.com/v1")
8272 .headers(headers);
8273
8274 let json = serde_json::to_value(&request).unwrap();
8275 assert_eq!(
8276 json,
8277 json!({
8278 "providerId": "main",
8279 "apiType": "openai",
8280 "baseUrl": "https://api.openai.com/v1",
8281 "headers": {
8282 "Authorization": "Bearer sk-test"
8283 }
8284 })
8285 );
8286
8287 let deserialized: SetProviderRequest = serde_json::from_value(json).unwrap();
8288 assert_eq!(deserialized.provider_id.to_string(), "main");
8289 assert_eq!(deserialized.api_type, LlmProtocol::OpenAi);
8290 assert_eq!(deserialized.base_url, "https://api.openai.com/v1");
8291 assert_eq!(deserialized.headers.len(), 1);
8292 assert_eq!(
8293 deserialized.headers.get("Authorization").unwrap(),
8294 "Bearer sk-test"
8295 );
8296 }
8297
8298 #[cfg(feature = "unstable_llm_providers")]
8299 #[test]
8300 fn test_set_provider_request_omits_empty_headers() {
8301 let request =
8302 SetProviderRequest::new("main", LlmProtocol::Anthropic, "https://api.anthropic.com");
8303
8304 let json = serde_json::to_value(&request).unwrap();
8305 assert!(!json.as_object().unwrap().contains_key("headers"));
8307 }
8308
8309 #[cfg(feature = "unstable_llm_providers")]
8310 #[test]
8311 fn test_disable_provider_request_serialization() {
8312 let request = DisableProviderRequest::new("secondary");
8313
8314 let json = serde_json::to_value(&request).unwrap();
8315 assert_eq!(json, json!({ "providerId": "secondary" }));
8316
8317 let deserialized: DisableProviderRequest = serde_json::from_value(json).unwrap();
8318 assert_eq!(deserialized.provider_id.to_string(), "secondary");
8319 }
8320
8321 #[cfg(feature = "unstable_llm_providers")]
8322 #[test]
8323 fn test_providers_capabilities_serialization() {
8324 let caps = ProvidersCapabilities::new();
8325
8326 let json = serde_json::to_value(&caps).unwrap();
8327 assert_eq!(json, json!({}));
8328
8329 let deserialized: ProvidersCapabilities = serde_json::from_value(json).unwrap();
8330 assert!(deserialized.meta.is_none());
8331 }
8332
8333 #[cfg(feature = "unstable_llm_providers")]
8334 #[test]
8335 fn test_agent_capabilities_with_providers() {
8336 let caps = AgentCapabilities::new().providers(ProvidersCapabilities::new());
8337
8338 let json = serde_json::to_value(&caps).unwrap();
8339 assert_eq!(json["providers"], json!({}));
8340
8341 let deserialized: AgentCapabilities = serde_json::from_value(json).unwrap();
8342 assert!(deserialized.providers.is_some());
8343 }
8344
8345 #[test]
8346 fn prompt_request_rejects_malformed_content_block() {
8347 use serde_json::json;
8348
8349 assert!(
8350 serde_json::from_value::<PromptRequest>(json!({
8351 "sessionId": "sess-1",
8352 "prompt": [{"type": "text"}]
8353 }))
8354 .is_err()
8355 );
8356 }
8357
8358 #[test]
8359 fn prompt_request_rejects_non_array_prompt() {
8360 use serde_json::json;
8361
8362 assert!(
8363 serde_json::from_value::<PromptRequest>(json!({
8364 "sessionId": "sess-1",
8365 "prompt": "hello"
8366 }))
8367 .is_err()
8368 );
8369 }
8370
8371 fn assert_session_setup_lists_are_strict<T>(base: &serde_json::Value)
8372 where
8373 T: serde::de::DeserializeOwned + PartialEq + std::fmt::Debug,
8374 {
8375 let name = std::any::type_name::<T>();
8376 let with = |field: &str, value: serde_json::Value| {
8377 let mut request = base.clone();
8378 request[field] = value;
8379 serde_json::from_value::<T>(request)
8380 };
8381
8382 for (field, value) in [
8383 (
8385 "mcpServers",
8386 json!([
8387 {"name": "github", "command": "/usr/bin/gh-mcp", "args": [], "env": [{"name": "GITHUB_TOKEN", "value": null}]},
8388 {"name": "fs", "command": "/usr/bin/fs-mcp", "args": [], "env": []}
8389 ]),
8390 ),
8391 ("mcpServers", json!({"name": "fs"})),
8392 ("additionalDirectories", json!(["/repo/lib", 42])),
8393 ("additionalDirectories", json!("/repo/lib")),
8394 ] {
8395 assert!(
8396 with(field, value.clone()).is_err(),
8397 "{name}.{field}: {value}"
8398 );
8399 }
8400
8401 let empty = serde_json::from_value::<T>(base.clone()).unwrap();
8402 for field in ["mcpServers", "additionalDirectories"] {
8403 assert_eq!(
8404 with(field, serde_json::Value::Null).unwrap(),
8405 empty,
8406 "{name}.{field}"
8407 );
8408 }
8409 }
8410
8411 #[test]
8412 fn session_setup_requests_reject_malformed_mcp_servers_and_directories() {
8413 assert_session_setup_lists_are_strict::<NewSessionRequest>(&json!({
8414 "cwd": "/repo",
8415 "mcpServers": []
8416 }));
8417 assert_session_setup_lists_are_strict::<LoadSessionRequest>(&json!({
8418 "sessionId": "sess-1",
8419 "cwd": "/repo",
8420 "mcpServers": []
8421 }));
8422 assert_session_setup_lists_are_strict::<ResumeSessionRequest>(&json!({
8423 "sessionId": "sess-1",
8424 "cwd": "/repo"
8425 }));
8426 #[cfg(feature = "unstable_session_fork")]
8427 assert_session_setup_lists_are_strict::<ForkSessionRequest>(&json!({
8428 "sessionId": "sess-1",
8429 "cwd": "/repo"
8430 }));
8431 }
8432
8433 #[test]
8434 fn mcp_server_lists_treat_null_as_empty() {
8435 let servers: Vec<McpServer> = serde_json::from_value(json!([
8436 {"name": "fs", "command": "/usr/bin/fs-mcp", "args": null, "env": null},
8437 {"type": "http", "name": "api", "url": "https://example.com/mcp", "headers": null},
8438 {"type": "sse", "name": "events", "url": "https://example.com/sse", "headers": null}
8439 ]))
8440 .unwrap();
8441
8442 assert_eq!(
8443 servers,
8444 vec![
8445 McpServer::Stdio(McpServerStdio::new("fs", "/usr/bin/fs-mcp")),
8446 McpServer::Http(McpServerHttp::new("api", "https://example.com/mcp")),
8447 McpServer::Sse(McpServerSse::new("events", "https://example.com/sse")),
8448 ]
8449 );
8450 }
8451
8452 #[test]
8453 fn terminal_auth_methods_reject_malformed_launch_config() {
8454 let response: InitializeResponse = serde_json::from_value(json!({
8458 "protocolVersion": 1,
8459 "authMethods": [
8460 {"type": "terminal", "id": "bad-args", "name": "Log in", "args": ["auth", "--port", 8123]},
8461 {"type": "terminal", "id": "bad-env", "name": "Log in", "env": {"AUTH_MODE": "device", "DEBUG": 1}},
8462 {"type": "terminal", "id": "null-config", "name": "Log in", "args": null, "env": null},
8463 {"id": "agent", "name": "Agent login"}
8464 ]
8465 }))
8466 .unwrap();
8467
8468 assert_eq!(
8469 response.auth_methods,
8470 vec![
8471 AuthMethod::Terminal(AuthMethodTerminal::new("null-config", "Log in")),
8472 AuthMethod::Agent(AuthMethodAgent::new("agent", "Agent login")),
8473 ]
8474 );
8475 assert!(
8476 serde_json::from_value::<AuthMethod>(json!({
8477 "type": "terminal",
8478 "id": "bad-args",
8479 "name": "Log in",
8480 "args": ["auth", 8123]
8481 }))
8482 .is_err()
8483 );
8484 }
8485
8486 #[cfg(feature = "unstable_auth_status")]
8487 #[test]
8488 fn auth_status_response_round_trips() {
8489 let response = AuthStatusResponse::new(AuthState::Authenticated).accounts(vec![
8490 AuthAccount::new("Anthropic API key").active(true),
8491 AuthAccount::new("Claude Max").email("user@example.com".to_string()),
8492 ]);
8493 let json = serde_json::to_value(&response).unwrap();
8494 assert_eq!(
8495 json,
8496 json!({
8497 "state": "authenticated",
8498 "accounts": [
8499 {
8500 "label": "Anthropic API key",
8501 "active": true
8502 },
8503 {
8504 "label": "Claude Max",
8505 "email": "user@example.com"
8506 }
8507 ]
8508 })
8509 );
8510 assert_eq!(
8511 serde_json::from_value::<AuthStatusResponse>(json).unwrap(),
8512 response
8513 );
8514 assert_eq!(
8515 serde_json::to_value(AuthStatusResponse::new(AuthState::NotRequired)).unwrap(),
8516 json!({"state": "not_required"})
8517 );
8518 }
8519
8520 #[cfg(feature = "unstable_auth_status")]
8521 #[test]
8522 fn auth_status_state_is_strict_and_accounts_are_lenient() {
8523 assert!(serde_json::from_value::<AuthStatusResponse>(json!({})).is_err());
8524 assert!(serde_json::from_value::<AuthStatusResponse>(json!({"state": null})).is_err());
8525 assert!(serde_json::from_value::<AuthStatusResponse>(json!({"state": 1})).is_err());
8526
8527 let response: AuthStatusResponse = serde_json::from_value(json!({
8528 "state": "_vendor_state",
8529 "accounts": [
8530 {"active": true},
8531 {
8532 "label": "Vertex AI",
8533 "active": "yes",
8534 "email": ["not", "a", "string"]
8535 }
8536 ]
8537 }))
8538 .unwrap();
8539 assert_eq!(
8540 response,
8541 AuthStatusResponse::new(AuthState::Other("_vendor_state".to_string()))
8542 .accounts(vec![AuthAccount::new("Vertex AI")])
8543 );
8544 assert_eq!(
8545 serde_json::from_value::<AuthStatusResponse>(
8546 json!({"state": "unknown", "accounts": null})
8547 )
8548 .unwrap(),
8549 AuthStatusResponse::new(AuthState::Unknown)
8550 );
8551 }
8552
8553 #[cfg(feature = "unstable_auth_status")]
8554 #[test]
8555 fn auth_status_update_notification_routes() {
8556 use crate::v1::{AgentNotification, CLIENT_METHOD_NAMES};
8557
8558 assert_eq!(AGENT_METHOD_NAMES.auth_status, "auth/status");
8559 assert_eq!(CLIENT_METHOD_NAMES.auth_status_update, "auth/status_update");
8560 let notification = AgentNotification::AuthStatusUpdateNotification(
8561 AuthStatusUpdateNotification::new(AuthState::Unauthenticated),
8562 );
8563 assert_eq!(notification.method(), "auth/status_update");
8564 assert_eq!(
8565 serde_json::to_value(¬ification).unwrap(),
8566 json!({"state": "unauthenticated"})
8567 );
8568 }
8569}