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")]
215 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
216 #[serde(default)]
217 pub title: Option<String>,
218 pub version: String,
221 #[serde_as(deserialize_as = "DefaultOnError")]
227 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
228 #[serde(default)]
229 #[serde(rename = "_meta")]
230 pub meta: Option<Meta>,
231}
232
233impl Implementation {
234 #[must_use]
236 pub fn new(name: impl Into<String>, version: impl Into<String>) -> Self {
237 Self {
238 name: name.into(),
239 title: None,
240 version: version.into(),
241 meta: None,
242 }
243 }
244
245 #[must_use]
250 pub fn title(mut self, title: impl IntoOption<String>) -> Self {
251 self.title = title.into_option();
252 self
253 }
254
255 #[must_use]
261 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
262 self.meta = meta.into_option();
263 self
264 }
265}
266
267#[serde_as]
273#[skip_serializing_none]
274#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
275#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
276#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = AUTHENTICATE_METHOD_NAME)))]
277#[serde(rename_all = "camelCase")]
278#[non_exhaustive]
279pub struct AuthenticateRequest {
280 pub method_id: AuthMethodId,
283 #[serde_as(deserialize_as = "DefaultOnError")]
289 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
290 #[serde(default)]
291 #[serde(rename = "_meta")]
292 pub meta: Option<Meta>,
293}
294
295impl AuthenticateRequest {
296 #[must_use]
298 pub fn new(method_id: impl Into<AuthMethodId>) -> Self {
299 Self {
300 method_id: method_id.into(),
301 meta: None,
302 }
303 }
304
305 #[must_use]
311 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
312 self.meta = meta.into_option();
313 self
314 }
315}
316
317crate::serde_util::default_on_null! {
318 #[serde_as]
320 #[skip_serializing_none]
321 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
322 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
323 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = AUTHENTICATE_METHOD_NAME)))]
324 #[serde(rename_all = "camelCase")]
325 #[non_exhaustive]
326 pub struct AuthenticateResponse {
327 #[serde_as(deserialize_as = "DefaultOnError")]
333 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
334 #[serde(default)]
335 #[serde(rename = "_meta")]
336 pub meta: Option<Meta>,
337 }
338}
339
340impl AuthenticateResponse {
341 #[must_use]
343 pub fn new() -> Self {
344 Self::default()
345 }
346
347 #[must_use]
353 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
354 self.meta = meta.into_option();
355 self
356 }
357}
358
359crate::serde_util::default_on_null! {
362 #[serde_as]
366 #[skip_serializing_none]
367 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
368 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
369 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = LOGOUT_METHOD_NAME)))]
370 #[serde(rename_all = "camelCase")]
371 #[non_exhaustive]
372 pub struct LogoutRequest {
373 #[serde_as(deserialize_as = "DefaultOnError")]
379 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
380 #[serde(default)]
381 #[serde(rename = "_meta")]
382 pub meta: Option<Meta>,
383 }
384}
385
386impl LogoutRequest {
387 #[must_use]
389 pub fn new() -> Self {
390 Self::default()
391 }
392
393 #[must_use]
399 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
400 self.meta = meta.into_option();
401 self
402 }
403}
404
405crate::serde_util::default_on_null! {
406 #[serde_as]
408 #[skip_serializing_none]
409 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
410 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
411 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = LOGOUT_METHOD_NAME)))]
412 #[serde(rename_all = "camelCase")]
413 #[non_exhaustive]
414 pub struct LogoutResponse {
415 #[serde_as(deserialize_as = "DefaultOnError")]
421 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
422 #[serde(default)]
423 #[serde(rename = "_meta")]
424 pub meta: Option<Meta>,
425 }
426}
427
428impl LogoutResponse {
429 #[must_use]
431 pub fn new() -> Self {
432 Self::default()
433 }
434
435 #[must_use]
441 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
442 self.meta = meta.into_option();
443 self
444 }
445}
446
447#[cfg(feature = "unstable_auth_status")]
450crate::serde_util::default_on_null! {
451 #[serde_as]
462 #[skip_serializing_none]
463 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
464 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
465 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = AUTH_STATUS_METHOD_NAME)))]
466 #[serde(rename_all = "camelCase")]
467 #[non_exhaustive]
468 pub struct AuthStatusRequest {
469 #[serde_as(deserialize_as = "DefaultOnError")]
475 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
476 #[serde(default)]
477 #[serde(rename = "_meta")]
478 pub meta: Option<Meta>,
479 }
480}
481
482#[cfg(feature = "unstable_auth_status")]
483impl AuthStatusRequest {
484 #[must_use]
486 pub fn new() -> Self {
487 Self::default()
488 }
489
490 #[must_use]
496 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
497 self.meta = meta.into_option();
498 self
499 }
500}
501
502#[cfg(feature = "unstable_auth_status")]
508#[serde_as]
509#[skip_serializing_none]
510#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
511#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
512#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = AUTH_STATUS_METHOD_NAME)))]
513#[serde(rename_all = "camelCase")]
514#[non_exhaustive]
515pub struct AuthStatusResponse {
516 pub state: AuthState,
521 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_>>")]
527 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
528 #[serde(default, skip_serializing_if = "Vec::is_empty")]
529 pub accounts: Vec<AuthAccount>,
530 #[serde_as(deserialize_as = "DefaultOnError")]
536 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
537 #[serde(default)]
538 #[serde(rename = "_meta")]
539 pub meta: Option<Meta>,
540}
541
542#[cfg(feature = "unstable_auth_status")]
543impl AuthStatusResponse {
544 #[must_use]
546 pub fn new(state: AuthState) -> Self {
547 Self {
548 state,
549 accounts: vec![],
550 meta: None,
551 }
552 }
553
554 #[must_use]
556 pub fn accounts(mut self, accounts: Vec<AuthAccount>) -> Self {
557 self.accounts = accounts;
558 self
559 }
560
561 #[must_use]
567 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
568 self.meta = meta.into_option();
569 self
570 }
571}
572
573#[cfg(feature = "unstable_auth_status")]
583#[serde_as]
584#[skip_serializing_none]
585#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
586#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
587#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "client", "x-method" = AUTH_STATUS_UPDATE_NOTIFICATION)))]
588#[serde(rename_all = "camelCase")]
589#[non_exhaustive]
590pub struct AuthStatusUpdateNotification {
591 pub state: AuthState,
596 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_>>")]
602 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
603 #[serde(default, skip_serializing_if = "Vec::is_empty")]
604 pub accounts: Vec<AuthAccount>,
605 #[serde_as(deserialize_as = "DefaultOnError")]
611 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
612 #[serde(default)]
613 #[serde(rename = "_meta")]
614 pub meta: Option<Meta>,
615}
616
617#[cfg(feature = "unstable_auth_status")]
618impl AuthStatusUpdateNotification {
619 #[must_use]
621 pub fn new(state: AuthState) -> Self {
622 Self {
623 state,
624 accounts: vec![],
625 meta: None,
626 }
627 }
628
629 #[must_use]
631 pub fn accounts(mut self, accounts: Vec<AuthAccount>) -> Self {
632 self.accounts = accounts;
633 self
634 }
635
636 #[must_use]
642 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
643 self.meta = meta.into_option();
644 self
645 }
646}
647
648#[cfg(feature = "unstable_auth_status")]
654#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
655#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
656#[serde(rename_all = "snake_case")]
657#[non_exhaustive]
658pub enum AuthState {
659 Authenticated,
661 Unauthenticated,
664 NotRequired,
666 Unknown,
668 #[serde(untagged)]
674 Other(String),
675}
676
677#[cfg(feature = "unstable_auth_status")]
688#[serde_as]
689#[skip_serializing_none]
690#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
691#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
692#[serde(rename_all = "camelCase")]
693#[non_exhaustive]
694pub struct AuthAccount {
695 pub label: String,
698 #[serde_as(deserialize_as = "DefaultOnError")]
704 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
705 #[serde(default)]
706 pub active: Option<bool>,
707 #[serde_as(deserialize_as = "DefaultOnError")]
711 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
712 #[serde(default)]
713 pub name: Option<String>,
714 #[serde_as(deserialize_as = "DefaultOnError")]
718 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
719 #[serde(default)]
720 pub email: Option<String>,
721 #[serde_as(deserialize_as = "DefaultOnError")]
725 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
726 #[serde(default)]
727 pub organization: Option<String>,
728 #[serde_as(deserialize_as = "DefaultOnError")]
734 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
735 #[serde(default)]
736 #[serde(rename = "_meta")]
737 pub meta: Option<Meta>,
738}
739
740#[cfg(feature = "unstable_auth_status")]
741impl AuthAccount {
742 #[must_use]
744 pub fn new(label: impl Into<String>) -> Self {
745 Self {
746 label: label.into(),
747 active: None,
748 name: None,
749 email: None,
750 organization: None,
751 meta: None,
752 }
753 }
754
755 #[must_use]
757 pub fn active(mut self, active: impl IntoOption<bool>) -> Self {
758 self.active = active.into_option();
759 self
760 }
761
762 #[must_use]
764 pub fn name(mut self, name: impl IntoOption<String>) -> Self {
765 self.name = name.into_option();
766 self
767 }
768
769 #[must_use]
771 pub fn email(mut self, email: impl IntoOption<String>) -> Self {
772 self.email = email.into_option();
773 self
774 }
775
776 #[must_use]
778 pub fn organization(mut self, organization: impl IntoOption<String>) -> Self {
779 self.organization = organization.into_option();
780 self
781 }
782
783 #[must_use]
789 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
790 self.meta = meta.into_option();
791 self
792 }
793}
794
795#[cfg(feature = "unstable_auth_status")]
803#[serde_as]
804#[skip_serializing_none]
805#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
806#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
807#[non_exhaustive]
808pub struct AuthStatusCapabilities {
809 #[serde_as(deserialize_as = "DefaultOnError")]
815 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
816 #[serde(default)]
817 #[serde(rename = "_meta")]
818 pub meta: Option<Meta>,
819}
820
821#[cfg(feature = "unstable_auth_status")]
822impl AuthStatusCapabilities {
823 #[must_use]
825 pub fn new() -> Self {
826 Self::default()
827 }
828
829 #[must_use]
835 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
836 self.meta = meta.into_option();
837 self
838 }
839}
840
841#[serde_as]
843#[skip_serializing_none]
844#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
845#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
846#[serde(rename_all = "camelCase")]
847#[non_exhaustive]
848pub struct AgentAuthCapabilities {
849 #[cfg(feature = "unstable_auth_status")]
858 #[serde_as(deserialize_as = "DefaultOnError")]
859 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
860 #[serde(default)]
861 pub status: Option<AuthStatusCapabilities>,
862 #[serde_as(deserialize_as = "DefaultOnError")]
867 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
868 #[serde(default)]
869 pub logout: Option<LogoutCapabilities>,
870 #[serde_as(deserialize_as = "DefaultOnError")]
876 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
877 #[serde(default)]
878 #[serde(rename = "_meta")]
879 pub meta: Option<Meta>,
880}
881
882impl AgentAuthCapabilities {
883 #[must_use]
885 pub fn new() -> Self {
886 Self::default()
887 }
888
889 #[cfg(feature = "unstable_auth_status")]
895 #[must_use]
896 pub fn status(mut self, status: impl IntoOption<AuthStatusCapabilities>) -> Self {
897 self.status = status.into_option();
898 self
899 }
900
901 #[must_use]
903 pub fn logout(mut self, logout: impl IntoOption<LogoutCapabilities>) -> Self {
904 self.logout = logout.into_option();
905 self
906 }
907
908 #[must_use]
914 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
915 self.meta = meta.into_option();
916 self
917 }
918}
919
920#[serde_as]
924#[skip_serializing_none]
925#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
926#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
927#[non_exhaustive]
928pub struct LogoutCapabilities {
929 #[serde_as(deserialize_as = "DefaultOnError")]
935 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
936 #[serde(default)]
937 #[serde(rename = "_meta")]
938 pub meta: Option<Meta>,
939}
940
941impl LogoutCapabilities {
942 #[must_use]
944 pub fn new() -> Self {
945 Self::default()
946 }
947
948 #[must_use]
954 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
955 self.meta = meta.into_option();
956 self
957 }
958}
959
960#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
962#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Display, From)]
963#[serde(transparent)]
964#[from(Arc<str>, String, &'static str)]
965#[non_exhaustive]
966pub struct AuthMethodId(pub Arc<str>);
967
968impl AuthMethodId {
969 #[must_use]
971 pub fn new(id: impl Into<Arc<str>>) -> Self {
972 Self(id.into())
973 }
974}
975
976#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
981#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
982#[serde(tag = "type", rename_all = "snake_case")]
983#[non_exhaustive]
984pub enum AuthMethod {
985 Terminal(AuthMethodTerminal),
988 #[serde(untagged, deserialize_with = "deserialize_agent_auth_method_fallback")]
992 Agent(AuthMethodAgent),
993}
994
995fn deserialize_agent_auth_method_fallback<'de, D>(
1000 deserializer: D,
1001) -> Result<AuthMethodAgent, D::Error>
1002where
1003 D: serde::Deserializer<'de>,
1004{
1005 let value = serde_json::Value::deserialize(deserializer)?;
1006 if value.get("type").and_then(serde_json::Value::as_str) == Some("terminal") {
1007 return Err(serde::de::Error::custom(
1008 "known authentication method `terminal` did not match its schema",
1009 ));
1010 }
1011 AuthMethodAgent::deserialize(value).map_err(serde::de::Error::custom)
1012}
1013
1014impl AuthMethod {
1015 #[must_use]
1017 pub fn id(&self) -> &AuthMethodId {
1018 match self {
1019 Self::Agent(a) => &a.id,
1020 Self::Terminal(t) => &t.id,
1021 }
1022 }
1023
1024 #[must_use]
1026 pub fn name(&self) -> &str {
1027 match self {
1028 Self::Agent(a) => &a.name,
1029 Self::Terminal(t) => &t.name,
1030 }
1031 }
1032
1033 #[must_use]
1035 pub fn description(&self) -> Option<&str> {
1036 match self {
1037 Self::Agent(a) => a.description.as_deref(),
1038 Self::Terminal(t) => t.description.as_deref(),
1039 }
1040 }
1041
1042 #[must_use]
1048 pub fn meta(&self) -> Option<&Meta> {
1049 match self {
1050 Self::Agent(a) => a.meta.as_ref(),
1051 Self::Terminal(t) => t.meta.as_ref(),
1052 }
1053 }
1054}
1055
1056#[serde_as]
1060#[skip_serializing_none]
1061#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1062#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1063#[serde(rename_all = "camelCase")]
1064#[non_exhaustive]
1065pub struct AuthMethodAgent {
1066 pub id: AuthMethodId,
1068 pub name: String,
1070 #[serde_as(deserialize_as = "DefaultOnError")]
1072 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1073 #[serde(default)]
1074 pub description: Option<String>,
1075 #[serde_as(deserialize_as = "DefaultOnError")]
1081 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1082 #[serde(default)]
1083 #[serde(rename = "_meta")]
1084 pub meta: Option<Meta>,
1085}
1086
1087impl AuthMethodAgent {
1088 #[must_use]
1090 pub fn new(id: impl Into<AuthMethodId>, name: impl Into<String>) -> Self {
1091 Self {
1092 id: id.into(),
1093 name: name.into(),
1094 description: None,
1095 meta: None,
1096 }
1097 }
1098
1099 #[must_use]
1101 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
1102 self.description = description.into_option();
1103 self
1104 }
1105
1106 #[must_use]
1112 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1113 self.meta = meta.into_option();
1114 self
1115 }
1116}
1117
1118#[serde_as]
1126#[skip_serializing_none]
1127#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1128#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1129#[serde(rename_all = "camelCase")]
1130#[non_exhaustive]
1131pub struct AuthMethodTerminal {
1132 pub id: AuthMethodId,
1134 pub name: String,
1136 #[serde_as(deserialize_as = "DefaultOnError")]
1138 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1139 #[serde(default)]
1140 pub description: Option<String>,
1141 #[serde_as(deserialize_as = "DefaultOnNull")]
1143 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-null" = true)))]
1144 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1145 pub args: Vec<String>,
1146 #[serde_as(deserialize_as = "DefaultOnNull")]
1149 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-null" = true)))]
1150 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
1151 pub env: HashMap<String, String>,
1152 #[serde_as(deserialize_as = "DefaultOnError")]
1158 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1159 #[serde(default)]
1160 #[serde(rename = "_meta")]
1161 pub meta: Option<Meta>,
1162}
1163
1164impl AuthMethodTerminal {
1165 #[must_use]
1167 pub fn new(id: impl Into<AuthMethodId>, name: impl Into<String>) -> Self {
1168 Self {
1169 id: id.into(),
1170 name: name.into(),
1171 description: None,
1172 args: Vec::new(),
1173 env: HashMap::new(),
1174 meta: None,
1175 }
1176 }
1177
1178 #[must_use]
1180 pub fn args(mut self, args: Vec<String>) -> Self {
1181 self.args = args;
1182 self
1183 }
1184
1185 #[must_use]
1188 pub fn env(mut self, env: HashMap<String, String>) -> Self {
1189 self.env = env;
1190 self
1191 }
1192
1193 #[must_use]
1195 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
1196 self.description = description.into_option();
1197 self
1198 }
1199
1200 #[must_use]
1206 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1207 self.meta = meta.into_option();
1208 self
1209 }
1210}
1211
1212#[serde_as]
1218#[skip_serializing_none]
1219#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1220#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1221#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_NEW_METHOD_NAME)))]
1222#[serde(rename_all = "camelCase")]
1223#[non_exhaustive]
1224pub struct NewSessionRequest {
1225 pub cwd: PathBuf,
1227 #[serde_as(deserialize_as = "DefaultOnNull")]
1233 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-null" = true)))]
1234 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1235 pub additional_directories: Vec<PathBuf>,
1236 #[serde_as(deserialize_as = "DefaultOnNull")]
1238 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-null" = true)))]
1239 pub mcp_servers: Vec<McpServer>,
1240 #[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 system_prompt: None,
1268 meta: None,
1269 }
1270 }
1271
1272 #[must_use]
1274 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1275 self.additional_directories = additional_directories;
1276 self
1277 }
1278
1279 #[must_use]
1281 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1282 self.mcp_servers = mcp_servers;
1283 self
1284 }
1285
1286 #[must_use]
1288 pub fn system_prompt(mut self, system_prompt: impl IntoOption<SystemPrompt>) -> Self {
1289 self.system_prompt = system_prompt.into_option();
1290 self
1291 }
1292
1293 #[must_use]
1299 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1300 self.meta = meta.into_option();
1301 self
1302 }
1303}
1304
1305#[serde_as]
1309#[skip_serializing_none]
1310#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1311#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1312#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_NEW_METHOD_NAME)))]
1313#[serde(rename_all = "camelCase")]
1314#[non_exhaustive]
1315pub struct NewSessionResponse {
1316 pub session_id: SessionId,
1320 #[serde_as(deserialize_as = "DefaultOnError")]
1324 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1325 #[serde(default)]
1326 pub modes: Option<SessionModeState>,
1327 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_>>>")]
1329 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1330 #[serde(default)]
1331 pub config_options: Option<Vec<SessionConfigOption>>,
1332 #[serde_as(deserialize_as = "DefaultOnError")]
1338 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1339 #[serde(default)]
1340 #[serde(rename = "_meta")]
1341 pub meta: Option<Meta>,
1342}
1343
1344impl NewSessionResponse {
1345 #[must_use]
1347 pub fn new(session_id: impl Into<SessionId>) -> Self {
1348 Self {
1349 session_id: session_id.into(),
1350 modes: None,
1351 config_options: None,
1352 meta: None,
1353 }
1354 }
1355
1356 #[must_use]
1360 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1361 self.modes = modes.into_option();
1362 self
1363 }
1364
1365 #[must_use]
1367 pub fn config_options(
1368 mut self,
1369 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1370 ) -> Self {
1371 self.config_options = config_options.into_option();
1372 self
1373 }
1374
1375 #[must_use]
1381 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1382 self.meta = meta.into_option();
1383 self
1384 }
1385}
1386
1387#[serde_as]
1395#[skip_serializing_none]
1396#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1397#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1398#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_LOAD_METHOD_NAME)))]
1399#[serde(rename_all = "camelCase")]
1400#[non_exhaustive]
1401pub struct LoadSessionRequest {
1402 #[serde_as(deserialize_as = "DefaultOnNull")]
1404 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-null" = true)))]
1405 pub mcp_servers: Vec<McpServer>,
1406 pub cwd: PathBuf,
1408 #[serde_as(deserialize_as = "DefaultOnNull")]
1415 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-null" = true)))]
1416 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1417 pub additional_directories: Vec<PathBuf>,
1418 pub session_id: SessionId,
1420 #[serde(default)]
1428 pub system_prompt: Option<SystemPrompt>,
1429 #[serde_as(deserialize_as = "DefaultOnError")]
1435 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1436 #[serde(default)]
1437 #[serde(rename = "_meta")]
1438 pub meta: Option<Meta>,
1439}
1440
1441impl LoadSessionRequest {
1442 #[must_use]
1444 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1445 Self {
1446 mcp_servers: vec![],
1447 cwd: cwd.into(),
1448 additional_directories: vec![],
1449 session_id: session_id.into(),
1450 system_prompt: None,
1451 meta: None,
1452 }
1453 }
1454
1455 #[must_use]
1457 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1458 self.additional_directories = additional_directories;
1459 self
1460 }
1461
1462 #[must_use]
1464 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1465 self.mcp_servers = mcp_servers;
1466 self
1467 }
1468
1469 #[must_use]
1471 pub fn system_prompt(mut self, system_prompt: impl IntoOption<SystemPrompt>) -> Self {
1472 self.system_prompt = system_prompt.into_option();
1473 self
1474 }
1475
1476 #[must_use]
1482 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1483 self.meta = meta.into_option();
1484 self
1485 }
1486}
1487
1488crate::serde_util::default_on_null! {
1489 #[serde_as]
1491 #[skip_serializing_none]
1492 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1493 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
1494 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_LOAD_METHOD_NAME)))]
1495 #[serde(rename_all = "camelCase")]
1496 #[non_exhaustive]
1497 pub struct LoadSessionResponse {
1498 #[serde_as(deserialize_as = "DefaultOnError")]
1502 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1503 #[serde(default)]
1504 pub modes: Option<SessionModeState>,
1505 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_>>>")]
1507 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1508 #[serde(default)]
1509 pub config_options: Option<Vec<SessionConfigOption>>,
1510 #[serde_as(deserialize_as = "DefaultOnError")]
1516 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1517 #[serde(default)]
1518 #[serde(rename = "_meta")]
1519 pub meta: Option<Meta>,
1520 }
1521}
1522
1523impl LoadSessionResponse {
1524 #[must_use]
1526 pub fn new() -> Self {
1527 Self::default()
1528 }
1529
1530 #[must_use]
1534 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1535 self.modes = modes.into_option();
1536 self
1537 }
1538
1539 #[must_use]
1541 pub fn config_options(
1542 mut self,
1543 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1544 ) -> Self {
1545 self.config_options = config_options.into_option();
1546 self
1547 }
1548
1549 #[must_use]
1555 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1556 self.meta = meta.into_option();
1557 self
1558 }
1559}
1560
1561#[cfg(feature = "unstable_session_fork")]
1574#[serde_as]
1575#[skip_serializing_none]
1576#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1577#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1578#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_FORK_METHOD_NAME)))]
1579#[serde(rename_all = "camelCase")]
1580#[non_exhaustive]
1581pub struct ForkSessionRequest {
1582 pub session_id: SessionId,
1584 pub cwd: PathBuf,
1586 #[serde_as(deserialize_as = "DefaultOnNull")]
1592 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-null" = true)))]
1593 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1594 pub additional_directories: Vec<PathBuf>,
1595 #[serde_as(deserialize_as = "DefaultOnNull")]
1597 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-null" = true)))]
1598 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1599 pub mcp_servers: Vec<McpServer>,
1600 #[serde(default)]
1608 pub system_prompt: Option<SystemPrompt>,
1609 #[serde_as(deserialize_as = "DefaultOnError")]
1615 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1616 #[serde(default)]
1617 #[serde(rename = "_meta")]
1618 pub meta: Option<Meta>,
1619}
1620
1621#[cfg(feature = "unstable_session_fork")]
1622impl ForkSessionRequest {
1623 #[must_use]
1625 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1626 Self {
1627 session_id: session_id.into(),
1628 cwd: cwd.into(),
1629 additional_directories: vec![],
1630 mcp_servers: vec![],
1631 system_prompt: None,
1632 meta: None,
1633 }
1634 }
1635
1636 #[must_use]
1638 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1639 self.additional_directories = additional_directories;
1640 self
1641 }
1642
1643 #[must_use]
1645 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1646 self.mcp_servers = mcp_servers;
1647 self
1648 }
1649
1650 #[must_use]
1652 pub fn system_prompt(mut self, system_prompt: impl IntoOption<SystemPrompt>) -> Self {
1653 self.system_prompt = system_prompt.into_option();
1654 self
1655 }
1656
1657 #[must_use]
1663 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1664 self.meta = meta.into_option();
1665 self
1666 }
1667}
1668
1669#[cfg(feature = "unstable_session_fork")]
1675#[serde_as]
1676#[skip_serializing_none]
1677#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1678#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1679#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_FORK_METHOD_NAME)))]
1680#[serde(rename_all = "camelCase")]
1681#[non_exhaustive]
1682pub struct ForkSessionResponse {
1683 pub session_id: SessionId,
1685 #[serde_as(deserialize_as = "DefaultOnError")]
1689 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1690 #[serde(default)]
1691 pub modes: Option<SessionModeState>,
1692 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_>>>")]
1694 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1695 #[serde(default)]
1696 pub config_options: Option<Vec<SessionConfigOption>>,
1697 #[serde_as(deserialize_as = "DefaultOnError")]
1703 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1704 #[serde(default)]
1705 #[serde(rename = "_meta")]
1706 pub meta: Option<Meta>,
1707}
1708
1709#[cfg(feature = "unstable_session_fork")]
1710impl ForkSessionResponse {
1711 #[must_use]
1713 pub fn new(session_id: impl Into<SessionId>) -> Self {
1714 Self {
1715 session_id: session_id.into(),
1716 modes: None,
1717 config_options: None,
1718 meta: None,
1719 }
1720 }
1721
1722 #[must_use]
1726 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1727 self.modes = modes.into_option();
1728 self
1729 }
1730
1731 #[must_use]
1733 pub fn config_options(
1734 mut self,
1735 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1736 ) -> Self {
1737 self.config_options = config_options.into_option();
1738 self
1739 }
1740
1741 #[must_use]
1747 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1748 self.meta = meta.into_option();
1749 self
1750 }
1751}
1752
1753#[serde_as]
1762#[skip_serializing_none]
1763#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1764#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1765#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_RESUME_METHOD_NAME)))]
1766#[serde(rename_all = "camelCase")]
1767#[non_exhaustive]
1768pub struct ResumeSessionRequest {
1769 pub session_id: SessionId,
1771 pub cwd: PathBuf,
1773 #[serde_as(deserialize_as = "DefaultOnNull")]
1780 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-null" = true)))]
1781 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1782 pub additional_directories: Vec<PathBuf>,
1783 #[serde_as(deserialize_as = "DefaultOnNull")]
1785 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-null" = true)))]
1786 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1787 pub mcp_servers: Vec<McpServer>,
1788 #[serde(default)]
1796 pub system_prompt: Option<SystemPrompt>,
1797 #[serde_as(deserialize_as = "DefaultOnError")]
1803 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1804 #[serde(default)]
1805 #[serde(rename = "_meta")]
1806 pub meta: Option<Meta>,
1807}
1808
1809impl ResumeSessionRequest {
1810 #[must_use]
1812 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1813 Self {
1814 session_id: session_id.into(),
1815 cwd: cwd.into(),
1816 additional_directories: vec![],
1817 mcp_servers: vec![],
1818 system_prompt: None,
1819 meta: None,
1820 }
1821 }
1822
1823 #[must_use]
1825 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1826 self.additional_directories = additional_directories;
1827 self
1828 }
1829
1830 #[must_use]
1832 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1833 self.mcp_servers = mcp_servers;
1834 self
1835 }
1836
1837 #[must_use]
1839 pub fn system_prompt(mut self, system_prompt: impl IntoOption<SystemPrompt>) -> Self {
1840 self.system_prompt = system_prompt.into_option();
1841 self
1842 }
1843
1844 #[must_use]
1850 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1851 self.meta = meta.into_option();
1852 self
1853 }
1854}
1855
1856crate::serde_util::default_on_null! {
1857 #[serde_as]
1859 #[skip_serializing_none]
1860 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1861 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
1862 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_RESUME_METHOD_NAME)))]
1863 #[serde(rename_all = "camelCase")]
1864 #[non_exhaustive]
1865 pub struct ResumeSessionResponse {
1866 #[serde_as(deserialize_as = "DefaultOnError")]
1870 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1871 #[serde(default)]
1872 pub modes: Option<SessionModeState>,
1873 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_>>>")]
1875 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1876 #[serde(default)]
1877 pub config_options: Option<Vec<SessionConfigOption>>,
1878 #[serde_as(deserialize_as = "DefaultOnError")]
1884 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1885 #[serde(default)]
1886 #[serde(rename = "_meta")]
1887 pub meta: Option<Meta>,
1888 }
1889}
1890
1891impl ResumeSessionResponse {
1892 #[must_use]
1894 pub fn new() -> Self {
1895 Self::default()
1896 }
1897
1898 #[must_use]
1902 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1903 self.modes = modes.into_option();
1904 self
1905 }
1906
1907 #[must_use]
1909 pub fn config_options(
1910 mut self,
1911 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1912 ) -> Self {
1913 self.config_options = config_options.into_option();
1914 self
1915 }
1916
1917 #[must_use]
1923 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1924 self.meta = meta.into_option();
1925 self
1926 }
1927}
1928
1929#[serde_as]
1939#[skip_serializing_none]
1940#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1941#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1942#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_CLOSE_METHOD_NAME)))]
1943#[serde(rename_all = "camelCase")]
1944#[non_exhaustive]
1945pub struct CloseSessionRequest {
1946 pub session_id: SessionId,
1948 #[serde_as(deserialize_as = "DefaultOnError")]
1954 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1955 #[serde(default)]
1956 #[serde(rename = "_meta")]
1957 pub meta: Option<Meta>,
1958}
1959
1960impl CloseSessionRequest {
1961 #[must_use]
1963 pub fn new(session_id: impl Into<SessionId>) -> Self {
1964 Self {
1965 session_id: session_id.into(),
1966 meta: None,
1967 }
1968 }
1969
1970 #[must_use]
1976 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1977 self.meta = meta.into_option();
1978 self
1979 }
1980}
1981
1982crate::serde_util::default_on_null! {
1983 #[serde_as]
1985 #[skip_serializing_none]
1986 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1987 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
1988 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_CLOSE_METHOD_NAME)))]
1989 #[serde(rename_all = "camelCase")]
1990 #[non_exhaustive]
1991 pub struct CloseSessionResponse {
1992 #[serde_as(deserialize_as = "DefaultOnError")]
1998 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1999 #[serde(default)]
2000 #[serde(rename = "_meta")]
2001 pub meta: Option<Meta>,
2002 }
2003}
2004
2005impl CloseSessionResponse {
2006 #[must_use]
2008 pub fn new() -> Self {
2009 Self::default()
2010 }
2011
2012 #[must_use]
2018 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2019 self.meta = meta.into_option();
2020 self
2021 }
2022}
2023
2024#[cfg(feature = "unstable_session_status")]
2038#[serde_as]
2039#[skip_serializing_none]
2040#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2041#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2042#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_STATUS_METHOD_NAME)))]
2043#[serde(rename_all = "camelCase")]
2044#[non_exhaustive]
2045pub struct SessionStatusRequest {
2046 pub session_id: SessionId,
2048 #[serde_as(deserialize_as = "DefaultOnError")]
2054 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2055 #[serde(default)]
2056 #[serde(rename = "_meta")]
2057 pub meta: Option<Meta>,
2058}
2059
2060#[cfg(feature = "unstable_session_status")]
2061impl SessionStatusRequest {
2062 #[must_use]
2064 pub fn new(session_id: impl Into<SessionId>) -> Self {
2065 Self {
2066 session_id: session_id.into(),
2067 meta: None,
2068 }
2069 }
2070
2071 #[must_use]
2077 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2078 self.meta = meta.into_option();
2079 self
2080 }
2081}
2082
2083#[cfg(feature = "unstable_session_status")]
2092#[serde_as]
2093#[skip_serializing_none]
2094#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2095#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2096#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_STATUS_METHOD_NAME)))]
2097#[serde(rename_all = "camelCase")]
2098#[non_exhaustive]
2099pub struct SessionStatusResponse {
2100 pub status: SessionStatus,
2104 #[serde_as(deserialize_as = "DefaultOnError")]
2110 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2111 #[serde(default)]
2112 #[serde(rename = "_meta")]
2113 pub meta: Option<Meta>,
2114}
2115
2116#[cfg(feature = "unstable_session_status")]
2117impl SessionStatusResponse {
2118 #[must_use]
2120 pub fn new(status: SessionStatus) -> Self {
2121 Self { status, meta: None }
2122 }
2123
2124 #[must_use]
2130 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2131 self.meta = meta.into_option();
2132 self
2133 }
2134}
2135
2136#[cfg(feature = "unstable_session_status")]
2142#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2143#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
2144#[serde(rename_all = "snake_case")]
2145#[non_exhaustive]
2146pub enum SessionStatus {
2147 Open,
2154 Saved,
2158 #[serde(untagged)]
2165 Other(String),
2166}
2167
2168crate::serde_util::default_on_null! {
2171 #[serde_as]
2175 #[skip_serializing_none]
2176 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2177 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
2178 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_LIST_METHOD_NAME)))]
2179 #[serde(rename_all = "camelCase")]
2180 #[non_exhaustive]
2181 pub struct ListSessionsRequest {
2182 #[serde(default)]
2184 pub cwd: Option<PathBuf>,
2185 #[serde(default)]
2187 pub cursor: Option<String>,
2188 #[cfg(feature = "unstable_session_archive")]
2198 #[serde(default)]
2199 pub archived: Option<SessionArchiveFilter>,
2200 #[serde_as(deserialize_as = "DefaultOnError")]
2206 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2207 #[serde(default)]
2208 #[serde(rename = "_meta")]
2209 pub meta: Option<Meta>,
2210 }
2211}
2212
2213impl ListSessionsRequest {
2214 #[must_use]
2216 pub fn new() -> Self {
2217 Self::default()
2218 }
2219
2220 #[must_use]
2222 pub fn cwd(mut self, cwd: impl IntoOption<PathBuf>) -> Self {
2223 self.cwd = cwd.into_option();
2224 self
2225 }
2226
2227 #[must_use]
2229 pub fn cursor(mut self, cursor: impl IntoOption<String>) -> Self {
2230 self.cursor = cursor.into_option();
2231 self
2232 }
2233
2234 #[cfg(feature = "unstable_session_archive")]
2240 #[must_use]
2241 pub fn archived(mut self, archived: impl IntoOption<SessionArchiveFilter>) -> Self {
2242 self.archived = archived.into_option();
2243 self
2244 }
2245
2246 #[must_use]
2252 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2253 self.meta = meta.into_option();
2254 self
2255 }
2256}
2257
2258#[serde_as]
2260#[skip_serializing_none]
2261#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2262#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2263#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_LIST_METHOD_NAME)))]
2264#[serde(rename_all = "camelCase")]
2265#[non_exhaustive]
2266pub struct ListSessionsResponse {
2267 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_>>")]
2269 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
2270 pub sessions: Vec<SessionInfo>,
2271 #[serde_as(deserialize_as = "DefaultOnError")]
2274 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2275 #[serde(default)]
2276 pub next_cursor: Option<String>,
2277 #[serde_as(deserialize_as = "DefaultOnError")]
2283 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2284 #[serde(default)]
2285 #[serde(rename = "_meta")]
2286 pub meta: Option<Meta>,
2287}
2288
2289impl ListSessionsResponse {
2290 #[must_use]
2292 pub fn new(sessions: Vec<SessionInfo>) -> Self {
2293 Self {
2294 sessions,
2295 next_cursor: None,
2296 meta: None,
2297 }
2298 }
2299
2300 #[must_use]
2302 pub fn next_cursor(mut self, next_cursor: impl IntoOption<String>) -> Self {
2303 self.next_cursor = next_cursor.into_option();
2304 self
2305 }
2306
2307 #[must_use]
2313 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2314 self.meta = meta.into_option();
2315 self
2316 }
2317}
2318
2319#[serde_as]
2325#[skip_serializing_none]
2326#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2327#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2328#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_DELETE_METHOD_NAME)))]
2329#[serde(rename_all = "camelCase")]
2330#[non_exhaustive]
2331pub struct DeleteSessionRequest {
2332 pub session_id: SessionId,
2334 #[serde_as(deserialize_as = "DefaultOnError")]
2340 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2341 #[serde(default)]
2342 #[serde(rename = "_meta")]
2343 pub meta: Option<Meta>,
2344}
2345
2346impl DeleteSessionRequest {
2347 #[must_use]
2349 pub fn new(session_id: impl Into<SessionId>) -> Self {
2350 Self {
2351 session_id: session_id.into(),
2352 meta: None,
2353 }
2354 }
2355
2356 #[must_use]
2362 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2363 self.meta = meta.into_option();
2364 self
2365 }
2366}
2367
2368crate::serde_util::default_on_null! {
2369 #[serde_as]
2371 #[skip_serializing_none]
2372 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2373 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
2374 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_DELETE_METHOD_NAME)))]
2375 #[serde(rename_all = "camelCase")]
2376 #[non_exhaustive]
2377 pub struct DeleteSessionResponse {
2378 #[serde_as(deserialize_as = "DefaultOnError")]
2384 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2385 #[serde(default)]
2386 #[serde(rename = "_meta")]
2387 pub meta: Option<Meta>,
2388 }
2389}
2390
2391impl DeleteSessionResponse {
2392 #[must_use]
2394 pub fn new() -> Self {
2395 Self::default()
2396 }
2397
2398 #[must_use]
2404 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2405 self.meta = meta.into_option();
2406 self
2407 }
2408}
2409
2410#[cfg(feature = "unstable_session_archive")]
2426#[serde_as]
2427#[skip_serializing_none]
2428#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2429#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2430#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_ARCHIVE_METHOD_NAME)))]
2431#[serde(rename_all = "camelCase")]
2432#[non_exhaustive]
2433pub struct ArchiveSessionRequest {
2434 pub session_id: SessionId,
2436 #[serde_as(deserialize_as = "DefaultOnError")]
2442 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2443 #[serde(default)]
2444 #[serde(rename = "_meta")]
2445 pub meta: Option<Meta>,
2446}
2447
2448#[cfg(feature = "unstable_session_archive")]
2449impl ArchiveSessionRequest {
2450 #[must_use]
2452 pub fn new(session_id: impl Into<SessionId>) -> Self {
2453 Self {
2454 session_id: session_id.into(),
2455 meta: None,
2456 }
2457 }
2458
2459 #[must_use]
2465 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2466 self.meta = meta.into_option();
2467 self
2468 }
2469}
2470
2471#[cfg(feature = "unstable_session_archive")]
2472crate::serde_util::default_on_null! {
2473 #[serde_as]
2479 #[skip_serializing_none]
2480 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2481 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
2482 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_ARCHIVE_METHOD_NAME)))]
2483 #[serde(rename_all = "camelCase")]
2484 #[non_exhaustive]
2485 pub struct ArchiveSessionResponse {
2486 #[serde_as(deserialize_as = "DefaultOnError")]
2492 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2493 #[serde(default)]
2494 #[serde(rename = "_meta")]
2495 pub meta: Option<Meta>,
2496 }
2497}
2498
2499#[cfg(feature = "unstable_session_archive")]
2500impl ArchiveSessionResponse {
2501 #[must_use]
2503 pub fn new() -> Self {
2504 Self::default()
2505 }
2506
2507 #[must_use]
2513 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2514 self.meta = meta.into_option();
2515 self
2516 }
2517}
2518
2519#[cfg(feature = "unstable_session_archive")]
2534#[serde_as]
2535#[skip_serializing_none]
2536#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2537#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2538#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_UNARCHIVE_METHOD_NAME)))]
2539#[serde(rename_all = "camelCase")]
2540#[non_exhaustive]
2541pub struct UnarchiveSessionRequest {
2542 pub session_id: SessionId,
2544 #[serde_as(deserialize_as = "DefaultOnError")]
2550 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2551 #[serde(default)]
2552 #[serde(rename = "_meta")]
2553 pub meta: Option<Meta>,
2554}
2555
2556#[cfg(feature = "unstable_session_archive")]
2557impl UnarchiveSessionRequest {
2558 #[must_use]
2560 pub fn new(session_id: impl Into<SessionId>) -> Self {
2561 Self {
2562 session_id: session_id.into(),
2563 meta: None,
2564 }
2565 }
2566
2567 #[must_use]
2573 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2574 self.meta = meta.into_option();
2575 self
2576 }
2577}
2578
2579#[cfg(feature = "unstable_session_archive")]
2580crate::serde_util::default_on_null! {
2581 #[serde_as]
2587 #[skip_serializing_none]
2588 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2589 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
2590 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_UNARCHIVE_METHOD_NAME)))]
2591 #[serde(rename_all = "camelCase")]
2592 #[non_exhaustive]
2593 pub struct UnarchiveSessionResponse {
2594 #[serde_as(deserialize_as = "DefaultOnError")]
2600 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2601 #[serde(default)]
2602 #[serde(rename = "_meta")]
2603 pub meta: Option<Meta>,
2604 }
2605}
2606
2607#[cfg(feature = "unstable_session_archive")]
2608impl UnarchiveSessionResponse {
2609 #[must_use]
2611 pub fn new() -> Self {
2612 Self::default()
2613 }
2614
2615 #[must_use]
2621 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2622 self.meta = meta.into_option();
2623 self
2624 }
2625}
2626
2627#[cfg(feature = "unstable_session_archive")]
2636#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2637#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
2638#[serde(rename_all = "snake_case")]
2639#[non_exhaustive]
2640pub enum SessionArchiveFilter {
2641 #[default]
2643 Exclude,
2644 Include,
2646 Only,
2648 #[serde(untagged)]
2654 Other(String),
2655}
2656
2657#[serde_as]
2659#[skip_serializing_none]
2660#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2661#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2662#[serde(rename_all = "camelCase")]
2663#[non_exhaustive]
2664pub struct SessionInfo {
2665 pub session_id: SessionId,
2667 pub cwd: PathBuf,
2669 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_>>")]
2675 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
2676 #[serde(default, skip_serializing_if = "Vec::is_empty")]
2677 pub additional_directories: Vec<PathBuf>,
2678
2679 #[serde_as(deserialize_as = "DefaultOnError")]
2681 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2682 #[serde(default)]
2683 pub title: Option<String>,
2684 #[serde_as(deserialize_as = "DefaultOnError")]
2686 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2687 #[serde(default)]
2688 pub updated_at: Option<String>,
2689 #[cfg(feature = "unstable_session_archive")]
2698 #[serde_as(deserialize_as = "DefaultOnError")]
2699 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2700 #[serde(default)]
2701 pub archived: Option<bool>,
2702 #[serde_as(deserialize_as = "DefaultOnError")]
2708 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2709 #[serde(default)]
2710 #[serde(rename = "_meta")]
2711 pub meta: Option<Meta>,
2712}
2713
2714impl SessionInfo {
2715 #[must_use]
2717 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
2718 Self {
2719 session_id: session_id.into(),
2720 cwd: cwd.into(),
2721 additional_directories: vec![],
2722 title: None,
2723 updated_at: None,
2724 #[cfg(feature = "unstable_session_archive")]
2725 archived: None,
2726 meta: None,
2727 }
2728 }
2729
2730 #[must_use]
2732 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
2733 self.additional_directories = additional_directories;
2734 self
2735 }
2736
2737 #[must_use]
2739 pub fn title(mut self, title: impl IntoOption<String>) -> Self {
2740 self.title = title.into_option();
2741 self
2742 }
2743
2744 #[must_use]
2746 pub fn updated_at(mut self, updated_at: impl IntoOption<String>) -> Self {
2747 self.updated_at = updated_at.into_option();
2748 self
2749 }
2750
2751 #[cfg(feature = "unstable_session_archive")]
2757 #[must_use]
2758 pub fn archived(mut self, archived: impl IntoOption<bool>) -> Self {
2759 self.archived = archived.into_option();
2760 self
2761 }
2762
2763 #[must_use]
2769 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2770 self.meta = meta.into_option();
2771 self
2772 }
2773}
2774
2775#[cfg(feature = "unstable_session_set_title")]
2791#[serde_as]
2792#[skip_serializing_none]
2793#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2794#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2795#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_TITLE_METHOD_NAME)))]
2796#[serde(rename_all = "camelCase")]
2797#[non_exhaustive]
2798pub struct SetSessionTitleRequest {
2799 pub session_id: SessionId,
2801 pub title: String,
2808 #[serde_as(deserialize_as = "DefaultOnError")]
2814 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2815 #[serde(default)]
2816 #[serde(rename = "_meta")]
2817 pub meta: Option<Meta>,
2818}
2819
2820#[cfg(feature = "unstable_session_set_title")]
2821impl SetSessionTitleRequest {
2822 #[must_use]
2824 pub fn new(session_id: impl Into<SessionId>, title: impl Into<String>) -> Self {
2825 Self {
2826 session_id: session_id.into(),
2827 title: title.into(),
2828 meta: None,
2829 }
2830 }
2831
2832 #[must_use]
2838 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2839 self.meta = meta.into_option();
2840 self
2841 }
2842}
2843
2844#[cfg(feature = "unstable_session_set_title")]
2850#[serde_as]
2851#[skip_serializing_none]
2852#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2853#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2854#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_TITLE_METHOD_NAME)))]
2855#[serde(rename_all = "camelCase")]
2856#[non_exhaustive]
2857pub struct SetSessionTitleResponse {
2858 pub title: String,
2863 #[serde_as(deserialize_as = "DefaultOnError")]
2869 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2870 #[serde(default)]
2871 #[serde(rename = "_meta")]
2872 pub meta: Option<Meta>,
2873}
2874
2875#[cfg(feature = "unstable_session_set_title")]
2876impl SetSessionTitleResponse {
2877 #[must_use]
2879 pub fn new(title: impl Into<String>) -> Self {
2880 Self {
2881 title: title.into(),
2882 meta: None,
2883 }
2884 }
2885
2886 #[must_use]
2892 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2893 self.meta = meta.into_option();
2894 self
2895 }
2896}
2897
2898#[serde_as]
2902#[skip_serializing_none]
2903#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2904#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2905#[serde(rename_all = "camelCase")]
2906#[non_exhaustive]
2907pub struct SessionModeState {
2908 pub current_mode_id: SessionModeId,
2910 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_>>")]
2912 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
2913 pub available_modes: Vec<SessionMode>,
2914 #[serde_as(deserialize_as = "DefaultOnError")]
2920 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2921 #[serde(default)]
2922 #[serde(rename = "_meta")]
2923 pub meta: Option<Meta>,
2924}
2925
2926impl SessionModeState {
2927 #[must_use]
2929 pub fn new(
2930 current_mode_id: impl Into<SessionModeId>,
2931 available_modes: Vec<SessionMode>,
2932 ) -> Self {
2933 Self {
2934 current_mode_id: current_mode_id.into(),
2935 available_modes,
2936 meta: None,
2937 }
2938 }
2939
2940 #[must_use]
2946 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2947 self.meta = meta.into_option();
2948 self
2949 }
2950}
2951
2952#[serde_as]
2956#[skip_serializing_none]
2957#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2958#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2959#[serde(rename_all = "camelCase")]
2960#[non_exhaustive]
2961pub struct SessionMode {
2962 pub id: SessionModeId,
2964 pub name: String,
2966 #[serde_as(deserialize_as = "DefaultOnError")]
2968 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2969 #[serde(default)]
2970 pub description: Option<String>,
2971 #[serde_as(deserialize_as = "DefaultOnError")]
2977 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2978 #[serde(default)]
2979 #[serde(rename = "_meta")]
2980 pub meta: Option<Meta>,
2981}
2982
2983impl SessionMode {
2984 #[must_use]
2986 pub fn new(id: impl Into<SessionModeId>, name: impl Into<String>) -> Self {
2987 Self {
2988 id: id.into(),
2989 name: name.into(),
2990 description: None,
2991 meta: None,
2992 }
2993 }
2994
2995 #[must_use]
2997 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
2998 self.description = description.into_option();
2999 self
3000 }
3001
3002 #[must_use]
3008 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3009 self.meta = meta.into_option();
3010 self
3011 }
3012}
3013
3014#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3016#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, From, Display)]
3017#[serde(transparent)]
3018#[from(Arc<str>, String, &'static str)]
3019#[non_exhaustive]
3020pub struct SessionModeId(pub Arc<str>);
3021
3022impl SessionModeId {
3023 #[must_use]
3025 pub fn new(id: impl Into<Arc<str>>) -> Self {
3026 Self(id.into())
3027 }
3028}
3029
3030#[serde_as]
3032#[skip_serializing_none]
3033#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3034#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3035#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODE_METHOD_NAME)))]
3036#[serde(rename_all = "camelCase")]
3037#[non_exhaustive]
3038pub struct SetSessionModeRequest {
3039 pub session_id: SessionId,
3041 pub mode_id: SessionModeId,
3043 #[serde_as(deserialize_as = "DefaultOnError")]
3049 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3050 #[serde(default)]
3051 #[serde(rename = "_meta")]
3052 pub meta: Option<Meta>,
3053}
3054
3055impl SetSessionModeRequest {
3056 #[must_use]
3058 pub fn new(session_id: impl Into<SessionId>, mode_id: impl Into<SessionModeId>) -> Self {
3059 Self {
3060 session_id: session_id.into(),
3061 mode_id: mode_id.into(),
3062 meta: None,
3063 }
3064 }
3065
3066 #[must_use]
3068 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3069 self.meta = meta.into_option();
3070 self
3071 }
3072}
3073
3074crate::serde_util::default_on_null! {
3075 #[serde_as]
3077 #[skip_serializing_none]
3078 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3079 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
3080 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODE_METHOD_NAME)))]
3081 #[serde(rename_all = "camelCase")]
3082 #[non_exhaustive]
3083 pub struct SetSessionModeResponse {
3084 #[serde_as(deserialize_as = "DefaultOnError")]
3090 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3091 #[serde(default)]
3092 #[serde(rename = "_meta")]
3093 pub meta: Option<Meta>,
3094 }
3095}
3096
3097impl SetSessionModeResponse {
3098 #[must_use]
3100 pub fn new() -> Self {
3101 Self::default()
3102 }
3103
3104 #[must_use]
3110 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3111 self.meta = meta.into_option();
3112 self
3113 }
3114}
3115
3116#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3120#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, From, Display)]
3121#[serde(transparent)]
3122#[from(Arc<str>, String, &'static str)]
3123#[non_exhaustive]
3124pub struct SessionConfigId(pub Arc<str>);
3125
3126impl SessionConfigId {
3127 #[must_use]
3129 pub fn new(id: impl Into<Arc<str>>) -> Self {
3130 Self(id.into())
3131 }
3132}
3133
3134#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3136#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, From, Display)]
3137#[serde(transparent)]
3138#[from(Arc<str>, String, &'static str)]
3139#[non_exhaustive]
3140pub struct SessionConfigValueId(pub Arc<str>);
3141
3142impl SessionConfigValueId {
3143 #[must_use]
3145 pub fn new(id: impl Into<Arc<str>>) -> Self {
3146 Self(id.into())
3147 }
3148}
3149
3150#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3152#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, From, Display)]
3153#[serde(transparent)]
3154#[from(Arc<str>, String, &'static str)]
3155#[non_exhaustive]
3156pub struct SessionConfigGroupId(pub Arc<str>);
3157
3158impl SessionConfigGroupId {
3159 #[must_use]
3161 pub fn new(id: impl Into<Arc<str>>) -> Self {
3162 Self(id.into())
3163 }
3164}
3165
3166#[serde_as]
3168#[skip_serializing_none]
3169#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3170#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3171#[serde(rename_all = "camelCase")]
3172#[non_exhaustive]
3173pub struct SessionConfigSelectOption {
3174 pub value: SessionConfigValueId,
3176 pub name: String,
3178 #[serde_as(deserialize_as = "DefaultOnError")]
3180 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3181 #[serde(default)]
3182 pub description: Option<String>,
3183 #[serde_as(deserialize_as = "DefaultOnError")]
3189 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3190 #[serde(default)]
3191 #[serde(rename = "_meta")]
3192 pub meta: Option<Meta>,
3193}
3194
3195impl SessionConfigSelectOption {
3196 #[must_use]
3198 pub fn new(value: impl Into<SessionConfigValueId>, name: impl Into<String>) -> Self {
3199 Self {
3200 value: value.into(),
3201 name: name.into(),
3202 description: None,
3203 meta: None,
3204 }
3205 }
3206
3207 #[must_use]
3209 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
3210 self.description = description.into_option();
3211 self
3212 }
3213
3214 #[must_use]
3220 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3221 self.meta = meta.into_option();
3222 self
3223 }
3224}
3225
3226#[serde_as]
3228#[skip_serializing_none]
3229#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3230#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3231#[serde(rename_all = "camelCase")]
3232#[non_exhaustive]
3233pub struct SessionConfigSelectGroup {
3234 pub group: SessionConfigGroupId,
3236 pub name: String,
3238 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_>>")]
3240 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
3241 pub options: Vec<SessionConfigSelectOption>,
3242 #[serde_as(deserialize_as = "DefaultOnError")]
3248 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3249 #[serde(default)]
3250 #[serde(rename = "_meta")]
3251 pub meta: Option<Meta>,
3252}
3253
3254impl SessionConfigSelectGroup {
3255 #[must_use]
3257 pub fn new(
3258 group: impl Into<SessionConfigGroupId>,
3259 name: impl Into<String>,
3260 options: Vec<SessionConfigSelectOption>,
3261 ) -> Self {
3262 Self {
3263 group: group.into(),
3264 name: name.into(),
3265 options,
3266 meta: None,
3267 }
3268 }
3269
3270 #[must_use]
3276 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3277 self.meta = meta.into_option();
3278 self
3279 }
3280}
3281
3282#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3284#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3285#[serde(untagged)]
3286#[non_exhaustive]
3287pub enum SessionConfigSelectOptions {
3288 Ungrouped(Vec<SessionConfigSelectOption>),
3290 Grouped(Vec<SessionConfigSelectGroup>),
3292}
3293
3294impl From<Vec<SessionConfigSelectOption>> for SessionConfigSelectOptions {
3295 fn from(options: Vec<SessionConfigSelectOption>) -> Self {
3296 SessionConfigSelectOptions::Ungrouped(options)
3297 }
3298}
3299
3300impl From<Vec<SessionConfigSelectGroup>> for SessionConfigSelectOptions {
3301 fn from(groups: Vec<SessionConfigSelectGroup>) -> Self {
3302 SessionConfigSelectOptions::Grouped(groups)
3303 }
3304}
3305
3306#[skip_serializing_none]
3308#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3309#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3310#[serde(rename_all = "camelCase")]
3311#[non_exhaustive]
3312pub struct SessionConfigSelect {
3313 pub current_value: SessionConfigValueId,
3315 pub options: SessionConfigSelectOptions,
3317}
3318
3319impl SessionConfigSelect {
3320 #[must_use]
3322 pub fn new(
3323 current_value: impl Into<SessionConfigValueId>,
3324 options: impl Into<SessionConfigSelectOptions>,
3325 ) -> Self {
3326 Self {
3327 current_value: current_value.into(),
3328 options: options.into(),
3329 }
3330 }
3331}
3332
3333#[skip_serializing_none]
3335#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3336#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3337#[serde(rename_all = "camelCase")]
3338#[non_exhaustive]
3339pub struct SessionConfigBoolean {
3340 pub current_value: bool,
3342}
3343
3344impl SessionConfigBoolean {
3345 #[must_use]
3347 pub fn new(current_value: bool) -> Self {
3348 Self { current_value }
3349 }
3350}
3351
3352#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3362#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3363#[serde(rename_all = "snake_case")]
3364#[non_exhaustive]
3365pub enum SessionConfigOptionCategory {
3366 Mode,
3368 Model,
3370 ModelConfig,
3372 ThoughtLevel,
3374 #[serde(untagged)]
3376 Other(String),
3377}
3378
3379#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3381#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3382#[serde(tag = "type", rename_all = "snake_case")]
3383#[cfg_attr(feature = "schemars", schemars(extend("discriminator" = {"propertyName": "type"})))]
3384#[non_exhaustive]
3385pub enum SessionConfigKind {
3386 Select(SessionConfigSelect),
3388 Boolean(SessionConfigBoolean),
3390}
3391
3392#[serde_as]
3394#[skip_serializing_none]
3395#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3396#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3397#[serde(rename_all = "camelCase")]
3398#[non_exhaustive]
3399pub struct SessionConfigOption {
3400 pub id: SessionConfigId,
3402 pub name: String,
3404 #[serde_as(deserialize_as = "DefaultOnError")]
3406 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3407 #[serde(default)]
3408 pub description: Option<String>,
3409 #[serde_as(deserialize_as = "DefaultOnError")]
3411 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3412 #[serde(default)]
3413 pub category: Option<SessionConfigOptionCategory>,
3414 #[serde(flatten)]
3416 pub kind: SessionConfigKind,
3417 #[serde_as(deserialize_as = "DefaultOnError")]
3423 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3424 #[serde(default)]
3425 #[serde(rename = "_meta")]
3426 pub meta: Option<Meta>,
3427}
3428
3429impl SessionConfigOption {
3430 #[must_use]
3432 pub fn new(
3433 id: impl Into<SessionConfigId>,
3434 name: impl Into<String>,
3435 kind: SessionConfigKind,
3436 ) -> Self {
3437 Self {
3438 id: id.into(),
3439 name: name.into(),
3440 description: None,
3441 category: None,
3442 kind,
3443 meta: None,
3444 }
3445 }
3446
3447 #[must_use]
3449 pub fn select(
3450 id: impl Into<SessionConfigId>,
3451 name: impl Into<String>,
3452 current_value: impl Into<SessionConfigValueId>,
3453 options: impl Into<SessionConfigSelectOptions>,
3454 ) -> Self {
3455 Self::new(
3456 id,
3457 name,
3458 SessionConfigKind::Select(SessionConfigSelect::new(current_value, options)),
3459 )
3460 }
3461
3462 #[must_use]
3464 pub fn boolean(
3465 id: impl Into<SessionConfigId>,
3466 name: impl Into<String>,
3467 current_value: bool,
3468 ) -> Self {
3469 Self::new(
3470 id,
3471 name,
3472 SessionConfigKind::Boolean(SessionConfigBoolean::new(current_value)),
3473 )
3474 }
3475
3476 #[must_use]
3478 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
3479 self.description = description.into_option();
3480 self
3481 }
3482
3483 #[must_use]
3485 pub fn category(mut self, category: impl IntoOption<SessionConfigOptionCategory>) -> Self {
3486 self.category = category.into_option();
3487 self
3488 }
3489
3490 #[must_use]
3496 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3497 self.meta = meta.into_option();
3498 self
3499 }
3500}
3501
3502#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3513#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3514#[serde(tag = "type", rename_all = "snake_case")]
3515#[non_exhaustive]
3516pub enum SessionConfigOptionValue {
3517 Boolean {
3519 value: bool,
3521 },
3522 #[serde(untagged)]
3528 ValueId {
3529 value: SessionConfigValueId,
3531 },
3532}
3533
3534impl SessionConfigOptionValue {
3535 #[must_use]
3537 pub fn value_id(id: impl Into<SessionConfigValueId>) -> Self {
3538 Self::ValueId { value: id.into() }
3539 }
3540
3541 #[must_use]
3543 pub fn boolean(val: bool) -> Self {
3544 Self::Boolean { value: val }
3545 }
3546
3547 #[must_use]
3550 pub fn as_value_id(&self) -> Option<&SessionConfigValueId> {
3551 match self {
3552 Self::ValueId { value } => Some(value),
3553 _ => None,
3554 }
3555 }
3556
3557 #[must_use]
3559 pub fn as_bool(&self) -> Option<bool> {
3560 match self {
3561 Self::Boolean { value } => Some(*value),
3562 _ => None,
3563 }
3564 }
3565}
3566
3567impl From<SessionConfigValueId> for SessionConfigOptionValue {
3568 fn from(value: SessionConfigValueId) -> Self {
3569 Self::ValueId { value }
3570 }
3571}
3572
3573impl From<bool> for SessionConfigOptionValue {
3574 fn from(value: bool) -> Self {
3575 Self::Boolean { value }
3576 }
3577}
3578
3579impl From<&str> for SessionConfigOptionValue {
3580 fn from(value: &str) -> Self {
3581 Self::ValueId {
3582 value: SessionConfigValueId::new(value),
3583 }
3584 }
3585}
3586
3587#[serde_as]
3589#[skip_serializing_none]
3590#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3591#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3592#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_CONFIG_OPTION_METHOD_NAME)))]
3593#[serde(rename_all = "camelCase")]
3594#[non_exhaustive]
3595pub struct SetSessionConfigOptionRequest {
3596 pub session_id: SessionId,
3598 pub config_id: SessionConfigId,
3600 #[serde(flatten)]
3605 pub value: SessionConfigOptionValue,
3606 #[serde_as(deserialize_as = "DefaultOnError")]
3612 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3613 #[serde(default)]
3614 #[serde(rename = "_meta")]
3615 pub meta: Option<Meta>,
3616}
3617
3618impl SetSessionConfigOptionRequest {
3619 #[must_use]
3621 pub fn new(
3622 session_id: impl Into<SessionId>,
3623 config_id: impl Into<SessionConfigId>,
3624 value: impl Into<SessionConfigOptionValue>,
3625 ) -> Self {
3626 Self {
3627 session_id: session_id.into(),
3628 config_id: config_id.into(),
3629 value: value.into(),
3630 meta: None,
3631 }
3632 }
3633
3634 #[must_use]
3640 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3641 self.meta = meta.into_option();
3642 self
3643 }
3644}
3645
3646#[serde_as]
3648#[skip_serializing_none]
3649#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3650#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3651#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_CONFIG_OPTION_METHOD_NAME)))]
3652#[serde(rename_all = "camelCase")]
3653#[non_exhaustive]
3654pub struct SetSessionConfigOptionResponse {
3655 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_>>")]
3657 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
3658 pub config_options: Vec<SessionConfigOption>,
3659 #[serde_as(deserialize_as = "DefaultOnError")]
3665 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3666 #[serde(default)]
3667 #[serde(rename = "_meta")]
3668 pub meta: Option<Meta>,
3669}
3670
3671impl SetSessionConfigOptionResponse {
3672 #[must_use]
3674 pub fn new(config_options: Vec<SessionConfigOption>) -> Self {
3675 Self {
3676 config_options,
3677 meta: None,
3678 }
3679 }
3680
3681 #[must_use]
3687 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3688 self.meta = meta.into_option();
3689 self
3690 }
3691}
3692
3693#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3702#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3703#[serde(tag = "type", rename_all = "snake_case")]
3704#[non_exhaustive]
3705pub enum McpServer {
3706 Http(McpServerHttp),
3710 Sse(McpServerSse),
3714 #[cfg(feature = "unstable_mcp_over_acp")]
3723 Acp(McpServerAcp),
3724 #[serde(untagged)]
3728 Stdio(McpServerStdio),
3729}
3730
3731#[serde_as]
3733#[skip_serializing_none]
3734#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3735#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3736#[serde(rename_all = "camelCase")]
3737#[non_exhaustive]
3738pub struct McpServerHttp {
3739 pub name: String,
3741 pub url: String,
3743 #[serde_as(deserialize_as = "DefaultOnNull")]
3745 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-null" = true)))]
3746 pub headers: Vec<HttpHeader>,
3747 #[serde_as(deserialize_as = "DefaultOnError")]
3753 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3754 #[serde(default)]
3755 #[serde(rename = "_meta")]
3756 pub meta: Option<Meta>,
3757}
3758
3759impl McpServerHttp {
3760 #[must_use]
3762 pub fn new(name: impl Into<String>, url: impl Into<String>) -> Self {
3763 Self {
3764 name: name.into(),
3765 url: url.into(),
3766 headers: Vec::new(),
3767 meta: None,
3768 }
3769 }
3770
3771 #[must_use]
3773 pub fn headers(mut self, headers: Vec<HttpHeader>) -> Self {
3774 self.headers = headers;
3775 self
3776 }
3777
3778 #[must_use]
3784 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3785 self.meta = meta.into_option();
3786 self
3787 }
3788}
3789
3790#[serde_as]
3792#[skip_serializing_none]
3793#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3794#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3795#[serde(rename_all = "camelCase")]
3796#[non_exhaustive]
3797pub struct McpServerSse {
3798 pub name: String,
3800 pub url: String,
3802 #[serde_as(deserialize_as = "DefaultOnNull")]
3804 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-null" = true)))]
3805 pub headers: Vec<HttpHeader>,
3806 #[serde_as(deserialize_as = "DefaultOnError")]
3812 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3813 #[serde(default)]
3814 #[serde(rename = "_meta")]
3815 pub meta: Option<Meta>,
3816}
3817
3818impl McpServerSse {
3819 #[must_use]
3821 pub fn new(name: impl Into<String>, url: impl Into<String>) -> Self {
3822 Self {
3823 name: name.into(),
3824 url: url.into(),
3825 headers: Vec::new(),
3826 meta: None,
3827 }
3828 }
3829
3830 #[must_use]
3832 pub fn headers(mut self, headers: Vec<HttpHeader>) -> Self {
3833 self.headers = headers;
3834 self
3835 }
3836
3837 #[must_use]
3843 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3844 self.meta = meta.into_option();
3845 self
3846 }
3847}
3848
3849#[cfg(feature = "unstable_mcp_over_acp")]
3858#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3859#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Display, From)]
3860#[serde(transparent)]
3861#[from(Arc<str>, String, &'static str)]
3862#[non_exhaustive]
3863pub struct McpServerAcpId(pub Arc<str>);
3864
3865#[cfg(feature = "unstable_mcp_over_acp")]
3866impl McpServerAcpId {
3867 #[must_use]
3869 pub fn new(id: impl Into<Arc<str>>) -> Self {
3870 Self(id.into())
3871 }
3872}
3873
3874#[serde_as]
3883#[skip_serializing_none]
3884#[cfg(feature = "unstable_mcp_over_acp")]
3885#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3886#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3887#[serde(rename_all = "camelCase")]
3888#[non_exhaustive]
3889pub struct McpServerAcp {
3890 pub name: String,
3892 pub server_id: McpServerAcpId,
3897 #[serde_as(deserialize_as = "DefaultOnError")]
3903 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3904 #[serde(default)]
3905 #[serde(rename = "_meta")]
3906 pub meta: Option<Meta>,
3907}
3908
3909#[cfg(feature = "unstable_mcp_over_acp")]
3910impl McpServerAcp {
3911 #[must_use]
3913 pub fn new(name: impl Into<String>, id: impl Into<McpServerAcpId>) -> Self {
3914 Self {
3915 name: name.into(),
3916 server_id: id.into(),
3917 meta: None,
3918 }
3919 }
3920
3921 #[must_use]
3927 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3928 self.meta = meta.into_option();
3929 self
3930 }
3931}
3932
3933#[serde_as]
3935#[skip_serializing_none]
3936#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3937#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3938#[serde(rename_all = "camelCase")]
3939#[non_exhaustive]
3940pub struct McpServerStdio {
3941 pub name: String,
3943 pub command: PathBuf,
3945 #[serde_as(deserialize_as = "DefaultOnNull")]
3947 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-null" = true)))]
3948 pub args: Vec<String>,
3949 #[serde_as(deserialize_as = "DefaultOnNull")]
3951 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-null" = true)))]
3952 pub env: Vec<EnvVariable>,
3953 #[serde_as(deserialize_as = "DefaultOnError")]
3959 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3960 #[serde(default)]
3961 #[serde(rename = "_meta")]
3962 pub meta: Option<Meta>,
3963}
3964
3965impl McpServerStdio {
3966 #[must_use]
3968 pub fn new(name: impl Into<String>, command: impl Into<PathBuf>) -> Self {
3969 Self {
3970 name: name.into(),
3971 command: command.into(),
3972 args: Vec::new(),
3973 env: Vec::new(),
3974 meta: None,
3975 }
3976 }
3977
3978 #[must_use]
3980 pub fn args(mut self, args: Vec<String>) -> Self {
3981 self.args = args;
3982 self
3983 }
3984
3985 #[must_use]
3987 pub fn env(mut self, env: Vec<EnvVariable>) -> Self {
3988 self.env = env;
3989 self
3990 }
3991
3992 #[must_use]
3998 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3999 self.meta = meta.into_option();
4000 self
4001 }
4002}
4003
4004#[serde_as]
4006#[skip_serializing_none]
4007#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4008#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4009#[serde(rename_all = "camelCase")]
4010#[non_exhaustive]
4011pub struct EnvVariable {
4012 pub name: String,
4014 pub value: String,
4016 #[serde_as(deserialize_as = "DefaultOnError")]
4022 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4023 #[serde(default)]
4024 #[serde(rename = "_meta")]
4025 pub meta: Option<Meta>,
4026}
4027
4028impl EnvVariable {
4029 #[must_use]
4031 pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
4032 Self {
4033 name: name.into(),
4034 value: value.into(),
4035 meta: None,
4036 }
4037 }
4038
4039 #[must_use]
4045 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4046 self.meta = meta.into_option();
4047 self
4048 }
4049}
4050
4051#[serde_as]
4053#[skip_serializing_none]
4054#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4055#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4056#[serde(rename_all = "camelCase")]
4057#[non_exhaustive]
4058pub struct HttpHeader {
4059 pub name: String,
4061 pub value: String,
4063 #[serde_as(deserialize_as = "DefaultOnError")]
4069 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4070 #[serde(default)]
4071 #[serde(rename = "_meta")]
4072 pub meta: Option<Meta>,
4073}
4074
4075impl HttpHeader {
4076 #[must_use]
4078 pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
4079 Self {
4080 name: name.into(),
4081 value: value.into(),
4082 meta: None,
4083 }
4084 }
4085
4086 #[must_use]
4092 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4093 self.meta = meta.into_option();
4094 self
4095 }
4096}
4097
4098#[serde_as]
4107#[skip_serializing_none]
4108#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4109#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4110#[serde(rename_all = "camelCase")]
4111#[non_exhaustive]
4112pub struct SystemPrompt {
4113 pub mode: SystemPromptMode,
4118 pub content: Vec<ContentBlock>,
4128 #[serde_as(deserialize_as = "DefaultOnError")]
4134 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4135 #[serde(default)]
4136 #[serde(rename = "_meta")]
4137 pub meta: Option<Meta>,
4138}
4139
4140impl SystemPrompt {
4141 #[must_use]
4146 pub fn new(content: Vec<ContentBlock>) -> Self {
4147 Self {
4148 mode: SystemPromptMode::default(),
4149 content,
4150 meta: None,
4151 }
4152 }
4153
4154 #[must_use]
4156 pub fn mode(mut self, mode: SystemPromptMode) -> Self {
4157 self.mode = mode;
4158 self
4159 }
4160
4161 #[must_use]
4167 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4168 self.meta = meta.into_option();
4169 self
4170 }
4171}
4172
4173#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4179#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
4180#[serde(rename_all = "snake_case")]
4181#[non_exhaustive]
4182pub enum SystemPromptMode {
4183 #[default]
4190 Append,
4191 Override,
4200 #[serde(untagged)]
4206 Other(String),
4207}
4208
4209#[serde_as]
4217#[skip_serializing_none]
4218#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4219#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4220#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_PROMPT_METHOD_NAME)))]
4221#[serde(rename_all = "camelCase")]
4222#[non_exhaustive]
4223pub struct PromptRequest {
4224 pub session_id: SessionId,
4226 pub prompt: Vec<ContentBlock>,
4240 #[serde_as(deserialize_as = "DefaultOnError")]
4246 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4247 #[serde(default)]
4248 #[serde(rename = "_meta")]
4249 pub meta: Option<Meta>,
4250}
4251
4252impl PromptRequest {
4253 #[must_use]
4255 pub fn new(session_id: impl Into<SessionId>, prompt: Vec<ContentBlock>) -> Self {
4256 Self {
4257 session_id: session_id.into(),
4258 prompt,
4259 meta: None,
4260 }
4261 }
4262
4263 #[must_use]
4269 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4270 self.meta = meta.into_option();
4271 self
4272 }
4273}
4274
4275#[serde_as]
4279#[skip_serializing_none]
4280#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4281#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4282#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_PROMPT_METHOD_NAME)))]
4283#[serde(rename_all = "camelCase")]
4284#[non_exhaustive]
4285pub struct PromptResponse {
4286 pub stop_reason: StopReason,
4288 #[cfg(feature = "unstable_end_turn_token_usage")]
4294 #[serde_as(deserialize_as = "DefaultOnError")]
4295 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4296 #[serde(default)]
4297 pub usage: Option<Usage>,
4298 #[serde_as(deserialize_as = "DefaultOnError")]
4304 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4305 #[serde(default)]
4306 #[serde(rename = "_meta")]
4307 pub meta: Option<Meta>,
4308}
4309
4310impl PromptResponse {
4311 #[must_use]
4313 pub fn new(stop_reason: StopReason) -> Self {
4314 Self {
4315 stop_reason,
4316 #[cfg(feature = "unstable_end_turn_token_usage")]
4317 usage: None,
4318 meta: None,
4319 }
4320 }
4321
4322 #[cfg(feature = "unstable_end_turn_token_usage")]
4328 #[must_use]
4329 pub fn usage(mut self, usage: impl IntoOption<Usage>) -> Self {
4330 self.usage = usage.into_option();
4331 self
4332 }
4333
4334 #[must_use]
4340 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4341 self.meta = meta.into_option();
4342 self
4343 }
4344}
4345
4346#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4350#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize)]
4351#[serde(rename_all = "snake_case")]
4352#[non_exhaustive]
4353pub enum StopReason {
4354 EndTurn,
4356 MaxTokens,
4358 MaxTurnRequests,
4361 Refusal,
4365 Cancelled,
4372}
4373
4374#[cfg(feature = "unstable_end_turn_token_usage")]
4380#[serde_as]
4381#[skip_serializing_none]
4382#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4383#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4384#[serde(rename_all = "camelCase")]
4385#[non_exhaustive]
4386pub struct Usage {
4387 pub total_tokens: u64,
4389 pub input_tokens: u64,
4391 pub output_tokens: u64,
4393 #[serde_as(deserialize_as = "DefaultOnError")]
4395 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4396 #[serde(default)]
4397 pub thought_tokens: Option<u64>,
4398 #[serde_as(deserialize_as = "DefaultOnError")]
4400 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4401 #[serde(default)]
4402 pub cached_read_tokens: Option<u64>,
4403 #[serde_as(deserialize_as = "DefaultOnError")]
4405 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4406 #[serde(default)]
4407 pub cached_write_tokens: Option<u64>,
4408 #[serde_as(deserialize_as = "DefaultOnError")]
4414 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4415 #[serde(default)]
4416 #[serde(rename = "_meta")]
4417 pub meta: Option<Meta>,
4418}
4419
4420#[cfg(feature = "unstable_end_turn_token_usage")]
4421impl Usage {
4422 #[must_use]
4424 pub fn new(total_tokens: u64, input_tokens: u64, output_tokens: u64) -> Self {
4425 Self {
4426 total_tokens,
4427 input_tokens,
4428 output_tokens,
4429 thought_tokens: None,
4430 cached_read_tokens: None,
4431 cached_write_tokens: None,
4432 meta: None,
4433 }
4434 }
4435
4436 #[must_use]
4438 pub fn thought_tokens(mut self, thought_tokens: impl IntoOption<u64>) -> Self {
4439 self.thought_tokens = thought_tokens.into_option();
4440 self
4441 }
4442
4443 #[must_use]
4445 pub fn cached_read_tokens(mut self, cached_read_tokens: impl IntoOption<u64>) -> Self {
4446 self.cached_read_tokens = cached_read_tokens.into_option();
4447 self
4448 }
4449
4450 #[must_use]
4452 pub fn cached_write_tokens(mut self, cached_write_tokens: impl IntoOption<u64>) -> Self {
4453 self.cached_write_tokens = cached_write_tokens.into_option();
4454 self
4455 }
4456
4457 #[must_use]
4463 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4464 self.meta = meta.into_option();
4465 self
4466 }
4467}
4468
4469#[cfg(feature = "unstable_llm_providers")]
4482#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4483#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4484#[serde(rename_all = "snake_case")]
4485#[non_exhaustive]
4486#[expect(clippy::doc_markdown)]
4487pub enum LlmProtocol {
4488 Anthropic,
4490 #[serde(rename = "openai")]
4492 OpenAi,
4493 Azure,
4495 Vertex,
4497 Bedrock,
4499 #[serde(untagged)]
4501 Other(String),
4502}
4503
4504#[cfg(feature = "unstable_llm_providers")]
4510#[serde_as]
4511#[skip_serializing_none]
4512#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4513#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4514#[serde(rename_all = "camelCase")]
4515#[non_exhaustive]
4516pub struct ProviderCurrentConfig {
4517 pub api_type: LlmProtocol,
4519 pub base_url: String,
4521 #[serde_as(deserialize_as = "DefaultOnError")]
4527 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4528 #[serde(default)]
4529 #[serde(rename = "_meta")]
4530 pub meta: Option<Meta>,
4531}
4532
4533#[cfg(feature = "unstable_llm_providers")]
4534impl ProviderCurrentConfig {
4535 #[must_use]
4537 pub fn new(api_type: LlmProtocol, base_url: impl Into<String>) -> Self {
4538 Self {
4539 api_type,
4540 base_url: base_url.into(),
4541 meta: None,
4542 }
4543 }
4544
4545 #[must_use]
4551 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4552 self.meta = meta.into_option();
4553 self
4554 }
4555}
4556
4557#[cfg(feature = "unstable_llm_providers")]
4563#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4564#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Display, From)]
4565#[serde(transparent)]
4566#[from(Arc<str>, String, &'static str)]
4567#[non_exhaustive]
4568pub struct ProviderId(pub Arc<str>);
4569
4570#[cfg(feature = "unstable_llm_providers")]
4571impl ProviderId {
4572 #[must_use]
4574 pub fn new(id: impl Into<Arc<str>>) -> Self {
4575 Self(id.into())
4576 }
4577}
4578
4579#[cfg(feature = "unstable_llm_providers")]
4585#[serde_as]
4586#[skip_serializing_none]
4587#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4588#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4589#[serde(rename_all = "camelCase")]
4590#[non_exhaustive]
4591pub struct ProviderInfo {
4592 pub provider_id: ProviderId,
4594 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_>>")]
4596 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
4597 pub supported: Vec<LlmProtocol>,
4598 pub required: bool,
4601 #[serde(default)]
4604 pub current: Option<ProviderCurrentConfig>,
4605 #[serde_as(deserialize_as = "DefaultOnError")]
4611 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4612 #[serde(default)]
4613 #[serde(rename = "_meta")]
4614 pub meta: Option<Meta>,
4615}
4616
4617#[cfg(feature = "unstable_llm_providers")]
4618impl ProviderInfo {
4619 #[must_use]
4621 pub fn new(
4622 provider_id: impl Into<ProviderId>,
4623 supported: Vec<LlmProtocol>,
4624 required: bool,
4625 current: impl IntoOption<ProviderCurrentConfig>,
4626 ) -> Self {
4627 Self {
4628 provider_id: provider_id.into(),
4629 supported,
4630 required,
4631 current: current.into_option(),
4632 meta: None,
4633 }
4634 }
4635
4636 #[must_use]
4642 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4643 self.meta = meta.into_option();
4644 self
4645 }
4646}
4647
4648#[cfg(feature = "unstable_llm_providers")]
4649crate::serde_util::default_on_null! {
4650 #[serde_as]
4656 #[skip_serializing_none]
4657 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4658 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
4659 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_LIST_METHOD_NAME)))]
4660 #[serde(rename_all = "camelCase")]
4661 #[non_exhaustive]
4662 pub struct ListProvidersRequest {
4663 #[serde_as(deserialize_as = "DefaultOnError")]
4669 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4670 #[serde(default)]
4671 #[serde(rename = "_meta")]
4672 pub meta: Option<Meta>,
4673 }
4674}
4675
4676#[cfg(feature = "unstable_llm_providers")]
4677impl ListProvidersRequest {
4678 #[must_use]
4680 pub fn new() -> Self {
4681 Self::default()
4682 }
4683
4684 #[must_use]
4690 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4691 self.meta = meta.into_option();
4692 self
4693 }
4694}
4695
4696#[cfg(feature = "unstable_llm_providers")]
4702#[serde_as]
4703#[skip_serializing_none]
4704#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4705#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4706#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_LIST_METHOD_NAME)))]
4707#[serde(rename_all = "camelCase")]
4708#[non_exhaustive]
4709pub struct ListProvidersResponse {
4710 pub providers: Vec<ProviderInfo>,
4712 #[serde_as(deserialize_as = "DefaultOnError")]
4718 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4719 #[serde(default)]
4720 #[serde(rename = "_meta")]
4721 pub meta: Option<Meta>,
4722}
4723
4724#[cfg(feature = "unstable_llm_providers")]
4725impl ListProvidersResponse {
4726 #[must_use]
4728 pub fn new(providers: Vec<ProviderInfo>) -> Self {
4729 Self {
4730 providers,
4731 meta: None,
4732 }
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")]
4755#[serde_as]
4756#[skip_serializing_none]
4757#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4758#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
4759#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_SET_METHOD_NAME)))]
4760#[serde(rename_all = "camelCase")]
4761#[non_exhaustive]
4762pub struct SetProviderRequest {
4763 pub provider_id: ProviderId,
4765 pub api_type: LlmProtocol,
4767 pub base_url: String,
4769 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
4772 pub headers: HashMap<String, String>,
4773 #[serde_as(deserialize_as = "DefaultOnError")]
4779 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4780 #[serde(default)]
4781 #[serde(rename = "_meta")]
4782 pub meta: Option<Meta>,
4783}
4784
4785#[cfg(feature = "unstable_llm_providers")]
4786impl SetProviderRequest {
4787 #[must_use]
4789 pub fn new(
4790 provider_id: impl Into<ProviderId>,
4791 api_type: LlmProtocol,
4792 base_url: impl Into<String>,
4793 ) -> Self {
4794 Self {
4795 provider_id: provider_id.into(),
4796 api_type,
4797 base_url: base_url.into(),
4798 headers: HashMap::new(),
4799 meta: None,
4800 }
4801 }
4802
4803 #[must_use]
4806 pub fn headers(mut self, headers: HashMap<String, String>) -> Self {
4807 self.headers = headers;
4808 self
4809 }
4810
4811 #[must_use]
4817 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4818 self.meta = meta.into_option();
4819 self
4820 }
4821}
4822
4823#[cfg(feature = "unstable_llm_providers")]
4824crate::serde_util::default_on_null! {
4825 #[serde_as]
4831 #[skip_serializing_none]
4832 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4833 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
4834 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_SET_METHOD_NAME)))]
4835 #[serde(rename_all = "camelCase")]
4836 #[non_exhaustive]
4837 pub struct SetProviderResponse {
4838 #[serde_as(deserialize_as = "DefaultOnError")]
4844 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4845 #[serde(default)]
4846 #[serde(rename = "_meta")]
4847 pub meta: Option<Meta>,
4848 }
4849}
4850
4851#[cfg(feature = "unstable_llm_providers")]
4852impl SetProviderResponse {
4853 #[must_use]
4855 pub fn new() -> Self {
4856 Self::default()
4857 }
4858
4859 #[must_use]
4865 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4866 self.meta = meta.into_option();
4867 self
4868 }
4869}
4870
4871#[cfg(feature = "unstable_llm_providers")]
4877#[serde_as]
4878#[skip_serializing_none]
4879#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4880#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4881#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_DISABLE_METHOD_NAME)))]
4882#[serde(rename_all = "camelCase")]
4883#[non_exhaustive]
4884pub struct DisableProviderRequest {
4885 pub provider_id: ProviderId,
4887 #[serde_as(deserialize_as = "DefaultOnError")]
4893 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4894 #[serde(default)]
4895 #[serde(rename = "_meta")]
4896 pub meta: Option<Meta>,
4897}
4898
4899#[cfg(feature = "unstable_llm_providers")]
4900impl DisableProviderRequest {
4901 #[must_use]
4903 pub fn new(provider_id: impl Into<ProviderId>) -> Self {
4904 Self {
4905 provider_id: provider_id.into(),
4906 meta: None,
4907 }
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")]
4923crate::serde_util::default_on_null! {
4924 #[serde_as]
4930 #[skip_serializing_none]
4931 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4932 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
4933 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_DISABLE_METHOD_NAME)))]
4934 #[serde(rename_all = "camelCase")]
4935 #[non_exhaustive]
4936 pub struct DisableProviderResponse {
4937 #[serde_as(deserialize_as = "DefaultOnError")]
4943 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4944 #[serde(default)]
4945 #[serde(rename = "_meta")]
4946 pub meta: Option<Meta>,
4947 }
4948}
4949
4950#[cfg(feature = "unstable_llm_providers")]
4951impl DisableProviderResponse {
4952 #[must_use]
4954 pub fn new() -> Self {
4955 Self::default()
4956 }
4957
4958 #[must_use]
4964 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4965 self.meta = meta.into_option();
4966 self
4967 }
4968}
4969
4970#[serde_as]
4979#[skip_serializing_none]
4980#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4981#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4982#[serde(rename_all = "camelCase")]
4983#[non_exhaustive]
4984pub struct AgentCapabilities {
4985 #[serde_as(deserialize_as = "DefaultOnError")]
4987 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4988 #[serde(default)]
4989 pub load_session: bool,
4990 #[serde_as(deserialize_as = "DefaultOnError")]
4992 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4993 #[serde(default)]
4994 pub prompt_capabilities: PromptCapabilities,
4995 #[serde_as(deserialize_as = "DefaultOnError")]
4997 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4998 #[serde(default)]
4999 pub mcp_capabilities: McpCapabilities,
5000 #[serde_as(deserialize_as = "DefaultOnError")]
5002 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5003 #[serde(default)]
5004 pub session_capabilities: SessionCapabilities,
5005 #[serde_as(deserialize_as = "DefaultOnError")]
5007 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5008 #[serde(default)]
5009 pub auth: AgentAuthCapabilities,
5010 #[cfg(feature = "unstable_llm_providers")]
5019 #[serde_as(deserialize_as = "DefaultOnError")]
5020 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5021 #[serde(default)]
5022 pub providers: Option<ProvidersCapabilities>,
5023 #[serde_as(deserialize_as = "DefaultOnError")]
5029 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5030 #[serde(default)]
5031 #[serde(rename = "_meta")]
5032 pub meta: Option<Meta>,
5033}
5034
5035impl AgentCapabilities {
5036 #[must_use]
5038 pub fn new() -> Self {
5039 Self::default()
5040 }
5041
5042 #[must_use]
5044 pub fn load_session(mut self, load_session: bool) -> Self {
5045 self.load_session = load_session;
5046 self
5047 }
5048
5049 #[must_use]
5051 pub fn prompt_capabilities(mut self, prompt_capabilities: PromptCapabilities) -> Self {
5052 self.prompt_capabilities = prompt_capabilities;
5053 self
5054 }
5055
5056 #[must_use]
5058 pub fn mcp_capabilities(mut self, mcp_capabilities: McpCapabilities) -> Self {
5059 self.mcp_capabilities = mcp_capabilities;
5060 self
5061 }
5062
5063 #[must_use]
5065 pub fn session_capabilities(mut self, session_capabilities: SessionCapabilities) -> Self {
5066 self.session_capabilities = session_capabilities;
5067 self
5068 }
5069
5070 #[must_use]
5072 pub fn auth(mut self, auth: AgentAuthCapabilities) -> Self {
5073 self.auth = auth;
5074 self
5075 }
5076
5077 #[cfg(feature = "unstable_llm_providers")]
5083 #[must_use]
5084 pub fn providers(mut self, providers: impl IntoOption<ProvidersCapabilities>) -> Self {
5085 self.providers = providers.into_option();
5086 self
5087 }
5088
5089 #[must_use]
5095 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5096 self.meta = meta.into_option();
5097 self
5098 }
5099}
5100
5101#[cfg(feature = "unstable_llm_providers")]
5109#[serde_as]
5110#[skip_serializing_none]
5111#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5112#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5113#[non_exhaustive]
5114pub struct ProvidersCapabilities {
5115 #[serde_as(deserialize_as = "DefaultOnError")]
5121 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5122 #[serde(default)]
5123 #[serde(rename = "_meta")]
5124 pub meta: Option<Meta>,
5125}
5126
5127#[cfg(feature = "unstable_llm_providers")]
5128impl ProvidersCapabilities {
5129 #[must_use]
5131 pub fn new() -> Self {
5132 Self::default()
5133 }
5134
5135 #[must_use]
5141 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5142 self.meta = meta.into_option();
5143 self
5144 }
5145}
5146
5147#[serde_as]
5157#[skip_serializing_none]
5158#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5159#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5160#[serde(rename_all = "camelCase")]
5161#[non_exhaustive]
5162pub struct SessionCapabilities {
5163 #[serde_as(deserialize_as = "DefaultOnError")]
5168 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5169 #[serde(default)]
5170 pub list: Option<SessionListCapabilities>,
5171 #[serde_as(deserialize_as = "DefaultOnError")]
5176 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5177 #[serde(default)]
5178 pub delete: Option<SessionDeleteCapabilities>,
5179 #[serde_as(deserialize_as = "DefaultOnError")]
5189 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5190 #[serde(default)]
5191 pub additional_directories: Option<SessionAdditionalDirectoriesCapabilities>,
5192 #[serde_as(deserialize_as = "DefaultOnError")]
5197 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5198 #[serde(default)]
5199 pub system_prompt: Option<SessionSystemPromptCapabilities>,
5200 #[cfg(feature = "unstable_session_fork")]
5209 #[serde_as(deserialize_as = "DefaultOnError")]
5210 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5211 #[serde(default)]
5212 pub fork: Option<SessionForkCapabilities>,
5213 #[cfg(feature = "unstable_session_archive")]
5223 #[serde_as(deserialize_as = "DefaultOnError")]
5224 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5225 #[serde(default)]
5226 pub archive: Option<SessionArchiveCapabilities>,
5227 #[cfg(feature = "unstable_session_status")]
5236 #[serde_as(deserialize_as = "DefaultOnError")]
5237 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5238 #[serde(default)]
5239 pub status: Option<SessionStatusCapabilities>,
5240 #[cfg(feature = "unstable_session_set_title")]
5252 #[serde_as(deserialize_as = "DefaultOnError")]
5253 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5254 #[serde(default)]
5255 pub title: Option<SessionTitleCapabilities>,
5256 #[serde_as(deserialize_as = "DefaultOnError")]
5261 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5262 #[serde(default)]
5263 pub resume: Option<SessionResumeCapabilities>,
5264 #[serde_as(deserialize_as = "DefaultOnError")]
5269 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5270 #[serde(default)]
5271 pub close: Option<SessionCloseCapabilities>,
5272 #[serde_as(deserialize_as = "DefaultOnError")]
5278 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5279 #[serde(default)]
5280 #[serde(rename = "_meta")]
5281 pub meta: Option<Meta>,
5282}
5283
5284impl SessionCapabilities {
5285 #[must_use]
5287 pub fn new() -> Self {
5288 Self::default()
5289 }
5290
5291 #[must_use]
5296 pub fn list(mut self, list: impl IntoOption<SessionListCapabilities>) -> Self {
5297 self.list = list.into_option();
5298 self
5299 }
5300
5301 #[must_use]
5306 pub fn delete(mut self, delete: impl IntoOption<SessionDeleteCapabilities>) -> Self {
5307 self.delete = delete.into_option();
5308 self
5309 }
5310
5311 #[must_use]
5321 pub fn additional_directories(
5322 mut self,
5323 additional_directories: impl IntoOption<SessionAdditionalDirectoriesCapabilities>,
5324 ) -> Self {
5325 self.additional_directories = additional_directories.into_option();
5326 self
5327 }
5328
5329 #[must_use]
5334 pub fn system_prompt(
5335 mut self,
5336 system_prompt: impl IntoOption<SessionSystemPromptCapabilities>,
5337 ) -> Self {
5338 self.system_prompt = system_prompt.into_option();
5339 self
5340 }
5341
5342 #[cfg(feature = "unstable_session_fork")]
5343 #[must_use]
5348 pub fn fork(mut self, fork: impl IntoOption<SessionForkCapabilities>) -> Self {
5349 self.fork = fork.into_option();
5350 self
5351 }
5352
5353 #[cfg(feature = "unstable_session_archive")]
5363 #[must_use]
5364 pub fn archive(mut self, archive: impl IntoOption<SessionArchiveCapabilities>) -> Self {
5365 self.archive = archive.into_option();
5366 self
5367 }
5368
5369 #[cfg(feature = "unstable_session_status")]
5378 #[must_use]
5379 pub fn status(mut self, status: impl IntoOption<SessionStatusCapabilities>) -> Self {
5380 self.status = status.into_option();
5381 self
5382 }
5383
5384 #[cfg(feature = "unstable_session_set_title")]
5396 #[must_use]
5397 pub fn title(mut self, title: impl IntoOption<SessionTitleCapabilities>) -> Self {
5398 self.title = title.into_option();
5399 self
5400 }
5401
5402 #[must_use]
5407 pub fn resume(mut self, resume: impl IntoOption<SessionResumeCapabilities>) -> Self {
5408 self.resume = resume.into_option();
5409 self
5410 }
5411
5412 #[must_use]
5417 pub fn close(mut self, close: impl IntoOption<SessionCloseCapabilities>) -> Self {
5418 self.close = close.into_option();
5419 self
5420 }
5421
5422 #[must_use]
5428 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5429 self.meta = meta.into_option();
5430 self
5431 }
5432}
5433
5434#[serde_as]
5438#[skip_serializing_none]
5439#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5440#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5441#[non_exhaustive]
5442pub struct SessionListCapabilities {
5443 #[serde_as(deserialize_as = "DefaultOnError")]
5449 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5450 #[serde(default)]
5451 #[serde(rename = "_meta")]
5452 pub meta: Option<Meta>,
5453}
5454
5455impl SessionListCapabilities {
5456 #[must_use]
5458 pub fn new() -> Self {
5459 Self::default()
5460 }
5461
5462 #[must_use]
5468 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5469 self.meta = meta.into_option();
5470 self
5471 }
5472}
5473
5474#[serde_as]
5478#[skip_serializing_none]
5479#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5480#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5481#[non_exhaustive]
5482pub struct SessionDeleteCapabilities {
5483 #[serde_as(deserialize_as = "DefaultOnError")]
5489 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5490 #[serde(default)]
5491 #[serde(rename = "_meta")]
5492 pub meta: Option<Meta>,
5493}
5494
5495impl SessionDeleteCapabilities {
5496 #[must_use]
5498 pub fn new() -> Self {
5499 Self::default()
5500 }
5501
5502 #[must_use]
5508 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5509 self.meta = meta.into_option();
5510 self
5511 }
5512}
5513
5514#[serde_as]
5521#[skip_serializing_none]
5522#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5523#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5524#[non_exhaustive]
5525pub struct SessionAdditionalDirectoriesCapabilities {
5526 #[serde_as(deserialize_as = "DefaultOnError")]
5532 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5533 #[serde(default)]
5534 #[serde(rename = "_meta")]
5535 pub meta: Option<Meta>,
5536}
5537
5538impl SessionAdditionalDirectoriesCapabilities {
5539 #[must_use]
5541 pub fn new() -> Self {
5542 Self::default()
5543 }
5544
5545 #[must_use]
5551 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5552 self.meta = meta.into_option();
5553 self
5554 }
5555}
5556
5557#[serde_as]
5562#[skip_serializing_none]
5563#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5564#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5565#[serde(rename_all = "camelCase")]
5566#[non_exhaustive]
5567pub struct SessionSystemPromptCapabilities {
5568 #[serde_as(deserialize_as = "DefaultOnError")]
5572 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5573 #[serde(default)]
5574 pub mode: Option<SessionSystemPromptModeCapabilities>,
5575 #[serde_as(deserialize_as = "DefaultOnError")]
5581 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5582 #[serde(default)]
5583 #[serde(rename = "_meta")]
5584 pub meta: Option<Meta>,
5585}
5586
5587impl SessionSystemPromptCapabilities {
5588 #[must_use]
5590 pub fn new() -> Self {
5591 Self::default()
5592 }
5593
5594 #[must_use]
5598 pub fn mode(mut self, mode: impl IntoOption<SessionSystemPromptModeCapabilities>) -> Self {
5599 self.mode = mode.into_option();
5600 self
5601 }
5602
5603 #[must_use]
5609 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5610 self.meta = meta.into_option();
5611 self
5612 }
5613}
5614
5615#[serde_as]
5620#[skip_serializing_none]
5621#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5622#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5623#[serde(rename_all = "camelCase")]
5624#[non_exhaustive]
5625pub struct SessionSystemPromptModeCapabilities {
5626 #[serde_as(deserialize_as = "DefaultOnError")]
5632 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5633 #[serde(default, rename = "override")]
5634 pub override_: Option<SessionSystemPromptOverrideCapabilities>,
5635 #[serde_as(deserialize_as = "DefaultOnError")]
5641 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5642 #[serde(default)]
5643 #[serde(rename = "_meta")]
5644 pub meta: Option<Meta>,
5645}
5646
5647impl SessionSystemPromptModeCapabilities {
5648 #[must_use]
5650 pub fn new() -> Self {
5651 Self::default()
5652 }
5653
5654 #[must_use]
5660 pub fn override_(
5661 mut self,
5662 override_: impl IntoOption<SessionSystemPromptOverrideCapabilities>,
5663 ) -> Self {
5664 self.override_ = override_.into_option();
5665 self
5666 }
5667
5668 #[must_use]
5674 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5675 self.meta = meta.into_option();
5676 self
5677 }
5678}
5679
5680#[serde_as]
5685#[skip_serializing_none]
5686#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5687#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5688#[non_exhaustive]
5689pub struct SessionSystemPromptOverrideCapabilities {
5690 #[serde_as(deserialize_as = "DefaultOnError")]
5696 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5697 #[serde(default)]
5698 #[serde(rename = "_meta")]
5699 pub meta: Option<Meta>,
5700}
5701
5702impl SessionSystemPromptOverrideCapabilities {
5703 #[must_use]
5705 pub fn new() -> Self {
5706 Self::default()
5707 }
5708
5709 #[must_use]
5715 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5716 self.meta = meta.into_option();
5717 self
5718 }
5719}
5720
5721#[cfg(feature = "unstable_session_fork")]
5729#[serde_as]
5730#[skip_serializing_none]
5731#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5732#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5733#[non_exhaustive]
5734pub struct SessionForkCapabilities {
5735 #[serde_as(deserialize_as = "DefaultOnError")]
5741 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5742 #[serde(default)]
5743 #[serde(rename = "_meta")]
5744 pub meta: Option<Meta>,
5745}
5746
5747#[cfg(feature = "unstable_session_fork")]
5748impl SessionForkCapabilities {
5749 #[must_use]
5751 pub fn new() -> Self {
5752 Self::default()
5753 }
5754
5755 #[must_use]
5761 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5762 self.meta = meta.into_option();
5763 self
5764 }
5765}
5766
5767#[cfg(feature = "unstable_session_archive")]
5776#[serde_as]
5777#[skip_serializing_none]
5778#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5779#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5780#[non_exhaustive]
5781pub struct SessionArchiveCapabilities {
5782 #[serde_as(deserialize_as = "DefaultOnError")]
5788 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5789 #[serde(default)]
5790 #[serde(rename = "_meta")]
5791 pub meta: Option<Meta>,
5792}
5793
5794#[cfg(feature = "unstable_session_archive")]
5795impl SessionArchiveCapabilities {
5796 #[must_use]
5798 pub fn new() -> Self {
5799 Self::default()
5800 }
5801
5802 #[must_use]
5808 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5809 self.meta = meta.into_option();
5810 self
5811 }
5812}
5813
5814#[cfg(feature = "unstable_session_status")]
5822#[serde_as]
5823#[skip_serializing_none]
5824#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5825#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5826#[non_exhaustive]
5827pub struct SessionStatusCapabilities {
5828 #[serde_as(deserialize_as = "DefaultOnError")]
5834 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5835 #[serde(default)]
5836 #[serde(rename = "_meta")]
5837 pub meta: Option<Meta>,
5838}
5839
5840#[cfg(feature = "unstable_session_status")]
5841impl SessionStatusCapabilities {
5842 #[must_use]
5844 pub fn new() -> Self {
5845 Self::default()
5846 }
5847
5848 #[must_use]
5854 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5855 self.meta = meta.into_option();
5856 self
5857 }
5858}
5859
5860#[cfg(feature = "unstable_session_set_title")]
5869#[serde_as]
5870#[skip_serializing_none]
5871#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5872#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5873#[non_exhaustive]
5874pub struct SessionTitleCapabilities {
5875 #[serde_as(deserialize_as = "DefaultOnError")]
5881 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5882 #[serde(default)]
5883 #[serde(rename = "_meta")]
5884 pub meta: Option<Meta>,
5885}
5886
5887#[cfg(feature = "unstable_session_set_title")]
5888impl SessionTitleCapabilities {
5889 #[must_use]
5891 pub fn new() -> Self {
5892 Self::default()
5893 }
5894
5895 #[must_use]
5901 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5902 self.meta = meta.into_option();
5903 self
5904 }
5905}
5906
5907#[serde_as]
5911#[skip_serializing_none]
5912#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5913#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5914#[non_exhaustive]
5915pub struct SessionResumeCapabilities {
5916 #[serde_as(deserialize_as = "DefaultOnError")]
5922 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5923 #[serde(default)]
5924 #[serde(rename = "_meta")]
5925 pub meta: Option<Meta>,
5926}
5927
5928impl SessionResumeCapabilities {
5929 #[must_use]
5931 pub fn new() -> Self {
5932 Self::default()
5933 }
5934
5935 #[must_use]
5941 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5942 self.meta = meta.into_option();
5943 self
5944 }
5945}
5946
5947#[serde_as]
5951#[skip_serializing_none]
5952#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5953#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5954#[non_exhaustive]
5955pub struct SessionCloseCapabilities {
5956 #[serde_as(deserialize_as = "DefaultOnError")]
5962 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5963 #[serde(default)]
5964 #[serde(rename = "_meta")]
5965 pub meta: Option<Meta>,
5966}
5967
5968impl SessionCloseCapabilities {
5969 #[must_use]
5971 pub fn new() -> Self {
5972 Self::default()
5973 }
5974
5975 #[must_use]
5981 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5982 self.meta = meta.into_option();
5983 self
5984 }
5985}
5986
5987#[serde_as]
6000#[skip_serializing_none]
6001#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
6002#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
6003#[serde(rename_all = "camelCase")]
6004#[non_exhaustive]
6005pub struct PromptCapabilities {
6006 #[serde_as(deserialize_as = "DefaultOnError")]
6008 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
6009 #[serde(default)]
6010 pub image: bool,
6011 #[serde_as(deserialize_as = "DefaultOnError")]
6013 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
6014 #[serde(default)]
6015 pub audio: bool,
6016 #[serde_as(deserialize_as = "DefaultOnError")]
6021 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
6022 #[serde(default)]
6023 pub embedded_context: bool,
6024 #[serde_as(deserialize_as = "DefaultOnError")]
6030 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
6031 #[serde(default)]
6032 #[serde(rename = "_meta")]
6033 pub meta: Option<Meta>,
6034}
6035
6036impl PromptCapabilities {
6037 #[must_use]
6039 pub fn new() -> Self {
6040 Self::default()
6041 }
6042
6043 #[must_use]
6045 pub fn image(mut self, image: bool) -> Self {
6046 self.image = image;
6047 self
6048 }
6049
6050 #[must_use]
6052 pub fn audio(mut self, audio: bool) -> Self {
6053 self.audio = audio;
6054 self
6055 }
6056
6057 #[must_use]
6062 pub fn embedded_context(mut self, embedded_context: bool) -> Self {
6063 self.embedded_context = embedded_context;
6064 self
6065 }
6066
6067 #[must_use]
6073 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
6074 self.meta = meta.into_option();
6075 self
6076 }
6077}
6078
6079#[serde_as]
6081#[skip_serializing_none]
6082#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
6083#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
6084#[serde(rename_all = "camelCase")]
6085#[non_exhaustive]
6086pub struct McpCapabilities {
6087 #[serde_as(deserialize_as = "DefaultOnError")]
6089 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
6090 #[serde(default)]
6091 pub http: bool,
6092 #[serde_as(deserialize_as = "DefaultOnError")]
6094 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
6095 #[serde(default)]
6096 pub sse: bool,
6097 #[cfg(feature = "unstable_mcp_over_acp")]
6103 #[serde_as(deserialize_as = "DefaultOnError")]
6104 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
6105 #[serde(default)]
6106 pub acp: bool,
6107 #[serde_as(deserialize_as = "DefaultOnError")]
6113 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
6114 #[serde(default)]
6115 #[serde(rename = "_meta")]
6116 pub meta: Option<Meta>,
6117}
6118
6119impl McpCapabilities {
6120 #[must_use]
6122 pub fn new() -> Self {
6123 Self::default()
6124 }
6125
6126 #[must_use]
6128 pub fn http(mut self, http: bool) -> Self {
6129 self.http = http;
6130 self
6131 }
6132
6133 #[must_use]
6135 pub fn sse(mut self, sse: bool) -> Self {
6136 self.sse = sse;
6137 self
6138 }
6139
6140 #[cfg(feature = "unstable_mcp_over_acp")]
6146 #[must_use]
6147 pub fn acp(mut self, acp: bool) -> Self {
6148 self.acp = acp;
6149 self
6150 }
6151
6152 #[must_use]
6158 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
6159 self.meta = meta.into_option();
6160 self
6161 }
6162}
6163
6164#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
6170#[non_exhaustive]
6171pub struct AgentMethodNames {
6172 pub initialize: &'static str,
6174 pub authenticate: &'static str,
6176 #[cfg(feature = "unstable_llm_providers")]
6178 pub providers_list: &'static str,
6179 #[cfg(feature = "unstable_llm_providers")]
6181 pub providers_set: &'static str,
6182 #[cfg(feature = "unstable_llm_providers")]
6184 pub providers_disable: &'static str,
6185 pub session_new: &'static str,
6187 pub session_load: &'static str,
6189 pub session_set_mode: &'static str,
6191 pub session_set_config_option: &'static str,
6193 pub session_prompt: &'static str,
6195 pub session_cancel: &'static str,
6197 #[cfg(feature = "unstable_mcp_over_acp")]
6199 pub mcp_message: &'static str,
6200 pub session_list: &'static str,
6202 pub session_delete: &'static str,
6204 #[cfg(feature = "unstable_session_fork")]
6206 pub session_fork: &'static str,
6207 #[cfg(feature = "unstable_session_archive")]
6209 pub session_archive: &'static str,
6210 #[cfg(feature = "unstable_session_archive")]
6212 pub session_unarchive: &'static str,
6213 #[cfg(feature = "unstable_session_status")]
6215 pub session_status: &'static str,
6216 #[cfg(feature = "unstable_session_set_title")]
6218 pub session_set_title: &'static str,
6219 pub session_resume: &'static str,
6221 pub session_close: &'static str,
6223 pub logout: &'static str,
6225 #[cfg(feature = "unstable_auth_status")]
6227 pub auth_status: &'static str,
6228}
6229
6230pub const AGENT_METHOD_NAMES: AgentMethodNames = AgentMethodNames {
6232 initialize: INITIALIZE_METHOD_NAME,
6233 authenticate: AUTHENTICATE_METHOD_NAME,
6234 #[cfg(feature = "unstable_llm_providers")]
6235 providers_list: PROVIDERS_LIST_METHOD_NAME,
6236 #[cfg(feature = "unstable_llm_providers")]
6237 providers_set: PROVIDERS_SET_METHOD_NAME,
6238 #[cfg(feature = "unstable_llm_providers")]
6239 providers_disable: PROVIDERS_DISABLE_METHOD_NAME,
6240 session_new: SESSION_NEW_METHOD_NAME,
6241 session_load: SESSION_LOAD_METHOD_NAME,
6242 session_set_mode: SESSION_SET_MODE_METHOD_NAME,
6243 session_set_config_option: SESSION_SET_CONFIG_OPTION_METHOD_NAME,
6244 session_prompt: SESSION_PROMPT_METHOD_NAME,
6245 session_cancel: SESSION_CANCEL_METHOD_NAME,
6246 #[cfg(feature = "unstable_mcp_over_acp")]
6247 mcp_message: MCP_MESSAGE_METHOD_NAME,
6248 session_list: SESSION_LIST_METHOD_NAME,
6249 session_delete: SESSION_DELETE_METHOD_NAME,
6250 #[cfg(feature = "unstable_session_fork")]
6251 session_fork: SESSION_FORK_METHOD_NAME,
6252 #[cfg(feature = "unstable_session_archive")]
6253 session_archive: SESSION_ARCHIVE_METHOD_NAME,
6254 #[cfg(feature = "unstable_session_archive")]
6255 session_unarchive: SESSION_UNARCHIVE_METHOD_NAME,
6256 #[cfg(feature = "unstable_session_status")]
6257 session_status: SESSION_STATUS_METHOD_NAME,
6258 #[cfg(feature = "unstable_session_set_title")]
6259 session_set_title: SESSION_SET_TITLE_METHOD_NAME,
6260 session_resume: SESSION_RESUME_METHOD_NAME,
6261 session_close: SESSION_CLOSE_METHOD_NAME,
6262 logout: LOGOUT_METHOD_NAME,
6263 #[cfg(feature = "unstable_auth_status")]
6264 auth_status: AUTH_STATUS_METHOD_NAME,
6265};
6266
6267pub(crate) const INITIALIZE_METHOD_NAME: &str = "initialize";
6269pub(crate) const AUTHENTICATE_METHOD_NAME: &str = "authenticate";
6271#[cfg(feature = "unstable_llm_providers")]
6273pub(crate) const PROVIDERS_LIST_METHOD_NAME: &str = "providers/list";
6274#[cfg(feature = "unstable_llm_providers")]
6276pub(crate) const PROVIDERS_SET_METHOD_NAME: &str = "providers/set";
6277#[cfg(feature = "unstable_llm_providers")]
6279pub(crate) const PROVIDERS_DISABLE_METHOD_NAME: &str = "providers/disable";
6280pub(crate) const SESSION_NEW_METHOD_NAME: &str = "session/new";
6282pub(crate) const SESSION_LOAD_METHOD_NAME: &str = "session/load";
6284pub(crate) const SESSION_SET_MODE_METHOD_NAME: &str = "session/set_mode";
6286pub(crate) const SESSION_SET_CONFIG_OPTION_METHOD_NAME: &str = "session/set_config_option";
6288pub(crate) const SESSION_PROMPT_METHOD_NAME: &str = "session/prompt";
6290pub(crate) const SESSION_CANCEL_METHOD_NAME: &str = "session/cancel";
6292pub(crate) const SESSION_LIST_METHOD_NAME: &str = "session/list";
6294pub(crate) const SESSION_DELETE_METHOD_NAME: &str = "session/delete";
6296#[cfg(feature = "unstable_session_fork")]
6298pub(crate) const SESSION_FORK_METHOD_NAME: &str = "session/fork";
6299#[cfg(feature = "unstable_session_archive")]
6301pub(crate) const SESSION_ARCHIVE_METHOD_NAME: &str = "session/archive";
6302#[cfg(feature = "unstable_session_archive")]
6304pub(crate) const SESSION_UNARCHIVE_METHOD_NAME: &str = "session/unarchive";
6305#[cfg(feature = "unstable_session_status")]
6307pub(crate) const SESSION_STATUS_METHOD_NAME: &str = "session/status";
6308#[cfg(feature = "unstable_session_set_title")]
6310pub(crate) const SESSION_SET_TITLE_METHOD_NAME: &str = "session/set_title";
6311pub(crate) const SESSION_RESUME_METHOD_NAME: &str = "session/resume";
6313pub(crate) const SESSION_CLOSE_METHOD_NAME: &str = "session/close";
6315pub(crate) const LOGOUT_METHOD_NAME: &str = "logout";
6317#[cfg(feature = "unstable_auth_status")]
6319pub(crate) const AUTH_STATUS_METHOD_NAME: &str = "auth/status";
6320
6321#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
6328#[derive(Clone, Debug, Serialize, Deserialize)]
6329#[serde(untagged)]
6330#[cfg_attr(feature = "schemars", schemars(inline))]
6331#[non_exhaustive]
6332#[allow(clippy::large_enum_variant)]
6333pub enum ClientRequest {
6334 InitializeRequest(InitializeRequest),
6345 AuthenticateRequest(AuthenticateRequest),
6356 #[cfg(feature = "unstable_llm_providers")]
6362 ListProvidersRequest(ListProvidersRequest),
6363 #[cfg(feature = "unstable_llm_providers")]
6369 SetProviderRequest(SetProviderRequest),
6370 #[cfg(feature = "unstable_llm_providers")]
6376 DisableProviderRequest(DisableProviderRequest),
6377 LogoutRequest(LogoutRequest),
6382 #[cfg(feature = "unstable_auth_status")]
6391 AuthStatusRequest(AuthStatusRequest),
6392 NewSessionRequest(NewSessionRequest),
6405 LoadSessionRequest(LoadSessionRequest),
6416 ListSessionsRequest(ListSessionsRequest),
6422 DeleteSessionRequest(DeleteSessionRequest),
6426 #[cfg(feature = "unstable_session_fork")]
6427 ForkSessionRequest(ForkSessionRequest),
6443 #[cfg(feature = "unstable_session_archive")]
6444 ArchiveSessionRequest(ArchiveSessionRequest),
6452 #[cfg(feature = "unstable_session_archive")]
6453 UnarchiveSessionRequest(UnarchiveSessionRequest),
6461 #[cfg(feature = "unstable_session_status")]
6462 SessionStatusRequest(SessionStatusRequest),
6470 #[cfg(feature = "unstable_session_set_title")]
6471 SetSessionTitleRequest(SetSessionTitleRequest),
6482 ResumeSessionRequest(ResumeSessionRequest),
6489 CloseSessionRequest(CloseSessionRequest),
6496 SetSessionModeRequest(SetSessionModeRequest),
6510 SetSessionConfigOptionRequest(SetSessionConfigOptionRequest),
6512 PromptRequest(PromptRequest),
6524 ExtMethodRequest(ExtRequest),
6531}
6532
6533impl ClientRequest {
6534 #[must_use]
6536 pub fn method(&self) -> &str {
6537 match self {
6538 Self::InitializeRequest(_) => AGENT_METHOD_NAMES.initialize,
6539 Self::AuthenticateRequest(_) => AGENT_METHOD_NAMES.authenticate,
6540 #[cfg(feature = "unstable_llm_providers")]
6541 Self::ListProvidersRequest(_) => AGENT_METHOD_NAMES.providers_list,
6542 #[cfg(feature = "unstable_llm_providers")]
6543 Self::SetProviderRequest(_) => AGENT_METHOD_NAMES.providers_set,
6544 #[cfg(feature = "unstable_llm_providers")]
6545 Self::DisableProviderRequest(_) => AGENT_METHOD_NAMES.providers_disable,
6546 Self::LogoutRequest(_) => AGENT_METHOD_NAMES.logout,
6547 #[cfg(feature = "unstable_auth_status")]
6548 Self::AuthStatusRequest(_) => AGENT_METHOD_NAMES.auth_status,
6549 Self::NewSessionRequest(_) => AGENT_METHOD_NAMES.session_new,
6550 Self::LoadSessionRequest(_) => AGENT_METHOD_NAMES.session_load,
6551 Self::ListSessionsRequest(_) => AGENT_METHOD_NAMES.session_list,
6552 Self::DeleteSessionRequest(_) => AGENT_METHOD_NAMES.session_delete,
6553 #[cfg(feature = "unstable_session_fork")]
6554 Self::ForkSessionRequest(_) => AGENT_METHOD_NAMES.session_fork,
6555 #[cfg(feature = "unstable_session_archive")]
6556 Self::ArchiveSessionRequest(_) => AGENT_METHOD_NAMES.session_archive,
6557 #[cfg(feature = "unstable_session_archive")]
6558 Self::UnarchiveSessionRequest(_) => AGENT_METHOD_NAMES.session_unarchive,
6559 #[cfg(feature = "unstable_session_status")]
6560 Self::SessionStatusRequest(_) => AGENT_METHOD_NAMES.session_status,
6561 #[cfg(feature = "unstable_session_set_title")]
6562 Self::SetSessionTitleRequest(_) => AGENT_METHOD_NAMES.session_set_title,
6563 Self::ResumeSessionRequest(_) => AGENT_METHOD_NAMES.session_resume,
6564 Self::CloseSessionRequest(_) => AGENT_METHOD_NAMES.session_close,
6565 Self::SetSessionModeRequest(_) => AGENT_METHOD_NAMES.session_set_mode,
6566 Self::SetSessionConfigOptionRequest(_) => AGENT_METHOD_NAMES.session_set_config_option,
6567 Self::PromptRequest(_) => AGENT_METHOD_NAMES.session_prompt,
6568 Self::ExtMethodRequest(ext_request) => &ext_request.method,
6569 }
6570 }
6571}
6572
6573#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
6580#[derive(Clone, Debug, Serialize, Deserialize)]
6581#[serde(untagged)]
6582#[cfg_attr(feature = "schemars", schemars(inline))]
6583#[non_exhaustive]
6584#[allow(clippy::large_enum_variant)]
6585pub enum AgentResponse {
6586 InitializeResponse(InitializeResponse),
6588 AuthenticateResponse(#[serde(default)] AuthenticateResponse),
6590 #[cfg(feature = "unstable_llm_providers")]
6592 ListProvidersResponse(ListProvidersResponse),
6593 #[cfg(feature = "unstable_llm_providers")]
6595 SetProviderResponse(#[serde(default)] SetProviderResponse),
6596 #[cfg(feature = "unstable_llm_providers")]
6598 DisableProviderResponse(#[serde(default)] DisableProviderResponse),
6599 LogoutResponse(#[serde(default)] LogoutResponse),
6601 #[cfg(feature = "unstable_auth_status")]
6603 AuthStatusResponse(AuthStatusResponse),
6604 NewSessionResponse(NewSessionResponse),
6606 LoadSessionResponse(#[serde(default)] LoadSessionResponse),
6608 ListSessionsResponse(ListSessionsResponse),
6610 DeleteSessionResponse(#[serde(default)] DeleteSessionResponse),
6612 #[cfg(feature = "unstable_session_fork")]
6614 ForkSessionResponse(ForkSessionResponse),
6615 #[cfg(feature = "unstable_session_archive")]
6617 ArchiveSessionResponse(#[serde(default)] ArchiveSessionResponse),
6618 #[cfg(feature = "unstable_session_archive")]
6620 UnarchiveSessionResponse(#[serde(default)] UnarchiveSessionResponse),
6621 #[cfg(feature = "unstable_session_status")]
6623 SessionStatusResponse(SessionStatusResponse),
6624 #[cfg(feature = "unstable_session_set_title")]
6626 SetSessionTitleResponse(SetSessionTitleResponse),
6627 ResumeSessionResponse(#[serde(default)] ResumeSessionResponse),
6629 CloseSessionResponse(#[serde(default)] CloseSessionResponse),
6631 SetSessionModeResponse(#[serde(default)] SetSessionModeResponse),
6633 SetSessionConfigOptionResponse(SetSessionConfigOptionResponse),
6635 PromptResponse(PromptResponse),
6637 ExtMethodResponse(ExtResponse),
6639}
6640
6641#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
6648#[derive(Clone, Debug, Serialize, Deserialize)]
6649#[serde(untagged)]
6650#[cfg_attr(feature = "schemars", schemars(inline))]
6651#[non_exhaustive]
6652#[allow(clippy::large_enum_variant)]
6653pub enum ClientNotification {
6654 CancelNotification(CancelNotification),
6666 #[cfg(feature = "unstable_mcp_over_acp")]
6672 MessageMcpNotification(MessageMcpNotification),
6673 ExtNotification(ExtNotification),
6680}
6681
6682impl ClientNotification {
6683 #[must_use]
6685 pub fn method(&self) -> &str {
6686 match self {
6687 Self::CancelNotification(_) => AGENT_METHOD_NAMES.session_cancel,
6688 #[cfg(feature = "unstable_mcp_over_acp")]
6689 Self::MessageMcpNotification(_) => AGENT_METHOD_NAMES.mcp_message,
6690 Self::ExtNotification(ext_notification) => &ext_notification.method,
6691 }
6692 }
6693}
6694
6695#[serde_as]
6699#[skip_serializing_none]
6700#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
6701#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
6702#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_CANCEL_METHOD_NAME)))]
6703#[serde(rename_all = "camelCase")]
6704#[non_exhaustive]
6705pub struct CancelNotification {
6706 pub session_id: SessionId,
6708 #[serde_as(deserialize_as = "DefaultOnError")]
6714 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
6715 #[serde(default)]
6716 #[serde(rename = "_meta")]
6717 pub meta: Option<Meta>,
6718}
6719
6720impl CancelNotification {
6721 #[must_use]
6723 pub fn new(session_id: impl Into<SessionId>) -> Self {
6724 Self {
6725 session_id: session_id.into(),
6726 meta: None,
6727 }
6728 }
6729
6730 #[must_use]
6736 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
6737 self.meta = meta.into_option();
6738 self
6739 }
6740}
6741
6742#[cfg(test)]
6743mod test_serialization {
6744 use super::*;
6745 use serde_json::json;
6746
6747 fn test_meta() -> Meta {
6748 json!({ "source": "test" }).as_object().unwrap().clone()
6749 }
6750
6751 fn serialized_meta_key_count(value: &impl serde::Serialize) -> usize {
6752 serde_json::to_string(value)
6753 .unwrap()
6754 .matches("\"_meta\"")
6755 .count()
6756 }
6757
6758 #[test]
6761 fn prompt_response_has_no_error_stop_reason() {
6762 assert_eq!(
6763 serde_json::from_value::<PromptResponse>(json!({ "stopReason": "end_turn" }))
6764 .unwrap()
6765 .stop_reason,
6766 StopReason::EndTurn
6767 );
6768 assert!(
6769 serde_json::from_value::<PromptResponse>(json!({ "stopReason": "error" })).is_err()
6770 );
6771 }
6772
6773 #[test]
6774 fn test_initialize_capabilities_default_on_malformed_values() {
6775 let request: InitializeRequest = serde_json::from_value(json!({
6776 "protocolVersion": 1,
6777 "clientCapabilities": false
6778 }))
6779 .unwrap();
6780 assert_eq!(request.client_capabilities, ClientCapabilities::default());
6781
6782 let response: InitializeResponse = serde_json::from_value(json!({
6783 "protocolVersion": 1,
6784 "agentCapabilities": false
6785 }))
6786 .unwrap();
6787 assert_eq!(response.agent_capabilities, AgentCapabilities::default());
6788 }
6789
6790 #[test]
6791 fn test_agent_capabilities_default_on_malformed_values() {
6792 let capabilities: AgentCapabilities = serde_json::from_value(json!({
6793 "loadSession": "yes",
6794 "promptCapabilities": {
6795 "image": "yes",
6796 "audio": true,
6797 "embeddedContext": {}
6798 },
6799 "mcpCapabilities": {
6800 "http": "yes",
6801 "sse": true
6802 },
6803 "sessionCapabilities": false,
6804 "auth": false
6805 }))
6806 .unwrap();
6807
6808 assert!(!capabilities.load_session);
6809 assert!(!capabilities.prompt_capabilities.image);
6810 assert!(capabilities.prompt_capabilities.audio);
6811 assert!(!capabilities.prompt_capabilities.embedded_context);
6812 assert!(!capabilities.mcp_capabilities.http);
6813 assert!(capabilities.mcp_capabilities.sse);
6814 assert_eq!(
6815 capabilities.session_capabilities,
6816 SessionCapabilities::default()
6817 );
6818 assert_eq!(capabilities.auth, AgentAuthCapabilities::default());
6819 }
6820
6821 #[test]
6822 fn test_mcp_server_stdio_serialization() {
6823 let server = McpServer::Stdio(
6824 McpServerStdio::new("test-server", "/usr/bin/server")
6825 .args(vec!["--port".to_string(), "3000".to_string()])
6826 .env(vec![EnvVariable::new("API_KEY", "secret123")]),
6827 );
6828
6829 let json = serde_json::to_value(&server).unwrap();
6830 assert_eq!(
6831 json,
6832 json!({
6833 "name": "test-server",
6834 "command": "/usr/bin/server",
6835 "args": ["--port", "3000"],
6836 "env": [
6837 {
6838 "name": "API_KEY",
6839 "value": "secret123"
6840 }
6841 ]
6842 })
6843 );
6844
6845 let deserialized: McpServer = serde_json::from_value(json).unwrap();
6846 match deserialized {
6847 McpServer::Stdio(McpServerStdio {
6848 name,
6849 command,
6850 args,
6851 env,
6852 meta: _,
6853 }) => {
6854 assert_eq!(name, "test-server");
6855 assert_eq!(command, PathBuf::from("/usr/bin/server"));
6856 assert_eq!(args, vec!["--port", "3000"]);
6857 assert_eq!(env.len(), 1);
6858 assert_eq!(env[0].name, "API_KEY");
6859 assert_eq!(env[0].value, "secret123");
6860 }
6861 _ => panic!("Expected Stdio variant"),
6862 }
6863 }
6864
6865 #[test]
6866 fn test_mcp_server_http_serialization() {
6867 let server = McpServer::Http(
6868 McpServerHttp::new("http-server", "https://api.example.com").headers(vec![
6869 HttpHeader::new("Authorization", "Bearer token123"),
6870 HttpHeader::new("Content-Type", "application/json"),
6871 ]),
6872 );
6873
6874 let json = serde_json::to_value(&server).unwrap();
6875 assert_eq!(
6876 json,
6877 json!({
6878 "type": "http",
6879 "name": "http-server",
6880 "url": "https://api.example.com",
6881 "headers": [
6882 {
6883 "name": "Authorization",
6884 "value": "Bearer token123"
6885 },
6886 {
6887 "name": "Content-Type",
6888 "value": "application/json"
6889 }
6890 ]
6891 })
6892 );
6893
6894 let deserialized: McpServer = serde_json::from_value(json).unwrap();
6895 match deserialized {
6896 McpServer::Http(McpServerHttp {
6897 name,
6898 url,
6899 headers,
6900 meta: _,
6901 }) => {
6902 assert_eq!(name, "http-server");
6903 assert_eq!(url, "https://api.example.com");
6904 assert_eq!(headers.len(), 2);
6905 assert_eq!(headers[0].name, "Authorization");
6906 assert_eq!(headers[0].value, "Bearer token123");
6907 assert_eq!(headers[1].name, "Content-Type");
6908 assert_eq!(headers[1].value, "application/json");
6909 }
6910 _ => panic!("Expected Http variant"),
6911 }
6912 }
6913
6914 #[cfg(feature = "unstable_mcp_over_acp")]
6915 #[test]
6916 fn test_mcp_server_acp_serialization() {
6917 let server = McpServer::Acp(McpServerAcp::new("project-tools", "project-tools-id"));
6918
6919 let json = serde_json::to_value(&server).unwrap();
6920 assert_eq!(
6921 json,
6922 json!({
6923 "type": "acp",
6924 "name": "project-tools",
6925 "serverId": "project-tools-id"
6926 })
6927 );
6928
6929 let deserialized: McpServer = serde_json::from_value(json).unwrap();
6930 match deserialized {
6931 McpServer::Acp(McpServerAcp {
6932 name,
6933 server_id: id,
6934 meta: _,
6935 }) => {
6936 assert_eq!(name, "project-tools");
6937 assert_eq!(id, McpServerAcpId::new("project-tools-id"));
6938 }
6939 _ => panic!("Expected Acp variant"),
6940 }
6941 }
6942
6943 #[cfg(feature = "unstable_mcp_over_acp")]
6944 #[test]
6945 fn test_client_mcp_message_method_names() {
6946 use serde_json::json;
6947
6948 assert_eq!(AGENT_METHOD_NAMES.mcp_message, "mcp/message");
6949
6950 let notification =
6951 MessageMcpNotification::new("server-1", "req-1", "notifications/progress");
6952 assert_eq!(
6953 ClientNotification::MessageMcpNotification(notification.clone()).method(),
6954 "mcp/message"
6955 );
6956 assert_eq!(
6957 serde_json::to_value(notification).unwrap(),
6958 json!({
6959 "serverId": "server-1",
6960 "requestId": "req-1",
6961 "method": "notifications/progress"
6962 })
6963 );
6964 let notification: MessageMcpNotification = serde_json::from_value(json!({
6965 "serverId": "server-1", "requestId": "req-1", "method": "notifications/progress",
6966 "params": null, "_meta": null
6967 }))
6968 .unwrap();
6969 assert_eq!(notification.params, None);
6970 assert_eq!(notification.meta, None);
6971 for key in ["serverId", "requestId", "method"] {
6972 let mut value = json!({"serverId":"server-1", "requestId":"req-1", "method":"notifications/progress"});
6973 value.as_object_mut().unwrap().remove(key);
6974 assert!(serde_json::from_value::<MessageMcpNotification>(value).is_err());
6975 }
6976 }
6977
6978 #[cfg(all(feature = "unstable_mcp_over_acp", feature = "schemars"))]
6979 #[test]
6980 fn test_mcp_server_acp_schema() {
6981 let mcp_server_schema = serde_json::to_value(schemars::schema_for!(McpServer)).unwrap();
6982 assert!(json_contains_entry(
6983 &mcp_server_schema,
6984 "const",
6985 &json!("acp")
6986 ));
6987 assert!(json_contains_entry(
6988 &mcp_server_schema,
6989 "$ref",
6990 &json!("#/$defs/McpServerAcp")
6991 ));
6992
6993 let capabilities_schema =
6994 serde_json::to_value(schemars::schema_for!(McpCapabilities)).unwrap();
6995 assert!(json_contains_key(&capabilities_schema, "acp"));
6996 }
6997
6998 #[cfg(all(feature = "unstable_mcp_over_acp", feature = "schemars"))]
6999 fn json_contains_entry(
7000 value: &serde_json::Value,
7001 key: &str,
7002 expected: &serde_json::Value,
7003 ) -> bool {
7004 match value {
7005 serde_json::Value::Object(map) => {
7006 map.get(key) == Some(expected)
7007 || map
7008 .values()
7009 .any(|value| json_contains_entry(value, key, expected))
7010 }
7011 serde_json::Value::Array(values) => values
7012 .iter()
7013 .any(|value| json_contains_entry(value, key, expected)),
7014 _ => false,
7015 }
7016 }
7017
7018 #[cfg(all(feature = "unstable_mcp_over_acp", feature = "schemars"))]
7019 fn json_contains_key(value: &serde_json::Value, key: &str) -> bool {
7020 match value {
7021 serde_json::Value::Object(map) => {
7022 map.contains_key(key) || map.values().any(|value| json_contains_key(value, key))
7023 }
7024 serde_json::Value::Array(values) => {
7025 values.iter().any(|value| json_contains_key(value, key))
7026 }
7027 _ => false,
7028 }
7029 }
7030
7031 #[test]
7032 fn test_mcp_server_sse_serialization() {
7033 let server = McpServer::Sse(
7034 McpServerSse::new("sse-server", "https://sse.example.com/events")
7035 .headers(vec![HttpHeader::new("X-API-Key", "apikey456")]),
7036 );
7037
7038 let json = serde_json::to_value(&server).unwrap();
7039 assert_eq!(
7040 json,
7041 json!({
7042 "type": "sse",
7043 "name": "sse-server",
7044 "url": "https://sse.example.com/events",
7045 "headers": [
7046 {
7047 "name": "X-API-Key",
7048 "value": "apikey456"
7049 }
7050 ]
7051 })
7052 );
7053
7054 let deserialized: McpServer = serde_json::from_value(json).unwrap();
7055 match deserialized {
7056 McpServer::Sse(McpServerSse {
7057 name,
7058 url,
7059 headers,
7060 meta: _,
7061 }) => {
7062 assert_eq!(name, "sse-server");
7063 assert_eq!(url, "https://sse.example.com/events");
7064 assert_eq!(headers.len(), 1);
7065 assert_eq!(headers[0].name, "X-API-Key");
7066 assert_eq!(headers[0].value, "apikey456");
7067 }
7068 _ => panic!("Expected Sse variant"),
7069 }
7070 }
7071
7072 #[test]
7073 fn test_session_config_option_category_known_variants() {
7074 assert_eq!(
7076 serde_json::to_value(&SessionConfigOptionCategory::Mode).unwrap(),
7077 json!("mode")
7078 );
7079 assert_eq!(
7080 serde_json::to_value(&SessionConfigOptionCategory::Model).unwrap(),
7081 json!("model")
7082 );
7083 assert_eq!(
7084 serde_json::to_value(&SessionConfigOptionCategory::ModelConfig).unwrap(),
7085 json!("model_config")
7086 );
7087 assert_eq!(
7088 serde_json::to_value(&SessionConfigOptionCategory::ThoughtLevel).unwrap(),
7089 json!("thought_level")
7090 );
7091
7092 assert_eq!(
7094 serde_json::from_str::<SessionConfigOptionCategory>("\"mode\"").unwrap(),
7095 SessionConfigOptionCategory::Mode
7096 );
7097 assert_eq!(
7098 serde_json::from_str::<SessionConfigOptionCategory>("\"model\"").unwrap(),
7099 SessionConfigOptionCategory::Model
7100 );
7101 assert_eq!(
7102 serde_json::from_str::<SessionConfigOptionCategory>("\"model_config\"").unwrap(),
7103 SessionConfigOptionCategory::ModelConfig
7104 );
7105 assert_eq!(
7106 serde_json::from_str::<SessionConfigOptionCategory>("\"thought_level\"").unwrap(),
7107 SessionConfigOptionCategory::ThoughtLevel
7108 );
7109 }
7110
7111 #[test]
7112 fn test_session_config_option_category_unknown_variants() {
7113 let unknown: SessionConfigOptionCategory =
7115 serde_json::from_str("\"some_future_category\"").unwrap();
7116 assert_eq!(
7117 unknown,
7118 SessionConfigOptionCategory::Other("some_future_category".to_string())
7119 );
7120
7121 let json = serde_json::to_value(&unknown).unwrap();
7123 assert_eq!(json, json!("some_future_category"));
7124 }
7125
7126 #[test]
7127 fn test_session_config_option_category_custom_categories() {
7128 let custom: SessionConfigOptionCategory =
7130 serde_json::from_str("\"_my_custom_category\"").unwrap();
7131 assert_eq!(
7132 custom,
7133 SessionConfigOptionCategory::Other("_my_custom_category".to_string())
7134 );
7135
7136 let json = serde_json::to_value(&custom).unwrap();
7138 assert_eq!(json, json!("_my_custom_category"));
7139
7140 let deserialized: SessionConfigOptionCategory = serde_json::from_value(json).unwrap();
7142 assert_eq!(
7143 deserialized,
7144 SessionConfigOptionCategory::Other("_my_custom_category".to_string()),
7145 );
7146 }
7147
7148 #[test]
7149 fn test_auth_method_agent_serialization() {
7150 let method = AuthMethod::Agent(AuthMethodAgent::new("default-auth", "Default Auth"));
7151
7152 let json = serde_json::to_value(&method).unwrap();
7153 assert_eq!(
7154 json,
7155 json!({
7156 "id": "default-auth",
7157 "name": "Default Auth"
7158 })
7159 );
7160 assert!(!json.as_object().unwrap().contains_key("description"));
7162 assert!(!json.as_object().unwrap().contains_key("type"));
7164
7165 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
7166 match deserialized {
7167 AuthMethod::Agent(AuthMethodAgent { id, name, .. }) => {
7168 assert_eq!(id.0.as_ref(), "default-auth");
7169 assert_eq!(name, "Default Auth");
7170 }
7171 _ => panic!("Expected Agent variant"),
7172 }
7173 }
7174
7175 #[test]
7176 fn test_auth_method_explicit_agent_deserialization() {
7177 let json = json!({
7179 "id": "agent-auth",
7180 "name": "Agent Auth",
7181 "type": "agent"
7182 });
7183
7184 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
7185 assert!(matches!(deserialized, AuthMethod::Agent(_)));
7186 }
7187
7188 #[test]
7189 fn test_session_delete_serialization() {
7190 assert_eq!(AGENT_METHOD_NAMES.session_delete, "session/delete");
7191 assert_eq!(
7192 ClientRequest::DeleteSessionRequest(DeleteSessionRequest::new("sess_abc123")).method(),
7193 "session/delete"
7194 );
7195 assert_eq!(
7196 serde_json::to_value(DeleteSessionRequest::new("sess_abc123")).unwrap(),
7197 json!({
7198 "sessionId": "sess_abc123"
7199 })
7200 );
7201 assert_eq!(
7202 serde_json::to_value(DeleteSessionResponse::new()).unwrap(),
7203 json!({})
7204 );
7205 assert_eq!(
7206 serde_json::to_value(
7207 SessionCapabilities::new().delete(SessionDeleteCapabilities::new())
7208 )
7209 .unwrap(),
7210 json!({
7211 "delete": {}
7212 })
7213 );
7214 }
7215 #[cfg(feature = "unstable_session_set_title")]
7216 #[test]
7217 fn test_session_set_title_serialization() {
7218 assert_eq!(AGENT_METHOD_NAMES.session_set_title, "session/set_title");
7219 assert_eq!(
7220 ClientRequest::SetSessionTitleRequest(SetSessionTitleRequest::new(
7221 "sess_abc123",
7222 "Investigate OAuth timeout"
7223 ))
7224 .method(),
7225 "session/set_title"
7226 );
7227 assert_eq!(
7228 serde_json::to_value(SetSessionTitleRequest::new(
7229 "sess_abc123",
7230 "Investigate OAuth timeout"
7231 ))
7232 .unwrap(),
7233 json!({
7234 "sessionId": "sess_abc123",
7235 "title": "Investigate OAuth timeout"
7236 })
7237 );
7238 assert_eq!(
7239 serde_json::to_value(SetSessionTitleResponse::new("Investigate OAuth timeout"))
7240 .unwrap(),
7241 json!({
7242 "title": "Investigate OAuth timeout"
7243 })
7244 );
7245 assert_eq!(
7246 serde_json::to_value(SessionCapabilities::new().title(SessionTitleCapabilities::new()))
7247 .unwrap(),
7248 json!({
7249 "title": {}
7250 })
7251 );
7252 }
7253
7254 #[cfg(feature = "unstable_session_set_title")]
7255 #[test]
7256 fn test_session_set_title_requires_title() {
7257 for params in [
7258 json!({"sessionId": "sess_abc123"}),
7259 json!({"sessionId": "sess_abc123", "title": null}),
7260 json!({"sessionId": "sess_abc123", "title": 42}),
7261 ] {
7262 assert!(serde_json::from_value::<SetSessionTitleRequest>(params).is_err());
7263 }
7264 for result in [json!({}), json!({"title": null})] {
7265 assert!(serde_json::from_value::<SetSessionTitleResponse>(result).is_err());
7266 }
7267 }
7268
7269 #[cfg(feature = "unstable_session_status")]
7270 #[test]
7271 fn test_session_status_serialization() {
7272 assert_eq!(AGENT_METHOD_NAMES.session_status, "session/status");
7273 assert_eq!(
7274 ClientRequest::SessionStatusRequest(SessionStatusRequest::new("sess_abc123")).method(),
7275 "session/status"
7276 );
7277 assert_eq!(
7278 serde_json::to_value(SessionStatusRequest::new("sess_abc123")).unwrap(),
7279 json!({"sessionId": "sess_abc123"})
7280 );
7281 assert_eq!(
7282 serde_json::to_value(SessionStatusResponse::new(SessionStatus::Saved)).unwrap(),
7283 json!({"status": "saved"})
7284 );
7285 assert_eq!(
7286 serde_json::to_value(
7287 SessionCapabilities::new().status(SessionStatusCapabilities::new())
7288 )
7289 .unwrap(),
7290 json!({"status": {}})
7291 );
7292 }
7293
7294 #[cfg(feature = "unstable_session_status")]
7295 #[test]
7296 fn test_session_status_is_strict_and_open() {
7297 let custom =
7298 serde_json::from_value::<SessionStatusResponse>(json!({"status": "_suspended"}))
7299 .unwrap();
7300 assert_eq!(
7301 custom.status,
7302 SessionStatus::Other("_suspended".to_string())
7303 );
7304 assert_eq!(
7305 serde_json::to_value(&custom).unwrap(),
7306 json!({"status": "_suspended"})
7307 );
7308 for result in [json!({}), json!({"status": null}), json!({"status": 1})] {
7309 assert!(serde_json::from_value::<SessionStatusResponse>(result).is_err());
7310 }
7311 for params in [json!({}), json!({"sessionId": null})] {
7312 assert!(serde_json::from_value::<SessionStatusRequest>(params).is_err());
7313 }
7314 }
7315
7316 #[cfg(feature = "unstable_session_archive")]
7317 #[test]
7318 fn test_session_archive_serialization() {
7319 assert_eq!(AGENT_METHOD_NAMES.session_archive, "session/archive");
7320 assert_eq!(AGENT_METHOD_NAMES.session_unarchive, "session/unarchive");
7321 assert_eq!(
7322 ClientRequest::ArchiveSessionRequest(ArchiveSessionRequest::new("sess_abc123"))
7323 .method(),
7324 "session/archive"
7325 );
7326 assert_eq!(
7327 ClientRequest::UnarchiveSessionRequest(UnarchiveSessionRequest::new("sess_abc123"))
7328 .method(),
7329 "session/unarchive"
7330 );
7331 assert_eq!(
7332 serde_json::to_value(ArchiveSessionRequest::new("sess_abc123")).unwrap(),
7333 json!({"sessionId": "sess_abc123"})
7334 );
7335 assert_eq!(
7336 serde_json::to_value(UnarchiveSessionResponse::new()).unwrap(),
7337 json!({})
7338 );
7339 assert_eq!(
7340 serde_json::to_value(
7341 SessionCapabilities::new().archive(SessionArchiveCapabilities::new())
7342 )
7343 .unwrap(),
7344 json!({"archive": {}})
7345 );
7346 assert_eq!(
7347 serde_json::to_value(
7348 ListSessionsRequest::new()
7349 .cwd("/home/user/project")
7350 .archived(SessionArchiveFilter::Only)
7351 )
7352 .unwrap(),
7353 json!({"cwd": "/home/user/project", "archived": "only"})
7354 );
7355 assert_eq!(
7356 serde_json::to_value(
7357 SessionInfo::new("sess_abc123", "/home/user/project").archived(true)
7358 )
7359 .unwrap(),
7360 json!({"sessionId": "sess_abc123", "cwd": "/home/user/project", "archived": true})
7361 );
7362 }
7363
7364 #[cfg(feature = "unstable_session_archive")]
7365 #[test]
7366 fn test_session_archive_filter_is_strict_and_open() {
7367 for (value, expected) in [
7368 (json!(null), None),
7369 (json!("include"), Some(SessionArchiveFilter::Include)),
7370 (
7371 json!("_recent"),
7372 Some(SessionArchiveFilter::Other("_recent".to_string())),
7373 ),
7374 ] {
7375 let request =
7376 serde_json::from_value::<ListSessionsRequest>(json!({"archived": value})).unwrap();
7377 assert_eq!(request.archived, expected);
7378 }
7379 for value in [json!(true), json!(1), json!({})] {
7380 assert!(
7381 serde_json::from_value::<ListSessionsRequest>(json!({"archived": value})).is_err()
7382 );
7383 }
7384 let info = serde_json::from_value::<SessionInfo>(
7385 json!({"sessionId": "sess_abc123", "cwd": "/home/user/project", "archived": "yes"}),
7386 )
7387 .unwrap();
7388 assert_eq!(info.archived, None);
7389 }
7390
7391 #[test]
7392 fn test_session_additional_directories_serialization() {
7393 assert_eq!(
7394 serde_json::to_value(NewSessionRequest::new("/home/user/project")).unwrap(),
7395 json!({
7396 "cwd": "/home/user/project",
7397 "mcpServers": []
7398 })
7399 );
7400 assert_eq!(
7401 serde_json::to_value(
7402 NewSessionRequest::new("/home/user/project").additional_directories(vec![
7403 PathBuf::from("/home/user/shared-lib"),
7404 PathBuf::from("/home/user/product-docs"),
7405 ])
7406 )
7407 .unwrap(),
7408 json!({
7409 "cwd": "/home/user/project",
7410 "additionalDirectories": [
7411 "/home/user/shared-lib",
7412 "/home/user/product-docs"
7413 ],
7414 "mcpServers": []
7415 })
7416 );
7417 assert_eq!(
7418 serde_json::to_value(SessionInfo::new("sess_abc123", "/home/user/project")).unwrap(),
7419 json!({
7420 "sessionId": "sess_abc123",
7421 "cwd": "/home/user/project"
7422 })
7423 );
7424 assert_eq!(
7425 serde_json::to_value(
7426 SessionInfo::new("sess_abc123", "/home/user/project").additional_directories(vec![
7427 PathBuf::from("/home/user/shared-lib"),
7428 PathBuf::from("/home/user/product-docs"),
7429 ])
7430 )
7431 .unwrap(),
7432 json!({
7433 "sessionId": "sess_abc123",
7434 "cwd": "/home/user/project",
7435 "additionalDirectories": [
7436 "/home/user/shared-lib",
7437 "/home/user/product-docs"
7438 ]
7439 })
7440 );
7441 assert_eq!(
7442 serde_json::from_value::<SessionInfo>(json!({
7443 "sessionId": "sess_abc123",
7444 "cwd": "/home/user/project"
7445 }))
7446 .unwrap()
7447 .additional_directories,
7448 Vec::<PathBuf>::new()
7449 );
7450 }
7451 #[test]
7452 fn test_session_additional_directories_capabilities_serialization() {
7453 assert_eq!(
7454 serde_json::to_value(
7455 SessionCapabilities::new()
7456 .additional_directories(SessionAdditionalDirectoriesCapabilities::new())
7457 )
7458 .unwrap(),
7459 json!({
7460 "additionalDirectories": {}
7461 })
7462 );
7463 }
7464
7465 #[test]
7466 fn test_session_system_prompt_capabilities_serialization() {
7467 assert_eq!(
7468 serde_json::to_value(
7469 SessionCapabilities::new().system_prompt(SessionSystemPromptCapabilities::new())
7470 )
7471 .unwrap(),
7472 json!({ "systemPrompt": {} })
7473 );
7474 assert_eq!(
7475 serde_json::to_value(
7476 SessionCapabilities::new().system_prompt(
7477 SessionSystemPromptCapabilities::new().mode(
7478 SessionSystemPromptModeCapabilities::new()
7479 .override_(SessionSystemPromptOverrideCapabilities::new())
7480 )
7481 )
7482 )
7483 .unwrap(),
7484 json!({ "systemPrompt": { "mode": { "override": {} } } })
7485 );
7486 assert_eq!(
7487 serde_json::from_value::<SessionCapabilities>(
7488 json!({ "systemPrompt": { "mode": { "override": {} } } })
7489 )
7490 .unwrap()
7491 .system_prompt
7492 .and_then(|capabilities| capabilities.mode)
7493 .and_then(|mode| mode.override_),
7494 Some(SessionSystemPromptOverrideCapabilities::new())
7495 );
7496
7497 assert_eq!(
7499 serde_json::from_value::<SessionCapabilities>(json!({ "systemPrompt": "yes" }))
7500 .unwrap()
7501 .system_prompt,
7502 None
7503 );
7504 assert_eq!(
7505 serde_json::from_value::<SessionCapabilities>(
7506 json!({ "systemPrompt": { "mode": { "override": true } } })
7507 )
7508 .unwrap()
7509 .system_prompt,
7510 Some(
7511 SessionSystemPromptCapabilities::new()
7512 .mode(SessionSystemPromptModeCapabilities::new())
7513 )
7514 );
7515 assert_eq!(
7516 serde_json::from_value::<SessionCapabilities>(
7517 json!({ "systemPrompt": { "mode": "override" } })
7518 )
7519 .unwrap()
7520 .system_prompt,
7521 Some(SessionSystemPromptCapabilities::new())
7522 );
7523 }
7524
7525 #[test]
7526 fn test_system_prompt_lifecycle_request_serialization() {
7527 let system_prompt = SystemPrompt::new(vec![ContentBlock::from(
7528 "You are a code review specialist.",
7529 )]);
7530 let system_prompt_json = json!({
7531 "mode": "append",
7532 "content": [{ "type": "text", "text": "You are a code review specialist." }]
7533 });
7534
7535 let request =
7536 NewSessionRequest::new("/home/user/project").system_prompt(system_prompt.clone());
7537 let request_json = json!({
7538 "cwd": "/home/user/project",
7539 "mcpServers": [],
7540 "systemPrompt": system_prompt_json
7541 });
7542 assert_eq!(serde_json::to_value(&request).unwrap(), request_json);
7543 assert_eq!(
7544 serde_json::from_value::<NewSessionRequest>(request_json).unwrap(),
7545 request
7546 );
7547
7548 assert_eq!(
7549 serde_json::to_value(
7550 LoadSessionRequest::new("sess_abc123", "/home/user/project")
7551 .system_prompt(system_prompt.clone())
7552 )
7553 .unwrap()["systemPrompt"],
7554 system_prompt_json
7555 );
7556 assert_eq!(
7557 serde_json::to_value(
7558 ResumeSessionRequest::new("sess_abc123", "/home/user/project")
7559 .system_prompt(system_prompt.clone())
7560 )
7561 .unwrap()["systemPrompt"],
7562 system_prompt_json
7563 );
7564 #[cfg(feature = "unstable_session_fork")]
7565 assert_eq!(
7566 serde_json::to_value(
7567 ForkSessionRequest::new("sess_abc123", "/home/user/project")
7568 .system_prompt(system_prompt.clone())
7569 )
7570 .unwrap()["systemPrompt"],
7571 system_prompt_json
7572 );
7573
7574 let override_prompt =
7575 SystemPrompt::new(vec![ContentBlock::from("...")]).mode(SystemPromptMode::Override);
7576 let override_json = json!({
7577 "mode": "override",
7578 "content": [{ "type": "text", "text": "..." }]
7579 });
7580 assert_eq!(
7581 serde_json::to_value(&override_prompt).unwrap(),
7582 override_json
7583 );
7584 assert_eq!(
7585 serde_json::from_value::<SystemPrompt>(override_json).unwrap(),
7586 override_prompt
7587 );
7588 }
7589
7590 #[test]
7593 fn test_system_prompt_new_defaults_to_append() {
7594 let system_prompt = SystemPrompt::new(vec![ContentBlock::from("...")]);
7595 assert_eq!(system_prompt.mode, SystemPromptMode::Append);
7596 assert_eq!(
7597 serde_json::to_value(&system_prompt).unwrap(),
7598 json!({ "mode": "append", "content": [{ "type": "text", "text": "..." }] })
7599 );
7600 }
7601
7602 #[test]
7606 fn test_system_prompt_preserves_unknown_modes() {
7607 for mode in ["_vendor_mode", "prepend"] {
7608 let system_prompt_json =
7609 json!({ "mode": mode, "content": [{ "type": "text", "text": "..." }] });
7610 let system_prompt: SystemPrompt =
7611 serde_json::from_value(system_prompt_json.clone()).unwrap();
7612 assert_eq!(
7613 system_prompt.mode,
7614 SystemPromptMode::Other(mode.to_string())
7615 );
7616 assert_eq!(
7617 serde_json::to_value(&system_prompt).unwrap(),
7618 system_prompt_json
7619 );
7620 }
7621 }
7622
7623 fn assert_system_prompt_is_strict<T>(base: &serde_json::Value)
7627 where
7628 T: serde::de::DeserializeOwned + PartialEq + std::fmt::Debug,
7629 {
7630 let name = std::any::type_name::<T>();
7631 let with = |system_prompt: serde_json::Value| {
7632 let mut request = base.clone();
7633 request["systemPrompt"] = system_prompt;
7634 serde_json::from_value::<T>(request)
7635 };
7636
7637 for system_prompt in [
7638 json!("You are a code review specialist."),
7639 json!({ "content": [{ "type": "text", "text": "..." }] }),
7640 json!({ "mode": null, "content": [{ "type": "text", "text": "..." }] }),
7641 json!({ "mode": 1, "content": [{ "type": "text", "text": "..." }] }),
7642 json!({ "mode": "append" }),
7643 json!({ "mode": "append", "content": "..." }),
7644 json!({ "mode": "append", "content": [{ "type": "text" }] }),
7645 json!({ "mode": "append", "content": [{ "type": "video", "uri": "..." }] }),
7646 ] {
7647 assert!(
7648 with(system_prompt.clone()).is_err(),
7649 "{name}.systemPrompt: {system_prompt}"
7650 );
7651 }
7652
7653 assert_eq!(
7654 with(serde_json::Value::Null).unwrap(),
7655 serde_json::from_value::<T>(base.clone()).unwrap(),
7656 "{name}.systemPrompt"
7657 );
7658 }
7659
7660 #[test]
7661 fn test_session_setup_requests_reject_malformed_system_prompts() {
7662 assert!(
7663 serde_json::to_value(NewSessionRequest::new("/repo"))
7664 .unwrap()
7665 .get("systemPrompt")
7666 .is_none()
7667 );
7668 assert_system_prompt_is_strict::<NewSessionRequest>(&json!({
7669 "cwd": "/repo",
7670 "mcpServers": []
7671 }));
7672 assert_system_prompt_is_strict::<LoadSessionRequest>(&json!({
7673 "sessionId": "sess-1",
7674 "cwd": "/repo",
7675 "mcpServers": []
7676 }));
7677 assert_system_prompt_is_strict::<ResumeSessionRequest>(&json!({
7678 "sessionId": "sess-1",
7679 "cwd": "/repo"
7680 }));
7681 #[cfg(feature = "unstable_session_fork")]
7682 assert_system_prompt_is_strict::<ForkSessionRequest>(&json!({
7683 "sessionId": "sess-1",
7684 "cwd": "/repo"
7685 }));
7686 }
7687
7688 #[test]
7689 fn test_auth_method_terminal_serialization() {
7690 let method = AuthMethod::Terminal(AuthMethodTerminal::new("tui-auth", "Terminal Auth"));
7691
7692 let json = serde_json::to_value(&method).unwrap();
7693 assert_eq!(
7694 json,
7695 json!({
7696 "id": "tui-auth",
7697 "name": "Terminal Auth",
7698 "type": "terminal"
7699 })
7700 );
7701 assert!(!json.as_object().unwrap().contains_key("args"));
7703 assert!(!json.as_object().unwrap().contains_key("env"));
7704
7705 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
7706 match deserialized {
7707 AuthMethod::Terminal(AuthMethodTerminal { args, env, .. }) => {
7708 assert_eq!(args, Vec::<String>::new());
7709 assert!(env.is_empty());
7710 }
7711 _ => panic!("Expected Terminal variant"),
7712 }
7713 }
7714
7715 #[test]
7716 fn test_auth_method_terminal_with_args_and_env_serialization() {
7717 use std::collections::HashMap;
7718
7719 let mut env = HashMap::new();
7720 env.insert("TERM".to_string(), "xterm-256color".to_string());
7721
7722 let method = AuthMethod::Terminal(
7723 AuthMethodTerminal::new("tui-auth", "Terminal Auth")
7724 .args(vec!["--interactive".to_string(), "--color".to_string()])
7725 .env(env),
7726 );
7727
7728 let json = serde_json::to_value(&method).unwrap();
7729 assert_eq!(
7730 json,
7731 json!({
7732 "id": "tui-auth",
7733 "name": "Terminal Auth",
7734 "type": "terminal",
7735 "args": ["--interactive", "--color"],
7736 "env": {
7737 "TERM": "xterm-256color"
7738 }
7739 })
7740 );
7741
7742 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
7743 match deserialized {
7744 AuthMethod::Terminal(AuthMethodTerminal { args, env, .. }) => {
7745 assert_eq!(args, vec!["--interactive", "--color"]);
7746 assert_eq!(env.len(), 1);
7747 assert_eq!(env.get("TERM").unwrap(), "xterm-256color");
7748 }
7749 _ => panic!("Expected Terminal variant"),
7750 }
7751 }
7752
7753 #[test]
7754 fn test_session_config_option_value_id_serialize() {
7755 let val = SessionConfigOptionValue::value_id("model-1");
7756 let json = serde_json::to_value(&val).unwrap();
7757 assert_eq!(json, json!({ "value": "model-1" }));
7759 assert!(!json.as_object().unwrap().contains_key("type"));
7760 }
7761
7762 #[test]
7763 fn test_session_config_option_value_boolean_serialize() {
7764 let val = SessionConfigOptionValue::boolean(true);
7765 let json = serde_json::to_value(&val).unwrap();
7766 assert_eq!(json, json!({ "type": "boolean", "value": true }));
7767 }
7768
7769 #[test]
7770 fn test_session_config_option_value_deserialize_no_type() {
7771 let json = json!({ "value": "model-1" });
7773 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
7774 assert_eq!(val, SessionConfigOptionValue::value_id("model-1"));
7775 assert_eq!(val.as_value_id().unwrap().to_string(), "model-1");
7776 }
7777
7778 #[test]
7779 fn test_session_config_option_value_deserialize_boolean() {
7780 let json = json!({ "type": "boolean", "value": true });
7781 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
7782 assert_eq!(val, SessionConfigOptionValue::boolean(true));
7783 assert_eq!(val.as_bool(), Some(true));
7784 }
7785
7786 #[test]
7787 fn test_session_config_option_value_deserialize_boolean_false() {
7788 let json = json!({ "type": "boolean", "value": false });
7789 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
7790 assert_eq!(val, SessionConfigOptionValue::boolean(false));
7791 assert_eq!(val.as_bool(), Some(false));
7792 }
7793
7794 #[test]
7795 fn test_session_config_option_value_deserialize_unknown_type_with_string_value() {
7796 let json = json!({ "type": "text", "value": "freeform input" });
7798 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
7799 assert_eq!(val.as_value_id().unwrap().to_string(), "freeform input");
7800 }
7801
7802 #[test]
7803 fn test_session_config_option_value_roundtrip_value_id() {
7804 let original = SessionConfigOptionValue::value_id("option-a");
7805 let json = serde_json::to_value(&original).unwrap();
7806 let roundtripped: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
7807 assert_eq!(original, roundtripped);
7808 }
7809
7810 #[test]
7811 fn test_session_config_option_value_roundtrip_boolean() {
7812 let original = SessionConfigOptionValue::boolean(false);
7813 let json = serde_json::to_value(&original).unwrap();
7814 let roundtripped: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
7815 assert_eq!(original, roundtripped);
7816 }
7817
7818 #[test]
7819 fn test_session_config_option_value_type_mismatch_boolean_with_string() {
7820 let json = json!({ "type": "boolean", "value": "not a bool" });
7822 let result = serde_json::from_value::<SessionConfigOptionValue>(json);
7823 assert!(result.is_ok());
7825 assert_eq!(
7826 result.unwrap().as_value_id().unwrap().to_string(),
7827 "not a bool"
7828 );
7829 }
7830
7831 #[test]
7832 fn test_session_config_option_value_from_impls() {
7833 let from_str: SessionConfigOptionValue = "model-1".into();
7834 assert_eq!(from_str.as_value_id().unwrap().to_string(), "model-1");
7835
7836 let from_id: SessionConfigOptionValue = SessionConfigValueId::new("model-2").into();
7837 assert_eq!(from_id.as_value_id().unwrap().to_string(), "model-2");
7838
7839 let from_bool: SessionConfigOptionValue = true.into();
7840 assert_eq!(from_bool.as_bool(), Some(true));
7841 }
7842
7843 #[test]
7844 fn test_set_session_config_option_request_value_id() {
7845 let req = SetSessionConfigOptionRequest::new("sess_1", "model", "model-1");
7846 let json = serde_json::to_value(&req).unwrap();
7847 assert_eq!(
7848 json,
7849 json!({
7850 "sessionId": "sess_1",
7851 "configId": "model",
7852 "value": "model-1"
7853 })
7854 );
7855 assert!(!json.as_object().unwrap().contains_key("type"));
7857 }
7858
7859 #[test]
7860 fn test_set_session_config_option_request_boolean() {
7861 let req = SetSessionConfigOptionRequest::new("sess_1", "brave_mode", true);
7862 let json = serde_json::to_value(&req).unwrap();
7863 assert_eq!(
7864 json,
7865 json!({
7866 "sessionId": "sess_1",
7867 "configId": "brave_mode",
7868 "type": "boolean",
7869 "value": true
7870 })
7871 );
7872 }
7873
7874 #[test]
7875 fn test_set_session_config_option_request_deserialize_no_type() {
7876 let json = json!({
7878 "sessionId": "sess_1",
7879 "configId": "model",
7880 "value": "model-1"
7881 });
7882 let req: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
7883 assert_eq!(req.session_id.to_string(), "sess_1");
7884 assert_eq!(req.config_id.to_string(), "model");
7885 assert_eq!(req.value.as_value_id().unwrap().to_string(), "model-1");
7886 }
7887
7888 #[test]
7889 fn test_set_session_config_option_request_deserialize_boolean() {
7890 let json = json!({
7891 "sessionId": "sess_1",
7892 "configId": "brave_mode",
7893 "type": "boolean",
7894 "value": true
7895 });
7896 let req: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
7897 assert_eq!(req.value.as_bool(), Some(true));
7898 }
7899
7900 #[test]
7901 fn test_set_session_config_option_request_roundtrip_value_id() {
7902 let original = SetSessionConfigOptionRequest::new("s", "c", "v");
7903 let json = serde_json::to_value(&original).unwrap();
7904 let roundtripped: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
7905 assert_eq!(original, roundtripped);
7906 }
7907
7908 #[test]
7909 fn test_set_session_config_option_request_roundtrip_boolean() {
7910 let original = SetSessionConfigOptionRequest::new("s", "c", false);
7911 let json = serde_json::to_value(&original).unwrap();
7912 let roundtripped: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
7913 assert_eq!(original, roundtripped);
7914 }
7915
7916 #[test]
7917 fn test_session_config_boolean_serialization() {
7918 let cfg = SessionConfigBoolean::new(true);
7919 let json = serde_json::to_value(&cfg).unwrap();
7920 assert_eq!(json, json!({ "currentValue": true }));
7921
7922 let deserialized: SessionConfigBoolean = serde_json::from_value(json).unwrap();
7923 assert!(deserialized.current_value);
7924 }
7925
7926 #[test]
7927 fn test_session_config_option_boolean_variant() {
7928 let opt = SessionConfigOption::boolean("brave_mode", "Brave Mode", false)
7929 .description("Skip confirmation prompts")
7930 .meta(test_meta());
7931 assert_eq!(serialized_meta_key_count(&opt), 1);
7932
7933 let json = serde_json::to_value(&opt).unwrap();
7934 assert_eq!(
7935 json,
7936 json!({
7937 "id": "brave_mode",
7938 "name": "Brave Mode",
7939 "description": "Skip confirmation prompts",
7940 "type": "boolean",
7941 "currentValue": false,
7942 "_meta": {
7943 "source": "test"
7944 }
7945 })
7946 );
7947
7948 let deserialized: SessionConfigOption = serde_json::from_value(json).unwrap();
7949 assert_eq!(deserialized.id.to_string(), "brave_mode");
7950 assert_eq!(deserialized.name, "Brave Mode");
7951 match deserialized.kind {
7952 SessionConfigKind::Boolean(ref b) => assert!(!b.current_value),
7953 _ => panic!("Expected Boolean kind"),
7954 }
7955 }
7956
7957 #[test]
7958 fn test_session_config_option_select_still_works() {
7959 let opt = SessionConfigOption::select(
7961 "model",
7962 "Model",
7963 "model-1",
7964 vec![
7965 SessionConfigSelectOption::new("model-1", "Model 1"),
7966 SessionConfigSelectOption::new("model-2", "Model 2"),
7967 ],
7968 )
7969 .meta(test_meta());
7970 assert_eq!(serialized_meta_key_count(&opt), 1);
7971
7972 let json = serde_json::to_value(&opt).unwrap();
7973 assert_eq!(json["type"], "select");
7974 assert_eq!(json["currentValue"], "model-1");
7975 assert_eq!(json["options"].as_array().unwrap().len(), 2);
7976 assert_eq!(json["_meta"]["source"], "test");
7977
7978 let deserialized: SessionConfigOption = serde_json::from_value(json).unwrap();
7979 match deserialized.kind {
7980 SessionConfigKind::Select(ref s) => {
7981 assert_eq!(s.current_value.to_string(), "model-1");
7982 }
7983 _ => panic!("Expected Select kind"),
7984 }
7985 }
7986
7987 #[cfg(feature = "unstable_llm_providers")]
7988 #[test]
7989 fn test_llm_protocol_known_variants() {
7990 assert_eq!(
7991 serde_json::to_value(&LlmProtocol::Anthropic).unwrap(),
7992 json!("anthropic")
7993 );
7994 assert_eq!(
7995 serde_json::to_value(&LlmProtocol::OpenAi).unwrap(),
7996 json!("openai")
7997 );
7998 assert_eq!(
7999 serde_json::to_value(&LlmProtocol::Azure).unwrap(),
8000 json!("azure")
8001 );
8002 assert_eq!(
8003 serde_json::to_value(&LlmProtocol::Vertex).unwrap(),
8004 json!("vertex")
8005 );
8006 assert_eq!(
8007 serde_json::to_value(&LlmProtocol::Bedrock).unwrap(),
8008 json!("bedrock")
8009 );
8010
8011 assert_eq!(
8012 serde_json::from_str::<LlmProtocol>("\"anthropic\"").unwrap(),
8013 LlmProtocol::Anthropic
8014 );
8015 assert_eq!(
8016 serde_json::from_str::<LlmProtocol>("\"openai\"").unwrap(),
8017 LlmProtocol::OpenAi
8018 );
8019 assert_eq!(
8020 serde_json::from_str::<LlmProtocol>("\"azure\"").unwrap(),
8021 LlmProtocol::Azure
8022 );
8023 assert_eq!(
8024 serde_json::from_str::<LlmProtocol>("\"vertex\"").unwrap(),
8025 LlmProtocol::Vertex
8026 );
8027 assert_eq!(
8028 serde_json::from_str::<LlmProtocol>("\"bedrock\"").unwrap(),
8029 LlmProtocol::Bedrock
8030 );
8031 }
8032
8033 #[cfg(feature = "unstable_llm_providers")]
8034 #[test]
8035 fn test_llm_protocol_unknown_variant() {
8036 let unknown: LlmProtocol = serde_json::from_str("\"cohere\"").unwrap();
8037 assert_eq!(unknown, LlmProtocol::Other("cohere".to_string()));
8038
8039 let json = serde_json::to_value(&unknown).unwrap();
8040 assert_eq!(json, json!("cohere"));
8041 }
8042
8043 #[cfg(feature = "unstable_llm_providers")]
8044 #[test]
8045 fn test_provider_current_config_serialization() {
8046 let config =
8047 ProviderCurrentConfig::new(LlmProtocol::Anthropic, "https://api.anthropic.com");
8048
8049 let json = serde_json::to_value(&config).unwrap();
8050 assert_eq!(
8051 json,
8052 json!({
8053 "apiType": "anthropic",
8054 "baseUrl": "https://api.anthropic.com"
8055 })
8056 );
8057
8058 let deserialized: ProviderCurrentConfig = serde_json::from_value(json).unwrap();
8059 assert_eq!(deserialized.api_type, LlmProtocol::Anthropic);
8060 assert_eq!(deserialized.base_url, "https://api.anthropic.com");
8061 }
8062
8063 #[cfg(feature = "unstable_llm_providers")]
8064 #[test]
8065 fn test_provider_info_with_current_config() {
8066 let info = ProviderInfo::new(
8067 "main",
8068 vec![LlmProtocol::Anthropic, LlmProtocol::OpenAi],
8069 true,
8070 Some(ProviderCurrentConfig::new(
8071 LlmProtocol::Anthropic,
8072 "https://api.anthropic.com",
8073 )),
8074 );
8075
8076 let json = serde_json::to_value(&info).unwrap();
8077 assert_eq!(
8078 json,
8079 json!({
8080 "providerId": "main",
8081 "supported": ["anthropic", "openai"],
8082 "required": true,
8083 "current": {
8084 "apiType": "anthropic",
8085 "baseUrl": "https://api.anthropic.com"
8086 }
8087 })
8088 );
8089
8090 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
8091 assert_eq!(deserialized.provider_id.to_string(), "main");
8092 assert_eq!(deserialized.supported.len(), 2);
8093 assert!(deserialized.required);
8094 assert!(deserialized.current.is_some());
8095 assert_eq!(
8096 deserialized.current.as_ref().unwrap().api_type,
8097 LlmProtocol::Anthropic
8098 );
8099 }
8100
8101 #[cfg(feature = "unstable_llm_providers")]
8102 #[test]
8103 fn test_provider_info_disabled() {
8104 let info = ProviderInfo::new(
8105 "secondary",
8106 vec![LlmProtocol::OpenAi],
8107 false,
8108 None::<ProviderCurrentConfig>,
8109 );
8110
8111 let json = serde_json::to_value(&info).unwrap();
8112 assert_eq!(
8113 json,
8114 json!({
8115 "providerId": "secondary",
8116 "supported": ["openai"],
8117 "required": false
8118 })
8119 );
8120
8121 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
8122 assert_eq!(deserialized.provider_id.to_string(), "secondary");
8123 assert!(!deserialized.required);
8124 assert!(deserialized.current.is_none());
8125 }
8126
8127 #[cfg(feature = "unstable_llm_providers")]
8128 #[test]
8129 fn test_provider_info_missing_current_defaults_to_none() {
8130 let json = json!({
8132 "providerId": "main",
8133 "supported": ["anthropic"],
8134 "required": true
8135 });
8136 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
8137 assert!(deserialized.current.is_none());
8138 }
8139
8140 #[cfg(feature = "unstable_llm_providers")]
8141 #[test]
8142 fn test_provider_info_explicit_null_current_decodes_to_none() {
8143 let json = json!({
8147 "providerId": "main",
8148 "supported": ["anthropic"],
8149 "required": true,
8150 "current": null
8151 });
8152 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
8153 assert!(deserialized.current.is_none());
8154 }
8155
8156 #[cfg(feature = "unstable_llm_providers")]
8157 #[test]
8158 fn test_list_providers_response_serialization() {
8159 let response = ListProvidersResponse::new(vec![ProviderInfo::new(
8160 "main",
8161 vec![LlmProtocol::Anthropic],
8162 true,
8163 Some(ProviderCurrentConfig::new(
8164 LlmProtocol::Anthropic,
8165 "https://api.anthropic.com",
8166 )),
8167 )]);
8168
8169 let json = serde_json::to_value(&response).unwrap();
8170 assert_eq!(json["providers"].as_array().unwrap().len(), 1);
8171 assert_eq!(json["providers"][0]["providerId"], "main");
8172
8173 let deserialized: ListProvidersResponse = serde_json::from_value(json).unwrap();
8174 assert_eq!(deserialized.providers.len(), 1);
8175 }
8176
8177 #[cfg(feature = "unstable_llm_providers")]
8178 #[test]
8179 fn test_set_provider_request_serialization() {
8180 use std::collections::HashMap;
8181
8182 let mut headers = HashMap::new();
8183 headers.insert("Authorization".to_string(), "Bearer sk-test".to_string());
8184
8185 let request =
8186 SetProviderRequest::new("main", LlmProtocol::OpenAi, "https://api.openai.com/v1")
8187 .headers(headers);
8188
8189 let json = serde_json::to_value(&request).unwrap();
8190 assert_eq!(
8191 json,
8192 json!({
8193 "providerId": "main",
8194 "apiType": "openai",
8195 "baseUrl": "https://api.openai.com/v1",
8196 "headers": {
8197 "Authorization": "Bearer sk-test"
8198 }
8199 })
8200 );
8201
8202 let deserialized: SetProviderRequest = serde_json::from_value(json).unwrap();
8203 assert_eq!(deserialized.provider_id.to_string(), "main");
8204 assert_eq!(deserialized.api_type, LlmProtocol::OpenAi);
8205 assert_eq!(deserialized.base_url, "https://api.openai.com/v1");
8206 assert_eq!(deserialized.headers.len(), 1);
8207 assert_eq!(
8208 deserialized.headers.get("Authorization").unwrap(),
8209 "Bearer sk-test"
8210 );
8211 }
8212
8213 #[cfg(feature = "unstable_llm_providers")]
8214 #[test]
8215 fn test_set_provider_request_omits_empty_headers() {
8216 let request =
8217 SetProviderRequest::new("main", LlmProtocol::Anthropic, "https://api.anthropic.com");
8218
8219 let json = serde_json::to_value(&request).unwrap();
8220 assert!(!json.as_object().unwrap().contains_key("headers"));
8222 }
8223
8224 #[cfg(feature = "unstable_llm_providers")]
8225 #[test]
8226 fn test_disable_provider_request_serialization() {
8227 let request = DisableProviderRequest::new("secondary");
8228
8229 let json = serde_json::to_value(&request).unwrap();
8230 assert_eq!(json, json!({ "providerId": "secondary" }));
8231
8232 let deserialized: DisableProviderRequest = serde_json::from_value(json).unwrap();
8233 assert_eq!(deserialized.provider_id.to_string(), "secondary");
8234 }
8235
8236 #[cfg(feature = "unstable_llm_providers")]
8237 #[test]
8238 fn test_providers_capabilities_serialization() {
8239 let caps = ProvidersCapabilities::new();
8240
8241 let json = serde_json::to_value(&caps).unwrap();
8242 assert_eq!(json, json!({}));
8243
8244 let deserialized: ProvidersCapabilities = serde_json::from_value(json).unwrap();
8245 assert!(deserialized.meta.is_none());
8246 }
8247
8248 #[cfg(feature = "unstable_llm_providers")]
8249 #[test]
8250 fn test_agent_capabilities_with_providers() {
8251 let caps = AgentCapabilities::new().providers(ProvidersCapabilities::new());
8252
8253 let json = serde_json::to_value(&caps).unwrap();
8254 assert_eq!(json["providers"], json!({}));
8255
8256 let deserialized: AgentCapabilities = serde_json::from_value(json).unwrap();
8257 assert!(deserialized.providers.is_some());
8258 }
8259
8260 #[test]
8261 fn prompt_request_rejects_malformed_content_block() {
8262 use serde_json::json;
8263
8264 assert!(
8265 serde_json::from_value::<PromptRequest>(json!({
8266 "sessionId": "sess-1",
8267 "prompt": [{"type": "text"}]
8268 }))
8269 .is_err()
8270 );
8271 }
8272
8273 #[test]
8274 fn prompt_request_rejects_non_array_prompt() {
8275 use serde_json::json;
8276
8277 assert!(
8278 serde_json::from_value::<PromptRequest>(json!({
8279 "sessionId": "sess-1",
8280 "prompt": "hello"
8281 }))
8282 .is_err()
8283 );
8284 }
8285
8286 fn assert_session_setup_lists_are_strict<T>(base: &serde_json::Value)
8287 where
8288 T: serde::de::DeserializeOwned + PartialEq + std::fmt::Debug,
8289 {
8290 let name = std::any::type_name::<T>();
8291 let with = |field: &str, value: serde_json::Value| {
8292 let mut request = base.clone();
8293 request[field] = value;
8294 serde_json::from_value::<T>(request)
8295 };
8296
8297 for (field, value) in [
8298 (
8300 "mcpServers",
8301 json!([
8302 {"name": "github", "command": "/usr/bin/gh-mcp", "args": [], "env": [{"name": "GITHUB_TOKEN", "value": null}]},
8303 {"name": "fs", "command": "/usr/bin/fs-mcp", "args": [], "env": []}
8304 ]),
8305 ),
8306 ("mcpServers", json!({"name": "fs"})),
8307 ("additionalDirectories", json!(["/repo/lib", 42])),
8308 ("additionalDirectories", json!("/repo/lib")),
8309 ] {
8310 assert!(
8311 with(field, value.clone()).is_err(),
8312 "{name}.{field}: {value}"
8313 );
8314 }
8315
8316 let empty = serde_json::from_value::<T>(base.clone()).unwrap();
8317 for field in ["mcpServers", "additionalDirectories"] {
8318 assert_eq!(
8319 with(field, serde_json::Value::Null).unwrap(),
8320 empty,
8321 "{name}.{field}"
8322 );
8323 }
8324 }
8325
8326 #[test]
8327 fn session_setup_requests_reject_malformed_mcp_servers_and_directories() {
8328 assert_session_setup_lists_are_strict::<NewSessionRequest>(&json!({
8329 "cwd": "/repo",
8330 "mcpServers": []
8331 }));
8332 assert_session_setup_lists_are_strict::<LoadSessionRequest>(&json!({
8333 "sessionId": "sess-1",
8334 "cwd": "/repo",
8335 "mcpServers": []
8336 }));
8337 assert_session_setup_lists_are_strict::<ResumeSessionRequest>(&json!({
8338 "sessionId": "sess-1",
8339 "cwd": "/repo"
8340 }));
8341 #[cfg(feature = "unstable_session_fork")]
8342 assert_session_setup_lists_are_strict::<ForkSessionRequest>(&json!({
8343 "sessionId": "sess-1",
8344 "cwd": "/repo"
8345 }));
8346 }
8347
8348 #[test]
8349 fn mcp_server_lists_treat_null_as_empty() {
8350 let servers: Vec<McpServer> = serde_json::from_value(json!([
8351 {"name": "fs", "command": "/usr/bin/fs-mcp", "args": null, "env": null},
8352 {"type": "http", "name": "api", "url": "https://example.com/mcp", "headers": null},
8353 {"type": "sse", "name": "events", "url": "https://example.com/sse", "headers": null}
8354 ]))
8355 .unwrap();
8356
8357 assert_eq!(
8358 servers,
8359 vec![
8360 McpServer::Stdio(McpServerStdio::new("fs", "/usr/bin/fs-mcp")),
8361 McpServer::Http(McpServerHttp::new("api", "https://example.com/mcp")),
8362 McpServer::Sse(McpServerSse::new("events", "https://example.com/sse")),
8363 ]
8364 );
8365 }
8366
8367 #[test]
8368 fn terminal_auth_methods_reject_malformed_launch_config() {
8369 let response: InitializeResponse = serde_json::from_value(json!({
8373 "protocolVersion": 1,
8374 "authMethods": [
8375 {"type": "terminal", "id": "bad-args", "name": "Log in", "args": ["auth", "--port", 8123]},
8376 {"type": "terminal", "id": "bad-env", "name": "Log in", "env": {"AUTH_MODE": "device", "DEBUG": 1}},
8377 {"type": "terminal", "id": "null-config", "name": "Log in", "args": null, "env": null},
8378 {"id": "agent", "name": "Agent login"}
8379 ]
8380 }))
8381 .unwrap();
8382
8383 assert_eq!(
8384 response.auth_methods,
8385 vec![
8386 AuthMethod::Terminal(AuthMethodTerminal::new("null-config", "Log in")),
8387 AuthMethod::Agent(AuthMethodAgent::new("agent", "Agent login")),
8388 ]
8389 );
8390 assert!(
8391 serde_json::from_value::<AuthMethod>(json!({
8392 "type": "terminal",
8393 "id": "bad-args",
8394 "name": "Log in",
8395 "args": ["auth", 8123]
8396 }))
8397 .is_err()
8398 );
8399 }
8400
8401 #[cfg(feature = "unstable_auth_status")]
8402 #[test]
8403 fn auth_status_response_round_trips() {
8404 let response = AuthStatusResponse::new(AuthState::Authenticated).accounts(vec![
8405 AuthAccount::new("Anthropic API key").active(true),
8406 AuthAccount::new("Claude Max").email("user@example.com".to_string()),
8407 ]);
8408 let json = serde_json::to_value(&response).unwrap();
8409 assert_eq!(
8410 json,
8411 json!({
8412 "state": "authenticated",
8413 "accounts": [
8414 {
8415 "label": "Anthropic API key",
8416 "active": true
8417 },
8418 {
8419 "label": "Claude Max",
8420 "email": "user@example.com"
8421 }
8422 ]
8423 })
8424 );
8425 assert_eq!(
8426 serde_json::from_value::<AuthStatusResponse>(json).unwrap(),
8427 response
8428 );
8429 assert_eq!(
8430 serde_json::to_value(AuthStatusResponse::new(AuthState::NotRequired)).unwrap(),
8431 json!({"state": "not_required"})
8432 );
8433 }
8434
8435 #[cfg(feature = "unstable_auth_status")]
8436 #[test]
8437 fn auth_status_state_is_strict_and_accounts_are_lenient() {
8438 assert!(serde_json::from_value::<AuthStatusResponse>(json!({})).is_err());
8439 assert!(serde_json::from_value::<AuthStatusResponse>(json!({"state": null})).is_err());
8440 assert!(serde_json::from_value::<AuthStatusResponse>(json!({"state": 1})).is_err());
8441
8442 let response: AuthStatusResponse = serde_json::from_value(json!({
8443 "state": "_vendor_state",
8444 "accounts": [
8445 {"active": true},
8446 {
8447 "label": "Vertex AI",
8448 "active": "yes",
8449 "email": ["not", "a", "string"]
8450 }
8451 ]
8452 }))
8453 .unwrap();
8454 assert_eq!(
8455 response,
8456 AuthStatusResponse::new(AuthState::Other("_vendor_state".to_string()))
8457 .accounts(vec![AuthAccount::new("Vertex AI")])
8458 );
8459 assert_eq!(
8460 serde_json::from_value::<AuthStatusResponse>(
8461 json!({"state": "unknown", "accounts": null})
8462 )
8463 .unwrap(),
8464 AuthStatusResponse::new(AuthState::Unknown)
8465 );
8466 }
8467
8468 #[cfg(feature = "unstable_auth_status")]
8469 #[test]
8470 fn auth_status_update_notification_routes() {
8471 use crate::v1::{AgentNotification, CLIENT_METHOD_NAMES};
8472
8473 assert_eq!(AGENT_METHOD_NAMES.auth_status, "auth/status");
8474 assert_eq!(CLIENT_METHOD_NAMES.auth_status_update, "auth/status_update");
8475 let notification = AgentNotification::AuthStatusUpdateNotification(
8476 AuthStatusUpdateNotification::new(AuthState::Unauthenticated),
8477 );
8478 assert_eq!(notification.method(), "auth/status_update");
8479 assert_eq!(
8480 serde_json::to_value(¬ification).unwrap(),
8481 json!({"state": "unauthenticated"})
8482 );
8483 }
8484}